ATpad
Herní konzole s ATmega8
Sestavit výkonný a levný počítač pomocí moderních součástek není dnes už žádný problém. Ale použít k tomu zcela nevhodný a nevýkonný procesor - to je teprve ten pravý challenge! :-D ... A proč zrovna ATmega8?
Pozn.: Obrázky zde uvedené zvětšíte kliknutím
Ukázkové video ATpad na YouTube: https://www.youtube.com/watch?v=jmdYueKbfG8
ATpad generuje obrazový signál softwarově. Výstup lze připojit k televizoru s RGB vstupem (televizní normy PAL nebo NTSC) nebo počítačový monitor VGA. Přes redukci lze sloučit RGB a SYNC signály do černobílého kompozitního signálu (pouhým spojením vodičů) a připojit přes CINCH konektor na kompozitní vstup televizoru (vhodné v případě, že televizor nepodporuje RGB vstup).
Ke spouštění programů slouží běžná SD karta. Karta musí být naformátována formátem FAT16. Zbylý prostor SD karty může být používán běžným způsobem s FAT32.
Procesor obsahuje boot loader o velikosti 2 KB, který po resetu vyhledá na kartě soubor zavaděče BOOT.* (přípona souboru závisí na typu procesoru) a ten nahraje do paměti ROM Flash. Standardně je zavaděčem program pro výběr programů z karty - ten zajistí načtení vybraného programu do ROM paměti a jeho spuštění. Není-li při resetu zasunuta SD karta, spustí se z paměti naposledy nahraný program.
Součástí programů je pole vzorů dlaždic v ROM paměti. V RAM je pole indexů dlaždic (pro rozlišení 20 x 14 dlaždic zabere pole v RAM pouze 280 bajtů). Zobrazovací rutina čte indexy dlaždic z RAM a zobrazuje příslušné dlaždice z ROM. Každá dlaždice zabere v ROM 32 bajtů (8 x 8 pixelů, 16 barev, tj. 2 pixely na 1 bajt). Počet dlaždic je omezený pouze velikostí paměti. To umožňuje rychlou manipulaci s obrazem s malými nároky na paměť. Vhodně připravenými dlaždicemi lze zajistit i animace, jako např. jednoduché video.
Velikost programu v ROM je omezena na 6 KB (zbylé 2 KB zabírá boot loader). Lze spouštět i větší program technikou overlay - program může načítat potřebné další části z SD karty až za běhu (do ROM, RAM nebo EEPROM) - vhodné např. k načítání definice scén. Použitím vyššího typu procesoru (ATmega328p) lze načítat větší programy bez nutnosti overlay ... ovšem tím už přicházíte o tu správnou zábavu "vměstnat program do 6 KB" :-) .
ATpad umožňuje i generování zvukových tónů s obdélníkovým nebo pilovým průběhem. Tóny vznikají modulací horizontální synchronizace. U televizního obrazu je kmitočet synchronizace 16 kHz a je proto nutné počítat s poměrně špatnou kvalitou generovaného tónu (vysoký obsah rušivých harmonických). Při použití VGA monitoru je kmitočet 32 kHz a zvuk je podstatně lepší. Kvalita zvuku by byla lepší v případě, když by se místo modulace nosné použilo spínání výstupu podle periody tónu - ovšem za cenu snížení přesnosti frekvence tónu.
Minimálním podporovaným procesorem je ATmega8 (8 KB ROM, 1 KB RAM, 512 B EEPROM). Poslední 2 KB ROM se používají pro zavaděč (bootloader), zbylých 6 KB je k dispozici pro aplikaci, včetně vzorů obrazových dlaždic. Procesor lze použít jak v TQFP pouzdru, tak v PDIP pouzdru. PDIP verze má výhodu v možnosti snadné výměny procesoru - při závadě nebo při experimentování s různými procesory.
Kromě ATmega8 lze použít i vyšší typy, pinově kompatibilní. Programy musí být přeloženy pro konkrétní použitý procesor a frekvenci krystalu. V ukázkových programech jsou připraveny překlady pro ATmega8, ATmega88 a ATmega328p. ATmega88 je nejnižší podporovaný typ z modernější řady xx8. ATmega328p je levný typ s větší pamětí (32 KB ROM, 2 KB RAM). To umožňuje použití většího rozlišení obrazovky a větších aplikací.
Frekvence krystalu není striktně určená. Je však nutné překládat aplikace i bootloader pro konkrétní použitou frekvenci. Během překladu se automaticky spočítá časování pro softwarové generování obrazového signálu. Frekvence krystalu určuje především dosažitelné rozlišení generovaného obrazu. Při použití jmenovité frekvence (16 MHz pro ATmega8 nebo 20 MHz pro ATmegaxx8) není u většiny programů podporováno typické rozlišení obrazu pro VGA monitor (to je dosaženo až přetaktováním vyšší frekvencí). Je použit nouzový režim dělené obrazovky, kdy se levá a pravá půlka obrazu zobrazí nad sebou. Pro televizní módy je jmenovitá frekvence dostatečná, obraz se zobrazí správně.
Dělená obrazovka na VGA monitoru při použití nízké frekvence:
Ukázkové aplikace jsou navrženy pro frekvenci 24 MHz. Na tuto frekvenci lze přetaktovat většinu procesorů (jak ATmega8, tak ATmegaxx8). Pouze u některých starších ATmega8 jsem narazil na omezení na 16 MHz. Některé procesory lze přetaktovat až na 27 MHz, ale na tuto frekvenci je nutné procesory již vybírat. Přínosem může být vyšší horizontální rozlišení, ovšem omezením už může být velikost RAM a tak je tato frekvence podporovaná jen jako zajímavost.
Aby bylo možné mít na jedné SD kartě verze pro různé procesory a různé frekvence, liší se soubory příponou a ATpad vybírá jen verze se správnou příponou. Jméno přípony je uloženo v bootloaderu a určuje se během překladu. V ukázkových programech jsou použity následující přípony:
Aplikace se spouštějí z SD karty. V posledních 2 KB paměti ROM je uložen bootloader (zavaděč), který z root adresáře SD karty načte a spustí program BOOT.*, kde přípona souboru je určena typem procesoru a frekvencí krystalu (viz předešlá sekce). Programy se zavádějí do prvních 6 KB ROM paměti, resp. u ATmega328p do prvních 30 KB ROM paměti. Program se v paměti uchová i po vypnutí ATpadu. Není-li po zapnutí vložena SD karta s platným souborem BOOT.*, spustí se poslední nahraná aplikace (nacházející se v paměti ROM).
Počet zápisů do paměti ROM je omezen na asi 10 tisíc. Při běžném použití je to dostatečný počet, ale může to být omezení v případě zasunuté SD karty, provádí-li se častý reset.
Ke spouštění aplikací z SD karty slouží zaváděcí program BOOT.* (v ukázkových programech složka !BootLoader). Program zobrazí seznam aplikací na SD kartě. Zobrazí jen soubory se správnou příponou (=správný procesor a frekvence). Soubory lze umisťovat i do složek.
BootLoader umožňuje nastavení konfigurace displeje. Kombinací tlačítka B (vpravo nahoře) se současným stiskem šipky se změní použitý typ dispeje. Spouštěné programy si převezmou zvolenou konfiguraci z EEPROM paměti a při startu se přepnou na správný typ displeje. Konfigurace se uplatní pouze u programů s režimem displeje UNI.
SD kartu je nutné před použitím naformátovat ve čtečce karet na formát FAT16 (jediný formát podporovaný ATpadem). Na SD kartě se může nacházet více oddílů disku (max. 4), ATpad použije první nalezený oddíl s formátem FAT16. Postup při vytvoření SD karty pod Windows:
Velikost alokační jednotky | Velikost FAT16 disku od- | Velikost FAT16 disku do- |
512 B | 2 MB | 32 MB |
1024 B | 4 MB | 64 MB |
2048 B | 8 MB | 128 MB |
4096 B | 16 MB | 256 MB |
8192 B | 32 MB | 512 MB |
16 KB | 64 MB | 1 GB |
32 KB | 128 MB | 2 GB |
ATpad je ve 2 provedeních, podle typu pouzdra procesoru - TQFP (SMD montáž) nebo PDIP (objímka).
Schéma zapojení TQFP varianty (kliknutím zvětšíte):
Schéma zapojení PDIP varianty (kliknutím zvětšíte):
Procesor je vybavený resetovacím tlačítkem S1, kterým se lze dostat z programu do bootloaderu. Konektor S5 ISP je programovací, slouží k naprogramování procesoru. Použijte některý standardní programátor pro AVR procesory s 6-pinovým ISP konektorem. Současně jsou programovací signály ISP přivedeny na SD kartu, přes odporové děličky sloužící k přizpůsobení úrovní 5V a 3.3V. Nemusí to být nutné, ale raději nepřipojujte programátor, máte-li zasunutou SD kartu. Mohlo by dojít k poškození jejího obsahu. Konektor X1S mini-USB je napájecí konektor. Nepoužívá datové vodiče, pouze zajišťuje napájení +5V ze standardního nabíjecího zdroje (nebo z USB portu počítače). Stabilizátor IC2 připravuje napětí +3.3V pro SD kartu. Rezistor R17 zajistí úroveň HIGH na CS vstupu SD karty během startu procesoru, kdy jsou výstupy v HIGH impedanci, aby náhodným stavem signálů nedošlo k modifikaci obsahu SD karty. Konektor SD karty nevyužívá signály vložení karty ani ochranu proti zápisu (v software ATpadu není ani zápis na kartu implementován). K CS signálu SD karty je připojena indikační LED dioda, monitorující aktivitu čtení z SD karty, a také jako signalizační LED programu.
Odpory R7 až R12, R19, R30 a R31 jsou odporové děliče, ke změně výstupní úrovně procesoru na video signály RGB. Odpory R19, R30 a R31 nejsou nutné. Byly přidány ve snaze zlepšit impedanční přizpůsobení výstupů k 75-ohmovému vstupu televizoru, aby se zlepšily zákmity na hranách obrazu. Zákmity se moc nezlepšily (problém bude asi někde jinde) a budete-li chtít tyto 3 odpory vypustit, v tom případě změňte odpory R7 až R12 na hodnoty 680 a 1K5. Odpory R21 a R29 vytváří napěťové úrovně potřebné pro signály SWITCH a BLANK pro SCART konektor. Pro výstup na TV nebo VGA lze použít jak X4 RGB konektor, tak X2 VGA konektor. Oba konektory obsahují všechny potřebné signály. Audio výstup je přiveden nestandardně na pin 14 VGA konektoru (běžně používaný pro VSYNC). Díky vstupní impedanci 75 ohmů je zvukový signál utlumen a nebude nesprávně považován za VSYNC signál. Při zasunutí konektoru do X3 AUDIO výstupu je signál od VGA konektoru odpojen, aby nebyl VGA monitorem utlumen. Synchronizační signál je na oba konektory veden jako synchronizační směs (HSYNC i VSYNC pohromadě), který podporují i VGA monitory. Je možné neosazovat konektor X4 RGB a používat pouze X2 VGA konektor - snáz se letuje (větší vzdálenost mezi piny) a s mini-DIN konektorem se špatně manipuluje (příliš jemný konektor na příliš silný kabel)..
Nepodporuje-li televizor RGB vstup, lze použít černobílý kompozitní obrazový signál - stačí pouze dohromady spojit výstupy R, G, B a SYNC. U některých televizorů již může dojít k přebuzení vstupu příliš vysokou úrovní signálu (špatně se synchronizuje horní část obrazu a je přejasněná) - v tom případě může být nutné přidat ještě omezující odpor.
Konektor X6 JOY je konektor portů. Obsahuje 2 digitální vstupně/výstupní piny (B1 a B2) a 2 analogové vstupní piny (X1 a Y1). Ke konektoru lze připojit standardní analogový joystick s 15-pinovým CANON konektorem. K tomu slouží odpory R6 a R13, které spolu s proměnlivým odporem joysticku (0 až 100 kOhm) vytvoří vstupní napětí v rozsahu +2.5 až +5.0V (hodnota naměřená na ADC převodníku bude v rozsahu 512 až 1023). Pro přístup k portům není v ukázkových programech připraven příklad. Předpokládá se začlenění obsluhy čtení ADC vstupů do obsluhy vertikální synchronizace video výstupu. Při čtení ADC vstupů je potřeba pamatovat na to, že z technických důvodů jsou během generování videosignálu vysílány na piny PC4 a PC5 náhodná data, což se projevuje náhodným připojováním a odpojováním pull-up rezistorů 36 kOhm. To by zkreslilo hodnotu naměřenou z analogového joysticku. Proto je vhodné doplnit obsluhu čtení ADC vstupu do obsluhy vertikální synchronizace, během které lze pull-up rezistory vypnout. Jinak, v krajním případě, by bylo možné vypnout interní pull-up rezistory procesoru globálně (přepínač PUD) a vstupy z tlačítek ošetřit externími pull-up rezistory.
Signály B1 a B2 (BTN1 a BTN2) lze použít jako digitální vstupy nebo digitální výstupy. Piny lze použít též k sériové komunikaci I2C (2-wire serial bus TWI, signály SDA a SCL). Takto lze vzájemně propojit více zařízení s procesory, formou sběrnice. Signály používají výstupy s otevřeným kolektorem. K I2C není připraven ukázkový příklad.
Chcete-li konstrukci minimalizovat, vypusťte konektor X4 RGB, odpory R19, R30, R31, konektor portů X6 JOY s odpory R2-R6, R13 a kondenzátor C8 (filtr zvuku).
Plošné spoje jsou navrženy jako oboustranné, bez prokovených děr, s nutností několika propojek mezi horní a spodní vrstvou. Spodní vrstvu je možné nahradit drátovými propojkami (spoje jsou vedeny především v horní vrstvě). Spoje jsou vytvořené ve free verzi Eagle, proto jsou limitovány rozměrem 10x15 cm. Současně je to i rozměr vhodný pro použitou krabičku. Shora jsou osazena tlačítka, SD konektor, USB konektor a procesor v TQFP verzi. Použijete-li tlačítka s aretačními výstupky, doporučuji výstupky upilovat, aby tlačítka dolehla těsně na plošný spoj - vnitřní výška krabičky doléhá těsně na tlačítka, při ponechání výstupků by tlačítka překážela.
Při osazování doporučuji osadit nejdříve USB konektor a zkontrolovat přítomnost napětí +5V. Dále přiletovat stabilizátor a zkontrolovat napětí +3.3V na jeho výstupu. U stabilizátoru pozor na to, že každý výrobce používá jiné zapojení pinů stabilizátoru. Neřiďte se zde uvedenou orientací pinů (nemusí souhlasit s vaším stabilizátorem). Dokonce prodejci (jako GME) přikládají datasheety od jiných výrobců, které jsou sice kompatibilní po elektrické stránce, ale nesouhlasí piny. Proto je důležité ověření správné funkce stabilizátoru hned na začátku, později se chyba už špatně hledá.
Výroba plošného spoje: Použijte oboustrannou desku plošného spoje o rozměru 10x15 cm. Pro ni jsou připraveny zaměřovací kříže v rozích předlohy spoje. Předlohu vytisknete na inkoustové nebo laserové tiskárně. Je potřeba použít průhlednou fólii pro inkoustovou nebo laserovou tiskárnu. Na jiné fólii barva nemusí držet. Každou stranu předlohy vytiskněte 2x, zrcadlově obráceně. Oba výtisky přiložte k sobě, přesně je sesaďte (podle krytí nejjemnějších částí spoje) a slepte izolepou. Přiložte předlohu tiskem dolů na plošný spoj (proto zrcadlově obrácený tisk), zaměřovací kříže v rozích usaďte přesně na rohy spoje 10x15 cm. Spoj osviťte UV zářivkou nebo UV LEDkami. Přesnou dobu osvitu si předem vyzkoušejte na proužku plošného spoje. Pro osvitku s 15 UV LEDkami je při vzdálenosti 30 cm doba osvitu asi 8 minut. Po osvitu jedné strany desku otočte a osviťte ji s použitím druhé předlohy (pozor na správnou orientaci stran k sobě). Spoj vyvolejte v 1% roztoku hydroxidu sodného (Tesco, drogerie) a vyleptejte v 7% roztoku kyseliny solné (PeMi, OBI) s 1% peroxidu vodíku (Barvy Laky).
Horní strana (varianta TQFP a PDIP):
Dolní strana (varianta TQFP a PDIP):
Potisk dolní strany (varianta TQFP a PDIP):
Montáž - pohled z dolní strany (varianta TQFP a PDIP):
Letování pinů na dolní straně (varianta TQFP a PDIP):
Spoj je připraven k umístění do krabičky KM78.Ve stěnách a víku krabičky je nutné vyřezat následující otvory (klikněte pro zvětšení; pozor u bočních pohledů si povšimněte šipky směru nahoru). Otvor pro USB konektor bude nutné vyřezat poměrně velký, konektor je hluboko zapuštěný a je nutno zasunout zástrčku i s její izolací.
Ke dnu je deska uchycena pomocí distančních sloupků o délce 5 mm a se závitem M3. Závit sloupku je nutné trochu upilovat, aby nebyl delší než sloupek krabičky. Závit M3 drží ve sloupcích krabičky dobře, ale lze snadno strhnout neopatrným šroubováním sloupku.
Deska se do sloupků přišroubuje šroubky M3.
Konektory na dolní straně desky přiléhají těsně na dno krabičky. Horní víko krabičky doléhá těsně na osazení hmatníků tlačítek. Pozorujete-li, že tlačítka nereagují na stisk (necvakají), jsou zamáčknutá víkem krabičky. V tom připadě je nutné buď podložit víko krabičky, nebo zvětšit otvory pro tlačítka (aby se vešla i s jejich osazením), nebo ze spodní strany víka rozšířit otvory vyfrézováním drážky (to je použito na fotografiích).
Potisk krabičky jsem vyřešil vytištěním papírové popisky a přelepením průhlednou izolepou. Doporučuji na štítku uvést použitý procesor, frekvenci a příponu souborů. K tomu lze využít připravené potisky.
Použijete-li již naprogramovaný procesor, měla by po zapnutí (připojení USB nabíječky s mini-USB konektorem) začít blikat indikační LED, indikující že se bootloader snaží zavést bootovací program. Budete-li procesor programovat sami, doporučuji nejdříve vyzkoušet testovací program, který nedělá nic jiného, než že bliká indikační LED diodou v rytmu 1 Hz. Tím ověříte, zda je procesor funkční a zda je jeho oscilátor správně funkční. V balíku jsou testovací programy přeložené pro různé varianty ATpadu - podle dříve uvedeného seznamu označení přípon souborů. Pro testovací program použijte následující nastavení pojistek (rychlý krystal, reset vektor ukazuje do aplikace na adresu 0):
ATmega8: low 0xEF (default 0xE1), high 0xC9
(default 0xD9)
ATmega88: low 0xE7 (default 0x62), high 0xDF (default 0xDF), ext
0xF9 (default 0xF9)
ATmega328p: low 0xE7 (default 0x62), high 0xDB (default 0xD9),
ext 0xFF (default 0xFF)
Po základním ověření funkčnosti naprogramujte do procesoru BootLoader, který naleznete v root adresáři demonstračního disku.- jsou to soubory s příponou .HEX, ve jménu souboru je jméno varianty podle dříve uvedeného seznamu. Pojistky naprogramujte takto:
ATmega8: low 0xEF (default 0xE1), high 0xC8
(default 0xD9)
ATmega88: low 0xE7 (default 0x62), high 0xDF (default 0xDF), ext
0xF8 (default 0xF9)
ATmega328p: low 0xE7 (default 0x62), high 0xDA (default 0xD9),
ext 0xFF (default 0xFF)
V pojistkách je důležité nastavení - použít rychlý krystal, použít boot loader o velikosti 2 KB (= 1 K slov), resetovací vektor umístit do boot loaderu.
Po zápisu BootLoaderu zapněte pojistku procesoru BLB11. Ta slouží k ochraně boot loaderu proti chybě aplikace (aby aplikace nemohla boot loader poškodit neoprávněným zápisem). Bez této pojistky sice ATpad pojede také, ale mohlo by se stát, že někdy po chybě přestane boot loader fungovat.
Po naprogramování by měla začít blikat indikační LED, indikující zavádění boot loaderu z SD karty. Po připojení displeje by měl být vidět obraz zavaděče programů. Není-li obraz vidět, zkuste zapnout správný typ displeje pomocí tlačítek B+šipka (při prvním startu implicitně zvolen VGA displej).
Nejjednodušší způsob připojení je pro VGA displej, který jen zasunete do VGA monitoru. K připojení televizoru můžete použít buď X4 RGB konektor (8-pin mini-DIN) nebo X2 VGA konektor. U obou konektorů jsou k dispozici prakticky všechny potřebné signály (včetně zvuku). U X4 RGB konektoru jsou k dispozici řídicí signály SWITCH a BLANK pro SCART konektor, které zajistí automatické přepínání vstupu televizoru po zapnutí ATpadu a volbu správného poměru obrazu. U X2 VGA konektoru lze pro signál BLANK použít odpor 100R připojený k signálu SWITCH. Nepodporuje-li televizor RGB vstup, lze vytvořit kompozitní černobílý signál pouhým spojením výstupů R, G, B a SYNC (příp. ještě přes omezující odpor, dochází-li k přebuzení).
Root složka disku:
Složka DEMO (demonstrace):
Složka GAME (hry):
Složka TEST (testování a diagnostika ATpad):
![]() |
COLORS - horizontální testovací pruhy barev s indexem 1 až 15 (černá barva s indexem 0 chybí). Klávesy: B = opuštění programu. |
![]() |
LED - testovací blikání indikační LED, s intervalem 1 sekunda. Všechny ostatní funkce jsou potlačeny, neprobíhá výstup na displej. Program lze přerušit pouze resetem ATpad. |
Složka TUTORIAL:
![]() |
HELLO - nejjednodušší ukázkový program. Vypíše text na obrazovce. Program lze přerušit pouze resetem ATpad. |
Programy pro ATpad (včetně bootovacího zavaděče) jsou napsány v C spolu s assemblerem AVR a překládají se na PC pomocí překladače WinAVR 20100110 (avr-gcc 4.3.3). Instalátor lze stáhnout např. ze SourceForge https://sourceforge.net/projects/winavr/. Instalátor by měl přidat do systémové proměnné PATH cestu do složky C:\WinAVR\bin, odkud se bude volat překladač.
Rozbalte archiv se zdrojovými kódy ATpad do nové složky. Uvnitř naleznete složky s jednotlivými aplikacemi. Složka !BootLoader obsahuje kód bootovacího zavaděče (2 KB trvale se nacházející na konci paměti ROM) spolu s programem pro spouštění aplikací. Po překladu se vygeneruje soubor HEX, který zapíšete do ROM procesoru programátorem. Po zápisu nastavte pojistky a zámky procesoru tak, jak bylo uvedeno v sekci Oživení. Další přeložené programy již nebudete do procesoru zapisovat programátorem, ale uložíte je na SD kartu a spustíte v ATpadu spouštěcím programem. SD karta musí být naformátována na FAT16, návod byl uveden v sekci SD karta.
Aplikace se překládají povelovým souborem c.bat (=compile). Nepotřebné produkty překladu lze smazat pomocí d.bat (=delete). Vygenerované soubory se současně nakopírují i do složky !OK. Po překladu všech aplikací bude složka obsahovat obraz SD disku. Všechny programy naráz lze přeložit dávkovým souborem c_all.bat. Překlad všech aplikací trvá asi půl hodiny.
Složka "_timings" obsahuje program ATpad_timings, který slouží k výpočtu časování. Volá se během překladu. Programu se předají potřebné parametry přes příkazový řádek. Ze souboru timings.ini si načítá konfiguraci knihoven (počet taktů jednotlivých větví programu). Pokud možno, nezasahujte do knihoven ve složce "video", změny by vyžadovaly opravu parametrů časování.
Složka "_sprites" obsahuje společné grafické podklady - definice fontů a programy pro import fontů, obrázků a sprajtů do ATpad.
Složka "_lib" obsahuje knihovny použité aplikacemi ATpad, většinou psané v assembleru - matematické operace, obsluha displeje, generátor náhody, obsluha souborů a zvuku. Podrobný popis funkcí naleznete v sekci Knihovny.
Budete-li si chtít vytvořit svou vlastní aplikaci:
Dobrým příkladem je aplikace HELLO. Nedělá nic jiného, než že zobrazí text uprostřed obrazovky. Je tam dobře vidět minimum potřebné pro překlad aplikací. Soubor "asm_sprites.S" obsahuje grafické podklady (fonty, sprajty). Je překládaný assemblerem, aby bylo možné řídit zarovnání polí. Soubor "include.h" obsahuje odkazy na všechny použité soubory *.h (definice) a je vnořen do každého souboru *.c. Soubor main.c je hlavní program, main.h je jeho hlavičkový soubor (zpřístupnění definic pro další části programu). Soubor makefile obsahuje odkazy na překládané části programu - do něj přidáte jména všech přidávaných souborů *.c a *.S.
Prvním příkazem funkce main() by vždy měl být Init(). Inicializuje ATpad, software i hardware. Druhým příkazem je ReadConfigLoader() - načte konfiguraci displeje a přepne displej na PAL, NTSC nebo VGA. Displej se přepíná programově pouze při použití UNI módu (univerzální mód). V UNI módu je rozměr videomódu omezen nejnáročnějším prvkem - což obvykle znamená VGA displej. Zvolíte-li typ displeje explicitně (místo UNI zvolíte PAL, NTSC nebo VGA), můžete u televizních módů použít podstatně vyšší horizontální rozlišení. Ovšem za cenu, že program nelze přepnout na jiný typ displeje (resp. pro každý displej musíte vygenerovat zvláštní soubor).
Používá-li se v aplikaci generátor náhodných čísel, měl by následovat příkaz Randomize(). Ten zajistí načtení výchozí hodnoty generátoru náhody z EEPROM a tím různou náhodnost při opakovaném spouštění. Následuje hlavní smyčka programu - obvykle nekonečná smyčka while(1) {}. Je vhodné, aby smyčka obsahovala příkaz WaitFrame(). Příkaz čeká na vertikální synchronizační puls a to zajistí nezávislost běhu programu na rychlosti procesoru.
Knihovní soubory se nachází ve složce "_lib". Do aplikace jsou přidané pomocí odkazu z makefile "include ..\_lib\makefile", v asm_sprites.S odkaz "#include ..\_lib\asm.inc" a v include.h odkaz "#include ..\_lib\base.h". Knihovna obsahuje složky: add součet čísel, bits bitové operace, disp zobrazení na textovém displeji, div dělení čísel, func matematické funkce, mul násobení čísel, rand generátor náhody, shift bitové posuvy, video generátor video signálu. V základní složce knihoven naleznete podporu klávesnice, inicializace, čekání, textový displej, eeprom, obsluha souborů, grafický displej a obsluha zvuku. Pro matematické operace můžete sice využít i standardní operace WinAVR, ale bývají často mnohem pomalejší a větší - obzvláště co se týká 64-bitových operací. V souboru common.h naleznete mnohé užitečné definice, společné pro C i assembler- bitové konstanty, barvy, kódy kláves. V souboru base.h jsou definice použité jen v C - definice znaků, datové typy, hlavičky funkcí. Během překladu se ve složce aplikace vytvoří soubor timings.h, ze kterého můžete použít definice pro displej - především konstanty WIDTH a HEIGHT, představující šířku a výšku displeje (resp. videopaměti) ve znacích (sprajtech). V grafickém módu tyto konstanty opět znamenají rozměr ve znacích, tj. políčko 8x8 pixelů.
Během překladu jsou překládány všechny knihovní soubory. Překladač zajistí, že jsou do výsledného kódu zahrnuty jen použité prvky. Použití znamená nejen uvedení funkce v kódu, ale také zavolání kódu z funkce, která nebude vypouštěna, např. z main(). Překlad funkcí tedy nezvětšuje velikost výsledného kódu, pouze zpomaluje překlad. Chcete-li překlad urychlit, můžete zakomentovat nepoužité funkce volané ze souboru makefile (ve složce _lib) - uvedením znaku # na začátku řádku.
Z důvodu mechanismu vypouštění funkcí je každá funkce v assembleru uvedená v samostatném souboru *.S. Zjistí-li totiž překladač, že některá z funkcí má být v kódu použita, zahrne do výsledného kódu celý soubor *.S, ne jen volanou funkci (ve skutečnosti ani neví, které části souboru k funkci patří a které ne). Proto musí být funkce odděleny.
Globální definice:
WIDTH ... šířka displeje ve znacích (sprajtech)
HEIGHT ... výška displeje ve znacích (sprajtech)
Board[] ... video paměť o velikost WIDTH*HEIGHT. Pro
textové módy s barevným atributem je rozměr 2* větší. Pro
grafický mód obsahuje barevné atributy.
BoardColor[] ... barvy řádků pro textové režimy MONO s
celobarevným řádkem (bity 0..3=popředí, 4..7=pozadí)
Graph[] ... bitová grafika v grafickém módu (1 bit = 1 pixel,
rozliší zda se zobrazí barva pozadí nebo popředí z pole
Board[].
Sprites ... začátek grafických podkladů v ROM (fonty,
sprajty)
s32 abs(s32 n) ... absolutní hodnota celého čísla
void Init() ... inicializace ATpadu
B0..B31 ... konstanta představující bit 0..31
BIT(pos) ... makro definující bit 0..31
COLOR(bg,fg) ... sloučení barevných složek pozadí a popředí
do barevného atributu
knihovna add
Součet celých čísel bez znaménka, výstupem je u64 (QWORD)
u64 AddQB(u64 num1, u8 num2);
u64 AddQW(u64 num1, u16 num2);
u64 AddQD(u64 num1, u32 num2)
u64 AddQQ(u64 num1, u64 num2)
knihovna bits
Zjištění pořadí nejvyššího bitu (=bitová pozice + 1), binární logaritmus. Číslo 0 vrací 0.
u8 OrderByte(u8 val);
u8 OrderWord(u16 val);
u8 OrderDWord(u32 val);
u8 OrderQWord(u64 val);
Zjištění masky čísla, tj. binární číslo z "1" větší nebo rovno zadanému číslu. Např. 0x123 vrací 0x1FF.
u8 MaskByte(u8 val);
u16 MaskWord(u16 val);
u32 MaskDWord(u32 val);
u64 MaskQWord(u64 val);
knihovna div
Dělení čísel bez znaménka, s různou kombinací rozměru vstupů a výstupů. Parametr "rem" je ukazatel na zbytek po dělení (= modulo), může být NULL.
extern u8 DivBB(u8 num, u8 d, u8* rem);
extern u8 DivB10(u8 num);
extern u8 ModB10(u8 num, u8* quot);
extern u8 DivWBB(u16 num, u8 d, u8* rem);
extern u16 DivWB(u16 num, u8 d, u8* rem);
extern u16 DivWW(u16 num, u16 d, u16* rem);
extern u16 DivW10(u16 num);
extern u8 ModW10(u16 num, u16* quot);
extern u16 DivDWW(u32 num, u16 d, u16* rem);
extern u32 DivDB(u32 num, u8 d, u8* rem);
extern u32 DivDW(u32 num, u16 d, u16* rem);
extern u32 DivDD(u32 num, u32 d, u32* rem);
extern u32 DivD10(u32 num);
extern u8 ModD10(u32 num, u32* quot);
extern u32 DivQDB(u64 num, u8 d, u8* rem);
extern u32 DivQDW(u64 num, u16 d, u16* rem);
extern u32 DivQDD(u64 num, u32 d, u32* rem);
extern u64 DivQB(u64 num, u8 d, u8* rem);
extern u64 DivQW(u64 num, u16 d, u16* rem);
extern u64 DivQD(u64 num, u32 d, u32* rem);
extern u64 DivQQ(u64 num, u64 d, u64* rem);
knihovna mul
Násobení čísel bez znaménka, s různou kombinací rozměru vstupů a výstupu.
extern u8 MulBB(u8 num1, u8 num2);
extern u8 MulB10(u8 num);
extern u16 MulWBB(u8 num1, u8 num2);
extern u16 MulWB(u16 num1, u8 num2);
extern u16 MulWW(u16 num1, u16 num2);
extern u16 MulW10(u16 num);
extern u32 MulDWB(u16 num1, u8 num2);
extern u32 MulDWW(u16 num1, u16 num2);
extern u32 MulDB(u32 num1, u8 num2);
extern u32 MulDW(u32 num1, u16 num2);
extern u32 MulDD(u32 num1, u32 num2);
extern u32 MulD10(u32 num);
extern u64 MulQDB(u32 num1, u8 num2);
extern u64 MulQDW(u32 num1, u16 num2);
extern u64 MulQDD(u32 num1, u32 num2);
extern u64 MulQB(u64 num1, u8 num2);
extern u64 MulQW(u64 num1, u16 num2);
extern u64 MulQD(u64 num1, u32 num2);
extern u64 MulQQ(u64 num1, u64 num2);
extern u64 MulQ10(u64 num);
knihovna shift
Bitový posun celých čísel bez znaménka (Shl vlevo, Shr vpravo).
extern u8 ShlB(u8 num, s8 shift);
extern u16 ShlW(u16 num, s8 shift);
extern u32 ShlD(u32 num, s8 shift);
extern u64 ShlQ(u64 num, s8 shift);
extern u8 ShrB(u8 num, s8 shift);
extern u16 ShrW(u16 num, s8 shift);
extern u32 ShrD(u32 num, s8 shift);
extern u64 ShrQ(u64 num, s8 shift);
knihovna video
Obsluha video výstupu (renderování video signálu).
volatile s16 VLine; ... příští
renderovaná videolinka
volatile u16 Frame; ... aktuální snímek (používá se k
časování)
u8 DispMode; ... aktuálně vybraný displej VGA, PAL, NTSC
u8 SplitMode; ... aktuální mód displeje (0 normální, 1 dělená
obrazovka, 2 dvojnásobná výška řádků, 3 poloviční výška
řádků)
u8 Hor; ... horizontální rozlišení ve sprajtech
s16 VVisible; ... počet viditelných videolinek (používá se k
zatemnění části obrazu)
s16 VSyncBeg; ... začátek vertikálního synchronizačního
pulzu
s16 VSyncEnd; ... konec vertikálního synchronizačního pulzu
s16 VLines; ... celkový počet videolinek
u16 GetVLine(); ... zjištění aktuální
video linky
void SetVLine(s16 num); ... nastavení aktuální videolinky
Bool CheckVSync(); ... test zda probíhá vertikální zatemnění
void SetVVisible(s16 num); ... nastavení počtu viditelných
videolinek
void SetVSyncBeg(s16 num); ... nastavení začátku
vertikálního synchronizačního pulzu
void SetVSyncEnd(s16 num); ... nastavení konce vertikálního
synchronizačního pulzu
void SetVLines(s16 num); ... nastavení celkového počtu vertikálních
videolinek
void WaitVSync(); ... čekání na vertikální synchronizační
pulz
u16 GetFrame(); ... zjištění aktuálního snímku
(inkrementuje se každý snímek, používá se jako časovač)
void WaitFrame(); ... čekání na další snímek (používá se
jako časovač po 20 ms nebo 16.7 ms)
void WaitFrameNum(u16 num); ... čekání na zadaný počet snímků
knihovna key
Obsluha klávesnice. Indexy tlačítek naleznete v common.h (KEY_1 = B0, ...)
u8 KeyCnt[KEY_NUM]; ... čítače pro
detekci stisku tlačítek.
u8 KeyMap; ... mapa stisknutých tlačítek
void KeyLoop(); ... obsluha tlačítek, měla by být volána
opakovaně pokud možno každý video snímek
u8 GetKeyMap(); ... zjištění mapy stisknutých tlačítek
(bitové pozice KEY_1 atd), nejdříve je potřeba volat KeyIn()
u16 KeyIn(); ... vstup tlačítek (stisk nebo uvolnění), ve vyšším
bajtu vrací příznak uvolnění tlačítka KEY_REL; 0=nebyla změna
void KeyFlush(); ... vyprázdnění zásobníku kláves
void KeyAllOff(); ... čekání na uvolnění všech tlačítek
knihovna wait
Obsluha čekání. Čekání probíhá formou čekací smyčky s odpočítáváním taktů procesoru. Je přesné pouze v případě, že neprobíhá žádné přerušení. Probíhá-li obsluha zobrazení na displej, mohou se čekací smyčky zpomalit až 10x. Chcete-li čekání nezávislé na zatížení procesoru, použijte WaitFrame().
void wait1us(); ... prodleva 1 us
void waitus(u16 us); ... prodleva 2 až 65535 us
void waitms(u16 ms); ... prodleva 1 až 65535 ms
knihovna disp
Výstup na textový displej.
u8 Color ... aktuálně vybraná barva
(implicitní barva pro textový výstup; bity 0..3=popředí,
4..7=pozadí)
void SetCol(u8 bg, u8 fg); ... nastavení aktuální barvy
void SetFgCol(u8 fg); ... nastavení barvy popředí
void SetBgCol(u8 bg); ... nastavení barvy pozadí
u8* BoardAddr(u8 x, u8 y); ... výpočet adresy ve videopaměti
s16 GetHCycles(); ... počet taktů na
horizontální linku
s16 GetHSyncLen(); ... délka horizontálního synchronizačního
pulzu
s16 GetVLines(); ... celkový počet vertikálních linek
s16 GetVVisible(); ... počet viditelných vertikálních linek
s16 GetVFreq(); ... vertikální frekvence v Hz * 256
s16 GetVBP(); ... vertikální back porch (mezi vsync a obrazem)
s16 GetVFP(); ... vertikální front porch (mezi obrazem a vsync)
u8 GetVSyncLen(); ... délka vertikálního synchronizačního
pulzu
u8 GetRowLines(); ... počet linek na jeden řádek sprajtů
u8 GetSplit(); ... split mód (0 normální, 1 dělený displej,
2 dvojnásobná výška, 3 poloviční výška)
u8 GetHor(); ... počet sprajtů horizontálně
s16 GetViewDefStart() ... implicitní počáteční
viditelná linka
s16 GetViewStart(); ... počáteční viditelná linka
s16 GetViewDefHeight() ... implicitní viditelná výška
s16 GetViewHeight(); ... viditelná výška
void SetView(s16 start, s16 height); ... nastavení počátku a
výšky viditelných linek
void SetViewRel(s16 start, s16 height); ... nastavení počátku
a výšky viditelného obrazu relativně (v 1/1000)
void DispOff() ... vypnutí displeje (pro zrychlení výpočtů)
void DispOn() ... zapnutí displeje
void OpenView(s16 minheight); ... otevření displeje -
rozsvícení po dobu 1/3 sekundy
void CloseView(s16 minheight); ... uzavření displeje -
zhasnutí po dobu 1/3 sekundy
u8 ConvAsc(u8 ch); ... konverze ASCII znaku na index sprajtu
Následující funkce jsou ve variantách: x = zobrazení s implicitní barvou Color, xCol = se zadanou barvou, xNoCol = bez změny barvy
Zobrazení znaku
void DispChar(u8 x, u8 y, u8 ch);
void DispCharCol(u8 x, u8 y, u8 ch, u8 col);
void DispCharNoCol(u8 x, u8 y, u8 ch);
Opakované zobrazení znaku
void DispCharRep(u8 x, u8 y, u8 ch, u8
num);
void DispCharRepCol(u8 x, u8 y, u8 ch, u8 num, u8 col);
void DispCharRepNoCol(u8 x, u8 y, u8 ch, u8 num);
Zobrazení mezery
void DispSpc(u8 x, u8 y);
void DispSpcCol(u8 x, u8 y, u8 col);
void DispSpcNoCol(u8 x, u8 y);
Opakované zobrazení mezery
void DispSpcRep(u8 x, u8 y, u8 num);
void DispSpcRepCol(u8 x, u8 y, u8 num, u8 col);
void DispSpcRepNoCol(u8 x, u8 y, u8 num);
Zobrazení textu z ROM (text má atribut PROGMEM)
void DispTextROM(u8 x, u8 y, const char*
txt, u8 len);
void DispTextROMCol(u8 x, u8 y, const char* txt, u8 len, u8 col);
void DispTextROMNoCol(u8 x, u8 y, const char* txt, u8 len);
Zobrazení textu z RAM
void DispTextRAM(u8 x, u8 y, const char*
txt, u8 len);
void DispTextRAMCol(u8 x, u8 y, const char* txt, u8 len, u8 col);
void DispTextRAMNoCol(u8 x, u8 y, const char* txt, u8 len);
Dekódování čísla od konce bufferu OutBuf s koncovou 0, vrací ukazatel na začátek textu.
u8* DecNum(u32 num);
u8* DecNumW(u16 num);
u8* DecNumB(u8 num);
Délka čísla v OutBuf (vstupem je ukazatel na začátek textu z DecNum)
u8 LenNum(u8* text);
Zobrazení čísla zarovnaného doprava (x je pozice posledního znaku)
void DispNumR(u8 x, u8 y, u32 num);
void DispNumRCol(u8 x, u8 y, u32 num, u8 col);
void DispNumRNoCol(u8 x, u8 y, u32 num);
Zobrazení čísla zarovnaného doleva (x je pozice prvního znaku)
void DispNum(u8 x, u8 y, u32 num);
void DispNumCol(u8 x, u8 y, u32 num, u8 col);
void DispNumNoCol(u8 x, u8 y, u32 num);
Zobrazení HEX čísla (počet číslic: 1, 2, 4, 8)
void DispHexN(u8 x, u8 y, u8 n);
void DispHexNCol(u8 x, u8 y, u8 n, u8 col);
void DispHexNNoCol(u8 x, u8 y, u8 n);
void DispHexB(u8 x, u8 y, u8 n);
void DispHexBCol(u8 x, u8 y, u8 n, u8 col);
void DispHexBNoCol(u8 x, u8 y, u8 n);
void DispHexW(u8 x, u8 y, u16 n);
void DispHexWCol(u8 x, u8 y, u16 n, u8 col);
void DispHexWNoCol(u8 x, u8 y, u16 n);
void DispHexD(u8 x, u8 y, u32 n);
void DispHexDCol(u8 x, u8 y, u32 n, u8 col);
void DispHexDNoCol(u8 x, u8 y, u32 n);
Zobrazení dat z RAM v HEX formátu
void DispHexData(u8 x, u8 y, const u8*
data, u8 num);
void DispHexDataCol(u8 x, u8 y, const u8* data, u8 num, u8 col);
void DispHexDataNoCol(u8 x, u8 y, const u8* data, u8 num);
Zobrazení HEX dat z DOS sektoru 512 B, off=offset v sektoru (zajistí načtení z SD karty)
void DispHexSect(u8 x, u8 y, u32 sect, u16
off, u8 num);
void DispHexSectCol(u8 x, u8 y, u32 sect, u16 off, u8 num, u8
col);
void DispHexSectNoCol(u8 x, u8 y, u32 sect, u16 off, u8 num);
Vymazání obrazovky
void DispClear();
void DispClearCol(u8 col);
void DispClearNoCol();
void SetDispCol(u8 col); ... Nastavení
barvy celé obrazovky a nastavení implicitní barvy (znaky nemaže)
void SetRowCol(u8 y, u8 col); ... Nastavení barvy jednoho řádku
void SetDispMode(u8 dispmode); ... Reinicializace módu displeje
knihovna eeprom
Obsluha EEPROM paměti (ukládání konfigurace programů). Každý program používá své 16-bitové číslo MAGIC k označení konfigurace. Čísla 0, 1 a 0xFFFF jsou rezervována pro systém. Konfiguračních dat může být 6 bajtů. sConfig (v eeprom.h) je konfigurační struktura.
u16 ConfigFind(u16 magic); ... vyhledání
konfiguračního záznamu (vrací offset v EEPROM, -1=nenalezeno)
Bool ConfigRead(void* config); ... načtení konfiguračních dat
(False=nenalezeno)
Bool ConfigVerify(const void* config, u16 off); ... verifikace
konfiguračních dat (False=nesouhlasí)
Bool ConfigWrite(const void* config); ... zápis konfiguračních
dat
sConfig_Loader ConfigLoader; ... konfigurační záznam boot
loaderu
void ReadConfigLoader(); ... načtení konfigurace boot loaderu a
nastavení módu displeje
knihovna file
Obsluha souborů. Souborové funkce v ATpad používají menší velikost sektorů SECT_SIZE než standardní 512 B, kvůli omezené velikosti RAM (pro ATmega8 je to 64 bajtů). SD karty vyžadují přístup po 512 bajtech - ATpad načítá jen potřebnou část fyzického sektoru, zbytek zahazuje. Proto je čtení z SD disku pomalejší než by mohlo být. Sektory se načítají do bufferu DiskBuf.
void FileOpen(sFile* file, u16 sclust); ...
otevření souboru nebo adresáře se zadáním počátečního
clusteru (=alokační blok)
Bool FileSeek(sFile* file, u32 off); ... posun ukazatele v
souboru nebo adresáři
s16 FileReadSect(sFile* file, u32 off); ... načtení sektoru do
DiskBuf (soubor/adresář musí být otevřený s FileOpen)
Bool FileRead(sFile* file, u32 off, void* buf, s16 len); ... načtení
otevřeného souboru do bufferu v RAM
knihovna func
Matematické funkce - základní goniometrické funkce.
Celočíselný sin/cos. Vstupem je relativní úhel v rozsahu 0 až 255. Hodnota úhlu 0 až 256 odpovídá úhlu 0 až 90 stupňů. Výstupem je relativní číslo 0..255, představující hodnotu 0 až 1.
u8 SinB(u8 angle);
u8 CosB(u8 angle);
sin/cos v plném rozsahu. Vstupem je číslo 0..255 představující úhel 0..360 stupňů. Výstupem je hodnota -127 až +127, odpovídající hodnotě -1..+1.
s8 SinBFull(u8 angle);
s8 CosBFull(u8 angle);
knihovna graph
Obsluha grafického displeje - bitová mapa s barevnými atributy, 1 atribut je přiřazen políčku 8x8 pixelů. Definici barevného módu "colormode" naleznete v graph.h - zobrazení bez změny barvy, se zadáním barvy, nastavení pixelu, nulování pixelu, změna pixelu. Kreslicí funkce nekontrolují přetečení hranic displeje.
void DrawPixel(u8 x, u8 y, u8 colormode, u8
col); ... vykreslení pixelu
void DrawLine(u8 x1, u8 y1, u8 x2, u8 y2, u8 colormode, u8 col);
... vykreslení linky
void DrawBox(u8 x, u8 y, u8 w, u8 h, u8 colormode, u8 col); ...
vykreslení obdélníku
knihovna sound
Obsluha zvukového výstupu. Je-li to možné, používejte k výstupu jednoduchých tónů pouze funkci Beep. Funkce pro přehrátí melodie Play je náročná na spotřebu paměti ROM.
void Beep(u16 f, u8 len); ... přehrátí
tónu, f=časová konstanta (tón závisí na horizontální
frekvenci displeje), len=délka ve snímcích
Bool Playing(); ... test zda probíhá přehrávání melodie
(zadané příkazem Play)
void WaitPlaying(); ... čekání na ukončení přehrávání
melodie
void PlayLoop(); ... obsluha přehrávání melodie (mělo by být
voláno periodicky z hlavní smyčky)
Přehrátí melodie z ROM (zadané jako
text s atributem PROGMEM). Syntaxe textu:
On ... nastavení bázové oktávy n=0..7
Ln ... nastavení implicitní délky n=0..7
+ ... zvýšení oktávy pro následující 1 notu
- ... snížení oktávy pro následující 1 notu
C, C#, D, D#, E, F, F#, G, G#, B (nebo H) ... přehrátí noty, může
následovat číslice 0..7 udávající délku, tečka prodlouží
o polovinu
R ... přehrátí pauzy, může následovat číslice 0..7
udávající délku, tečka prodlouží o polovinu
n ... číslice 0..7 následující za notou nebo pauzou udává
délku noty
. ... tečka následující za notou nebo pauzou (a příp. číslicí
délky) prodlouží délku o polovinu
void Play(const char* melody); ... přehrátí melodie zadané jako text v ROM (atribut PROGMEM)
knihovna rand
Generátor náhody.
u32 RandSeed; ... náplň generátoru
náhody
void SetRandSeed(u32 seed); ... inicializace generátoru náhody
u32 RandShift(); ... posun generátoru náhody o 1 krok (navrací
novou hodnotu RandSeed)
Výpočet náhodného čísla bez znaménka
u8 RandByte();
u16 RandWord();
u32 RandDWord();
u64 RandQWord();
Výpočet náhodného čísla se znaménkem
s8 RandChar()
s16 RandShort()
s32 RandInt()
s64 RandLong()
Výpočet náhodného čísla bez znaménka, v rozsahu 0 až max (včetně zadané hraniční hodnoty)
u8 RandByteMax(u8 max);
u16 RandWordMax(u16 max);
u32 RandDWordMax(u32 max);
u64 RandQWordMax(u64 max);
Výpočet náhodného čísla se znaménkem, v rozsahu 0 až max (včetně zadané hraniční hodnoty, max může být negativní)
s8 RandCharMax(s8 max);
s16 RandShortMax(s16 max);
s32 RandIntMax(s32 max);
s64 RandLongMax(s64 max);
Výpočet náhodného čísla v zadaném rozsahu min až max (včetně zadaných hraničních hodnot). Je-li min > max, generuje se číslo vně intervalu.
u8 RandByteMinMax(u8 min, u8 max);
u16 RandWordMinMax(u16 min, u16 max);
u32 RandDWordMinMax(u32 min, u32 max);
u64 RandQWordMinMax(u64 min, u64 max);
s8 RandCharMinMax(s8 min, s8 max);
s16 RandShortMinMax(s16 min, s16 max);
s32 RandIntMinMax(s32 min, s32 max);
s64 RandLongMinMax(s64 min, s64 max);
void Randomize(); ... inicializace generátoru náhody číslem z EEPROM. Mělo by být voláno pouze 1x při startu aplikace. Funkce zajistí, že při příštím spuštění bude mít aplikace jiný výchozí stav generátoru náhody.
knihovna boot
Funkce rezidentního bootovacího zavaděče. Zavaděč začíná na adrese BootStart, což odpovídá adrese resetovacího vektoru. U ATmega8 je to adresa 0x1800 (offset 6 KB). Pozor, boot loader nepoužívá fyzické sektory 512 bajtů (jak vyžadují SD karty), ale používá menší sektory SECT_SIZE (z důvodu omezené RAM, typicky 64 bajtů). Položky odvolávající se na sektory jsou přepočítány na logické sektory.
Data boot loaderu v RAM
u8 DiskBuf[SECT_SIZE]; ... diskový buffer
(sem se načítá logický sektor z SD disku)
u32 DiskBufSect; ... aktuální logický sektor načtený v
DiskBuf (-1 = není)
u16 RootNum; ... počet položek v ROOT adresáři
u16 ClustSizeSect; ... velikost clusteru v počtu logických
sektorů
u32 FatBase; ... logický sektor začátku FAT
u32 RootBase; ... logický sektor začátku ROOT adresáře
u32 DataBase; ... logický sektor začátku dat
u16 FileClust; ... počáteční cluster aktuálně spouštěného
programu
u16 DirClust; ... počáteční cluster adresáře se spouštěným
programem
u16 FileInx; ... index spouštěného programu v adresáři
u8 ClustSizeSectBits; ... počet bitů vyjadřující velikost
clusteru v počtu sektorů (0=1 sektor)
u8 SDType; ... typ SD karty
Data na začátku boot loaderu (jsou v ROM, tedy atribut PROGMEM)
const u8 BootVer PROGMEM; ... verze boot
loaderu (bity 7..4 major číslice, bity 3..0 minor číslice)
const u8 BootVar PROGMEM; ... varianta procesoru (bit 7..4
velikost ROM v KB, 3=8KB...7=128KB, bit 3..0 alternativa MCU)
const u8 BootFile[8] PROGMEM; ... jméno startovaného boot
loaderu ("BOOT")
const u8 BootExt[4] PROGMEM; ... přípona jména načítaných
programů
Funkce boot loaderu
void BootReset(); ... reset boot loaderu
void SDInit(); ... inicializace SD karty
Bool SDConnect(); ... připojení SD karty
void SDDisconnect(); ... odpojení SD karty
Bool SDReadSect(u32 sector, u8* buffer); ... načtení sektoru z
SD karty
u8 SDSendCmd(u8 cmd, u32 arg); ... odeslání povelu na SD kartu
void SDSel(); ... zapnutí výběru SD karty
void SDUnsel(); ... vypnutí výběru SD karty
u8 SDByte(u8 data); ... příjem a vyslání bajtu na SD kartu
(vyšlete 0xFF chcete-li jen číst)
void DiskInit(); ... inicializace obsluhy disků (předtím volat
SDInit())
extern Bool DiskMount(); ... mountování disku
extern void DiskUnmount(); ... odmountování disku
void DiskExecFile(u16 clust, u32 size); ... spuštění programu
zadaného počátečním clusterem a velikostí
Bool DiskReadFile(u16 clust, u32 off, u16 num, u16 addr, u8 mem);
.... načtení souboru do ROM, RAM, EEPROM
void DiskWriteMem(u16 addr, u8 off, u8 len, u8 mem); ... zápis
dat z DiskBuf do ROM, RAM, EEPROM
Bool DiskMoveBuf(u32 sect); ... přesun okna v DiskBuf na zadaný
sektor
Bool DiskClustValid(u16 clust); ... kontrola platnosti clusteru
u32 DiskClustSect(u16 clust); ... přepočet clusteru na logický
sektor
u16 DiskReadFat(u16 clust); ... čtení položky FAT pro zadaný
cluster
u8 DiskGetByte(u32 sect, u16 off); ... načtení bajtu z DOS
sektoru (sect je fyzické číslo sektoru 512 B, off je offset v
sektoru)
u8 DiskCheckFS(u32 sect); ... kontrola FAT souborového systému
(sect je fyzické číslo sektoru 512 B)
void SpmWait(); ... čekání na ukončení SPM zápisu
void SpmCmd(u8 cmd); ... provedení instrukce SPM
void SpmWrite(void* dst, void* src); ... zápis SPM stránky do
ROM
void EEWait(); ... čekání na ukončení zápisu do EEPROM
u8 EERead(u16 addr); ... čtení bajtu z EEPROM
void EEWrite(u16 addr, u8 data); ... zápis bajtu do EEPROM
void EEWriteData(u16 dst, const void* src, u16 num); ... zápis
dat do EEPROM
void MemCpy(void* dst, const void* src, u16 len); ... kopie dat v
RAM
V knihovně "video" je k dispozici 12 předdefinovaných videomódů. Je sice možné vytvořit si své vlastní videomódy, ovšem vyžadovalo by to úpravu programu ATpad_timings, který se používá k výpočtu časování renderovacích funkcí.
Horizontální rozlišení videomódu závisí na frekvenci použitého krystalu. Program pro výpočet časování kontroluje během překladu překročení hranic, v tom případě ohlásí chybu a překlad se přeruší. Kontrolují se hranice mezi horizontálními synchronizačními pulsy, ne zobrazitelnost. Skutečná zobrazitelná část je o něco menší než vzdálenost mezi pulzy a je potřeba zkontrolovat zkouškou. Obzvláště malé přenosné televizory ořezávají obraz značně.
(0) MODE_ASCMONO6 - mono ASCII text 6x8 pixelů. Tabulka znaků používá jen první polovinu, tj. nižších 128 znaků. Ze znaků se zobrazí jen 6 pixelů na lince. K jednotlivým znakům nelze přiřazovat barvu. Ovšem lze nastavovat barvu pro celý řádek najednou. Tento režim je velmi úsporný jak k paměti ROM (tabulka znaků spotřebuje 1 KB), tak i k paměti RAM. Oproti následujícímu módu (s 8 pixely) umožňuje zobrazit více znaků na řádek.
(1) MODE_ASCMONO8 - platí stejné jako u předešlého módu, jen znaky jsou širší (8 pixelů místo 6 pixelů) a tak se na řádek displeje vejde o něco méně znaků.
(2) MODE_MONO6 - liší se od režimu ASCMONO6 tím, že k dispozici je všech 256 znaků. To je náročnější na paměť ROM (tabulka znaků spotřebuje 2 KB).
(3) MODE_MONO8 - liší se od režimu ASCMONO8 tím, že k dispozici je všech 256 znaků. To je náročnější na paměť ROM (tabulka znaků spotřebuje 2 KB).
(4) MODE_ASCTEXT6 - barevný ASCII text 6x8 pixelů. Tabulka znaků používá jen první polovinu, tj. nižších 128 znaků, tabulka znaků tak zabere jen 1 KB ROM. Ze znaků se zobrazí jen 6 pixelů, to umožní zobrazit více znaků než font 8x8. Ke každému znaku lze přiřadit barevný atribut (ve videopaměti se střídají znaky s barevnými atributy) - za cenu 2x vyšší spotřeby paměti RAM oproti MONO videomódu.
(5) MODE_ASCTEXT8 - od předešlého módu se liší použitím znaků 8x8 pixelů (na řádek se vejde o něco méně znaků)
(6) MODE_TEXT6 - od režimu ASCTEXT6 se liší plnou tabulkou 256 znaků (náročnější na ROM, tabulka znaků zabere 2 KB)
(7) MODE_TEXT8 - od režimu ASCTEXT8 se liší plnou tabulkou 256 znaků (náročnější na ROM, tabulka znaků zabere 2 KB)
(8) MODE_TILE6 - barevné dlaždice (sprajty) 6x8 pixelů. Ve video-RAM jsou indexy do pole dlaždic. Tímto způsobem lze nadefinovat plně barevné dlaždice. Vhodnou přípravou sprajtů lze zajistit i animace. Ovšem dlaždice jsou velmi náročné na paměť ROM (1 dlaždice zabere 28 bajtů).
(9) MODE_TILE7 - barevné dlaždice 7x8 pixelů. Paměťové nároky jsou stejné jako u následujícího režimu 8x8 pixelů (1 dlaždice zabere 32 bajtů), výhodou je o něco větší počet sprajtů na řádek.
(10) MODE_TILE8 - barevné dlaždice 8x8 pixelů. 1 dlaždice zabere v ROM 32 bajtů.
(11) MODE_GRAPH - grafický mód s barevnými atributy (ve stylu grafiky ZX Spectrum). Velmi náročné na RAM. V poli Graph je bitová mapa. Každý 1 bit představuje 1 pixel na obrazovce a přepíná, zda se zobrazí barva pozadí nebo popředí. Pole Board obsahuje barevné atributy s barvou popředí a pozadí. Každý atribut přináleží políčku 8x8 pixelů.
Ukázkové aplikace (přeložené pro ATmega8, 88 a 328p, frekvence 16/20/24/27 MHz)
Zdrojové kódy boot loaderu a aplikací
Grafické podklady (schéma a plošný spoj)
Kompletní download podkladů ATpad (včetně www stránky)
Výběr součástek byl uzpůsoben na prodejnu GM Electronics, kterou mám blízko
Součet ceny za vše je 432 Kč (včetně fotocuprextitu, krabičky a zástrčky mini-din).
Výše uvedená verze ATpad je již 3. prototypovou verzí. První prototyp (ATpad verze 1) měl ale také zajímavé vlastnosti, které by mohly posloužit k inspiraci pro další vývoj. Čím se lišil:
Miroslav Němeček