チカラの技術

電子工作やプログラミング

BMPファイルをマイコンで使いやすい形式に変換するソフト

こんにちわ。
BMPファイルをマイコン用の画像形式に変換するソフトを作りました。

イメージ 3
先頭からデータを読み込んでそのまま表示できる無圧縮データを生成します。



○ダウンロード


実行ファイルのダウンロード


プロジェクトのダウンロード


○機能


このソフトはマイコンでの画像表示を支援する為のソフトでBMPファイルから変換します。
BMPファイルのフォーマットはこちらのページで詳しく解説されています。

主な機能は以下の3つです。
1.ピクセル配置を「下から上へ」→「上から下へ」に並び替えます。
例えばこのようなBMPファイルが有った場合、
イメージ 2
BMPフォーマットは下から上にピクセルが並んでいるのでマイコンで先頭から
画像を読み出すと下のようになってしまいます。

イメージ 1
このソフトはBMPファイルのpixlel配列を並び替えて先頭から画像を読める形式に変換にします。
(画像はcatman)

2.ヘッダファイルを削除します。(非有効化を選択できます。)

3.カラーbitを減色します。



○使い方


1.セレクタから出力したいカラー形式を選択してください。
ヘッダーを残したい場合は右隣のボックスをチェックしてください。
連番BMPの場合は先頭ファイルのヘッダーのみ残します。

2.変換対象のBMPファイルを含むフォルダを選択してください。
入力BMPのファイル名に5桁の連番を設定した場合、00001番から順に変換,結合されます。
00001の無い連番や途中で番号が抜けていた場合、欠番以後は単体のファイルとして処理されます。

選択後、出力ファイルの情報が表示されます。
「Serial file」に動画ファイルが含むBMPファイル数、画像サイズが表示されます。
「Unit files」に単体のファイルの数が表示されます。

3.出力ファイルを保存するフォルダを選択してください。


4.「Start to convert files」をクリックすると変換が開始されます。

5.終了後メッセージが表示され、ファイルが出力されます。
出力後のファイルは「xxxx_yy.bin」
xxxxxにはファイル名,yyには出力後のbit数を表します。

○入力と出力の関係
入力ファイルは8bit,16bit,24bitに対応しています。
ただし、BMP8bitはカラーパレットなので出力もカラーパレットのみ対応しています。
データは入力,出力共にリトルエンディアンです。

『24bit→RGB565』
入力ファイルが24bitBMのとき、ビット配列はMSBから
[R7 R6 R5 R4 R3 R2 R1 R0,G7 G6 G5 G4 G3 G2 G1 G0,B7 B6 B5 B4 B3 B2 B1 B0]
(R:RED, G:GREEN, B:BLUE)
です。

出力ファイル16bitは入力ファイルから
[R7 R6 R5 R4 R3 G7 G6 G5 , G4 G3 G2 B7 B6 B5 B4 B3]
にbit移動,減色されます。

『16bit→RGB555』
16bitBMPファイルはRGB555であるので入出力共に
 [ x R4 R3 R2 R1 R0 G4 G3,G2 G1 G0 B4 B3 B2 B1 B0]
となります。
よって色情報を多く取得したい場合は24bitカラーから16bitへ変換する事をお勧めします。


○画像生成に役立つお勧めのフリーソフト


○Super Bara-Baby X
http://www.vector.co.jp/soft/win95/art/se481023.html
動画からfpsを指定して画像を抽出してくれます。
このソフトで出力したBMPファイルの連番はそのまま私のソフトの動画出力機能へ入力できます。

○縮小マシン easypiccnv

http://www.vector.co.jp/soft/winnt/art/se486873.html
アスペクト比を保ったまま画像を縮小し、余白は設定した背景色で埋めてくれます。
ドラッグ&ドロップで複数ファイルの縮小が可能です。

○リネーム君
http://www.vector.co.jp/soft/win95/util/se093487.html
複数のファイル名を連番で変更してくれます。
Super Bara-Baby Xで抜き出した動画の一部分を切り出して変換したい時に便利。


○その他

○対応していない形式

1. 1bit,2bit,4bit, 32bit のBMPカラーには現在、対応していません。

2.  パディングを含むBMPは対応していません。
バイトパディングとはBMPの1行に含まれるデータが4バイトにアライメントしていない場合に詰め込まれるデータを指します。
入力カラーのバイト数(24bitなら3バイト)× 一行のピクセル数 ÷ 4 で余りが出た場合、そのBMPはパディングを含んでいます。
 一般的なLCDモジュールのpixel幅である320, 400, 480, 680 はパディングを含まないので使用できます。


その他の情報はreadmeを参照してください。
質問等有ればコメントでお気軽にどうぞ。

60fpsの動画をアップしました。

こんばんわ。



○UPしたよ

