データシートはセイコーインスツルメントのホームページからダウンロードできます。
このモジュールは5V単一電源で動くので楽です。端子の機能を簡単に説明すると、
D0〜D3 |
データ入力です。 |
FRM |
フレーム開始信号です。厳密にイコールではありませんがテレビの垂直同期に該当します。 |
M |
交流化信号です。フレームごとに0、1を反転させます。 |
CL1 |
ラインクロックです。厳密にイコールではありませんがテレビの水平同期に該当します。 |
CL2 |
データクロックです。周期は4ドット時間ぶんです。 |
Vdd,Vss |
電源 |
よく使われているキャラクタ液晶モジュールには「液晶ドライバ」「RAMとリフレッシュコントローラ」が内蔵されており、簡単に使うことができるのですが、グラフィック液晶モジュールはほとんどの場合液晶ドライバしか内蔵されていないので(今回のG2436もそうです)リフレッシュコントローラを自作し、RAMを外付けしなければいけません。
必要なRAM容量は約2Kバイト(240/8*64=1920)。H8/3052なら内蔵RAMは8Kバイトあるからそのうちの2KをLCD用RAMに割いてもなんとかなりそう。リフレッシュコントローラはタイミング発生だけにして、データはH8内蔵DMAコントローラで送ればよいのではないか?と考えました。
しかし、液晶モジュールにはテレビで言うところの「ブランク期間」が存在せず、1フレーム表示した直後、切れ目なくすぐ次のフレームのデータを送らなければいけません。H8のDMAコントローラは、送るデータ量が256バイト以下なら「リピートモード」が使えるのですが、今回は1920バイトなので無理です。結局割り込みで定期的にDMAコントローラを再起動するしかないわけですが、時間的にかなり厳しいです。
割り込み禁止にすると画面が出なくなるシステム、ってのも情けないので、H8内蔵のRAMは使わずにRAMを外付けし、リフレッシュコントローラにRAMのバス制御も含めることにしました。
RAMは2Kバイトあればよいのですが、いまどき6116なんて少容量のRAMのほうが入手は大変です。また、グラフィックを使うようなアプリケーションはデータもたくさん使うだろうからデータ用のRAMもあったほうがよいでしょう。しかし、データ用と液晶用に2つもRAMを積むのは大変なので1つで兼ねる事にしました。思いきって628512を積み、最初の2Kバイトだけ液晶用にし、残りは全てデータ用です。
液晶用とデータ用が兼用なので、データ用RAM領域にもウエイトがかかってしまいます。しかし、176クロックに8クロックの割合でウエイトがはいるだけなので、そのデメリットはRAMを2つ積んで回路が複雑化するデメリットよりはるかに小さいと思いました。
RAMはH8のエリア1(h’200000〜)に配置しました。ちなみに、回路を簡単にするため1ラインを32バイトとし(本来は30バイトあればいい)、末尾2バイトは表示されないようにしました。
大体以下のようなブロックに分かれます。(カッコ内は主なVHDLの信号名)
さっきも書いたように、日立のLM258Xを引きずっているので見づらいソースです。たとえば b:std_logic という信号名がありますが、最初はこれは b:std_logic_vector(2 downto 0) でした。LM258Xは1ビットづつシリアルで送るので、この変数はビット位置を表していました。G2436では4ビットづつ送るので、この変数は前半4ビットか、後半4ビットかを表す1ビットの変数になりました。
i で始まる信号名は Inner の意味で、 i の付いていない外部信号名に対応します。どうしてVHDLって外に出す信号名を内部で参照しちゃいけないんだろう。
カウンタ div はCPUクロックの25MHzを44分周してデータクロック CP2 を作ります。1バイト=4ビット×2なので、b は CP2 のさらに半分の周波数です。
b='1'のときの icp2 の立ちあがりでRAMからデータを q にとりこみ(ibsel='1',ma=アドレスカウンタ)、同時にアドレスカウンタをインクリメントします。またその前後の時間、CPUがRAMをアクセスしないようウエイトをかけます(iwait='1)。
ma17 が ca17 の反転なのは、RAMに628128も使えるようにするためです。628512のA17は628128ではCS(アクティブH)なので、そのままではCPUがh’200000番地をアクセスしたときCS=Lとなり、アクセスできないからです。
-- G2436 Controller (c)2003 A.Hiramatsu library IEEE; use IEEE.STD_LOGIC_1164.ALL; use IEEE.STD_LOGIC_ARITH.ALL; use IEEE.STD_LOGIC_UNSIGNED.ALL; entity lcd4 is Port ( clk : in std_logic; ca : in std_logic_vector(18 downto 0); cd : inout std_logic_vector(7 downto 0); crd : in std_logic; cwr : in std_logic; ccs : in std_logic; cwait : out std_logic; ma : out std_logic_vector(18 downto 0); md : inout std_logic_vector(7 downto 0); mrd : out std_logic; mwr : out std_logic; cp1 : out std_logic; cp2 : out std_logic; do : out std_logic_vector(3 downto 0); frm : out std_logic; m : out std_logic); end lcd4; architecture behavioral of lcd4 is signal div:std_logic_vector(5 downto 0); signal icp1,icp2:std_logic; signal b:std_logic; signal x:std_logic_vector(4 downto 0); signal y:std_logic_vector(5 downto 0); signal q:std_logic_vector(7 downto 0); signal iwait:std_logic; signal ibsel:std_logic; signal ima:std_logic_vector(18 downto 0); signal ifrm:std_logic; signal im:std_logic; signal iadr:std_logic_vector(10 downto 0); begin process(clk) begin if(clk'event and clk='1') then if(div="101011") then if(icp2='0') then icp1 <= '0'; if(b='1') then q <= md; if(x="11101") then y <= y+1; x <= "00000"; else x <= x+1; end if; else q(7 downto 4) <= q(3 downto 0); end if; b <= not b; else if(b='1' and x="00000") then icp1 <= '1'; end if; end if; icp2 <= not icp2; div <= "000000"; else div <= div+1; end if; end if; end process; cp1 <= icp1; cp2 <= icp2; do(3 downto 0) <= q(7 downto 4); iadr <= y & x; process(clk) begin if(clk'event and clk='1') then if(b='1' and icp2='0') then if(div="101001") then ibsel <= '1'; elsif(div="101011") then ibsel <= '0'; end if; if(div="100110") then iwait <= '1'; end if; elsif(b='0' and icp2='1' and div="000000") then iwait <= '0'; end if; end if; end process; process(crd,ccs,md) begin if(crd='1' or ccs='1') then cd <= "ZZZZZZZZ"; else cd <= md; end if; end process; process(crd,ccs,ibsel,cd) begin if((crd='0' and ccs='0') or ibsel='1') then md <= "ZZZZZZZZ"; else md <= cd; end if; end process; process(ibsel,iadr,ca) begin if(ibsel='1') then ima <= "01000000" & iadr; else ima(18) <= ca(18); ima(17) <= not ca(17); ima(16 downto 0) <= ca(16 downto 0); end if; end process; cwait <= not( not ccs and iwait); ma <= ima; mrd <= not(ibsel or (not crd and not ccs)); mwr <= not(not ibsel and not cwr and not ccs); process(clk) begin if(clk'event and clk='1') then if(iadr="00000000001" and b='0' and div="101011") then ifrm <= '1'; else if(iadr="00000100001" and b='0' and div="101011") then ifrm <= '0'; end if; end if; end if; end process; process(ifrm) begin if(ifrm'event and ifrm='0') then im <= not im; end if; end process; frm <= ifrm; m <= im; end behavioral; |