fc2ブログ

ミニ・エレキーを解剖する-C言語処理編

2013-09-22      
 今回製作したエレキーは、Mid Rangeの8ピンPICにXC8(オールC言語)という組み合わせで窮屈なメモリに押し込んだことなど、ちょっと記録しておきたいところがありますので、得意の備忘記事にしてみます。

 なお、実プログラムの即値定義として各種のdefine定義を行っていますが、以下「ON:1、OFF:0」というもののみ残す形にしてあります。

 ◆ BSSの初期化を自動で行わせない

 初期設定が必要な変数には初期値を事前に入れておくわけですが、XC8のLinkerはスタートアップに絡む便利そうな関数を勝手に付けてきます。とりわけ、BSSの0クリアに関しては一気にクリアする処理を付けてきますので、「初期設定は確実に自分でやる」という方には不要でしょう。これを外すと数十バイト分のプログラムエリア消費が無くなります・・・まぁ微々たるもんでも無駄は無駄

 この処理の取っ払いは、「MPLAB X IDE」のプロジェクトのプロパティにチェックボックスを外すことで行えます。



 ◆ SLEEP機能を「前向きに使う」

 C言語のmain関数は以下のようになっています。

void    main(void)
{
    initializer();                  // 初期設定
    
    while (1) {
        key_handler();         // キー処理
        event_handler();     // イベント処理
        if (sts == 0) {            // 処理無し・・・
            SLEEP();              // イベント待ち
            NOP();
        }
    }
}

 メインループで「やることがないぞ」となれば即就寝・・・という作りです。変数「sts」は状態遷移表により「どんな状態か」を記憶しています。この値が「0」の時には何も実行している処理がないという判断で寝てしまいます。SLEEPからの復帰は、エレキーが待機状態で期待する動き・・・即ち、パドル操作か本体タクタイルスイッチ押下を待っていることになります。これを実現するために、初期設定関数内では以下のように初期化を行っています。

   OPTION_REG = 0b11001000;
              // No WPU, Prescaler 1/2
                 :
   IOCAN = 0b00001111;     // Negエッジ
   IOCIE = ON;                       // IOC使用

 今回は全入力ポートが外付け抵抗でプルアップしていますから、パドルやスイッチがONになると当該ビットが「1⇒0」に動くため、「アクティブ・ロー」(ネガティブ・エッジ)でコントロールするようにIOCレジスタを設定しています。さらに、OPTION_REGで弱プルアップを禁止しています。

 割込処理ではIOCIFをチェックし、立っていればポート読み出しをしてメインラインの処理に渡す・・・というやり方です。

    if (IOCIF == ON) {
        if ((IOCAF&0b00000011) != 0) {
            i_key_change();     // キー入力確認
            IOCAF &= 0b11111100;
        }
        if ((IOCAF & 0b00001100) != 0) {
            i_put_event();         // SW押下
            IOCAF &= 0b11110011;
        }
        IOCIF = OFF;
    }

 パドル入力はエレキー処理のキューへ渡し(i_key_change)、スイッチ操作はメインラインのキュー(i_put_event)に渡すという形です。

 この割込処理が動作するとmain関数のSLEEPから起き上がりNOPからスタートします(このNOPはデバッグ用に入れたまんまになっています)。そしてwhile文を前に戻り、割込処理でキューイングした個々のイベントを「xxx_handler」が覗き込み、実際の処理を開始します。すると、次の動作を待つ状態になるため「sts」が0以外の値となり、メインラインが空転を開始して処理を進め、やがて「sts」が0に戻るとまた寝るという形です。

 イベントが起こるまでSLEEPするという作りは、今後もPICで何か作る場合には大いに利用して「省エネ化」を図りたいと思います。

 ◆ 状態遷移表関連の処理

 状態遷移表については、ミニ・エレキーのとりあえずの完成記事に載せてありますが、これをハンドリングする処理は非常に簡単です(以下、uchar : unsigned char)。

static void     kproc_null();
static void     kproc_0000();
static void     kproc_0001();
static void     kproc_0002();
static void     kproc_0103();
      :
static void     kproc_0503();


static  void    (*mtx_p[6][4])() = {
    {kproc_0000,kproc_0001,kproc_0002,kproc_null},  // 00
    {kproc_null,kproc_null,kproc_null,kproc_0103},
      :
    {kproc_null,kproc_null,kproc_null,kproc_0503}  // 05
};

uchar ksts;

                 :

static void    handler(uchar evno)
{
    (mtx_p[ksts][evno])();
}

 記事にある状態遷移表のものとは違いますが、要は「ある状態でやるべき処理があれば、その関数を書いたデータ」を作っておけばいいだけです。処理のないところは「何もしない関数」(上記ではkproc_null:単にリターンのみの関数)を記述して埋めておけばOK・・・なんですが、以下の欠点があります。

 1) スカスカの遷移表では、データに無駄が多くなる(上記の場合「kproc_null」だらけに・・・)
 2) 横の要素数を2のべき乗の数(2,4,8・・・)にしないと、掛け算処理が必要になる
 3) XC8では大きさに制限がある(最大255⇒同様な属性の部分と合わさってしまうため、実際の最大数は作りによる)

 案の定、最初のバージョン完成時は何とかなっていましたが、結局3) に引っかかってしまいマイナーチェンジしました。

static void     kproc_null();
static void     kproc_0000();
static void     kproc_0001();
static void     kproc_0002();
static void     kproc_0103();
      :
static void     kproc_0503();

static void     kproc_00(uchar);
static void     kproc_01(uchar);
static void     kproc_02(uchar);
static void     kproc_03(uchar);
static void     kproc_04(uchar);
static void     kproc_05(uchar);

static  void    (*mtx_p[6])(uchar) = {
    kproc_00,kproc_01,kproc_02,
    kproc_03,kproc_04,kproc_05
}

uchar ksts;

                  :

static void    handler(uchar evno)
{
    (mtx_p[ksts])(evno);
}

static void    kproc_00(uchar evno)
{
    switch (evno) {
        case 0
関連記事

コメントの投稿

非公開コメント

Calendar
11 | 2023/12 | 01
Sun Mon Tue Wed Thu Fri Sat
- - - - - 1 2
3 4 5 6 7 8 9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30
31 - - - - - -
New !
Category
Comments
Monthly Archives
Track Backs
Counter
Sunspot Now !

 


Survey Results

 

Profile

どよよん無線技士

Author :どよよん無線技士
こおるさいん:JM1DPL

アパマンというハンデにさらにQRPまで課し、失敗連続のヘッポコリグや周辺機器の製作・・・趣味というより「荒行」か!?

メールは「JARL経由」でお願いします。

Links
Follow me !
RSS Links
QR Code
QR