Myši a ZX Spectrum

Ú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ě všelijaké 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, což byly všelijaké 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ň trochu 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. Jednou z možností 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 nemělo standardně sériový port, kromě modelů ZX Spectrum 128kB, a šedivých ZX Spectrum +2, +2A, +3, které však měly naprosto nestandardní konektory, navíc nevhodně umístěné, protože je zakrývalo kdejaké zařízení připojené k systémové sběrnici (např. Betadisk). Tato, v té době rozšířenější, implementace sériového portu používá obvod AY-3-8912 jako IO port. Řízení signálů musel provádět software a 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ů. Takže sériová myš existuje, ale je velmi obtížně připojitelná (má-li být zachována kompatibilita) 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í chyběly převodníky z TTL <-> RS232 a napájecí zdroj dodávající napětí +12V a -12V. Dnes dostupný např. MAX232 neexistoval.

Další volbou byl port paralelní, nejčastěji 8255 v UR-4 a Didakticích. Zapojení myši do UR-4 je extrémně jednoduché, vlastně není potřeba provádět vůbec žádnou úpravu, pokud se spokojíte jen s jedním tlačítkem. Bohužel velmi zásadní nevýhodou 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í, ale je to zcela nepouž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. Této myši se říkalo "Amiga Mouse" (zkráceně jen A-Mouse) podle typu použité myši, vyráběné původně pro Amigu a Atari.

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". Bohužel ji znám jen z doslechu, ale vím, že byla použitelná místo Kempston joysticku. 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. Ale velmi jednoduché bylo využití v programech. Interface myši emuloval Kempston joystick a řídil čas sepnutí směrů pomocí PWM takže bylo možné v několika málo krocích měnit i rychlost kurzoru v závislosti na rychlosti pohybu myší. Díky tomu 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ě podobně jako skutečná myš. Tato verze se v mém okolí nevyskytovala vůbec. Článek o této myši zde.

Poslední variantou je vytvoření vlastního interface s alespoň minimální hardwareovou akcelerací, aby se o myš nemusel starat procesor. Každý ušetřený takt je užitečný. Nejzajímavější varianta pochází od firmy Kempston, stejně jako známé zapojení joysticku na port 31 a připojuje s k ní taky Amiga myš s TTL rozhraním. Výsledkem činnosti nepříliš složitého a vcelku levného rozhraní jsou tři čísla na třech portech. Dvě čísla udávají polohu myši v rozsahu od 0 do 255 včetně a bity ve třetím bytu určují stisknutá tlačítka. Je sice nutné provést jednoduchou softwarovou korekci pro výšku obrazovky 192px, ale to je zanedbatelné vzhledem k ostatním variantám myší. A jedná se o skutečnou myš, takže pohyb kurzoru zcela kopíruje pohyb myši včetně změn rychlosti pohybu. S touto variantou jsem se setkal až o mnoho let později, kdy jsem už měl k dispozici připojení k internetu a ZX Spectrum už tolik uživatelů nezajímalo (1995 - 1996).

Souhrn

Typ myširozhranívýhodynevýhodyostatní
Kempston Mousespeciální interface, schéma zde, nebo zde.Skoro vůbec nezatěžuje procesor. Stačí číst 3 čísla na 3 portech a to je vše.Obsazuje 3 porty, vrací nevhodně stav tlačítek (podle mého názoru).Původní interface firmy Kepston, vyskytuje se často u ruských počítačů Pentagon, Scorpion a zcela určitě v počítači Sprinter, emulována v X128.
Kempston Mouse
Proxima
speciální rozhraní od Proximy, prý s jednočipem PICNení třeba speciální software, pracuje v programech, které umí pracovat s Kempston joystickem.Je nutné speciální, relativně složité rozhraní.Není to skutečná myš. Pohyb kurzoru není zcela dokonalý. Spíše se jedná o joystick s možností zpomalení pohybu kurzoru.
Amiga Mouse
(Heptau?)
UR-4, nebo jiný interface Kempston joysticku se správně zapojeným napájením.MHB8255 je velmi rozšířený interface na území české a slovenské republiky. Máte-li UR-4, nic jiného nepotřebujete.Velmi hodně zatěžuje procesor, vše musí obsloužit program (zabere nejméně 1/2 přerušení). Dobře použitelné v užitkových programech se spoustou ikon a tlačítek, horší ve hrách.V ČR a SR velmi rozšířený typ myši, kvůli jednoduchosti připojení. Tuto myš jsem podporoval ve svých programech až do náhrady za KMouse od Velesofta, nyní jen volitelně.
Sériová Myš
(ing. Petr Simandl)
RS232, které je součástí Spectra 128 kBRelativně málo zatěžuje procesor, nutné pouze čtení několika bytů jednou za přerušení, ovšem ze sériového rozhraní.Rozumně použitelná jen u ZX Specter 128kB, u ostatních bývají kompatibilní sériové porty jen vyjímečně.Nutno upravit konektor RS232 na cannon 9pinů, úprava myši na konektor Spectra není vhodné. Originální konektor obtížně sehnatelný a nevhodně umístěný.

