Aufgepfropft und fremdgegangen: PC-Handscanner voll kompatibel

Handscanner für den Atari ST sind immer noch selten für nennenswert weniger als 4 „Schumänner“ zu haben. Anscheinend mangelt es in diesem Marktsegment etwas an Konkurrenz. Die ist jedoch bei der PC-Peripherie knallhart. Was liegt also näher, als die Anschaffung eines PC-Handscanners und eine entsprechende Anpassung an den Atari ST?

Sonderangebot einer großen HiFi- und Computerkette in Mülheim/Ruhr: Beim Preis von 125 DM für einen Marstek M 105 (abgesehen von einem leicht zu ergänzenden DIP-Schalter, baugleich mit den Typen M 105 Plus, M 800, M 800 Plus, siehe Literaturhinweis) mit PC-Interface schlage ich zu. Beim Auspacken der Neuerwerbung stellt sich allerdings recht schnell Ernüchterung ein: Das 37seitige „Handbuch“ enthält hauptsächlich Angaben zur Bedienung des mitgelieferten Programms; Informationen zum Datentransfer zwischen Handscanner und PC suche ich leider vergeblich. Die Firma Marstek in Neuss kann meine Neugier ebenfalls nicht befriedigen. Sie vertreibt das taiwanische Erzeugnis nur und deutet an, daß der Hersteller selbst sich wahrscheinlich über Anschlußbelegung und Ablauf der Datenübertragung am 8poligen Scanner-Stecker nicht äußern wird.

Marstek bietet jedoch ein preislich attraktives ST-Interface an. Ich erstehe es für ca. 110 DM - ohne (optional erhältliches) 12V-Netzteil, da ich bereits ein geeignetes besitze - inkl. Software und Versandkosten direkt bei der Firma. Das beiliegende Software-Paket, „DAATAscan Professional“ ist brauchbar und beinhaltet die üblichen Möglichkeiten wie Scannen, Abspeichern (wahlweise im Degas- oder IMG-Format), Laden, Invertieren, Spiegeln, Drehen von Bildern, allein Dithering

ist hiermit nicht möglich, wenn auch im englischen Manual Gegenteiliges behauptet wird. Auch mit Druckertreibern ist das Paket nicht eben üppig ausgestattet: Wie zu erwarten, wird mein Star LC 24-10 ^ nicht speziell unterstützt, so daß die ausgedruckten Grafiken alles andere als maßstäblich sind. Naja, die Treiber für den Star fehlen oft auch bei wesentlich teureren „Weichwaren“ - und was erwartet man bei Gesamtkosten von nicht einmal 240,- DM für Scanner, Interface und Programm?

Nun: In dem 24seitigen Manual für die ST-Software steht „natürlich“ wieder nichts über den Datenaustausch zwischen dem in den ROM-Port des ST zu steckenden, ca. 9x3x5 (BxHxT) großen, „DAATAscan-PANDAAL“-Adapter und dem Rechner. Offensichtlich möchte Marstek den werten Kunden auf käufliche Programme festnageln. Was bleibt mir also anderes übrig, als „DAATAscan“ etwas näher unter die Lupe zu nehmen, möchte ich doch später einmal den Scanner auch für die Erstellung eigener EAN(Bar-)-Code- und OCR-Software verwenden.

Von grauer Theorie...

Gesagt, getan. Hier die Ergebnisse meiner Analyse, die durch ein kleines Demonstrationsprogrämmchen, das lediglich den SM-124-Monitor füllt (eine Anpassung an Farbmonitore mag der engagierte Leser bitte selbst vornehmen, das würde hier den Rahmen sprengen), etwas veranschaulicht werden: Wie bei allen Geräten, die an den ROM-Port angeschlossen werden, verbietet es sich auch hier, auf den ROM-Port zu schreiben, was allenfalls zu einem Bombenhagel führte. Die Richtung vom ST zum Scanner, die für die Synchronisation beider Geräte zweifellos erforderlich ist, wird deshalb über das Lesen von gewissen Speicherstellen realisiert. Da Adreßleitungen letztendlich eine Untergruppe der Datenleitungen sind (zwar nur in eine Richtung, aber immerhin), genügt es also, wenn man ein Byte/Wort/Doppel wort „ausliest“ und den somit erhaltenen Müll im Datenregister einfach ignoriert.

Prinzipiell läuft die Sache folgendermaßen ab:

  1. Scanner einschalten

- Lesen der Adresse $FB2000

  1. Scanner auf Zeilenanfang zurücksetzen

- Lesen der Adresse SFB3000

  1. Einlesen der Daten einer Scanner-Zeile

