1.はじめに
約9年前(2013.11.3)にMZ-80エミュレータを製作しました。 この時は、ブラウン管式のアナログTVに映し出せるようにNTSC信号で映像を出力しました。 現在では、アナログ放送も終了しブラウン管TVも無くなってしまいました。そこで、パソコンのディスプレーに映し出せるように、VGA(640x480ドット)で映像出力するエミュレータを製作してみました。 前回はランニングエレクトロニクスで販売されている'SBDBT32'マイコン基板を使いましたが、マイコンのピン割り当ての都合で、'REPIC32SD'という別の基板を使いました。こちらの基板は、 簡易ドライブレコーダの製作で一度使ったことがあります。
2.使い方 前回製作したエミュレータと同様、SDカードにエミュレータの動作に必要なモニターROMやCGーROMのファイルを格納しておきます。 エミュレータとディスプレーをDサブミニ15ピンのVGAケーブルで接続します。USBコネクタにUSBキーボードを差し込み、+5VのACアダプタをVGAコネクタの横にある電源ジャックに接続します。 本体が正常に動作すると、ディスプレーに、モニターの起動開始画面が表示されます。左右上下の表示位置がずれている場合にはディスプレー側で調整を行います。 これ以降の操作については、前回製作のエミュレータと同じです。詳細は、前回の製作記事を参考にしてください。
3.製 作 3−1 回路 回路は右の通りです。'REPIC32SD'基板の回路そのものではなくそれと等価な回路で描いています。 基板は異なるもののマイコンチップは前回と同じ'PIC32MX695H512H'です。回路やピン割り当てはほとんど前と同じです。PICのファームウエアも映像出力を除いて前の物をそのまま流用しています。 NTSCの出力では、水平同期信号と垂直同期信号は複合されているので1ピンの割り当てで済みましたが、VGAの出力では、水平同期信号と垂直同期信号は分離されているので2ピンの割り当てが必要となりました。 ビデオの映像信号については、VGAでは、本来、RED(赤),GREEN(緑),BLUE(青)の3色を必要とするのですが、MZ-80ではモノクロ表示ですので、RGBのG(緑)だけ出力することにします。これにより、映像信号の出力処理は、VGAにおいてもNTSCの時と同じ考えで製作出来ます。 ファームウエアは、MPLAB IDE で c32 Cコンパイラーで作成しました。プロジェクトファイル一式はこちらです。 3−2 VGA信号の生成 VGAの信号は次のように作成しました。タイマー2(T2)と出力比較モジュール1(OC1)を使って同期信号を生成、映像信号は SPI3 で出力しました。 タイマー2のクロックを40MHzに設定します。水平同期信号は、31.469KHz ですので、その周期は、40MHzクロックで換算すると1271クロック(40MHz/31.469KHz=1271)となります。 水平同期パルスのパルス幅は4μsec ですので クロック換算で160クロックです。タイマー2と出力比較モジュール1(OC1)の設定を次のように行って、その出力ピン RD0 から水平同期信号を出力しました。 // timing parameter #define H_LINE_CPS 1271 // 40MHz/31.469KHz=1271 // 40MHz/1271=31.471KHz // (1/40MHz)*1271=31.775usec #define H_SYNC_CPS 160 // (1/40MHz)*160=4usec // set Timer2 T2CON = 0x0010; // prescale 1:2 40MHz TMR2 = 0; PR2 = H_LINE_CPS-1; // set OC1(RD0) for Horizontal sync signal OC1CON = 0; OC1R = H_SYNC_CPS; OC1RS = PR2; OC1CONbits.OCM = 0b101; // continues pulse 次に垂直同期信号ですが、こちらはタイマー2の割込み処理で、出力ピン RD10 をトグルすることで生成しました。水平走査1回毎に割込みが発生しますので水平走査線数 525 本毎に垂直同期信号を作ります。 具体的には フロントポーチ区間、垂直同期パルス区間、バックポーチ区間、映像表示区間、の4区間(ステート)に分割して、VGA信号全体の生成を行っています。 映像表示区間においては、OC2Rをクロックカウンターとして動かし、OC2Rの割込み処理の中でSPI3の送信割込みを許可し、映像信号を出力するようにしています。、 // 垂直同期ステートにより分岐 switch(VState){ case ST_V_BP: // バックポーチ区間 case ST_V_FP: // フロントポーチ区間 V_SYNC_OUT = 1; break; case ST_V_SYNC: // 垂直同期パルス区間 V_SYNC_OUT = 0; break; case ST_V_SIGNAL: // 映像表示区間 if(v_gate){ OC2R = H_SYNC_CPS; // + H_BP_CPS; // 映像開始までの遅延(SPI3の送信開始遅延を考慮) OC2CON = 0x8001; // ワンショット L->H } if((Line & 0xF) == 0){ Lptr = VPtr; // saved begin address of line LrvsPtr = VrvsPtr; }else{ VPtr = Lptr; // restore begin address of line VrvsPtr = LrvsPtr; } cgrom=cgROM[((Line++)>>1)&0x7]; // set read line break; } 解像度についてです。VGAは 640x480ドットですが、MZ-80は、320x200ドットです。640ドット表示の映像信号のクロック周波数は25.175MHzですが、この約半分の13.333MHzのクロックでSPI3を動かし、320ドット表示にしています。、 縦は水平走査2ラインで文字の縦1ドットを表示するようにしました。これで縦25行の文字表示に水平走査 400ラインを使います。残りの80ラインは、フロントポーチ、バックポーチに含めました。 詳細は、ソースコードvideo_vga.cを参照ください。 VGA出力の確認は、ディスプレーの調整画面にて確認しました。その時の様子が下の写真です。
3−3 VGA表示例 実際にVGAで表示したのが下記の写真となります。
MZ-80のカセットテープ読み出しのエミュレートではSDカードに格納されているファイル一覧をメニュー表示するのですが、前回の製作ではメニューの枠の表示がずれる不具合がありましたが今回は修正しています。 |