From d48bacbae713bd85e2761be5962018613978ef4a Mon Sep 17 00:00:00 2001 From: Bora Date: Wed, 11 Jun 2025 11:04:50 +0200 Subject: [PATCH] halo --- Modul4/automat.c | 222 ++++++++++++++++++++++++++++++----------------- 1 file changed, 144 insertions(+), 78 deletions(-) diff --git a/Modul4/automat.c b/Modul4/automat.c index 0bd02b2..7b2b469 100644 --- a/Modul4/automat.c +++ b/Modul4/automat.c @@ -1,98 +1,164 @@ +/**********************************************************************\ +* 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 #include "automat.h" -typedef enum {A=0, B, C, D, E, F, NR_OF_STATES} state_t; +/*--- #defines -------------------------------------------------------*/ +/* Macro zur Ermittlung der Array Groesse */ +#define SIZE_OF(a) (sizeof((a))/ sizeof(*(a))) +#define NR_OF_STATES (I-A+1) // Achtung: A=0, I=8, ergibt 9 Zustände -static state_t s_curstate = A; -static int s_guthaben = 0; -static bool s_kaffee_los = false; -static bool s_muenz_rueck = false; -static bool s_display = false; -static const char* s_display_string = "Warten"; +/*--- Datentypen (typedef) -------------------------------------------*/ +/* Definition der Zustaende */ +typedef enum {A=0,B,C,D,E,F,G,H,I} state_t; +/* Struktur zur Beschreibung eines Uebergangs mit "Don't Care"-Moeglichkeit */ +typedef struct { + int input; + int mask; + state_t nxtstate; +} fsm_state_t; + +/* Struktur zur Beschreibung aller Uebergaenge eines Zustands */ +typedef struct { + 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 */ + +/* Definition aller Zustandsuebergaenge fuer jeden Zustand */ +/* Die Masken sind invertiert, was ungewöhnlich ist, aber beibehalten. */ +static const fsm_state_t s_transitions_A[] = { + /* input mask nxtstate */ + { 0x002, ~0x004, B }, + { 0x003, ~0x004, C } +}; +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 */ +static const fsm_full_state_t s_state_table[NR_OF_STATES] = { + /* 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), A }, + { s_transitions_E, SIZE_OF(s_transitions_E), D }, + { s_transitions_F, SIZE_OF(s_transitions_F), F }, + { s_transitions_G, SIZE_OF(s_transitions_G), F }, + { s_transitions_H, SIZE_OF(s_transitions_H), H }, + { s_transitions_I, SIZE_OF(s_transitions_I), H } +}; + +/* 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 --------------------------------------------*/ +/* Setzt den Automaten in den Startzustand zurück */ void automat_reset(void) { - s_curstate = A; - s_guthaben = 0; - s_kaffee_los = false; - s_muenz_rueck = false; - s_display = false; - s_display_string = "Warten"; + printf("---- automat_reset ----\n"); + s_curstate = A; } +/* Führt einen Zustandsübergang durch, basierend auf den Eingaben */ void automat_transition(BOOL becher, BOOL muenze, BOOL muenz_wert) { - s_kaffee_los = false; - s_muenz_rueck = false; - s_display = false; + printf("---- automat_transition becher(%0d) muenze(%0d) muenz_wert(%0d) ----\n", + becher, muenze, muenz_wert); - int wert = muenz_wert ? 2 : 1; + /* Eingabewert als Bitfeld kodieren: becher=Bit2, muenze=Bit1, muenz_wert=Bit0 */ + int in = (becher << 2) | (muenze << 1) | (muenz_wert << 0); - switch (s_curstate) { - case A: case B: case C: case D: case E: - // Münzeinwurf - if (muenze) { - if (s_guthaben + wert > 4) { - s_muenz_rueck = true; - s_display = true; - s_display_string = "Zu viel! Münze zurück"; - break; - } else { - s_guthaben += wert; - } - } + const fsm_full_state_t * full_transition = &s_state_table[s_curstate]; + const fsm_state_t * transition = full_transition->transitions; + int i; - // Guthaben prüfen - if (s_guthaben < 4) { - if (s_guthaben == 0) { s_curstate = A; s_display_string = "Warten"; } - else if (s_guthaben == 1) { s_curstate = B; s_display_string = "1 Euro"; } - else if (s_guthaben == 2) { s_curstate = C; s_display_string = "2 Euro"; } - else if (s_guthaben == 3) { s_curstate = D; s_display_string = "3 Euro"; } - // Kein Display aktivieren! - } else if (s_guthaben == 4) { - if (becher) { - s_curstate = F; - s_kaffee_los = true; - s_display = true; - s_display_string = "Kaffee wird ausgegeben"; - s_guthaben = 0; - } else { - s_curstate = E; - s_display = true; - s_display_string = "Bitte Becher unterstellen!"; - } - } - break; - - case F: - s_display = true; - s_display_string = "Becher entnehmen"; - if (!becher) { - s_curstate = A; - s_display = false; - s_display_string = "Warten"; - } - break; - - default: - s_curstate = A; - s_guthaben = 0; - s_display = false; - s_display_string = "Warten"; - break; - } + /* Übergänge prüfen */ + for(i = 0; i < full_transition->nrOfTransitions; i++) + { + /* Maskenlogik: input == (in & mask) */ + if(transition[i].input == (in & transition[i].mask)) + { + s_curstate = transition[i].nxtstate; + break; + } + } + /* Wenn kein Übergang passt, gehe in den Default-Zustand */ + if(i == full_transition->nrOfTransitions) + { + s_curstate = full_transition->defaultNxtState; + } } +/* Gibt die aktuellen Ausgänge des Automaten zurück */ fsm_action_t automat_output(void) { - return (fsm_action_t){ - .display = s_display, - .muenz_rueck = s_muenz_rueck, - .kaffee_los = s_kaffee_los, - .guthaben = s_guthaben, - .display_string = s_display_string - }; + return s_out_table[s_curstate]; } - //gcc automat.c view.c main.c io.c checker.c -o console_automat