10

コードに実装する必要がある (やや) 大きな真理値表/ステート マシンがあります (埋め込み 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 を、出力の各行の入力を説明する /**/ コメントと共に、各状態の意味を表すより役立つ #define に置き換えます。助けてくれてありがとう、みんな!

4

7 に答える 7

4

どちらかをお勧めします(最初に推奨されるアプローチ):

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

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

行に入力するアルゴリズムをコード化するのが簡単な場合は、インデックス番号で各行に入力するマクロを #define することができます。

于 2009-03-02T17:10:21.510 に答える
3

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

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

于 2009-03-02T16:47:31.173 に答える
2

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

1111,0000
1110,0110
...

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

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

于 2009-03-02T17:03:38.000 に答える
1

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

于 2009-03-02T17:43:38.497 に答える
1

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

于 2009-03-02T17:10:08.110 に答える
1

出力状態を取得するための現在の状態への参照はありません。これは、ステート マシンではなく、単なる真理値表であることを意味します。入力が 4 つあるため、入力の組み合わせは 16 通りしかありません。したがって、16 ポジションのテーブルで十分です。

于 2009-03-02T17:12:31.207 に答える