マイコンからメモリ空間を通じてVFDパネルをコントロールするハードはできたので、今度はソフトを作成したいと思います。
/* VFDのMCU外部バス空間におけるベースアドレス定義 */ #define VFD_ADDRESS_BASE 0x200000 /* VFDレジスタ/データライト */ static void vfddd_write(unsigned char address,unsigned char data){ *((unsigned char*)VFD_ADDRESS_BASE + 1) = address; NOP_2US; *((unsigned char*)VFD_ADDRESS_BASE) = data; NOP_2US; } /* VFDデータリード */ static unsigned char vfddd_read(unsigned char address){ unsigned char val; *((unsigned char*)VFD_ADDRESS_BASE + 1) = address; NOP_2US; val = *((unsigned char*)VFD_ADDRESS_BASE); NOP_2US; return (val); }
なお、上記ソース内の「NOP_2US」は、コマンド指定後に2マイクロ秒のウェイトがいるそうでしたので、インラインアセンブリで2マイクロ秒分のNOPを挿入したマクロです。
データのリード・ライト後には必要ないはずですが残ってしまっています^^;
このタイプのVFDパネルは2画面表示機能があり、任意で、それぞれの画面をテキスト、またはグラフィック画面に設定する事が出来ます。
テキスト画面として設定すると、7ドット×5ドット構成のANKが表示可能です。
ここでは、1面目をビットマップ、2面目をテキストに設定して、1面目のバッファ開始アドレスを0x0000、2面目のバッファ開始アドレスを0x0800に設定する事にします。
/* VFDパネル・仮想VRAMの初期化 [input] none [output] none */ void vfd_init(void){ vfddd_write(VFDCMD_SCREEN_1_2_ON,0x00); // ページ1を表示する vfddd_write(VFDCMD_SCREEN_1_2_OR,0x00); // ページ1と2をOR表示する vfddd_write(VFDCMD_BRIGHTNESS_100,0x00); // 輝度 100% vfddd_write(VFDCMD_SCREEN2_CHAR,0x00); // SCREEN2はテキスト表示にする vfddd_write(VFDCMD_CURSOR_AUTOINC,0x00); vfddd_write(VFDCMD_DISP_1_STARTADDR_LOW,0x00); vfddd_write(VFDCMD_DISP_1_STARTADDR_HIGH,0x00); vfddd_write(VFDCMD_DISP_2_STARTADDR_LOW,0x00); vfddd_write(VFDCMD_DISP_2_STARTADDR_HIGH,0x08); // テキスト面、グラフィック面共に初期化 vfd_clear(3); } /* VFD GVRAM/TVRAMクリア [input] int type : 1 : SCREEN 1(Graphic) 2 : SCREEN 2(TEXT) 3 : SCREEN 1 and 2 [output] none */ void vfd_clear(int type){ int i; if (type & 0x01){ vfddd_write(VFDCMD_CURSOR_ADDR_LOW,0x00); vfddd_write(VFDCMD_CURSOR_ADDR_HIGH,0x00); for (i=0;i<=0x7ff;i++){ vfddd_write(VFDCMD_DISPDATA_WRITE,0x00); } } if (type & 0x02){ vfddd_write(VFDCMD_CURSOR_ADDR_LOW,0x00); vfddd_write(VFDCMD_CURSOR_ADDR_HIGH,0x0a); for (i=0;i<=0x1ff;i++){ vfddd_write(VFDCMD_DISPDATA_WRITE,0x20); } } }
vfd_clear()関数は、引数でテキスト/グラフィック/テキスト+グラフィックのクリアを選択できます。
昔やってたPC-9801のN88-BASIC(86)のCLSコマンドを思い出しながら実装しました^^;;(懐かしい...)
テキスト面への表示は以下のように実装しました。
表示位置を指定できます。
/* VFD(TVRAM)に文字列(ANK)を一行表示 line : 0 - 3 */ void vfd_txs(int line,int column,char* str){ unsigned short startaddr; startaddr = 0x800 + 0x200 + line * 0x80 + column; vfddd_write(VFDCMD_CURSOR_ADDR_LOW,startaddr & 0xff); vfddd_write(VFDCMD_CURSOR_ADDR_HIGH,startaddr >> 8); while (*str){ vfddd_write(VFDCMD_DISPDATA_WRITE,*(str++)); } }
ドロー系の関数を作成しないとせっかくのドットマトリクスVFDを活かせないので、ドロー系の処理を作成し、ドロー系処理は仮想VRAMに描画するようにします。そして、この仮想VRAMから実際のVFDの表示にコピーする処理を作成します。
以下の処理で、「gtf_vvram」という構造体が仮想VRAMで、後述するドローライブラリ「gtk」が確保しています。
/* 仮想VRAMからVFDへのデータコピー [input] none [output] none */ void vfd_refresh(void){ int i; vfddd_write(VFDCMD_CURSOR_ADDR_LOW,0x00); vfddd_write(VFDCMD_CURSOR_ADDR_HIGH,0x00); for (i=0;i<=0x7ff;i++){ vfddd_write(VFDCMD_DISPDATA_WRITE,gtk_vvram.vbuf[i]); } }