2009-03-02 19 views
10

Ich habe eine (etwas) große Wahrheitstabelle/Zustandsmaschine, die ich in meinem Code (eingebettetes C) implementieren muss. Ich gehe davon aus, dass sich die Verhaltensspezifikation dieser Zustandsmaschine in Zukunft ändern wird, und deshalb möchte ich diese in der Zukunft leicht modifizierbar halten.Wahrheitstabellen im Code? Wie man Zustandsmaschine strukturiert?

Meine Wahrheitstabelle hat 4 Eingänge und 4 Ausgänge. Ich habe alles in einer Excel-Tabelle, und wenn ich das einfach mit ein wenig Formatierung in meinen Code einfügen könnte, wäre das ideal.

Ich dachte, ich mag meine Wahrheitstabelle für den Zugriff auf in etwa so:

u8 newState[] = decisionTable[input1][input2][input3][input4]; 

Und dann konnte ich den Ausgangswert Zugriff mit:

setOutputPin(LINE_0, newState[0]); 
setOutputPin(LINE_1, newState[1]); 
setOutputPin(LINE_2, newState[2]); 
setOutputPin(LINE_3, newState[3]); 

Aber damit es zu bekommen, sieht so aus als ob ich eine ziemlich verwirrende Tabelle machen müsste:

static u8 decisionTable[][][][][] = 
{{{{ 0, 0, 0, 0 }, 
    { 0, 0, 0, 0 }}, 
    {{ 0, 0, 0, 0 }, 
    { 0, 0, 0, 0 }}}, 
    {{{ 0, 0, 1, 1 }, 
    { 0, 1, 1, 1 }}, 
    {{ 0, 1, 0, 1 }, 
    { 1, 1, 1, 1 }}}}, 
{{{{ 0, 1, 0, 1 }, 
    { 1, 1, 1, 1 }}, 
    {{ 0, 1, 0, 1 }, 
    { 1, 1, 1, 1 }}}, 
    {{{ 0, 1, 1, 1 }, 
    { 0, 1, 1, 1 }}, 
    {{ 0, 1, 0, 1 }, 
    { 1, 1, 1, 1 }}}}; 

Diese verschachtelten Klammern ca n etwas verwirrend sein - hat jemand eine bessere Idee dafür, wie ich einen hübsch aussehenden Tisch in meinem Code behalten kann?

Danke!

bearbeiten basierend auf HUAGHAGUAH Antwort:

eine Verschmelzung aller-Eingabe (danke - ich wünschte, ich könnte „akzeptieren“ 3 oder 4 dieser Antworten), ich denke, ich werde es versuchen als ein zweidimensionales Array. Ich werde Index in meinen Array ein kleines Bitverschiebung Makro weiter:

#define SM_INPUTS(in0, in1, in2, in3) ((in0 << 0) | (in1 << 1) | (in2 << 2) | (in3 << 3)) 

Und das wird meine Wahrheitstabelle Array wie folgt aussehen lassen:

static u8 decisionTable[][] = { 
{ 0, 0, 0, 0 }, 
{ 0, 0, 0, 0 }, 
{ 0, 0, 0, 0 }, 
{ 0, 0, 0, 0 }, 
{ 0, 0, 1, 1 }, 
{ 0, 1, 1, 1 }, 
{ 0, 1, 0, 1 }, 
{ 1, 1, 1, 1 }, 
{ 0, 1, 0, 1 }, 
{ 1, 1, 1, 1 }, 
{ 0, 1, 0, 1 }, 
{ 1, 1, 1, 1 }, 
{ 0, 1, 1, 1 }, 
{ 0, 1, 1, 1 }, 
{ 0, 1, 0, 1 }, 
{ 1, 1, 1, 1 }}; 

Und ich kann zugreifen dann meine Wahrheitstabelle wie also:

decisionTable[ SM_INPUTS(line1, line2, line3, line4) ] 

Ich gebe das einen Schuss und sehe, wie es funktioniert. Ich werde auch die 0 und 1 durch hilfreichere # defines ersetzen, die ausdrücken, was jeder Zustand bedeutet, zusammen mit/**/Kommentaren, die die Eingaben für jede Zeile von Ausgaben erklären. Danke für die Hilfe, alle!

+0

Da Sie eingebettet sind, sollte der Speicher eine Ressourcenbeschränkung sein? – EvilTeach

+0

@EvilTeach: Danke für die Frage. Obwohl es eingebettet ist, laufen wir auf ziemlich schwerem Eisen mit viel Flash und RAM herum (im Rahmen des Zumutbaren). Codelesbarkeit ist hier der wichtigste Faktor. – HanClinto

+0

Ein mehr. Haben Sie einen API-Anruf, mit dem Sie alle 4 Pins gleichzeitig setzen können? – EvilTeach

Antwort

3

Keine Notwendigkeit für eine multidimensionale Tabelle. Mit einem 4 Bit => 4 Bit-Mapping können Sie ein einzelnes u8 [16] -Array verwenden, das Eingänge auf Ausgänge abbildet. Zustandssuchen werden viel billiger, und Sie können einzelne Bits mit einigen Schiebe-und-Maske-Operationen extrahieren.

Wenn der Algorithmus zum Auffüllen von Zeilen einfach zu kodieren ist, können Sie # ein Makro definieren, um jede Zeile nach Indexnummer zu füllen.

+0

