H8でVFDパネルをコントロールするデバイスドライバを作成する

マイコンからメモリ空間を通じてVFDパネルをコントロールするハードはできたので、今度はソフトを作成したいと思います。

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初期化処理と、画面消去処理を作成する

このタイプの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コマンドを思い出しながら実装しました^^;;(懐かしい...)

テキスト面へのANK表示

テキスト面への表示は以下のように実装しました。
表示位置を指定できます。

/*
  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++));
    }
}

ビットマップ描画仮想VRAMからVFDへのコピー処理を作成する

ドロー系の関数を作成しないとせっかくのドットマトリクス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]);
    }
}

ソースコード


VFDドライバソースコード




Author: projectc3@gmail.com
Last modified: Sun Aug 07 22:56:04 JST 2005