/**********************************************************************\ * 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 // Standard Ein-/Ausgabe #include // Standardbibliothek (z.B. für malloc) #include "automat.h" // Eigene Headerdatei für Automatentypen und -funktionen /*--- #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) /*--- 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 /* 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 } 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 } fsm_full_state_t; /*--- Modulglobale static Variablen ----------------------------------*/ /* Definition der Zustandsvariablen */ static state_t s_curstate = A; /* Initialisierung */ // Aktueller Zustand, Start bei A /* 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 }; static const fsm_state_t s_transitions_B[] = { { 0x002, ~0x004, C }, { 0x003, ~0x004, D } }; static const fsm_state_t s_transitions_C[] = { { 0x002, ~0x004, D }, { 0x003, ~0x000, F }, { 0x007, ~0x000, H } }; static const fsm_state_t s_transitions_D[] = { { 0x002, ~0x000, F }, { 0x003, ~0x004, E }, { 0x006, ~0x000, H } }; static const fsm_state_t s_transitions_E[] = { { 0x002, ~0x000, F }, { 0x003, ~0x004, E }, { 0x006, ~0x000, H } }; static const fsm_state_t s_transitions_F[] = { { 0x002, ~0x001, G }, { 0x004, ~0x001, H }, { 0x006, ~0x001, I } }; static const fsm_state_t s_transitions_G[] = { { 0x002, ~0x001, G }, { 0x004, ~0x001, H }, { 0x006, ~0x001, I } }; static const fsm_state_t s_transitions_H[] = { { 0x000, ~0x001, A }, { 0x002, ~0x000, B }, { 0x003, ~0x000, C }, { 0x006, ~0x001, I } }; static const fsm_state_t s_transitions_I[] = { { 0x000, ~0x001, A }, { 0x002, ~0x000, B }, { 0x003, ~0x000, C }, { 0x006, ~0x001, I } }; /* Definition der Uebergangstabelle */ /* Die Reihenfolge der Zustaende in der enum Definition muss der * 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 }; /* 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 */ }; /*--- Funktionsdefinition --------------------------------------------*/ void automat_reset(void) { printf("---- automat_reset ----\n"); // Ausgabe zur Kontrolle s_curstate = A; // Automat in Startzustand (A) zurücksetzen } /*--- 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 } } /*--- Funktionsdefinition --------------------------------------------*/ fsm_action_t automat_output(void) { return s_out_table[s_curstate]; // Aktuelle Ausgabewerte für Zustand zurückgeben } //gcc automat.c view.c main.c io.c checker.c -o console_automat