← ST-Computer 08 / 1988

Wenn der Atari ST mit der Gabi anbandelt (Teil 2)

Projekt

In der heutigen Ausgabe wollen wir uns weiter mit der Verbindung von ATARI ST und TA-Gabriele 9009 bzw. kompatiblen Schreibmaschinen beschÀftigen. Doch bevor wir uns in das Reich der Bits und Bytes begeben, möchte ich die Aufgabenstellung definieren:

Gesucht wird ein Programm, das im Auto-Ordner mitgebootet wird und sich resistent im Speicher hĂ€lt. Dieses Programm “verbiegt” die Druckerausgabe auf eine Routine, die die spezielle Aussteuerung der Schreibmaschine entsprechend der in der letzten Ausgabe aufgefĂŒhrten Befehlssequenzen realisiert.

Außerdem installiert es eine Interruptroutine, die dafĂŒr sorgt, daß die Schreibmaschine ĂŒber die entsprechenden Tasten von der Schreibmaschinentastatur aus zwischen den BetriebszustĂ€nden ONLINE und OFFLINE umgeschalten werden kann.

Das Programm sorgt auch fĂŒr die Verwaltung der Druckschlittenposition und fĂŒr die Realisierung einiger spezieller Funktionen.

Alle diese nachfolgend aufgelisteten Funktionen werden durch Codes bzw. Sequenzen gesteuert, die vollkompatibel zur Original-Interfacebox von TA sind. Dadurch ist es möglich, einen entsprechenden Druckertreiber mitzuverwenden. Es ist durch Änderungen im Programm aber auch möglich, eine Anpassung an beispielweise EPSON-Sequenzen zu erreichen.

ASCII-Code-Befehle

Folgende Steuerzeichen innerhalb des ASCII-Codes werden von der Druckroutine erkannt und realisiert:

  • 08H : Backspace: Der Druckschlitten wird um eine Schreibteilung nach links bewegt.
  • 0AH : Linefeed: Dieser Code löst das Weiterschalten der Schreibmaschine um eine Zeile aus.
  • 0CH : Form Feed: Dieser Befehl fĂŒhrt ĂŒblicherweise dazu, daß das Papier zum Anfang der nĂ€chsten Seite transportiert wird (Endlospapier). Da die Schreibmaschine allerdings nur Einzelblattverarbeitung erlaubt, wurde die Funktion im Programm so realisiert, daß die Schreibmaschine beim Auftreten des Befehls in den OFFLINE-Modus geschaltet wird. Sie wartet dann, bis ein neues Blatt eingespannt und ĂŒber die ONLINE-Taste auf der Schreibmaschinentastatur das Weiterdrucken veranlaßt wurde. - 0DH : Carriage Return: Der Druckschlitten wird zum linken Rand zurĂŒckbewegt.
  • 1BH: ESCAPE: Erstes Byte einer folgenden Befehlssequenz.
  • 20H: Space: Leerzeichen entsprechend der eingestellten Schreibteilung. Um eine Geschwindigkeits-Optimierung bei mehreren aufeinanderfolgenden Leerzeichen zu erreichen, werden diese nicht einzeln ausgefĂŒhrt, sondern zu einer schnelleren direkten Bewegung zusammengefaßt.

Andere Kontrollbytes. die im Bereich der ASCII-Codes bis 20H (z.B. DCI/3 oder HT) liegen, werden ĂŒblicherweise nicht benutzt und deshalb von unserem Programm einfach unterdrĂŒckt.

ESCAPE-Sequenzen

Unter ESC-Sequenz versteht man eine Reihenfolge von Steuerbefehlen, die mit einem ESC-Zeichen (=1BH) beginnen und druckerspezifische Funktionen (z.B. VerĂ€nderung der Schreibteilung) steuern. Leider sind diese Sequenzen fĂŒr die verschiedenen Drucker nicht standardisiert. Unser Programm richtet sich nach den von der Original-Interfacebox vorgegebenen ESC-Sequenzen. Allerdings wurde nur eine Untermenge der von der IFD1 vorgegebenen Sequenzen realisiert, jedoch genĂŒgen diese, um eine leistungsfĂ€hige FunktionalitĂ€t zu erreichen.

  • ESC 9 (= 1BH + 39H): Linken Rand setzen

ErlÀuterung: Der linke Rand wird auf die Position gesetzt, auf der gerade der Druckschlitten steht.

  • ESC D (= 1BH + 44H): Hochstellen

ErlĂ€uterung: Die Schreibwalze wird um eine halbe Grundzeile zurĂŒckgedreht, wodurch ein Hochstellen der Zeichen auf dem Papier erfolgt.

  • ESC U (= 1BH + 55H): Tiefstellen

ErlÀuterung: Die Schreibwalze wird um eine halbe Grundzeile vorgedreht, wodurch ein Tiefstellen der Zeichen auf dem Papier erfolgt.

  • ESC LF (= 1BH + 0AH): Linefeed rĂŒckwĂ€rts

ErlĂ€uterung: Die Schreibwalze wird entsprechend dem eingestellten Zeilenabstand eine Zeile zurĂŒckbewegt.

  • ESC W (= 1BH + 57H): Fettschrift einschalten

ErlĂ€uterung: Alle anschließenden Zeichen werden in Fettdruck dargestellt. Dies erfolgt dadurch, daß jedes Zeichen zweimal abgeschlagen und zwischen den AnschlĂ€gen eine minimale Horizontalbewegung (1/120”) ausgefĂŒhrt.

  • ESC & (= 1BH + 26H): Fettschrift ausschalten

