Domanda

Ho una (in qualche modo) grande tabella di verità / macchina a stati che devo implementare nel mio codice (C incorporato). Prevedo che le specifiche di comportamento di questa macchina a stati cambieranno in futuro, quindi mi piacerebbe mantenerle facilmente modificabili in futuro.

La mia tabella di verità ha 4 ingressi e 4 uscite. Ho tutto in un foglio di calcolo Excel e se potessi semplicemente incollarlo nel mio codice con un po 'di formattazione, sarebbe l'ideale.

Stavo pensando che vorrei accedere alla mia tabella della verità in questo modo:

u8 newState[] = decisionTable[input1][input2][input3][input4];

E poi ho potuto accedere ai valori di output con:

setOutputPin( LINE_0, newState[0] );
setOutputPin( LINE_1, newState[1] );
setOutputPin( LINE_2, newState[2] );
setOutputPin( LINE_3, newState[3] );

Ma per farlo, sembra che dovrei fare una tabella abbastanza confusa in questo modo:

static u8 decisionTable[][][][][] =
 {{{{ 0, 0, 0, 0 },
    { 0, 0, 0, 0 }},
   {{ 0, 0, 0, 0 },
    { 0, 0, 0, 0 }}},
  {{{ 0, 0, 1, 1 },
    { 0, 1, 1, 1 }},
   {{ 0, 1, 0, 1 },
    { 1, 1, 1, 1 }}}},
 {{{{ 0, 1, 0, 1 },
    { 1, 1, 1, 1 }},
   {{ 0, 1, 0, 1 },
    { 1, 1, 1, 1 }}},
  {{{ 0, 1, 1, 1 },
    { 0, 1, 1, 1 }},
   {{ 0, 1, 0, 1 },
    { 1, 1, 1, 1 }}}};

Quelle parentesi nidificate possono essere un po 'confuse: qualcuno ha un'idea migliore di come posso mantenere una bella tabella nel mio codice?

Grazie!

Modifica in base alla risposta di HUAGHAGUAH:

Usando una fusione di input di tutti (grazie - Vorrei poter "accettare" 3 o 4 di queste risposte), penso che lo proverò come un array bidimensionale. Indicizzerò nel mio array usando una piccola macro che sposta i bit:

#define SM_INPUTS( in0, in1, in2, in3 ) ((in0 << 0) | (in1 << 1) | (in2 << 2) | (in3 << 3))

E questo farà apparire il mio array di tabelle di verità in questo modo:

static u8 decisionTable[][] = {
{ 0, 0, 0, 0 },
{ 0, 0, 0, 0 },
{ 0, 0, 0, 0 },
{ 0, 0, 0, 0 },
{ 0, 0, 1, 1 },
{ 0, 1, 1, 1 },
{ 0, 1, 0, 1 },
{ 1, 1, 1, 1 },
{ 0, 1, 0, 1 },
{ 1, 1, 1, 1 },
{ 0, 1, 0, 1 },
{ 1, 1, 1, 1 },
{ 0, 1, 1, 1 },
{ 0, 1, 1, 1 },
{ 0, 1, 0, 1 },
{ 1, 1, 1, 1 }};

E quindi posso accedere alla mia tabella della verità in questo modo:

decisionTable[ SM_INPUTS( line1, line2, line3, line4 ) ]

Ci proverò e vedrò come funziona. Sostituirò anche gli 0 e gli 1 con #define più utili che esprimono il significato di ciascuno stato, insieme a / ** / commenti che spiegano gli input per ogni linea di output. Grazie per l'aiuto a tutti!

È stato utile?

Soluzione

Non è necessaria una tabella multidimensionale. Con un 4 bit = > Mappatura a 4 bit, è possibile avere un singolo u8 [16] array di mappatura degli ingressi verso le uscite. Le ricerche di stato saranno molto più economiche e puoi estrarre singoli bit con alcune operazioni di spostamento e maschera.

Se l'algoritmo per popolare le righe è facile da codificare, è possibile #definire una macro per popolare ogni riga in base al numero indice.

Altri suggerimenti

Suggerirei entrambi (prima gli approcci preferiti):

  • Utilizza una macro per inizializzare ogni "riga" - questo nasconderà le parentesi graffe all'interno della chiamata macro.
  • Utilizza i commenti per suddividere le righe.
  • Usa una funzione init per inizializzare esplicitamente il contesto - forse usa le funzioni per inizializzare ogni sezione. Questo è simile alla prima opzione sopra, ma ha uno svantaggio che la funzione init deve essere invocata prima di poter usare la macchina a stati.

Personalmente, l'avrei letto da un file di configurazione. CSV, forse, che è facile da esportare da Excel. Oppure potresti semplicemente copiare e incollare da Excel in testo semplice, il che ti dà valori separati da spazio, che è altrettanto facile da importare.

Ciò significa anche, dato che stai lavorando con C, che non dovrai ricompilare il tuo codice ogni volta che cambia la tabella delle decisioni.

se la tua tabella della verità è tutta booleana, puoi semplicemente comprimerla in un elenco di coppie, ad esempio

1111,0000
1110,0110
...

per la compressione dei dati, rappresentano i valori come byte (due nybbles) ...

dove / come memorizzarlo per il soft-coding nella particolare configurazione del sistema incorporato, solo tu puoi dire ;-)

Se la tabella di verità è davvero solo 4x4x4x4, allora userei le macro. Se dovesse mai andare oltre, userei Ragel . È probabile che renderà il codice C più piccolo e più veloce di te.

Non vedo alcun riferimento allo stato corrente per ottenere il tuo stato di output. Ciò significa che non è una macchina a stati, ma solo una tabella di verità. Ci sono quattro ingressi, quindi ci sono solo 16 possibili combinazioni di ingressi. Quindi, un tavolo con 16 posizioni dovrebbe farlo.

Di solito quando si ha un problema come questo, si tenta di ridurlo a una semplice formula booleana. Non vedo perché non sarebbe l'approccio migliore qui. Sarebbe molto più compatto e più leggibile, inoltre ha il potenziale per essere più veloce (immagino che una manciata di AND e OR verrebbero eseguiti più rapidamente rispetto alla raccolta di moltiplicazioni / turni + accesso alla memoria necessario per l'approccio della tabella di ricerca). Il modo più semplice per ridurre questa tabella a una formula booleana è con una K-Map .

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top