Build your OS – Der Regnatix-Code – Seite 2
3. Slave-Funktionen
Nun sehen wir die ersten Lebenszeichen von Regnatix über den Bildschirm huschen. Der nächste folgerichtige Schritt wäre nun, die Keyboard Funktionen von Bellatrix über den Bus verfügbar zu machen. Aber vor der konkreten Realisierung dieses Schrittes sollten wir uns einige grundlegende Gedanken zum übergeordneten Dialog zwischen den Propellern machen.
Da alle Macht von Regnatix ausgeht, ist der erste Gedanke wie die Funktionen abgerufen werden können recht einfach: Jeder Busdialog beginnt mit der Übersendung einer entsprechenden Funktionsnummer zum Slave. Darauf folgt eine funktionsabhängige Abfolge von Sende- und Empfangszyklen. Genau nach diesem Muster funktioniert das BIOS in Administra im TriOS.
Bei Bellatrix aber habe ich für den Texttreiber einen anderen, asymetrischen Ablauf realisiert, da ein großer Anteil der Daten zwischen Bellatrix und Regnatix Zeichenausgaben sein werden. Also werden alle Daten <> 0 als Ausgabezeichen interpretiert und auf dem Bildschirm ausgegeben. Empfängt Bellatrix aber eine $0, so folgt darauf eine entsprechende Funktionsnummer. Für unser nächstes Experiment wollen wir zwei Funktionen in Bellatrix integrieren: Status und Tastaturcode abfragen.
Unser erstes Experiment dazu soll eine einfache Textkonsole sein. Die Routine in Regnatix sendet dazu alle per Tastatur eingegebenen Zeichen, welche er bei Bellatrix abfragt, einfach wieder zurück, um sie auf dem Textbildschirm auszugeben.
[002-reg-textkonsole.spin] – Regnatix-Code
[002-bel-bios.spin] – Bellatrix-Code
REGNATIX-CODE PUB main 'Hauptroutine bus_init print(@msg1) repeat repeat until keystat > 0 'taste gedrückt? printchar(key) 'echo der taste auf bildschirm BELLATRIX-CODE PUB main | zeichen,n 'Hauptroutine init_subsysteme 'bus/vga/keyboard/maus initialisieren repeat zeichen := bus_getchar '1. zeichen empfangen if zeichen > 0 print_char(zeichen) else zeichen := bus_getchar '2. zeichen kommando empfange case zeichen 1: bus_putchar(key.gotkey) '1: Tastaturstatus senden 2: bus_putchar(key.key) '2: Tastaturzeichen senden |
4. Kommandointerpreter
Im vorigen Abschnitt haben wir im Regnatix-Code schon einige elementare Routinen gefunden. In unserem Fall sind es eigentlich nur die verschiedenen Funktionen für Textausgaben (print, printchar) und Zeicheneingabe (keystat, keycode). Da wir diese universellen Routinen in vielen Programmen brauchen werden, ist es sinnvoll, diese als Bibliothek in ein gesondertes Objekt auszulagern. Im TriOS heißt dieses Objekt „IOS“ (Input-Output-System), um Verwechslungen zu vermeiden, wollen wir unser Objekt „SIOS“ (Spin-IOS) nennen.
[003-reg-cli.spin] – Regnatix-Code
[003-bel-bios.spin] – Bellatrix-Code
Im Quelltext [003] ist das SIOS schon eingebunden. Auch das Bella-Bios ist an einigen wenigen Stellen verändert. So werden jetzt auch diverse Steuercodes eingebunden. Im SIOS findet man zu den meisten Funktionen die entsprechenden Routinen. Schauen wir uns an was wir bis jetzt in unserer Bibliothek verfügbar haben:
PUB start: wflag | n 'system: initialisiert system PUB key:wert 'key: holt tastaturcode PUB keyspec:wert 'key: statustasten zum letzten tastencode PUB keystat:status 'key: übergibt tastaturstatus PUB keywait:n 'key: wartet bis taste gedrückt wird PUB print(stringptr) 'screen: bildschirmausgabe einer zeichenkette (0-terminiert) PUB printdec(value) | i 'screen: dezimalen zahlenwert auf bildschirm ausgeben PUB printhex(value, digits) 'screen: hexadezimalen zahlenwert auf bildschirm ausgeben PUB printchar(c) 'screen: einzelnes zeichen auf bildschirm ausgeben PUB printctrl(c) 'screen: steuerzeichen ($100 bis $1FF) auf bildschirm ausgeben PUB printnl 'screen: $0D - CR ausgeben PUB printcls 'screen: screen löschen PUB curhome 'screen: cursorposition auf erste position setzen PUB printtab 'screen: zur nächsten tabulatorposition PUB curchar(char) 'screen: setzt cursorzeichen PUB curpos1 'screen: setzt cursor auf spalte 1 in zeile PUB setcolor(color) 'screen: farbe setzen PUB curon 'screen: schaltet cursor an PUB curoff 'screen: schaltet cursor aus PUB sline(n) 'screen: startzeile scrollbereich setzen PUB screeninit(stradr,n) 'screen: löschen, kopfzeile ausgeben und setzen PUB bus_init 'bus: initialisiert bussystem PUB bus_putchar2(c) 'BUS: Byte an Prop1 (Bellatrix) senden PUB bus_getchar2:wert 'BUS: Byte vom Prop1 (Bellatrix) empfangen |
Kern des Interpreters ist die Variable tib für eine Kommandozeile. In dieser Variable wird die Zeichenkette gespeichert, schrittweise zerlegt und interpretiert. Das Programm enthält keine großen Geheimnisse und es sollte schnell klar werden wie man den Interpreter durch weitere Kommandos erweitern kann.
Um die Funktionsweise zu verdeutlichen, habe ich noch zwei experimentelle Kommandos eingefügt – para und paranum. An diesen beiden Kommandos kann man gut die Funktion der Parameterübergabe sehen um selbst eigene Kommandos zu realisieren.
Dieser Kommandozeileninterpreter war lange Zeit die Basis meiner Versuche und Tests mit dem ersten Prototypen. Mit den entsprechenden Kommandos wird daraus ein Speichermonitor, ein Bustest, ein Speichertest usw.
Testroutinen zur Parameterübergabe PUB fPara | stradr, i 'cmd: para - test parameterübergabe i := 0 repeat stradr := os_nextpara 'nächsten parameter aus tib in puffer kopieren if stradr > 0 sios.print(string("Parameter ")) sios.printdec(i++) sios.print(string(" : ")) sios.print(stradr) sios.printnl until stradr == 0 'wiederhole bis kein parameter mehr vorhanden PUB fParaNum | stradr, i, n, m 'cmd: paranum - test zahlenparameter i := 0 m := 0 repeat stradr := os_nextpara 'nächsten parameter aus tib in puffer kopieren if stradr > 0 sios.print(string("Parameter ")) sios.printdec(i++) sios.print(string(" : ")) n := num.FromStr(stradr,num#dec) sios.printdec(n) sios.printnl m := m + n until stradr == 0 'wiederhole bis kein parameter mehr vorhanden sios.print(string("Summe : ")) sios.printdec(m) sios.printnl |
Seite 1 – Seite 2 – Seite 3 – Fortsetzung