; **************************************************** ; ovladač Myš602 pro PMD-85 (3rd generation) ; **************************************************** ; vstupní port: 8Ch ; formát bitů portu: PL--XXYY ; 6. 7. 2020 - výrazné úpravy => 3rd generation ; 13500-14500 čtení/sec ; 12. 12. 2020 - oprava dynamiky pohybu dle Pythagora ; **************************************************** .org ($+255)/256*256 ; zarovnat na adresu s LSB=00h ; ****************************************************** ; Rutina pro rozpoznání pohybu myši typu 602. ; Detekce pohybu myši bez překreslování jejího kurzoru. ; ****************************************************** ; Po návratu je stav L tlačítka myši přítomen ; v nejvyšším bitu reg. A (a je nastaven příznak S) ; a stav pravého tlačítka je v příznaku CY. ; Proto: JC adr => skok při P tlačítku ; JM adr => skok při L tlačítku ; ****************************************************** MysDriver xra a mov b,a ; BC = přírůstek souřadnice X mov c,a mov d,a ; DE = přírůstek souřadnice Y mov e,a dcr a ; odpočet doby chodu sta MysRpt ; (ideální je velké číslo, max. 255) ; doba chodu nesmí být větší než 255, ; protože pak neplatí některé ; předpoklady u matematických úprav MysLoop in mysport ; načíst signály myši ani 0fh ; ponechat jen clonky MysOld adi 0 ; plus starý stav clonek mov l,a ; index v tabulce přechodů add a ; starý stav se vysune z ACC add a ; a nový stav clonek se add a ; uloží do vyšší poloviny bajtu add a ; a následně do paměti jako sta MysOld+1 ; starý stav clonek mvi h,MysTab/256 ; začátek tabulky přechodů mov l,m ; načíst LO-adr ovladače směru dcr h ; k němu HI-adr ovladače směru ; ve stránce 00xxh pchl ; a skok na tento ovladač ; *********************************** ; návrat z obsluhy jednotlivých směrů ; a škálování přírůstků dX a dY ; *********************************** MysQuit mov a,b ; C = ABS(X) ana a ; +uschovat info o změně znaménka push psw cm Neg_BC mov a,d ; E = ABS(Y) ana a ; +uschovat info o změně znaménka push psw cm Neg_DE lxi h,tbRoot ; (HL) = dX^2 mvi a,Max_dL cmp c jc MysMax_dX mov a,c MysMax_dX call Add_A2HL push h lxi h,tbRoot ; ACC = dY^2 mvi a,Max_dL cmp e jc MysMax_dY mov a,e MysMax_dY call Add_A2HL mov a,m pop h ; A = dX^2 + dY^2 (<256) add m jnc MysSenstvtPos mvi a,255 ; max dL MysSenstvtPos call MysDPIEmu ; vlastní dynamický pohyb mov a,b ; byla změna souřadnic během cyklu? ora c ; test dX ora d ; a dY ora e sta MysXCHG ; ACC=0 <=> myš bez pohybu pop psw ; obnova znaménka dX a dY cm Neg_DE pop psw cm Neg_BC lhld MysY ; Y:=Y+dY (plus test pozice Y) dad d call TestYCoor ; test nastavených dorazů v ose Y shld MysY ; uložit novou hodnotu souřadnice Y lhld MysX ; X:=X+dX (plus test pozice X) dad b call TestXCoor ; test nastavených dorazů v ose X shld MysX ; uložit novou hodnotu souřadnice Y in mysport ; načíst signály myši add a ; CY=pravé tlačítko, P=levé tlačítko ret ; ************************************** ; Tabulka druhých mocnin a její velikost ; ************************************** tbRoot .db 0,1,4,9,16,25,36,49,64,81,100,121,144,169,196 .db 225 Max_dL .equ $-tbRoot-1 ; *********************** ; Ovladač citlivosti NORM ; vstup: BC = dX ; DE = dY ; *********************** MysDPIStd cpi 64 ; pro pomalý pohyb rc ; f(dX,dY)=1 ; jinak f(dX,dY)=3/2 call MysMul3 ; x3 jmp MysDiv2 ; /2 ; *********************** ; Ovladač citlivosti SLOW ; vstup: BC = dX ; DE = dY ; *********************** MysDPIEmu cpi 255 ; pro pomalý pohyb jc MysDiv2 ; f(dX,dY)=1/2 ; jinak f(dX,dY)=3/4 call MysMul3 ; x3 ana a ; /2 mov a,d rar mov d,a mov a,e rar mov e,a ana a mov a,b rar mov b,a mov a,c rar mov c,a MysDiv2 ana a ; /2 mov a,d rar mov d,a mov a,e rar mov e,a ana a mov a,b rar mov b,a mov a,c rar mov c,a ret ; ************************************************ ; Obslužné vektory pro směry pohybu myši ; musí ležet ve 256 bajtové stránce před ; tabulkou přechodových stavů clonek myši "mystab" ; tabulka "mystab" obsahuje jen LO-adr vektorů!!! ; ************************************************ mys_sv: dcx d ; Y-- mys_vv: inx b ; X++ mysnul: lxi h,MysRpt dcr m jnz MysLoop jmp MysQuit mys_jz: inx d ; Y++ mys_zz: dcx b ; X-- lxi h,MysRpt dcr m jnz MysLoop jmp MysQuit mys_sz: dcx b ; X-- mys_ss: dcx d ; Y-- lxi h,MysRpt dcr m jnz MysLoop jmp MysQuit mys_jv: inx b ; X++ mys_jj: inx d ; Y++ lxi h,MysRpt dcr m jnz MysLoop jmp MysQuit ; ********************************************** ; Tabulka nižších bajtů adres obslužných vektorů ; (vyšší bajt adresy obslužného vektoru je vždy! ; o jedničku menší než vyšší bajt bázové adresy ; tabulky "mystab"). ; Tyto equations nepřesouvat před rutiny!!! ; ********************************************** m60 .equ mysnul%256 ; nulová funkce m61 .equ mys_ss%256 ; sever m62 .equ mys_sv%256 ; severovýchod m63 .equ mys_vv%256 ; východ m64 .equ mys_jv%256 ; jihovýchod m65 .equ mys_jj%256 ; jih m66 .equ mys_jz%256 ; jihozápad m67 .equ mys_zz%256 ; západ m68 .equ mys_sz%256 ; severozápad ; *********************************************************** ; Bufer pro zálohu pozadí kurzoru myši. Musí končit na adrese ; dělitelné 256-ti, aby při inkrementaci LSB generoval Z=1. ; *********************************************************** .org ($+23)/256*256+0e8h MysBufer .ds 24 ; vlastní bufer pozadí kurzoru myši ; *********************************************** ; Tabulka přechodových stavů clonek myši 602. ; Obsahuje LO-adr obslužných vektorů detekovaných ; směrů. Tabulka musí začínat na adrese xx00h! ; *********************************************** ; nižší nibble adresy je nový stav clonek ; vyšší nibble adresy je starý stav clonek ; 01/02 v rámci nibble je svislý směr ; 04/08 v rámci nibble je vodorovný směr .org MysBufer+24 ; zarovnat na adresu s LSB=00h ; tabulka pro detekci pohybu MysTab: .db m60,m65,m61,m60,m63,m64,m62,m63 ; 00 .db m67,m66,m68,m67,m60,m65,m61,m60 .db m61,m60,m60,m65,m62,m63,m63,m64 ; 10 .db m68,m67,m67,m66,m61,m60,m60,m65 .db m65,m60,m60,m61,m64,m63,m63,m62 ; 20 .db m66,m67,m67,m68,m65,m60,m60,m61 .db m60,m61,m65,m60,m63,m62,m64,m63 ; 30 .db m67,m68,m66,m67,m60,m61,m65,m60 .db m67,m66,m68,m67,m60,m65,m61,m60 ; 40 .db m60,m65,m61,m60,m63,m64,m62,m63 .db m68,m67,m67,m66,m61,m60,m60,m65 ; 50 .db m61,m60,m60,m65,m62,m63,m63,m64 .db m66,m67,m67,m68,m65,m60,m60,m61 ; 60 .db m65,m60,m60,m61,m64,m63,m63,m62 .db m67,m68,m66,m67,m60,m61,m65,m60 ; 70 .db m60,m61,m65,m60,m63,m62,m64,m63 .db m63,m64,m62,m63,m60,m65,m61,m60 ; 80 .db m60,m65,m61,m60,m67,m66,m68,m67 .db m62,m63,m63,m64,m61,m60,m60,m65 ; 90 .db m61,m60,m60,m65,m68,m67,m67,m66 .db m64,m63,m63,m62,m65,m60,m60,m61 ; A0 .db m65,m60,m60,m61,m66,m67,m67,m68 .db m63,m62,m64,m63,m60,m61,m65,m60 ; B0 .db m60,m61,m65,m60,m67,m68,m66,m67 .db m60,m65,m61,m60,m67,m66,m68,m67 ; C0 .db m63,m64,m62,m63,m60,m65,m61,m60 .db m61,m60,m60,m65,m68,m67,m67,m66 ; D0 .db m62,m63,m63,m64,m61,m60,m60,m65 .db m65,m60,m60,m61,m66,m67,m67,m68 ; E0 .db m64,m63,m63,m62,m65,m60,m60,m61 .db m60,m61,m65,m60,m67,m68,m66,m67 ; F0 .db m63,m62,m64,m63,m60,m61,m65,m60 ; ************************************************************ ; Tabulka pixelových ofsetů v ose X pro výběr kurzoru ; dle pixelové pozice 0..5 ; Tabulka vrací hodnotu MOD3 (dvěma se předdělí instrukcí RAR) ; Rozsah tabulky (vstupních hodnot) je 0..(287/2) ; ************************************************************ .org ($+255)/256*256 ; zarovnat na adresu s LSB=00h tbPix2Ofs .db 0,1,2,0,1,2,0,1,2,0,1,2,0,1,2,0,1,2,0,1,2,0,1,2 .db 0,1,2,0,1,2,0,1,2,0,1,2,0,1,2,0,1,2,0,1,2,0,1,2 .db 0,1,2,0,1,2,0,1,2,0,1,2,0,1,2,0,1,2,0,1,2,0,1,2 .db 0,1,2,0,1,2,0,1,2,0,1,2,0,1,2,0,1,2,0,1,2,0,1,2 .db 0,1,2,0,1,2,0,1,2,0,1,2,0,1,2,0,1,2,0,1,2,0,1,2 .db 0,1,2,0,1,2,0,1,2,0,1,2,0,1,2,0,1,2,0,1,2,0,1,2 ; ****************************************** ; Kontrola rozsahu souřadnice X kurzoru myši ; vstup: HL = souřadnice X ; výstup: HL = souřadnice X omezená dorazy ; ****************************************** LoadXCoor lhld MysX ; souřadnici X TestXCoor xchg lhld MysXMin ; a L doraz call CmpHLDE ; porovnám rnc ; X < L doraz, vracím L doraz lhld MysXMax ; načtu P doraz call CmpHLDE ; porovnám xchg rnc ; X < P doraz, souřadnice X je OK mov a,h ; když je X > P doraz, může být ana a ; ještě souřadnice X záporná.. xchg rp ; není => vracím tedy P doraz lhld MysXMin ; je => vracím L doraz ret ; ****************************************** ; Kontrola rozsahu souřadnice Y kurzoru myši ; vstup: HL = souřadnice Y ; výstup: HL = souřadnice Y omezená dorazy ; ****************************************** LoadYCoor lhld MysY ; souřadnici Y TestYCoor xchg lhld MysYMin ; a H doraz call CmpHLDE ; porovnám rnc ; Y je nad H dorazem, vracím H doraz lhld MysYMax ; načtu D doraz call CmpHLDE ; porovnám xchg rnc ; Y nad D dorazem, souřadnice Y je OK mov a,h ; když je Y pod D dorazem, může být ana a ; ještě souřadnice Y záporná.. xchg rp ; není => vracím tedy D doraz lhld MysYMin ; je => vracím H doraz ret ; ******************************************* ; Deaktivace myši ; Obnoví pozadí pod kurzorem myši z buferu. ; Bufer sám je adresován lineárně, ovšem ; obsah je zpřeházen pro adresaci vram 0-4R-8 ; ******************************************* MysDea lxi b,-(7*64)-1 ; BC = řádkovač lxi d,MysBufer ; DE = bufer pozadí lhld MysAOld RefreshLoop ldax d ; 0 mov m,a inr l inr e ldax d mov m,a inr h inr e ldax d ; 4R mov m,a dcr l inr e ldax d mov m,a stax d inr h inr e ldax d ; 8 mov m,a inr l inr e ldax d mov m,a dad b inr e jnz RefreshLoop ; konec buferu? ret ; ******** ; proměnné ; ******** MysX .dw 0 ; souřadnice X kurzoru myši MysY .dw 0 ; souřadnice Y kurzoru myši MysXMin .dw 0 ; L doraz kurzoru myši (min 0!!!) MysXMax .dw 281 ; P doraz kurzoru myši (max 281!!!) MysYMin .dw 0 ; H doraz kurzoru myši (min 0!!!) MysYMax .dw 244 ; D doraz kurzoru myši (max 244) MysAdr .dw 0 ; adresa kurzoru myši ve videoram MysAOld .dw 0 ; stará adresa kurzoru myši ve videoram MysXCHG .db 0 ; příznak změny pozice kurzoru MysRpt .db 0 ; počitadlo opakování ve smyčce MysBit .dw MysCrv ; ukazatel na vybraný kurzor dle MysX ; *********************************************************** ; Tabulka adres v ose X pro posun kurzoru dle pixelové pozice ; Tabulka vrací hodnotu /3 (dvěma se předdělí instrukcí RAR) ; Rozsah tabulky (vstupních hodnot) je 0..(287/2) ; *********************************************************** .org ($+255)/256*256 ; zarovnat na adresu s LSB=00h tbPix2Adr .db 00,00,00,01,01,01,02,02,02,03,03,03,04,04,04 .db 05,05,05,06,06,06,07,07,07,08,08,08,09,09,09 .db 10,10,10,11,11,11,12,12,12,13,13,13,14,14,14 .db 15,15,15,16,16,16,17,17,17,18,18,18,19,19,19 .db 20,20,20,21,21,21,22,22,22,23,23,23,24,24,24 .db 25,25,25,26,26,26,27,27,27,28,28,28,29,29,29 .db 30,30,30,31,31,31,32,32,32,33,33,33,34,34,34 .db 35,35,35,36,36,36,37,37,37,38,38,38,39,39,39 .db 40,40,40,41,41,41,42,42,42,43,43,43,44,44,44 .db 45,45,45,46,46,46,47,47,47 ; ********************* ; aktivace myši ; - test validní adresy ; - uschování pozadí ; - vykreslení kurzoru ; ********************* MysAct ; ******************************************* ; uschová pozadí pod kurzorem myši do buferu ; bufer sám je adresován lineárně, ovšem ; obsah je zpřeházen pro adresaci vram 0-4R-8 ; ******************************************* call Pixel2Adr ; HL = adresa kurzoru myši ; včetně testu validity MysActBufer lxi b,-(7*64)-1 ; BC = řádkovač lxi d,MysBufer ; DE = bufer pozadí MysSaveLoop mov a,m ; [0,0] stax d inr l inr e mov a,m ; [1,0] stax d inr h inr e mov a,m ; [1,4] stax d dcr l inr e mov a,m ; [0,4] stax d inr h inr e mov a,m ; [0,8] stax d inr l inr e mov a,m ; [1,8] stax d dad b inr e jnz MysSaveLoop ; konec buferu? ; ****************************** ; nakreslí kurzor myši na pozadí ; ****************************** ShowMys lxi h,0 ; uschovat hodnotu SP dad sp shld ShowMysSP+1 lhld MysBit ; H:L = 02:uu, kde uu je bitová ; pozice kurzoru myši 0..5 mov l,m ; H:L = 02:vv, což je úplná adresa ; s animační fází kurzoru myši sphl ; SP = předloha kurzoru myši podle ; horizontální pozice v bajtu lhld MysAdr ; HL = adresa kurzoru shld MysAOld lxi d,MysBufer ; DE = bufer pozadí kurzoru ShowMysLoop pop b ; 0 ldax d inr e ana b ora c mov m,a inr l pop b ldax d inr e ana b ora c mov m,a inr h pop b ; 4R ldax d inr e ana b ora c mov m,a dcr l pop b ldax d inr e ana b ora c mov m,a inr h pop b ; 8 ldax d inr e ana b ora c mov m,a inr l pop b ldax d ana b ora c mov m,a lxi b,-(7*64)-1 ; řádkovač dad b inr e jnz ShowMysLoop ShowMysSP lxi sp,0 ; obnova hodnoty reg. SP ret ; ****************************************************** ; 6 animačních fází myšího kurzoru. ; Tabulka ofsetů až po návěští myscr5 musí ležet v jedné ; 256-bajtové stránce! ; ****************************************************** .org ($+255)/256*256 ; zarovnat na adresu s LSB=00h MysCrv: .db myscr0%256 ; ofset fáze 0 .db myscr1%256 ; ofset fáze 1 .db myscr2%256 ; ofset fáze 2 .db myscr3%256 ; ofset fáze 3 .db myscr4%256 ; ofset fáze 4 .db myscr5%256 ; ofset fáze 5 myscr0: .dw 0f800h,0ff00h ; 0 - fáze 0 .dw 0fe00h,0c01eh ; 4R .dw 0c010h,0fe00h ; 8 .dw 0f002h,0ff00h ; 1 .dw 0fe00h,0c03eh ; 5R .dw 0c720h,0fe00h ; 9 .dw 0e006h,0ff00h ; 2 .dw 0fe00h,0c00eh ; 6R .dw 0cf20h,0fe00h ; 10 .dw 0c00eh,0ff00h ; 3 .dw 0ff00h,0c012h ; 7R .dw 0cf00h,0fe00h ; 11 myscr1: .dw 0f100h,0ff00h ; 0 - fáze 1 .dw 0fc00h,0c13ch ; 4R .dw 0c120h,0fc00h ; 8 .dw 0e104h,0ff00h ; 1 .dw 0fc01h,0c13ch ; 5R .dw 0cf00h,0fc01h ; 9 .dw 0c10ch,0ff00h ; 2 .dw 0fc00h,0c11ch ; 6R .dw 0df00h,0fc01h ; 10 .dw 0c11ch,0fe00h ; 3 .dw 0fe00h,0c124h ; 7R .dw 0df00h,0fc00h ; 11 myscr2: .dw 0e300h,0ff00h ; 0 - fáze 2 .dw 0f801h,0c338h ; 4R .dw 0c300h,0f801h ; 8 .dw 0c308h,0ff00h ; 1 .dw 0f803h,0c338h ; 5R .dw 0df00h,0f802h ; 9 .dw 0c318h,0fe00h ; 2 .dw 0f800h,0c338h ; 6R .dw 0ff00h,0f802h ; 10 .dw 0c338h,0fc00h ; 3 .dw 0fc01h,0c308h ; 7R .dw 0ff00h,0f800h ; 11 myscr3: .dw 0c700h,0ff00h ; 0 - fáze 3 .dw 0f003h,0c730h ; 4R .dw 0c700h,0f002h ; 8 .dw 0c710h,0fe00h ; 1 .dw 0f007h,0c730h ; 5R .dw 0ff00h,0f004h ; 9 .dw 0c730h,0fc00h ; 2 .dw 0f001h,0c730h ; 6R .dw 0ff00h,0f104h ; 10 .dw 0c730h,0f801h ; 3 .dw 0f802h,0c710h ; 7R .dw 0ff00h,0f100h ; 11 myscr4: .dw 0cf00h,0fe00h ; 0 - fáze 4 .dw 0e007h,0cf20h ; 4R .dw 0cf00h,0e004h ; 8 .dw 0cf20h,0fc00h ; 1 .dw 0e00fh,0cf20h ; 5R .dw 0ff00h,0e108h ; 9 .dw 0cf20h,0f801h ; 2 .dw 0e003h,0cf20h ; 6R .dw 0ff00h,0e308h ; 10 .dw 0cf20h,0f003h ; 3 .dw 0f004h,0cf20h ; 7R .dw 0ff00h,0e300h ; 11 myscr5: .dw 0df00h,0fc00h ; 0 - fáze 5 .dw 0c00fh,0df00h ; 4R .dw 0df00h,0c008h ; 8 .dw 0df00h,0f801h ; 1 .dw 0c01fh,0df00h ; 5R .dw 0ff00h,0c310h ; 9 .dw 0df00h,0f003h ; 2 .dw 0c007h,0df00h ; 6R .dw 0ff00h,0c710h ; 10 .dw 0df00h,0e007h ; 3 .dw 0e009h,0df00h ; 7R .dw 0ff00h,0c700h ; 11 ; ********************************************************* ; Z pixelových souřadnic, které ořeže na platný rozsah, ; vypočte adresu kurzoru ve videoram ; vstup: proměnné MysX, MysY ; výstup: HL = adresa kurzoru ve videoram ; ; ********************************************************* Pixel2Adr call LoadYCoor ; HL := 11yyyyyy yy000000 shld MysY dad h dad h dad h dad h dad h dad h mov a,h adi 0c0h mov h,a push h call LoadXCoor ; HL := HL + pozice bajtu na řádku shld MysX ; tedy HL := 11yyyyyy yyxxxxxx mov a,h rar mov a,l rar mov l,a ; nejprve L := X/2 (CY=zbytek) mvi h,tbPix2Ofs/256 mov a,m ; A := pixelový ofset 0..5 ral sta MysBit inr h mov e,m mvi d,0 pop h dad d shld MysAdr ret ; **************************************************** ; Nastavení citlivosti myši ; vstup: A=0: bez myši ; A=1: malá citlivost (verze emulátor) ; A=2: střední citlivost (std HW mouse 130DPI ) ; A=3: vysoká citlivost (homemade 40DPI) ; **************************************************** MysDPISet lda MysSensitivity ; podle nastavení myši cpi 4 ; (pouze platného) rnc lxi h,tbMysDPISet ; z tabulky citlivostí call GetWord ; vybere tu požadovanou shld MysSenstvtPos+1 ; a uloží ji ;lda MysSensitivity ; podle nastavení myši ;ana a ; vybere ;lxi h,KbdOvladac ; buď ovladač klávesnice ;jz MysDPISetup ;lxi h,MysDriver ; nebo ovladač myši ;MysDPISetup ;shld Ovladani+1 ; uloží ovladač myš/klávesnice ret tbMysDPISet .dw 0,MysDPIEmu,MysDPIStd,MysDPIHom ; *********************** ; Ovladač citlivosti FAST ; vstup: BC = dX ; DE = dY ; *********************** MysDPIHom cpi 4 ; x1 rc cpi 16 ; x3 jnc MysMul3 MysMul2 mov a,e ; x2 add a mov e,a mov a,d adc a mov d,a mov a,c add a mov c,a mov a,b adc a mov b,a ret MysMul3 mov l,e ; x3 mov h,d dad h dad d mov d,h mov e,l mov l,c mov h,b dad h dad b mov b,h mov c,l ret ; ************************* ; Změna znaménka čísla v BC ; ************************* Neg_BC mov a,c cma mov c,a mov a,b cma mov b,a inx b ret ; ************************* ; Změna znaménka čísla v DE ; ************************* Neg_DE mov a,e cma mov e,a mov a,d cma mov d,a inx d ret