156 lines
7.1 KiB
C
156 lines
7.1 KiB
C
/**********************************************************************\
|
|
* 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 <stdio.h> // Standard Ein-/Ausgabe
|
|
#include <stdlib.h> // 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
|