60fpsの再生動画をUPしました。
今回もささくれPさんの動画を再生させて頂きました。
データ量がSDカードに納まりきらなかったので前半の一部をカットしています。
申し訳ないです。

元は30fpsの動画です。
スピード感のある60fpsの動画が中々無かったので・・・

ただ、短銃にリフレッシュレートを60fpsにしただけではなく、フレーム補間法という
フレーム間に中間フレームを追加する技術を使って30fps->60fpsへ変換してヌルヌル度を上げています。
こちらのブログが非常に参考になりました。
AviSynthを用いたフレーム補間法


○つくづく撮影が・・・

うまくいっていません・・・
前回も言いましたが元はもっと綺麗な画面なのですが、ビデオカメラに映すと暗く写ってしまいます。
無理にISO感度等を上げても今度は白飛びしてしまってうまくいきません。
何度もやり直したのですが納得できる画質にはならなかったです。
実際の画面ははるかに綺麗なので興味のある方は自作して直接見てみてくださいね。



○謝辞

今回はスペック的にかなり厳しい電子工作で、自力だけでは60fpsを達成できなかったと思います。
ネット上の方にアドバイスを頂いたおかげでなんとかできました。
特にとんすけさん、J.SHIMADAさんには非常に有益なアドバイスを頂きました。
ありがとうございました!


次回は自作のBMP→バイナリ変換ソフトをUPする予定です。

50fpsの動画再生をアップしました

こんにちわ。

前回の日記で60fpsの再生が出来るようになりましたが、
無圧縮の動画サイズで60fpsを再生するとSDカードの4Gbyteを使いきってしまい
動画の再生時間が4分17秒が限界になってしまいます。

今、60fps再生の為の適した動画は探しているところです。

今回は50fpsで再生した動画を見て頂ければと思います。


○動画UPしたよ



再生させて頂いた動画はささくれPさんのタイガーランペイジです。
山月記をテーマにした動画で、自分がUPした動画でこの曲を再生するのはこれで3回目になりますw
素晴らしい音楽とMV。

実は50fpsに落としてもSDカードの容量が一杯になってしまい最後の数秒は描画できませんでした。
申し訳ないです。
なお、ソースの動画のフレームレートは30fpsです。
60fpsの動画は意外に少数派なのです・・・


○液晶について


1・画質
液晶を撮影していつも思うのは、本来の画質を撮影できないという事です。
実際はもっと綺麗で色鮮やかなので興味を持った人は自作して肉眼で見てもらえると嬉しいです。

この解像度の液晶になってくると表示がかなり高精細です。
youtubeで全画面にして見てもドットがほとんど分かりません。
自分でもハメコミみたいに見えてしまいますが、ちゃんと再生した液晶画面ですw

無圧縮ゆえマイコンのリソース大部分とデータ量を必要としますが
画質はマイコンで再生した動画の中 (狭w) でもかなりいい部類だと思います。

2.コントローラ無し液晶を使う利点
最近はVRAMを内臓したコントローラICのついた液晶が主流ですが
コントローラの無い液晶にも利点があります。

これは以前、自分がコントローラIC付きの液晶で動画を再生した際の経験ですが
画面の動きが激しいとき、画面がフラッシュした時に画面上に斜めのラインが現れてしまいます。
イメージ 1

この写真だと3本の線が現れていますね。
これはLCDの内臓コントローラが画面をリフレッシュするタイミングと
マイコンからのGRAMへのデータ書き込みが非同期である事によって起こる現象です。
リフレッシュしている間に次の画像がGRAMに書き込まれると、
別のフレームの画像が同じ画面に現れてしまいます。

逆にコントローラICの無い液晶はこのような現象が発生しないため
動きの激しい動画の再生にも適しています。
自分は動きのある動画が好みなのでコレは大きなポイントですね。


○.ピン配置変えました。

SDIOのCMDピンがPDポートだという事が分かったので
16bitポートをPD→PEへ変更しました。
SDIOの他のピンはPCなのになぜ・・・・

それからTIM3のピンもSDカードソケットの実装に邪魔になったのでCHを変えました。
今のピン配置は以下の通りです。
イメージ 2

ピンの移動に伴いボード上の加速度センサも取り外しました。
イメージ 3
仕方・・・仕方なかったんや・・・

以上です。
次回は60fps動画をあげたいと思います。



SDカードの読み出し速度向上とオーバークロック

こんにちは。

共立2000円液晶で動画表示を目指しています。
動画再生の仕組みは至って簡単で、画像をフレームレートの数だけ連続で描画するだけです。

画像表示は前回成功したので、残るは以下の作業だけです。

①PC上でmp4などの動画からマイコンで扱える画像データへ変換
②STM32F4の読み出しバッファに画像データを供給する。

①については自作のソフトを作りました。改良して公開できればと思っています。
今回は②について話します。



○転送速度の見積もり

バッファに供給する1秒当たりのデータ量を決定します。