ErlÀuterung: Alle nachfolgenden Zeichen werden wieder ohne Fettdruck abgedruckt.

  • ESC E(= 1BH + 45H): Unterstreichen einschalten

ErlÀuterung: Bei allen nachfolgenden Zeichen wird zusÀtzlich zum Zeichenabdruck auch ein Unterstreichstrich abgedruckt.

  • ESC R(= 1BH + 52H): Unterstreichen ausschalten

ErlÀuterung: Alle nachfolgenden Zeichen werden wiederohne Unterstreichen abgedruckt.

  • ESC US x (= 1BH + 0BH + x): Schreibteilung setzen auf x-Schritte

ErlĂ€uterung: Die Schreibteilung wird auf 12(12 Zeichen pro Zoll) vorbesetzt. Mit dieser Sequenz ist es möglich, die Schreibteilung im Bereich von 1/120" bis 255/120”-Schritten einzustellen.

Die Sequenzdefinition der Interface-Box sagt aus unerklĂ€rlichen GrĂŒnden, daß als Schrittzahl (x + 1) ĂŒbergeben werden muß.

Nachfolgend ist die Zuordnung der Schrittzahlen zu den gebrĂ€uchlichsten Schreibteilungen aufgefĂŒhrt:

Schreibteilung Schrittzahl X

 10                 13
 12                 11
 15                  9
  6                 23
  • ESC RS x(= 1BH + 1EH + x): Zeilenabstand setzen auf (x + 1) Schritte ErlĂ€uterung: Der Zeilenabstand ist auf die genormte Grundzeile von 1/6“ voreingestellt. Durch die Sequenz ist es möglich, den Zeilenabstand zwischen 1/96” und 255/96" einzustellen. FĂŒr die Grundzeile st als x beispielsweise der Wert 17 einzusetzen.

Absichtlich nicht realisiert wurden die ESC-Sequenzen fĂŒr bidirektionalen Druck (Druck links - rechts - links usw.), da die Schreibmaschine Gabriele 9009 zwar prinzipiell von rechts nach links drucken kann, jedoch aus internen GrĂŒnden nach jedem Schritt nach links eine seltsame RĂŒttelbewegung ausfĂŒhrt Damit wird der durch den bidirektionellen Druck gewonnene Zeitvorteil mehr als aufgebraucht.

Nicht verwirklicht wurde auch die Funktion Proportionaldruck. Proportionaldruck bedeutet, daß jedem Zeichen ein spezifischer Horizontalabstand zugeordnet ist; der Abstand zwischen “i” ist somit viel schmaler als zwischen “M”. Wir haben auf die Realisierung der Funktion verzichtet, da diese nur in Zusammenarbeit mit speziellen TypenrĂ€dern ansprechende Ergebnisse bringt und andererseits großen Aufwand im Programm sowie in entsprechenden Treibern bedeutet hĂ€tte.

Das nachfolgende aufgelistete Programm wurde inAssembler erstellt, um möglichst “maschinennah" arbeiten zu können. Die enthaltenen Kommentare sollten genĂŒgen, die verschiedenen Programmabschnitte nachvollziehbar zu machen. Es wird somit auch möglich sein, bei Bedarf kleinere Modifikationen einzubringen.

Da der ATARI ST ĂŒber die serielle Schnittstelle wĂ€hrend des Hochlaufs oft Undefiniertes aussendet, ist es sinnvoll, die angeschlossene Schreibmaschine erst nach abgeschlossenem Boot-Vorgang einzuschalten. Denn empfĂ€ngt die Schreibmaschine Zeichen, mit denen sie nichts anfangen kann, ignoriert sie diese nicht immer, sondern stĂŒrzt manchmal auch ab, was nur durch erneutes Aus-/ Einschalten der Schreibmaschine behoben werden kann.

Bevor man mit dem Drucken beginnen kann, muß man die Schreibmaschine durch BetĂ€tigen der ONL-Taste (oder entsprechende Tastenkombination) auf ONLINE schalten.

Obwohl die serielle Verbindung physika-Hsch ĂŒber die V.24-Schnittstelle erfolgt,ist als logische Schnittstelle die voreingestellte Parallelschnittstelle zu verwenden. FĂŒr WORDPLUS-Benutzer habe ich noch einen kleinen Treiber erstellt. der die vorgenannten ESC-Sequenzen beim Ausdrucken automatisch ansteuert.

Eine Code-Umsetzung der Schreibzeichen ist nicht erforderlich, da unser "IFD-EMULATOR" schon alle druckfÀhigen Zeichen ansteuert.

*****************************************************************
*                                                               *
* Nachbildung der INTERFACEBOX IFD1 durch Software im ST	    *
* (Einsatz des deutschen Typenrades Grp. 01)                    *
* *
* Diese Datei enthĂ€lt Tabellen bezĂŒglich der CODE SEQUENZEN und *
* des Zeichensatzes. Dadurch ist es möglich, die verschiedenen  *
* Funktionen und den Zeichensatz anzupassen.                    *
*                                                               *
*****************************************************************
	

*
* Name of printer
* ===============
*
IFD 1 - Emulator 
*
* Miscellaneous configurable variables
* ====================================
*
* 1: printer type, 0=dot matrix, 1=daisy wheel
*    Note if printer type is 0 the following 4 variables are never used.
* 2: unit width of one character
* 3: unit height of one line
* 4: Approximate middle of carriage after formfeed
* 5: Carriage shift for bold overstrike
*
0,0,0,0, 0,0 

