Myši a ZX Spectrum
Historický úvod
S prvními zmínkami o myši u ZX Spectra jsem se setkal snad už v 90. roce, ale tenkrát nebylo ještě snadné sehnat pěknou myš za rozumné peníze. Velmi často bylo možné koupit myši jen velmi nepraktické do ruky, často velmi hranaté a neergonomické (např. třítlačítkové modely od firmy Genius, případně jako stavebnice - mám jednu s pingpongovým míčkem a tlačítky realizovanými ze svěracích špendlíků s papírovými clonkami). Myši se začaly nejprve vyskytovat u vícebitových počítačů orientovaných na grafiku. Úplně prvním počítačem s kurzorem ovládaným myší byl Xerox Alto z počátku 70. let o kterém jsme tehdy ani netušili, že existuje. Později Apple Macintosh, Atari, Amiga a později i IBM PC. Koncem 80. a začátkem 90. let, tj. v době největšího rozmachu ZX Spectra byly např. u Amigy myši standardní součástí výbavy, u IBM PC je uživatelé teprve objevovali.
Není divu, že uživatelé ZX Spectra uživatelům počítačů s grafickým prostředím trochu záviděli a přemýšleli, jak si taky myšku připojit a naučit se s ní pracovat. Bohužel to nebylo tak jednoduché. U ZX Spectra se vyskytovalo mnoho různých rozhraní, jak paralelních, tak sériových, ale žádné nebylo rozšířeno globálně, žádné rozhraní nikdy nemělo status standardu (byť nepsaného v rámci platformy). Jako např. sériové porty, PS/2 a později USB na platformě PC.
Bylo tedy nutné použít rozhraní, když ne globálně rozšířené, tak alespoň dostatečně rozšířené a pokud možno snadno sehnatelné a levné, aby připojení už tak drahé myši (tenkrát stály často kolem 500Kčs i víc a platy se pohybovaly někde od 2,5 - 5000Kčs) nebylo zbytečně zatěžováno i drahým rozhraním.
Myš připojitelná k sériovému portu
Jednou z možností jak myš připojit byl sériový port. Sériové myši byly snadněji sehnatelné, levnější a byl v nich výrazně větší výběr. Ale ZX Spectrum 48k ani Didaktiky sériový port neměly. Originální ZX Spectrum 128kB, šedivé ZX Spectrum +2, a následující modely Amstradu +2A, +3 už sériový port měly. Ale Sinclair zvolil (a Amstrad převzal) u nás tehdy nesehnatelný britský konektor BT631A. U šedé +2 a následujících modelů od Amstradu navíc není nejšťastněji umístěný, je příliš blízko sběrnice a může být překrytý připojeným interface (např. Betadiskem).
Pokud by toto nebyla dost velká bariéra pro použití sériové myši, tak tento originální sériový port využívá osmibitovou bránu zvukového čipu AY-3-8912. To znamená, že řízení signálů a hlavně serializaci dat musel provádět software, to stojí výpočetní čas. Zároveň v různých přídavných rozhraních s kompatibilním zvukovým čipem se používaly i jiné varianty čipu AY, případně jeho klony a občas i verze bez IO portů. Vytvoření sériového portu by pro uživatele znamenalo zapojení tehdy komplikovaného převodníku úrovní (MAX232 nebyl dostupný), úpravu interface a jiné drobné potíže, které se málo komu chtělo řešit.
Takže sériová myš pro ZX Spectrum existuje, ale je obtížněji připojitelná, má-li být zachována kompatibilita i s 48kB verzemi ZX Spectra včetně těch rozšířených na 128kB a doplněných o AY, protože těm i po rozšíření často chyběly převodníky úrovní mezi TTL a RS232.
Dodnes (rok 2021) jsem se setkal jen s jediným programem, který s RS232 myší pracuje, je jím program Modplay od Štěpána Obdržálka, který hraje na D/A převodník Petra Simandla (též málo známý).
- + skutečná myš
- + standardní PC myš v 90. letech snadno sehnatelná
- − softwarová RS232 náročná na procesorový čas i když mnohem méně než AMouse
- − RS232 interface není tak moc rozšířený
- − minimální softwarová podpora
- − po roce 2020 jsou sériové myši hůř sehnatelné než PS/2
- − moderní klony ZX Spectra často RS232 nemají
Myš připojitelná k paralelnímu portu - AMouse
Paralelní port byl v našich krajích u ZX Spectra mnohem běžnější než port sériový. Existovaly amatérské konstrukce, koupit se dala UR-4 vyráběná v Tesle a hlavně byl v Didaktiku Gama už od výroby. Později byl kompatibilní interface přítomen i v disketových jednotkách Didaktik 40 a Didaktik 80. Dal se dokoupit k Didaktiku M v podobě Interface M/P a v mnoha dalších podobách (třeba Jiiirův UPI). S připojením myši počítá i moje redukce k Didaktiku Gama 192k.
Všechna tato paralelní rozhraní, nejčastěji s čipem 8255, byla určena především k připojení tiskáren a k připojení joysticků kompatibilních se standardem Kempston joystick. Ne vždy ale byl součástí rozhraní i konektor pro joystick. Pokud však byl a pokud měl správně zapojené napájení jako to má UR-4, dal se použít i k připojení některých myší a to bez jakékoli další hardwarové úpravy. Stačilo připojit myš a spustit program. Takovou vhodnou myší byly myši určené pro Amigu případně pro Atari, má-li přepínač přehazující signály z clonek. Proto takové myši říkáme zkráceně AMouse.
Velkou nevýhodou AMouse je obrovské zatížení CPU, protože myš je potřeba obsluhovat zcela kompletně programově a tímto programem, pokud možno, číst stav signálů neustále. Pro další činnosti, krom obsluhy myši zbývá nejvýše 50% času CPU, spíš méně, pokud má být pohyb kurzoru opravdu plynulý. U klikacích menu to většinou nevadí, tam může čtení portu běžet skoro pořád, ale je to těžko použitelné v náročnějších hrách. Přesto se tato myš v mém okolí po určitou dobu rozšířila nejvíc. Částečně kvůli ART Studiu v češtině pro tento typ myši a Betadisk, trochu i kvůli mému Bootu a dalším drobnostem.
Nejsem si jistý, kdo přišel s připojením AMouse první. Možná Heptau? Vzpomínám si, že se objevila na jednom ze Samconů, kdosi tam rozdával nakopírovaný výtisk papíru A4 se zdrojovým kódem jednoduchého ovladače. Fakt je, že stejný princip už byl dříve využíván na jiných osmibitech. Např. na osmibitovém Atari lze ovládat myší (resp. trackballem - princip snímání je stejný) hru Missile Command. TTL myš se taky připojuje do joystickového portu. I na Amize se k připojení myši používá joystickový port. Takže asi bylo jen otázkou času, než někdo zkusí totéž i na ZX Spectrum.
- + skutečná myš
- + triviální připojení, stačí správně zapojený joystick interface
- + standardní Amiga myš (TTL myš), kdysi snadno dostupné
- + existují redukce z PS/2 na Amiga myš, lze používat i optické myši
- + existují dokonce i optické čipy s kompatibilními výstupy
- − zpracování velmi náročné na procesorový čas
- − softwarová podpora není velká, ale taky ne zcela zanedbatelná
Joysticková Kempston Mouse od Proximy
V souvislosti s UR-4 musím zmínit pokus Proximy o rozšíření kompatibilnější a méně náročné varianty, tzv. "Kempston Mouse" Ing. Holmana - neplést se skutečnou Kempston Mouse od firmy Kempston.
Bohužel tuto myš znám jen "z doslechu", neměl jsem příležitost ji vyzkoušet, ale vím (a viz odkazovaný článek), že byla použitelná místo Kempston joysticku tak, že pomocí PWM simulovala délku sepnutí příslušných směrů joysticku a tím se dala hrubě měnit rychlost pohybu kurzoru po obrazovce.
Bylo potřeba, kromě samotného rozhraní joysticku, ještě rozhraní s jednočipovým mikroprocesorem PIC, takže její připojení zcela jednoduché nebylo. O to jednodušší bylo využití v programech. Teoreticky fungovala s naprostou většinou programů používajících Kempston joystick a to buď stejně jako joystick, nebo v lepším případě skoro jako skutečná myš. Viz článek o této myši přímo od autora (bohužel už jen na Archive.org).
- + teoreticky funkční s každým programem, který pracuje s Kempston joystickem
- − není skutečná myš, spíš hybrid mezi joystickem a myší
- − softwarová podpora diskutabilní
Skutečná Kempston Mouse zvaná KMouse
Jednou z možností je i vytvoření vlastního interface s nějakou hardwerovou akcelerací, aby se o dekódování pohybu myši nemusel starat procesor. Každý ušetřený takt je užitečný. Nejzajímavější varianta pochází od firmy Kempston, od stejné firmy jako známé a velmi používané zapojení joysticku na port 31.
K původnímu Kempston Mouse interface se připojuje taky myš s TTL rozhraním, jako jsou Amiga/Atari myši. Interface dekóduje směr pohybu v osách X/Y a podle toho inkrementuje, nebo dekrementuje osmibitové čítače. Hodnotu z čítačů lze kdykoli přečíst na dvou portech. Na třetím portu se čte stav tlačítek. To nestojí o mnoho víc procesorového času, než čtení joysticku, nebo klávesnice. Takový myší interface je z pohledu softwaru tak nenáročný, jak je jen technicky možné.
Kempston myš (zkráceně KMouse) je na ZX Spectrum jediný interface, který dovoluje myš používat i v akčních hrách. Proto se stal velmi oblíbeným mimo jiné v Rusku, postupem času s klesající cenou hardwaru potřebného k postavení interface se KMouse stala defakto standardem. Je podporována v mnoha emulátorech a jsou jí vybaveny i některé nové klony ZX Spectra.
Jednodušší a starší varianty interface pracovaly s TTL myší a mohly být zapojené např. takto. Modernější varianty pracují s PS/2 myší, příp. mohou pracovat i s USB myší (staré USB myši uměly i PS/2 protokol). Ve Velesoftově KMouse Turbo se o konverzi stará MCU PIC16F84A podobně jako v mnoha PS/2 - Amiga myš konvertorech.
Originální Kempston Mouse podporuje pouze dvě tlačítka. Poslední Velesoftova varianta, kterou považuji za nejlepší, podporuje tlačítka tři a dokonce i scrollovací kolečko je-li připojena kompatibilní PS/2 myš. V emulátorech ale podpora kolečka a často i třetího tlačítka chybí. Software by s tím měl počítat.
Výsledkem činnosti KMouse interface jsou tedy tři čísla na třech portech. Dvě čísla udávají polohu myši v rozsahu od 0 do 255, třetí port slouží ke čtení tlačítek, případně kolečka, umí-li to interface. Vrácené souřadnice lze buď přímo použít a zkonvertovat na souřadnice na obrazovce (z 255 na max 191 v ose y). Nebo lze spočítat rozdíl od minulé hodnoty a o tolik posunout kurzor.
- + skutečná myš
- + velmi nenáročná na software, použitelná i v akčních hrách
- + velmi rozšířená a dobře podporovaná mnoha programy
- + často emulovaná v emulátorech
- + existuje několik KMouse interface i k reálným počítačům
- + možnost používat optické PS/2 myši s kolečkem
- + pokud nový klon ZX Spectra podporuje myš, bývá to právě KMouse
- − vyžaduje komplikovanější interface
- − obsazuje hned tři 16 bitové porty
Detailní popis Velesoftovy konstrukce KMouse Turbo a Velesoftů článek o originální Kempston myši.
Můj článek věnovaný převážně KMouse.
AMX Mouse
A nakonec nelze opominout AMX Mouse. S touto myší jsem se osobně také nikdy nesetkal. V 90. letech jsme o ní věděli jen díky programu Artist, kde byla na výběr (podporována prý byla i v konkurenčním Art Studiu), jako jedna z možností ovládání. I tato myš vyžaduje speciální interface, málo obvyklý, použitelný jen pro tuto myš, který ještě ke všemu pracuje na stejných portech jako 8255 a tedy není společně s ním použitelný.
Podle popisu je tak trochu vylepšenou AMouse. Změny na clonkách zpracovává procesor Z80, ale nemusí stav myši hlídat v cyklu, protože interface vyvolává přerušení když změna nastane. V konečném důsledku to může být podobně náročné jako AMouse, pokud uživatel myší pohybuje, nebo možná nenáročné, když je myš v klidu, nebo je s ní pohybováno jen pomalu. Nejsem si jistý, nezkoušel jsem.
V dnešní době (rok 2021), kdy KMouse podporuje většina emulátorů a leckterý nový hardware vč. ZX Spectrum Next už bych AMX Mouse považoval jen za zajímavou technickou kuriozitu.
Zajímavé detaily o AMX myši lze najít i u Velesofta.
Další myši pro ZX Spectrum zmiňuje Jarek (GEOS mouse a sériovou myš na skutečném UARTu s čipem 8250/8251). Myš lze určitě připojit i přes SIF, zkoušel jsem to, jen se to kvůli malé rozšířenosti SIFu nevyužívá.
Amiga Mouse zvaná AMouse
Amiga myš (přepínatelná Atari myš), zkráceně AMouse není zaměnitelná se sériovou i když její konektor vypadá stejně. U počítačů ZX Spectrum, ale i Amiga a Atari se připojuje do joystickového portu a komunikuje s nimi na úrovních TTL logiky.
Počítači myš předává přímo stav clonek přes tvarovač se Schmittovými klopnými obvody, např. 74HC14. Tvarovač s hysterezí v myši je důležitý, protože fototranzistory mohou být zastíněné jen částečně a jejich zastínění se může měnit velmi pomalu. Přímo připojený výstup z fototranzistoru na TTL vstup by při pomalém průchodu zakázanou oblastí (přibližně mezi napětím 1V až 2.5V) mohl vést k zákmitům na výstupu hradla a to by vedlo k chybnému určení rychlosti a směru pohybu myši počítačem.
Připojit TTL myš do RS232 je špatný nápad, RS232 pracuje s napětím až ±15V a to by mohlo TTL logiku poškodit. Pokud si nejste jistí, jakou myš máte, podívejte se dovnitř, podívejte se jaký čip je uvnitř myši a kolika vodiči je připojená k počítači. RS232 myši v sobě určitě nebudou mít pouze Schmittovy klopné obvody a budou připojeny méně vodiči, nejčastěji jen čtyřmi.
Typické připojení AMouse k ZX Spectru pomocí joystickového interface.
Na pravém snímku je optická Amiga myš, která vznikla úpravou původně PS/2 myši, krátká zmínka je i v tomto srovnání. Úprava byla možná jen díky optickému snímači, který kromě PS/2 umí poskytovat i kvadraturní signály, stejné jako výstupy z kuličkové Amiga myši. Jiiirovo rozhraní UPI je s UR-4 plně kompatibilní a opět jde jen o paralelní port s konektorem pro Kempston joystick.
AMouse používá 4 vodiče pro přenos pulzů ze čtyř čidel, dva signály ze dvou fototranzistorů pro každou osu. Další jeden až tři vodiče používá pro přenos stavu tlačítek a dva vodiče pro napájení GND a +5V. Celkem myš potřebuje pro připojení 7 až 9 vodičů. Víc nemá smysl, protože se u ní, stejně jako u joysticku (Kempston, Amiga ...) používá devítipinový konektor DSUB (Canon).
Velikost mé staré červené kuličkové Amiga myši je docela běžná, nijak nevybočuje ani ve srovnání se "současnými", resp. vyráběnými o cca 10 až 20 let později. Na pravém obrázku je vidět obvod 74HC14N tvořící veškerou logiku myši. Konstrukce je tedy narozdíl od RS232 a pozdějších myší extrémně jednoduchá. Přesto bývaly i tyto myši velmi drahé a tehdy možná ještě o pár korun dražší kvůli barvě. Opravdu, i mnoho let potom bylo u PC běžné, že skoro všechny komponenty byly v barvě "slonovinová kost", tj. trochu zažloutle béžové plasty a výjimečně jiné (nejčastěji bílé, hnědé, černé).
Konstrukce Amiga myši
Na prvním obrázku je kromě jednoduché elektroniky jasně vidět i konektor s pouze osmi vodiči. Zapojené je totiž pouze levé a pravé tlačítko. Na připojení prostředního tlačítka už vodič nezbyl i kdyby to interface umožňoval.
Všimněte si přepínače na spodní straně myši, ale nenechte se zmást písmeny MS/PC, to se této myši netýká, plast je společný i pro RS232 variantu. Smysl mají písmena AM a AT, která značí počítače Amiga a Atari. K oběma se používala TTL myš, ale u Atari byly oproti Amize jinak zpřeházené signály z clonek. Pro ZX Spectrum je správná poloha přepínače AM
Konstrukce mechaniky je opět velmi jednoduchá, dva válečky s clonkami a přítlačné kolečko s pružinkou. Válečky i kolečko bylo občas nutné očistit, protože se na ně přes kuličku lepí prach z podložky. Ten vytvoří nejprve tenkou vrstvu, později tlustší a hrbolatější až se nakonec začnou válečky, nebo kulička zadrhávat, častý problém všech kuličkových myší.
Na snímku je vidět i trochu odřené místo, kde se kulička válečků dotýká, to je běžný důsledek používání.
A ještě příklad jiné varianty myši. Rozlišení má velmi podobné, viz srovnání myší zde, opět je vybavena přepínačem. Měly ho skoro všechny myši, snad jen s výjimkou těch původních, co se dodávaly přímo k počítačům Amiga a Atari. Stejný druh myší lze použít i s počítači Sam Coupe (viz originál SAMCo interface) a od roku 2020 i s PMD 85.
Integrovaný obvod MC14584BC uvnitř bílé myši je opět šestice invertorů se Schmittovými klopnými obvody na vstupu. Zapojením se od červené myši téměř neliší.
Zapojení konektoru AMouse
Pro srovnání jsem přidal i zapojení Kempston joysticku. Tlačítko 2 se u joysticku využívá výjimečně, pokud ano, tak by vždy měla existovat i alternativní klávesa, která dělá totéž. Dvě tlačítka bývají na joysticku často, ale málokterý joystick je má zapojená samostatně.
bit | vývod | Kempston joystick | Amiga Myš |
---|---|---|---|
0 | 4 | vpravo | osa X2 (XB) |
1 | 3 | vlevo | osa Y1 (YA) |
2 | 2 | dolů | osa X1 (XA) |
3 | 1 | nahoru | osa Y2 (YB) |
4 | 6 | tlačítko 1 | tlačítko 1 (levé) |
5 | 9 | tlačítko 2 (výjimečně) | tlačítko 2 (pravé) |
6 | 5 | tlačítko 3 (prostřední) | |
7 | nezapojeno | nezapojeno | |
7 | +5V | +5V | |
8 | GND | GND |
V případě UR-4 je pro 2. a 3. tlačítko nutné doplnit invertory po vzoru ostatních signálů joysticku (jako směry a fire). V případě jiných interface možná ne, Jiiirův UPI i moje redukce k Didaktiku Gama 192k mají zapojená všechna 3 tlačítka.
Nepřipojený bit 7 znamená, že interface na tomto bitu vždy vrací 0. Podle toho lze při čtení hodnoty z portu 31 softwarově odhadnout přítomnost Kempston joysticku, nebo kompatibilního rozhraní. Resp. když se na bitu 7 vyskytne 1, můžeme s velkou pravděpodobností říct, že Kempston joystick interface není k počítači připojený a čtení joysticku, nebo myši vypnout.
Na snímku konektoru je černou čárkou označený vývod číslo 1. Následující nákres ukazuje číslování všech vývodů kabelového konektoru.
- HwB - popis konektoru pro připojení myši a joysticku k Amize
- HwB - popis konektoru podobné myši používané u Atari
Stavový diagram pulzů na výstupu myši a jejich zpracování
Jak jsem psal výše, AMouse vrací tvarovaný signál z fototranzistorů, ty jsou zakrývány clonkami tak, aby při jednom směru pohybu přicházel pulz z jednoho tranzistoru dříve než z druhého. Ideálně přesně o 90° při konstantní rychlosti pohybu, ale v praxi to přesné není, protože fototranzistor může být vůči štěrbině v clonce mírně posunutý, nebo nakloněný. Do určité míry to nevadí. Počítač detekuje změny stavů, ne trvání jednotlivých pulzů.
K zobrazení stavů clonek připojené myši můžete použít můj program portscope. Signály zobrazené na skutečném osciloskopu ukazují následující snímky obrazovky. Pořadí kanálů je shodné s pořadím bitů, žlutý kanál 1 je bit 0 atd...
Doba trvání pulzů záleží na rychlosti pohybu myši. Z kombinace pulzů, jak jdou po sobě, lze určit směr pohybu myši. Každá změna stavu na dvojici signálů v jedné ose znamená jeden krok pohybu kurzoru odpovídajícím směrem. Všimněte si, že se nikdy nemění oba signály jedné osy, v podstatě to je nejjednodušší forma Grayova kódu používaná u nejrůznějších rotačních enkodérů.
Nejkratší pulzy s optickou myší, která má rozlišení 400cpi, jsem zaznamenal dlouhé zhruba okolo 250μs, resp. okolo 500μs celý jeden cyklus všech čtyř stavů. To znamená, že by počítač měl snímat port rychlostí alespoň dvojnásobnou (s frekvencí přibližně 4kHz), aby spolehlivě nedocházelo ke ztrátě informace při rychlých pohybech. Rychlejší snímání neuškodí.
Dekódování směru pohybu je docela jednoduché. Například když se stav bitů z kombinace 00 změní na 01 můžeme jednoznačně určit, že došlo k posunu myši o jeden krok jedním směrem, když se ale změní z 00 na 10, tak došlo k pohybu směrem opačným. Ovladač myši k dekódování používá dekódovací tabulku pro každou z možných kombinací předchozího a nového stavu. Vezme dva bity předchozího stavu (např. na pozici bitů 0 a 2), přidá je pomocí OR k dvěma bitům nového stavu (např. na pozici bitů 1 a 3), tím vznikne 4 bitové číslo 0 až 15, číslo přičte k adrese tabulky a z ní přečte hodnotu 0, +1, nebo -1 (to jsou ty 255), kterou může rovnou přičíst k aktuálním souřadnicím kurzoru. Totéž provede pro druhou osu a to celé provádí většinu času z 1/50s, pak překreslí kurzor na novou pozici. To celé opakuje dokud uživatel na nějakém místě obrazovky nestiskne tlačítko myši.
Díky tomu může kurzor na obrazovce počítače přesně kopírovat pohyb myši a ten pohyb je pro uživatele přirozený.
Kempston Mouse
TODO: přesunout tuto část textu do článku o KMouse a tento článek nechat výhradně pro AMouse.
Kempston Mouse interface vytvořila v roce 1986 stejná firma, jako interface pro připojení joysticků na port 31 jehož vylepšenou variantou je i UR-4. Jako polohovací zařízení se k interface připojuje zas TTL myš podobná té k Amize (zpřeházené vývody, viz schéma překreslené Velesoftem), ale navíc je v interface logika, která signály z clonek převádí na byte, jehož hodnota se mění v rozsahu <0, 255> podle směru a rychlosti pohybu myši. Logika interface prakticky dělá totéž, co by jinak musel provádět procesor. Uživateli pak stačí přečíst ze dvou portů hodnoty pro osy X a Y jednou za čas, třeba jednou za 1/50s. Nároky na čas procesoru jsou tak minimální.
S touto myší jsem se poprvé setkal v emulátoru X128, později jsem ji objevil na ruských webových stránkách. V Rusku byla zjevně oblíbená pro svou použitelnost i ve hrách, např. v předělávce WarCraft 1 pro ZX Spectrum "Black Raven" (rusky Чёрный Ворон) a mnoha dalších, dokonce není problém ji používat v Basicu, což ani s A-Mouse, ani s RS232 myší přímo možné není.
Kempston Mouse používá šestnáctibitové adresy portů (detailněji v tomto článku) a to na portech uvedených v tabulce. Původní interface pracoval se dvěma tlačítky, ruské verze i se třemi, v některých případech bylo levé a pravé tlačítko přehozené. Velesoftův interface podporuje tři tlačítka s možností levé a pravé přehodit, navíc na horních 4 bitech vrací hodnotu v rozsahu <0, 15> měnící se podle pohybu kolečkem myši. Princip čtení kolečka je stejný jako princip čtení polohy myši.
porty Kempston mouse
Hex | Dec | označení | poznámka |
---|---|---|---|
#FADF | 64223 | tlačítka | B0=pravé, B1=levé, B2=střední (0=stisknuto, 1=nestisknuto) |
#FBDF | 64479 | souřadnice X | souřadnice v intervalu <0, 255> |
#FFDF | 65503 | souřadnice Y | souřadnice v intervalu <0, 255> |
#FEDF | 65247 | souřadnice Z | kolečko myši implementované Velesoftem (později, přesunuto na port tlačítek kvůli kompatibilitě, verze 2008 zde vrací obsah portu #7FFD, na orig. ZXS 128k nečitelný) |
Kempston Mouse vrací hodnotu od 0 do 255 i pro Y-ovou souřadnici, je tedy potřeba provést jednoduchou korekci na výšku obrazovky 192px. Hodnoty je možné chápat jako absolutní souřadnici, což je triviální, ale v některých ohledech problematické, nebo porovnáním s minulou hodnotou získat posun určitým směrem a ten pak použít.
- článek o Kempston Mouse na Wikipedii
- článek o originální Kempston mouse od Velesofta
- podrobnosti o KMouse Turbo 2008 na webu Velesofta
- můj článek o KMouse
Program zobrazující šipku ovládanou myší
K využití myši je dobré mít i program, který to vše usnadní. Postupem času vzniklo několik verzí různých ovladačů. Program tady uvedený je založený na původním ovladači, který jsem kdysi dávno získal vytištěný na papíru. Postupem času byl různě přizpůsobován. Pro potřeby článku jsem ho zjednodušil na minimum, upravil tak, aby byl dobře čitelný a důkladně okomentoval v angličtině, protože to je dnešní standard. Snažil jsem se, aby komentáře byly stručné a věcně správné. Doufám, že se mi to i podařilo.
Ovladač pracuje výhradně s klávesnicí a AMouse, přičemž AMouse lze nastavením MOUSE_HID na nulu vypnout a šipku ovládat pouze klávesnicí. Ovladač neobsahuje zpracování horkých kláves, emulaci kolečka, neřeší čtení josticku a případnou kolizi s myší. To proto, aby v něm nebylo nic navíc, co by mohlo komplikovat pochopení práce s AMouse a komplikovat přenesení částí kódu do jiných programů. Existuje komplikovanější ovladač s podporou KMouse, který to vše umí.
Program se skládá ze dvou základních částí. Části, která čte porty, mění souřadnice myšího kurzoru a vykresluje šipku na obrazovku a z části, která je v podstatě nejjednodušším možným programem, který ovladač využívá. Ta část smaže obrazovku, vykreslí ikonu (jeden červený čtverec), nadefinuje ovládací klávesy a souřadnice ikon a potom zavolá myší ovladač s šipkou. Ovladač běží tak dlouho, dokud uživatel neklikne na ikonu a pak provede v tabulce nadefinovanou akci, v případě této ukázky EXIT, tj. vrátí se to BASICu.
Zde je možné zobrazit ukázkový program se zvýrazněním syntaxe. Zde je původní, méně přehledná a špatně komentovaná verze z doby, než jsem ji nahradil tou současnou.
;============================================================================== ; simplified AMouse + keyboard only driver ;============================================================================== ; simplest possible demo with one icon (red square) for exit cpu z80undoc org 32768 START push iy ; some registers are needed for Sinclair BASIC exx push hl exx ld a,56 ; PAPER 7, INK 7 call CLS ; clear screen ld a,2*8 ; red PAPER, black ink ld (22528),a ; make red square 16x16px in top left corner ld (22528+1),a ; = simplest icon "exit" ld (22528+32),a ld (22528+33),a ld a,6 ; BORDER 6 out (254),a ld a,1 ; enable AMouse ld (MOUSE_HID),a ld hl,ICONS ; set address of icon table ld (MOUSE_ICONS),hl ; should contain at leas one icon ld hl,KEYTAB ; set address of table, where are defined control keys ld (MOUSE_KEYTAB),hl jp CALLMOUSE ; call mouse driver EXIT exx ; return to Sinclair BASIC pop hl exx pop iy ret ;-------------------------------------------------------------------------------------------------- ICONS db 0,16,0,16 ; x1,x2,y1,y2 - area where icon is dw EXIT ; address where to jump if clicked on icon db 255 ; end of table ; Every item in these tables is composed from 5 bytes. First two are port address. ; For example 254+256*127 = 32766 which is io port for keys B, N, M, symbol shift and space ; Third byte is mask. Last two bytes is address determinig what code to call if key will be ; pressed. KEYTAB db 254, 223, 00000010b ; LEFT (O) dw MOUSE_KLEFT ; where call if key pressed db 254, 223, 00000001b ; RIGHT (P) dw MOUSE_KRIGHT db 254, 251, 00000001b ; UP (Q) dw MOUSE_KUP db 254, 253, 00000001b ; DOWN (A) dw MOUSE_KDOWN db 254, 127, 00000100b ; FIRE (M) dw MOUSE_KFIRE1 db 255 ; end of table ; This table can be defined for Kempson joystick too, but it doesn't make sense if ; AMouse is connected to the same port. Disable AMouse, redefine table and it will work. ; ; In table could be more keys with same function. For example OPQAM and Sinclair joystick 67890. ;================================================================================================== MOUSE_CHEIGHT equ 13 ; height of pointer - all pointers have same height ;-------------------------------------------------------------------------------------------------- ; start of main loop MOUSE ld hl,128+96*256 ; cursor coordinates X in L, Y in H ld a,h ; copy cordinates ld c,l ; X -> C, Y -> A call 8880 ; from coordinates compute address in VRAM in HL ld (MOUSE_DRAW+1),hl ; set pattern for drawing ld (MOUSE_CLEAR+1),hl ; set pattern for erasing ld (MOUSE_DRAW_2+1),a ; set, how many rotations subtract from 8 call MOUSE_DRAW ; draw cursor on screen ;------------------------------------------------------------------------------ ; change coordinates of mouse cursor by keyboard MOUSE_KEYBOARD ld ix,MOUSE_DUMMY_TAB ; get address of table with defined keys ld hl,(MOUSE_XY) ; get cursor coordinates in HL xor a ld (MOUSE_RKEYS_JR+1),a ; modify address in relative jump to MOUSE_RKEYS ld d,a ; set D = 0, default a state of buttons = nothing pressed (yet) ld e,a ; set E = 0, it has no use in this driver call MOUSE_READKEYS ; process whole key table ld (MOUSE_XY),hl ; store new coordinates ld a,d ld (MOUSE_BUTTONS),a ; store new buttons status ; keyboard processed - continue with real mouse if enabled ; ; MOUSE_HID ; 0 = only keyboard ; 1 = keyboard + AMouse MOUSE_HIDLD ld a,0 ; is AMouse enabled? or a jp nz,MOUSE_AMOUSE ; NZ = jump to AMouse driver MOUSE_COMMON ei ; enable interrupt (just for any case) halt ; and wait for interrupt (1/50s when picture is starting on TV screen) call MOUSE_CLEAR ; remove old cursor from screen MOUSE_FB_STATE ld a,0 ; get buttons status (FIRE BUTTONS, or HOTKEYS) or a ; 0 = check for zero (nothing pressed) ret nz ; NZ = something was pressed -> return jr MOUSE ; repeat whole loop ;-------------------------------------------------------------------------------------------------- ; these subroutines are called by table of control keys MOUSE_KFIRE1 set 0,d ; fire 1 was pressed - set bit 0 ret MOUSE_KLEFT ld a,l ; get X coordinate in A sub c ; subtract step size ld l,a ; store new X coordinate back ret nc ; NC = no correction is needed ld l,0 ; left border was crossed, correct it ret MOUSE_KRIGHT ld a,l ; get X coordinate in A add a,c ; add step size ld l,a ; store new X coordinate back ret nc ; NC = no correction is needed ld l,254 ; right border was crossed, correct it ret MOUSE_KUP ld a,h ; get Y coordinate in A sub c ; subtract step size ld h,a ; store new Y coordinate back ret nc ; NC = korekce není potřeba ld h,0 ; top border was crossed, correct it ret MOUSE_KDOWN ld a,h ; get Y coordinate in A add a,c ; add step size ld h,a ; store new Y coordinate back cp 190 ; check if bottom border was crossed ret c ; C = no correction is needed ld h,190 ; bottom border was crossed, correct it ret ;-------------------------------------------------------------------------------------------------- ; MOUSE_READKEYS - universal code for processing table of ports and masks for keys or joystick ; need address of table in register IX ; doesn't affect registers HL & DE (HL contains coordinates, DE state of buttons and scroll wheel) MOUSE_READKEYS ld a,(ix+0) cp 255 ; 255 = end of table? ret z ; Z = end of table reached = return ld c,a ; read 16 bit address in register BC, will be port address ld b,(ix+1) in a,(c) ; read 16 bit io port bit 7,c ; try detect if port was keyboard or Kempston joystick ; for Kempston joystick should be bit 7 always 0 ; for keyboard should be bit 7 alwais 1 jr z,MOUSE_RKEYS_JOY ; Z = probably joystick cpl ; invert bits, for keyboard is pressed key = 0 MOUSE_RKEYS_JOY and (ix+2) ; now should be pressed key or joystick direction = 1, apply mask jr z,MOUSE_RKEYS_NXT ; Z = tested key not pressed ld c,(ix+3) ; address of code for tested key in BC ld b,(ix+4) ; this relative jump is switch for differen behavior for regular keys (directions, fire...) and hotkeys MOUSE_RKEYS_JR jr MOUSE_RKEYS ; relative address will be modified do MOUSE_RKEYS, or to MOUSE_RHKEYS ; regular keys for moving cursor etc. MOUSE_RKEYS ld (MOUSE_RKEYS_3+1),bc ; modify address in instruction CALL MOUSE_KSLD ld c,2 ; step size for cursor movement MOUSE_RKEYS_3 call MOUSE_RET ; call subroutine for pressed key MOUSE_RKEYS_NXT ld bc,5 ; 5 bytes per item in table add ix,bc ; compute address of next item in table jr MOUSE_READKEYS ; repeat MOUSE_RET ret ;------------------------------------------------------------------------------ ; change coordinates by AMouse ; ; will change these coordinates ; will change status of buttons on address MOUSE_BUTTONS if pressed MOUSE_AMOUSE ld bc,130*256 ; B = how many times read port every 1/50s (compromise), set C = 0 ld a,(MOUSE_X) ; copy coordinates in operands inside cycle ld (MOUSE_AM_X+1),a ld a,(MOUSE_Y) ld (MOUSE_AM_Y+1),a MOUSE_AM_LOOP push bc ; 11T store BC - here starts main loop for AMouse ld b,c ; 4T copy zero from C to B (zero will be returned every pass through loop from stack) in a,(31) ; 11T read AMouse (Kjoy) port ld de,MOUSE_AM_STAT ; 10T pointer to old status of mouse signals for X call MOUSE_AM_DIR ; 17T check which direction mouse moved MOUSE_AM_X ld a,0 ; 7T get X coordinate in A add a,(hl) ; 7T add value 0, +1 or -1 from table jr z,MOUSAKX ; 12/7T Z = left border reached or right border crossed, don't store new coordinate ld (MOUSE_AM_X+1),a ; 13T write new X coordinate MOUSAKX inc de ; 6T increment pointer to old status of mouse signals to Y in a,(31) ; 11T read AMouse (Kjoy) port rrca ; 4T rotate 1 bit right, to be able use same subroutine as for X call MOUSE_AM_DIR ; 17T check which direction mouse moved MOUSE_AM_Y ld a,0 ; 7T get Y coordinate in A add a,(hl) ; 7T add value 0, +1 or -1 from table jr z,MOUSAKY ; 12/7T Z = top border was reached, don't store new coordinate cp 190 ; 7T check if bottom border was crossed jr c,MOUSADO ; 12/7T C = mouse cursor is still above bottom border ld a,190 ; 7T make correction MOUSADO ld (MOUSE_AM_Y+1),a ; 13T write new Y coordinate MOUSAKY pop bc ; 10T restore BC djnz MOUSE_AM_LOOP ; 13/8T repeat B times ; total 11+4+11+10+17+75+7+7+7+13+6+11+4+17+75+7+7+7+7+12+13+10+13 = 351T most typical run (cca 10kHz) ld a,(MOUSE_AM_X+1) ; copy new coordinates from AMouse part to main "variable" ld (MOUSE_X),a ld a,(MOUSE_AM_Y+1) ld (MOUSE_Y),a in a,(31) ; last time read AMouse port rra ; move bits 4,5,6 for buttons to position of bits 0,1,2 rra rra rra and 00000001b ; leave only bit significant for button (can be up to three) ld b,a ; copy to register B ld a,(MOUSE_BUTTONS) ; read status of "fire" keys or b ; OR it with mouse buttons, ld (MOUSE_BUTTONS),a ; now can be used both at a same time jp MOUSE_COMMON ; this subroutine will combine old and new status of mouse signals and will return pointer in HL to value 0,+1,-1 MOUSE_AM_DIR and 00000101b ; 7T leave only bits for mouse signals ld c,a ; 4T store it in C ld a,(de) ; 7T read old state of mouse signals rlca ; 4T rotate left and 00001010b ; 7T and leave only these bits or c ; 4T combine with new state of mouse signals - now ve have number 0..15 ld (de),a ; 7T store result for future use ld c,a ; 4T copy it in C, B is already zero ld hl,MOUSE_AM_TAB ; 10T get pointer in "directions" table add hl,bc ; 11T add number 0..15 assembled from "new and old mouse signals" ret ; 10T ; total 7+4+7+4+7+4+7+4+10+11+10 = 75T MOUSE_AM_TAB db 0,255,1,0 ; table of values 0, +1, -1 for every possible db 1,0,0,255 ; combination of old and new mouse signals db 255,0,0,1 db 0,1,255,0 MOUSE_AM_STAT db 0 ; old status of mouse signals for axis X db 0 ; old status of mouse signals for axis Y ;-------------------------------------------------------------------------------------------------- ; cursor drawing - code heavily inspired by book "Assembler and ZX Spectrum II" from Proxima ;-------------------------------------------------------------------------------------------------- ; MOUSE_DRAW a MOUSE_CLEAR subroutines can be called any time without need set registers. ; MOUSE_DRAW will draw cursor on screen at same position as it was last time when was driver running. ; Buffer will be updated, so MOUSE_CLEAR can be called after that. MOUSE_DRAW ld hl,19472 ; pointer to the screen where mouse cursor should be MOUSE_CURLD ld ix,MOUSE_SPR_ARROW ; sprite address in IX (can be changed for another sprite) exx ld hl,MOUSE_BACKGRBUF ; buffer address in second HL, in buffer will be copied screen content exx ld b,MOUSE_CHEIGHT ; sprite height MOUSE_DRAW_1 push bc ; store height in stack push hl ; store screen pointer twice on stack push hl ld h,0 ; 0 in H, here will be rotated sprite/mask if needed ld l,(ix+0) ; read sprite in L ld d,h ; 0 in D ld e,(ix+MOUSE_CHEIGHT) ; read mask in E inc ix ; move pointer IX to next byte of graphics ld a,8 ; 8 in A (8 bits/rotations per byte) MOUSE_DRAW_2 sub 0 ; subtract number of rotations to the right ld b,a ; number of rotation to the left in B MOUSE_DRAW_3 add hl,hl ; HL *= 2 (rl HL) sla e ; DE *= 2 (rl DE) rl d djnz MOUSE_DRAW_3 ; repeat until B = 0 (up to 7 times) ex (sp),hl ; swap address of cursor on screen from stack to HL pop bc ; get rotated graphics of cursor into BC (was in HL originally) ld a,(hl) ; read original content of screen exx ; second set of registers ld (hl),a ; store original content of screen in buffer inc hl ; next byte in buffer exx ; primary set of registers ld a,d ; get left part of mask cpl ; invert it and (hl) ; remove pixels from background where mask had 0 or b ; add graphics of mouse cursor ld (hl),a ; store it back in screen inc l ld a,l and 00011111b ; was right border crossed? jr z,MOUSE_DRAW_4 ; Z = yes ld a,(hl) ; whole proccess repeat again for second byte exx ld (hl),a inc hl exx ld a,e cpl and (hl) ; remove pixels from background where mask had 0 or c ; add graphics of mouse cursor ld (hl),a MOUSE_DRAW_5 pop hl ; restore address of left byte in screen from stack call DOWNHL ; compute address one pixel down pop bc ; restore counter djnz MOUSE_DRAW_1 ; repeat for whole height of mouse cursor ret MOUSE_DRAW_4 exx inc hl ; only increment pointer to the buffer exx jr MOUSE_DRAW_5 ;-------------------------------------------------------------------------------------------------- ; clear cursor and replace it with original content of screen before mouse cursor was drawn ;-------------------------------------------------------------------------------------------------- MOUSE_CLEAR ld hl,16384 ; pointer to the screen where is placed mouse cursor ld b,MOUSE_CHEIGHT ; height of mouse cursor in pixelx ld de,MOUSE_BACKGRBUF ; address of buffer with original content MOUSE_CLEAR_1 ld a,(de) ; get byte from buffer ld (hl),a ; write it in screen inc de ; move DE to next byte in buffer push hl ; store HL inc l ld a,l and 00011111b ; was right border crossed? jr z,MOUSE_CLEAR_2 ; Z = yes, jump over processing second byte ld a,(de) ; get byte from buffer ld (hl),a ; write it in screen MOUSE_CLEAR_2 inc de ; move DE to next byte in buffer pop hl ; restore HL to address of left byte call DOWNHL ; compute address one pixel down djnz MOUSE_CLEAR_1 ; repeat for whole height of mouse cursor ret ;================================================================================================== ; graphics of some very basic cursors ;================================================================================================== MOUSE_SPR_ARROW db 00000000b ; classic arrow cursor db 01000000b db 01100000b db 01110000b db 01111000b db 01111100b db 01111110b db 01111000b db 01001000b db 00001000b db 00000100b db 00000100b db 00000000b db 11100000b ; mask db 11110000b db 11111000b db 11111100b db 11111110b db 11111111b db 11111111b db 11111111b db 11111100b db 11111110b db 00011110b db 00011110b db 00001110b MOUSE_BACKGRBUF ds MOUSE_CHEIGHT*2 ; buffer for part of screen where cursor was drawn ;================================================================================================== ; wait until any key is pressed include mouse buttons if selected ; PAUSE 0 because command in Sinclair BASIC with similar behaviour PAUSE0 call MOUSE_TESTFIRE jr z,PAUSE0 ; Z = no key or button was pressed, repeat ret ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ; wait while any key is pressed include mouse buttons if selected PAUSENK call MOUSE_TESTFIRE jr nz,PAUSENK ; NZ = some key or button is pressed, repeat ret ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ; common part for keys/buttons testing - returns Z if nothing pressed MOUSE_TESTFIRE xor a ; set port upper byte of address to zero in a,(254) ; read all keyboard ports at once cpl ; invert bits and 11111b ; leave only bits significant for keys ret nz ; NZ = a key was pressed, return, otherwise we will check mouse buttons ld a,(MOUSE_HID) ; is mouse control enabled? or a ; check for zero ret z ; Z = only keyboard is enabled, but fire is not pressed, return jr MOUSE_TSTBUTAM ; NZ = AMouse enabled, jump to test AMouse buttons MOUSE_TSTBUTAM in a,(31) ; AMouse left button, or Kempston Joystick fire button and 00010000b ; only bit for buttons (can be up to three buttons) ret ;================================================================================================== ; CALLMOUSE is the main entry point for program using this driver ;================================================================================================== ; See example how to use it. ; Basically call this code and it will jump to address defined in table for clicked icon or pressed hotkey. CALLMOUSE call MOUSE ; call main loop, it will draw mouse cursor ; until fire button will be pressed MOUSE_TSTXY ld de,(MOUSE_XY) ; read coordinates where user clicked in DE (D = X, E = Y) ld bc,6 ; size of item in BC (4 bytes coordinates, 2 bytes address) MOUSE_TSTXY_0 ld ix,MOUSE_DUMMY_TAB ; table address in IX jr MOUSE_TSTXY_FRS ; jump over first add MOUSE_TSTXY_NXT add ix,bc ; add size of intem BC and pointer to table IX MOUSE_TSTXY_FRS ld a,(ix+0) ; read coordinate X1 cp 255 ; is it end of table (255)? jr z,CALLMOUSE ; Z = end of table, user did not clicked on icon, but somewhere else cp e ; compare coordinates of cursor with coordinates from table jr nc,MOUSE_TSTXY_NXT ; NC = cursor is outside icon ld a,(ix+1) cp e jr c,MOUSE_TSTXY_NXT ; C = cursor is outside icon ld a,(ix+2) cp d jr nc,MOUSE_TSTXY_NXT ; NC = cursor is outside icon ld a,(ix+3) cp d jr c,MOUSE_TSTXY_NXT ; C = cursor is outside icon ld h,(ix+5) ; get address for this icon in HL ld l,(ix+4) jp (hl) ; and jump on that address ;================================================================================================== ; important addresses for this driver ;================================================================================================== ; compiler needs these values here, at end of code MOUSE_BUTTONS equ MOUSE_FB_STATE+1 ; button status (of not zero, button or key was pressed) MOUSE_X equ MOUSE+1 ; last known coordinates MOUSE_Y equ MOUSE+2 MOUSE_XY equ MOUSE+1 MOUSE_HID equ MOUSE_HIDLD+1 ; 0 = keyboard only, 1 = AMouse enabled MOUSE_KEYSTEP equ MOUSE_KSLD+1 ; KEYSTEP, step size for cursor movement by keyboard MOUSE_ICONS equ MOUSE_TSTXY_0+2 ; address where set pointer to icon table MOUSE_KEYTAB equ MOUSE_KEYBOARD+2 ; address where set pointer to table of control keys MOUSE_DUMMY_TAB equ 15360 ; it points in ROM, where should be 255 = end of table ; MOUSE_DUMMY_TAB should be always replaced by real address ;================================================================================================== ; compute address on screen one pixel down under current address ; This is usualy part of program which is using this driver DOWNHL inc h ld a,h and 7 ret nz ld a,l add a,32 ld l,a ld a,h jr c,DOWNHL2 sub 8 ld h,a DOWNHL2 cp 88 ret c ld h,0 ; if bottom margin was reached draw sprite in read only ROM ret ;-------------------------------------------------------------------------------------------------- ; clear screen - short and slow CLS ld (CLS_2+1),a ld hl,16384 ld de,16385 ld bc,6144 ld (hl),0 ldir ; fill pixels with zeroes ld bc,767 CLS_2 ld a,56 ; colors - 0*128 + 0*64 + 8*7 + 0 = FLASH 0, BRIGHT 0, PAPER 7, INK 0 ld (hl),a ldir ; fill color attributes ret ;================================================================================================== ; Chips 8255 (clones of Intel 8255) are often used for paralell interface compatible with ; Kempston joystick. Normally after reset it have all 3 ports set as input, but sometimes it ; need to be set again. You can do it by this code. SET8255INPUT ld a,155 ; all ports as input (default state after reset) out (127),a ret ; Standard decimal addresses are ; ; 31 - io port ; 63 - io port ; 95 - io port ; 127 - control port ; ;==================================================================================================
Program by mělo být možné zkompilovat většinou kompilerů pro PC. Já jsem ho kompiloval pomocí kompileru AS a testoval na reálném ZX Spectrum +2 s AMouse k čemuž mi opět pomohl program sercp.
Kompletnější ovladač s podporou KMouse a dalších vychytávek je ke stažení v článku o KMouse. V reálném použití taky nebývá dobrý nápad nějaký ovladač použít bez možnosti konfigurace uživatelem. Přítomnost AMouse se nedá spolehlivě rozpoznat, pouze s nějakou mírou nejistoty odhadnout. Na přítomnost AMouse lze usuzovat z bitu 7, který je roven 0 a z toho, že směry joysticku vlevo a vpravo, nebo nahoru a dolu, mohou být sepnuté současně, což s joystickem nejde. Ale pořád to neznamená, že je na portu přítomna myš. Bit 7 může být 0 protože je k počítači připojen úplně jiný interface a protilehlé směry mohou být aktivní současně protože místo joysticku uživatel připojil tlačítka, nebo taky úplně z jiného důvodu. Proto by každý program měl mít volbu ovládání, kde si uživatel sám zvolí, co chce používat.
Download
- amouse_simplified_driver.tar.bz2 - okomentovaný a zjednodušený ovladač pouze pro AMouse
- mouse_driver_old_and_deprecated.tar.bz2 - stará verze ovladače se spoustou hloupostí jen pro účely archivace
Související odkazy
- HwB - popis konektoru pro připojení myši a joysticku k Amize
- HwB - popis konektoru podobné myši používané u Atari
- článek o AMX Mouse na Wikipedii
- článek o Kempston Mouse na Wikipedii
- článek o originální AMX Mouse na Velesoftově webu
- článek o originální Kempston Mouse na Velesoftově webu
- podrobnosti o KMouse Turbo 2006 na Velesoftově webu
- podrobnosti o KMouse Turbo 2008 na Velesoftově webu
- můj článek o KMouse - článek je do značné míry pokračováním tohoto
- použitý kompiler AS - protože se špatně vyhledává
Historie změn článku
- 2004-02-28 - celý článek přepracován, výrazně rozšířen úvod, opraveny chyby, doplněn datasheet 74HC14 a obrázek myši zevnitř.
- 2005-04-11 - opraveny přehozené bity 0 a 1 (v tabulce i diagramu), upozornil Velesoft
- 2005-04-11 - doplněny odkazy na HWBook s popisem konektorů, vše znovu pečlivě zkontrolováno podle reálného fungujícího hardwaru
- 2015-12-23 - revidováno, promazán balast a nesmysly z textu, doplněny obrázky, opraven pinout (poštouchl nalezenou chybou z00m).
- 2021-06-12 - opět revidováno, přepsán historický úvod, opraven a doplněn text o AMouse