ライン

大容量メモリ搭載PIC32MXシリーズによる高解像度ビデオ信号出力実験

ライン

2014年1月3日

 解像度が高く、色数も多いグラフィック出力を実現するには、大容量のメモリを必要とします。以前、SRAMを外付けして240×224ドット、15ビット色出力の実験を行いました。画質については満足したのですが、やはり外付けのSRAMを使うとなると製作が大変で、またPICからのアクセスも面倒なため、手軽に使えるというものではありませんでした。
 PICで内蔵SRAM容量がもっと大きいものはないかと調べたところ、新シリーズのPIC32MZは別にして、PIC32MXの場合、最大容量は128Kバイトのようです。そこで128KバイトのSRAMを搭載したPICの1つであるPIC32MX695F512Hを入手し、どの程度使えるか実験してみました。

実験結果画像

実験回路

 今回の実験には64ピンTQFPタイプのPIC32MX695F512Hを使用しました。これまでのビデオ出力実験と同様にシステムクロックには3.579545MHzの水晶を使用します。ビデオ信号出力はPORT EのRE0〜RE4に抵抗でDAコンバーターを形成して行いました。使用した抵抗は外付けSRAMの時と同じで200Ω〜3.9KΩです。このくらいの抵抗値でDAコンバーター構成すると、5ビットをフルに使ってビデオ信号を生成することができます。
 回路図にあるように、今回はSDカードを使い、画像ファイルを読み込んでテレビに表示する実験も行いました。SDカードへのアクセスにはSPI通信を使用します。CS(Chip Select)にはRF3ポートを接続しました。また、一般的にWE(Write Enable)、CD(Card Detect)で書込み禁止やカード検出を行うのですが、この機能に対応したカードスロットを持っていないので省略しています。ただし、使用したMicrochip社製のライブラリがこの機能を実装しているため、RF1とRF0を割り当てグランドに接続することで、常時「書き込み許可」、「カード検出あり」としています。これらの機能に対応したスロットを使用する場合は、RF1、RF0を接続してください。
 PIC32MX695F512HにはUSBはもちろん、Ethernetインターフェイスや高速ADコンバーターなど豊富な機能が搭載されていますが、今回の実験では使用しておらず、単なるSRAM容量が大きく高速なマイコンという扱いとなっていて、ちょっともったいないです。

回路図

ハードウェア製作

 今回の実験はブレッドボード上で行いました。0.5mmピッチの64ピンTQFPから2.54mmピッチへの変換基板を使用しました。一般的には変換基板にピンヘッダーをハンダ付けするようですが、それだとブレッドボードでそのまま使えないので、私はいつもピンソケットをハンダ付けして、ワイヤを使ってブレッドボード上の回路と接続しています。
 SDカードスロットは、マイクロSDカードを購入したときによく付属されている、変換アダプタで代用しました。SDカードはピンのピッチがちょうど2.54mmのため、ピンヘッダーをハンダ付けすると、そのままブレッドボードに挿すことができます。市販のSDカードスロットはそのままではブレッドボードやユニバーサル基板で使用することができず、またこの変換アダプタはマイクロSDカードを購入するたびに付いて来て手元に余っているので、このやり方はいつも重宝しています。ただし、前述のように書込み禁止やカード検出機能を使うことができません。

製作写真

マイクロSDカードスロット

システム設計

 マイコンを用いたカラーコンポジット信号生成の詳細については、以前実験したこちらをご参照ください。
 PIC32MX695F512Hは128KバイトのSRAMを搭載し、最大80MHz(=80MIPS)で動作させることが可能な高性能マイコンです。これにあった解像度と色数の検討を行います。
 アナログテレビのライン数から縦は225ドットとします。画素をほぼ正方形とするには横の長さをカラーサブキャリア周波数の5分の3とするとよいようです。このときの横方向のドット数は、テレビにもよりますが、300ドット程度まで表示可能なようです。
 次に色数です。1ドットに1バイトを割り当てると300×225=約66Kバイトとなります。SRAM容量は128Kバイトありますからまだ余裕がありますが、倍にすることもできないので、これで決定とします。1ドット1バイトということで、同時に表現できる色数は256色となります。
 システムクロックは80MHzを上回らないよう、カラーサブキャリアの約3.58MHzを内部で20倍した約71.6MHzとします。規格上22倍までは対応可能ですが、半端なため使いにくそうです。(また内部22倍という設定は実際のところありません。)20倍の場合は、1ドットに対して12命令かけることができます。1ドット当たり3回の信号出力を行うとすると、カラーサブキャリア1周期を5分割した72度単位の信号データが必要となります。