*
* Printer characteristics
* =======================
*
* This table specifies the printer command sequences.
* If the top bit of a code is set, then this indicates the position
* of a parameter passed to the printer. The code whose top bit is set
* in this table is added to the parameter passed before being sent to the
* printer. It is not used in all command sequences, only in those where
* the printer requires a variable value such as the length of a vertical
* tab.
*
* 0 * Character width
1, D, A * Linefeed WITH return
* 2 * Forward print
* 3 * Reverse print
* 4 * Vertical tab to line
* 5 * Absolute horizontal tab
6 * Draft bold on
7 * Draft bold off
8, 1B, 57 * Near Letter Quality (NLQ) bold on
9, 1B, 26 * NLQ bold off
A * Draft italic on
B * Draft italic off
C * NLQ italic on
D * NLQ italic off
E * Draft light on
F * Draft light off
* 10, 1B, 78, 0 * NLQ light on
* 11, 1B, 78, 1 * NLQ light off
12, 1B, 44		* Draft superscript on
13, 1B, 55		* Draft superscript off
14, 1B, 44		* NLQ superscript on
15, 1B, 55		* NLQ superscript off
16, 1B, 55		* Draft subscript on
17, 1B, 44		* Draft subscript off
18, 1B, 55		* NLQ subscript on
19, 1B, 44		* NLQ subscript off
1A
1B 				* Draft underline off
1C, 1B, 45		* NLQ underline on
1D, 1B, 52		* NLQ underline off
1E, 0C,0D		* Formfeed
1F, 12			* Horizontal Initialisation
20,0D			* Termination: printer reset
21,0D			* Termination: printer reset
22,08					* Backspace
23,13					* Carriage Return
* 24					* Form length in lines
* 25					* Set line feed to N units
* 26					* Start graphics (mode 0)
* 27					* Reserved
28,1B,1F,0D				* Draft Pica (10 cpi)
29,1B,IF,0D				* NLQ Pica (10 cpi)
2A,1B,IF,0B				* Draft Elite (12 cpi)
2B,1B,1F,0B				* NQL Elite (12 cpi)
2C,1B,1F,9				* Draft Condensed (15 cpi)
2D,1B,1F,9				* NQL Condensed (15 cpi)
2E,1B,1F,15				* Draft Expanded (6 cpi)
2F,1B,1F,15				* NQL Expanded (6 cpi)
* 30					* Black ink
* 31					* Magenta ink
* 32					* Cyan ink
* 33					* Yellow ink
0						* NULL termination byte

*
* Translation Table
* =================
*
* Diese Tabelle ĂŒbersetzt einfache ATARI Eingangscodes in vielfache
* Druckercodes, dies ermöglicht den Entwurf eines erweiterten Zeichen-
* satzes usw. .
*
* Da der Zeichensatz schon vom Steuerprogramm verwirklicht wird, ist es
* hier nicht nötig, nochmals eine Übersetzung durchzufĂŒhren.

Abb. 1: Tabelle der CODE-SEQUENZEN


*******************************************************
* IFD 1 - EMULATOR fĂŒr ATARI ST                       *
*                                                     *
* Diese Routine verbiegt d.Druckerausgabe a.ein Kon-  *
* vertierprogramm, das d.ASCII-Code i.f. die Schreib- *
* maschine Gabriele 9009 verstÀnd1.Steuerbefehle um-  *
* setzt. Die Kommunikation m.d.Schreibmaschine erfolgt*
* o.Spooler-Pufferung ĂŒ.d.serielle V.24-Verbindung.   *
*******************************************************

	move.b #16,zeile 
	move.b #10,teilung
	move.l 4(sp),a0 ; Groesse des Programms
	move.l #$100,d6 ; berechnen
	add.l 12(a0),d6
	add.l 20(a0),d6
	add.l 28(a0),d6
	move.l d6,-(sp) ; Ergebnis auf Stack Zwischenlagern

	clr.l -(sp) ; In SUPER-Modus schalten
	move.w #$20,-(sp) 
	trap #1 
	add.l #6,sp
	move.l d0,-(sp) ; Alten Stack merken

	move.l #trap13,-(sp) ; TRAP13 "verbiegen"
	move #45,-(sp)
	move #5,-(sp)
	trap #13
	addq.l #8,sp
	move.l d0,tr_save ; alte Sprungadresse merken

	move.l #em_int,-(sp) ; Interruptroutine installieren, 
	move.w #12,-(sp) ; die ausgelöst wird, wenn von der SM ein 
	move #13,-(sp) ; Zeichen empfangen wurde
	trap #14 ; -> Offline - Online
	addq.l #8,sp

	bsr init ; Intialisierungsroutine
	move.l (sp)+,d1 ; In USER-Modus zurueckschalten
	move.l d0,-(sp) 
	move.w #$20,-(sp) 
	trap #1 
	addq.l #6,sp

	move.l (sp)+,d6 ; Programmgroesse zurĂŒckholen

	clr -(sp) ; Programm im Speicher halten
	move.l d6,-(sp) 
	move #$31,-(sp) 
	trap #1

trap13: move.l sp,a2 ; neue Trap 13-Routine
	btst #5,(sp) ; jetzt abprĂŒfen, ob
	bne super ; Druckerangesprochen ist
	move.l usp,a2 
	subq #6,a2 