- Lesen der Adresse (Wort) $FAFFFE
Die Daten stecken in den unteren 8 Bits (Bit 0-7). Vor der Übernahme der Daten ist jeweils zu überprüfen, ob sie gültig sind (Bit 8 gesetzt).

Es werden nacheinander so viele Bytes eingelesen, wie es die gewünschte Bildbreite erfordert, höchstens aber so viele, daß die Scan-Breite des Geräts nicht überschritten wird.

  1. Warten auf das Zeilenende; ist Bit 9 von SFAFFFE.W gesetzt, geht es weiter mit Punkt 2 oder - falls die letzte gewünschte Scanline erreicht ist - mit Punkt 5.
  2. Scanner ausschalten - Lesen von $FB0000

Wie dieser Aufstellung leicht zu entnehmen ist, kennt das Interface zwei Register:

  1. das kombinierte Read/Status-Register $FAFFFE (Wort):
Bit  
0-7 Scanline-Daten
8 Data Strobe, gesetzt, wenn anliegende Daten gültig
9 End of Line, gesetzt, wenn Zeilenende erreicht
  1. das Command-Register $FBX***, bei dem das Nibble X folgendermaßen strukturiert ist:
Bit  
0 Carriage Return, hierdurch wird der Scanner an den Zeilenanfang gesetzt.
1 Scanner on, Beleuchtung und übrige Stromversorgung einschalten. Zwar sind Kombinationen möglich, es ist jedoch wenig sinnvoll, für CR nur Bit 0 zu setzen (wer’s mag, kann selbstverständlich auch seine Briefe in den ausgeschalteten Computer eingeben).

Die nicht aufgeführten Bits am Interface sind offensichtlich nicht belegt.

... zum Sprung in das kalte Wasser

Unter BASIC z.B. lassen sich die grundlegenden Dinge durchaus nachvollziehen. Zeitweilige Datentransferraten von ca. 111 KByte/ sec verbieten jedoch auch in Assembler eine ausschweifende Programmierung, so daß wir hier über Hochsprachen schon nicht mehr zu diskutieren brauchen. Daß die Interrupts beim Einlesen ebenfalls ausgeschaltet werden müssen, versteht sich nun von selbst. Wie das Listing zeigt, weicht die Praxis in zwei bedeutenden Punkten von der bislang behandelten Theorie ab:

Erstens benötigt der Scanner nach jedem „Wagenrücklauf" (CR) eine kleine Verschnaufpause, in der er üblicherweise nur „Schrott“ sendet. Aus diesem Grunde ist die Warteschleife first_wt eingebaut. Der Wert in D4 ist empirisch ermittelt, andere Werte können ebenfalls korrekt sein (ausprobieren!).

Zweitens wiederholt das Gerät in einigen Auflösungsstufen (wohl aus übertragungstechnischen Gründen) die gleichen Daten ein- bis dreimal (siehe Tabelle). Diese Wiederholungs-Bytes müssen natürlich wieder ausgefiltert werden, möchte man nicht seltsam verzerrte Bilder erhalten. Deshalb wird nicht jedes Byte aus der tstbusy-Schleife auch in den Bildschirm geschrieben.

Auflösung [dpi] Scanline-Breite [Bytes] davon verwertbare Bytes Anzahl der Wiederholungs-Bytes / verwertbarem Byte
100 208 52 3
200 208 104 1
300 156 156 0
400 208 208 0
500 260 260 0
600 312 312 0
700 364 364 0
800 416 416 0

Alle Werte empirisch ermittelt, also ein Ergebnis von Versuchen.


