diff --git a/Modul4/automat.c b/Modul4/automat.c index 3b70f08..f5f5446 100644 --- a/Modul4/automat.c +++ b/Modul4/automat.c @@ -1,156 +1,240 @@ /**********************************************************************\ -* Kurzbeschreibung: automat.c -* Stellt Funktionen zur Realisierung eines Automaten zur Verfügung, -* die über die in der automat.h vorgegebene C-Schnittstelle -* mit einer grafischen Schnittstelle kommunizieren. -* -* Datum: Autor: Grund der Aenderung: -* -* + * Kurzbeschreibung: automat.c + * Stellt Funktionen zur Realisierung eines Automaten zur Verfügung, + * die über die in der automat.h vorgegebene C-Schnittstelle + * mit einer grafischen Schnittstelle kommunizieren. + * + * Datum: Autor: Grund der Aenderung: + * + * \**********************************************************************/ #include #include #include "automat.h" + /*--- #defines -------------------------------------------------------*/ /* Macro zur Ermittlung der Array Groesse */ -#define SIZE_OF(a) (sizeof((a))/ sizeof(*(a))) // Gibt die Anzahl der Elemente eines Arrays zurück -#define NR_OF_STATES (I-A + 1) // Anzahl der Zustände (Enum von A bis I) +#define SIZE_OF(a) (sizeof((a))/ sizeof(*(a))) + +#define NR_OF_STATES (I-A + 1) + /*--- Datentypen (typedef) -------------------------------------------*/ /* Definition der Zustaende */ -typedef enum {A=0,B,C,D,E,F,G,H,I} state_t; // Aufzählung der Zustände von A bis I +typedef enum {A=0,B,C,D,E,F,G,H,I} state_t; + /* Definition der fsm-spezifischen Variablen */ /* Struktur zur Beschreibung eines Uebergangs mit "Don't Care"-Moeglichkeit */ typedef struct { - int input; // Erwarteter Eingabewert (Bitmaske) - int mask; // Maske für relevante Bits - state_t nxtstate; // Zielzustand bei passender Eingabe + int input; + int mask; + state_t nxtstate; } fsm_state_t; + /* Struktur zur Beschreibung aller Uebergaenge eines Zustands */ typedef struct { - const fsm_state_t * transitions; // Zeiger auf Array von Übergängen - int nrOfTransitions; // Anzahl der Übergänge - state_t defaultNxtState; // Standard-Zielzustand, falls keine Transition passt + const fsm_state_t * transitions; + int nrOfTransitions; + state_t defaultNxtState; } fsm_full_state_t; + /*--- Modulglobale static Variablen ----------------------------------*/ /* Definition der Zustandsvariablen */ -static state_t s_curstate = A; /* Initialisierung */ // Aktueller Zustand, Start bei A +static state_t s_curstate = A; /* Initialisierung */ + /* Definition aller Zustandsuebergaenge fuer jeden Zustand */ static const fsm_state_t s_transitions_A[] = { /* input mask nxtstate */ - { 0x002, ~0x004, B }, // Übergang zu B bei passender Eingabe - { 0x003, ~0x004, C } // Übergang zu C bei anderer Eingabe + // Wenn 1?-Münze eingeworfen (muenze=1, muenz_wert=0), egal ob Becher steht oder nicht (weil mask ~0x004, also becher-Bit egal) + { 0x002, ~0x004, B }, // A -> B: 1? eingeworfen + // Wenn 2?-Münze eingeworfen (muenze=1, muenz_wert=1), egal ob Becher steht oder nicht + { 0x003, ~0x004, C } // A -> C: 2? eingeworfen }; + static const fsm_state_t s_transitions_B[] = -{ - { 0x002, ~0x004, C }, - { 0x003, ~0x004, D } +{ /* input mask nxtstate */ + // Nochmal 1? eingeworfen (muenze=1, muenz_wert=0), becher egal + { 0x002, ~0x004, C }, // B -> C: 1? dazu, jetzt 2? + // 2? eingeworfen (muenze=1, muenz_wert=1), becher egal + { 0x003, ~0x004, D } // B -> D: 2? dazu, jetzt 3? }; + static const fsm_state_t s_transitions_C[] = -{ - { 0x002, ~0x004, D }, - { 0x003, ~0x000, F }, - { 0x007, ~0x000, H } +{ /* input mask nxtstate */ + // Nochmal 1? eingeworfen (muenze=1, muenz_wert=0), becher egal + { 0x002, ~0x004, D }, // C -> D: 1? dazu, jetzt 3? + // Becher steht (becher=1), egal was mit Münze, weil mask ~0x000 (alle Bits relevant) + { 0x003, ~0x000, F }, // C -> F: Becher untergestellt (becher=1, muenze=1, muenz_wert=1) + // Becher steht (becher=1), muenze=1, muenz_wert=1 (also 2?), mask ~0x000 + { 0x007, ~0x000, H } // C -> H: Becher steht, 2? eingeworfen }; + static const fsm_state_t s_transitions_D[] = -{ - { 0x002, ~0x000, F }, - { 0x003, ~0x004, E }, - { 0x006, ~0x000, H } +{ /* input mask nxtstate */ + // Becher steht (becher=1), egal was mit Münze, mask ~0x000 + { 0x002, ~0x000, F }, // D -> F: Becher untergestellt + // 2? eingeworfen (muenze=1, muenz_wert=1), becher egal + { 0x003, ~0x004, E }, // D -> E: 2? dazu, jetzt 5? (Überzahlung) + // Becher steht (becher=1), muenze=1, muenz_wert=0 (1?), mask ~0x000 + { 0x006, ~0x000, H } // D -> H: Becher steht, 1? eingeworfen }; + static const fsm_state_t s_transitions_E[] = { - { 0x002, ~0x000, F }, - { 0x003, ~0x004, E }, - { 0x006, ~0x000, H } + // Becher steht (becher=1), egal was mit Münze + { 0x002, ~0x000, F }, // E -> F: Becher untergestellt + // 2? eingeworfen, becher egal + { 0x000, ~0x005, D }, // E bleibt E: weitere Überzahlung + // Becher steht (becher=1), muenze=1, muenz_wert=0 (1?) + { 0x006, ~0x000, H } // E -> H: Becher steht, 1? eingeworfen }; + static const fsm_state_t s_transitions_F[] = { - { 0x002, ~0x001, G }, - { 0x004, ~0x001, H }, - { 0x006, ~0x001, I } + // Becher steht, 1? eingeworfen (becher=1, muenze=1, muenz_wert=0), mask ~0x001 (muenz_wert egal) + { 0x002, ~0x001, G }, // F -> G: Becher steht, Münze eingeworfen + // Becher steht, 2? eingeworfen (becher=1, muenze=0, muenz_wert=1) + { 0x004, ~0x001, H }, // F -> H: Becher steht, 2? eingeworfen + // Becher steht, 1? eingeworfen (becher=1, muenze=1, muenz_wert=0) + { 0x006, ~0x001, I } // F -> I: Becher steht, 1? eingeworfen }; + static const fsm_state_t s_transitions_G[] = { - { 0x002, ~0x001, G }, - { 0x004, ~0x001, H }, - { 0x006, ~0x001, I } + // Becher steht, 1? eingeworfen + { 0x000, ~0x001, F }, // G bleibt G: Becher steht, Münze eingeworfen + // Becher steht, 2? eingeworfen + { 0x004, ~0x001, H }, // G -> H: Becher steht, 2? eingeworfen + // Becher steht, 1? eingeworfen + { 0x006, ~0x001, I } // G -> I: Becher steht, 1? eingeworfen }; + static const fsm_state_t s_transitions_H[] = { - { 0x000, ~0x001, A }, - { 0x002, ~0x000, B }, - { 0x003, ~0x000, C }, - { 0x006, ~0x001, I } + // Kein Becher, keine Münze, kein Wert (alles 0) + { 0x000, ~0x001, A }, // H -> A: Reset, alles leer + // Becher steht, keine Münze, kein Wert + { 0x002, ~0x000, B }, // H -> B: Becher steht, 1? eingeworfen + // Becher steht, 2? eingeworfen + { 0x003, ~0x000, C }, // H -> C: Becher steht, 2? eingeworfen + // Becher steht, 1? eingeworfen + { 0x006, ~0x001, I } // H -> I: Becher steht, 1? eingeworfen }; + static const fsm_state_t s_transitions_I[] = -{ - { 0x000, ~0x001, A }, - { 0x002, ~0x000, B }, - { 0x003, ~0x000, C }, - { 0x006, ~0x001, I } + { // Kein Becher, keine Münze, kein Wert (alles 0) + { 0x000, ~0x001, A }, // I -> A: Reset, alles leer + // Becher steht, keine Münze, kein Wert + { 0x002, ~0x000, B }, // I -> B: Becher steht, 1? eingeworfen + // Becher steht, 2? eingeworfen + { 0x003, ~0x000, C }, // I -> C: Becher steht, 2? eingeworfen + // Becher steht, 1? eingeworfen + { 0x004, ~0x001, H} // I bleibt I: Becher steht, 1? eingeworfen }; + /* Definition der Uebergangstabelle */ /* Die Reihenfolge der Zustaende in der enum Definition muss der -* Reihenfolge der Zustaende in der Uebergangstabelle entsprechen -* [Zeile] [Spalte] */ + * Reihenfolge der Zustaende in der Uebergangstabelle entsprechen + * [Zeile] [Spalte] */ static const fsm_full_state_t s_state_table[NR_OF_STATES] = { - /* transitions nrOfTransitions defaultNxtState */ - { s_transitions_A, SIZE_OF(s_transitions_A), A }, // Zustand A - { s_transitions_B, SIZE_OF(s_transitions_B), B }, // Zustand B - { s_transitions_C, SIZE_OF(s_transitions_C), C }, // Zustand C - { s_transitions_D, SIZE_OF(s_transitions_D), D }, // Zustand D - { s_transitions_E, SIZE_OF(s_transitions_E), D }, // Zustand E - { s_transitions_F, SIZE_OF(s_transitions_F), F }, // Zustand F - { s_transitions_G, SIZE_OF(s_transitions_G), F }, // Zustand G - { s_transitions_H, SIZE_OF(s_transitions_H), H }, // Zustand H - { s_transitions_I, SIZE_OF(s_transitions_I), H } // Zustand I - }; + /* transitions nrOfTransitions defaultNxtState */ + { s_transitions_A, SIZE_OF(s_transitions_A), A }, + { s_transitions_B, SIZE_OF(s_transitions_B), B }, + { s_transitions_C, SIZE_OF(s_transitions_C), C }, + { s_transitions_D, SIZE_OF(s_transitions_D), D }, + + /* TODO */ + + { s_transitions_E, SIZE_OF(s_transitions_E), E }, + { s_transitions_F, SIZE_OF(s_transitions_F), F }, + { s_transitions_G, SIZE_OF(s_transitions_G), G }, + { s_transitions_H, SIZE_OF(s_transitions_H), H }, + { s_transitions_I, SIZE_OF(s_transitions_I), I } + }; + /* Definition der Ausgaenge */ static const fsm_action_t s_out_table[NR_OF_STATES] = { - /* display muenz_rueck kaffee_los guthaben, display_string */ - { false, false, false, 0, "Warten" }, /* state A */ - { false, false, false, 1, "1 Euro" }, /* state B */ - { false, false, false, 2, "2 Euro" }, /* state C */ - { false, false, false, 3, "3 Euro" }, /* state D */ - { false, true, false, 3, "3 Euro" }, /* state E */ - { true, false, false, 4, "Becher unterstellen" }, /* state F */ - { true, true, false, 4, "Becher unterstellen" }, /* state G */ - { true, false, true, 0, "Kaffe kommt" }, /* state H */ - { true, true, true, 0, "Kaffe kommt" } /* state I */ + /* display muenz_rueck kaffee_los guthaben, display_string */ + { false, false, false, 0, "Warten" }, /* state A */ + { false, false, false, 1, "1 Euro" }, /* state B */ + { false, false, false, 2, "2 Euro" }, /* state C */ + { false, false, false, 3, "3 Euro" }, /* state D */ + + /* TODO */ + + { false, true, false, 3, "3 Euro + M" }, /* state E */ + { true, false, false, 4, "4 Euro" }, /* state F */ + { true, true, false, 4, "4 Euro + M" }, /* state G */ + { true, false, true, 0, "Kaffe kommt" }, /* state H */ + { true, true, true, 0, "Kaffe + M" } /* state I */ + }; + /*--- Funktionsdefinition --------------------------------------------*/ void automat_reset(void) { - printf("---- automat_reset ----\n"); // Ausgabe zur Kontrolle - s_curstate = A; // Automat in Startzustand (A) zurücksetzen + printf("---- automat_reset ----\n"); + + /* TODO go into IDLE state */ + + s_curstate = A; + } + /*--- Funktionsdefinition --------------------------------------------*/ void automat_transition(BOOL becher, BOOL muenze, BOOL muenz_wert) { - printf("---- automat_transition becher(%0d) muenze(%0d) muenz_wert(%0d) ----\n", - becher, muenze, muenz_wert); // Eingaben ausgeben - int in = (becher << 2) | (muenze << 1) | (muenz_wert << 0); // Eingabewert als Bitmuster kodieren - const fsm_full_state_t * full_transition = &s_state_table[s_curstate]; // Übergangstabelle für aktuellen Zustand holen - const fsm_state_t * transition = full_transition->transitions; // Zeiger auf Übergänge - int i; - for(i = 0; i < full_transition->nrOfTransitions; i++) // Alle möglichen Übergänge prüfen - { - if(transition[i].input == (in & transition[i].mask)) // Prüfen, ob Eingabe zur Transition passt - { - s_curstate = transition[i].nxtstate; // In Zielzustand wechseln - break; // Schleife verlassen - } - } - if(i == full_transition->nrOfTransitions) // Falls keine Transition gepasst hat - { - s_curstate = full_transition->defaultNxtState; // In Default-Zustand wechseln - } + // Ausgabe der aktuellen Eingabewerte zur Fehlersuche + printf("---- automat_transition becher(%0d) muenze(%0d) muenz_wert(%0d) ----\n", + becher, muenze, muenz_wert); + + // Kombiniere die Eingabewerte zu einem einzigen Integer mittels Bitoperationen. + // Die Eingaben werden wie folgt kombiniert: + // - 'becher' wird um 2 Bits nach links verschoben (belegt die dritte Bitposition) + // - 'muenze' wird um 1 Bit nach links verschoben (belegt die zweite Bitposition) + // - 'muenz_wert' bleibt in der ersten Bitposition + // Dies ergibt einen 3-Bit-Integer, der den aktuellen Eingabestatus darstellt. + int in = (becher << 2) | (muenze << 1) | (muenz_wert << 0); + + // Hole die Übergangsinformationen des aktuellen Zustands aus der Zustandstabelle. + // 's_curstate' enthält den aktuellen Zustand, und 's_state_table' liefert die + // Übergangsdetails für jeden Zustand. + const fsm_full_state_t * full_transition = &s_state_table[s_curstate]; + + // Hole das Array der Übergänge für den aktuellen Zustand. + // Jeder Übergang spezifiziert eine Eingabebedingung, eine Maske und einen Folgezustand. + const fsm_state_t * transition = full_transition->transitions; + int i; + + // Iteriere über alle definierten Übergänge für den aktuellen Zustand. + for(i = 0; i < full_transition->nrOfTransitions; i++) + { + // Überprüfe, ob die aktuelle Eingabe die Übergangsbedingung erfüllt. + // Die Bedingung ist erfüllt, wenn die Eingabe, maskiert durch die Übergangsmaske, + // dem spezifizierten Eingabewert des Übergangs entspricht. + if(transition[i].input == (in & transition[i].mask)) + { + // Wenn ein passender Übergang gefunden wird, aktualisiere den aktuellen Zustand + // auf den im Übergang spezifizierten Folgezustand. + s_curstate = transition[i].nxtstate; + // Beende die Schleife, da der Übergang erfolgreich angewendet wurde. + break; + } + } + + // Wenn nach Überprüfung aller Übergänge kein passender Übergang gefunden wurde, + // setze den aktuellen Zustand auf den Standard-Folgezustand für den aktuellen Zustand. + // Dies behandelt Fälle, in denen die Eingabe keinem spezifischen Übergang entspricht. + if(i == full_transition->nrOfTransitions) + { + s_curstate = full_transition->defaultNxtState; + } } /*--- Funktionsdefinition --------------------------------------------*/ fsm_action_t automat_output(void) { - return s_out_table[s_curstate]; // Aktuelle Ausgabewerte für Zustand zurückgeben + return s_out_table[s_curstate]; } + //gcc automat.c view.c main.c io.c checker.c -o console_automat \ No newline at end of file