Tigrian tasztillesztője

From Enterprise Wiki
Revision as of 18:06, 14 March 2007 by Mrprise (talk | contribs)

Jump to: navigation, search

Tasztillesztő

Protokol

Az egész protokol az EP taszt --nem használt-- 10..15 címét használja.

A bootloader addig (és csak addig) aktív, amíg ilyen címeket kap. Az elsõ "igazi" EP-taszt címre (0..9) a mûködése befejezõdik.

Van tehát 6-féle kódunk, ezek egyenként:

[font=Courier New]0A: EADDR (cím beállítása) 0B: EBIT1 (1-es bit küldése) 0C: EBIT0 (0-s bit küldése 0D: EDATA (RAM adat cseréje) 0E: EFLSH (flash, vagy EEPROM írása) 0F: ELAST (utolsó kód?)[/font]

A válasz-adatokat a normál taszt-emu táblába teszem. Ami ezután az U27 bemenetén olvasható, [b]a következõ alkalommal[/b] . Miért is? Mert a Z80-nal a kommunikáció OUT-IN párossal történik. Az OUT (B5),0A..0F hatására megy valamelyik programrészre, ami beírja a taszt-emu táblát, ugyanúgy, mint normál mûködés esetén. A taszt-emu táblából viszont IT rutin-nal kérdezhetõ le az adat, vagyis a következõ OUT hatására teszi ki az adatot.

[quote] Miért nem azonnal? Egyrészt, mert nincs "azonnal". Idõt kéne definiálni rá, hogy leghamarabb mikor kerülne ki az adat. Ami igencsak változó, a legtöbb esetben gyorsabban, mint ahogy a Z80 új utasítást hajt végre ;) , de pl. az EEPROM írás 30 msec körüli. Másrészt, mert akkor csak egyféle adatot tudnék küldeni, mindig. Így viszont az emu-ramból egyszerre többféle is kiolvasható. [/quote]


Minden egyes címre elõször azonnal 00-t tesz az emuram[0F]-re (tehát a Z80-nal OUT (B5),0F / IN (B5)-re FF olvasható), majd amikor elvégezte a feladatot, akkor egy kódot (rendszerint u.azt a címet) teszi ki.

Az adatok cseréje tehát az egyik irányban (EP->uC) bitenként, míg a másik irányba (uC->EP) byte-onként történik. A bootloader 1 shift regisztert, pár egyéb regisztert és egy 64 byte-os RAM területet használ ehhez. Valamint természetesen a normál emu-RAM területet.

[font=Courier New] progdataw: ... 16 bites (shift) adatregister progaddrw: ... 16 bites címregiszter progcnt: ..... 8 bites adatszámláló (valójában biteket is számol) bufptr: ...... pointer a belsõ pufferre tab_ram: ..... ez maga a puffer is egyben lastcode: .... 8 bites adat, amivel lekérdezhetõ, mi is történt [/font] Van még egy timer is (kb. 120 msec), amit az elsõ belépéskor indítok, és minden EFLSH újraindítja.


C (szerû) szintakszist használok itt, elnézést, ha valakinek nem egyértelmû


0A..0F: emuram[0F] = 0 lastcode = funkció (0A..0F) call func


A funkciók


[font=Courier New]EBIT1 (0B): progdataw = progdataw * 2 + 1 emu[0B] = EEPROM[progaddr] emu[0C] = FLASH[progaddr++] progcnt = progcnt+1


EBIT0 (0C): progdataw = progdataw * 2 + 0 emu[0C] = FLASH[progaddr++] progcnt = progcnt+1


EADDR (0A): progaddrw = progdataw bufptr = tab_ram progcnt = 0


EDATA (0D): progcnt = 0 : emu[0D] = *bufptr++ ....... !=0 : bufptr túlcsordult ? lastcode |= D0 ............. egyébként: ................... *bufptr++ = LOW(progdataw) ................... ++progcnt



EFLSH (0E): timer lejárt ? .......... lastcode |= 0x10 progcnt != 32 ? ..........lastcode |= 0x20 progaddr -= progcnt progaddr != progdata ? .. lastcode |= 0x40 progaddr hibás ? ........ lastcode |= 0x40 bufptr != tabram ? ...... lastcode |= 0x80