; Programm zum probeweisen Einlesen und ; Abbilden der Daten auf einen SM 124 ; vom Handscanner Marstek M 105 ; ; Assembler: Profimat (Data Becker), ; relozierbar zu assemblieren. Nicht ausdrücklich ; mit einem Extender versehene Operatoren beziehen ; sich auf den Datentyp "Wort". ; ; Autor: Thomas Maurer ; (c) MAXON Computer GmbH 1993 ; text ; Auflösung eingeben eingabe pea info(pc) ; GEMDOS-PRINT-LINE move #9,-(sp) trap #1 addq.l #6,sp move #1,-(sp) ; CONIN trap #1 addq.l #2,sp cmpi.b #'1’,d0 ; Überprüfung auf bcs eingabe ; Bereichsüberschrei- cmpi.b #'9',d0 ; tung bei der Ein- bcc eingabe ; gabe, andi #$f,d0 ; Zahlwert maskieren move d0,d7 ; und sichern, lea jtable(pc),a0 ; Anzahl der subq #1,d0 ; Schrottbytes in move.b 0(a0,d0),d0 ; einem Datenpaket move d0,datajump ; aus Tabelle, ab- ; hängig von der ; Auflösung, pea meld(pc) ; Meldung ausgeben move #9,-(sp) ; GEMDOS trap #1 ; PRINT- addq.l #6,sp ; LINE clr.l -(sp) ; Supervisormodus move #$20,-(sp) ; modus einschalten trap #1 addq.l #6,sp move.l d0,ssp_save move sr,save_sr ; SR retten ori #$700,sr ; Interrupts aus, ; die würden hier nur ; stören. ; Register vorbesetzen: ; A6 : Scanner CR ; A5 : Scanner Read data/status ; A4 : Schreibzeiger VRAM ; d1 : 8, für NOT BUSY lea $fb3000,a6 lea $fafffe,a5 moveq #8,d1 move.l $44e,a4 ; logical screenbase move #80,d3 ; Bildschirm-Byte- ; breite des SW- ; Monitors. moveq #51,d0 ; Scanline-Breite ; Breite in Bytes bei ; 100 dpi. mulu d7,d0 ; * Auflösung / 100 ; = verwertbarer An- ; teil der Scanline ; in Bytes, cmpi #81,d0 ; Mehr als 80 Bytes/ bcs.s ok ; Scanline sind nicht moveq #80,d0 ; darstellbar. ok sub d0,d3 ; Gewünschte Breite ; des Bildes (Bytes) ; = Differenz zum ; nächsten Zeilen- ; anfang. subq #1,d0 ; für DBRA move d0,b_breite move #399,line_num ; 400 Zeilen move $fb2000,d0 ; Scanner ein,d0: Schrott. move line_num,d6 ; Anzahl der zu ; scannenden Linien. ; Es folgen nun die elementaren ; Lesestrukturen cr move (a6),d0 ; CR auf Scanner aus- ; geben, d0: Schrott. first_rd move (a5),d0 ; Das erste Datenbyte btst d1,d0 ; der jeweiligen Scan- beq first rd ; line ist Schrott, moveq #20,d4 ; Scanner muß sich first_wt dbra d4,first wt ; erst einmal "beruhigen". move b_breite,d7 ; Bytebreite der ; Scanline exclusive ; Schrottbytes waitbusy move datajump(pc),d4 ; Anzahl der ; Schrottbytes in ; jedem Datenpaket tstbusy move (a5),d0 ; Datenregister btst d1,d0 beq tstbusy ; Scanner busy dbra d4,tstbusy ; war Schrott, also ; noch einmal not d0 ; verwertbares Byte des Daten- ; pakets invertieren, da Weiß ; vom Scanner einem gesetzten ; Bit entspricht, bei ATARI ; dies aber einen schwarzen ; Punkt erzeugt. move.b d0,(a4)+ ; Ab in den Bildschirm dbra d7,waitbusy ; Nächstes Datenpaket adda d3,a4 ; Differenz zur nächsten ; Bildschirmzeile ergänzen, wait_le btst #1,(a5) ; Warten auf das Ende beq wait_le ; der Scannerzeile, dbra d6,cr ; zur nächsten Seile move $fb0000,d0 ; Scanner aus. move save_sr(pc),sr ; Statusregister ; restaurieren move.l ssp_save(pc),-(sp) ; Supervisor- move #$20,-(sp) ; modus trap #1 ; ausschalten addq.l #6,sp clr -(sp) ; GEMDOS TERM trap #1 data info dc.b $1b,'E' ; clear screen dc.b 'Scannen mit Marstek M 105 in ' dc.b 'allen 8 Auflösungsstufen',$d,$a dc.b '-------------------------------' dc.b '-----------------------', $d, $a, $a dc.b 'Auflösung eingeben;',$d,$a,$a dc.b ' (1) - (8) für (1)00' dc.b 'bis (8)00 dpi',$d,$a,0 meld dc.b $1b,'E' ; clear screen dc.b 'Vor dem Scannen bitte die einge-' dc.b 'stellte Auflösung am Scanner ' dc.b 'selbst uberprüfen.',$d,$a dc.b 'Sie muß mit der gerade eingege-' dc.b 'benen übereinstimmen.',$d,$a,$a dc.b 'Es kann losgehen!’,0 jtable dc.b 3,1,0,0,0,0,0,0 bss datajump ds.w 1 ; Anzahl der Schrottbytes je ; Datenpaket ssp_save ds.l 1 ; alter Stackpointer save_sr ds.w 1 ; altes Statusregister b_breite ds.l 1 ; tatsächliche Bildbreite line_num ds.l 1 ; Anzahl der Bildzeilen end

Thomas Mäurer
Links

Copyright-Bestimmungen: siehe Über diese Seite