● 実験テーマ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へ →