Amiga Mouse

Amiga myš není zaměnitelná se sériovou. Komunikuje na úrovních TTL a v podstatě počítači předává přímo stav clonek přes tvarovač se Schmittovými klopnými obvody 74HC14. Používá 4 vodiče pro přenos pulzů ze čtyř čidel, dva signály/clonky pro každou osu, další až tři vodiče pro přenos stavu tlačítek a dva pro napájení GND a +5V. tj. 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). Narozdíl od sériové myši, kde se napětí pulzů může pohybovat od -15V do -3V pro log. 1 a od +3V do +15V pro log. 0 a data se přenáší protokolem RS232, jsou u Amiga myši signály TTL, tj. log. 0 je 0V až cca 1V a log. 1 přibližně 2.5V až 5V.

foto foto

Velikost 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

foto foto foto

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

foto

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.

Na snímku je vidět i trochu odřené místo, kde se kulička válečků dotýká, běžný důsledek používání.

Stavový diagram pulzů na výstupu myši

stavovy diagram výstupu z Amiga myši

Délka pulzů záleží na rychlosti pohybu myši. Aby se kurzor myši mohl pohnout musí být dokončena celá sekvence pulzů od stavu 0, 0 do stavu 0, 0. Pořadí pulzů udává směr pohybu, resp. směr pohybu je možné zjistit z toho, který pulz přijde první. Pokud sekvence začíná jedním z pulzů a končí tímtéž, pohyb není detekován (odpovídá pohybu myši o stejnou vzdálenost tam a zpět) a kurzorem myši nebude pohnuto.

Zapojení konektoru A-Mouse

Pro srovnání jsem přidal i zapojení Kempston joysticku. Tlačítko 2 se u joystiku 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 joystiku často, ale málokterý joystik je má zapojená samostatně.

bitvývodKempston joystickAmiga Myš
04vpravoosa X2 (XB)
13vlevoosa Y1 (YA)
22dolůosa X1 (XA)
31nahoruosa Y2 (YB)
46tlačítko 1tlačítko 1 (levé)
59tlačítko 2 (výjimečně)tlačítko 2 (pravé)
65 tlačítko 3 (prostřední)
7 nezapojenonezapojeno
 7+5V+5V
 8GNDGND

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, např Jiiirův UPI má 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 joystiku, resp. kompatibilního rozhraní.

foto

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.

nakres

Kempston Mouse

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

HexDecoznačenípoznámka
#FADF64223tlačítkaB0=pravé, B1=levé, B2=střední (0=stisknuto, 1=nestisknuto)
#FBDF64479souřadnice Xsouřadnice v intervalu <0, 255>
#FFDF65503souřadnice Ysouřadnice v intervalu <0, 255>
#FEDF65247souřadnice Zkoleč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.

Program zobrazující šipku ovládanou myší

Šipku zobrazovanou následujícím programem lze ovládat buď klávesami (Sinclair joystick, OPQAM), Kempston joystickem, nebo Amiga myší. Program je napsán univerzálně, podle bitu 7 v log. 1 (což s připojenou UR-4/UPI nenastane) detekuje přítomnost interface pro Kempston joystick, nebo Amiga myš na portu 31 a podle současně nastavených bitů pro směry vlevo a vpravo, nebo nahoru a dolů dokáže rozlišit Amiga myš od joysticku. Případně lze obojí vypnout, kdyby to náhodou na nějaké hardwarové konfiguraci nefungovalo.

