ライン

PIC32MKシリーズによるSPI転送4chを使ったカラーコンポジット信号出力実験

ライン

2017年10月8日
最終更新日 2017年10月9日

 これまでPICマイコンを使用したNTSCカラーコンポジット信号出力実験を数多く行ってきましたが、全てに共通して言えるのは、マイコンのCPUでリアルタイムに汎用I/Oポートへ順次出力するプログラムを走らせることで、カラー映像出力を実現してきたことです。
 これに対して、今回の実験ではマイコンの周辺機能を活用して映像信号を生成します。これまでにも何とかうまく周辺機能を活用して出来ないものかと検討はしてきましたが、残念ながら機能不足で出来ませんでした。しかし、このたび最新のマイコンを利用した、ごんべいさんによる実験を目の当たりにして大きな衝撃を受けたので、私なりに改良して公開することにしました。そのため、私の実験記事というより、ごんべいさんの実験の解説といった内容となります。

実験結果画像
実験に使用したレイトレーシング画像


ハードウェア

 実験に使用したマイコンは、マイクロチップ社の32ビット最新PICマイコン「PIC32MKシリーズ」のPIC32MK1024GPD064です。通常プログラム用フラッシュ1Mバイト+ブート用フラッシュ16Kバイト、SRAM256Kバイトとこれまでのマイコンに比べ大容量のメモリを搭載し、システムクロックは最大120MHzまで対応します。また、DMA(Direct Memory Access)機能を8チャンネル、SPI通信機能を6チャンネル搭載しており、今回はこの2つの機能をうまく活用します。
 PIC32MKシリーズは位置付け的にはこれまでのPIC32MXシリーズと、上位のPIC32MZシリーズの中間に当たります。機能面ではPIC32MXシリーズから引き継いだ機能と、PIC32MZシリーズから引き継いだ機能があるようです。価格についてはマイクロチップ社のDirect販売で1つ6.73ドルと、やはり中間的な価格で購入しました。
 今回の実験は右図の回路で行いました。クロック源には色副搬送波の周波数(Fsc、3.579545MHz)の4倍の水晶発振子から、マイコン内部のPLL回路でFsc×32倍の約115MHzを生成してシステムクロックとしています。SPIの転送レートはこの2分の1になります。
 使用したSPIの4チャンネルはSPI3〜SPI6です。周辺ピン選択(PPS)機能でPORTBの12〜15に割り当てています。そのほかはPIC32MKを使用する上での最低限の回路となっています。
 実験は写真のように0.5ミリピッチ64ピンQFPのマイコンを自作のDIP変換基板にハンダ付けし、ブレッドボード上で行いましたが、PIC32MX等に比べるとクロック周りがシビアになっているように感じました。各電源ピンにつないでいるパスコンを外すと動作しなくなるなどしますので、注意が必要です。

実験写真
実験写真

回路図
回路図(クリックで拡大)

出力ポートと使用SPI、DMAチャンネルの割り当て
ビット番号出力ポートSPIチャンネルDMAチャンネル
3(MSB)RB13SPI6DMA ch4
2RB15SPI5DMA ch3
1RB14SPI4DMA ch2
0(LSB)RB12SPI3DMA ch1


仕組みの解説

 これまでにもSPI転送機能を利用したビデオ信号出力実験はありましたが、それらはモノクロ2値出力のみの対応でした。ごんべいさんによる実験では、下図のように複数チャンネルのSPIのシリアル出力を同時に使い、抵抗ネットワークで構成されたDAコンバーターに出力することでアナログ波形を生成しています。図ではSPI×3チャンネルとなっていますが、実際には4チャンネルを使って4ビットDAコンバーターとしました。
 正常なビデオ信号出力を実現するために、以下を満たす必要があります。
  (1)SPI各チャンネルの頭だしをぴったり揃える
  (2)SPI信号出力を途切れずに出し続ける

SPIによる信号生成
解説図。実際にはDMA、SPIを4チャンネル使用

