halo
This commit is contained in:
parent
6da144e049
commit
d48bacbae7
222
Modul4/automat.c
222
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 <stdio.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdlib.h>
|
||||
#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
|
||||
|
Loading…
x
Reference in New Issue
Block a user