波形

 ビデオメモリの構成は非常にシンプルです。1ドット当たり1バイトですから、全ドット数分の大きさのunsigned charの配列を用意し、その座標に応じた場所にパレット番号の書き込みを行うことで、パレットで指定した色のドットを表示することができます。
 ところで、解像度300×225ドットの縦横比はちょうど4:3で、VGAやXGAなどと同じです。一般的なデジカメも4:3となっているので、デジカメで撮った写真の縦横比を変更したり、切り取ったりすることなく、画面いっぱいに出力することも可能です。

ビデオメモリ構成

映像信号タイミング

 今回はシステムクロックをカラーサブキャリア周波数の20倍としたので、各信号のタイミングは下図のようになります。

水平1ラインのタイミング


プログラム製作

 これまでPIC32MXシリーズで何度もカラーコンポジット信号を生成するプログラムを作成してきましたので、大まかにはこれまで同様になっています。
 しかし、これまで使ったPIC32MXシリーズは少ピンの1xx/2xx番台で、今回初めてPIC32MXシリーズ本来の性能を発揮するものを使うことになりました。少ピンPIC32との大きな違いは、システムクロック80MHz、つまり80MIPSへの対応と、そのためのキャッシュ機能にあります。PICのプログラムは通常内蔵フラッシュメモリに書き込まれたものを実行しますが、フラッシュのアクセス速度は遅く、クロックが上がるとウェイトが必要となり、思い通りの実行速度が出せなくなります。それを克服するために、フラッシュからコードを先読みして一時的に蓄え、順次実行させるプリフェッチキャッシュ機能が搭載されています。しかし、このキャッシュ機能は完璧ではありません。プログラムのジャンプや分岐があると、新たにキャッシュへの読み込みを行うため、ウェイトが発生します。
 カラーコンポジット信号をプログラムで生成する場合、実行が1クロックでもずれると正しい色が出なくなります。同期信号や映像信号の生成はタイマー割り込みでタイミングを図りますが、そのとき実行中の命令やアイドル状態などにより、割り込み発生から最初の命令実行までのタイミングにばらつきが発生します。そこで、これまでの映像出力実験では割り込み発生後にタイマー値を読み込み、ばらつきを補正するプログラムを組み込んでいました。このときジャンプ命令を使用していたのですが、今回はおそらくこのジャンプ命令実行時に発生するウェイトの影響で、どうしても1クロック程度のばらつきを補正することができず、応用プログラムやコンパイルの条件を変更すると、色のずれが発生することがありました。
 色のずれは、カラーバースト信号の位相のタイミングと映像信号のタイミングのずれにより発生します。そのため、今回はカラーバースト信号生成から映像信号の終了まで、一切ジャンプや分岐命令を使用しないことにしました。命令をリニアに実行している限りは、ウェイトによるばらつきが発生することはありません。その代わり、無駄なNOP(No Operation)命令をひたすら実行したり、ループで済ませられるところを全て展開させたりすることになりますが、幸いプログラムフラッシュ領域は512Kバイトと巨大なので、あまり気にはなりません。

  PIC32MXのキャッシュ機能については、後閑哲也氏のサイトのここに解説があります。


ダウンロード

 コンポジット信号出力システムとサンプルプログラムのソースを公開します。下記よりダウンロードしてください。私の開発環境は、MPLAB IDE Ver 8.80です。コンパイルに際して、最適化オプションは特に指定してもしなくても、問題なく動作しています。

ソースプログラムのダウンロード


グラフィックライブラリ

 今回、グラフィック関連の簡単なライブラリを作成しました。以下の関数を用意しています。ソースはgraphlib.cで、graphlib.hにて関数の宣言等を行っていますのでincludeして利用してください。実際の利用方法はサンプル1を参考にしてください。

  void pset(int x,int y,unsigned char c)
    座標(x,y)にカラーcで点を描画

  void line(int x1,int y1,int x2,int y2,unsigned int c)
    座標(x1,y1)から(x2,y2)にカラーcの線分を描画

  void circle(int x0,int y0,unsigned int r,unsigned int c)
    座標(x0,y0)に半径rの円をカラーcで描画

  void putfont(int x,int y,unsigned int c,unsigned char n)
    座標(x,y)にカラーcで文字コードnのフォントを描画

  void printstr(int x,int y,unsigned int c,unsigned char *s)
    座標(x,y)にカラーcで文字列sを描画

  void printnum(int x,int y,unsigned char c,unsigned int n)
    座標(x,y)にカラーcで数値nを10桁の10進数で描画

  void putbmpmn(int x,int y,char m,char n,const unsigned char bmp[])
    座標(x,y)に横m×縦nの定数配列bmpに保存された画像を描画
    配列の中身はカラー番号、ただし0は透明色

  void clrbmpmn(int x,int y,char m,char n)
    座標(x,y)の横m×縦nドットの画像を消去(カラー0で塗りつぶし)

