● 実験テーマ59
「PIC32MX_オシロ画面イメージを、SDカードに書込む実験」
(モノクロ液晶のオシロ画面を、BMPイメージとして、SDカードに書込む実験をしてみました。)
・以下、この実験の顛末記です。
■ 2014.10.15
・前回の実験で、SDカードに記録されている、モノクロ128x64の、BMPイメージを、読込んで
同じ解像度のモノクロ液晶に表示することは出来た。
今回は、その逆で、モノクロ液晶に表示されている画像(オシロ画面を想定)イメージを、
BMPファイルとして、SDカードに記録(書込み)する実験をしてみようと思う。
読込みより、書込みの方が、難しいし、まして今回は、液晶画面のイメージを書込むので
なおさらである。
本当に実現できるのかなと思いつつ、実験の準備を少しずつ始めた。
・最初は、超簡易チェックにする。
@ ベースのハードは、PIC32MXトレーニング基板を使用。
A オシロ動作にしたいのだが、タイムベース切替用の、ロータリディプSWの信号線は、
丁度、SDカードの、SPIポートと重なっているので、タイムベース(時間軸)は、1mS/div
固定にした。
今回は実験なのでこれで十分である。
B SDカードへの、イメージ保存ファイル名は、「TEST.bmp」固定とする。
<チェック方法>
@ オシロ画面に適当な波形を表示する。
A HOLD SWを押して、波形をホールドさせる。
B WRITE SWが押されたら、その波形を、SDにセーブして、ファイルクローズさせる。
C 保存後、PCのエクスプローラにて、ファイルを閲覧し、TEST.bmpが生成されているか確認する。
D 保存されたbmpファイルを、ビューワ等で見た時、液晶画面上の表示と同じであるか確認する。
■ 2014.10.16
・これからの作業予定を書きだしてみた。
@ ソフトは、以前作成した、「Scope_PIC32MX.c」を、大元に使う。
A これに、外部割込みで、HOLD SWを読込んで、メインで表示をホールドさせるルーチンを追加する。
このホールドループ内に、書込みルーチンを追加する。
B トレーニング基板で、その動作を確認する。
・今回のソース名は、「PIC32MX_BMP_WriteTest_1.c」とした。
・ソフトを、検討し始める。
まずは、HOLD
機能の追加(これは、何度も実績あり)をし、SD(FAT32)関連のフォルダも追加
してプロジェクトを組み、ビルド〜HEX書込みまで済ませ、オシロ動作/HOLD動作までは問題
ないことを確認した。
・核心部のソフトを考えないといけない。
いくつかあるが、主要部は以下
@ 液晶画面を読込んで、そのデータを、Disp_BUFに格納
A Disp_BUFの内容を、標準BMPデータに変換し、Bufferに格納
(丁度、SD読出しの時と逆の操作)
B ヘッダ情報部62バイト分を、BMPイメージデータの前に付加する。
C それを、SDカードに書込む。
■ 2014.10.17
・核心部のソフト検討
昨日の、@ 液晶画面を読込んで、そのデータを、Disp_BUFに格納
については、void lcd_ImageRead(void)という関数名にして、後閑氏が作成された、lcd_Read関数を
下請け関数として利用し、何とか書き上げた。
次に、A Disp_BUFの内容を、標準BMPデータに変換し、Bufferに格納する関数を考えた。
今回は、縦方向8bit列を、横方向8bit列にする変換を考えないといけない。
関数名を、void Conv_DispBufTable_to_BmpTable(void)とした。
これは、前回作った変換関数を、ちょうど逆に考えていけばよいので、ちょっとややっこしい面はあるが
これも何とか書き上げた。
■ 2014.10.18
・今日は、B ヘッダ情報部62バイト分を、BMPイメージデータの前に付加する
を考える。
最初は、この部分(ヘッダ情報)を、WAVファイルの時と同じく、構造体で定義と、固定値設定を
してみた。
このように記述しました。(あくまで記述例です。)→ HEADER.txt
・次に、Cの、「それを、SDカードに書込む」部分を書かないといけない。
■ 2014.10.19
・オシロ表示から、液晶画面イメージの書込みまでの、ヒューマンインターフェースを含め
とりあえず、ソースを書き上げた。
コンパイル〜へHEX書込みまで何とかOKになるが、動作確認で、まずは駄目。
@ オシロ画面ホールドは、OK
A WRITE SW ONで、カード検知〜ライトモードで、ファイルオープンまで成功していることは
確認できた。
B 次のヘッダ書込みのところの、whileループを抜けたところに来ない。
C 試しに、ヘッダ書込みブロックをコメントアウトして、BMPデータ1024バイトの書込みのみ
実行後、ファイルクローズまで動かしてみると、正しく動く。
また書込み終了後、自動的に、オシロ計測画面に戻る。
■ 2014.10.20
・ヘッダ情報部62バイトの、SDカードへの書込みが、うまく行かない。
ヘッダ部の構造体での定義と固定値設定の記述を見直すが、良さそう。
この記述は、WAV録音付のMP3プレーヤ(PIC24F使用)の時と、同じ書式で書いたのだが、
PIC32MXでは、この構造体の記述では何か問題があるのか・・・
ただ、コンパイルエラーは出ていない。
この部分のメモリエリア割付がうまくいってないのかな?
よく解らない。
本当に問題があるのか、試しに、構造体記述によらないで、単純に配列で、16バイトの適当なヘッダ
データを用意して書込んだ後、1024バイトの、BMPデータを書込んでみたら、うまく行った。
(バイナリエディタにてデータダンプで確認した。)
そこで、構造体による記述をあきらめ、単純に配列で、62バイト分のヘッダデータ部を記述して
みた。
まあ、今回は、固定値書込みでよいので、特に構造体記述にこだわることもない。
このように記述しました。→ HEADER2.txt
この修正で、SDカードへの書込みまで、プログラムは、RUNしたが、SDカードに生成された
「TEST.bmp」を、ビュワーで開くと、何やら、:点画(または、QRコード)のようなイメージが現れた
ではないか??
・生成された「TEST.bmp」を、バイナリエディタで、ダンプしてデータそのものを確認したところ、
ヘッダ部の62バイト分は、間違いなく書込まれていることを確認した。
ところが、肝心のイメージデータ本体が、おかしい。
ざっと見て、上のイメージ通りの、データ並びになっているようだ。
(上のイメージ図の、黒い帯状になっている部分は、0x00で埋め尽くされている。)
黒い部分が多いのは、心当たりがあったのですぐひらめいた。
読込んだイメージデータを、反転する必要がある。
これは、液晶への白黒表示論理と、標準BMPデータの白黒論理は、反転の関係にあるからである。
それともうひとつ間違いを見つけた。
Disp_BUFの内容を、標準BMPデータに変換し、Bufferに格納する関数に誤りがあった。
基本はあっていたが、8x8ビットブロック移動時の条件文が抜けていたのと、while文の条件式が
違っていた。
この2つの点を修正したら、Windows7標準のビューワと、フリーのビューワ:jTrimで、
「TEST.bmp」を開くと、液晶画面(オシロ画面)のイメージが、うまく取れていることを確認した。
いくつかのイメージサンプルを取りたかったので、この時に、保存ファイルのファイル名自動更新ソフト
を追加した。
しかし、ファイルをエクスプローラで閲覧した時に、更新日時の項目表示がデタラメになっている。
■ 2014.10.21
・何とか、オシロ画面のキャプチャ(SDカードへのイメージ保存)実験はうまく行ったが・・・・
エクスプローラで、BMPファイルの更新日時を見ると、目茶苦茶な日時になっている。
たぶん、タイムスタンプを、SDカードのどこかに書込まないと駄目と思われる。
どこにタイムスタンプが記録されているのか、ちょっと調べてみた。
ディレクトリ・エントリ・テーブル領域というところにタイムスタンプが記録されているようだ。
タイムスタンプの他には、ファイル名もここに記録されているようだ。
しかし、私には、タイムスタンプを書込む関数を書ける技量もないし、どうしようかとWEBを検索
したら、目からうろこのサイトを見つけた。
「マイコンな日曜」というサイトで、FAT32についての、いろいろなCHIPSが載っていた。
その中に、
「RTCCの日付時間データを自動的にファイルのタイムスタンプに使うための前処理」という
タイトルの記事があった。
それによると、
「ファイルのタイムスタンプに使う日付け時間のデータをファイルシステムのなかで
リアルタイムクロック(RTCC)から自動的に取得して記録するようにするためには、
FSconfig.h
の次の定義をアクティブにしておくことが必要です。
#define USEREALTIMECLOCK
あとの次の二つはコメント化させて無効化しておきます。
//#define USERDEFINEDCLOCK
//#define INCREMENTTIMESTAMP
USERDEFINEDCLOCKはプログラマがプログラムで何らかの方法で日付け時間データを
取得し(もちろんRTCCから取得してもいい)タイムスタンプの日付け時間データをセットする関数
のSetClockVars()を使って手動で値をセットする場合にアクティブにします。」
ということである。
早速、FSconfig.hの、当該記述を確認してみたら、私のリストでは、
USEREALTIMECLOCK(自動で値をセット)になっていた。
自動ということが、どういう意味なのか解らないが、これを試すべく、RTCCを動かすソフトを追加
してみることにした。
幸い、PIC32MXには内蔵のRTCCが組み込まれているし、トレーニング基板にも基準となる水晶が
外付されているので、ソフトさえ追加すれば直ぐチェックできる。
せっかくなので、HOLD中のみ、年月日と、時分秒を、液晶最上段の1行に表示してみることにした。
時計ソフトは、後閑氏のハンドブックのサンプルを参考にさせて頂いた。
この時、部屋の時計は、深夜0時を回って、日付が変わっていた。
■ 2014.10.22
・ ソフトを追加して試すもまだおかしい。
更新日時が、1991/・・・となったり、何も表示されなかったりする。
ただ、液晶上の時計はちゃんと動いている。
・自動で値をセット:USEREALTIMECLOCKでは、駄目なのかな?
WEB記事にあった、手動セット:USERDEFINEDCLOCKでも試してみることにした。
ただ、手動であるがゆえに、ソフトは面倒になる。
まず、SetClockVars関数なるものが、どんな書式なのかも解らないんでは、ソフトの書きようがない。
解らない時は、とにかくググるのが一番。
_microchip社の、「FAT_LIBアプリケーションマニュアル(01045a)」pdf文書をダウンロードすることが
できた。
その中にこの関数の書式と説明が英文で載っていた。
要は、引数として、RTCCレジスタから読込んだ、時計データを渡して実行すればよいようだ。
まず、そのままRTCCレジスタから読込んだ時計データをそのまま、引数として渡してみたが、
まだ、更新日時表示はおかしい。
よくよく考えてみれば、レジスタから読込んだ値は、時計表示に都合よいように、BCDになっている。
また、年レジスタは、2桁のBCDになっているのに対し、引数としては、4桁分必要だ。
引数としては、バイナリで渡す必要がある。
BCD(バイナリ・コーディッド・デシマル)では駄目である。
つまり、BCDを、バイナリに変換してから渡してやらないといけない。
それと、年だけは、2000を足しこんでやらないといけない。
この変換は最初、こんなの出来るのと思ったが、結局、思ったより、割とシンプルな記述で書けた。
この修正は行うのだが、あと1つ気になっていることがあるのでそれも修正することにした。
それは、最初考えた、液晶への時計表示が、全部で、18文字あり、液晶の1行分の幅ギリギリ
になってしまっているため、うるさい感じがするし、これを表示することによって、Y座標線の頭の部分が
欠けてしまうので見栄えも悪いという点である。
秒まで表示する必要は無いと思い、年月日 時分のみの計15文字表示にした。
そうすれば、画面もすっきりする。
この2点の修正で、なかなかいい具合な表示になった。(自己満足だが・・)
また肝心な、更新日時表示の問題も解決した。
※ 他のサンプルと、エクスプローラでの、BMPファイルの閲覧の模様は、」このページ頭の表紙の
写真を参照してください。
<最終回路図>
・こちらから、どうぞ→ 「PIC32MX_BMP書込み実験回路」
<最終ソース>
・こちらから、どうぞ→ PIC32MX_BMP_WriteTest_1.c
← 実験テーマ1に戻る TOP PAGEに戻る 実験テーマ60へ →