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














