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
  1. Scanner auf Zeilenanfang zurücksetzen
  1. Einlesen der Daten einer Scanner-Zeile

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

Links

Copyright-Bestimmungen: siehe Über diese Seite