PC-Maustreiber für ATARI

Der Anschluß einer seriellen Maus an den ATARI ist nicht problematisch; für den Betrieb braucht man jedoch eine Treiber-Software. Der hier vorgestellte Treiber arbeitet mit der LOGITECH-Pilot-Maus.

Früher oder später muß eine neue Maus her. Entweder weil die alte nach Jahren treuen Dienstes langsam ihren Geist aufgibt, oder weil man sich vielleicht doch eine Maus mit höherer Auflösung und Mikrotasten wünscht. Obwohl Fremdmäuse für den ATARI auf dem Markt existieren, schaut man doch oftmals etwas neidisch auf den PC-Bereich. Entweder weil es dort recht preisgünstige, oder aber auch von namhaften Designern gestylte Mäuse gibt.

Von der Idee ...

Nachdem die Idee geboren wurde, eine PC-Maus an den ATARI anzuschließen, stand die Treiber-Software als großes Problem da. Gerade hierbei kam die Frage auf, warum die Hersteller von seriellen Mäusen nicht gleich eine Treibersoftware auf der Diskette mitliefern. Bekanntlich kann der ATARI DOS-formatierte Disketten lesen, so daß auf der sowieso mitgelieferten 3,5"-Diskette ein kleines Verzeichnis „ATARI“ mit dem entsprechenden Programm immer noch Platz hätte. Da es solch einen Treiber bis jetzt nicht gibt, mußte ein eigener her.

Das Ergebnis ist ein PC-Maustreiber für die LOGITECH-Pilot-Maus. Als Besonderheit ist hier zu erwähnen, daß erstens die alte Originalmaus parallel weiter läuft, d.h. man kann den Mauszeiger mit beiden Mäusen gleichzeitig bewegen, und zweitens, daß die LOGITECH-Maus drei Tasten besitzt, während das Betriebssystem nur mit zwei Tasten umgehen kann. Aus dieser Tatsache heraus wurde auf die mittlere Taste der Doppelklick gelegt. Das Öffnen von Laufwerken oder Starten von Programmen ist so zum Kinderspiel geworden.

... über die Realisierung ...

Das Programm ist in seiner Grundstruktur wie jedes Programm, welches sich irgendwie in die inneren Anlegenheiten eines Rechners einmischt, aufgebaut. Nach Bestimmung der Speicherplatzlänge und Bereitstellung eines Programm-Stacks wird die serielle Schnittstelle auf die Maus eingestellt, d.h. 1200 Baud, 7 Daten-Bits, 1 Stop-Bit, keine Parität und kein Handshake. Dann folgt das Einklemmen der eigentlichen Routine in den Vektor 76 „RS232 Empfangspuffer voll“. Beim Beenden des Programms bleibt natürlich nur der Speicherbereich, der weiterhin gebraucht wird, resistent. Somit werden nur 582 Bytes im Speicher belegt. Wird das Programm ein zweites Mal gestartet, so wird der ursprüngliche Vektor wieder hergestellt.

Der Aufbau der Daten, die von der Maus kommen bzw. ins Betriebssystem geschickt werden, ist in den beiden Bildern erklärt.

Bild 1: Daten von der LOGITECH-Maus kommend
Bild 2: Daten für das Betriebssystem

Nun zur eigentlichen Routine. Ist ein Byte von der Maus an der seriellen Schnittstelle angekommen, wird ein Interrupt ausgelöst und über Vektor 76 die Maustreiberroutine angesprungen. Hier wird jenes Byte ausgewertet und zwischengespeichert. Sind alle Daten-Bytes von der Maus angekommen, wird das aufbereitete Datenpaket zum Betriebssystem abgeschickt. Die Erkennung der Daten-Bytes wird dadurch realisiert, daß im ersten Byte das sechste Bit (Header-Bit) gesetzt ist. Die nächsten Bytes werden dann nur abgezählt. Eine Besonderheit ist das eventuell auftretende vierte Byte für die mittlere Maustaste, welches, wenn wieder das erste Byte erwartet wird, aber das empfangene Byte kein Header-Bit hat, erkannt wird. Die Doppelklickroutine wird nur dann aufgerufen, wenn die mittlere Taste ihren Zustand von nicht gedrückt auf gedrückt ändert.

