MagicSLM: Der ATARI-Laserdrucker am Apple Macintosh (2)

Nachdem wir uns im ersten Teil um die Grundlagen gekümmert haben, geht es nun zur Sache, und zwar um die Ausgabe auf den SLM-Drucker. Zum Ausdrucken auf den SLM muß vorher der Diablo-Emulator gestartet worden sein. Er bietet die Möglichkeit, eine komplette Bitmap mit wenigen Befehlen auszudrucken - und das sogar in verschiedenen Größen.

Bevor mit dem Drucken begonnen wird, wird zunächst eine 10tel Sekunde lang gewartet, damit das vorher abgesendete XOFF auf jeden Fall vom Mac ausgewertet wurde. Denn während der ATARI druckt, kann er keine Daten über die serielle Schnittstelle empfangen.

Dann wird die Diablo-Image-Struktur ausgefüllt. Sie enthält einen Zeiger auf den Datenanfang sowie die Ausmaße und den Vergrößerungsfaktor. Als Vergrößerung können nur Zweierpotenzen (1,2,4) benutzt werden. Dann werden die nötigen Befehle auf den Standard-Druckerkanal ausgegeben:

fprintf(etdprn,n\033\015P\0333");
fprintf(etdprn,"\033\022G$%081x ", (lonjy)&diabloimjj) ; 
fprintf(etdprn,”\0334"); 
fprintf(etdprn,"\014");

Zuerst wird ein Reset gesendet und der Grafikmode angeschaltet. In der 2. Zeile wird dann der Befehl zum Drucken des Images gegeben, danach wird der Grafikmode ausgeschaltet und schließlich ein FormFeed ausgegeben.

Ausgabe als PCX-File

Eine andere Möglichkeit zum Ausgeben der Bitmap ist es, eine Bilddatei zu erzeugen. Aus den vielen möglichen Grafikformaten haben wir das PCX-Format ausgewählt.

Da beim Ausdrucken natürlich mehrere Seiten gedruckt werden können, müssen von MagicSLM auch mehrere PCX-Files erzeugt werden. Deswegen kürzt die Routine PcxWrite den vom User angegebenen Dateinamen auf 5 Zeichen und hängt dann eine dreistellige Seitennummer an. Als Extension dient dann ,PCX‘.

Dann wird das File erzeugt und der Header aufgebaut und geschrieben.

Danach werden die Daten gepackt geschrieben: Die eigentliche Kompression von PCX ist verhältnismäßig einfach. Wenn bei einem PCX-Daten-Byte die oberen 2 Bit gesetzt sind, so wird es von einer Entpackroutine als Zähler betrachtet, dessen untere 6 Bit angeben, wie oft das darauffolgende Byte wiederholt wird. Beim Verpacken muß man deshalb darauf achten, daß einzelnen Daten-Bytes, bei denen die oberen beiden Bits gesetzt sind, immer ein Zähler-Byte vorangestellt werden muß. Außerdem darf der Wiederholzähler für ein Byte natürlich nur Werte bis maximal 63 enthalten, und die Kompression muß am Ende einer Rasterzeile enden.

Schließlich ist noch zu bedenken, daß gesetzte Bits in der Bitmap als geschwärzt zu verstehen sind, während gesetzte Bits im PCX-File weiß sind. Deswegen müssen die Werte invertiert werden.

Das Kontrollmodul

Dieses Modul enthält die Funktionen zur Kontrolle und Koordination der Wandlung.

StartScan startet entweder das Abfragen der seriellen Schnittstelle (im Hintergrund) oder direkt die Konversion (einer Datei).

StopScan gibt, falls nötig, die serielle Schnittstelle wieder frei.

AllocBuffer alloziert direkt vor der Wandlung den Bufferfürdie komplette Seite und einen für die jeweils aktuelle Rasterzeile (die auch groß genug für den Landscape-Modus sein muß).

PrintStat zeigt den aktuellen Wandlungsstatus an:

StartConversion leistet nun die eigentliche Arbeit. Zunächst werden in Abhängigkeit von der gewünschten Ein- und Ausgabeform die entsprechenden Lese- und Schreibroutinen bestimmt.

Dann werden sämtliche Buffer und Zähler initialisiert und der Statusdialog dargestellt.

Nun wird der nächste PCL-Befehl gelesen. Falls dieser einen Wert größer 255 besitzt, so handelt es sich dabei um einen vom User gedrückten Button des Statusdialogs, der gesondert behandelt wird:

Entweder wird solch ein Befehl einfach in einen entsprechenden PCL-Befehl (FormFeed oder Reset) umgewandelt, oder er führt zum Abbruch der Wandlung. Bei Bedarf wird der Statusdialog aktualisiert.

Schließlich wird der PCL-Befehl mit ExCmd ausgeführt - das heißt in die Rasterseite übertragen.

Diese Schleife wird solange wiederholt, bis das File komplett gelesen wurde, oder- bei der seriellen Schnittstelle - bis der Benutzer .Abbruch“ angewählt hat.

Sollten sich am Ende noch Daten in der Rasterseite befinden, ohne daß diese vorher geschrieben wurde, dann wird nun noch ein FormFeed ausgeführt.

Der PCL-Interpreter

Die Printer Control Language der Firma Flewlett Packard beinhaltet neben einigen Kontrollzeichen (wie Form Feed oder Carriage Return) ausschließlich sogenannte Escape-Sequenzen. Damit sind Zeichenfolgen gemeint, die mit einem Escape-Zeichen eingeleitet werden. Das direkt nachfolgende Zeichen stellt dann den eigentlichen Befehl dar, dem dann noch spezielle Parameter folgen können.

Da diese Escape-Sequenzen also unterschiedliche Länge haben können und weitere Escape-Zeichen als Parameter erscheinen können, ist es etwas aufwendig, das Ende einer solchen Sequenz zu bestimmen.

Daher werden die gültigen PCL-Be-fehle, die in der Struktur-Liste PcIBefehle eingetragen sind, zur Wandlung in eine Baumstruktur eingetragen (durch die Funktion InitPcl). Jeder Knoten dieses Baumes beinhaltet ein mögliches Zeichen, einen Zeiger auf einen weiteren Knoten mit einem Zeichen (Next-ElemlnLine), das diesem folgen kann, und einen Zeiger auf einen Knoten mit einem Zeichen, das ebenfalls an dieser Stelle auftreten kann (FirstElemNext-Line). Wenn ein Knoten einen kompletten PCL-Befehl abschließt, so ist First-ElemNextLinegteich 0, und der Eintrag BefehINo gibt die Nummer des Befehls in der Struktur-Liste PcIBefehle an.

Dazu vielleicht das Beispiel in Bild 1: Angenommen, die Zeichenfolge ESC, &, I (ein Befehl zum Einstellen des Seitenlayouts) soll interpretiert werden: Der Interpreter beginnt immer bei einem speziellen Knoten TopElem und liest das erste Zeichen (ESC). Von TopElem hangelt er sich dann über den Zeiger in FirstElemNextLine zum ersten Knoten, mit dessen Zeichen (Carriage return) verglichen wird. Da die beiden Zeichen nicht übereinstimmen, geht’s über NextElemlnLine zum nächsten Knoten in der Ebene. Dieser enthält das gesuchte Zeichen - aber keine Befehlsnummer, der Befehl ist noch nicht zu Ende. Der Interpreter liest also das nächste Zeichen (&) und sucht im Zeiger FirstElemNextLine den ersten Knoten der nächsten Ebene. In dieser Ebene gehts es dann solange über NextElemlnLine weiter, bis das Zeichen in einem Knoten gefunden wird. Auch dieser Knoten hat noch keine Befehlsnummer. Deshalb wird ein weiteres Zeichen gelesen (I) und mit den Knoten der nächsten Ebene verglichen. Der passende Knoten enthält jetzt eine Befehlsnummer. Der Befehl ist daher vollständig erkannt. Allerdings können diesem Befehl jetzt noch Argumente folgen. Das ist dann in der Struktur-Liste PcIBefehle vermerkt. Diese Argumente bestehen ausschließlich aus Ziffern oder Vorzeichen und werden durch einen Buchstaben abgeschlossen. Falls ein solches Argument folgt, wird es und sein Terminator noch aus dem Datenstrom gelesen.

Um diesen Baum nun aufzubauen, benutzt InitPcl die Funktion PutNext-CmdlnList. Diese verfolgt nun erst den bestehenden Baum so weit wie möglich - es kann ja sein, daß der Befehl mit den gleichen Zeichen beginnt wie ein bereits eingetragener:

do {
	LastElem = NextElem;
	NextElem = FindNextElemInLine
		(LastElem,PcIBefehle 
		[CmdNo].BefPrefix[i++]);
} while (NextElem != 0);

FindNextElemlnLine sucht dabei einen Knoten in der dem übergebenen Knoten folgenden Ebene mit dem gewünschten Zeichen.

Danach werden die restlichen Zeichen des Befehls in jeweils tieferen Ebenen in den Baum eingetragen.

Der eigentliche Interpreter besteht nun aus den Funktionen zum Lesen des nächsten PCL-Befehls (Parse-NextCmd) und denen zur Ausführung eines Befehls {ExCmd).

ParseNextCmd arbeitet exakt wie oben beschrieben. Es wird nur noch berücksichtigt, daß auch Benutzereingaben durch den Statusdialog in Form von .Zeichen“ mit einem Wert größer als 255 eingelesen werden. Auch werden sogenannte Mehrfachbefehle unterstützt. Zurückgegeben werden die Nummer des erkannten Befehls, die Argument-Zeichenfolge und das Terminatorzeichen.

Bild 2: Der Hauptdialog von MagicSLM

ExCmd besteht im wesentlichen aus einem switch-Befehl, in dem alle wichtigen Befehlsnummern separat behandelt werden. Hier werden dann Argument und Terminator ausgewertet. Falls nötig werden den Befehlen nachfolgende (Grafik-)Daten gelesen und bearbeitet.

Auf jeden PCL-Befehl einzeln einzugehen würde den Rahmen dieses Artikel sprengen, aber sie sind ja im Quellcode ausführlich kommentiert. Daher nur noch eine Bemerkung: es werden nur die nötigen Befehle für Layout und Rastergrafik unterstützt, also weder reine Textdaten noch Zeichenbefehle. Praktisch alle Macintosh- und ATARI-Programme für Textverarbeitung und Grafik benutzen Rastergrafik zum Ausdrucken, das stellt also keine große Einschränkung dar.

MagicSLM-Bedienung

Installation auf dem ATARI

Kopieren Sie den Diablo-Treiber in den Autoordner und die nötigen Fonts - die im Diablo-Programm angemeldet sind - auf die Boot-Partition (Sie können den Treiber aber auch von Hand starten). Das Accessory kopieren Sie ebenfalls auf die Boot-Partition.

Im Kontrollfeld stellen Sie dieselbe Baud-Rate ein wie auf dem Macintosh und schalten das Handshake aus. Natürlich sollten Sie beachten, die richtige Schnittstelle als Standard-Port anzuwählen (falls Ihr ATARI mehrere besitzt).

Auf dem Mac unter Mac-OS

Ziehen Sie einen der oben erwähnten Druckertreiber auf den Systemordner. Wählen Sie dann im Apple-Menü unter "Auswahl“ den entsprechenden Treiber an und klicken Sie auf "Setup“. Hier wählen Sie die Baud-Rate aus, schalten Sie XON/XOFF ein und wählen Sie, wenn nötig, Laseijet/Deskjet aus.

Auf dem Mac unter MagiCMac

Leiten Sie den .parallelen“ Drucker-Port des ST auf den Mac Drucker-Port um (im MagiCMac-Hauptprogramm). Dann wählen Sie einen Deskjet-/Laserjet-Treiber unter GDOS, Speedo-GDOS, NVDI oder einem anderen Programm an.

Schließlich verbinden Sie beide Computer mit dem oben beschriebenen Kabel.

Bild 3: Der Statusdialog

Betrieb

Wählen Sie das Accessory im Menü an. Nun können Sie wählen, ob Sie Daten über die serielle Schnittstelle empfangen oder eine bereits vorliegende PCL-Datei umwandeln wollen. Außerdem können Sie den Output auf den SLM-Laserdrucker oder in PCX-Files leiten. Dann Wählen Sie .Start“ oder brechen das Programm mit "Stop“ ab.

Falls als Input eine PCL-Datei gewählt wurde, wird sie sofort gewandelt, und das Accessory verschwindet wieder im Hintergrund. Sonst wartet MagicSLM im Hintergrund solange, bis Daten ankommen - andere Programme sollten die Schnittstelle jetzt natürlich nicht benutzen.

Während der Wandlung öffnet sich der Statusdialog, und Sie haben folgende Möglichkeiten: "Abbruch“ unterbricht die Wandlung, und MagicSLM gibt die Schnittstelle wieder frei und legt sich wieder schlafen. "FormFeed“ führt einen Seitenvorschub aus. Die Wandlungs-Buffer werden neu initialisiert, und die Wandlung wird fortgesetzt. .Reset“ initialisiert die Wandlungs-Buffer, ohne sie zu drucken, und die Wandlung wird weitergeführt.

Am Ende einer File-Wandlung verschwindet MagicSLM automatisch wieder im Hintergrund. Bei der seriellen Schnittstelle als Input kann das Programm natürlich nicht ahnen, wann keine Daten mehr ankommen. In diesem Fall muß es, wenn alles gedruckt wurde und der ATARI wieder für anderes verwendet werden soll, mit "Abbruch" in den Hintergrund geschickt werden.

Fehlerquellen

Auf dem ATARI

Auf dem Mac

Ausblick

Bisher unterstützt MagicSLM nicht explizit die schnellen Ports des STE/ TT oder gar des Falcon. Wer hier selbst Hand anlegen will, sei auf die beiliegenden Quellcodes verwiesen. Für viele Anwendungen dürfte auch ein IMG-File-Export interessant sein.

Außerdem sei noch erwähnt, daß man natürlich auch von PCs aus über die serielle Schnittstelle ausdrucken und damit MagicSLM nutzen kann -aber dabei ist zu beachten, daß einige PC-Programme die eingebauten Fonts des Deskjets benutzen wollen. Das klappt dann leider nicht.

Wir hoffen, daß MagicSLM sich als praktikable Lösung bewährt und damit das Überleben der STs und der SLMs noch für einige Zeit sicherstellt.

Harald Schönfeld

Literatur:

[1] HP LaserJet III Printer Technical Referece Manual
[2] ATARI Profibuch, Sybex


Bernd Spellenberg Harald Schönfeld
Aus: ST-Computer 02 / 1996, Seite 46

Links

Copyright-Bestimmungen: siehe Über diese Seite