2015年9月9日水曜日

遅延キーイングのプログラム備忘録

先ほどKeyer Mini-V2のプログラムに遅延キーイング(PTTオンに少し遅れてキーイングが開始する仕組み)機能を追加しましたが、後々応用が利くと考えたのでここで備忘録的にプログラムの考え方を書き残しておきます。

PTTと同時に符号開始(上の赤がPTT,下の黄色がKEY出力 ”V V"
遅延キーイングモード(約90msec)
すでに出来上がっている符号生成のルーチンを弄りたくなかったので、直接出力ポートを駆動するレジスタに符号出力をつないでいるところを一旦切り離し、符号出力を一般の変数に置き換えその変数の動きを遅延させて出力ポートを駆動させるという流れを考えました。

具体的には#define文をつかって、#define KEY_OUT LATAbits.LATA0 -> PORTA0レジスタ(LATA0)をKEY_OUTに呼び変えて直接代入する(Boolean値なので0か1)方法で出力操作をしていたのを一旦KEY_OUTを一般変数として宣言し、#define文のKEY_OUTをKEY_OUT1として切り離す、といったところがまず最初の一歩です。

mainループ内でKEY_OUT1 = KEY_OUTとすれば(正確には型変換を必要とするところですが)切り離す前と結果は変わりありません。で、このKEY_OUTをKEY_OUT1に繋げる前に何かしらの遅延ルーチンを通せばよいわけです。

しかし、この遅延ルーチンをどうやって作るかで少し試行錯誤しました。

まず、mainループ内でKEY_OUT変数を監視して立ち上がりから立下りまでの時間を記憶させ、遅延時間後にKEY_OUT1操作(立ち上げて、記憶した時間を経過したら立ち下げる)という方法でプログラムを書いてみましたが、割り込み処理の関係で時間が不正確になりまったくうまくいきません。

そこで、まず割り込み処理関数内にKEY_OUT変数を監視する命令を置いてリングバッファへ変数の状態をコピーしインデックスを1つ加算します。バッファは256個の1元配列としました。結果1インデックスが1ミリ秒に相当する時間のいわばKEY_OUT値のサンプリングになります。この処理のすぐ下に、今サンプリングして格納したバッファのインデックス値から遅延したい時間に相当する数を引いたインデックスのバッファの値を参照しKEY_OUT1につなげる 処理を置くという方法にしました。

  /////グローバル変数宣言/////

    unsigned char delay_buffer[256] = {0};                        <-バッファの変数宣言と初期化
    unsigned char delay_time = 50;  

  /////1ミリ秒割り込み処理関数内/////

    static unsigned char idx = 0, idx2 = 0;

    if(KEY_OUT) delay_buffer[idx] = 1;        <-KEY_OUT値をサンプリングしバッファへコピー
    else if(KEY_OUT == 0) delay_buffer[ind] = 0;
       
    if(idx < delay_time) idx2 = 255 - delay_time + idx;           <-参照インデックス計算
    else idx2 = idx - delay_time;
       
    if(delay_buffer[idx2]){            <-KEY_OUT1操作
        if(KEY_OUT1 == 0) KEY_OUT1 = 1;
        }
    else if(delay_buffer[idx2] == 0){
        if(KEY_OUT1) KEY_OUT1 = 0;
        }
       
    if(idx > 254) idx = 0;                                     <-インデックス値インクリメント
    else idx++;


たとえば上のような感じになります。バッファの要素は8bit変数なので格納される値が1bitだとなんとなく勿体ない感じもしますね^^;RAMを節約したいのならビットシフトやビットマスクを活用して8分の1にRAM消費を抑えることも出来そうです。

逆に要素のビット数を増やして(8bitから16bit, 32bit...)監視する変数をAD変換されたデータにすると...と妄想が拡がります(笑) 

0 件のコメント:

コメントを投稿