質問

(多少の)大きな真理値表/ステートマシンがあり、それをコードに実装する必要があります(埋め込みC)。このステートマシンの動作仕様は将来変更されると予想されるため、今後も簡単に変更できるようにしたいと思います。

私の真理値表には、4つの入力と4つの出力があります。すべてをExcelスプレッドシートに収めており、少し書式設定してコードに貼り付けることができれば理想的です。

次のように真理値表にアクセスしたいと考えていました:

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

そして、出力値にアクセスするには次のようにします:

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

しかし、それを得るためには、次のようにかなり混乱したテーブルを作成する必要があるように見えます:

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 }}}};

入れ子になった括弧はやや混乱する可能性があります。コード内にきれいな表を保持する方法について、だれかがより良いアイデアを持っていますか?

ありがとう!

HUAGHAGUAHの回答に基づいて編集:

全員の入力の融合を使用して(おかげで-これらの回答の3つまたは4つを「受け入れ」たいと思います)、2次元配列として試してみると思います。小さなビットシフトマクロを使用して配列にインデックスを付けます。

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

そしてそれは私の真理値表の配列を次のようにします:

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 }};

そして、次のように真理値表にアクセスできます:

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

これを試して、どのように機能するかを確認します。また、0と1を、出力の各行の入力を説明する/ ** /コメントとともに、各状態の意味を表すより有用な#definesに置き換えます。みんな、助けてくれてありがとう!

役に立ちましたか?

解決

多次元テーブルは必要ありません。 4ビット= gt; 4ビットマッピング。入力を出力にマッピングする単一のu8 [16]配列を使用できます。状態のルックアップははるかに安くなり、いくつかのシフトとマスクの操作で個々のビットを抽出できます。

行を移入するアルゴリズムを体系化するのが簡単な場合は、マクロを定義して、各行にインデックス番号を移入することができます。

他のヒント

次のいずれかをお勧めします(優先アプローチを最初に):

  • マクロを使用して、各「行」を初期化します。 -これにより、マクロ呼び出し内のブレースが非表示になります。
  • コメントを使用して行を分割します。
  • init関数を使用してコンテキストを明示的に初期化します-おそらく関数を使用して各セクションを初期化します。これは上記の最初のオプションに似ていますが、ステートマシンを使用する前にinit関数を呼び出す必要があるという欠点があります。

個人的には、構成ファイルから読み取りました。 CSV。おそらく、Excelから簡単にエクスポートできます。または、Excelからプレーンテキストにコピーアンドペーストするだけで、スペースで区切られた値が得られます。インポートも同様に簡単です。

これは、Cを使用している場合、デシジョンテーブルが変更されるたびにコードを再コンパイルする必要がないことも意味します。

真理値表がすべてブール値である場合、ペアのリストに折りたたむことができます。例:

1111,0000
1110,0110
...

データ圧縮の場合、値をバイト(2ニブル)として表します...

特定の組み込みシステム構成でソフトコーディングのためにどこに/どのように保存するか、あなただけが言うことができます;-)

真理値表が実際に4x4x4x4のみである場合、マクロを使用します。それを超えて成長する場合は、 Ragel を使用します。おそらく、あなたよりも小さくて高速なCコードが作成されるでしょう。

出力状態を取得するための現在の状態への参照が表示されません。つまり、ステートマシンではなく、真理値表にすぎません。入力は4つあるため、可能な入力の組み合わせは16のみです。したがって、16ポジションのテーブルでそれを行う必要があります。

通常、このような問題が発生した場合、単純なブール式に縮小しようとします。ここでなぜそれが最良のアプローチではないのかわかりません。それははるかにコンパクトで読みやすく、さらに高速になる可能性があります(ルックアップテーブルアプローチに必要な乗算/シフト+メモリアクセスのコレクションよりも少数のANDとORがより速く実行されると思います)。このテーブルをブール式に減らす最も簡単な方法は、 K-Map を使用することです。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top