line()関数およびcircle()関数の作成にはFussyさんのアルゴリズムのコーナーを参考にしました。また、putfont()等で使用している文字フォントは古いPCから抽出したものです。
 上記ライブラリではなく、カラー出力システム本体側で提供している関数は以下の通りです。

  void init_composite(void)
    システムを初期化し、映像信号出力開始
    カラーパレットは、0〜7を通常の8色、8〜15は0〜7の明るさを半分にしたもの、残りは真っ白に設定されます。

  void stop_composite(void)
    映像信号出力停止

  void start_composite(void)
    映像信号出力開始(再開)

  void clearscreen(void)
    画面クリア(カラー番号0で塗りつぶす)

  void set_palette(unsigned char n,unsigned char b,unsigned char r,unsigned char g)
    カラーパレット設定。カラー番号nの青、赤、緑の強さを0〜255で設定


サンプルプログラムと実験結果

 実験用にサンプルプログラムを3点作成しました。

サンプル1

 いつものサンプルプログラムです。ライブラリの基本的な使用方法の参考にしてください。
<プロジェクトに追加するファイル>
 composite32mx695_demo1.c (mainプログラム)
 composite32mx695.c (システム本体)
 composite32mx695.h
 graphlib.c (グラフィックライブラリ)
 graphlib.h

サンプル写真1

サンプル2

 外付けSRAM利用のシステムでも紹介したレイトレーシングプログラムです。
<プロジェクトに追加するファイル>
 composite32mx695_demo2.c (mainプログラム)
 composite32mx695.c (システム本体)
 composite32mx695.h
 graphlib.c (グラフィックライブラリ)
 graphlib.h

サンプル写真2

サンプル3

 SDカードに保存の画像ファイルを順次表示します。画像形式は300×225ドット、Windowsのフルカラーbmp形式で保存されたファイルです。細かいエラーチェックは行っていないので、参考程度に見てください。
 SDカードの読み取りには、Microchip社が提供しているライブラリを利用しました。複数のファイルに分かれていて分かりにくいですが、全部必要ですので、あまり深く考えずにプロジェクトに追加してコンパイルしてください。
 フルカラーのbmpファイルから赤3ビット、緑3ビット、青2ビットに減色して表示しています。その際、乱数で簡易的なディザをかけています。
<プロジェクトに追加するファイル>
 composite32mx695_demo3.c (mainプログラム)
 composite32mx695.c (システム本体)
 composite32mx695.h
 graphlib.c (グラフィックライブラリ)
 graphlib.h
(以下はSDカード関連)
 Compiler.h
 FSconfig.h
 FSDefs.h
 FSIO.c
 FSIO.h
 GenericTypeDefs.h
 HardwareProfile.h (ポートの指定等はここで行う)
 SD-SPI.c
 SD-SPI.h

サンプル写真3

サンプル写真4

最後に

 PICワンチップだけでどこまで表現できるかのチャレンジのつもりで実験してみました。以前作成した外付けSRAMによる15ビット色対応に比べると表現力は劣りますが、ここまでできたのは予想外でした。PIC32MX695F512Hは1000円程度ですが、今のところ国内の店舗では販売されていないようで、ネット通販だと送料も必要となるため、あまり気軽に使えるチップではありません。できれば、機能はそれほど豊富でなくてもよいので、SRAMとフラッシュの容量だけが巨大で、DIPタイプの高速PIC32シリーズが低価格で出てくることを望みます。(あり得ないか。)

 と、ここまで書いてから調べてみたところ、DIPではないですが、128KバイトのSRAM搭載で、Ethernet等はない代わりに、最大100MHz(=100MIPS)に対応したチップが最近出ていることに気付きました。例えばPIC32MX370F512H。PIC32MX695F512Hよりだいたい250円くらい安そうです。次はこれを使ってみますか。でも100MHz対応といっても、外部クロックの24倍までしか設定できないので、実際には3.58×24=86MHzで使うことになります。せめて25倍ができれば、今回と同じカラーサブキャリアの5分の3周期で1ドットが作れるのですが。8分の5周期だとちょっと横長のドットになりそう。。。
 → PIC32MX370F512Hで同様の実験を行った記事をこちらに掲載しました。クロックはより巧妙な手を使いました。(2015年3月28日)

Copyright (C) KenKen All Rights Reserved.