前回の記事の後半です。ここでは、実際の GPIF 初期化コードを書いていきます。
初期化コード全体
いきなりですが、全体です。前回の配列は省略しています。
void GpifInit(void) {
IFCONFIG = 0xC2;
GPIFABORT = 0xFF; // abort any waveforms pending & go into idle state
GPIFREADYCFG = 0x20; // connect RDY siglal to GPIF
GPIFCTLCFG = 0x00; // All CMOS output, Output Enabled
GPIFIDLECS = 0x00; // Data bus is not driven during idle state.
GPIFIDLECTL = 0x00; // Disable All output during idle state
GPIFWFSELECT = 0x00; // tekitou(wave form 0 is chosen in all xfer/recv modes)
volatile char *dest = &GPIF_WAVE_DATA;
const char *src = (const void *)WaveData;
for(unsigned int i = 0; i < 4 * 4 * 8; i++) {
dest[i] = src[i];
}
}
解説
それではざっくりと解説をしていきましょう。お手元にユーザーマニュアルをどうぞ。
GPIF設定の準備
IFCONFIG = 0xC2;
GPIFABORT = 0xFF; // abort any waveforms pending & go into idle state
ここでは GPIF を設定する前の準備をしています。IFCONFIG
の値は、1. IFCLK = 48MHz, 2. GPIF マスターモード、3. 非同期(Asynchronous)モードでの動作 を示しています。3. については、実際に SRAM 等でスレーブと通信をする時にクロックを使うことがあると思いますが、どうやらそういった時にマスタとスレーブをクロックで同期して動かしたい時に使うモードらしいです。また、3bit 目を1にすると、PORTE[2:0] がステート番号を表すようになるらしい。デバッグ用らしいです。
GPIFABORT
は 0xFF
を書き込むと、現在進行中の GPIF 動作を全て強制終了させて Idle State に移行させるものです。このレジスタには他の値を書き込んでも何も起きません。
GPIFのハードウェア設定
GPIFREADYCFG = 0x20; // connect RDY siglal to GPIF
GPIFCTLCFG = 0x00; // All CMOS output, Output Enabled
GPIFIDLECS = 0x00; // Data bus is not driven during idle state.
GPIFIDLECTL = 0x00; // Disable All output during idle state
GPIFWFSELECT = 0x00; // tekitou(WaveData 0 is chosen in all xfer/recv modes)
ここで GPIF を使う上で一番最初の初期化をしています。データバスとの接続、出力ピンのモード選択、出力 WaveForm の選択です。起動時の GPIF アイドル時の設定があるんですね〜今回は関係ありませんが。
最後の GPIFWFSELECT
では、とりあえず Single Write から FIFO Read まで全て WaveData0 を使う設定にしてあります。
WaveFormデータのコピー
volatile char *dest = &GPIF_WAVE_DATA;
const char *src = (const void *)WaveData;
for(unsigned int i = 0; i < 4 * 4 * 8; i++) {
dest[i] = src[i];
}
これでデータをコピーしています。ここには前回の記事の OPCODE 等々のレジスタ値が記述されています。
これで設定は終わりです!ちなみに現状は Idle state に入っていて、しかも FLOWSTATE
の値によると、初期値で 0 だそうです。つまり最初に動作を開始する時は S0 から始まるということです。
今回はこれで都合がいいので、他の設定はいじらずこれで OK!
動かしてみよう
GPIF の設定は完了しましたが、このあと Single Write 動作で、GPIF をトリガする必要があります。なので、早速 main 関数にて記述しましょう。
int main(void) {
GpifInit();
XGPIFSGLDATLX = 1;
while(1) {
}
}
XGPIFSGLDATLX = 1
がまさに Single Write を行うところです。今回はこの 1 という値に意味はありません。好きな値にどうぞ。とにかく、Single Write が行われたということ自体が重要なのです(この動作自体が設定した GPIF の動作をトリガするので)。
後は GPIF が勝手に状態遷移を無限ループしてくれるので、ソフトウェアでは何もすることがありません。実際、RDY0 & RDY1 == 1
のときにのみ CTL0 の出力は 1 になりました!