頭だしを揃える

 SPIは8ビットモードを使用しました。PIC32のSPIには拡張バッファと呼ばれる16バイト分のFIFOバッファがあり、バッファが空になるまで連続して出力します。通常であれば、バッファにデータが入ったところからすぐにシリアル出力が開始されるため、複数のSPI出力の頭だしを揃えるには工夫が必要です。
 PIC32MKではSPIモジュールのクロック源としてREFCLKO1と呼ばれる複数のクロックソースから出力クロックを選択できるモジュールを指定することができます。今回はシステムクロックからREFCLKO1を通してSPIモジュールにクロック供給することとしました。REFCLKO1はクロック出力を停止することができるため、クロックの供給を停止した状態で各SPIモジュールのFIFOバッファに十分にデータを貯めてから、一斉に共通のクロックを供給開始することで、全チャンネルの頭だしを揃えることができました。

途切れずに出し続ける

 上述のように各チャンネルには16バイトのバッファがあります。このバッファが空になるとSPIの転送が途切れることになるため、バッファには常にデータを貯め続ける必要があります。バッファが空になったことを知らせる割り込みで処理していては間に合わないため、各チャンネルに対して1つずつDMAのチャンネルを割り当て、バッファが空になる前にDMA転送用データ領域からSPIのバッファにDMA転送を行います。転送サイズは1回12バイトにしました。DMAのトリガーは12バイト(96ビット)分の出力時間から計算したタイマー割り込みとしています。
 DMAで転送をし続けるために、DMA転送元となるバッファに映像信号データを貯めておく必要があります。このバッファのサイズは映像信号の水平2ライン分としました。1ライン分のDMA転送が終了すると、割り込みが発生し、空いた領域に画像データから変換した波形データを各チャンネル分貯めていきます。この作業はCPUで行っています。


信号のタイミング

 NTSCカラーコンポジット信号の詳細については、これまでの記事(ここが詳しい)を参照ください。今回の実験ではシステムクロックを色副搬送波の32倍としました。SPIの転送レートはその半分としたので、SPI出力16ビットが色副搬送波の1周期、逆に言えば1周期を16分割となります。過去のPIC32MX等のCPUのソフトウェアで実現していたときはせいぜい4分割だったので、これまでに比べ波形の改善が期待できます。
 1ドットは色副搬送波の半波長、SPI出力8ビット分としました。1画素は正方形にならずやや縦長のドットとなってしまいますが、正方画素化は今後の課題とします。画面の水平1ラインのタイミングは以下の図のようになります。

1周期を16分割
1周期で2ドット出力

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


カラーテーブル

 1ドット分の信号出力には4ビットデータを8回の計32ビット(4バイト)の波形データが必要となります。各色ごとに波形データをあらかじめ計算してカラーテーブルとして保存しておく必要があるため、対応する色数によって、カラーテーブルの大きさは膨大となります。今回の実験では10ビット色(1024色)としました。波形データは右図のように偶数ドットと奇数ドットで波形が異なるため、2パターン必要となり、カラーテーブルに必要なメモリは4バイト×2パターン×1024色=8Kバイトとなります。カラーテーブルはプログラム上でパレットとして書き換えられるようRAM上に配置しました。もっと色数を増やすこともできますが、RAMの空き容量が圧迫されるため、今回は10ビット色までとしました。
 画像データ用メモリ(ビデオメモリ、VRAM)は1ドット10ビットですが、きりのよいように16ビットで1色としています。そのため、もったいないですが6ビットは未使用です。VRAM上に10ビットのパレット番号をリニアに格納し、パレット番号から波形に変換したものをDMA用バッファに貯めていくことになります。
 画面解像度は表示サイズの関係から横320ドット、縦216ドットとしました。必要な容量は135Kバイトとなります。

1色の波形を8バイトに変換
1色の波形を8バイトに変換


ソフトウェア

 今回実験用に使用したプログラムは大きく分けると以下の3つの部分で構成されています。

アプリケーション

 main()関数を含む映像出力デモ用のアプリケーションです。過去の実験で作ったデモンストレーションを今回も使用しました。また3Dグラフィックの一手法であるレイトレーシングも実行します。

SPIによるコンポジット出力使用開始

 init_composite()関数を呼び出すことで、映像出力システムを初期化し、映像出力を開始します。

