途中経過発表③
2010年11月24日
60fpsバージョンに修正しました。
今回はソフトウェアの説明です。
画像の右下をクリックすると処理の過程が拡大されます。
割と込み入った制御になってしまいますた。
項目が多いので、番号に沿って説明していきます。
①SDカード
SanDiskの2GB品を使用しています。
転送スピードクラス2のものを使用しています。
スピードクラス表記の無い製品は転送が遅く使用できませんでした。
SDIOはSTM32に内臓のSDカードとのインターフェイスで、4bitバスモードに対応しています。
SPIモードよりも高速な通信速度を実現し、60fpsの描画速度を達成できました。
なお、4bitBusモードはライセンス問題がよく話題に上がりますが、
個人利用や研究用途では抵触しないようです。
②SDIO→FATFS
DMA転送を使ってFATFSへとデータを転送しています。
SDIOのドライバ及び、FATFS用ライブラリはマイコン徹底入門のHPから
ダウンロードできるライブラリを使用しています。いつもお世話になってます!
ただ、読み込み用の低レベル関数のみ
シングルセクタ転送→マルチセクタ転送に改造しています。
5倍程度の転送速度向上が見込めます。
③書込み要求
リングバッファが半分転送したら、転送済の部分に上書きで書込むように割り込みを入れます。
リングバッファが全部転送したら、同様に書込み要求を入れます。
これをグルグル繰り返すのです。それがリングバッファの仕組みです。
④リングバッファへの書込み
FATFSの読み出し関数を使って書き込んでいます。
LCD表示用のバイナリファイルには
画像データ以外のデータは1bitも入っていないため、(同期信号データは無い)
単純にリングバッファを画像データで埋めていくのみです。⑤リングバッファサイズ
バッファサイズは大きいほどいいです。
なぜなら、SDカードの読み出しは転送速度がバラつくからです。
SDカードの読み出しは無反応時間がある為、なるべく少ない読み出しコマンド回数にて
データを受け取らなければならないのですが、下記の場合は別のアドレスに読みにいかなければなりません。
1.データのクラスタ境界においてSDカードのセクタ位置が別の場所にある
2.FAT領域を読みにいく
当然、別のアドレスに読みにいくためにコマンドを再送信して無反応時間を待たなければいけません。
よって、転送速度はバラつきます。
リングバッファサイズが大きいほど、早く転送が終わった分のマージンで、遅い転送の時間的穴埋めが
できる為有利です。
高速転送の際はこれが効いてきます。
40fpsの場合は28line分で動作しましたが、50fpsの場合は56line必要でした。
さらに60fpsでは68lineに拡張しました。うーん力技ww
リングバッファのline数÷2は、処理の都合上102line(垂直ブランキングを含めた画面サイズ高さ)の
約数です。
つまり、102÷(line数÷2)の答えが整数である必要があります。
⑥1line分のデータ
前回の図形描画の時はリングバッファサイズは水平ブランキング期間分も含めたましたが、
転送速度やデータサイズを考慮して今回は表示領域のみになっています。
その為、⑧で説明するように水平ブランキング中はDMA転送をとめて、リングバッファを進まないようにしています。
⑦DMA転送
CPUを介さずLCDにデータを送り続けてくれます。マジ天使。
TIM3が1クロックの時間を作っており、更新イベントでDMAリクエストが起動し、
SRAMからI/Oポートへ出力されます。
1クロックは72MHzの28分周です。
出力が間に合わなくなってきます。
そこでnatu_facさんの方法を参考にして下記のように対策しました。
秋月LCDは立下りエッジでデータを取り込む為、
TIM3によるメインクロックはHIGH期間を長くして(PWMのデューティー変更)
DMAがデータをI/Oポートに出力するのが間に合うようにしています。
⑧水平ブランキング中のDMA一時停止
文字通りですが、これの調整が地味に難しいです。
fpsを変える度に、調整しなければなりません。
DMAをストップするタイミングがズレると、本来より多くDMA転送されたり、少なく転送されたりして
画像が乱れます。
forループを使って時間調整します。
停止時と再開時両方のタイミング調整が必要な為、結構シビアです。
⑨垂直ブランキング中のリングバッファ書込みストップ
これは⑧に比べてとても簡単です。SDカードから読み出すline数を減らすだけです。
⑩水平ブランキング期間の調整
72MHzを分周しても正確な1クロックの時間は生成できません。
つまり、動画を再生していると(画像に乱れは出ませんが)
1分の動画の再生が59秒とか1分1秒で終了してしまいます。
同期をなんらかの方法でとる必要があると思うのですが
LCDクロックのストレッチをしてみたら画像がモロに乱れたので断念しました。
そこで水平ブランキング期間をいじる事によって誤差を穴埋めしています。
結果、5分程度の動画の再生で0.12秒の誤差に抑えられたのでとりあえず良しとします。
⑧と⑩はまだ改善の必要がありそうですね。
○使用したSTM32のペリフェラル
1.SDIO
3.TIM2(水平同期信号,DMA転送の一時停止、再開割込)
4.TIM5(垂直同期信号)
5.NVIC(割り込みは3つ。優先度の高い順に、DMA一時停止,SDIO,リングバッファ書込み,)
以上です。