in R26,PIND ; portD pin status is read into R26
RJMP 0x3a
...
...
3a: b6 3f in R3, SREG ; save status register to R3 [on AVR status register is in the "I/O space")
3c: fb a5 bst R26, 5 ; T-bit is set from bit 5 of R26
3e: f9 a3 bld R26, 3 ; T bit is loaded to bit3 of R26
40: 70 af andi R26, 0x0f ; R26 AND 0x0F
42: 2e 5a mov R5, R26 ; copy R26 into R5
44: 6d a0 ori R26, 0xd0 ; R26 OR 0xD0
46: 90 1c ld R1, X ; load memory byte at register X (which is R26-R27 register "pair") into R1
48: ba 17 out DDRB, R1 ; set port direction of portB from R1
4a: 94 23 inc R2 ; R2 = R2 + 1
4c: 24 11 eor R1, R1 ; R1 EOR R1 (R1:=0)
4e: be 3f out SREG, R3 ; restore status register from R3
50: 95 18 reti ; return from interrupt handler
No, ez itt kerem egy AVR disassembler kimenete Tigrian task illesztojenek flash tartalmabol (ami ugye file-ban megvan csak a forrast sikerult elkeverni ...), altalam commentalva, remelem hirtelen nem szurtam el semmit, illetve az I/O port es register neveket atirtam numerikus ertek helyett (amit disasm kidobott) az adott ATtiny-nek megfelelo dolgokra. Ez maga az interrupt handler lenne, amit az INT1 aktivizal, mely utobbi a WR0 (low active) signalra van kotve. Azaz, ha valtozik, a B4 EP porton vmi, mert oda irtak, az alacsony lesz, gondolom AVR itt a lefuto elre reagalva megszakitast general. Valojaban az AVR flash elejen levo (boot loader ezt kicsit megkeveri, mert ATmega-n legalabbis akkor ket helyen is van, sajnos kevesbe emlekszem mar, remelem jot nezek hehe) interrupt tablaban kezdodik a jatek, ahol van sokfele interruptra RJMP (ugras) utasitas, a legelso amugy a reset, itt nincs feltuntetve.
Az elso erdekesseg, amit meg a hex dump-al is megaldott resz ele tettem maga az interrupt tabla ideillo resze. Itt jon az elso trukk, amit Tigrian alkalmazott. Ugyanis, egy utasitasnyi hely van egy interrupt-nak, utana jon a masik interrupt, tehat logikus, hogy onnan el kell ugrani, azaz normal esetben mindenhol RJMP all ebben a tablazatban. Viszont pont az INT1 helyen egy IN utasitas van. Ennek hatasa ugye az, hogy mivel utana mar masik interrupt belepesi pontja van, arra "fut ra" a dolog, ami nem gond, ha az az interrupt ugyse fordulhat elo. Megis miert csinalhatta igy? Gondolom azert, mert igy tudja a leheto leggyorsabban olvasni a B4-re kiadott erteket, amig a Z80 meg tartja a buszon, ha elotte RJMP-vel elugrik, az biza 2 AVR orajelciklus mielott meg vegrehajtodhatna az IN. Ha most Zozo intelmeit megfogadjuk, ez a hokusz-pokusz nem kellene, ha nem kozvetlenul az adatbuszrol venne le ugye, hanem a demultiplexer bemeneterol.
Valojaban amugy a fenti kod ugy mokodhet amit elkepzeltem. Van a foprogram, o foglalkozik a PS/2 kezelessel. Nem tul time critical, par MHz-en siman elkezel egy PS/2 szintu protokolt. Van valahol tarolva az AVR SRAM-jaban egy 10 byte-nyi teruleten az, ami megfelel 8*10 bitre vonatkozolag az "emulalt" billentyuzet allapotanak, a foprogram PS/2 kutyulasa utan ott "nyom meg" vagy "enged el" billentyuket, a megfelelo byte megfelelo bitjenek allitgatasaval. Az interrupt handler nyilvan a WR0 jel lefuto elere lep eletbe, es feladata az, hogy beolvassa, melyik row-t akarja scannelni az EP, es amilyen gyorsan lehet, ez alapjan a B porton kikuldje a fenti kis "taszt allapot tombunk" ezzel indexelt erteket.
A kulcs itt ugye az, amirol targyaltunk, hogy vmi 11 Z80 orajelciklus van, ha a leheto leggyorsabban EP OUT-ba tesz vmit B4-re majd azonnal olvassa is, igy ennyi ido alatt azt meg kell oldani AVR-en.
Mivel AVR-nek azert van par registere, ilyen esetben "felaldozhatunk" parat, amit az interrupt handler hasznal, es nem fogja menteni, ennek eredmenye az, hogy persze foprogramban nem igazan erdemes hasznalni, mert az elso int utan "el fog allitodni". Viszont igy megsporolunk jo par orajelciklust. Viszont, AVR eseten az SREG (status register, amiben van ugye carry flag, meg a szokasos dolgok) mentese / visszaallitasa tovabbra is a mi dolgunk. Az SREG mint I/O port elerheto (valojaban meg a CPU registerek is, sot RAM cimkent is, csak ugy lassabb lenne, vannak trukkok azert AVR-en ...).
Az a T-bites jatek (a T bit az un transfer bit, arra jo, hogy pl adott reg adott bitjet belemasolhatod, vagy kimasolhatod, igy egyszerubb mindenfele bonyolult elforgatasos jatek helyett "kivagni" adott bitet es mashova "berakni") azert kell, mert a kerdeses AVR eszkozon a portD ugye nem bitfolyamatosan van, mivel egyik lab pont onnan INT1 celra van eppen.
Szoval kb logikus, a portB (ahova a 'valaszt' kiirja ugye) kezelese erdekes. Lathatoan nem vmi adatot ir ki, hanem a DDR-t (Data Direction Register, azaz meghatarozza, hogy az egyes labak a portB-n ki vagy bemenetek) allit helyette. Miert is jo ez? Azert, mert parhuzamosan kapcsolodik szegeny taszt illeszto a billentyuzettel! Ha a billentyuzet es a taszt illeszto rossz csillagallas mellett ellenkezo szinteket allitana be az nem lenne tul szep, illetve akar tonkre is tenne vmit. Itt gondolom vmi olyasmi lehet, hogy a portB mint kimenet mindig 0-ra van allitva. Ha a billentyu nincs lenyomva, akkor az adott pin a DDR-el input-ra all, ami kb nagy impendancias allapot, tehat nem szol bele az AVR a jelszintbe. Ha le van nyomva, akkor 0 ertek kell, ekkor output-ba teszi az adott bit-et, es mivel a portB AVR-ben outputra fixen 0-ra van allitva, ez "lehuzza" GND szintre. Ha kozben EP billencs is le van nyomva, no para, mert az is csak foldre huzna le, tehat nincs konfliktus. Bocs, lehet hirtelen elneztem vmit, illetve csak az interrupt kod alapjan mondom ezt, de kb ez a megerzesem, hogy igy mukodik az egesz a fenti par byte-nyi AVR kodra ranezes utan.
Ja, az ORI azert van ott persze, hogy a D0 memoricimtol nezze azt a kis tablazatunkat. Ebben az AVR-ben csak 128 byte RAm van, de az adat cimterulet elejen az I/O elerheto szinten, a D0 valojaban a RAM vege elott 16 byte-tal van. Ez ugye eleg a 10 byte-os "tablazatra", mivel alapvetoen a select jel 4 bites, max nem lesz hasznalva a tobbi.
Azert van itt feher folt, pl az EOR R1,R1 hogy mire jo ... Elvileg ugye nullaza az R1-et, az oke, de utana ugysem hasznalja mar. Gyanitom, hogy ez valamiert a foprogramnak kell aztan. Hasonlo az R2, amit novel eggyel, de semmire sincs hasznalva, gondolom ezt is a foprogram nezi valahol.
Na, vege a mesedelutannak. Most nem akarok felelotlen igeretet tenni, de szerintem ezt meg lehet tomorebben is oldani ... itt ugye a kulcs az, hogy az interrupt kiszolgalasa es az OUT vegrehajtasa kozott eltelt ido az, aminek akkor ugye 11 Z80 orajelnyi ido alatt le kell futnia. Szerintem meg lehetne csinalni gyorsabbra is ennel, foleg, mivel nem feltetlen ertem, mire valo itt 1-2 dolog
Mivel RAM nem kell tul sok az egesz cuccnak, akar fel lehet aldozni azt is, hogy a portD "nem folytonos" kiosztasa miatt vmi elkefelt matrixunk legyen, amiben van egy "nagy lyuk", cserebe a T bites jatek pl megsporolhato. Az R5 hogy mire kell neki az passz, szerintem felesleges. Ez talan szinten a foprogramnak szol, es arra kell, hogy programozni lehessen a taszt illesztot EP-rol? Lehet az R2 novelest erzekelve "latja" a foprogram hogy uj adat lett kiirva, es akkor nezi az R5-ot. Oszinen, en inkabb redundans modon (ha kell ilyen) megcsinalnam az IN-t a foprogramban is, ha a Zozo fele bekotest alkalmazzuk akkor az ott "taszt illeszto programzas" kapcsan nem critical, mig a matrix scan miatti lenne csak az interrupt-ban.
Szoval kiesne egy BST egy BLD, egy MOV, egy INC, egy EOR. Ez ot AVR orajelciklus sporolas az OUT-ig azonnal. Cserebe bonyolitottuk a foprogramot ha programozni is akarjuk az illesztot, es pazaroltunk RAM-ot mert nem "tomor" a kbd allapot "tombunk". Kovetkezo igen extrem optimalizacio: tegyuk az egesz interrupt handlert oda, ahol az int tablazat van
Ezzel nyerunk ket tovabbi AVR orajelciklust (az RJMP nem kell) cserebe kb egyetlen interrupt-ot sem tudunk hasznalni AVR-unkon ami az INT1 utan all, hiszen ott a mi kodunk van helyette. Ezt most csak a hasamra utottem, lehet nem lehet kikerulni vminek a hasznalatat, es ez az elv nem mukodik. Mindenestre a legextremebb adott AVR-re (ami pl mas AVR-n nem is igy nezne ki feltetlen pl mas portkiosztas stb) valo optimalizaciot bevetve 7 AVR orajelciklust sporoltunk azonnal.
Na, most azt hiszem eleget irtam ebben a temaban, kerdeses, hogy valakit erdekelt-e egyaltalan