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
Aus: ST-Computer 07 / 1993, Seite 72

Links

Copyright-Bestimmungen: siehe Über diese Seite