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.
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.
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.
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.
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