①いきなり妥協

液晶は24bitカラーで表示できるのですが、
正直肉眼でじっくり見ても16bitカラーとの差が判別できなかったので動画は16bitカラーとします。

②2000円液晶、恐ろしい子
実際に見積もって見ます。

480×272×2 (16bitカラー) × フレームレート = 1秒辺りの転送量
イメージ 1
ヤバイ。

STM32F4が読み出せるSDカードの理論上の最大転送量はデータバス×クロックなので
0.5 (4bit) × 24MHz = 12MByte/secです。

つまり50フレーム以上は理論値を超えているのです。

③もはや運
次にSDカードをかき集めて実際の読み出し速度を調べてみました。
イメージ 2

この中で最も転送速度が速かったのがPQIの8GBカードで(下段、左から2番目)
9.4MByte/secでした。(マイコン側のバッファサイズは100kbyte)

マイコンでの読み出し速度はPCと違い、価格やスペックに全く比例しない所が厄介です。
取り出して使ってみるまで分からないのでSDカードというよりデュエルカードみたいです。

③フレームレートの決定
決定というより、むしろ30fpsしか選択肢はありません。
しかし、ここでコントローラ無し液晶の問題が立ちはだかります。
フレームレート=リフレッシュレートが低いと画面にチラつきが生じてしまうのです。

リフレッシュレートとチラつきの認識度合い
30fps:ハッキリ分かる。
40fps:かすかに分かる
50fps:全く分からない

葛藤しましたが、やはり綺麗に動画を再生したかったので50fpsを目標としました。

限界を超えねばなぁJOJO・・・


○SDカードのオーバークロック

実はとんすけさん,ねむいさんは転送速度の限界を既に破っています。
何をしているのかというとSTM32F4を下記のように設定して
SDカードへのクロックを24MHz→48MHzと倍増させているのです。

SDIO_InitStructure.SDIO_ClockBypass = SDIO_ClockBypass_Enable;

これはSTM32F4のSDカード制御としてはオーバークロックでSDカードが壊れる可能性すらありますが
規格の中に納まっていたのでは達成できない転送量はやはり魅力的です。

という事で先ほどのSDカードを全てオーバークロックしてみました。
しかし読み出しができたのはなんとそのうち一つだけでした。
イメージ 3
シリコンパワー speed10 8GB

読み出し速度は12.8MByte/secで残念ながら目標に達成していません。
しかも読み出しが凄く不安定で開始後数秒で読み出しが出来なくなってしまいます。



○最強のSDカードとは

ここで数日間行き詰ってしまいました。
オーバークロック無しで複数のSDカードを使う事も考えましたがSPIによる
SDカードの転送量は3Mbyte/sec程度なのでそれでも足りません。
バッファを分ける事によって転送速度が逆に下がる可能性もあります。

煮詰まってたところでとんすけさんがカードを紹介してくれました。
『私が出会った中で最強のカードはKINGMAX製キティーちゃんの4GB CLASS4のものです。
 50MHzで18MB/sでました^^』

ティーちゃん!? と色んな意味で驚きを隠せませんでしたが、
本当に困っていたので早速amazonで購入しました。

イメージ 4
心なしか輝いて見えます。

ドキドキしながら転送量を調べたところ自分の環境では14.8MByte/secでした。
おお、50fpsの目標クリアです!

しかし、これも数秒後に読み出しが出来なくなってしまいました。
・・・困った。



オーバークロック対策

読み出しの不安定さを解決すべく調べて対策をしました。
結果、下記の対策により安定して読み出せるようになりました。

1.インダクタの除外
SDカードの回路は下記のようになっています。
イメージ 6

このうち電源ラインのインダクタはSDカードから発生する(マイコンボードへの)電源リプルを
低減させるフィルタの役割をしています。

しかし、オーバークロックによって消費電流が増した事で、インダクタが電流供給の妨げになり
十分な供給がされなくなっていたという事が分かりました。

そこでインダクタを除外して直接マイコンボードの電源をSDカードの電源へ接続しました。
電源リプルが100mV程度になりましたが、マイコンの動作に影響はありませんでした。
しかしオーディオを扱う際は注意したほうが良さそうですね。

2.配線は最短に
バスクロックが上がった事で信号線長による信号の反射が大きくなり、耐ノイズ性が低下しました。
DISCOVERYボードから5cm程度の配線でも読み出せなくなります。
フェライトコアを使っても効果はありませんでした。

そこでソケットピンに直接接続して配線長を最短にしました。
イメージ 5

Vddピン以外はソケットに直接差し込んでます。



○DMAの競合問題

読み出しは安定してできるようになったものの、
フレームレートを上げると再生中に画面上に液晶欠けのような白い点がポツポツと出るようになりました。

これはDMAの転送が競合している事によって起こる現象です。