信号データ生成(DMA割り込み処理ルーチン)

 SPIモジュールに連続出力するためのDMAバッファは水平2ライン分の大きさとなっています。1つ上のラインの信号をDMAとSPIで出力している間に、次回出力するライン用の信号データを生成させます。そのため、1ライン分の出力完了ごとにDMAの割り込みを発生させています。
 垂直同期期間や映像外の期間は単純な信号で呼び出す回数も少ないのでC言語で作りましたが、映像部分の信号生成は全体を占める時間が長く、作り方次第でシステム全体のパフォーマンスが大きく変わるため、インラインアセンブラーで記述しました。


実験結果

 ごんべいさんの実験結果から複数SPI出力によるコンポジット信号生成が可能であること自体は分かっていましたが、本当にSPIのタイミングをぴったり揃えたまま、途切れることなく連続出力し続けることが出来るのか疑問でした。しかし、実験してみると見事に映像信号を出力し続けられることがわかりました。
 これまで私が実験してきたソフトウェアによる出力実験は5ビットのDAコンバーターで行ってきましたが、今回はデータ作成のしやすさから4ビットに減らしています。その代わり出力のサンプリング回数がこれまでの倍以上と細かくなっています。どちらがよいかというと、まだよく検証できていません。4ビットしかないため、黒レベルと白レベルの出力として使用できる値が限られ、その他の色の出力波形計算にも制限が出ています。そのため、現在のところこれまでより、少し暗い映像出力となってしまっていますが、波形の計算にまだ改良の余地があると考えています。
 (2017.10.9) バースト信号の波形修正を行い、色の再現が少し改善しました。

実験画像
いつものデモ画像。正方画素ではないので真円にはなりません

実験画像
レイトレーシングは数値演算コプロ搭載により10数秒で描画


パフォーマンスについて

 以前のソフトウェアによるビデオ信号生成実験では映像期間中はCPUのリソースが100%信号生成に費やされ、全体としてはCPUのリソースの約3割しか空きがありませんでした。今回の実験では、およそ5割程度のCPU時間の空きが得られています。
 PIC32MKシリーズでは、フラッシュメモリ内の命令読み出しはシステムクロックに対して時間がかかるため、プリフェッチ機能とキャッシュ機能がありますが、私が実験に使用したPIC32MKの初期リビジョン(A1)ではプリフェッチ機能に問題があり、無効化しています。リビジョンA2では修正されているようですが、私はまだ入手できていません。プリフェッチ機能を有効化することによる性能アップが楽しみです。
 ほかにも、PIC32MKではRAM領域が2つのバンクに分けてバス接続されており、DMAバッファとその他の部分を分けることで、CPUとDMAの同時アクセスによるバスの調停回数が減り、性能が向上する場合があります。
 さらに、SPIの使用チャンネル数を減らし3ビットDAコンバーターにする、出力サンプリングのタイミングを半分程度に減らすなどすると、色再現の精度は下がりますが、大幅なパフォーマンスの向上が期待できます。


ダウンロード

 今回の実験で作成したシステム、サンプルプログラムのソースファイルとHEXファイルを公開します。実験に使用した環境はMPLAB X IDE v4.00とXC32 Compiler v1.42です。ソースプログラムをコンパイルする場合、文字コードはUTF-8を、最適化オプションはO1を指定してください。

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

 (2017.10.9) バースト信号の波形修正を行い、色の再現が少し改善しました。ソースファイルおよびHEXファイルに適用済みです。


最後に

 DMAとSPIを使ったカラーコンポジット信号出力は十分に実用的なことが分かりました。今後も改良していきたいと思います。
 PIC32MKシリーズはまだリリースされて間もないため、資料やサンプルが少なく、開発環境についてもまだ整備途中となっているようです。そのため、仕様を想定しながら実験を進めることもあったりしましたが、機能が豊富で性能は高く、コストパフォーマンスもよいと感じます。今後チップの入手性が上がり、使用サンプルも増えてくれば、よりよい使い道が出てくるものと思います。

 何かご不明点やご意見などありましたら、お気軽にこちらの掲示板に書き込みをお願いします。

Copyright (C) KenKen All Rights Reserved.