super: cmp #3,6(a2)
	bne normal ; wenn nicht —> alte Routine
	cmp #0, 8(a2)
	bne normal
	movem.l d1-d7/a0-a6,-(sp)
	move.l $4a2,a1
	move (sp)+,-(a1)
	move.l (sp)+,-(a1)
	move.l a1,$4a2 ; Drucker ist gemeint auszu-
	move 10(a2),d1 ; gebendes Zeichen nach d1
	move #$2700,sr
	cmp.w #0,esc_flag ; Folgebyte in ESC-Sequenz? 
	bne esc_folg ; Ja —> verzweigen 
	cmp.b #$20,d1 ; Druckbares Zeichen?
	bls so_zei ; Nein —> verzweigen
	cmp.w #0,step_li ; Sind noch Leerschritte nachzuholen? 
	bne spa_nach ; Ja —> verzweigen
drck: lea zei_satz,a2 ; Adresse f.Tabelle nach a1
	and.1 #$FFFF,d1
	sub.w #$21,d1 ; Offset von ASCII-Code subtrahieren 
	lsl.w #1,d1 ; Rest mit 2 multiplizieren
	add.l d1,a2 ; Als Offset zu Tabellenzeiger addieren
	cmp.w #0,son_flag ; Ist eine Sonderfunktion eingeschaltet ? 
	bne so_druck ; Ja —> verzweigen
narma: move.b (a2)+,d1 ; Typenrad-Code aus Tabelle
	bsr print ; holen und an SM senden
	move.b (a2),d1 ; Abschlag-Code aus Tabelle
	bsr print ; holen und an SM senden
gedr: move.b teilung,d0
	and.w #$FF,d0
	add.w d1,spalte ; Spaltenzaehler inkrem,
	moveq #-1,d0 ; kein Fehler aufgetreten
	bra exit ; Aussprung

spa_nach: ; Umwandeln von vorher nicht ausgedruckten 
	move.l d1,-(sp) ; Leerschritten in Direktbewegung 
	move.w step_li,d1 ; Anzahl der auszufĂŒhrenden Leerschritte
	lsr #8,d1
	bset #7,d1 ; Befehl fĂŒr SM bilden
	bset #6,d1
	bclr #5,d1
	bclr #4,d1
	bsr print
	move.w step_li,d1 ; High_byte fĂŒr direkte Bewegung
	bsr print
	move.w #0,step_li ; Low_byte fĂŒr direkte Bewegung
	move.l (sp)+,d1
	bra drck ; zurĂŒck —> normal drucken

so_druck:
	move.l a2,a4
	btst #1,son_flag ; unterstreichen eingeschaltet? 
	beq fett ; Nein —> Weiter mit Fettdruck-Abfrage
	move.b #$33,d1 ; Typenradcode fĂŒr bsr print
	move.b #$10,d1 ; Abschlagscode und Totzeichenkennung
	bsr print

fett: btst #2,son_flag ; fett eingeschaltet?
	beq narma ; Nein —> Normal weiter
	move.b (a2)+,d1 ; Typenradcode aus Tabelle holen 
	bsr print
	move.b (a2),d1 ; Abschlagscode aus Tabelle holen
	bclr #7,d1 ; Horizontalbewegung unterdrĂŒcken
	bsr print
	move.b #$83,d1 ; Mikrostep (1/120") ausfĂŒhren 
	bsr print 
	move.b #1,d1 
	bsr print
	move.b (a2),d1 ; War es wirklich ein druckbares Zeichen
	cmp.b #0,d1
	beq gedr ; Nein —> Aussprung
	sub.l #1,a2 ; Ja —> Zeichen nochmal drucken
	bra narma

esc_folg:
	cmp.w #1,esc_flag
	bne esc_3byt ; 3. oder 4. Byte einer ESC-Folge
	move.w #0,esc_flag
	cmp.b #$39,d1 ; Linken Rand setzen?
	beq li_rand ; Ja —> verzweigen
	cmp.b #$44,d1 ; Hochstellen?
	beq hochst ; Ja —> verzweigen
	cmp.b #$55,d1 ; Tiefstellen?
	beq tiefst ; Ja —> verzweigen
	cmp.b #$0A,d1 ; ZeilenrĂŒckschritt?
	beq lf_back ; Ja —> verzweigen
	cmp.b #$45,d1 ; Unterstreichen ein?
	beq unt_ein ; Ja —> verzweigen
	cmp.b #$52,d1 ; Unterstreichen aus?
	beq unt_aus ; Ja —> verzweigen
	cmp.b #$57,d1 ; Fettdruck ein?
	beq fett_ein ; Ja —> verzweigen
	cmp.b #$26,d1 ; Fettdruck aus?
	beq fett_aus ; Ja —> verzweigen
	cmp.b #$1F,d1 ; HMI setzen?
	beq hmi1 ; Ja —> verzweigen
	cmp.b #$05,d1 ; VMI setzen?
	beq vmi1 ; Ja —> verzweigen
	bra exit ; andere ESC-Sequenzen kenn ich nicht!!!

esc_3byt:
	cmp.w #2,esc_flag ; HMI-Sequenz?
	bne vmi2 ; Nein —> verzweigen
	subq.b #1,d1 ; HMI = N-1
	move.b d1,teilung ; Neue Teilung merken
	move.b #$80,d4 ; Neue Teilung an SM schicken
	bsr senden
	move.b teilung,d4
	bsr senden
	move.w #0,esc_flag ; Flag löschen 
	bra exit