Program umožňující volat myš z Basicu (kvůli HL')

Nezapomeňte si upravit cesty ke vkládaným zdrojovým textům sipka.za a downhl.za.

;==============================================================================
;  TESTOVACÍ PROGRAM PRO ŠIPKU
;==============================================================================

          cpu       z80undoc
          org       60000

START     di
          push      ix
          exx
          push      hl                  ; HL' nutno zachovat kvůli Basicu
          exx

          ld        a,6
          out       (254),a

          call      MOUSE

          ld         a,2
          out       (254),a
END       exx
          pop       hl
          exx
          pop       ix
          ei
          ret

EXIT      ld        a,1
          out       (254),a
          jr        END

XYIKON    db        0,255,0,192         ; x1,x2,y1,y2 (celá obrazovka)
          dw        EXIT
          db        255

          include ../libs/sipka.za
          include ../libs/downhl.za

Vlastní ovladač myši

Program byl zkoušen v emulátoru FUSE a kompilován kompilerem AS, nicméně s drobnými úpravami konstant by měl být zkompilovatelný kdekoliv. Zdrojový text je mimochodem odsazován po 10 znacích, některé řádky jsou proto trochu rozházené.

;==============================================================================
;     KOMPLEXNÍ PROGRAM PRO ČTENÍ KLÁVESNICE, AMIGA MYŠI A K-MOUSE
;==============================================================================

; Stručný princip:
;
;	Vezmi původní souřadnice, spočítej adresu na obrazovce (MOUSE_XY).
;	Vykresli šipku na obrazovku, zároveň ulož co bylo pod ní.
;	Zpracuj vstup ze zvoleného HID a spočítej nové souřadnice.
;	Zapiš nové souřadnice.
;	Zapiš stav tlačítek HID (proměnná MOUSE_B)
;	Čekej na přerušení.
;	Smaž šipku a místo ní vykresli původní obsah obrazovky.
;	Opakuj celý proces dokud není stisknuto tlačítko fire.
;	Zjisti jestli a na jakou ikonu bylo kliknuto, jinak opakuj.
;	Skoč na obslužnou rutinu ikony (JP).


; Význam bitů proměnné MOUSE_B:
;
;	bit 0	=	klávesa 1, nebo levé tlačítko myši
;	bit 1	=	klávesa 2, nebo pravé tlačítko myši
;	bit 2	=	klávesa 3, nebo prostřední tlačítko myši
;
;	další tlačítka nejsou definována %00000xxx - horní bity jsou vždy 0
;
;	update (spíše jen úvaha do budoucna):
;	bit 3	=	kolečko myši nahoru?, resp. tlačítko 4
;	bit 4	=	kolečko myši dolu, resp. tlačítko 5
;	bit 5	=	tlačítko 6, resp. tlačítko pod kolečkem myši

MOUSE_X	equ	MOUSE+2		; poslední známé souřadnice šipky
MOUSE_Y	equ	MOUSE+1
MOUSE_XY	equ	MOUSE_Y		; 16ti bitové souřadnice
MOUSE_T	equ	MOUSE_S+1		; typ zařízení  0=KEYS, 1=AMOUSE, 2=KMOUSE
MOUSE_B	equ	MOUSEBUTT+1	; stav tlačítek
MOUSE_KS	equ	MOUSEKS		; KEYSTEP, velikost kroku při ovládání pomocí kláves


MOUSE	ld	hl,96+128*256	; souřadnice šipky X do L, Y do H
	push	hl		; náhrada za neexistující instrukci ld bc,hl
	pop	bc		; takže X je v C, Y v B
	ld	ix,MSIPKA		; do IX adresu spritu
	exx
	ld	hl,MSIPKA_B	; do HL' adresu bufferu na pozadi sipky
	exx
	ld	a,b		; vezmi Y-ovou souradnici (jaký význam má v A?)
	call	8881		; ze souřadnic v BC spočítej adresu ve VRAM do HL
	ld	(MOUSEC+1),hl	; ulož tuto adresu, bude užitečná při mazání šipky
	ld	(MOUSE2+1),a	; toto cislo budu odecitat, co znamena ????

; vykreslení šipky  - pochází z knihy Assembler a ZX Spectrum II, komentáře jsem přepsal

	ld	b,15		; sprite šipky je vysoký 15 pixelů (mimochodem široký je 1 byte)
MOUSE1	push	bc		; ulož kolik opakování - mikrořádků zbývá
	push	hl		; dvakrát ulož adresu šipky ve VRAM, na kterou se bude kreslit
	push	hl
	ld	h,0		; do H ulož 0, sem se bude rotovat sprite/maska, pokud to bude třeba
	ld	l,(ix+0)		; do L přečti byte spritu
	ld	d,h		; vynuluj D (to samé jako H)
	ld	e,(ix+15)		; do E přečti byte masky
	inc	ix		; posuň ukazatel na grafiku spritu
	ld	a,8		; rotovat můžu nejvýše 8x
MOUSE2	sub	0		; od počtu rotací odečtu počet rotací vlevo a získám počet rotací vpravo
	ld	b,a		; počet rotací vpravo si uložím do B
MOUSE3	add	hl,hl		; HL *= 2 (náhrada rr hl)
	ex	de,hl		; prohoď HL a DE (add de,de taky bohužel neexistuje)
	add	hl,hl		; HL *= 2 (náhrada rr de)
	ex	de,hl		; HL a DE prohoď zase zpátky
	djnz	MOUSE3		; jednobytový sprite a maska jsou uloženy v HL a DE posunuté jak je třeba

	ex	(sp),hl		; prohoď poslední hodnotu v zásobníku (adresa šipky ve VRAM) a obsahem HL
	pop	bc		; do BC tak ze zásobníku vyzvednu odrotovanou předlohu
	ld	a,(hl)		; do A načtu původní obsah obrazovky
	exx
	ld	(hl),a		; uložím na (HL') - adresa bufferu na původní pozadí (1. levý byte, budou dva)
	inc	hl		; posunu ukazatel do bufferu
	exx
	ld	a,d		; vezmu do a pravou část masky
	cpl			; invertuju ji (kdybych ji uložil už invertovanou, měl bych problém s rotací)
	and	(hl)		; a z pozadí vymažu ty pixely, kde měla maska 0
	or	b		; a do vykousnutého pozadí zaoruju předlohu
	ld	(hl),a		; a nakonec uložím do VRAM
;	call	RIGHTL		; spočítej adresu o byte vpravo
	inc	hl
	ld	a,(hl)		; celé kreslení provedu ještě jednou pro 2. byte více vpravo
	exx
	ld	(hl),a
	inc	hl
	exx
	ld	a,e
 	cpl
	and	(hl)
	or	c
	ld	(hl),a
	pop	hl		; obnov adresu levého bytu ve VRAM
	call	DOWNHL		; spočítej adresu o pixel níž
	pop	bc		; obnov počítadlo
	djnz	MOUSE1		; a opakuj, dokud nejsou vykresleny všechny mikrořádky šipky

; volba polohovacího zařízení 0=KEYS, 1=AMOUSE, 2=KMOUSE

MOUSE_S	ld	a,0
	or	a
	jp	z,MOUSEB	; A=0	; Buttons - klávesy
	dec	a
	jp	z,MOUSEA	; A=1	; Amiga mouse (myška z Amigy zapojená do UR-4)
	dec	a
	jp	z,MOUSEK	; A=2	; ruská Kempston mouse vracející přímé souřadnice
				; v ostatních případech čtu klávesy

;------------------------------------------------------------------------------
; ZMĚNA SOUŘADNIC [X,Y] pomocí klávesnice
;------------------------------------------------------------------------------

MOUSEB	call	MOUSRKEY		; prečti porty definovaných kláves, v D bude stav testovaných kláves
	ld	hl,(MOUSE_XY)	; do HL přečti souřadnice šipky

MOUSEKS	ld	c,2		; velikost kroku šipky, o kolik se šipka pohne při stisku klávesy
	bit	5,d		; testování 1. klávesy (UP)
	jr	z,MOUSEB1		; Z = klávesa nebyla stisknuta => přeskoč zpracování
	ld	a,h		; vezmi z H Y-ovou souřadnici
	sub	c		; odečti krok posunu
	ld	h,a		; ulož novou Y-ovou souřadnici do H
	jr	nc,MOUSEB1	; nedošlo-li k podtečení, přeskoč korekci
	ld	h,0		; C = šipka narazila do horního okraje => proveď korekci, aby neprošla

MOUSEB1	bit	6,d		; testování 2. klávesy (DOWN)
	jr	z,MOUSEB2		; Z = klávesa nebyla stisknuta => přeskoč zpracování
	ld	a,h		; vezmi z H Y-ovou souřadnici
	add	a,c		; pričti krok posunu
	ld	h,a		; ulož novou Y-ovou souřadnici do H
	cp	189		; a otestuj jestli šipka neprošla dolním okrajem
	jr	c,MOUSEB2		; není-li souřadnice větší než 189, přeskoč korekci
	ld	h,190		; C = šipka narazila do dolního okraje => proveď korekci, aby neprošla

MOUSEB2	bit	3,d		; testování 3. klávesy (LEFT)
	jr	z,MOUSEB3		; Z = klávesa nebyla stisknuta => přeskoč zpracování
	ld	a,l		; vezmi z L X-ovou souřadnici
	sub	c		; odečti krok posunu
	ld	l,a		; ulož novou X-ovou souřadnici do L
	jr	nc,MOUSEB3	; nedošlo-li k podtečení, přeskoč korekci
	ld	l,0		; C = šipka narazila do levého okraje => proveď korekci, aby neprošla

MOUSEB3	bit	4,d		; testování 4. klávesy (RIGHT)
	jr	z,MOUSEB4		; Z = klávesa nebyla stisknuta => přeskoč zpracování
	ld	a,l		; vezmi z L X-ovou souřadnici
	add	a,c		; přičti krok posunu
	ld	l,a		; ulož novou X-ovou souřadnici do L
	cp	252		; a otestuj jestli šipka neprošla pravým okrajem
	jr	c,MOUSEB4		; není-li souřadnice větší než 252, přeskoč korekci
	ld	l,252		; C = šipka narazila do pravého okraje => proveď korekci, aby neprošla

MOUSEB4	ld	a,d		; vezmi do A stav prečtených kláves
	and	00000111b		; ponech jen bity, které označují tlačítka jako fire (jako tlač. myši)
	ld	(MOUSE_B),a	; a stav tlačítek zapiš do proměnné MOUSE_B
	ld	(MOUSE_XY),hl	; ulož nové souřadnice šipky pro příští použití
	jp	MOUSE50

; Rutina na čtení kláves z knihy "Assembler a ZX Spectrum 2"
; Může být společná pro klávesu a Kempston joystick (nemá s ruskou Kempston Myší nic společného, jen jméno)
MOUSRKEY	ld	hl,MOUSEKTAB	; vezmi adresu tabulky kláves
	ld	de,7		; v E je počet kláves a v D bude výsledek (1 = stisknuto)
MOUSRK1	ld	c,(hl)		; do BC prečti z tabulky adresu portu
	inc	hl
	ld	b,(hl)
	inc	hl
	in	a,(c)		; prečti port (BC - 16ti bitové adresování)
	bit	7,c		; otestuj bit 7, u kempston joysticku je tam vždy 0 (leda by byl vadný)
	jp	z,MOUSRK2		; přeskoč CPL jedná-li se o Kempston joystick
	cpl			; 1 = klávesa stisknuta (normálně to je u kláves obráceně)
MOUSRK2	and	(hl)		; ponech jen testovaný bit (filtrace tabulkou)
	inc	hl		; a posuň HL na začátek dalšího řádku tabulky
	jr	z,MOUSRK3
	set	7,d		; nastav bit 7 na 1
MOUSRK3	srl	d		; a posuň ho dolů (tím se do D postupně uloží stav všech kláves)
	dec	e		; sniž počítadlo portů k prečtení
	jr	nz,MOUSRK1	; opakuj dokud není vše přečteno
	ret

; Tabulka kódů kláves, kterou je možné měnit - první 2 byty jsou adresou portu, 3. byte je bitový filtr.
; Tímto způsobem je možno definovat i Kempston joystick, ale není možné ho rozumně detekovat, pokud je
; zároveň připojena amiga mouse, uživatel musí sám rozhodnout co chce používat, nejlépe stiskem klávesy.
; Kempston joystick a klávesy je samozřejmě možné libovolně kombinovat, i když to asi není praktické.

MOUSEKTAB	db	254, 127, 00000100b	; FIRE 1	(M)
	db	254, 127, 00001000b	; FIRE 2	(N)
	db	254, 127, 00010000b	; FIRE 3	(B)
	db	254, 223, 00000010b	; LEFT	(O)
	db	254, 223, 00000001b	; RIGHT	(P)
	db	254, 251, 00000001b	; UP	(Q)
	db	254, 253, 00000001b	; DOWN	(A)

;------------------------------------------------------------------------------
; ZMĚNA SOUŘADNIC [X,Y] pomocí AMIGA MOUSE
;------------------------------------------------------------------------------
; Pozor! Interface s MHB8255 je nutné inicializovat mimo tento program.

MOUSEA	ld	bc,130*256	; B = počet průchodů čtecí smyčkou (rozumný kompromis)
	ld	a,(MOUSE_X)	; souřadnice se budou uvnitř smyčky měnit a je lépe budou-li operandem
	ld	(MOUSAX+1),a
	ld	a,(MOUSE_Y)
	ld	(MOUSAY+1),a
MOUSEA1	push	bc		; uloz BC do zasobniku - zde zacina smycka
	ld	b,c		; a do B ?????
	in	a,(31)		; čti port
	ld	de,MOUSEAP	; pomocná proměnná
	call	MOUS_SM		; zjisti jakym smerem se mys pohnula
MOUSAX	ld	a,77h		; vezmi souradnice mysi
	add	a,(hl)
	jr	z,MOUSAKX		; Z = preskoc zapis X-ove souradnice
	ld	(MOUSAX+1),a

MOUSAKX	inc	de
	in	a,(31)		; čti port
	rrca			; posun o 1 bit vpravo, kvuli detekci smeru
	call	MOUS_SM		; a ted se da pouzit stejna rutina jako pro X
MOUSAY	ld	a,60h		; vezmi starou Y-ovou souradnici
	add	a,(hl)		; a pricti cislo prectene z tabulky
	jr	z,MOUSAKY		; Z = preskoc zapis a korekci Y-ove souradnice
	cp	192		; otestuj jestli sipka neprosla spodnim okr.
	jr	nz,MOUSADO	; pokud prosla (Z)
	ld	a,191		; proced korekci
MOUSADO	ld	(MOUSAY+1),a	; zapis novou Y-ovou souradnici
MOUSAKY	pop	bc		; obnov pocitadlo pruchodu
	djnz	MOUSEA1		; a opakuj pokud tento nebyl posledni
	ld	a,(MOUSAX+1)	; zapis nove souradnice do promennych
	ld	(MOUSE_X),a
	ld	a,(MOUSAY+1)
	ld	(MOUSE_Y),a
	in	a,(31)		; naposledy precti port mysi
	rra
	rra
	rra
	rra
	and	00000111b		; ponech jen bity tlacitek
	ld	(MOUSE_B),a
	jp	MOUSE50

MOUS_SM	and	5		; testuje jakym smerem se amiga mys pohnula
	ld	c,a		; na zaklade Karnaughovych map
	ld	a,(de)
	rlca
	and	10
	or	c
	ld	(de),a
	ld	c,a
	ld	hl,MOUSTAB
	add	hl,bc
	ret

MOUSTAB	db	0,255,1,0		; tabulka kódů pro výpočet pohybu AMOUSE
	db	1,0,0,255
	db	255,0,0,1
	db	0,1,255,0

MOUSEAP	dw	0		; promenna tykajici se vyhradne detekce smeru
				; pohybu AMIGA MOUSE

;------------------------------------------------------------------------------
; ZMENA SOURADNIC [X,Y] pomocí KMOUSE (Ruská verze - později i od Velesofta)
;------------------------------------------------------------------------------
; .... OTESTOVAT V PRAXI!

MOUSEK	ld	a,251		; cti X-ovou souradnici z portu 64479
	in	a,(223)
	ld	(MOUSE_X),a	; uloz pro pristi zavolani programu MOUSE
	ld	a,255
	in	a,(223)		; cti Y-ovou souradnici z portu 65503
	cpl			; u souradnice Y nam nevyhovuje hodnota nad 192
	cp	191		; takze provedu jednoduchou korekci
	jp	c,MOUSEKK		; IF A>191 THEN A=191
	ld	a,191
MOUSEKK	ld	(MOUSE_Y),a	; a uloz pro dalsi volani programu MOUSE
	ld	a,250		; cti port 64223 - BUTTONS
	in	a,(223)		; ale ziskal jsem nevhodny zpusob ulozeni stavu
	cpl			; takze zase provedu korekci, nejdrive neguju
	and	00000111b		; byte a pak z nej necham jen dolni 3 bity
	ld	b,a		; zalohuju do B a ted prehodim bit 0 a bit 1
	rla			; bit 0 v A posunu na pozici bitu 1
	and	00000010b		; ponecham jen bit 1
	ld	c,a		; a ulozim do C
	ld	a,b		; znovu vezmu puvodni byte
	rra			; posunu bit 1 v A na pozici bitu 0
	and	00000001b		; ponecham jen bit 0
	or	c		; pridam bit 1 ulozeny v C
	ld	c,a		; ted budu mit v C ulozene prehozene bity 0 a 1
	ld	a,b		; naposledy vezmu puvodni byte
	and	00000100b		; ponecham z nej jen bit 2
	or	c		; pridam k nemu bity 0 a 1
	ld	(MOUSE_B),a	; ulozim do pameti a je hotovo
	jp	MOUSE50

; Před HALT (za MOUSE50) je možno přidat automatickou detekci polohovacího zařízení a
; následnou změnu proměnné MOUSE_T. V dalším volaní pak bude takto zvolené zařízení
; normálně používáno.

; autodetect KEYBOARD - Je-li stisknuta klávesa přepne se ovladač na čtení klávesnice, užitečné
;                       pokud uživatel potřebuje z jakéhokoliv důvodu ovládat program klávesnicí
;                       ale byla zvolena myš.

;	xor	a		; ctu port 0*256+254
;	in	a,(254)
;	cpl
;	and	%00011111	; ponecham dolnich 5 bitu
;	jr	nz,MOUSE50
;	ld	a,0		; do A cislo odpovidajici klavesnici
;	ld	(MOUSE_T),a	; a zapisu ho do promenne MOUSE_T

; autodetect AMIGA MOUSE  - Amiga mouse se oproti Kempston joystiku liší tím, že u ní mohou běžně
;                           nastat log. 1 na bitech, které u joysticku znamenají protilehlé směry,
;                           takže je není možno zvolit bez jeho mechanického zničení.
;                           Bohužel detekce nemůže být 100% spolehlivá, ačkoli většinou funguje.

;	in	a,(31)		; čti port na němž je připojena myš
;	bit	a,7		; je-li bit 7 log. 1 pravděpodobně port 31 není funkční
;	jp	nz,MOUSE50	; takže zbytek rutiny přeskoč
;	and	%101		; tyto bity nemohou být nikdy v log. 1 pokud
;	cp	%101		; je připojen jenom Kempston joystick
;	jp	nz,MOUSE50	; Z = bity byly v log. 1 => myš je pravděpodobně připojena
;	ld	a,1		; do A číslo odpovídající amiga myši
;	ld	(MOUSE_T),a	; a zapíšu ho do proměnné MOUSE_T

; Jak jednoduše detekovat KEMPSTON MOUSE nevím!
; Jak jednoduše detekovat KEMPSTON joystick nevím (resp. vím, ale ne v kombinaci s Amiga mouse)!

MOUSE50	ei			; povolím přerušení, pokud náhodou povolené nebylo
	halt			; a počkám na něj (paprsek začíná kreslit obrazovku)
				; případný zákaz přerušení si přidejte sami

; smazání šipky a vykreslení původního obsahu obrazovky

MOUSEC	ld	hl,0		; do operandu je místo 0 zapisována adresa šipky ve VRAM
	ld	b,15		; počet pixelů na výšku
	ld	de,MSIPKA_B	; adresa uloženého původnho pozadí pod šipkou
MOUSEC1	ld	a,(de)		; vezmu byte z původního pozadí
	ld	(hl),a		; a zapíšu ho do VRAM
	inc	de		; posunu DE o 1
	push	hl		; zapamatuju HL
	call	RIGHTL		; a spočítám adresu HL o byte vpravo (inc HL nestačí, kus šipky může zmizet)
	ld	a,(de)		; vezmi další byte z původního pozadí
	ld	(hl),a		; a zapíšu ho do VRAM
	inc	de		; posunu DE o 1
	pop	hl		; obnovím v HL adresu levého bytu
	call	DOWNHL		; a z ní spočítám adresu o pixel níž
	djnz	MOUSEC1		; opakuj tolikrát, kolik pixelů na výšku šipka má

MOUSEBUTT	ld	a,0		; vezmi stav stisknutí tlačítek
	or	a		; 0 = žádné nebylo stisknuto
	jp	z,MOUSE		; pokud nebylo tlačítko stisknuto, opakuj činnost celého programu

	ret         		; nějaké tlačítko bylo stisknuto, vrať se, záleží na programu
				; využívajícím šipku jak tlačítka zpracuje (tím může být NOIKON)

;==============================================================================
;  GRAFIKA A NĚKTERÉ PROMĚNÉ
;==============================================================================

MSIPKA	db	00000000b		; sprite šipky
	db	01000000b
	db	01100000b
	db	01110000b
	db	01111000b
	db	01111100b
	db	01111110b
	db	01111000b
	db	01001000b
	db	00001000b
	db	00000100b
	db	00000100b
	db	00000010b
	db	00000010b
	db	00000000b

MSIPKA_M	db	11100000b		; maska šipky - musí následovat hned za spritem
	db	11110000b
	db	11111000b
	db	11111100b
	db	11111110b
	db	11111111b
	db	11111111b
	db	11111111b
	db	11111100b
	db	11111110b
	db	00011110b
	db	00001111b
	db	00001111b
	db	00000111b
	db	00000111b

MSIPKA_B	ds	30		; sem se ukládá z VRAM to co šipka překryla

;==============================================================================
;  PODPŮRNÉ RUTINY
;==============================================================================

RIGHTL	ld	a,l		; RIGHTL zajištuje posun adresy spritu ve
	inc	l		; VRAM o byte vpravo a jeho spravné vykreslení,
	xor	l		; pokud je jeho levá půlka přímo u pravého
	bit	5,a		; okraje obrazovky. V takovém případě se
	ret	z		; pravá půlka kreslí do ROM, takže vlastně
	ld	h,0		; nekreslí / BACHA NA WRITEABLE ROMky!! (nahradit 0 číslem 60, poškodí font)
	ret

;	include	downhl.za		; tato rutina by mela byt soucasti programu, který myš používá
;==============================================================================
; RUTINA, KTERÁ ZAVOLÁ ŠIPKU A VOLÁ JI TAK DLOUHO DOKUD UŽIVATEL NEKLIKNE
; NA NĚKTEROU PLATNOU IKONU (POLOHA DEFINOVANÁ V TABULCE). V TOM OKAMŽIKU
; RUTINA SKOČÍ NA ADRESU PŘÍSLUŠNÉ RUTINY, KTERÁ IKONĚ ODPOVÍDÁ.
;==============================================================================

NOICON	call	MOUSE		; zavolej program pro obsluhu HID a kreslení šipky na obrazovku
				; rutinu NOICON možno volat pomocí CALL a instrukci
				; RET umístit do rutiny reagující na kliknuti na ikonu

TSTXY	ld	de,(MOUSE_XY)	; souřadnice šipky do DE (D = X, E = Y)
	ld	bc,6		; do BC délku souřadnic v tabulce ikon a adresy příslušné rutiny
	ld	ix,XYIKON-6	; do IX adresu tabulky ikon a adres rutin mínus jednu položku

TSTXY_1	add	ix,bc		; pričti BC k registru IX
	ld	a,(ix+0)		; čti X1
	cp	255		; porovnej s 255 - znamená konec tabulky
	jr	z,NOICON		; je-li 255 (Z) nebylo kliknuto na ikonu a bude opakováno kreslení šipky
	ld	a,(ix+0)		; jinak porovnávej dál, dokud není nalezena ikona, nebo konec tabulky
	cp	d
	jr	nc,TSTXY_1
	ld	a,(ix+1)
	cp	d
	jr	c,TSTXY_1
	ld	a,(ix+2)
	cp	e
	jr	nc,TSTXY_1
	ld	a,(ix+3)
	cp	e
	jr	c,TSTXY_1
	ld	h,(ix+5)		; bylo kliknuto na nějakou ikonu, takže
	ld	l,(ix+4)		; přečti do HL adresu obslužné rutiny
	jp	(hl)		; a skoč na tuto adresu


; TOTO JE JEN UKAZKA - takovato tabulka by mela byt soucasti programu
;
;XYIKON	db 0,16,0,16		; x1,x2,y1,y2
;	defw EXIT_I		; adresa vykonne rutiny
;	db 255			; konec tabulky ikon (NUTNE! Nikdy nesmí chybět!)
;
;EXIT_I				; priklad
;	ret


;==============================================================================
Program už je v podstatě zastaralý, stahujte z popisu KMouse

Celý ovladač myši je nutné spouštět od adresy NOICON. Rutina TEST_M je skutečně jen k testování, to není vstupní bod programu. Je nutné mít správně vyplněnou tabulku XYIKON, která obsahuje souřadnice ikon a adresu rutiny, která bude zavolána po kliknutí na ikonu. A za poslední, před tuto rutinu doporučuju přidat možnost volby ovládání, rozhodně bych si ve svém programu nedovolil jako defaultní ovladač použít jednu z myší. Když už, tak klávesy. A pokud má uživatel možnost změnit šipkou (třeba v menu) ovládání, musí existovat možnost totéž provést klávesnicí i po změně na myš.

Download

Zdroje informací: Tak různě z webu (porty a schéma připojení Kempston mouse), knížka Assembler a ZX Spectrum (prapůvodní základy pro kreslení šipky ovládané klávesami), a dost vlastních zkušeností.

Související odkazy

Opravené chyby

  • 28.2.2004 - celý článek přepracován, výrazně rozšířen úvod, opraveny chyby, doplněn datasheet 74HC14 a obrázek myši zevnitř.
  • 11.4.2005 - opraveny přehozené bity 0 a 1 (v tabulce i diagramu), doplněny odkazy na HWBook s popisem konektorů, vše znovu pečlivě zkontrolováno podle reálného fungujícího hardwaru, upozornil Velesoft
  • 23.12.2015 - revidováno, promazán balast a nesmysly z textu, doplněny obrázky, opraven pinout (poštouchl nalezenou chybou z00m).

[ Zpět na hlavní stránku ]

Cygnusova stránka o ZX Spectru a kompatibilních počítačích byla napsána (přepsána) výhradně pomocí svobodného Open Source softwaru. V případě že naleznete chybu, nebo byste rádi cokoliv co se ZX Spectrem souvisí, neváhejte mi napsat na některý z mých emailů, nebo pracovně do zaměstnání. Stručně o mém webu se můžete dočíst zde.