lastcode < 0x10 : ......progaddr < 0x200 : EEPROM írása tabram-ból, 32 byte .......................: FLASH ----------- " ------------ ......timer újrindítása


A címnek 0x800-nál kisebbnek kell lenni, és az alsó 5 bit 0 kell legyen. Egyébként hibás. A buftr = tabram EADDR esetén keletkezik, EDATA viszont elrontja. Írás tehát csak akkor lehetséges, ha a sorrend EADDR, aztán (32-szer) EBITx volt.


ELAST (0F): emuram[0F] <- lastcode [/font]



A használat tehát a következõ:

--OLVASÁS-- EBITx funkciókkal 16 bitet át kell vinni. EADDR átteszi ezt címmé. Ezután

az EEPROM tartalmát folyamatos EBIT1 küldözgetésével lehet olvasni, ...vagy... a FLASH tartalmát folyamatos EBIT0 küldözgetésével lehet olvasni, ...vagy... tabRAM tartalmát folyamatos EDATA adja vissza (itt a cím értéke nem számít, de KELL az EADDR! Az EBITx viszont kihagyható)


--ÍRÁS-- eloször mindig a tabRAM-ba 1. EADDR 2. (8-szor) EBITx, majd EDATA, ez egyetlen byte-ot ír 3. (2) ismételve max. 64-szer, de FLASH és EEPROM írása csak az elsõ 32 byte-ból történik Ha csak a tabRAM-ot akarjuk írni, akkor ennyi.

4. FLASH, ill. EEPROM irása: a) címet be kell állítani: (16-szor) EBITx, majd EADDR b) még egyszer ki kell adni a címet, pontosan 32 db EBITx hívással c) EFLSH

[quote] Miért pont 32 byte? Mert ennek a uC-nek ekkora a belsõ lapmérete, egyszerre ennyi adatot ír a flash-be. Ez EEPROM-nál nem igaz, de egyrészt így jóval rövidebb a kód, másrészt újabb restrikció a protokolban, ami itt jól jön. [/quote]

ELAST az egész folyamat közben bármikor kiadható, az itt olvasott értékkel ellenõrizhetõ, hogy milyen hívás történt utoljára, és sikeres volt-e.


Az emuram-ba írt érték valójában nem az, amit az Z80 "lát", mert az EP-ben használt 373-as IC (az U27) kicsit zagyván használja a lábait. Mindenki 573-ast használt helyette, amikor már tehette (és akkor nem kéne annyi átkötés sem a uC beépítésekor).

in
76543210
out
65210347

A 7-es bitbõl tehát 6-os bitet, a 6-os bitbõl 5-ös bitet stb. kell "gyártani", a Z80 kódban.

A normál mûködést ez azért nem zavarja, mert már eleve "visszakavart" értékeket írok ki, a tasztdefiníciós értékek így készültek (epkeys.h)


Ha valaki jobban érti a forráskódot  :wink: : http://www.enterpriseforever.org/index.php?action=dlattach;topic=187.0;attach=402

Táblázatok

konverziós táblák felépítése

A taszt-konverzió 4 táblán keresztül valósul meg.

Taszt tables.png

- Van --max. 3 menetben-- a "korrekciós" konverzió. Ezekben a táblákban több bemenethez tartozhat egy (vagy akár több) kimenet. (Késõbb majd érthetõbb lesz, a példákból :-) )

[quote](Miért pont 3? Egy alap, kikapcsolhatatlanul, amire mindig szükség van, vélhetõleg. Ilyenek pl. a lapozó gombok. Egy másik tábla az adott (nyelvi) konfignak megfelelõ, egy pedig a RAM-ban, játszani, próbálkozni, ill. ideiglenes definíciók számára. Mindegyiket külön-külön át lehet programozni, a többi macerálása nélkül.) [/quote]