vmi2: cmp.w #3,esc_flag ; VMI-Sequenz?
	move.w #0,esc_flag ; Flag löschen 
	bne exit ; Nein —> dann unbekannt
	subq.l #1,d1 ; VMI = N-l
	move.b d1,zeile ; Neue Schrittzahl fĂŒr LF merken
	bra exit

li_rand: move.w #0,spalte ; SpaltenzÀhler auf Null setzen
	bra exit

hochst: move.w #$f0,d1 ; Vertikale Bewegung um 8/96"
	bsr print ; = 0,5 Grundzeilen zurĂŒck
	move.w #8 ,d1 
	bsr print 
	bra exit

tiefst: move.w #$D0,d1 ; Vertikale Bewegung um 8/96"
	bsr print ; = 0,5 Grundzeilen vorwÀrts
	move.w #8,d1 
	bsr print 
	bra exit

lf_back: move.w #$f0,d1 ; Vert.Bewegung u.normalerweis«
	bsr print ; 16/96" = 1 Grundzeile zurĂŒck
	move.b zeile,d1 
	bsr print 
	bra exit
unt_ein: bset #1,son_flag ; Bit 1 fĂŒr Unterstreichen setzen
	bra exit

unt_aus: bclr #1,son_flag ; Bit 1 fĂŒr Unterstreichen löschen
	bra exit

fett_ein: bset #2,son_flag ; Bit 2 fĂŒr Fettschrift setzen
	move.b #$80,d1 ; Horizontalschritt auf Teilung-1
	bsr print ; Teilung-1 anpassen
	move.b teilung,d1
	subq.b #1,d1
	bsr print
	bra exit

fett_aus: bclr #2,son_flag ; Bit 2 fĂŒr Fettschrift löschen
	move.b #$80,d1 ; Horizontalschritt auf
	bsr print ; eingestellte Teilung
	move.b teilung,d1 ; anpassen
	bsr print 
	bra exit

hmi1: move.w #2,esc_flag ; Flag fĂŒr HMI-Sequenz setzen
	bra exit

vmi1: move.w #3,esc_flag ; Flag fĂŒr VMI-Sequenz setzen
	bra exit

		; Abfrage nach Sonderzeichen 

so_zei: cmp.b #$20,d1 ; ASCII-Code = 32
	beq space ; Ja —> Leerschritt
	cmp.b #13,d1 ; ASCII-Code = 13
	beq cr ; Ja —> Carriage Return
	cmp.b #10,d1 ; ASCII-Code = 10
	beq lf ; Ja —> Linefeed
	cmp.b #$1B,d1 ; ASCII-Code = 27
	beq esc ; Ja —> ESC-Zeichen —> Flag setzen
	cmp.b #8,d1 ; ASCII-Code = 8
	beq backsp ; Ja —> Backspace
	cmp.b #12,d1 ; ASCII-Code = 12
	beq formfeed ; JA —> Formfeed
	bra exit ; Andere Sonderzeichen kenn ich nicht

esc: move.w #1,esc_flag / Flag fĂŒr erstes Byte aus Sequenz setzen
	bra exit

space:
	move.b teilung,d1 ; Leerschritt nicht direkt ausfĂŒhren,
	and.l #$FF,d1 ; sondern fĂŒr spĂ€ter zusammenfassen 
	add.w d1,step_li ; und in "step_li" merken 
	add.w d1,spalte 
	bra exit

backsp: move.w #$84,d1 ; Leerschritt nach links —> direkt ausfĂŒhren 
	bsr print ; direkt ausfĂŒhren
	move.b teilung,d1 
	and.w #$ff,d1 
	sub.w d1,spalte 
	move.w #0,d1 
	bsr print 
	bra exit

cr: move.w spalte, d0 ; Carriage-Return ausfĂŒhren, dabei auch 
			; noch nicht ausgefĂŒhrte Leerschritte 
	sub.w step_li,d0 ; berĂŒcksichtigen 
	move.w # 0,step_li 
	or.w #$e000,d0 
	move.w d1,d1 
	lsr #8,d1 
	move.w d1,-(sp) 
	bsr print 
	move.w (sp)+,d1 
	and.w #$FF,d1 
	bsr print
	move.w #0,spalte ; SpaltenzĂ€hler zurĂŒcksetzen 
	bra exit

lf: move.w #$D0,d1 ; Linefeed ausfĂŒhren, Anzah]
	bsr print ; der Schritte steht in #zei1
	move.b zeile,d1 
	bsr print 
	bra exit

formfeed:
	move.b #$a3,d1 
	bsr print 
	move.b #0,d1 
	bsr print 
	
wait: bsr lesen
	cmp.b #1,d5 
	bne wait 
	move.b #$a2,d1 
	bsr print 
	move.b #0,d1 
	bsr print
	bra exit

exit :
	move.w onl_flag,d0 
	cmp.w #1,d0 
	bne probl 
	moveq #-1,d0 
	bra exit1 

probl: moveq #0,d0
exitl: move.l $4a2,a1
	move.l (a1)+,-(sp)
	move (a1)+,-(sp) 
	move.l a1,$4a2
	movem.l (sp)+,d1-d7/a0-a6 
	move #$2300,sr 
	rte

normal:
	cmp #8,6(a2)
	bne norml
	cmp #0,8(a2)
	bne norm1

	moveq #-1,d0
	move.w onl_flag,d2 
	cmp.w #1,d2 
	bne probl1 
	movea.l #$fffa01,a3 
	move.b (a3),d2 
	btst #2,d2 
	beq platz

probll: moveq #0,d0

platz: rte

norm1: move.l tr_save,a0
	jmp (a0)

