PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : ESC-Interpreter - aber wie?



Import-Script
20.03.2004, 01:36
Hallo! <BR> <BR>F&uuml;r ein serielles Display &#40;per 80C31 &uuml;ber RS-232&#41; suche ich eine Möglichkeit Escape-Sequenzen richtig zu erkennen. Da ich mit &#39;selbsterlernten&#39; Assemblerkenntnissen programiere, ist die Sache doch etwas haarig, da mir keine passenden Ablaufschemen bekannt sind! <BR> <BR>Folgende Möglichkeiten sind mir eingefallen: <BR> <BR>- Das Prg. baumdiagramartig nach empfangenem ESC f&uuml;r jede Möglichkeit zu verzweigen und mit einem TimeOut zu versehen. <BR>Problem: irrer, un&uuml;bersichtlicher und speicherfressender Quelltext. Man nennt es wohl auch &#39;die Ochsentour&#39; mit Lizens zum Scheitern! <BR> <BR>- Nach vorgegebenen Zeichenketten im EmpfangsPuffer suchen und direkt in die entsprechende Routine springen. <BR>Problem: EmpfangsPuffer frißt wertvollen Speicher; wie verhindere ich Fehlinterpretationen zwischen z.B. &#39;Clr&#39; und &#39;ClrBuffer&#39; da der Befehl nicht &#40;mit z.B. ESC oder CRLF&#41; abgeschlossen wird und Leerzeichen zu ggf. &uuml;bergebenen Parametern fehlen? <BR> <BR>F&uuml;r einen Tip, Hinweise oder völlig anderen Lösungsansatz bin ich da echt dankbar...! <BR> <BR>Gruß, Arne <BR>

Bernd
27.03.2004, 15:57
Die einfachste Art so etwas zu implementieren, ist eine Status-Maschine a.k.a. Zustandsautomat.
Anstatt den "Zustand" anhand der Position im Quelltext zu speichern (das ist das, was Du als "baumartiges" Auffächern des Quelltextes angedeutet hast), speicherst Du je nach empfangenem Zeichen eine Zustandsnummer.

Beispiel (mit Ansi-Sequenzen):
Esc [ 2 J bedeutet "Bildschirm löschen"
Esc [ 0 m bedeutet "Normalschrift"
Esc [ 1 m bedeutet "Fettschrift"
Esc [ 2 m bedeutet "Unterstrichen" (jetzt mal als Beispiel, ist nicht original ANSI)

normalerweise befindet sich der Treiber im Zustand 0, d.h. alle Zeichen werden einfach weitergereicht.

wenn im Zustand 0 ein Esc empfangen wird, wechselt der Zustand nach 1, das Esc wird erst einmal geschluckt.

im Zustand 1 sollte als nächstes Zeichen ein "[" kommen. Kommt es, wechseln wir in den Zustand 2, kommt es nicht, wissen wir, daß das Esc nicht für uns bestimmt war und geben es einfach aus (wir wissen ja, daß wir im Zustand 1 sind, d.h. daß wir genau ein Esc gelesen haben). So reagieren wir immer, wenn ein "Syntax Error" kommt, d.h. ein Zeichen, das wir nicht erwartet haben. Es wird einfach die bisher empfangene Sequenz ausgegeben, und das war's dann.

Zustand 2: erlaubt wären bei den obigen Beispielen die Ziffer 0, 1 und 2. Wir wechseln in den Zustand 3 (namentlich "Ziffer empfangen") und speichern die Ziffer in einer extra Puffervariablen (das ist der Unterschied zwischen Kontrollzeichen wie die "Esc[" - Sequenz und den mitgelieferten Daten).
Kommt keine Ziffer, wird wieder wie oben "Esc[" und das gerade empfangene Zeichen ausgegeben.

Zustand 3: jetzt könnte bei "echtem" ANSI theoretisch ein ";" und noch weitere Argumente folgen... bei unserem Subset jedoch nicht. Wir lesen das ampfangene Zeichen und verzweigen in die entsprechende Verarbeitungsroutine, liefern natürlich die oben gespeicherte Ziffer mit.

Das ganze kommt mit relativ wenig Code aus, hier mal angedeutet, wie der Pseudocode auszusehen hat:

switch (state) {
case 0: if (c == ESC) state = 1; else output(c); break;
case 1: if (c == '[') state = 2; else { state = 0; output(ESC); output('['); } break;
case 2: if (isnum(c)) { state = 3; buf1 = c; } else { state = 0; output(ESC); output('['); output(c); } break;
case 3:
switch(c) {
case 'J': check_buf1_and_clear_screen(buf1); break;
case 'm': change_style(buf1); break;
default: // alles bisher gelesene ausgeben, wird hier zu länglich
}
default: // hier sollten wir nie hinkommen; als Fallback-Lösung einfach:
state = 0;
}

Wenn Du Beispiele suchst: es gab vor Jahren mal einen freien ANSI-Treiber namens NNANSI (8086-Assembler), oder schau in den Linux-Kernelquellen nach dem tty-Treiber für die Linux-Konsole (schön geschriebenes C).
Auch eine google-Suche nach State Machine bzw Zustandsautomat dürfte einiges an Hilfestellung liefern.

Viel Spaß damit!

Arne
31.03.2004, 06:40
Ja, danke erstmal!

Die Möglichkeit mit den Zuständen war mir so noch gar nicht aufgefallen. Damit werde ich dann mal anfangen. Weiter ausbauen kann ich es ja dann immer noch.

Mein anderes Problem mit erweiterten Befehlen (wie z.B. 'Clr' und 'ClrBuffer') sollte ich mit einer Prioritätssteuerung über eine Befehlsliste in den Griff bekommen, d.h. solange nur 'Clr' empangen wurde, beide genannten Befehle in Aussicht stehen, wird zuerst auf 'ClrBuffer' geprüft. Solange dieses möglich ist, wird die Befehlsliste bis 'Clr' gar nicht erst durchlaufen. In Kombination mit 'erweiterten Zuständen' habe ich das, was ich wollte! *freu-freu-freu*

Dank und Gruß,
Arne