|
CP/M-CONSOLE ist ein sehr komplexes Programm. Mit ihm kann die Softwareschnittstellen eines externen CP/M Computers über die serielle Schnittstelle des PCs bedient werden. Die Anforderungen an dieses Programm ergeben sich aus den definierten CP/M Schnittstellen, CONIN, CONOUT, READ, WRITE und zusätzlich BOOT. Nach dem Programmstart werden alle CP/M Dateien aus dem Ordner "CPM_DIR_IN" eigelesen. Daraus wird ein CP/M Image gebildet. Aus diesem Image werden die Daten für die READ und WRITE-Anweisungen gelesen bzw. geeschrieben. Ein zusätzliches Fenster zeigt alle Zeichen an, die über die CONOUT-Schnittstelle des CP/M Computers ausgegeben werden. Über die Tastatur des PCs können Zeichen an CONIN des CP/M Computers eingegeben werden. |
Das Projekt CONSOLE entstand zusammen mit meinem ersten CP/M Computer CPD2. Die CONSOLE wird aber auch von den nachfolgenden CP/M Computern CPD3 und CPD5 genutzt werden.
Wie bereits das SETERM - System-Terminal nutzt auch die CONSOLE den SYNASER-Treiber für die serielle Schnittstelle von Lukas Gebauer (siehe Project : Ararat Synapse).
Die anfängliche Konsole, für die Bearbeitung der Anfragen von der seriellen Schnittstelle, wurde wesentlich erweitert. Für die Anzeige der CP/M-Console (CONOUT) steht ein alphanumerischer Bildschirm bereit, der auch einige ESC-Sequenzen verarbeiten kann. So kann z.B. der Editor von Turbo Pascal genutzt werden.
Die Tastatureingaben des PCs (wenn das CP/M-Fenster aktiv ist) werden an die CP/M Console CONIN weiter geleitet.
Es werden aber auch alle Disketten-Operationen des CP/M Betriebssystems (SELDSK, SETTRK, SETSEC, SETDMA, READ, WRITE) bedient. Dadurch kann das CP/M-BIOS sehr einfach gehalten werden, da alle Funktionsaufrufe entweder nur zwischengespeichert werden, oder an die CONSOLE weiter gereicht werden können.
Die Aufrufe des CP/M Betriebssystems an das Diskettensystem werden von einem Disketten-Image bedient. Für das Format des Disketten-Image sind derzeit 3 verschiedene Formate (meist von CP/M-Emulatoren) auswählbar. Dieses Disketten-Image wird bei jedem Programmaufruf neu gebildet. Dazu werden alle Dateien, die sich im Verzeichnis "CPM_DIR_IN" in das Image eingelesen. In der unteren Hälfte des CONSOLE-Hauptfensters wird dann die Belegung des Disketten-Images grafisch dargestellt (Rot=Boot-Sektoren (werden aber nicht genutzt), Blau=Directory-Sektoren, Grün=durch Daten belegte Sektoren, Weiss=freie Sektoren).
Nach dem Schliessen des Programms werden alle Dateien aus dem Disketten-Image in das Verzeichnis "CPM_DIR_OUT" geschrieben. Dadurch kann man Dateien, die sich während der CP/M-Sitzung geändert haben (oder die neu angelegt wurden) abspeichern.
Die CP/M-Ausgaben an das LIST-Gerät werden in eine Textdatei mit dem Namen "Print.txt" im Unterordner "PRINT" umgeleitet.
Diese Textdatei kann während des laufenden Programms durch Drücken des Buttons aktualisiert werden (damit werden die LIST-Daten aus dem internen Programmspeicher in die Datei geschrieben).
Im Original CP/M wird das Betriebssystem zum Zeitpunkt des Starts von den Systempartitionen in den Arbeitsspeicher geladen und anschliessend gestartet. Bei meinen Projekten habe ich einen anderen Weg gewählt. Der Bootloader befindet sich im FLASH des CP/M-Computers. Dies ist ein Minimalsystem. Dieser Bootloader fragt bei der CONSOLE die Anzahl der Sektoren des eigentlichen CP/M-Systems ab (das System befindet sich als COM-Datei im Verzeichnis "BOOT"). Dann lädt der Bootloader das neue CP/M-System ab Adresse 100H in den TPA und startet es. Dann beginnt zu zweiten Mal das Hochladen des BIOS und der Sprung zur Kaltstartroutine des BIOS. Dieses zweite Laden des BIOS geht sehr schnell und gibt dem Syystem eine größere Fexibilität, da das BIOS auf dem CONSOLE-System schnell geändert werden kann.
Die grundsätzliche Arbeitsweise des CP/M-Computers mit der CONSOLE ist in der folgenden Übersicht dargestellt.
Der CP/M-Computer arbeitet als kleines Minimalsystem.
Im CP/M-BIOS werden die BIOS-Aufrufe an den Mikrocontroller weitergegeben (Softwareschnittstelle).
Der Mikrocontroller reicht die Anforderungen des CP/M-Computers über die serielle Schnittstelle (UART) an den PC weiter.
Dazu wird das CONSOLE-Protokoll genutzt.
Die Übertragung vom Mikrocontroller zum PC kann über eine RS232-Schnittstelle erfolgen, oder einen "UART zu USB-Konverter" auf der Mikrocontrollerseite und einen USB-Anschluss auf der PC-Seite.
Entsprechend den Vorgaben des CONSOLE-Protokolls, kann auch eine Antwort vom PC an den Mikrokontroller erfolgen.
Dieser wird dann an die CP/M-BIOS Softwareschnittstelle weitergeleitet (z.B. beim Lesen von Diskettensektoren mit READ).
Bevor die einzelnen Protokoll-Definitionen besprochen werden, soll das Grundprinzip kurz erläutert werden.
Die Richtung der Protokoll-Anforderungen ist ausschliesslich vom Mikrocontroller zum PC.
Bei einigen Protokoll-Anforderungen erfolgt dann eine Antwort vom PC zum Mikrocontroller.
Die Protokoll-Anforderung startet immer mit einem kleinen Buchstaben (oder mit dem @).
Nach dem kleinen Buchstaben, der den Anforderungscode darstellt, kann ein oder mehrere Zeichen folgen (meist Zahlen im Hex-Format als CHAR-Zeichen z.B. "0F" für 0FH).
Das Ende jeder Protokoll-Anforderung bildet der Zeilenabschluss mit den binären Werten für "Wagenrücklauf" und "Zeilenschaltung" (<CR><LF> oder Hexadezimal 0DH 0AH).
Dieses Zeilenende muss zwingend vorhanden sein. Erst wenn diese beiden Zeichen empfangen wurden, beginnt das CONSOLE-Programm mit der Auswertung.
Ist im Protokoll eine Antwort vom CONSOLE-Programm vorgesehen, so ist der Antwort-STRING ähnlich aufgebaut.
Nur beginnt die Antwort-STRING mit einem großen Buchstaben.
Durch diesen einfachen Aufbau des CONSOLE-Protokolls, kann man sämtliche Anforderungen und Antworten auch mit einem anderen Terminal-Programm generieren und anzeigen.
|
Antwort vom PC: |
keine |
|||
Länge = 3 Byte |
Diese Anforderung sollte immer gesendet werden, wenn der Mikrocontroller zurückgesetzt wurde (Drücken des RESET-Tasters). Auf der PC-Seite wird im CONSOLE-Programm mit dieser Anforderung der Puffer für die Daten der seriellen Schnittstelle geleert (vor allem nach einer fehlerhaften Übertragung notwendig).
|
Antwort vom PC: |
|
||||||||
Länge = 3 Byte |
Länge = 5 Byte |
Beispiel: Anfrage der Anzahl der Sektoren, Antwort = 10 Sektoren
Wie schon oben unter "Überblick" erläutert gibt die CONSOLE zusätzlich die Möglichkeit eine BOOT-Datei mit dem CP/M-Betriebssystem nachzuladen. Dazu muss der Loader aber die Anzahl der zu ladenden Sektoren kennen. Diese Anzahl wird mit dieser Funktion abgefragt. Nach dieser Funktion beginnt in der Regel das Laden der BOOT-Sektoren mit "b" (3.1.3 Lesen eines Sektors der BOOT-Datei).
|
Antwort vom PC: |
|
||||||||||||||||||||||||||||||||||||||||||||||
Länge = 7 Byte |
Länge = 39 Byte |
Beispiel: lese Abschnitt 05 vom Sektor 03, Antwort = die 32 konvertierten Daten-Bytes des Sektors
Nachdem durch die Funktion "a" (3.1.2 Abfrage der Anzahl der Sektoren der BOOT-Datei) die Anzahl der Sektoren der BOOT-Datei bekannt ist, können nun die Sektoren der BOOT-Datei einzeln gelesen werden. Dazu wird "b" + "BSEC_LFD_NR" + "BSEC_SECTOR " + <CR> + <LF>.
BSEC_LFD_NR = Da pro Anfrage nur 32 Byte an Daten übertragen werden, muss ein Sektor durch 4 Lesevorgänge zusammengesetzt werden. Daher wird diese laufende Nummer (von 0..3) benötigt.
BSEC_SECTOR = Die Nummer des Sektors der BOOT-Datei (läuft von 0..(Anzahl der Sektoren der BOOT-Datei-1)).
Um möglichst viele Daten übertragen zu können, werden die Binärdaten nicht im umgewandelten Hexadezimal-Wert übertragen. Sonst würde der zu übertragende Datensatz nur 16 Datenbytes plus "R" plus >CR> und <LF> lang sein.
Würden die binären Daten direkt gesendet werden, würde es irgendwann zu Problemen kommen, da die Gegenstelle (der Mikrocontroller) auf ein <CR> wartet, was bei der Übertragung des Binärwertes 0DH dann bereits im Datenblock der Fall wäre. Also müssen die binären Datenwerte vorher konvertiert werden.
Prinzip der Konvertierung
Alle Daten werden in den Datenraum 128 bis 255 (Bit 7=1) gehoben. Dadurch wird sicher gestellt, dass niemals ein 0DH oder 0AH als Datenwert übertragen wird.
Das 7. Bit wird immer auf 1 gesetzt. Dann folgt der serielle Datenstrom der 8-Bit Daten, der in die restlichen 7 Bit (Bit6...Bit0) eingelagert wird. Damit werden mehr Bytes benötigt. Das Ergebnis von 36 Byte ist aber wesentlich weniger als 64 Byte mit umgewandelten Hexadezimal-Werten.
Im Mikrocontroller müssen diese konvertierten 7-Byte-Werte wieder in 8-Byte-Datenwerte umgewandelt werden.
|
Antwort vom PC: |
|
||||||||||||||||
Länge = 3 Byte |
Länge = 13 Byte |
In CP/M 2.2 wird kein Datum verwendet. Aber in CP/M 3.0 wird ein Datum mit Uhrzeit benötigt. Diese Funktion sendet Datum und Uhrzeit im Hexadezimal-Format an den Mikrocontroller.
Beschreibung des Datums- und Uhrzeiformats
Das Format orientiert sich an das Datums- und Uhrzeitformat von CP/M 3.0.
DDDD = Datum, enthält die Anzahl der Tage ab dem "01.01.1978" bis heute (plus 1), abgespeichert in einem Word.
SS = Stundenwert im BCD-Format
MM = Minutenwert im BCD-Format
SS = Sekundenwert im BCD-Format
|
Antwort vom PC: |
keine |
|||||
Länge = 5 Byte |
Beispiel: Drucken von "L"
Unter CP/M wird der Drucker als LIST bezeichnet. Diese Funktion reicht das Zeichen, das an die LIST-Schnittstelle gesendet wurde (BIOS-Funktion 05 = LIST-Ausgabe) im Hexadezimal-Format an die CONSOLE weiter. Unter CP/M war der Drucker ein zeichenorientiertes Gerät. Unter den modernen grafischen Betriebssystemen ist die Druckerausgabe wesentlich komplexer und benötigt immer spezielle Treiber. Daher werden die Zeichen im CONSOLE-Programm einfach in die Datei "PRINT.txt" im Verzeichnis "PRINT" umgeleitet.
Da während der Laufzeit des Programms CONSOLE, die Datei "PRINT.txt" geöffnet ist, muss das Programm geschlossen werden, oder es muss der Button betätigt werden. Dann wird die Datei "PRINT.txt" zwischengespeichert. Weitere Druckausgaben werden an die bestehenden Druckzeichen in dieser Datei angehängt.
|
Antwort vom PC: |
keine |
|||||
Länge = 5 Byte |
Beispiel: Anzeige von "A"
Die Consolen-Ausgabe (CONOUT) ist sicher die wichtigste CP/M-Schnittstelle. Hier werden die Zeichen und Texte, die vom CP/M kommen angezeigt. Die Syntax dieser Funktion ist genau so einfach: "o" + das auszugebende Zeichen im Headezimal-Format + <CR> + <LF>.
|
Antwort vom PC: |
|
||||||||||||||||||||||||||||||||||||||||||||
Länge = 5 Byte |
Länge = 39 Byte |
Beispiel: lese Abschnitt 04 des Sektors, Antwort = die 32 konvertierten Daten-Bytes des Sektors
Wichtiger Hinweis: Vor dem Ausführen dieser Funktion müssen Sector, Track, Drive (STD) mit der Funktion "s" gesetzt werden.
Nach dem Setzen von Sector, Track, Drive (STD) durch die Funktion "s" werden nun die 32 Byte des Sektorabschittes gelesen. Im wesentlichen entspricht das der BIOS-Funktion READ, nur dass hier 4 einzelne Teilabschnitte eines Sektors gelesen und anschliessend zusammengesetzt werden müssen.
Um möglichst viele Daten übertragen zu können, werden die Binärdaten nicht im umgewandelten Hexadezimal-Wert übertragen. Sonst würde der zu übertragende Datensatz 2*32 Byte=64 Byte plus "R" plus >CR> und <LF> lang sein.
Die binären Daten können aber auch nicht direkt gesendet werden, da die Gegenstelle (der Mikrocontroller) auf ein <CR> wartet, was bei der Übertragung des Binärwertes 0DH ja der Fall wäre. Also müssen die Binärwerte vorher konvertiert werden.
Prinzip der Konvertierung
Alle Daten werden in den Datenraum 128 bis 255 (Bit 7=1) gehoben. Dadurch wird sicher gestellt, dass niemals ein 0DH oder 0AH als Datenwert übertragen wird.
Das 7. Bit wird immer auf 1 gesetzt. Dann folgt der serielle Datenstrom der 8-Bit Daten, der in die restlichen 7 Bit (Bit6...Bit0) eingelagert wird. Damit werden mehr Bytes benötigt. Das Ergebnis von 36 Byte ist aber wesentlich weniger als 64 Byte mit umgewandelten Hexadezimal-Werten.
Im Mikrocontroller müssen diese konvertierten 7-Byte-Werte wieder in 8-Byte-Datenwerte umgewandelt werden.
|
Antwort vom PC: |
keine |
|||||||||||
Länge = 3 Byte |
Beispiel: setze Sektor (VAR_SECTOR) mit 3AH, Spur (VAR_TRACK ist Word) mit 0027H und Laufwerk (VAR_DISKNO) mit 01
Format: s SE TH TL DR <CR> <LF>
SE = Sektor 1 Byte im Hexadezimal-Format
TH und TL = Track-High-Byte und Track-Low-Byte -> 2 Byte = 1 Word im Hexadezimal-Format
DR = Drive 1 Byte im Hexadezimal-Format
Diese Funktion entspricht im wesentlichen folgenden CP/M-BIOS-Funktionen:
SETSEC (11) Sektor auswählen
SETTRK (10) Spur auswählen
SELDSK (09) Laufwerk auswählen
Nach dem Einstellen von Sektor, Spur und Laufwerk folgt in der Regel das Lesen mit "r" (3.1.7 Lesen eines Sektors (komprimiert)) oder das Schreiben eines oder mehrerer Sektoren.
|
Antwort vom PC: |
|
||||||||||||||||||||||||||||||||||||||
Länge = 5 Byte |
Länge = 35 Byte |
Beispiel: lese Abschnitt 06 des Sektors, Antwort = die 16 Daten-Bytes des Sektors im Hexadezimal-Format
Wichtiger Hinweis: Vor dem Ausführen dieser Funktion müssen Sector, Track, Drive (STD) mit der Funktion "s" gesetzt werden.
Nach dem Setzen von Sector, Track, Drive (STD) durch die Funktion "s" werden nun die 16 Byte des Sektorabschittes gelesen. Im wesentlichen entspricht das der BIOS-Funktion READ, nur dass hier 8 einzelne Teilabschnitte eines Sektors gelesen und anschliessend zusammengesetzt werden müssen.
Diese Funktion entspricht im Prinzip der Funktion "r", nur dass hier 1 Datenbyte mit 2 Hexadezimalen-Bytes übertragen wird. Mit 32 Byte werden also nur 16 Datenbytes übertragen. Für einen Sektor werden 8 Abschnitte benötigt.
Dafür ist diese Funktion einfacher zu implementieren, denn im Mikrocontroller muss nun nicht aufwendig wieder konvertiert werden. Diese Funktion ist daher besser für Testzwecke und zur Erstimplementierung.
|
Antwort vom PC: |
keine |
|||||||||||||||||||||||||||||||||||
Länge = 37 Byte |
Beispiel: schreibe die folgenden 16 Byte im Hexadezimal-Format in den Sektor mit dem Anschnitt 06
"v"
06 = Sektor-Abschnitt
01..0F = 16 Byte Daten im Hxadezimal-Format
Wichtiger Hinweis: Vor dem Ausführen dieser Funktion müssen Sector, Track, Drive (STD) mit der Funktion "s" gesetzt werden.
Nach dem Setzen von Sector, Track, Drive (STD) durch die Funktion "s" werden nun die 16 Byte des Sektorabschittes geschrieben. Im wesentlichen entspricht das der BIOS-Funktion WRITE, nur dass hier 8 einzelne Teilabschnitte eines Sektors geschrieben werden müssen.
Diese Funktion entspricht im Prinzip der Funktion "w", nur dass hier 1 Datenbyte mit 2 Hexadezimalen-Bytes übertragen wird. Mit 32 Byte werden also nur 16 Datenbytes übertragen. Für einen Sektor werden 8 Abschnitte benötigt.
Dafür ist diese Funktion einfacher zu implementieren, denn im Mikrocontroller muss nun nicht aufwendig wieder konvertiert werden. Diese Funktion ist daher besser für Testzwecke und zur Erstimplementierung.
|
Antwort vom PC: |
keine |
|||||||||||||||||||||||||||||||||||||||||
Länge = 41 Byte |
Beispiel: schreibe die folgenden 36 Byte (nach Konvertierung = 32 Byte) Daten in den Sektor mit dem Anschnitt 03
"w"
03 = Sektor-Abschnitt
0..35 = 36 Byte Daten (nach der Konvertierung werden daraus32 Daten-Byte)
Wichtiger Hinweis: Vor dem Ausführen dieser Funktion müssen Sector, Track, Drive (STD) mit der Funktion "s" gesetzt werden.
Nach dem Setzen von Sector, Track, Drive (STD) durch die Funktion "s" werden nun die 32 Byte des Sektorabschittes geschrieben. Im wesentlichen entspricht das der BIOS-Funktion WRITE, nur dass hier 4 einzelne Teilabschnitte eines Sektors geschrieben werden müssen.
Diese Funktion entspricht im Prinzip der Funktion "v", nur dass hier 32 Datenbytes konvertiert und übertragen werden. Mit 41 Byte werden also 32 Datenbytes übertragen. Für einen Sektor werden 4 Abschnitte benötigt.
Im Mikrocontroller müssen die übertragenen Daten wieder konvertiert werden. Diese Funktion kann mehr Daten/Zeiteinheit übertragen als die Funktion "v".
|
Antwort vom PC: |
keine |
|||||
Länge = 5 Byte |
Beispiel: Anzeige von ">> Fehler Nr: 05 vom Controller gesendet" im Anzeigebereich des CONSOLE-Programms
Mit dieser Funktion ist es möglich vom Mikrocontroller an die CONSOLE Fehlermeldungen zu senden. Die Ursachen des Fehlers müssen an Hand der Nummer und der Stelle des Auftretens im BC analysiert werden.
Im Quelltext steht dann:
Write_String:='x03';
WriteLn;
|
Antwort vom PC: |
keine |
||||||||||||||||
Länge je nach Kommentar, hier 16 Byte |
Beispiel: Anzeige von "*** Hallo_Welt!!!" im Anzeigebereich des CONSOLE-Programms
Diese Funktion ist nicht für den produktiven Betrieb gedacht. Sie soll vielmehr im Testbetrieb zur Anzeige von durchlaufenen Programstellen dienen.
Im Quelltext steht dann:
Write_String:='yHallo_Welt!!!';
WriteLn;
keine |
Antwort vom PC: |
|
|||||
Länge = 5 Byte |
Beispiel: Eingabe des Wetes "B" (042H in hexadezimaler Form) von der Tastatur wird an den uC gesendet
Eigentlich ist diese Funktion nicht richtig implementiert, denn es sollte nur etwas übertragen werden, wenn eine Anforderung von Mikrokontroller erfolgt ist (soll später noch geändert werden).
... folgt in Kürze ...
Quelltexte: CONSOLE.ZIP
Diese(s)
Werk bzw. Inhalt von Ronald Daleske steht unter einer
Creative Commons Namensnennung-Nicht-kommerziell 3.0
Deutschland Lizenz.
keine Mängelgewähr
DIESE SOFTWARE WIRD VOM URHEBERRECHTSINHABER "OHNE MÄNGELGEWÄHR" BEREITGESTELLT. ALLE AUSDRÜCKLICHEN ODER STILLSCHWEIGENDEN GEWÄHRLEISTUNGEN, EINSCHLIESSLICH DER STILLSCHWEIGENDEN GEWÄHRLEISTUNG DER MARKTGÄNGIGKEIT UND EIGNUNG FÜR EINEN BESTIMMTEN ZWECK (JEDOCH NICHT DARAUF BESCHRÄNKT), WERDEN AUSGESCHLOSSEN. DER URHEBERRECHTSINHABER IST IN KEINEM FALL UND NACH KEINER HAFTUNGSTHEORIE (SEI ES AUF VERTRAGSBASIS, AUF DER BASIS STRENGER HAFTUNG ODER UNERLAUBTER HANDLUNGEN, EINSCHLIESSLICH FAHRLÄSSIGKEIT) FÜR BELIEBIGE VERURSACHTE DIREKTE, INDIREKTE, ZUFÄLLIGE, BESONDERE, EXEMPLARISCHE SCHÄDEN ODER FOLGESCHÄDEN (EINSCHLIESSLICH, JEDOCH NICHT BESCHRÄNKT AUF BESCHAFFUNG VON ERSATZPRODUKTEN ODER -LEISTUNGEN, NUTZUNGSAUSFALL, DATEN- UND GEWINNVERLUST ODER GESCHÄFTSAUSFALL) HAFTBAR, DIE AUFGRUND DER VERWENDUNG DIESER SOFTWARE ENTSTEHEN KÖNNEN. DIES GILT AUCH, WENN AUF DIE MÖGLICHKEIT SOLCHER SCHÄDEN HINGEWIESEN WURDE.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS AS IS AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
BDS style license
Die Lizenzbedingungen zum SYNASER-Treiber für die serielle Schnittstelle finden Sie unter license Ararat Synapse