ビデオディスプレイコントローラ3の使い方について(SH7262)

 はじめまして。るーでるという者です。

 

質問についてなのですが、表題の通りSH7262内臓のVDC3の使い方についてです。

動きのある絵を表示させる場合の画面書き換えタイミングで悩んでおります。

具体的には下記の通りです。

 

現状では解像度分のVRAM(私の環境では320*240のLCDを使っています)を2面用意しダブルバッファにします。

わかりやすくする為、バッファのVRAM領域をA面B面とすると、

A面←表示中

B面←次に表示させる絵を準備

次の画面の準備ができたらA面とB面のアドレスをVSYNCを待って入れ替える。

ここまではレジスタの操作で問題ないのですが、プログラム側がLCDにB面が反映されたかどうかをプログラムが検出できないので、VSYNCを待たずしてA面の書き換えを行ってしまう。

現状での解決方法として下記を考えました。

1:タイマー割込みを利用して1フレーム+αの時間で割込みを掛け、画面の反映を検出する。

2:VSYNCの信号をPINTに取り込んで割込みを掛け、画面の反映を検出する。

方法1だとフレームレートを上げるのがむつかしいでしょうし、方法2では現状で出来上がっているハードを手直ししないといけない。

 

皆さんはどのように制御されていますか?

ご教授の程、よろしくお願いいたします。

  • わわいです
    VSync のタイミングで割り込みはかけれないんでしょうか?
    SH7269だとライン割り込みとかありましたが
  • 回答ありがとうございます。
    SH7262では、VDC3の割り込みは、
    1.VSYNC 周期乱れ検出(VIVSYNCJ)
    2.バッファエラー (VBUFERR)
    3.フィールド書き込み完了 (VIFIELDE)
    4.ライン割り込み (VOLINE)
    の4つあるようです。
    VIFIELDEとVOLINEが使えそうだなと思い、調べてみると、VIFIELDEはモードが録画の時に利用できる物、VOLINEはVIDEOもーどについてはかかれていなかったですが、下記のように設定しても割り込みが掛からなかったです。
    ・割り込みの設定
    VDC3.SGINTCNT.BIT.INT_LINE_NUM = 0; 又はVDC3.SGINTCNT.BIT.INT_LINE_NUM = 239;
    VDC3.SGINTCNT.BIT.INT_LINE_EN = 1;
    INTC.IPR10.BIT._VDC3 = 0x7;

    ・intprogc.cのベクタ174を下記のように変更
    // 174 VDC VOLINE
    void INT_VDC_VOLINE(void) { int_vdc_voline(); }

    ・int_vdc_voline();の実体
    void int_vdc_voline(void)
    {
      画面全体を白で塗りつぶす処理
    }
    一度でも割り込みが発生すると画面が白になるよう組んでいるのですが、どうも割り込みが発生しないようです。
    ※「画面全体を白で塗りつぶす処理」は正しく動作することを確認しております。
    もしかして割り込みの使い方が間違っているのでしょうか?
  • わわいです
    ライン割り込みあるぢゃん。
    それでVsyncのタイミングだろーと表示期間終了のタイミングだろーと自由に割り込みがかけれます。
    割り込みルーチンでどっかのポートをON/OFFさせてオシロででも見てみましょう

    ※「画面全体を白で塗りつぶす処理」は正しく動作することを確認しております。
    おおかた塗りつぶしたあと通常の描画処理に入って上書きされてるだけなよかん。。

  • るーでるです。
    わわいさん、回答有難うございます。

    >割り込みルーチンでどっかのポートをON/OFFさせてオシロででも見てみましょう
    そうですね。オシロで見てみます。
  • るーでるです。

    上記ソースの「画面全体を白で塗りつぶす処理」の部分を下記のように変更し動作確認してみました。

    void int_vdc_voline(void)
    {
    debugPortOn();
    }

    ・debugPortOn();の実体
    void debugPortOn(char state)
    {
      PORT.PCDR0.BIT.PC8DR =  1;
    }

    ・ポートCの初期化処理
    PORT.PCDR0.BIT.PC8DR = 1;
    PORT.PCIOR0.BIT.PC8IOR = 1;
    PORT.PCCR2.BIT.PC8MD = 0;

    PORTC8がONになる事はありませんでした。
    intprogc.cを下記のように書き換え試してみました。

    #include "iodefine.h"を追加
    // 174 VDC VOLINE
    void INT_VDC_VOLINE(void) { PORT.PCDR0.BIT.PC8DR = 1; }
    これもやはりPORTC8はONになる事はありませんでした。
    念のためPORT.PCDR0.BIT.PC8DR=1;単体で、該当のpinがONとなるか試しましたが問題なくONになりました。
  • わわいです
    ルネサスでVDC3のサンプルプログラムが公開されてます。
    それでライン割り込みも実装してると思いますんで、それを走らせてみましょう

    追記:
    割り込み許可した後、SGINTCNT.LINE_STATUSを0にしてみよう

  • るーでるです。

    VDC3.SGINTCNT.BIT.INT_LINE_EN=1の後にVDC3.SGINTCNT.BIT.LINE_STATUS=0を追加してみましたが、割り込みは掛かりませんでした。
    サンプルは現在確認中です。
  • わわいです
    CPUの割り込みをイネーブルにしてから、LINE_STATUS を0にしてみましょう
    マニュアルを見る限り、LINE_STATUSが0から1に変化するときに割り込みが発生する、とみえます
    ところが、CPUが割り込みイネーブルになった時点でLINE_STATUSが1になっていた場合には割り込みがかからず、これ以降明示的にこれを0にしない限り割り込みはかからないことになります
  • るーでるです。

    とりあえず割り込み掛かるようになりました。
    勘違いも有り、解決に時間が掛かりました。
    原因は、割り込み優先度の設定の後にset_imask()という関数?マクロ?を実行していなかった為のようです。

    ◆初期化
    VDC3.SGINTCNT.BIT.INT_LINE_NUM = 0;
    VDC3.SGINTCNT.BIT.INT_LINE_EN = 1;
    INTC.IPR10.BIT._VDC3 = 0x7;
    set_imask(0);
    これで正しく動きました。
    1秒間隔でポートをトグルする関数をタイマー割り込みで実装していたのですが、動作を確認する前に処理を一時的に止めたくなって、for()を回すだけの遅延処理に書き換えたのを失念していました。
    そのせいで、タイマーは正しく動いていると思い込んでしまい発見が遅れました。
  • set_imask()の動作を把握しておりませんのでもう少し調べてみます。
    本件、回答有り難うございました。