LCD表示用の内臓SRAM→GPIOへのDMA転送と、
SDカード読み出し用のSDIO→内臓メモリへのDMA転送は共にDMA2のみアクセス可能で
DMAを使うと競合は避けられません。

そこでSDカードの読み出しをソフトウェアポーリングに変更しました。
SDIOのFIFOにデータが溜まるとフラグが立つのでそれを待ってCPUで内蔵メモリへデータを転送します。
効率の良いマルチブロック転送のポーリングプログラムをとんすけさんに教えていただきました。

ポーリング待ち部分のプログラムです。
    do {
        if (STA_RXFIFOHF_BB_FLAG) {
            pbuff[0] = SDIO->FIFO;
            pbuff[1] = SDIO->FIFO;
            pbuff[2] = SDIO->FIFO;
            pbuff[3] = SDIO->FIFO;
            pbuff[4] = SDIO->FIFO;
            pbuff[5] = SDIO->FIFO;
            pbuff[6] = SDIO->FIFO;
            pbuff[7] = SDIO->FIFO;
            pbuff += 8;
        }
    } while (!((sta = SDIO->STA) & SDIO_BLOCK_READ_STATUS_MASK) && timeout--);


DMAと比較しても速度に遜色ありませんでした。



○もう一声!!

これで50fpsで再生する為の読み出し環境がやっと整いました。
しかし・・・50fps・・・なんだか凄く中途半端です・・・

秋月300円液晶は60fpsだったというのもあるし、
60fpsの動画は再生できないという制約も気になります。

せっかくなのでさらに転送速度を上げる為にチューンする事にしました。

