5 / 8
LcdCmdをスーパクラスとするコマンド用クラス
LcdCmdをスーパクラスとするクラス群を実装しましょう.
-
LcdCmdクラス
このクラスにはprotectedなメンバである_cmd,_registerSelect,_executeTimeがあり,サブクラスから読み書きできるようになっています.そのうち,_registerSelectと_executeTimeはLcdCmdクラスにgetterがありますので実装してください. -
LcdReceiveCmdクラス
このクラスには,LCDのデータバスから取得したデータを設定するsetSerialDataメンバ関数があります.仮引数serial_dataを_cmdに代入してください. -
ReadBusyFlagCmdクラス
このクラスのコンストラクタでは,_registerSelectをインストラクションコードにすることと,実行時間を設定してください.isBusy関数では,_cmdの最上位ビットが1であったらtrue,そうでなかったらfalseを返してください.getAddressCounter関数では,_cmdの最上位ビットを除く7ビットを返してください. -
ReadCharacterCmdクラス
このクラスのコンストラクタでは,_registerSelectをデータにすることと,実行時間を設定してください.getCharacter関数では,_cmdを返してください. -
LcdTransmitCmdクラス
このクラスにはLCDのデータバスを介して送信したいデータを取得するgetSerialDataメンバ関数があります.この関数では_cmdを返すようにしてください. -
LcdInstructionクラス
このクラスのコンストラクタでは,_registerSelectをインストラクションコードにしてください. -
WriteCharacterCmdクラス
このクラスのコンストラクタでは,_registerSelectをデータにすることと,実行時間を設定してください.setCharacter関数では,仮引数characterを_cmdに代入してください. -
LcdInstructionクラスのサブクラス
8種類のインストラクションをモデル化したクラスはすべてLcdInstructionクラスのサブクラスとなっています.それらのクラスではおおよそ同じようなことを行っております.このページではFunctionSetCmdを例にとって説明しますので,他のクラスはすべて皆さんが考えて実装してください.
まずはコンストラクタです.定数_EXECUTE_TIMEと_CODE_IDがありますので,コンストラクタで_executeTimeと_cmdに設定してください.具体的には次のようになります._cmdの代入方法に注意をしてください.なぜこのようになるかというと,すべてのインストラクションは最上位から走査していき最初に1となるビットの位置でインストラクションを識別することができます.この「1」を_CODE_IDとして書くクラスでは定義してありますので,_CODE_IDを_cmdに論理和してあげる必要があるのです.
FunctionSetCmd::FunctionSetCmd(){ /* 実行時間を設定する */ _executeTime = _EXECUTE_TIME; /* このコマンドであることを表すビットを設定する */ _cmd |= _CODE_ID; }
次に,メンバ関数について説明します.FunctionSetCmdにはsetInterfaceDataWidth関数があります.この関数はインストラクションコード表にあるD/Lを表しています.この関数の仮引数widthがWIDTH8であったらD4(ビット4)を1にすればよいですので,_cmdには0x10(=2進数では00010000)と論理和したものを代入してください.反対に,widthがWIDTH4であったらD4を0にすればよいですので,_cmdには0x10を反転した(~0x10)と論理積したものを代入してください.具体的には下のようになります.
このように,インストラクションコード表を読んで,対応するビットを操作するようにしてください.void FunctionSetCmd::setInterfaceDataWidth(Interface /* データバスの幅を表すwidthにもとづき処理を分ける */ switch ( width ) { /* 8ビット幅であったら */ case WIDTH8: _cmd |= 0x10; break; /* 4ビット幅であったら */ case WIDTH4: _cmd &= ~( 0x10 ); break; } }
演習問題
FunctionSetCmdにある残りのメンバ関数に加え,以下のクラスにあるメンバ関数を実装してください.
CursorHomeCmd,ClearCmd,DisplayCmd,EntryModeSetCmd,CursorShiftCmd -
DdramAddressSetCmdクラス
まずコンストラクタでは,先ほど説明したLcdInstructionクラスのサブクラスと同様に,_executeTimeと_cmdを設定してください.さて,DdramAddressSetCmdクラスでは,以前説明したように,LCD内にあるDDRAMのアドレスを設定することで,パターンを表示する位置を指定することができます.そこで,setLocateメンバ関数を作り,表示位置をxとyで指定できるようにしましょう.なお,0<=x<=15,0<=y<=1と指定することとしますので,例えば左から5列目,2行目にパターンを表示したい場合にはx=4,y=1とするようにしましょう.この関数で行う処理の流れをアクティビティ図にしたものを示します.オブジェクトノードの色の意味等についてはこちらで確認しておいてください.
この処理で難しいのはビットの操作です.ビット6はDDRAMアドレスの最上位ビットですのでy=0のときには0,y=1のときには1となるようにする必要があります.ただし,ビット7にはDDRAMアドレスセットインストラクションを識別するためのビットとなっているので,これを消さずにビット6~0を操作しなければなりません.従いまして,1行目の場合次のようになります.
_cmd = _CODE_ID | x;
同じ要領で2行目のときのプログラムを考えてください.
-
CgramAddressSetCmdクラス
まずコンストラクタでは,先ほど説明したLcdInstructionクラスのサブクラスと同様に,_executeTimeと_cmdを設定してください.さて,CgramAddressSetCmdではオリジナルパターンを設定するときに使うsetCharacterPatternAddress関数があります.この関数では,オリジナルパターンを格納するCGRAMのアドレスを設定します.オリジナルパターンには5×7と5×10があり,前者の場合には8個,後者の場合には4個のオリジナルパターンを設定できます.5×7の場合,仮引数character_idを左へ3ビットシフトしたものと_CODE_IDとの論理和を_cmdに設定します.5×10の場合,仮引数character_idを左へ4ビットシフトしたものと_CODE_IDとの論理和を_cmdに設定します.下にこの関数の流れを表した図を示します.