Da bei der Programmierung streng darauf geachtet wurde, nur über Vektoren ins Geschehen einzugreifen, dürfte der Treiber auf allen ATARIs laufen.

... zur Anwendung

Der Maustreiber bewährt sich bei mir schon seit etwa 9 Monaten. Gerade die Doppelklickfunktion der mittleren Maustaste ist nicht nur für Anfänger eine gute Arbeitserleichterung. Obwohl sich der Maustreiber elementar in den Maus-Datenstrom im Betriebssystem einklemmt, kommt es zu einer sehr großen Verträglichkeit mit dem Betriebssystem und den Programmen. Ausnahmen bilden natürlich Programme, die die serielle Schnittstelle gebrauchen (z.B. KERMIT etc.). Bei TEMPUS funktioniert der PC-Maustreiber auch einwandfrei, lediglich der TEMPUS-interne Bildschirmschoner reagiert nicht auf den Maustreiber. Hierbei wird wohl die Aktivität des Tastaturprozessors überwacht. Bei den Steinberg Midi-Sequenzer-Programmen funktioniert der Maustreiber gar nicht. Hier wird der Timer D, der für die Baud-Ratengenerierung zuständig ist, abgeschaltet. Sonst sind mir keine Unverträglichkeiten mit Programmen bekannt. Wer eine andere Funktion als den Doppelklick auf der mittleren Taste haben möchte, dürfte keine Probleme haben, die Routine durch seine eigene zu ersetzen. Ausprobiert wurden schon Routinen, wie z.B. „Hardcopy starten“, welche gerade bei Nutzung von TEMPLEMON sehr hilfreich sein kann; Druck auf die mittlere Maustaste - und man ist dort.

Eine Anpassung des PC-Maustreibers an andere serielle Mäuse dürfte vom Prinzip her möglich sein. Das Problem besteht erstens darin, die Daten, die von der Maus gesendet werden, zu entschlüsseln, und zweitens die richtige Baud-Rate und Anzahl der Daten-Bits herauszufinden. Ohne Meßeinrichtung kann dies auch ziemlich lange dauern, gerade dann, wenn man nicht auf die Idee kommt, daß nur 7 Daten-Bits vorhanden sein könnten, und stattdessen seine kryptographischen Fähigkeiten bei 8 Bit versucht.

Literatur:

[1] Jankowski, Rabich, Reschke; ATARI Profibuch ST-STE-TT; 10. Auflage; 1991 Sybex-Verlag, Düsseldorf