print: move.b d1,d4
	bsr senden
	rts

; **************************************************** 
em_int: ; Interrupt-routine, die von
		move #$2700,sr ; der SM ausgelöst wird 
		MOVEM.L D0-D6/A0-A3,-(SP)
		bsr lesen ; Empfangenes Zeichen lesen
		cmp.b #1,d5 ; Wurde die Online-TastegedrĂŒckt?
		bne nionline ; Nein —> weitere Abfrage 
		move.w onl_flag,d5 ; Ist die SM schon ONLINE? 
		cmp.w #1,d5
		beq ni_line ; Ja —> nichts machen
		bsr online ; Nein —> Online schalten
		move.w #1,onl_flag ; Flag setzen 
		bra fertig 
nionline:
		cmp.b #2,d5 ; Wurde die OFFLINE-Taste gedrĂŒckt' 
		bne ni_line ; Nein —> nichts machen 
		move.w onl_flag,d5 ; Ist SM noch OFFLINE? 
		cmp.w #0,d5
		beq ni_line ; Ja —> nichts machen 
		bsr offline ; Nein —> Offline schalten 
		bsr offline
		move.w #0,onl_flag ; Flag zurĂŒcksetzen 
		bra fertig
ni_line:
		move.b #0,d4 ; zwei "dummy-Zeichen" senden
		bsr senden
		move.b #0,d4
		bsr delay2
		bsr senden
		bsr delay2
fertig:
		move.l #$FFFA0F,a0 ; Interrupt-Service-Bit löschen
		bclr #4,(a0)
		movem.l (sp)+,d0-d6/a0-a3
		move #$2300,sr
		rte

online:
		MOVEM.L D0-D7/A0-A4,-(SP) 
		bsr raus 
		bsr delay2 
		lea onl_tab,a1
		move.l #tab_end-onl_tab-1,d0

loop9:
		move.b (a1)+,d4
		bsr senden
		bsr delay1
		move.b #0,d4
		bsr senden
		bsr delay2
		bsr raus
		dbra d1,loop9
		movem.l (sp)+,d1-d7/aO-a4
		bsr delay2
		move.b #$82,d4
		bsr senden
		bsr delay1
		move.b #$lF,d4
		bsr senden
		bsr delay2
		move.b #$80,d4
		bsr senden
		bsr delay1
		move.b teilung,d4
		bsr senden
		bsr delay2
		move.w #0,spalte
		move.w #0,esc_flag
		move.w #0,son_flag
		rts

**************************************************
offline:
		lea offl_tab, a1
		move.w #tab_end2-offl_tab-1,d0 
		move.w #0,d6

loop1: move.b (a1)+,d4
		bsr senden 
		bsr delay2 
		dbra d1,loop1 
		rts

************************************************** 
senden:
		movea.l #$fffa01,a3 
		move.b (a3),d7 
		btst #2,d7 
		bne senden
send1:
		movea.l #$fffa2f,a3 
		move.b d4,(a3)
send2:
		movea.l #$fffa01,a3 
		move.b (a3),d7 
		btst #2,d7 
		beq send2 
		rts
lesen:
		move.w #100,d6 
les1: sub #1,d6
		cmp.w #0,d6 
		beq raus
		movea.l #$fffa2b,a3 
		move.b (a3),d5 
		and.w #$80,d5 
		cmp.b #0,d5 
		beq les1
raus:
		movea.l #$FFFa2F,a3 
		move.b (a3),d5 
		and.l #$FF,d5
		rts
delay1:
		move.l d0,-(sp) 
		move.l #$3fff,d0
loop2:
		dbra d1,loop2 
		move.l (sp)+,d0 rts
delay2:
		move.l d0,-(sp) 
		move.l #$ffff,d0
loop3:
		move.l d1,d1 
		move.l d1,d1 
		dbra d1,loop3 
		move.l (sp)+,d0 
		rts
init:
		move.w #-1,-(sp) 
		move.w #-1,-(sp) 
		move.w #-1,-(sp) 
		move.w #-1,-(sp) 
		move.w #2,-(sp) 
		move.w #2,-(sp) 
		move.w #15,-(sp) 
		trap #14 
		add.l #14,sp

		move.w #1,-(sp) 
		move.w #26,-(sp) 
		trap #14 
		addq.l #4,sp

		move.w #10,-(sp) 
		move.w #26,-(sp) 
		trap #14 
		addq.l #4,sp

		move.w #9,-(sp) 
		move.w #26,-(sp) 
		trap #14 
		addq.l #4,sp

		move.w #11,-(sp) 
		move.w #26,-(sp) 
		trap #14 
		addq.l #4,sp 
		rts

		move.w #2,-(sp) 
		move.w #26,-(sp) 
		trap #14 
		addq.l #4,sp
	
	.data 
onl_tab:
		dc.b $A1, $A4, $A2, 0
tab_end:
		move.w d1,d1 
offl_tab:
		dc.b $A3,0,$A0,0 
tab_end2:
		move.w d0,d0

onl_flag: dc.w 0

