Skocz do zawartości

jaromaz

Użytkownicy
  • Zawartość

    18
  • Rejestracja

  • Ostatnio

  • Wygrane dni

    1

jaromaz zajął 1. miejsce w rankingu.
Data osiągnięcia: 4 lipca.

Treści użytkownika jaromaz zdobyły tego dnia najwięcej polubień!

Ostatnio na profilu byli

Blok z ostatnio odwiedzającymi jest wyłączony i nie jest wyświetlany innym użytkownikom.

jaromaz's Achievements

2/10

2/10 (2/10)

26

Reputacja

  1. Na Raspberry Pi 3B+ wszystkie gry i programy z Mac OS 7 i Mac OS 8 działają płynnie, niektóre z Mac OS 9 już nieco mniej (ale jest to też bardziej wymagający "zasobowo" system). Wszystkie gry z Commodore 64/128 (BMC64) działają w 60 klatkach. Ten powyższy klip jest tylko skrótem poniższego, godzinnego filmu - można na nim zobaczyć znacznie dłuższe fragmenty oraz więcej gier i programów w działaniu (łatwiej ocenić płynność). Dzięki rozdziałom można ograniczyć się tylko do interesujących partii:
  2. MacintoshPi to mój mały projekt pozwalający na uruchomienie pełnoekranowych systemów Apple: Mac OS 7, Mac OS 8 i Mac OS 9 z dźwiękiem, aktywnym połączeniem internetowym i emulacją modemu pod Raspberry Pi OS Lite. Wszystko bez menadżera X.org, a wyłącznie za pomocą multimedialnej biblioteki SDL2 i z poziomu CLI – Raspberry Pi OS Lite. Dzięki temu emulatory wykorzystują pełną moc Raspberry Pi, są stabilniejsze i użyteczne w połączeniu z dodatkowym retro-oprogramowaniem. Instalacja wymaga uruchomienia jednego skryptu na czystym systemie Raspberry Pi OS Lite i poczekania około dwóch godzin na kompilację i instalację pakietów. Dodatkowo, dzięki zawartemu w projekcie dokumentowi, w dual-boot możliwe jest umieszczenie najszybszego (bare-metal) emulatora Commodore 64/128/PET BMC64 budując w ten sposób ciekawy retro pakiet na jednej karcie SD. Cały projekt MacintoshPi działa z urządzeniami Raspberry Pi Zero 2W, 2, 3, 3B, 3B+ (na razie nie działa z wersją 4). Poniżej film przedstawiający możliwości projektu MacintoshPi: Istnieje system Mac OS 7 dla maliny, ale do tej pory system Mac OS 9 w pełnoekranowym trybie (bez zbędnego menadżera okien - dla Raspberry Pi OS Lite) nie był dostępny. To chyba pierwsza taka implementacja pozwalająca na korzystanie z Mac OS 9 i SDL2 w trybie pełnoekranowym, z dźwiękiem i połączeniem internetowym – nawet na małym Raspberry Pi 2 W (a działa również na Raspbery Pi 2). Zajmuję się tematem emulacji Mac OS kilka lat (bo bardzo lubię retro systemy Apple'a) i temat jest dość złożony (gdyby zaczynać wszystko od początku): problemy z konfiguracją obrazów systemów pod obsługę Internetu, z właściwymi konfigami do emulatorów, z właściwymi opcjami do kompilacji emulatorów oraz (oddzielnie) SDL2 (bo oczywiście SDL z paczki nie zadziała w emulacji), z właściwą kompilacją NetDrivera, z wersjami bibliotek (bo muszą być legacy), problemy z dźwiękiem itp. itd. Oczywiście mówię o problemach, które napotkają początkujący, po czym zniechęcą się i rzucą te emulatory w kąt. Ponieważ rozwiązałem te wszystkie problemy na swoim Raspberry-Macintoshu, to postanowiłem udostępnić to rozwiązanie dla Wszystkich, tak żeby wystarczyło odpalić jeden skrypt i otrzymać wszystkie trzy systemy w jednym pakiecie bez żadnego wysiłku - i tym właśnie jest ten mały projekt. Składniki projektu W skład projektu wchodzą poniższe skrypty bash'owe auto-kompilujące i instalujące dla Raspberry Pi: Emulator Macintosh 68K Basilisk II obsługujący systemy Mac OS 7 (System 7.5.5) i Mac OS 8, Emulator PowerPC SheepShaver obsługujący system Mac OS 9, Emulator Commodore 64/128/Pet VICE, Wirtualny Modem wykorzystujący projekty tty0tty i tcpser, działający z powyższymi dwoma emulatorami dla produktów Apple, Commodore oraz z samym Raspberry Pi OS i pozwalający na łączenie się dowolnym oryginalnym retro-oprogramowaniem terminalowym z dzisiejszymi telnetowymi BBSami, Emulator CD-ROM, DVD-ROM CDEmu, pozwalający na montowanie pod Linuxem obrazów CD (iso, toast, cue/bin, mds/mdf itp.) – działa z emulatorami BasiliskII i SheepShaver oraz z Raspberry Pi OS. Emulatory są automatycznie skonfigurowane do obsługi tego wirtualnego napędu CD-ROM. Spójny launcher uruchamiający te wszystkie systemy w różnych rozdzielczościach (po restarcie) i w różnych konfiguracjach, SyncTERM – program do łączenia się z BBSami z poziomu Raspberry Pi OS kompilowany w połączeniu z biblioteką SDL, Informacje jak uruchomić w dual-boot Raspberry Pi OS z najszybszym emulatorem Commodore dla Raspberry Pi BMC64 – (bare metal/low latency emulator). O moim Macintoshu opartym na Raspberry Pi Moją wersję MacintoshPi napędza Raspberry Pi 3B+. Obudowę Macintosh Classic II zakupiłem na eBay-u – była kompletnie żółta, ale do stanu zgodnego z fabrycznym przywróciłem ją korzystając z wody utlenionej 18% i odpowiedniego naświetlania. Ekran LCD IPS 10,1'' 1024x600px HDMI Waveshare 11870 (zakupiony w Botlandzie) jest obrócony o 180°, aby okablowanie nie przeszkadzało górnej, wąskiej ramce Macintosha. Przestrzeń między płaskim ekranem, a pozostałościami kształtu CRT uzupełniłem wydrukiem 3D, który został zaprojektowany na potrzeby projektu twórców kanału YouTube 2GuysTek. Ekran Waveshare jest nieco zbyt szeroki, ale odpowiednie operowanie plikiem config.txt pozwala software'owo obrócić ekran i ustalić dokładną pozycję wyświetlanego obrazu, dla każdego z systemów lub programów oddzielnie (po każdorazowym restarcie). Ekran jest też nieco zbyt niski, dlatego puste przestrzenie wypełniłem czarnym bristolem i praktycznie nie widać tych elementów (wyglądają jak czarne tło ramki otaczającej ekran) – zalecam jednak wykorzystanie innego monitora, którego rozmiar będzie nieco większy, a dopiero software'owo zmniejszyć rozmiar i ustalić właściwą pozycję wyświetlanego obrazu. Klawiatura i mysz to zestaw Logiteh MK295 Silent Wireless Combo – są tylko nieznacznie zbliżone stylem do dostarczanych w tamtych latach peryferii, ale są też bezprzewodowe i korzystają z pojedynczego dongla bluetooth. Dodałem dwa głośniki podłączone do wejścia audio analog/jack Raspberry Pi 3B+ i do rozgałęźnika. Wszystkie te elementy są zintegrowałem wewnątrz obudowy komputera Apple Macintosh Classic II. Więcej informacji o MacintoshPi można znaleźć na GitHubie projektu: https://github.com/jaromaz/MacintoshPi lub po polsku na mojej stronie prywatnej: https://jm.iq.pl Wzmianka o tym projekcie pojawiła się w serwisie Hackster.io - również na ich Twitterze, chociaż nie wysyłałem im żadnych informacji : https://www.hackster.io/news/jaromaz-s-macintoshpi-turns-a-raspberry-pi-into-a-fast-feature-packed-classic-apple-mac-emulator-be88c17f66a8
  3. jaromaz

    Miniaturowy Tetris

    Dopiero teraz znalazłem chwilę na przygotowanie filmiku z moją wersją układu dla malutkiej, 170 stykowej płytki prototypowej. Całość prezentuje się następująco:
  4. jaromaz

    Miniaturowy Tetris

    Wreszcie dotarł czysty ATtiny85 i przeniosłem zestaw na wersję dla malutkiej płytki prototypowej (170 styków). Rozmieszenie jest dość nietypowe, ale dzięki takiemu upchnięciu większości połączeń w lewym górnym rogu możliwe było maksymalne zsunięcie ekranu w dół i nie wystaje on ponad płytkę, w wyniku czego jeszcze bardziej miniaturyzuje układ: Dzięki temu rozmieszczeniu dodatkowo żadne izolowane przewody nie przeszkadzają głośnikowi piezo i może być on maksymalnie dociśnięty do płytki. Na schemacie ekran nieznacznie wystaje, ale w rzeczywistości jest mniejszy, co można zobaczyć na zdjęciach. Zestaw zasilam okrągłą 3V baterią CR2032 lub 3.7V lipo. Poniżej schemat dla płytki 170-stykowej:
  5. Miniaturowy Tetris z pięcioma przyciskami, głośniczkiem Piezo i ekranem Oled 128×64. To wszystko przy zaledwie sześciu dostępnych GPIO jednodolarowego Digisparka/ATtiny85. Moja wersja kodu dodaje kilka ulepszeń, które znacząco zmieniają odbiór całej gry (opisane niżej), a koszt budowy całego zestawu wynosi około 15 zł. ATtiny Tetris Gold Multi Button obsługuje narastający poziom trudności (przyspieszanie opadania wraz z usuwaniem kolejnych linii), informację o klocku pojawiającym się w kolejnej turze, podpowiedź o pozycji klocka w dolnej partii planszy, pełną pseudo-losowość doboru klocków, dźwięki i temat muzyczny z oryginalnej gry. Poniżej mój filmik prezentujący ten układ w działaniu: W filmie można zobaczyć krótkie urywki z rozgrywki, proces instalacji szkicu w urządzeniu oraz pełny, pięciominutowy gameplay. Sprzęt Jakiś czas temu zainteresowały mnie klasyczne gry retro dla ATtiny85, ale w repo Attiny-Arduino-Games wszystkie były zaledwie dwu-przyciskowe. Tetris wymagał nieco więcej logiki, ale i tak obsługiwało się go przez naciskanie lub przytrzymywanie jednego z tylko dwóch przycisków, co generowało błędy i nie było zbyt wygodne. Z czasem jednak pojawiła się w repo wersja Tetris Multi Button, w której rozwiązano ten problem wykorzystując odpowiednią kombinację rezystorów i przycisków, dzięki czemu podłączono trzy przyciski pod jeden pin mikrokontrolera. Nie posiadam czystego ATtiny85, ale miałem na stanie Digisparka z tym chipem i postanowiłem złożyć to urządzenie. To chyba pierwsze nagranie wideo takiego zestawu - w sieci brak w sieci brak filmów i opisów wykonania pełnej, pięcio-przyciskowej wersji. Żeby się nie pogubić podczas montażu , korzystając z rozpiski pinów Digisparka i ATtiny85 przeniosłem dostarczony ze sketchem poniższy schemat: na lekko chaotyczną wersję graficzną dla stykowej płytki prototypowej i Digisparka zasilanego baterią 9V: a przy okazji też dla czystego ATtiny85 zasilanego baterią 3V: Poszczególne przyciski odpowiadają za: start nowej gry lub restart aktualnie rozgrywanej, włączenie/wyłączenie układu, obrót, przyspieszenie opadania, przesunięcie w lewo, przesunięcie w prawo. Przytrzymanie przycisku opadania i włączenie restartu gry aktywuje tryb ducha, a przytrzymanie przycisku opadania razem z przyciskiem obrotu podczas restartu ustawia trudny poziom gry, wypełniając dodatkowo błędnie klockami część planszy. Po aktywacji tych opcji grę należy uruchomić przyciskiem przyspieszonego opadania. Wersja na czystym ATtiny85 potrzebuje tylko 3V, bo sketch jest pisany dla obniżonego do 8MHz taktowania zegara. Wersję dla Digisparka zasilam poprzez pin VIN 9V baterią i przy takim poborze wystarczy jej na baaardzo długo. Wymagane do działania 5V przenoszę dodatkowym, pustym goldpinem na lewą stronę płytki prototypowej za pomocą dziesięciocentymetrowego przewodu połączeniowego żeńsko-męskiego. Po zlutowaniu powyższego układu w połączeniu z gołym ATtiny85 i po ubraniu go w miniaturowy brelok do kluczy, koszt (bez baterii) zamknąłby się poniżej 15 złotych. Na Aliexpress ATtiny85 kosztuje 0,80$, ekran Oled 128×64 1.80$, mały piezo buzzer 0,17$, a reszta części to już koszty groszowe. Tym sposobem otrzymujemy pełną grę sterowaną w identyczny sposób, jak w wielkich automatach Arcade lata temu, a do tego zasilaną malutką baterią 3V. Do zestawu zamiast białego ekranu można wybrać ekran niebieski lub żółto-niebieski, ale ponieważ ten ostatni jest dzielony na dwie różne części z odstępem, to nie prezentuje się zbyt atrakcyjnie (co widać na powyższym filmie) i polecam jednokolorowy odpowiednik. Potencjalny brelok mógłby wyglądać tak, jak na obrazku poniżej: Kod Zmiany w kodzie, których dokonałem, nie są duże, ale znaczące w odbiorze gry. Poniżej różnice między moją wersją, dostępną na GitHubie, a oryginałem gry dla ATtiny85: Dodałem losowość doboru klocków – domyślnie ATtiny Tetris generuje tę samą sekwencję klocków w każdej nowej grze, bo użyta funkcja random korzysta w kółko z tej samej tablicy liczb losowych. Programiści nie aktywowali randomSeed, ponieważ wszystkie piny w układzie są już podłączone. Moja wersja przesuwa tablicę liczb pseudo-losowych po każdym rozpoczęciu gry inkrementując seed do EEPROMu i aktywując w ten sposób pełną pseudolosowość doboru klocków (powtarzają się tylko pierwsze dwa). Grając w oryginalną wersję, do piątej linii miałem już ustalony optymalny schemat położenia klocków, przez co gra stawała się nudna. Teraz jest już poprawnie i mam świadomość, że wykorzystanie EEPROMu w randomSeedowaniu ograniczy liczbę rozgrywek do zaledwie 99000 (podana liczba uwzględnia już obecny w kodzie zapis najlepszych wyników również do EEPROMu). Na starcie gry dodałem fragment tematu muzycznego z oryginalnej gry Tetris z 1986 roku – domyślnie brak jakiejkolwiek muzyki w grze. Po wybraniu trybu ducha temat muzyczny jest nieco dłuższy. Dodałem dźwięk opadającego klocka (tylko podczas swobodnego spadania) oraz inny dźwięk dla klocka, który kończy opadanie. Domyślnie dźwięki w tej grze pojawiają się sporadycznie – tylko podczas usunięcia pełnej linii klocków oraz na zakończenie gry. Naprawiłem część błędnie wyświetlanych fontów na ekranie startowym Domyślnie wyłączyłem tryb ducha, który wyświetla podpowiedź o docelowej pozycji klocka. Tryb ducha można aktywować sposobem opisanym powyżej pod konfiguracją przycisków. Ze swoimi zmianami musiałem się zmieścić w sześciu procentach wolnej pamięci. Obecnie pozostaje już tylko 1% wolnego Projekcik jest dość interesujący i co najważniejsze, w pełni użyteczny, więc możliwe, że znajdą się osoby chcące zbudować taki układzik. Jako dodatek zamieszczam więc proces instalacji. Instalacja Kod zabiera blisko 100% pamięci ATtiny85, więc na Digisparku nie mieści się bootloader i nie można uploadować sketcha poprzez USB – należy więc skompilować hexa i wgrać go za pomocą programatora ISP. Jako programatora użyłem Arduino wg poniższego schematu: Na Arduino trzeba wgrać dostępny w przykładach Arduino IDE sketch ArduinoISP. Aby poprawnie skompilować tę wersję dla Digisparka należy w Arduino IDE zastąpić dodatkowy adres URL dla menadżera płytek od Digistump JSONem dla czystego ATtiny85, a następnie wybrać płytkę ATtiny25/45/85, procesor ATtiny85, zegar Internal 8MHz. Następnie z menu szkic eksportować skompilowany program, który zostanie wtedy umieszczony w katalogu źródła sketcha. Na koniec zostaje już tylko wgranie hexa na Digisparka poprzez Arduino programem avrdude. Poniżej przykładowe polecenie kopiujące (z fusami) wykonane na macOS, ale w innych systemach wygląda podobnie: /Applications/Arduino.app/Contents/Java/hardware/tools/avr/bin/avrdude -C/Applications/Arduino.app/Contents/Java/hardware/tools/avr/etc/avrdude.conf -v -pattiny85 -cstk500v1 -P/dev/cu.usbmodem14101 -b19200 -Uflash:w:/Users/username/Documents/ATtiny-Tetris-Gold/ATtiny-Tetris-Gold.ino.tiny8.hex -U lfuse:w:0xF1:m -U hfuse:w:0xD5:m -U efuse:w:0xFE:m Jak przebiega taki proces można obejrzeć na końcu powyższego filmiku. Poniżej też zdjęcie "programatora" i układu obok siebie. W filmie i na zdjęciach do włączania układu korzystam z przełącznika suwakowego SS22T25, ale lepiej sprawdził się przełącznik prosty ESP1010. Napięcia na przyciskach są istotne i podczas gry trzeba uważać aby nie dotykać rezystorów Ten problem wyeliminuje się po zlutowaniu układu. Najlepszy wynik gry jest również zapisywany w EEPROMie. Ponieważ głośniczek jest podłączony do pierwszego pinu Digisparka, to dodatkowo otrzymujemy LEDowe sygnały świetlne w momencie odtwarzania dźwięków. Po zakończeniu gry Tetris natychmiast przechodzi w tryb uśpienia z minimalnym poborem prądu, jednak do Digisparka dodałem przełącznik włączający/wyłączający zasilanie dla układu – wersja opierająca się wyłącznie na ATtiny85 nie wymaga wykonania tego kroku. Gra chodzi bardzo płynnie, co widać na powyższym filmie, gdy przytrzymuję przycisk przyspieszonego opadania dla kilku klocków pod rząd. Miniaturowy ATtiny Tetris Gold jest bardzo regrywalny (nie nudzi się) i to niesamowite, że udało się go upchnąć na tanim ATtiny85 przy zachowaniu tak dużej funkcjonalności. Serdecznie polecam montaż tego prostego układu. Powiększenia układów i trochę więcej informacji można znaleźć na moim blogu: http://jm.iq.pl/tetris
  6. Cześć, mam na imię Jarek i nieco ponad 40 lat. Elektroniką zajmuję się od niedawna, programowaniem od dzieciństwa Korzystam głównie z Arduino i z kilkunastu Digisparków. Jestem miłośnikiem lotnictwa, żeglarstwa, RC, muzyki oraz szeroko rozumianej symulacji.
  7. To Gemini PDA - najmniejszy produkowany seryjnie laptop na świecie w tym przypadku laptopo-telefon. W triple boot jest zainstalowany Android, pełna desktopowa wersja Debiana oraz Sailfish OS. O urządzeniu można poczytać na stronie producenta https://www.planetcom.co.uk
  8. Sketch DigiOS - mini OS emulator pozwala na zalogowanie się do Digisparka, wykonanie kilku komend, a następnie wylogowanie się. Działa na domyślnym Digisparku z zainstalowanym bootloaderem micronucleus oraz wykorzystuje moduł DigiCDC do emulacji komunikacji po USB, ponieważ sam Digispark nie posiada żadnego dodatkowego czipu USB i wszystko jest realizowane w oprogramowaniu AtTiny85. Emulator tylko naśladuje działanie systemu. Nie aspiruje do bycia czymś więcej, a już na pewno nie systemem operacyjnym to prosty kod wykonujący kilka poleceń, ale jego efekt końcowy jest dość użyteczny, co można ocenić na poniższym filmie: Przy zasilaniu Digisparka poprzez pin VIN można w dowolnym momencie podłączyć się do niego przez USB, a po wykonaniu komend odłączyć terminal i urządzenie - Digispark będzie dalej wykonywał kod uwzględniając wysłane komendy. W filmiku użyłem zamówionych w Botlandzie 10-cio centymetrowych przewodów połączeniowych żeńsko-żeńskich oraz żeńsko-męskich. Reszta sprzętu pochodzi z innych źródeł Dostępne komendy: p[0–2] [on|off] - wysyła sygnały HIGH i LOW na poszczególne piny od (0 do 2) uptime - wyświetla czas od uruchomienia Digisparka w linuxowym formacie uptime pretty vcc - podaje napięcie zasilania Digisparka w miliwoltach reboot - software’owo restartuje Digisparka clear - czyści ekran ls - wyświetla listę statusów GPIO temp - podaje temperaturę chipu login - wyświetla monit o podanie hasła clock [1–7] - zmniejsza taktowanie zegara (oszczędność energii). wartości: 1 – 8mHz, 2 – 4mHz, 3 – 2mHz, 4 – 1mHz, 5 – 500kHz, 6 – 250kHz, 7 – 125kHz, 0 – 16,5 mHz help - wyświetla ekran pomocy logout, exit - wylogowuje użytkownika Sketch z założenia miał zajmować jak najmniej miejsca – zamiast stringów wykorzystałem tablice znakowe, zamiast pinMode/digitalWrite rejestry i operacje bitowe, dzięki czemu udało się upchnąć tak dużo funkcji na tak małym urządzeniu. Wszystkie trzy elementy składowe zajmują razem blisko 100% pamięci Digisparka, aby jednak zwiększyć ilość dostępnego miejsca na własny kod, wystarczy usunąć odwołanie do zbędnych funkcji (np. temp, uptime, vcc). Odwołania te są oznaczone w kodzie specjalnym blokiem – po ich usunięciu udostępnione zostanie ponad 30% pamięci (z wyłączeniem bootloadera). Można wtedy łatwo rozbudować sketch o własne rozwiązania - staje się wtedy szablonem na pomysły użytkownika Dla Digisparka brak jest przykładów wieloznakowej, obustronnej komunikacji w połączeniu z DigiCDC. Jest dostępne jednoznakowe echo i zwykłe wyświetlanie informacji, ale też nie do końca poprawnie działają, szczególnie w najnowszych systemach. Musiałem przegrzebać się przez sieć i zastosować kilka własnych rozwiązań, żeby wszystko działało tak, jak w filmie. Tu właśnie moduł DigiCDC jest kluczowy i to co dla Arduino jest oczywiste, w Digisparku z DigiCDC wymagało trochę zachodu Umieszczone w kodzie delay'e są niezbędne bezpłatnej apce na Androida Serial USB Terminal, która jako jedyna obsługuje Digisparka w tym systemie. Bez nich apka źle łamie wyświetlany tekst. W kodzie jest też info, że można usunąć te delay'e, jeżeli do łączenia z Digisparkiem wykorzystuje się inny system operacyjny. Poważnym ograniczeniem biblioteki DigiCDC jest wymuszenie maksymalnie do siedmiu liczby znaków wpisywanej frazy. Przekroczenie tej liczby znaków w ciągu zawiesza komunikację. Definiowane hasło pozwala na wykonanie pewnych operacji z minimalnym poziomem autoryzacji. Minimalnym, bo zakładam, że łatwo jest je wyciągnąć bezpośrednio z Digisparka, ale może się mylę. Polecenie ls listuje stany LOW/HIGH wszystkich dostępnych GPIO w formie małej tabelki. Sprawdzane są bity - jeżeli wcześniej był ustawiony stan wysoki, to nawet po software'owym restarcie urządzenia polecenie to będzie uwzględniało wcześniejszą zmianę w wyświetlanym statusie. Zmiana taktowania wyłączy możliwość komunikacji po USB – można podpiąć pod tę zmianę wykonanie pewnych poleceń kończące się odwołaniem do funkcji reboot, wtedy Digispark się zrestartuje z domyślnymi ustawieniami zegara i automatycznie ponownie będzie możliwe logowanie do urządzenia. Chciałem nieco rozpropagować Digisparka, dlatego zależało mi na takiej uproszczonej formie: sketch + micronucleus + DigiCDC. DigiOS to szybka kompilacja w Arduino IDE, bezproblemowy upload do Digisparka przez Arduino IDE dzięki bootloaderowi micronucleus ... i gotowe Do uploadowania sketcha do Digisparka wymagane jest Arduino IDE w wersji 1.8.6 oraz poprawna instalacja Digisparka w IDE zgodnie z tą instrukcją. Do DigiOS można zalogować się pod Windows programem Putty (po wcześniejszej instalacji sterowników Digistump), w Linuxie aplikacją Minicom, a w Androidzie wspomnianą aplikacją Serial USB Terminal. Kod udostępniam poniżej, a jego zmiany można śledzić na stronie projektu w GitHubie - jest tam również dostępna wersja DigiLx z oknem logowania i znakiem zachęty w stylu linuksowym. /* ---------------------------------------------- DigiOS 1.4 - mini-OS emulator for Digispark Copyright (c) Jaromaz https://jm.iq.pl Available commands: login, p[0-2] [on|off], temp, help, vcc, clear, uptime, clock [1-7], ls, reboot, logout, exit ----------------------------------------------- */ // password of up to seven characters const char password[] = "admin12"; //----------------------------------------------- #include <DigiCDC.h> char serialChar[1], stringInput[8]; boolean stringComplete = false; byte state = 1; byte clocks[] = { 16, 8, 4, 2, 1, 500, 250, 125 }; static void reboot() //----------------------------------------------- { SerialUSB.print(F("\r\nRebooting ... ")); noInterrupts(); CLKPR = 0b10000000; CLKPR = 0; void (*ptrToFunction)(); ptrToFunction = 0x0000; (*ptrToFunction)(); } static void clockMessageFormat (byte speed) //----------------------------------------------- { SerialUSB.print(F("\r\nset to ")); SerialUSB.print(clocks[speed], DEC); SerialUSB.print((clocks[speed] > 16) ? F("k") : F("m")); SerialUSB.println(F("Hz\r\n\r\nbye ...")); } static void clockSpeed(byte speed) //----------------------------------------------- // edit the code of this procedure to get the right result { clockMessageFormat(speed); for (byte i = 0; i < 12; i++) { PORTB |= (1 << 1); SerialUSB.delay(200); PORTB &= ~(1 << 1); SerialUSB.delay(200); if (i == 5) { CLKPR = 0b10000000; CLKPR = speed; } } reboot(); } static void stateChg() { state = 2; } //----------------------------------------------- #define SECS_PER_MIN (60UL) #define SECS_PER_HOUR (3600UL) #define SECS_PER_DAY (SECS_PER_HOUR * 24L) #define numberOfSeconds(_time_) (_time_ % SECS_PER_MIN) #define numberOfMinutes(_time_) ((_time_ / SECS_PER_MIN) % SECS_PER_MIN) #define numberOfHours(_time_) (( _time_% SECS_PER_DAY) / SECS_PER_HOUR) #define elapsedDays(_time_) ( _time_ / SECS_PER_DAY) void uptimeFormat(byte digits, char* form) //----------------------------------------------- { if (digits > 0) { SerialUSB.print(digits, DEC); SerialUSB.print(F(" ")); SerialUSB.print(form); if (digits > 1) SerialUSB.print(F("s")); if (strcmp(form, "second")) { SerialUSB.print(F(", ")); } } } static void uptime() //----------------------------------------------- { long seconds = millis() / 1000; SerialUSB.print(F("\r\nup ")); uptimeFormat(elapsedDays(seconds), "day"); uptimeFormat(numberOfHours(seconds), "hour"); uptimeFormat(numberOfMinutes(seconds), "minute"); uptimeFormat(numberOfSeconds(seconds), "second"); SerialUSB.println(); } static void getVcc() //----------------------------------------------- { ADMUX = _BV(MUX3) | _BV(MUX2); SerialUSB.delay(2); ADCSRA |= _BV(ADSC); while (bit_is_set(ADCSRA, ADSC)); uint8_t low = ADCL; uint8_t high = ADCH; long result = (high << 8) | low; result = 1125300L / result; SerialUSB.print(F("\r\nVoltage: ")); SerialUSB.print(result); SerialUSB.println(F(" mV")); } static void getTemp() //----------------------------------------------- { analogReference(INTERNAL1V1); analogRead(A0); SerialUSB.delay(200); int temp = analogRead(A0 + 15) - 273; analogReference(DEFAULT); SerialUSB.print(F("\r\nDigispark temperature: ")); SerialUSB.print(temp); SerialUSB.println(F("°C")); } void clearScreen() //----------------------------------------------- { for (byte i = 0; i < 35; i++) { SerialUSB.println(); SerialUSB.delay(5); } } static void horizontaLine() //----------------------------------------------- { for (byte i = 0; i < 32; i++) SerialUSB.print(F("-")); } static void gpioList() //----------------------------------------------- { horizontaLine(); SerialUSB.print(F("\r\nGPIO status list\r\n")); horizontaLine(); for (byte i = 0; i < 3; i++) { SerialUSB.print(F("\r\nPin ")); SerialUSB.print(i, DEC); SerialUSB.print((PINB & (1 << i)) ? F(" HIGH") : F(" LOW")); } SerialUSB.println(); horizontaLine(); } static void help() //----------------------------------------------- { horizontaLine(); SerialUSB.println(F("\r\nDigiOS version 1.4 User Commands")); horizontaLine(); SerialUSB.println(F("\r\nlogin, p[0-2] [on|off], temp, help,\ vcc, clear,\r\nuptime, clock [1-7], ls, reboot, logout,\ exit\r\n\r\nclock 1 - 8mHz, 2 - 4mHz, 3 - 2mHz, 4 - 1mHz,\ \r\n5 - 500kHz, 6 - 250kHz, 7 - 125kHz")); } static void serialReader() //----------------------------------------------- { while (SerialUSB.available()) { serialChar[0] = (char)SerialUSB.read(); if ((' ' <= serialChar[0]) && (serialChar[0] <= '~')) { strcat(stringInput, serialChar); } else { if (stringInput[0] != 0) { stringComplete = true; return; } } } } void setup() //----------------------------------------------- { // Set pins 0-2 as OUTPUT: DDRB |= (1 << PB0) | (1 << PB1) | (1 << PB2); SerialUSB.begin(); } // list of keywords and procedures assigned to them static const struct { const char phrase[8]; void (*handler)(void); } keys[] = { // ---- comment on this block to get more memory for your own code --- { "vcc", getVcc }, { "help", help }, { "temp", getTemp }, { "reboot", reboot }, { "exit", stateChg }, { "uptime", uptime }, { "clear", clearScreen }, { "ls", gpioList }, // ------------------------------------------------------------------- { "logout", stateChg } }; void loop() //----------------------------------------------- { // the Android Serial USB Terminal app requires the following 200 ms delays // if you are using another system, you can remove all these delays. serialReader(); if (stringComplete) { SerialUSB.delay(200); if (!strcmp(stringInput, "login")) stateChg(); // password validation if (state == 4) { if (!strcmp(stringInput, password)) { state = 3; } else { SerialUSB.delay(1500); SerialUSB.println(F("\r\nLogin incorrect")); state = 1; } } // status after logging in if (state == 3) { // ---- comment on this block to get more memory for your own code --- if (stringInput[0] == 'p') { if ((stringInput[1] - 48) < 3 and stringInput[4] == 'n') { PORTB |= (1 << stringInput[1] - 48); } else if ((stringInput[1] - 48) < 3 and stringInput[4] == 'f') { PORTB &= ~(1 << stringInput[1] - 48); } } if (strstr(stringInput, "clock ")) clockSpeed(stringInput[6] - 48); // --------------------------------------------------------------------- // keyword procedures for (byte i = 0; i < sizeof keys / sizeof * keys; i++) { if (!strcmp(stringInput, keys[i].phrase)) keys[i].handler(); } if (state == 3) SerialUSB.print(F("\r\ncmd:> ")); } // password input window if (state < 3) { if (state > 1) clearScreen(); SerialUSB.print(F("\r\nDigiOS 1.4 - Digispark mini-OS\r\n\r\nPassword: ")); state = 4; } SerialUSB.delay(200); stringInput[0] = 0; stringComplete = false; } }
×
×
  • Utwórz nowe...

Ważne informacje

Ta strona używa ciasteczek (cookies), dzięki którym może działać lepiej. Więcej na ten temat znajdziesz w Polityce Prywatności.