************************************************* * LOGITECH-Pilot-Maustreiber für ATARI * von Ralf Schernewski * Version 1.02 vom 18.03.93 * GST-Macro-Assembler * (c) MAXON Computer 1993 ************************************************* OPT ABS ************************************************* XBRAKEN equ 'CSNM' ; XBRA-Kennung vtab equ 0 ; Vektor-Tabelle condit equ 4 ; Zustand n_xval equ 5 ; neg. x-Wert n_yval equ 6 ; neg. y-Wert okMT equ 7 ; ok für MT b1 equ 8 ; 1. Datenbyte b2 esu 9 ; 2. Datenbyte b3 equ 10 ; 3. Datenbyte mt_cond equ 11 ; Zustand mittl. ; Maustaste RCVBFL equ $130 ; Vektor - RS232 ; Empfangspuf. voll UDR equ $fffffa2f ; Datenregister MFP ISRA equ $fffffa0f ; Interrupt ; In-Service Reg.A ************************************************* SECTION CODE ************************************************* XBRABEG bra main ; Sprung zum HptPrg ************************************************* dc.b 'XBRA’ ; XBRA-Anfang dc.l XBRAKEN ; Kennung oldvek1 dc.l 0 ; alter Vektor ************************************************* newvek1 ; Byte über RS232 ; angekommen movem.l d0-d7/a0-a6,-(sp) ; Register retten move.b udr,d4 ; Datenbyte holen btst.l #7,d4 ; Bit 7 gesetzt? bne auxfehl ; ja, dann Fehler lea global,a4 ; globale Variablen lea condtab,a3 ; Routinen-Adresse clr.w d3 ; d3 löschen move.b condit(a4),d3 ; Zustand holen lsl.w #2,d3 ; * 4 move.l $0(a3,d3.w),a2; Routine holen jmp (a2) ; reinspringen aCond0 btst.l #6,d4 ; Header-Bit da? beq.s a_mt ; nein, m.Taste move.b d4,d3 ; Wert kopieren andi.b #%00110000,d3 ; Tastenbits mask, lsr.b #4,d3 ; / 16 move.b d3,b1(a4) ; Tasten absp. ori.b #$f8,b1(a4) ; Header move.b d4,d3 ; Wert kopieren andi.b #%1100,d3 ; neg. y-Bits mask, lsl.b #4,d3 ; * 16 move.b d3,n_yval(a4) ; abspeichern move.b d4,d3 ; Wert kopieren andi.b #%11,d3 ; neg. x-Bits mask, lsl.b #6,d3 ; * 64 move.b d3,n_xval(a4) ; abspeichern move.b #1,condit(a4) ; neuer Zustand: 1 bra.s auxend ; Ende a_mt tst.b okMT(a4) ; Teste, ob MT ok bmi.s auxend ; nein, dann Ende cmp.b #32,d4 ; m.Taste gedrückt? bne.s a_mt_0 ; nein, vielleicht ; losgelassen btst.b #0,mt_cond(a4); schon gedrückt? bne.s auxend ; dann Ende bset.b #0,mt_cond(a4); m. Taste gedrückt ; setzen bsr.s mtfkt ; MT-Funktion bra.s auxend ; Ende a_mt_0 cmp.b #0,d4 ; mittl. Taste ; losgelassen? bne.s auxfehl ; nein, dann Fehler bclr.b #0,mt_cond(a4) ; mittl. Taste ; losgelassen! bra.s auxend ; Ende a_setc0 move.b #0,condit(a4) ; Fehler: Zustand 0 bra.s auxfehl ; -> Fehler aCond1 cmp.b #63,d4 ; Wert über 63 bhi.s a_setc0 ; ja, -> Zustand 0 or.b n_xval(a4),d4 ; neg. x-Wert-Bits ; hinzuaddieren move.b d4,b2(a4) ; Wert in Buffer move.b #2,condit(a4) ; neuer Zustand: 2 bra.s auxend ; -> Ende aCond2 cmp.b #63,d4 ; Wert über 63 bhi.s a_setc0 ; ja, -> Zustand 0 or.b n_yval(a4),d4 ; neg. y-Wert-Bits ; hinzuaddieren move.b d4,b3(a4) ; Wert in Buffer move.b #0,condit(a4) ; neuer Zustand: 0 lea b1(a4),a0 ; Bufferadresse move.l vtab{a4),a3 ; mit Vektortabelle move.l $10(a3),a2 ; Mouseroutinen- ; vektor holen jsr (a2) ; zur Mausroutine move.b #0,okMT(a4) ; kein Fehler ; MT enablen bra.s auxend ; Sprung zum Ende auxfehl move.b #-1,okMT(a4) ; Fehler ; MT disablen auxend bclr #4,isra ; ISR-Bit löschen movem.l (sp)+,d0-d7/a0-a6 ; Register rest. rte ; interrupt Rück- ; sprung - Stack ; holen und zurück condtab dc.l aCond0,aCond1,aCond2 ; Vektortabelle ************************************************* MTFkt movem.l d0/a0-a4,-(sp) ; Register retten moveq #1,d0 ; 2 mal MTLOOP lea MTDat1,a0 ; Bufferadresse move.l vtab(a4),a3 ; mit Vektortabelle move.l $10(a3),a2 ; Mouseroutinen- ; vektor holen jsr (a2) ; zur Mausroutine lea MTDat2,a0 ; Bufferadresse move.l vtab(a4),a3 ; mit Vektortabelle move.l $10(a3),a2 ; Mouseroutinen- ; vektor holen jsr (a2) ; zur Mausroutine dbf d0,MTLOOP ; Schleifenende movem.l (sp)+,d0/a0-a4 ; Register rest. rts ; Rücksprung MTDat1 dc.b $fa,$0,$0,$0 ; linke Taste gedr. MTDat2 dc.b $f8,$0,$0,$0 ; linke Taste nicht ; gedrückt ************************************************* global dc.l 0,0,0,0 ; globale Variablen ************************************************* XBRAEND install move.w #34,-(sp) ; Kvdvbase trap #14 ; XBIOS addq.l #2,sp ; Stack korr. lea global,a4 ; Adresse für glob. ; Variablen move.l d0,vtab(a4) ; Vektortabelle ; abspeichern move.b #-1,okMT(a4) ; MT disablen movea.l RCVBFL,a3 ; Vektoradresse cmpi.l #XBRAKEN,-8(a3) ; Kennung vorhanden beq.s exstall ; ja, -> entfernen lea oldvek1,a3 ; Adresse der Save- ; variablen holen move.l RCVBFL,(a3) ; alte Routinenadr. ; abspeichern lea newvek1,a3 ; Adresse der neuen ; Routine holen move.l a3,RCVBFL ; und ablegen clr.b d1 ; Routine install. rts ; Rücksprung exstall movea.l RCVBFL,a3 ; Vektoradresse move.l -4(a3),RCVBFL ; alte Routinen- ; adr. restaurieren move.b #-1,d1 ; Routine nicht ; installiert rts ; Rücksprung ************************************************* RSInit move.w #-1,-{sp) ; SCR unverändert move.w #-1,-{sp) ; TSR unverändert move.w #-1,-(sp) ; RSR unverändert move.w #168,-(sp) ; UCR (7,1,none) move.w #0,-(sp) ; kein Handshake move.w #7,-(sp) ; (1200 Baud) move.w #15,-(sp) ; rsconf trap #14 ; XBIOS add.l #14,sp ; Stack korr. RSILoop move.w #1,-(sp) ; Ser. Schnittst, move.w #1,-(sp) ; Bconstat trap #13 ; BIOS addq.l #4,sp ; Stack korr. tst.w d0 ; Teste Rückgabe beq.s RSIEnd ; = 0, dann Ende move.w #1,-(sp) ; Ser. Schnittst, move.w #2,-(sp) ; Bconin trap #13 ; BIOS addq.l #4,sp ; Stack korr. bra.s RSILoop ; zum Anfang RSIEnd rts ; Rücksprung ************************************************* main move.l a7,a5 ; Stackpointer move.l $4(a5),a5 ; Basepageadresse move.l $c(a5),d5 ; Länge Programm add.l $14(a5),d5 ; + init. DB add.l $1c(a5),d5 ; + uninit. DB add.l #$100,d5 ; + Basepage move.l a5,d1 ; Anfangsadresse add.l d5,d1 ; + Programmlaenge add.l #$400,d1 ; + Stack and.l #-2,d1 ; Adresse gerade move.l d1,a7 ; --> neuer Stack bsr RSInit ; RS232 init. pea install ; Routinenadresse ; uebergeben move.w #38,-(sp) ; Supexec trap #14 ; XBIOS addq.l #6,sp ; Stack korr. cmp.b #0,d1 ; Routine install.? beq.s end_1 ; ja, KEEP PROCESS pea TEXT01 ; Textadresse push, move.w #9,-(sp) ; Cconws trap #1 ; GEMDOS addq.l #6,sp ; Stack korr. clr.w -(sp) ; TERM trap #1 ; GEMDOS end_1 pea TEXT00 ; Textadresse push. move.w #9,-(sp) ; Cconws trap #1 ; GEMDOS addq.l #6,sp ; Stack korr. move.l #XBRAEND-XBRABEG,d5 ; Länge d. Treibers addi.l #$100,d5 ; + Basepage move.l d5,-(sp) ; Programmlänge move.w #$31,-(sp) ; KEEP PROCESS trap #1 ; GEMDOS ************************************************* TEXT00 dc.b 13,10 dc.b 'LOGIMOUSE-Treiber installiert' dc.b 13,10,0 TEXT01 dc.b 13,10 dc.b 'LOGIMOUSE-Treiber entfernt' dc.b 13,10,0,0 ************************************************* END

Ralf Schernewski
Links

Copyright-Bestimmungen: siehe Über diese Seite