A 3 tábla szintaxisa, használata teljesen egyforma. Csak a --feldolgozási-- sorrendjük kötött. Ha valamelyik táblában "találat" van, akkor a feldolgozás ott véget ér, a többi tábla már nem kerül sorra. Ha egyik táblában sincs találat, akkor jön az EEPROM tábla.

- Ezután a keyboard által küldött scan kódokat átalakítom "EP" kódokra (vagyis egy saját kódra, ami persze az EP keyboard táblájából adott). Ez a tábla egy-az-egyben megfeleltet egy-egy bill. lenyomást/elengedést. Ez az alap, minden EP billentyûhöz tartozik legalább egy megfeleltetés. (Akár több is, mivel a PC taszton több gomb van.)


Essünk neki! :-) Itt az EEPROM táblája: [url=http://www.enterpriseforever.org/dload.php?action=download&file_id=8]scan2.c[/url] a belsõ "EP" kódok: [url=http://www.enterpriseforever.org/dload.php?action=download&file_id=7]epkeys.h[/url] Ill. kicsit olvashatóbb formában a 2-es scan kódok: [url=http://www.enterpriseforever.org/dload.php?action=download&file_id=10]scan2.txt[/url]

Ha valaki a képet kedveli: File:Taszt eptastnums.png File:Taszt scancodes.png (Az utóbbi [url=http://www.beyondlogic.org/keyboard/keybrd.htm]innen[/url] kölcsönözve. Itt a PC taszt protokollja is megtalálható.)

Vegyük pl. az "A" gombot. A PC taszt --lenyomáskor-- 1Ch kódot küld ki, az EEPROM 1C-edik értéke 15h. (Ez egy belsõ RAM táblába kerül, az IT rutin a tábla alapján "nyomogat".) Az "A" gomb felengedésekor a PC taszt F0 1C kódot küld ki, ebbõl a RAM-ba végül 15h+8 (1Dh) kerül (b3 bit jelzi a felengedést). Az extended kódok kezelése nem itt, vagy egyáltalán nem történik. A "/" és a Keypad "/" gombok pl. (4A ill. E0 4A) egyaránt ugyanazt az "EP" kódot (80h) eredményezik.

Ez tehát az "egy gomb itt - egy gomb ott" táblája.

Most jön a neheze. De elõbb egy kis kitérõ. A váltógombokról állapot-infót tárolok, vagyis a LeftShift, RightSift, Ctrl (bármelyik), LeftAlt, RightAlt (vagy AltGrey) gombok lenyomásának állapotát nyilvántartom (a PC taszt állapotát, nem az EP-ét). No tehát. A probléma a következõ: egy vagy több PC bill.-nek az EP egy vagy több bill.-je kell megfeleljen. Pl. az USA taszton a "'" (aposztróf) egygombos, míg az angol EP-n Shift+7. A magyar taszton Shift+1, a német EP-n meg egygombos. Viszont nemcsak a bill. lenyomását, hanem a felengedését is emulálni kell, így még tovább bonyolódik a helyzet (fordított sorrend az elengedésnél).

[hr]

Nézzünk itt is egy példát, legyen akkor az aposztróf. USA -> angol táblázatból a megfelelõ sor:

[font=Courier New]0x00+ANY+REV, 0x52, KEY_META_SHIFTS, KEY_7, KEY_NO, [/font] 52 a "'" scan-kódja KEY_7 a "7" EP kódja (epkeys.h-ban az értéke) KEY_META_SHIFT ez egy belsõ kód (mivel bármelyik shift lehet) 0x00+ANY+REV ezek a státuszbitek.

Egy definíció tehát így néz ki: státuszbitek, scan kód, EP kód(ok), lezáró (KEY_NO)

A státuszbitekben lehet jelezni - MAKE/BREAK állapotot (BRK) (PC gombra vonatkozik) - extended scan kódot (EXT) - a váltógombok állapotát, - azt, hogy ezek együttesen vagy bármelyik közülük elég-e (ANY) - a definíció oda-vissza érvényes-e (REV)

A scan kód egyértelmû, 2-es scankódtábla alapján.

"EP" kód pedig akár több is lehet, erre egy (jelenleg 8 elemû) puffert tartok fenn. Ezek között vannak metakódok is, ezek speciálisak, mert vagy nem, vagy nem egyértelmû bill.-höz tartoznak.

A fenti definíció tehát azt mondja: ha a bejövõ scan kód 52h [i]és[/i] bármilyen váltógomb-állapot is van, akkor: - lenyomáskor [i]elõbb[/i] legalább az egyik shiftet (most éppen a leftshift van bedrótozva) kell lenyomni, [i]aztán[/i] a 7-es gombot. - elengedéskor fordított a sorrend, [i]elõbb[/i] a 7-est kell elengedni, [i]aztán[/i] a shiftek állapotát visszaállítani (figyelem! nemcsak a leftshift-et! Ezért "meta" kód )

[hr]

Másik példa, PC-n Shift, EP-n nem. A "+" jel, HUN->BRD táblában:

[font=Courier New]// (+) Shift+3 -> [ (shifts care)

 0x20+REV, US_3, KEY_META_SH_BRK, KEY_LBRACKET,			KEY_NO,[/font]

0x20 bármelyik shift lenyomva KEY_META_SH_BRK ez is egy metakód, jelentése: elengedni minden shiftet, break esetén pedig visszaállítani

Tehát: ha shift nyomva és "3"-as bill. scan kódja jön, akkor - make esetén shift-eket elengedni, aztán "[" (angol taszt szerint) - break esetén "["-t elengedni, aztán Shift-ek állapotát vissza.


[hr]

Egy bonyolultabb példa, az "ö" betû, HUN->EPDOS viszonylatban:

[font=Courier New]// (oe) 0 -> Alt+G (shifts care)

 0x00+ANY+REV, US_0, KEY_ALT, KEY_G,					KEY_NO,

// (OE) Shift+0 -> Alt+T (shifts care)

 0x20+REV, US_0, KEY_META_SH_BRK,, KEY_ALT, KEY_T, 			KEY_NO,[/font]

0x20 bármelyik shift lenyomva US_0 ez a 9-estõl jobbra levõ gombot jelenti. Lusta voltam HUN_?? definíciókat készíteni, így mindenhol az US elrendezés szerint vannak

0x00+ANY+REV jelentése: _nincs_ shift lenyomva (és a def. visszafelé is érvényes)

Az elsõ sor tehát ezt mondja: ha [i]nincs[/i] shift nyomva [i]és[/i] a magyar taszton az "Ö" betû scan kódja jön (USA taszton "0"), akkor - lenyomáskor elõbb az Alt, aztán a "G" bill-t kell lenyomni - felengedéskor fordítva, elõbb a "G"-t, aztán az Alt-ot elengedni.

2-ik: Ha a shift lenyomva, és US_0 scan kód jön (vagyis magyar taszton Shift+Ö -t nyomtak), akkor elõbb el kell engedni mindkét shiftet (mert nem tudom, melyik van nyomva, de egyik sem maradhat úgy), Aztán Alt+T -t nyomni. Break (elengedés) esetén visszafelé: Shift lenyomva [i]és[/i] US_0 break kód jön, akkor T-t elengedni, aztán az Alt-ot.

[hr]

Itt rögtön van egy érdekesség. Amikor --sorrendben-- megnyomod a Shift-et, ez "átfut", lesz egy lenyomott Shift. Aztán hozzá az "Ö"-t, akkor --mivel az EPDOS Shift nélkül várja a nagybetût (???)-- az EP-n fel kell engedni. Most tehát a PC és az EP Shift állapota nem egyezik. Ezt vissza kell állítani elengedéskor. Ez meg is történik. De. Ha felengedéskor [i]elõbb[/i] a Shift gombot engeded el, [i]aztán[/i] az "Ö"-t, akkor az már nem fogja "triggerelni" a def. sort (mert az lenyomott Shift-et vár). Ez igaz az összes olyan esetre, ahol a PC és az EP bill. más Shift állapotban van. Ezért (hogy Shift ne ragadjon be) van két külön definíció: [quote](Ez egy kissé bumfordi, de hatékony megoldás. Jobb nem jutott eszembe.)[/quote]

[font=Courier New]// Shifts release

 0x28, US_LSHIFT, KEY_ALLBREAK, 		KEY_META_CONT,
 0x28, US_RSHIFT, KEY_ALLBREAK, 		KEY_META_CONT,[/font]

0x28 (0x20+BRK) bármelyik shift elengedése KEY_ALLBREAK metakód, minden gombot elenged KEY_META_CONT ez egy különleges lezárókód. Normál esetben, ha egy def. sor "triggerel", akkor csak az abban leírtakat hajtom végre, az EEPROM táblát nem használom. Ebben az esetben viszont az EEPROM tábla [i]is[/i] végrehajtásra kerül. [quote] (Hmmm. Ami az adott esetben értelmetlen. Hiszen úgyis minden gombot elngedek, így a Shift-et is. Ez még megmaradt, egy régebbi változatból, most derült csk ki, hogy már nem kell. Legalábbis ide. Ezért jó dokut írni :) )[/quote]

Apropó. Minden "EP" kód, ami ezekben a definíciókban szerepel (KEY_????), egy queue-ba kerül. Az EEPROM táblából jövõk viszont nem. A queue ürítésekor viszont várok egy teljes scan ciklust (20 msec az EP-ben), minden egyes bill.-nél. Muszáj, különben nem jutna érvényre. Emiatt az egész taszt-illesztõ "késik". Akár 40 msec-et is. 20-at a queue ürítésekor, és még 20-at, amíg a scan érvényre lép. Sorry.

[quote]Az egész konverzió egy RAM területet irkál csak. A tényleges információ az EP számára egy IT rutinban történik. A WR0 jel (U25-ös IC 11-es láb) hatására beolvasom az adatbuszt, ez címzi a RAM táblát. Az ott található értéket pedig kiteszem az U27 bemenetére. Viszont csak akkor tehetem ki, ha éppen azt a sort címzi az EP. Meg kell tehát várnom egy ciklust. Másképpen fogalmazva: az EP belsõ tasztja statikus, míg a taszt-illesztõ dinamikus mûködésû. Egyfolytában változik a kimenete.[/quote]

[hr]

Huh. Itt vannak a táblák: [url=http://www.enterpriseforever.org/dload.php?action=download&file_id=11]tab_all.c[/url] [url=http://www.enterpriseforever.org/dload.php?action=download&file_id=12]tab_usen.c[/url] [url=http://www.enterpriseforever.org/dload.php?action=download&file_id=13]tab_huge.c[/url] [url=http://www.enterpriseforever.org/dload.php?action=download&file_id=9]scan2.h[/url]

A táblákat egyenként át lehet írni, nem kell az egész programot módosítani hozzá. A dinamikus helykihasználás érdekében mindegyikre pointer mutat. Valahogy így:

[img]http://enterpriseforever.org/userpix/3_tabptr_2.png[/img]

A CRC ellenõrzés a táblákra nem vonatkozik, csak a "main" részre.

[hr]

Egy sor felépítése tehát:

MODBYTE, SCANCODE, EPCODE, ..... , DEFEND

MODBYTE: b7 Alt (LeftAlt) lenyomva b6 Ctrl (bármelyik) lenyomva b5 Shift (bármelyik) lenyomva b4 AltGr (RightAlt) lenyomva b3 BREAK flag (felengedés) b2 ANY flag b1 REVERSE flag (a definíció oda-vissza érvényes) b0 Extended code (PC ext. scan code)

SCANCODE: scan code set 2, az extended és a break code nélkül (ezek a MODBYTE-ba kerülnek)

A MODBYTE és a SCANCODE tehát azonosítanak egy [i]input[/i] eseményt. Ez egy tetszõleges PC bill. lenyomása vagy felengedése, plusz a váltógombok aktuális állapota.

EPCODE: Ez(ek) kerül(nek) a queue-n keresztül az EMURAM-ba. Ez tehát az [i]output[/i]. Értéke 10..17, 20..27,... 90..97 a lenyomott billentyûkre. Felengedéshez pedig b3 (BREAK bit) is beállítva (18..1F,....,98..9F)

DEFEND: a def. végét jelzi, értéke KEY_NO (FFh)

Ha tehát egy definíció BREAK flag nélkül van, akkor egy billentyû lenyomására aktiválódik. Ilyenkor a queue-ba az EPCODE-ok kerülnek, balról jobbra, ahogy vannak. Ha a definícióban a REVERSE flag is aktív [i]és[/i] felengedett input esemény van, akkor a definíció alapján [i]jobbról balra[/i] kerülnek a queue-ba az EPCODE-ok, de [i]invertált[/i] BREAK bittel.

Az ANY flag eredetileg arra szolgált, hogy a váltóbillentyûk között VAGY kapcsolatot létesítsen. Egy ilyen definíció tehát a benne szereplõ váltógombok [i]bármelyikére[/i] aktív. De sokkal fontosabb a másik használata, amikor egyetlen váltógomb [i]sem[/i] szerepel a MODBYTE-ban. Ilyenkor váltógombok nélküli definíciót jelent. (Tehát nem igaz olyan állapotokra, amikor bármelyik aktív). Lássuk pédákkal:

0xC0+ANY -> Ctrl és Alt gombok közül bármelyik. 0x00+ANY -> Egyetlen váltógomb sem lehet aktív.


A metakódok:

KEY_META_SCRL, KEY_META_NUML, KEY_META_CAPSL A megfelelõ LED-ek bekapcsolására. Értelme semmi, csak plusz fogyasztást jelentenek. A NumLock ráadásul megbolondítja az extended key-k mûködését.

KEY_META_TABSW0, .. . KEY_META_TABSW3 A 2 kapcsolható (tab_lang, tab_ram) konverziós tábla ki-bekapcsolására szolgál. 0 egyik sem aktív 1 lang 2 ram 3 mindkettõ aktív

KEY_META_OSCxxx Ezek tesztcélokat szolgálnak, a belsõ oszcillátor frekijének kiiratásához, módosításához (tab_all: Ctrl+Alt+ KP+, KP-, KP*)

KEY_META_SHIFTS Ez lenyomja a LeftShift-et. Ellentettje (break párja) KEY_META_RESTORE

KEY_META_RESTORE A két shiftet a --tárolt-- PC állapotnak megfelelõen beállítja.

KEY_META_SH_BRK Mindkét Shift-et felengedi. Break párja KEY_META_RESTORE

KEY_ALLBREAK minden gombot felenged. Ellentettje KEY_ALLMAKE (lenne, ha megírtam volna. De minek? :))

KEY_META_FORCE ez arra szolgál, hogy "erõszakkal" kirakjuk az EMURAM állapotát a portra. A STOP bill. (Ctrl+Break) így mûködik tape LOAD esetén. Hasznos lehet még játékoknál, ha a keyboard scan-t nem használnák. [quote]Ez durva megsértése az IT rutin lényegének. Csak indokolt esetben szabad használni. [/quote]

KEY_META_STOP Ez elõször "normál" STOP billenytût próbál nyomni. Ha adott ideig nem sikerül (az EP nem címzi azt a sort), akkor KEY_META_FORCE lesz belõle.


[hr]

Egy kis segítség: A Ctrl+Alt+PrtScr hatására debug módba kerül a program. Ilyenkor minden egyes billentyûre kiírja az inputot, amit kap, 16 bites számként, és az outputot (8 bites számok), ami ennek hatására a queue-ba kerülne. Ezzel lehet tesztelni a konverziós tábla mûködését, ill. hogy mi is jön ki a PC tasztból (nem a kapott PS2 kódokat mutatom, hanem amit a rutin kap, tehát a tábla felépítése szerint). Kilépni a debug módból ugyanezzel a 3 gombbl lehet (de gyorsan kell nyomni :) ) Vagy pedig Ctrl+Alt+Del, ez pedig SW reset-et generál. [quote]Ez a két spec. "3ujjas" kombináció nem a táblákban van, a fõprogramba van bedrótozva.[/quote]

[hr]