Ich mag diese Antwort am besten. Ich könnte es immer noch als zweidimensionales Array behalten (zu Array-ify meine Ausgänge), aber ich mag die Idee, die Eingänge in einen einzigen 4-Bit-Index zu kombinieren.Weil alle Ein- und Ausgänge Boolean sind, wird dies gut funktionieren. Danke! – HanClinto

3

Persönlich würde ich es aus einer Konfigurationsdatei lesen. Vielleicht CSV, das einfach aus Excel exportiert werden kann. Oder Sie können einfach aus Excel in einfachen Text kopieren und einfügen, wodurch Sie durch Leerzeichen getrennte Werte erhalten, die ebenso einfach zu importieren sind.

Dies bedeutet auch, dass Sie, wenn Sie mit C arbeiten, nicht jedes Mal, wenn sich die Entscheidungstabelle ändert, Ihren Code neu kompilieren müssen.

+0

@duffymo dieser Link ist jetzt tot :( –

+0

Die Antwort ist vier Jahre alt, und der Link scheint neun zu sein, so ist es keine Überraschung. – duffymo

4

würde ich vorschlagen, entweder (bevorzugte Ansätze zuerst):

  • ein Makro Verwenden Sie jede „Zeile“ intialize - dies wird die Klammern innerhalb des Makroaufruf verstecken.
  • Verwenden Sie Kommentare, um die Zeilen aufzuteilen.
  • Verwenden Sie eine Init-Funktion, um den Kontext explizit zu initialisieren - vielleicht verwenden Sie Funktionen, um jeden Abschnitt zu initialisieren. Dies ist ähnlich der ersten Option oben, hat aber den Nachteil, dass die init-Funktion aufgerufen werden muss, bevor die Zustandsmaschine verwendet werden kann.
2

Wenn Ihre Wahrheitstabelle boolesch ist, können Sie sie einfach auf eine Liste von Paaren reduzieren, z.

1111,0000 
1110,0110 
... 

zur Datenkompression, stellen die Werte als Bytes (zwei Nibbles) ...

wo/wie sie gespeichert wird für Soft-Codierung in Ihrer speziellen Embedded-System-Konfiguration, können nur Sie sagen; -)

+0

@ [EvilTeach] danke für die Bearbeitung, aber ich bevorzuge die y-Rechtschreibung (http://en.wikipedia.org/wiki/Nybble) –

+0

@SAL: Tolle Vorschläge, danke! Dies ist in der Tat eine der Ideen, die ich in meine Lösung gerollt - sehr geschätzt. – HanClinto

1

Wenn die Wahrheitstabelle wirklich nur 4x4x4x4 ist, dann würde ich Makros verwenden. Wenn es jemals darüber hinaus wachsen würde, würde ich Ragel verwenden. Wahrscheinlich wird es kleineren, schnelleren C-Code als Sie werden.

+0

Ordentliches Werkzeug! Wie Gbarry sagte, Ich denke, mein Problem ist mehr auf Wahrheitstabellen als auf Zustandsautomaten ausgerichtet, aber dies ist ein ausgezeichnetes Werkzeug, um in seinem Köcher zu bleiben. Danke! – HanClinto

1

Ich sehe keinen Verweis auf den aktuellen Status, um Ihren Ausgangszustand zu erhalten. Dies bedeutet, dass es keine Zustandsmaschine ist, sondern nur eine Wahrheitstabelle. Es gibt vier Eingänge, daher gibt es nur 16 mögliche Eingangskombinationen. Also, eine Tabelle mit 16 Positionen sollte es tun.

+0

Guter Punkt - eines der Dinge Ich habe nicht erwähnt, dass der zukünftige Wert einer der Eingabespalten eine der Ausgabespalten ist, also gibt es eine kleine Zustandsmaschine innerhalb der Wahrheitstabelle. Aber ja, der Einfachheit halber ist es wahrscheinlich am besten, dies als eine reine Zustandsmaschine zu betrachten. Tolle Kommentare, danke! – HanClinto

+0

Eigentlich ist es meistens die Zustandsmaschine, die eine Wahrheitstabelle enthält. Die Zustände sind Latches, die von Ausgabe zu Eingabe gehen. Ich denke, du meinst, du wirst es als reinen Wahrheitstisch behandeln.Sobald es funktioniert, ist der Rest natürlich nur Semantik. – gbarry

1

Normalerweise versucht man, wenn man ein Problem wie dieses hat, es auf eine einfache boolesche Formel zu reduzieren. Ich sehe nicht, warum das hier nicht der beste Weg wäre. Es wäre viel kompakter und lesbarer, und es hätte das Potenzial, schneller zu sein (ich stelle mir vor, dass eine Handvoll ANDs und ORs schneller ausgeführt werden würde als die Sammlung von Multiplikationen/Verschiebungen + Speicherzugriff, die für den Lookup-Tabellenansatz benötigt werden). Der einfachste Weg, diese Tabelle auf eine boolesche Formel zu reduzieren, ist eine K-Map.

+0

@rmeador: Der Hauptgrund, warum ich es nicht auf Boolesche Logik reduzieren wollte, ist nur, weil ich wollte, dass es sowohl leicht lesbar als auch leicht modifizierbar ist. Außerdem wollte ich bei der Optimierung meiner Booleschen Logik keine Annahmen treffen, die erfordern, dass meine Logik bei jeder Änderung vollständig neu programmiert wird. – HanClinto