This commit is contained in:
Bora Zuenbuelkoek 2025-06-13 10:29:10 +02:00
parent 923049e6a1
commit e6857d28b1

View File

@ -11,84 +11,126 @@
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include "automat.h" #include "automat.h"
/*--- #defines -------------------------------------------------------*/ /*--- #defines -------------------------------------------------------*/
/* Macro zur Ermittlung der Array Groesse */ /* Macro zur Ermittlung der Array Groesse */
#define SIZE_OF(a) (sizeof((a))/ sizeof(*(a))) // Gibt die Anzahl der Elemente eines Arrays zurück #define SIZE_OF(a) (sizeof((a))/ sizeof(*(a)))
#define NR_OF_STATES (I-A + 1) // Anzahl der Zustände (Enum von A bis I)
#define NR_OF_STATES (I-A + 1)
/*--- Datentypen (typedef) -------------------------------------------*/ /*--- Datentypen (typedef) -------------------------------------------*/
/* Definition der Zustaende */ /* 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 */ /* Definition der fsm-spezifischen Variablen */
/* Struktur zur Beschreibung eines Uebergangs mit "Don't Care"-Moeglichkeit */ /* Struktur zur Beschreibung eines Uebergangs mit "Don't Care"-Moeglichkeit */
typedef struct { typedef struct {
int input; // Erwarteter Eingabewert (Bitmaske) int input;
int mask; // Maske für relevante Bits int mask;
state_t nxtstate; // Zielzustand bei passender Eingabe state_t nxtstate;
} fsm_state_t; } fsm_state_t;
/* Struktur zur Beschreibung aller Uebergaenge eines Zustands */ /* Struktur zur Beschreibung aller Uebergaenge eines Zustands */
typedef struct { typedef struct {
const fsm_state_t * transitions; // Zeiger auf Array von Übergängen const fsm_state_t * transitions;
int nrOfTransitions; // Anzahl der Übergänge int nrOfTransitions;
state_t defaultNxtState; // Standard-Zielzustand, falls keine Transition passt state_t defaultNxtState;
} fsm_full_state_t; } fsm_full_state_t;
/*--- Modulglobale static Variablen ----------------------------------*/ /*--- Modulglobale static Variablen ----------------------------------*/
/* Definition der Zustandsvariablen */ /* 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 */ /* Definition aller Zustandsuebergaenge fuer jeden Zustand */
static const fsm_state_t s_transitions_A[] = static const fsm_state_t s_transitions_A[] =
{ /* input mask nxtstate */ { /* input mask nxtstate */
{ 0x002, ~0x004, B }, // Übergang zu B bei passender Eingabe // Wenn 1?-Münze eingeworfen (muenze=1, muenz_wert=0), egal ob Becher steht oder nicht (weil mask ~0x004, also becher-Bit egal)
{ 0x003, ~0x004, C } // Übergang zu C bei anderer Eingabe { 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[] = static const fsm_state_t s_transitions_B[] =
{ { /* input mask nxtstate */
{ 0x002, ~0x004, C }, // Nochmal 1? eingeworfen (muenze=1, muenz_wert=0), becher egal
{ 0x003, ~0x004, D } { 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[] = static const fsm_state_t s_transitions_C[] =
{ { /* input mask nxtstate */
{ 0x002, ~0x004, D }, // Nochmal 1? eingeworfen (muenze=1, muenz_wert=0), becher egal
{ 0x003, ~0x000, F }, { 0x002, ~0x004, D }, // C -> D: 1? dazu, jetzt 3?
{ 0x007, ~0x000, H } // 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[] = static const fsm_state_t s_transitions_D[] =
{ { /* input mask nxtstate */
{ 0x002, ~0x000, F }, // Becher steht (becher=1), egal was mit Münze, mask ~0x000
{ 0x003, ~0x004, E }, { 0x002, ~0x000, F }, // D -> F: Becher untergestellt
{ 0x006, ~0x000, H } // 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[] = static const fsm_state_t s_transitions_E[] =
{ {
{ 0x002, ~0x000, F }, // Becher steht (becher=1), egal was mit Münze
{ 0x003, ~0x004, E }, { 0x002, ~0x000, F }, // E -> F: Becher untergestellt
{ 0x006, ~0x000, H } // 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[] = static const fsm_state_t s_transitions_F[] =
{ {
{ 0x002, ~0x001, G }, // Becher steht, 1? eingeworfen (becher=1, muenze=1, muenz_wert=0), mask ~0x001 (muenz_wert egal)
{ 0x004, ~0x001, H }, { 0x002, ~0x001, G }, // F -> G: Becher steht, Münze eingeworfen
{ 0x006, ~0x001, I } // 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[] = static const fsm_state_t s_transitions_G[] =
{ {
{ 0x002, ~0x001, G }, // Becher steht, 1? eingeworfen
{ 0x004, ~0x001, H }, { 0x000, ~0x001, F }, // G bleibt G: Becher steht, Münze eingeworfen
{ 0x006, ~0x001, I } // 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[] = static const fsm_state_t s_transitions_H[] =
{ {
{ 0x000, ~0x001, A }, // Kein Becher, keine Münze, kein Wert (alles 0)
{ 0x002, ~0x000, B }, { 0x000, ~0x001, A }, // H -> A: Reset, alles leer
{ 0x003, ~0x000, C }, // Becher steht, keine Münze, kein Wert
{ 0x006, ~0x001, I } { 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[] = static const fsm_state_t s_transitions_I[] =
{ { // Kein Becher, keine Münze, kein Wert (alles 0)
{ 0x000, ~0x001, A }, { 0x000, ~0x001, A }, // I -> A: Reset, alles leer
{ 0x002, ~0x000, B }, // Becher steht, keine Münze, kein Wert
{ 0x003, ~0x000, C }, { 0x002, ~0x000, B }, // I -> B: Becher steht, 1? eingeworfen
{ 0x006, ~0x001, I } // 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 */ /* Definition der Uebergangstabelle */
/* Die Reihenfolge der Zustaende in der enum Definition muss der /* Die Reihenfolge der Zustaende in der enum Definition muss der
* Reihenfolge der Zustaende in der Uebergangstabelle entsprechen * Reihenfolge der Zustaende in der Uebergangstabelle entsprechen
@ -96,16 +138,20 @@ static const fsm_state_t s_transitions_I[] =
static const fsm_full_state_t s_state_table[NR_OF_STATES] = static const fsm_full_state_t s_state_table[NR_OF_STATES] =
{ {
/* transitions nrOfTransitions defaultNxtState */ /* transitions nrOfTransitions defaultNxtState */
{ s_transitions_A, SIZE_OF(s_transitions_A), A }, // Zustand A { s_transitions_A, SIZE_OF(s_transitions_A), A },
{ s_transitions_B, SIZE_OF(s_transitions_B), B }, // Zustand B { s_transitions_B, SIZE_OF(s_transitions_B), B },
{ s_transitions_C, SIZE_OF(s_transitions_C), C }, // Zustand C { s_transitions_C, SIZE_OF(s_transitions_C), C },
{ s_transitions_D, SIZE_OF(s_transitions_D), D }, // Zustand D { s_transitions_D, SIZE_OF(s_transitions_D), D },
{ s_transitions_E, SIZE_OF(s_transitions_E), D }, // Zustand E
{ s_transitions_F, SIZE_OF(s_transitions_F), F }, // Zustand F /* TODO */
{ s_transitions_G, SIZE_OF(s_transitions_G), F }, // Zustand G
{ s_transitions_H, SIZE_OF(s_transitions_H), H }, // Zustand H { s_transitions_E, SIZE_OF(s_transitions_E), E },
{ s_transitions_I, SIZE_OF(s_transitions_I), H } // Zustand I { 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 */ /* Definition der Ausgaenge */
static const fsm_action_t s_out_table[NR_OF_STATES] = static const fsm_action_t s_out_table[NR_OF_STATES] =
{ {
@ -114,43 +160,81 @@ static const fsm_action_t s_out_table[NR_OF_STATES] =
{ false, false, false, 1, "1 Euro" }, /* state B */ { false, false, false, 1, "1 Euro" }, /* state B */
{ false, false, false, 2, "2 Euro" }, /* state C */ { false, false, false, 2, "2 Euro" }, /* state C */
{ false, false, false, 3, "3 Euro" }, /* state D */ { false, false, false, 3, "3 Euro" }, /* state D */
{ false, true, false, 3, "3 Euro" }, /* state E */
{ true, false, false, 4, "Becher unterstellen" }, /* state F */ /* TODO */
{ true, true, false, 4, "Becher unterstellen" }, /* state G */
{ 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, false, true, 0, "Kaffe kommt" }, /* state H */
{ true, true, true, 0, "Kaffe kommt" } /* state I */ { true, true, true, 0, "Kaffe + M" } /* state I */
}; };
/*--- Funktionsdefinition --------------------------------------------*/ /*--- Funktionsdefinition --------------------------------------------*/
void automat_reset(void) void automat_reset(void)
{ {
printf("---- automat_reset ----\n"); // Ausgabe zur Kontrolle printf("---- automat_reset ----\n");
s_curstate = A; // Automat in Startzustand (A) zurücksetzen
/* TODO go into IDLE state */
s_curstate = A;
} }
/*--- Funktionsdefinition --------------------------------------------*/ /*--- Funktionsdefinition --------------------------------------------*/
void automat_transition(BOOL becher, BOOL muenze, BOOL muenz_wert) void automat_transition(BOOL becher, BOOL muenze, BOOL muenz_wert)
{ {
// Ausgabe der aktuellen Eingabewerte zur Fehlersuche
printf("---- automat_transition becher(%0d) muenze(%0d) muenz_wert(%0d) ----\n", printf("---- automat_transition becher(%0d) muenze(%0d) muenz_wert(%0d) ----\n",
becher, muenze, muenz_wert); // Eingaben ausgeben becher, muenze, muenz_wert);
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 // Kombiniere die Eingabewerte zu einem einzigen Integer mittels Bitoperationen.
const fsm_state_t * transition = full_transition->transitions; // Zeiger auf Übergänge // 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; int i;
for(i = 0; i < full_transition->nrOfTransitions; i++) // Alle möglichen Übergänge prüfen
// Iteriere über alle definierten Übergänge für den aktuellen Zustand.
for(i = 0; i < full_transition->nrOfTransitions; i++)
{ {
if(transition[i].input == (in & transition[i].mask)) // Prüfen, ob Eingabe zur Transition passt // Ü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))
{ {
s_curstate = transition[i].nxtstate; // In Zielzustand wechseln // Wenn ein passender Übergang gefunden wird, aktualisiere den aktuellen Zustand
break; // Schleife verlassen // auf den im Übergang spezifizierten Folgezustand.
s_curstate = transition[i].nxtstate;
// Beende die Schleife, da der Übergang erfolgreich angewendet wurde.
break;
} }
} }
if(i == full_transition->nrOfTransitions) // Falls keine Transition gepasst hat
// 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; // In Default-Zustand wechseln s_curstate = full_transition->defaultNxtState;
} }
} }
/*--- Funktionsdefinition --------------------------------------------*/ /*--- Funktionsdefinition --------------------------------------------*/
fsm_action_t automat_output(void) 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 //gcc automat.c view.c main.c io.c checker.c -o console_automat