zei_satz:
		dc.b $3E,$92 ; !
		dc.b $2B,$90
		dc.b $4C,$99 ; #
		dc.b $27,$97 ; $
		dc.b $43,$97 ; %
		dc.b $22,$99 ; &
		dc.b $0E,$8C
		dc.b $3A, $92 ; (
		dc.b $31,$92 ; )
		dc.b $29,$92 ; *
		dc.b $0F,$90 ; +
		dc.b $02,$8E
		dc.b $03,$8E
		dc.b $01,$8C
		dc.b $3C,$92 ; /
		dc.b $19,$94 ; 0
		dc.b $10,$94 ; 1
		dc.b $11,$94 ; 2
		dc.b $12, $94 ; 3
		dc.b $13,$94 ; 4
		dc.b $14,$94 ; 5
		dc.b $15,$94 ; 6
		dc.b $16,$92 ; 7
		dc.b $17,$97 ; 8
		dc.b $18,$94 ; 9
		dc.b $36,$90
		dc.b $35, $90
		dc.b $4A,$92 ; <
		dc.b $34,$92
		dc.b $0D,$92 ; >
		dc.b $2D,$94 ; ?
		dc.b $40,$99 ; §
		dc.b $24,$99 ; A
		dc.b $1C,$99 ; B
		dc.b $2A,$97 ; C
		dc.b $2C,$99 ; D
		dc.b $1A,$97 ; E
		dc.b $1D,$94 ; F
		dc.b $45,$99 ; G
		dc.b $39,$97 ; H
		dc.b $2F,$92 ; I
		dc.b $42, $94 ; J
		dc.b $3B,$97 ; K
		dc.b $26,$94 ; L
		dc.b $37,$99 ; M
		dc.b $2E,$99 ; N
		dc.b $3D,$99 ; O
		dc.b $1E,$99 ; P
		dc.b $41,$99 ; Q
		dc.b $28,$99 ; R
		dc.b $1F,$97 ; S
		dc.b $25,$94 ; T
		dc.b $30,$99 ; U
		dc.b $21,$94 ; V
		dc.b $32,$99 ; W
		dc.b $3F,$94 ; X
		dc.b $23,$94 ; Y
		dc.b $20,$97 ; Z
		dc.b $3A,$92 ; ( fĂŒr [
		dc.b $29,$92 ; ; fĂŒr \
		dc.b $31,$92 ; ) fĂŒr ]
		dc.b $0C,$8C
		dc.b $33,$90
		dc.b $48,$8C
		dc.b $5E,$94 ; a
		dc.b $62,$97 ; b
		dc.b $58,$92 ; c
		dc.b $60,$97 ; d
		dc.b $5D,$94 ; e
		dc.b $0B,$92 ; f
		dc.b $59,$97 ; g
		dc.b $57,$94 ; h
		dc.b $5F,$92 ; i
		dc.b $07,$92 ; j
		dc.b $55,$94 ; k
		dc.b $05,$92 ; 1
		dc.b $06,$97 ; m
		dc.b $5A,$94 ; n
		dc.b $63,$94 ; o
		dc.b $56,$97 ; p
		dc.b $4F,$97 ; q
		dc.b $5B,$92 ; r
		dc.b $5C,$94 ; s
		dc.b $4D,$92 ; t
		dc.b $61,$94 ; u
		dc.b $04,$92 ; v
		dc.b $08,$94 ; w
		dc.b $4E,$92 ; x
		dc.b $54,$94 ; y
		dc.b $64,$92 ; z
		dc.b $3A,$92 ; (
		dc.b $2F,$92 ; I
		dc.b $31,$92 ; )
		dc.b $83,0 ; nicht auf TR vorhanden
		dc.b $83,0 ; nicht auf TR vorhanden
		dc.b $83,0 ; nicht auf TR vorhanden
		dc.b $51, $97 ; ĂŒ
		dc.b $83,0 ; nicht auf TR vorhanden
		dc.b $83,0 ; nicht auf TR vorhanden
		dc.b $53,$97 ; À
		dc.b $83,0 ; nicht auf TR vorhanden
		dc.b $83,0 ; nicht auf TR vorhanden
		dc.b $83,0 ; nicht auf TR vorhanden
		dc.b $83,0 ; nicht auf TR vorhanden
		dc.b $83,0 ; nicht auf TR vorhanden
		dc.b $83,0 ; nicht auf TR vorhanden
		dc.b $83,0 ; nicht auf TR vorhanden
		dc.b $83,0 ; nicht auf TR vorhanden
		dc.b $83,0 ; nicht auf TR vorhanden
		dc.b $4b,$99 ; Ä
		dc.b $83,0 ; nicht auf TR vorhanden
		dc.b $83,0 ; nicht auf TR vorhanden
		dc.b $83,0 ; nicht auf TR vorhanden
		dc.b $83,0 ; nicht auf TR vorhanden
		dc.b $83,0 ; nicht auf TR vorhanden
		dc.b $52,$97 ; ö
		dc.b $83,0 ; nicht auf TR vorhanden
		dc.b $83,0 ; nicht auf TR vorhanden
		dc.b $83,0 ; nicht auf TR vorhanden
		dc.b $83,0 ; nicht auf TR vorhanden
		dc.b $49,$99 ; Ö
		dc.b $47,$99 ; O
		dc.b $83,0 ; nicht auf TR vorhanden
		dc.b $1B,$99 ; pfund
		dc.b $83,0 ; nicht auf TR vorhanden
		dc.b $50,$97
		dc.b $83,0 ; nicht auf TR vorhanden

		dc.b $83,0 ; nicht auf TR vorhanden
		dc.b $83,0 ; nicht auf TR vorhanden
		dc.b $83,0 ; nicht auf TR vorhanden
		dc.b $83,0 ; nicht auf TR vorhanden
		dc.b $83,0 ; nicht auf TR vorhanden
		dc.b $83,0 ; nicht auf TR vorhanden
		dc.b $83,0 ; nicht auf TR vorhanden
		dc.b $83,0 ; nicht auf TR vorhanden
		dc.b $83,0 ; nicht auf TR vorhanden
		dc.b $83,0 ; nicht auf TR vorhanden
		dc.b $83,0 ; nicht auf TR vorhanden
		dc.b $83,0 ; nicht auf TR vorhanden
		dc.b $83,0 ; nicht auf TR vorhanden
		dc.b $83,0 ; nicht auf TR vorhanden
		dc.b $83,0 ; nicht auf TR vorhanden
		dc.b $83,0 ; nicht auf TR vorhanden
		dc.b $83,0 ; nicht auf TR vorhanden
		dc.b $83,0 ; nicht auf TR vorhanden
		dc.b $83,0 ; nicht auf TR vorhanden
		dc.b $83,0 ; nicht auf TR vorhanden
		dc.b $83,0 ; nicht auf TR vorhanden
		dc.b $83,0 ; nicht auf TR vorhanden
		dc.b $83,0 ; nicht auf TR vorhanden
		dc.b $83,0 ; nicht auf TR vorhanden
		dc.b $83,0 ; nicht auf TR vorhanden
		dc.b $83,0 ; nicht auf TR vorhanden
		dc.b $83,0 ; nicht auf TR vorhanden
		dc.b $83,0 ; nicht auf TR vorhanden
		dc.b $83,0 ; nicht auf TR vorhanden
		dc.b $83,0 ; nicht auf TR vorhanden
		dc.b $83,0 ; nicht auf TR vorhanden
		dc.b $83,0 ; nicht auf TR vorhanden
		dc.b $83,0 ; nicht auf TR vorhanden
		dc.b $83,0 ; nicht auf TR vorhanden
		dc.b $83,0 ; nicht auf TR vorhanden
		dc.b $83,0 ; nicht auf TR vorhanden
		dc.b $83,0 ; nicht auf TR vorhanden
		dc.b $83,0 ; nicht auf TR vorhanden
		dc.b $83,0 ; nicht auf TR vorhanden
		dc.b $83,0 ; nicht auf TR vorhanden
		dc.b $83,0 ; nicht auf TR vorhanden
		dc.b $83,0 ; nicht auf TR vorhanden
		dc.b $83,0 ; nicht auf TR vorhanden
		dc.b $83,0 ; nicht auf TR vorhanden
		dc.b $83,0 ; nicht auf TR vorhanden
		dc.b $83,0 ; nicht auf TR vorhanden
		dc.b $83,0 ; nicht auf TR vorhanden
		dc.b $83,0 ; nicht auf TR vorhanden
		dc.b $83,0 ; nicht auf TR vorhanden
		dc.b $83,0 ; nicht auf TR vorhanden
		dc.b $83,0 ; nicht auf TR vorhanden
		dc.b $83,0 ; nicht auf TR vorhanden
		dc.b $83,0 ; nicht auf TR vorhanden
		dc.b $83,0 ; nicht auf TR vorhanden
		dc.b $83,0 ; nicht auf TR vorhanden
		dc.b $83,0 ; nicht auf TR vorhanden
		dc.b $83,0 ; nicht auf TR vorhanden
		dc.b $83,0 ; nicht auf TR vorhanden
		dc.b $83,0 ; nicht auf TR vorhanden
		dc.b $83,0 ; nicht auf TR vorhanden
		dc.b $83,0 ; nicht auf TR vorhanden
		dc.b $50,$97 ; P
		dc.b $83,0 ; nicht auf TR vorhanden
		dc.b $83,0 ; nicht auf TR vorhanden
		dc.b $83,0 ; nicht auf TR vorhanden
		dc.b $83,0 ; nicht auf TR vorhanden
		dc.b $83,0 ; nicht auf TR vorhanden
		dc.b $83,0 ; nicht auf TR vorhanden
		dc.b $83,0 ; nicht auf TR vorhanden
		dc.b $83,0 ; nicht auf TR vorhanden
		dc.b $83,0 ; nicht auf TR vorhanden
		dc.b $83,0 ; nicht auf TR vorhanden
		dc.b $83,0 ; nicht auf TR vorhanden
		dc.b $83,0 ; nicht auf TR vorhanden
		dc.b $83,0 ; nicht auf TR vorhanden
		dc.b $83,0 ; nicht auf TR vorhanden
		dc.b $83,0 ; nicht auf TR vorhanden
		dc.b $83,0 ; nicht auf TR vorhanden
		dc.b $83,0 ; nicht auf TR vorhanden
		dc.b $83,0 ; nicht auf TR vorhanden
		dc.b $83,0 ; nicht auf TR vorhanden
		dc.b $83,0 ; nicht auf TR vorhanden
		dc.b $83,0 ; nicht auf TR vorhanden
		dc.b $83,0 ; nicht auf TR vorhanden
		dc.b $83,0 ; nicht auf TR vorhanden
		dc.b $83,0 ; nicht auf TR vorhanden
		dc.b $83,0 ; nicht auf TR vorhanden
		dc.b $83,0 ; nicht auf TR vorhanden

buffer= 0
len= 4
head= 6
tail= 8

			.bss
step_li:	ds.w 1
step_re:	ds.w 1
spalte:		ds.w 1
esc_flag:	ds.w 1
son_flag:	ds.w 1
tr_save:	ds.1 1
zeile:		ds.b 1
teilung:	ds.b 1

end

Listing : Der IFD-Emulators fĂŒr TA Gabriele 9009 in Assembler

Wilfried Keller