調べた結果、ボトルネックはやはりSTM32F4側のバッファサイズでした。
バッファサイズが小さいとマルチブロック転送で一度に読み込めるブロック数が少なくなり
転送速度が低下するのです。(詳しくはこちら
前回、秋月300円液晶の時も最後はバッファサイズを拡大して転送速度不足を解決しました・・・

バッファサイズを100kByteから120kByteまで拡大しました。
これはSTM32F4の内臓SRAM(DMAでアクセスできないCCM領域を除く)のほとんど全てになります。

マイコンのリソースをほぼ全てSDカード読み出しに注ぎ込んだ結果、
転送量は15.8Mbyte/secまで向上しました!
これでやっと60fpsで動画を再生する準備ができました!


○謝辞
今回、様々な過程で煮詰まった際に貴重なアドバイスをくれた
とんすけさんJ.SHIMADAさん、本当にありがとうございました!


○参考サイト

とんすけさん:SDカードのベンチ比較 マイコン工作で速いカードはどれ?
ねむいさん  :STM32F4シリーズを使ってみる3 -FatFsと下部レイヤ(SDIO・MMC)ドライバたちの実装-

共立電子2000円液晶で画像表示

こんばんわ。

先日、日本橋のシリコンハウスで購入したTFT液晶ディスプレイ「FG040346DSSWBG03-DJK」
液晶コントローラを使わずSTM32F4DISCOVERY単体で駆動しました。

イメージ 1

480×272bit 24bitカラー リフレッシュレート75Hz
外付けのSRAM,ROMは使っていません。
背面にあるのはロジアナのLAP-Cです。

今回は前回の秋月300円液晶での反省点を活かして駆動方法を工夫しました。

まず液晶の仕様を紹介した後で、STM32F4による駆動方法を説明します。


○液晶の仕様
共立液晶はいわゆる秋月3000円とほぼ同じ仕様の液晶です。
またPSPの液晶に近い仕様になっていますが電源電圧やピン配置はPSP液晶と異なるため
互換性はありません。

秋月液晶との違いは秋月液晶の画面がノングレアであるのに対し、
共立液晶はグレアタイプで光沢があります。
個人的にはグレアタイプの方が色が鮮やかに見えるので好みです。

イメージ 2

ピン配置です。
画素データ以外の信号はクロックのPCLKとデータのゲート信号のDEのみで
水平と垂直の同期信号は使用せずにNCとしても良い事になっています。
どうやって同期を取っているのかというと次のような仕組みになっています。

イメージ 3

ブランキング期間の記載はデータシートに無かった為、シャープのPSP液晶を参考にしました。

表示期間中にDEをHIGHレベルにして、
その間のPCLKの立下りクロックごとに1pixelを取り込むようになっています。
水平ブランキング期間は45PCLK以上,垂直期間中は14H以上の間 DEをLOWレベルにします。
DEのHIGH期間で画像の表示タイミングを同期できるのでLCDコントローラの付いていない
液晶の中では比較的簡単で使いやすいと思います。


○回路

1.STM32F4DISCOVERY
LCDとの接続は上記の表どおりですが、
私の使っているボードはピンを自由に使うためにボード上の加速度センサ以外の部品を取り除いています。

イメージ 4


2.昇圧・定電流回路


このLCDLEDバックライト用に24Vの電圧と20mAの電流を必要とします。
これを5Vから生成する為に、MC34063を使った昇圧 + 定電流回路を組みました。
定電流にしたのはDCDCのリプル電圧でバックライトがチラつかない様にする為です。
イメージ 10


C3までが昇圧回路でそこから右側が定電流回路です。
右端の2つのピンにLEDアレイをつなぐと、21mAの定電流が流れます。
この時入力には160mAの電流が流れたので出力から見た効率は63%です。
MC34063は安い割に昇降圧どちらにも使えるので手元にあると便利ですね。

3.FPCコネクタ
前回、秋月300円液晶で散々接続に苦労したので今回は最初からaitendoにて
40pinのFPCコネクタを購入しました。
接続は下接点です(一度間違ってしまいました)。


○STM32F4による駆動

○前回の反省点
前回、秋月300円液晶を駆動した時の反省点は下記のとおりです。

①DMAのソフトウェア制御
DMAで内臓SRAM→GPIOへデータを転送していたが、ブランキング期間にDMAリクエストを止める
必要があり、ソフトで制御していた為にタイミングの調整が非常にシビアで大変だった。

②不正確な1フレーム
内臓SRAMの容量が一画面に足りないので小刻みに画像データを送り出していた。
1フレーム(30FPSなら1秒に30フレーム)に画像一枚を対応させる必要があるので1フレームの期間が正確に1/30秒になっていないと動画を再生する際に、本来の再生時間とずれてしまう。
しかし液晶の1クロック単位の長さをソフトでうまく調整する事が出来なかった。

○分析
結局、数MHzの周期で動き続けているDMAデータ転送やクロックを、
無理にソフトウェアで止めたりタイミングを調整していた事が主な原因でした。
CORTEX-M3は割り込みルーチンに入るまでに12クロック掛かるので
とめたいLCDクロックを先読みしてルーチンに入り、ルーチンの中でもタイミングの微調整が必要で苦労しました。根性で動かしていましたがw



○タイマ最高
そういう訳で今回はタイミングの制御は一切ペリフェラルに任せられるようにしました。
結果、正確なタイミングで転送できるようになり、ソフトはサーキュラーバッファに画像データを供給すれば良いだけになりました。

STM32F4は高機能なタイマが合計10個もあるので非常に応用の幅が広く便利です。
FPS=60の場合を例にとり説明します。

1.使用タイマの概要
今回は以下のようにTIMを5つ使用しました。全てPWMモードで駆動しています。
イメージ 6

●用語
タイマのゲート機能について
ゲート機能においてマスターとなったタイマはスレイブのタイマにゲート信号を送ります。
そしてゲート信号がHighレベルの間のみ、スレイブにclock(今回はAPBクロック)が供給されます。

タイマのリセット機能について
マスターはスレイブにリセット信号を送ります。
スレイブのカウンタはリセット信号の立ち上がりエッジで、カウントをリセットします。

DMAリクエストについて
DMAはDMAリクエスト毎にメモリ上のデータをペリフェラルに転送できます。
今回はタイマのPWM立ち上がりエッジのタイミングでサーキュラーバッファのデータをGPIOの出力レジスタに転送し、LCDへ1画素分の信号を送っています。
サーキュラーバッファの半分もしくは完全にデータを転送した時点で割り込みが起こり、
CPUにデータのプッシュを要求します。

2.信号の全体像
イメージ 5
実際のブランキング期間は仕様よりも長くなっています。
これは内臓クロック84MHzからPCLKの1周期を作ると分解能が足らず端数が出てしまう為です。
例: 1PCLKに対する内臓クロック = 84MHz ÷ (480 + 45) ÷ (272 + 14) ÷ 60fps =  9.32
端数は切り捨てになるので、切り捨てた分の誤差をブランキング期間で調整しています。

5つのタイマーの中で実際にLCDに信号を送るのはTIM2の水平ゲートとTIM3のPCLKのみであり、
他は同期とDMAリクエスト用のタイマとなっています。
水平ゲートは画素の送出を制御し、垂直ゲートは水平ゲートを制御しています。
また、垂直ゲート用タイマはPCLKを画素の出力タイミングと同期させる役割もあります。

3.水平ゲートの説明
以下はロジックアナライザで測定した水平ゲートの立ち上がり,画素表示の開始部分の波形です。イメージ 7水平ゲートの立ち上がり後にDMAリクエスト用タイマのPWM波形が現れているのが分かります。
DMAリクエスト用タイマの立ち上がり時にDMAリクエストがDMAへ送られます。

DMAリクエスト用のタイマを二つ使用しているのは1つのGPIOポートが16bitなので24bitカラーを表示するために2つのGPIOが必要で、各々のDMAリクエストを送るタイマが必要だった為です。
本当はDMA1とDMA2を併用させたかったのですが、DMA1はGPIOとバスが繋がっていないためDMA2のみ利用しました。
各々のGPIOに対してサーキュラーバッファを用意してデータを供給しています。
(DMAにスキャッタギャザー機能が有ればバッファは一つで済んだかも知れませんが。)

TIM3は常にLCDにPCLKを供給し続けますが、DMAリクエスト用タイマは水平ゲートがHighの間のみ画素をLCDに送ります。
そして水平ゲートがLowの間、水平ブランキング期間を作ります。

LCDはPCLKの立下りエッジで画素を取り込むので、それまでにGPIOにデータをセットアップしなければなりません。(厳密にはLCD側に信号取り込みのセットアップ時間が必要なのでそれより12nsec早く)
PCLKの立下りまでの時間を稼ぐために、DMAリクエストのタイミングをPCLKの立ち上がりより早くなるよう周期をずらしています。

横向きの矢印がDMAリクエストからGPIOの出力までの期間を示していますが、PCLKの立下りよりも十分早く出力されています。
明らかにDMAの反応がSTM32F1より早くなっています。
GPIOがAHBバスに直結されて、APBバスを経由するレイテンシが無くなったおかげですね。

4.垂直ゲートの説明

以下は垂直ゲートの立ち上がり,1フレームの開始部分の波形です。
イメージ 8
垂直ゲートはLCDに信号を送っていませんが重要な役割を担っています。
垂直ゲートがLowの間、水平ゲートのクロックが停止し垂直ブランキング期間を作ります。
また、1フレームを正確に1秒/FPSの期間に調整しています。
1フレームをTIMクロック単位で調整すれば水晶振動子の精度で正確な1フレームが作れます。

ただし、PCLKはクロックと同期しているわけでは無いので、1フレームごとに調整しなければ
ゲートやDMAリクエストのタイマ周期とずれを起こしてしまいます。
そこで垂直ゲートの立ち上がり時にPCLKにリセット信号を送って同期を取っています。
リセット信号から実際のリセットが起こるまでは矢印で表されるように数クロック分の遅延があります。

水平ゲートのLow期間の中央で垂直ゲートが立ち下がるようにしているので、水平ゲートの立ち上がりは画面外のずっと先です。

○ハマったポイント

TIM1とTIM8はSTM32の中でも高機能タイマに分類され、
モータ制御用に使用されるBREAK入力機能がついているのですが、ここでハマりました。
このBREAK機能の中でoutputの有効化という機能があるのですが、これがデフォルトの設定では
タイマー出力ごとにoutputが無効になるように設定されていてPWM信号を止めてしまうのです。
他の汎用タイマのようにPWMを設定するとここでハマると思います。

解決策ですがタイマごとに下記のように設定して
タイマの更新イベントごとにoutputが自動的に再有効となるようにします。

    //These settings are needed for continuous PWM cycle.
    TIM_BDTRInitTypeDef bdtr;
    TIM_BDTRStructInit(&bdtr);
    bdtr.TIM_AutomaticOutput = TIM_AutomaticOutput_Enable;
    TIM_BDTRConfig(TIM1, &bdtr);


○小技

☆DMAでGPIOの上位bitのみ操作する方法
今回GPIOBポートのB8 - B15までを8bitカラーに割り当てています。
STM32F4はGPIOがAHBに直結しているのでB0 - B7 に影響を与えずに
上位bitにアクセスする事が出来ます。 

具体的にはDMAの設定時に下記の通りペリフェラルアドレスを設定してバイト転送を行います。
DMA_InitStructure.DMA_PeripheralBaseAddr =  (uint32_t) ((uint8_t *) &(GPIOB->ODR) + 1);


なお、STM32F1はGPIOがAPBブリッジを経由している為、ワード未満のアクセスはワードに拡張されるので上記のようなアクセスは出来ないと思われます。(未確認)


○画質は?
今までに扱ってきた液晶の中で一番綺麗でした!

ただ、写真に撮るとどうしても画質が劣化してしまうのが残念です。
肉眼で見るともっと綺麗なのですが。
イメージ 9

画像データは無圧縮でSTM32F4の内臓ROMに収められ、1枚 480 * 272 * 3 = 391680byteです。
秋月液晶のときは16bitカラーで駆動したので 400 * 96 * 2 = 76800byteだったので5倍以上ですねw

これほど大量のデータを処理できるSTM32F4の能力は素晴らしいと思います。

それでは次は動画の再生にチャレンジします!

参考にさせて頂いたページ:
Chanさん    :秋月3000円液晶モジュールの試食
charanori さん:RX62Nで秋月3000円液晶 ATM0430D5の味見
Coocox forum :PWM STM32F4

STM32F4DISCOVERYと戯れる

こんばんわ。
今日の日記には電子工作要素はありません。


○ピンヘッダの改造

2週間前からSTM32F4DISCOVERYを始めたのですが
「念願のSTM32F4DISCOVERYを手に入れたぞ!」という感じでは全然無く、
一年前に買ってはいたものの言語の壁や開発環境がネックとなって使っていなかっただけです。

使い始めてすぐ分かったのですが、ピンヘッダがとても使いにくい。
2列になっているのでブレッドボードに差して使えるわけでもありません。

STBeeに慣れ親しんだ自分としてはソケットピンに変更したい。

そう思ってヘッダピンを抜く方法を考えました。
一本づつ抜くのは大変なのでアイロンでピンを熱して一気に抜こうと考えました。
イメージ 1

しかしいくら時間をかけても抜けない。

イメージ 2

均等に全てのピンにアイロンが当たらないのです。
しかも点接触なので全然熱量が足らない感じでした。

普通はここで諦めてチマチマ抜いていくところです。




でも僕は、オリーブオイル!
イメージ 3

油にピンヘッダの足がどっぷり漬かれば熱がしっかり伝わって抜けるに違いない!

「料理は科学だ」と昔の偉い人は言いましたが、
じゃあ逆に科学を料理してもいいんじゃないか、俺は正義だ。などと考えました。
(しかしオリーブオイルは高いのでサラダ油に変えました。)

イメージ 4

汚いコンロで申し訳ないです。
基板の下にカマボコの板を乾かしたものを敷いて基板をかさ上げしています。
こうしないと上からピンを押しても抜けませんからね。

しかし、火をつけて数分、予想外の事態が発生しました。
乾いていると思っていたカマボコの板に水分が残っており、油がはじけ始めたのです。

イメージ 5
必死に押してます。

飛び散る油、火に炙られる手、「晩御飯が作れない」と訴える家族。
そういった諸々に耐えつつピンヘッダを抜こうと頑張ってみましたがどうにも抜けません。

しばらくして・・・諦めました。
終わってから基板にベッタリついた油を拭いている時が一番惨めでした・・・
イメージ 6
結局ピンヘッダは抜かずに、上面のみ切りそろえてソケットピンをはんだ付けしました。
当初の目標は達成できたので良しとします。
イメージ 6

それからもう基板を油で煮るのは辞めようと思いました。
もこみち凄い。


○豊富過ぎる周辺部品

STM32F4DISCOVERYボードはMEMSやオーディオコーデック等の部品が沢山載っています。
しかし、それが設計をする上で障害となる事も多くあります。
特にSDIOとFSMC関連のピンが塞がれているのが非常に辛い。
STM32の良さはそこにあると信じている自分としてはなんとかしたい所です。

MotionJpegによるメディアプレイヤー』を作られたとんすけさんに伺ったところ
FSMCとSDIOが繋がっているのは周辺部品の入力ピンなので、
部品を取り外さなくても使えるという事が分かりました。

これは非常に助かりました。
しかし、他のピンを新しい回路に使おうと考えるたびに周辺部品と競合してしまうので
とうとう心が折れ、もういっそ綺麗にしてしまおうと思って加速度センサ以外全部取り外しました。

イメージ 7

これでほぼ全てのピンを自由に使えます。凄くスッキリした!

外した後にUSBは外さないほうが良かったかも知れないと思いましたが、
テンションが上がっちゃってたからしょうがないですね。

○外しにくい部品

写真を見れば分かりますがオーディオコーデックの底面は全面がパッドになっており、
非常に取り外しにくいです。
外側から熱して外すのはまず無理でしょう。
参考までに自分の場合を書いておきます。

1.パッケージをコテで熱する。半田を盛って熱が伝わる範囲を大きくする。
2.30秒熱しても取れないが、パッケージは熱で劣化するのでラジオペンチで砕く事ができる。
3.砕いて薄くなったパッケージをさらに熱すると部品が外れる。

もっと綺麗な外し方があるかもしれませんね。

これで安心してこのボードを使っていく事ができます。
それでは!

STM32F4DISCOVERYでWAV再生

こんばんは。
STM32F4DISCOVERYに載っているオーディオコーデック(アンプ付DAC)CS43L22の
音質を確かめてみたかったのでwav再生を試してみました。


○ソフト
STマイクロのファームウェアの中にあるCS43L22のAPIサンプルと、
MMCをFatFsから読み出せるように移植されたねむいさんのライブラリを使わせて頂きました。

プログラムの構成は以下のようになっています。
1.DMAをサーキュラーモードに設定してバッファ全体をSDカードから音声データで埋める。
2.I2Sはコーデックへの送信前にDMAへリクエストを送り、バッファからからデータを受け取る。
3.I2Sはサンプリング周波数の周期でコーデックに音声データを送信。
4.バッファの半分、もしくは全てが送信されるとDMAが割り込みを発生させる。
5.割り込み時にバッファへ半分ずつSDカードからデータを埋める。
6. 2~5を繰り返す。



○嵌ったポイント

1.DMAのバッファサイズ
STのライブラリの関数「Audio_MAL_Play」ではI2Sインターフェイス時のDMAバッファサイズの設定が
Size /2 となっています。
しかし引数の「Size」は4バイトで、DMA送信サイズが2バイトなので、DMA_BufferSize=(データ転送回数)はSize×2としなければいけません。
ここを変更しなければデータ転送がバッファの一部だけになって、まともに音楽が再生できません。

イメージ 1
1517行目が修正箇所

2.I2S_PLLの設定
サンプリングレートに応じたI2Sクロックを設定する為にはerrorの低いI2S_PLLの設定値が必要です。
パラメータが多いので手計算では難しいのですが、pcm1723さん
計算用プログラムを公開されていたので使わせて頂きました。

結果を載せておきます。
イメージ 4

基準周波数2MHz (HSE=8MHz, PLLM=4)


イメージ 5
基準周波数1MHz HSE=8MHz, PLLM=8)

