[20140906] MARY-VB基板の作者の白坂さんからコメントをいただき,記事の内容を再検討し,誤りを正しました.誤った内容で白坂さんにご迷惑をおかけしましたことを,記してお詫び申し上げます.
--------------------------------------------------------------------------
トランジスタ技術2014年7月号で紹介されたMARY-VB基板を買ってきました.
これは圓山さんの開発ではないのね…
コンデンサC1からC6に飛んでましたので,回路図を見ると,カメラユニットのVddに1.8Vを供給する線のようです.
誌面にはこのように書いてあるのですが,容量が足りなかったんですかねえ.
[追記20140903] モジュールを設計した白坂さんのコメント:「布線があるのは、カメラモジュールメーカの手違いで、1.8Vを外部から供給するモジュールが混じってしまったためで、供給能力等の問題ではありませんので安心して下さい。」とのこと.
なにはともあれ,動かしてみることにしました.
回路図はこんな感じです.VB基板はI2CとSPIを両方使う仕様です.ボタンがひとつ欲しかったので,Debounceモジュールを初めて使ってみました.昔はこんな便利なものはなかったので,いい時代になったものだ(爺モード).まだ慣れていないので,なんとなくもたもたしている感じがありますが,見逃してください.また,今回は割り込みを使っていないので,ボタンを押しても,プログラムがステータスレジスタを見る部分を実行していないと感知されないという手抜き仕様です.このモジュールだと1->0と0->1で別々の割り込みを発生することもできたりして,かなり高度な押し方(長押しなど)でもスマートにプログラムが書けそうです.割り込みを使わないなら,Glitch Filterというモジュールが同じように使えそうですが,今回は試しませんでした.
[20140906] 最初はPSB基板のソケットにMARY-OB基板(OLED)をセットし,MARY-VB基板をブレッドボードに置いて配線していたのですが,通信エラーが頻発して動作が安定しません.ハードウェアの問題を取り除くため,MARY-VBをソケットに差すようにし,MARY-OBをブレッドボードに置くことにしました.
I2CでもSPIでも順調にはまりましたが,少しづつプログラムの間違いや理解の誤りを修正し,プログラムが動き出しました.
しかしどうもうまくいかないのです.1画面読んだあと次の画面に更新がかからない,などです.
手持ちのmbedとmaple mini基板をひっぱり出してきて,mbed版のサンプルプログラムを動かしてみると,表示抜けは起こらず見事に動きます.
トラ技の著者(白坂さん)のサンプルプログラムを一生懸命見直して,先に開発されたmbedのMARY-VBライブラリのソースコードも読んでいったところ,相違点を見つけました.
MARY-VB基板は,カメラのフレームバッファを読みに行くとき,制御レジスタにフレームバッファの更新を停止してくれというリクエストを出し,ステータスレジスタに「止めたよ」という返事が返ってきたらデータを読み込みます.ステータスレジスタのbit0=1がその合図のはず.逆に読み込みが終わったのでフレームバッファの更新を再開していいよと制御レジスタにコマンドを送ると,ステータスレジスタのbit0=0が更新を再開したことの通知になります.ところが…
mbedのソースでは,0x51(データ読み込み開始時)と0x50(終了時)を待っています.さては隠しフラグにちがいない,と思い,やってみたところうまくいくので,ああこれが正解だった,と思い込んでしまったのでした.
ところが,この記事のコメントにもあるとおり,それはおかしい,bit0=0を待っていればうまくいくはず,とのこと.さあて,どこがおかしいんだろう…必死になって調べた結果…
見つかりました.プログラムミス.SPIでデータを読むときは,こちらからデータリクエストのコマンドをMOSIに出すと,同じクロックタイミングでコマンドの長さの分だけMISOからデータがやってくるので,それを読むわけですが,最初に出すときは,スレーブ側からみれば何のコマンドがくるかわからないので,ダミーのデータをだし,次にコマンドがやってきたタイミングで前のコマンドに対するデータを返してきます.PSoCのSPIはハードウェアで管理してくれていて,送られてきたデータは4バイトのバッファに入れてくれます.そのバッファの管理を誤ったのと,ステータスレジスタの読み取りに関する,最初のダミーデータの読み飛ばしを忘れてしまったのが,失敗の原因でした.
ごちゃごちゃ言葉でいってもかえってわかりにくいので,以下のソースで,どこを間違えたか,雰囲気をつかんでください.
誤:
void MARY_VB_DataRead_End() {
CPLD_SPI_ClearRxBuffer();
// Release frame buffer data
_CPLD_Transmit(CPLD_COMMAND_WriteRegister + CPLD_REGISTER_Control);
_CPLD_Transmit(0);
// wait until flag = 0
_CPLD_Transmit(CPLD_COMMAND_ReadRegister + CPLD_REGISTER_Status);
while ((_CPLD_TransmitandReceive(CPLD_COMMAND_ReadRegister + CPLD_REGISTER_Status) & 0x01) != 0)
;
}
正:
void MARY_VB_DataRead_End() {
// Release frame buffer data
_CPLD_Transmit(CPLD_COMMAND_WriteRegister + CPLD_REGISTER_Control);
_CPLD_Transmit(0);
// Data Read Start
CPLD_SPI_ClearRxBuffer();
// wait until flag = 0
_CPLD_TransmitandReceive(CPLD_COMMAND_ReadRegister + CPLD_REGISTER_Status);
while ((_CPLD_TransmitandReceive(CPLD_COMMAND_ReadRegister + CPLD_REGISTER_Status) & 0x01) != 0)
;
}
あー,もう,情けない.がっかりしました…
開発したプログラム(修正版)をここに置きます.PSoC Creator 3.0 SP1で開発しました.
DebugモードでもReleaseモードでも問題なく動くようになりました.更新レートは,
全ライン | 奇/偶ライン | |
---|---|---|
Debug | 5fps | 7.5fps |
Release | 7.5fps | 10fps |
となりました.半分づつの描画にしてもレートは倍にはなりません.そりゃそうだ,カメラ側は全ライン分用意しているわけだから.
</object>
YouTube: CQ PSoC5LP基板でMARY-VB基板を動かしてみた(訂正版)
トラ技の記事中の記述ですが,PSoCならR/Wビットはコマンドを介して立てることになるので,デバイスIDは0x21として考えます.また,「レジスタを読み出す場合は…」以下のくだり,これだとレジスタに0x43を書きこむ命令とどう違うの?と思ってしまいました.デバイスID+Wフラグとレジスタ番号を送ったらいったん送信を終了し,新しいI2CコマンドとしてデバイスID+Rフラグを送って,レジスタの値を受信する,という手順で示していただいたほうがよいように思います.
いい気分転換にはなりましたが,忙しいときに限って遊びたくなるのは困ったものだ…orz
追記 SPIの転送速度が遅いとき,フレームバッファデータ(2バイト)の送信順序が逆に見える(上位,下位の順のはずが下位,上位の順になる)現象が起きます.mbedのサンプルプログラムでもそうなったときの対策ルーチンが含まれており,どの環境でも起きうる現象のようです.なお現在,VB基板のSPIは16.5Mbpsで,OB基板のSPIも16.5Mbpsで動かしています.