○音量の調整
サンプルの設定では音量が物足りなく感じました。
「Codec_Init」内の設定を以下のように変更しました。
PCMボリュームは最大値にしています。
Headphone Analog Gainはまだ大きく出来ますがデータシートで音質に影響が出ると
警告があったので影響のない範囲で一番大きな値にしました。

 
イメージ 6


この設定でMasterVolumeを最大にしましたが、残念ながらまだ音量が物足りなく感じました。
CS43L22のチップサイズから見てこれが限界なのでしょうか。
実用レベル以下なので、何か設定が間違っている可能性が高いと思います。
もしも、音量をさらに上げられる設定をご存知の方が居たら教えてもらえると非常に助かります。


音量調整できました! 音質改善の最後に追記しています。



○視聴と音質の改善

1.改善前
聞きながらノイズが気になったので何度か改善を試みました。
まず、電源をUSBからリニア電源へ変更して再生した音楽を録音したものがこちらです。
使用曲はgoing_on (44.1kHz 16bit ステレオ)。

イメージ 2

電源のみ対策


2.電源ループの改善
ノイズがハッキリ聞こえますね。
色々試した結果、SDカードのGNDがSPIの信号線から離れている為に
ループが大きくなりノイズが発生している様子でした。
そこでループを小さくする為にC28に電源を直接配線しました。

イメージ 3


ノイズが小さくなったのが分かるでしょうか?

3.SPI周波数の変更
最後にSDカードのSPIの信号ノイズが小さくなるように必要最低限までSPIの周波数を下げました。

SPI2のBaudRatePrescalerを2→16へ

小さくなったとはいえ、まだ聞こえますね。

4.音量の調整
ホワイトノイズが主たるノイズですので、出力にシリアルに抵抗を繋げてS/N比を改善したいのですが、
CS43L22が出力できる最大音量が小さいので、抵抗で出力を抑えると音楽が小さくなってしまいます。


追記:音量が小さくなっていた原因が分かりました。
STのライブラリの初期設定と音量の設定関数は下記のような
ユーザーが設定したボリュームを変更するマクロが挿入されています。
イメージ 7
このVOLUME_CONVERTマクロによって100を超える設定値は全て100になっていたのです。
設定値100以下の場合は100分率で最大255に変換するマクロで、
このマクロの存在を知らなかった自分は255を設定してしまっていたという事でした。

設定値を100に変更したところ非常に大きな音が鳴りました。(耳が痛い!)
大体50程度が通常の音量だと思います。

改めて録音しました。非常にいい音になっています!


設定を調整し音量UP

5.抵抗の挿入(アッテネータ)
録音した音楽ではほとんど聞こえないのですが、実際にイヤホンを付けて聞いていると
ホワイトノイズがまだかすかに聞こえます。

対策としてDISCOVERYボードの出力に直列に抵抗を挿入する事にします。
ボリュームに関わらずホワイトノイズは一定ですので、抵抗でホワイトノイズを含む
全体の音量を下げた後ボリュームを上げればホワイトノイズを抑える事が出来ます。

DISCOVERYボードの改造はパターンの配線上難しかったので
ステレオジャックから自作のアッテネータを中継してイヤホンに接続するようにしました。
アッテネータといっても、各チャンネルの入出力間に47Ωを経由させるだけのものです。


録音しました。


ホワイトノイズは完全に消えています。
直列に抵抗を挿入すると若干周波数特性が変化しますが、自分は許容範囲内でした。


○まとめ

正直マイコンボードでここまでいい音が聞けるとは予想外でした。
心配していたホワイトノイズもほとんど聞こえません。

とんすけさんとAndreasさんのブログを設定の参考にさせて頂きました。

今回は凄く地味なテストでしたが、オーディオはとても繊細だという事が良く分かりました。
これが液晶の再生だと、些細なノイズがあっても信号のスレッショルドをまたがない限りは
画質にほぼ影響が無いのでとても楽ですねw

それでは!