mikroBASIC用液晶表示サブルーチン群 作成:2007-09-09

MikroBASICに標準で付いてくる液晶表示ルーチンは自由な配線が出来ないので自作しました。このプログラムはデジタル時計の一部ですが汎用性があるため今後再利用しやすいようここにまとめておきます。


■仕様



 1.8ビットモードでも4ビットモードでもどちらでも動作可能
 2.8ビットモードは速度優先なので、8ビットポートを1つ占有
     8ビットモードで使うPICの足の数は10
       DB0〜DB7用に8ビットポート1つ。つまり足8本
       以下のとおり結線すること Rx は RA でも RB でも8ビットポートであれば何でもいいという意味
         DB0 −> Rx0
         DB1 −> Rx1
         DB2 −> Rx2
         DB3 −> Rx3
         DB4 −> Rx4
         DB5 −> Rx5
         DB6 −> Rx6
         DB7 −> Rx7
       EnableSignal(E)用に足1本
       RegisterSelect(RS)用に足1本
     4ビットモードで使うPICの足の数は6
       DB4〜DB7用に足4本
       EnableSignal(E)用に足1本
       RegisterSelect(RS)用に足1本
 3.4ビットモードは配線の自由度を優先するため、PICのどのピンに接続しても良い
 4.対応している液晶は秋月電子で販売されている 16×2文字の SC1602 SD1602 の2種
     この互換機なら何でもOK
 5.PICの周波数は何でもOK(たぶん)
 6.液晶表示装置からの読み出しは非対応 BUSY FLAG のチェックもしていない
     液晶表示装置の機種により処理速度が違うので厳密にはBUSY FLAGをチェックして処理が完了したことを確認するのが美しいが
     プログラムが複雑になるのと、一部不安定とのうわさがあるので対応しないこととした


■関数一覧

LCD関数一覧  これを見るよりソースコードのサンプルを見たほうが早いかも
Procedure名 解説
my_lcd_init ■機能
LCDを初期化する
たのProcedureはこれを実行した後に使用する必要がある
■引数
なし
■補足
mikroBASICの標準関数にlcd_initというのがあるので、関数名がダブらないように my_lcd_init と命名した
my_lcd_clear ■機能
LCDの画面をすべてクリヤする
■引数
なし
■補足
mikroBASICの標準関数にlcd_clearというのがあるので、関数名がダブらないように my_lcd_clear と命名した
lcd_home ■機能
画面をクリヤせずにカーソルの位置をホームポジション(画面左上)にする
lcd_locate(0,0) と同じ
■引数
なし
■補足
lcd_locate(0,0) の法が処理速度が何倍も速いので使う必要性はあまりない
lcd_create_char ■機能
ユーザー定義フォントを最大8個登録できます
■引数
1.no −> 登録するフォントの番号 0 〜 7
2.ch −> 登録するフォントのビットパターン String[8]型
          フォントは8×5サイズ
          String[0] が 一番上の行のビットパターン
          String[7] はカーソル用の領域として 0x00 にしておくのがよい
          横方向は5ビットなので右詰で入力
■お作法
この機能を実行すると文字の表示位置がホームポジション(=左上の位置)になります
lcd_cursor ■機能
カーソルの表示非表示、カーソルの点滅を制御する
■引数
1.cursor_on −> True:カーソル表示 False:カーソル非表示
2.blink    −> True:カーソル点滅 False:カーソル点滅なし
lcd_char ■機能
LCDに一文字表示する
表示位置はlcd_locateであらかじめ設定しておく
続けて実行するばあいはlcd_locateを使用せずとも1文字ずつ右に表示位置が変わる
これはこのプログラムの機能ではなくLCD自体の機能
■引数
1.ch −> 表示する文字の1バイトコード 
lcd_string ■機能
LCDに文字列を表示する
■引数
1.buf −> 文字列を格納した String[17]型 の変数
lcd_locate ■機能
文字列の表示位置を変更する
カーソルを表示している場合、カーソルが移動する
カーソルを表示していないときは表面上何も起こらないがlcd_charやlcd_stringで文字を表示させたときの位置が変わる
■引数
1.x −> 表示位置の横方向の位置 一番左が0 で 一番右が15
2.y −> 表示位置の縦方向の位置 上段が0  で 下段が1
lcd_byte ■機能
LCDに1バイトのデータを送る
データの内容によって処理の待ち時間を判断する
他のProcedureが使用しているものなのでこれを直接使用することはない
■引数
rs −> RS信号線をHighにするかLowにするか 1 または 0 を渡す
ch −> LCDに送る1バイトのコード
lcd_enable_delay ■機能
LCDにEnableを送る
他のProcedureが使用しているものなのでこれを直接使用することはない
■引数
delay −> Enableを送った後の待ち時間


■回路の例


これは8ビットモードで使用するときのサンプル。ソフトの定義部分を変更すればDB0〜DB7,E,RSの結線は変更できます。


実験風景



■ソースコードの解説と使い方


Step1. 6行目〜238行目を切り取って貼り付ける。もちろん行番号は不要。行番号のないものが一番下にあるのでそれを使えばよい。
Step2. 8ビットモードで使うときは 6行目 を削除するかコメントにする。
Step3. 15行目〜38行目までを回路とあわせる
         編集するのは = の右側部分
         4ビットモードで使用するときは <<EDIT 4bit & 8bit>> と <<EDIT 4bit>> となっている行を編集する
         8ビットモードで使用するときは <<EDIT 4bit & 8bit>> と <<EDIT 8bit>> となっている行を編集する
Step4. メインルーチンを書く
        ご参考:上のサンプル回路図を組んで、このプログラムを書き込めば何も変更しなくても動きます
        サンプルを動かすとこうなります <−MOVIE

0001 '---------------------------------------------------------
0002 ' LCD TEST PROGRAM
0003 '---------------------------------------------------------
0004 program MY_LCD
0005 
0006 #define LCD_4BIT                  ' <<EDIT 4bit>>
0007 
0008 '---------------------------------------------------------
0009 ' LCD subroutines
0010 '---------------------------------------------------------
0011 symbol PORT_OUTPUT     = 0
0012 symbol PORT_INPUT      = 1
0013 
0014 '---- LCD --------------------------
0015 symbol LCD_E_TRIS      = TRISA    ' <<EDIT 4bit & 8bit>>
0016 symbol LCD_E_PORT      = PORTA    ' <<EDIT 4bit & 8bit>>
0017 symbol LCD_E_BIT       = 3        ' <<EDIT 4bit & 8bit>>
0018 
0019 symbol LCD_RS_TRIS     = TRISE    ' <<EDIT 4bit & 8bit>>
0020 symbol LCD_RS_PORT     = PORTE    ' <<EDIT 4bit & 8bit>>
0021 symbol LCD_RS_BIT      = 0        ' <<EDIT 4bit & 8bit>>
0022 
0023 #ifdef LCD_4BIT then
0024 symbol LCD_DB4_TRIS    = TRISD    ' <<EDIT 4bit>>
0025 symbol LCD_DB5_TRIS    = TRISD    ' <<EDIT 4bit>>
0026 symbol LCD_DB6_TRIS    = TRISD    ' <<EDIT 4bit>>
0027 symbol LCD_DB7_TRIS    = TRISD    ' <<EDIT 4bit>>
0028 symbol LCD_DB4_PORT    = PORTD    ' <<EDIT 4bit>>
0029 symbol LCD_DB5_PORT    = PORTD    ' <<EDIT 4bit>>
0030 symbol LCD_DB6_PORT    = PORTD    ' <<EDIT 4bit>>
0031 symbol LCD_DB7_PORT    = PORTD    ' <<EDIT 4bit>>
0032 symbol LCD_DB4_BIT     = 4        ' <<EDIT 4bit>>
0033 symbol LCD_DB5_BIT     = 5        ' <<EDIT 4bit>>
0034 symbol LCD_DB6_BIT     = 6        ' <<EDIT 4bit>>
0035 symbol LCD_DB7_BIT     = 7        ' <<EDIT 4bit>>
0036 #else
0037 symbol LCD_DB_PORT     = PORTD    ' <<EDIT 8bit>>
0038 symbol LCD_DB_TRIS     = TRISD    ' <<EDIT 8bit>>
0039 #endif
0040 
0041 
0042 '---------------------------------------------------------
0043 ' Private
0044 '    SEND enable signal & delay
0045 '---------------------------------------------------------
0046 sub procedure lcd_enable_delay(dim delay as word)
0047   dim i as word
0048 
0049   LCD_E_PORT.LCD_E_BIT = 1
0050   Delay_us(1)
0051   LCD_E_PORT.LCD_E_BIT = 0
0052   for i = 0 to delay
0053     Delay_us(1)
0054   next i
0055 end sub
0056 
0057 '---------------------------------------------------------
0058 ' Private
0059 '    SEND byte
0060 '---------------------------------------------------------
0061 sub procedure lcd_byte( dim rs as byte, dim ch as byte )
0062   if rs = 1 then
0063     LCD_RS_PORT.LCD_RS_BIT = 1
0064   else
0065     LCD_RS_PORT.LCD_RS_BIT = 0
0066   end if
0067 
0068 #ifdef LCD_4BIT THEN
0069   LCD_DB7_PORT.LCD_DB7_BIT = ( ch and %10000000 )
0070   LCD_DB6_PORT.LCD_DB6_BIT = ( ch and %01000000 )
0071   LCD_DB5_PORT.LCD_DB5_BIT = ( ch and %00100000 )
0072   LCD_DB4_PORT.LCD_DB4_BIT = ( ch and %00010000 )
0073   LCD_E_PORT.LCD_E_BIT = 1
0074   Delay_us(1)
0075   LCD_E_PORT.LCD_E_BIT = 0
0076   LCD_DB7_PORT.LCD_DB7_BIT = ( ch and %00001000 )
0077   LCD_DB6_PORT.LCD_DB6_BIT = ( ch and %00000100 )
0078   LCD_DB5_PORT.LCD_DB5_BIT = ( ch and %00000010 )
0079   LCD_DB4_PORT.LCD_DB4_BIT = ( ch and %00000001 )
0080 #else
0081   LCD_DB_PORT = ch
0082 #endif
0083   LCD_E_PORT.LCD_E_BIT = 1
0084   Delay_us(1)
0085   LCD_E_PORT.LCD_E_BIT = 0
0086   if (ch <= %00000011) then
0087     Delay_us(1640)
0088   else
0089     Delay_us(  43)
0090   end if
0091 
0092   LCD_RS_PORT.LCD_RS_BIT = 0
0093 end sub
0094 
0095 '---------------------------------------------------------
0096 ' Clear display
0097 '---------------------------------------------------------
0098 sub procedure my_lcd_clear()
0099   lcd_byte( 0, %00000001 )
0100 end sub
0101 
0102 '---------------------------------------------------------
0103 ' return the cursor to the home position
0104 '---------------------------------------------------------
0105 sub procedure lcd_home()
0106   lcd_byte( 0, %00000010 )
0107 end sub
0108 
0109 '---------------------------------------------------------
0110 ' Cursor control
0111 '
0112 ' cursor_on -> True:cursor on  False:cursor off
0113 ' blink     -> True:blink on   False:blink off
0114 '---------------------------------------------------------
0115 sub procedure lcd_cursor( dim cursor_on as boolean, dim blink as boolean )
0116   dim ch as byte
0117 
0118   ch = %00001100
0119   if cursor_on = True then
0120     ch = ch or %00000010
0121   end if
0122   if blink = True then
0123     ch = ch or %00000001
0124   end if
0125   lcd_byte( 0, ch )
0126 end sub
0127 
0128 '---------------------------------------------------------
0129 ' LCD initialize
0130 '---------------------------------------------------------
0131 sub procedure my_lcd_init()
0132   Delay_ms(15)
0133   LCD_E_TRIS.LCD_E_BIT         = PORT_OUTPUT
0134   LCD_RS_TRIS.LCD_RS_BIT       = PORT_OUTPUT
0135 #ifdef LCD_4BIT THEN
0136   LCD_DB7_TRIS.LCD_DB7_BIT   = PORT_OUTPUT
0137   LCD_DB6_TRIS.LCD_DB6_BIT   = PORT_OUTPUT
0138   LCD_DB5_TRIS.LCD_DB5_BIT   = PORT_OUTPUT
0139   LCD_DB4_TRIS.LCD_DB4_BIT   = PORT_OUTPUT
0140 #else
0141   LCD_DB_TRIS                = 0x00
0142 #endif
0143 
0144   LCD_RS_PORT.LCD_RS_BIT = 0
0145 
0146 #ifdef LCD_4BIT THEN
0147   LCD_DB7_PORT.LCD_DB7_BIT = 0
0148   LCD_DB6_PORT.LCD_DB6_BIT = 0
0149   LCD_DB5_PORT.LCD_DB5_BIT = 1
0150   LCD_DB4_PORT.LCD_DB4_BIT = 1
0151 #else
0152   LCD_DB_PORT = %00110000
0153 #endif
0154   lcd_enable_delay( 4100 )
0155   lcd_enable_delay(   40 )
0156   lcd_enable_delay(   40 )
0157 #ifdef LCD_4BIT THEN
0158   LCD_DB4_PORT.LCD_DB4_BIT = 0
0159   lcd_enable_delay(   40 )
0160 #endif
0161 
0162 #ifdef LCD_4BIT THEN
0163   lcd_byte( 0, %00101000 )
0164 #else
0165   lcd_byte( 0, %00111000 )
0166 #endif
0167   lcd_cursor( False, False )
0168   Delay_ms(100)
0169 end sub
0170 
0171 '---------------------------------------------------------
0172 ' display character
0173 '---------------------------------------------------------
0174 sub procedure lcd_char( dim ch as byte )
0175   lcd_byte( 1, ch )
0176 end sub
0177 
0178 '---------------------------------------------------------
0179 ' display string
0180 '---------------------------------------------------------
0181 sub procedure lcd_string( dim byref buf as string[17] )
0182   dim i    as byte
0183   dim len2 as byte
0184 
0185   len2 = strlen(buf) - 1
0186   for i = 0 to len2
0187     lcd_char( buf[i] )
0188   next i
0189 end sub
0190 
0191 '---------------------------------------------------------
0192 ' Locate cursor
0193 '
0194 ' x -> cusor x posision     range 0 to 15
0195 ' y -> cusor y posision     range 0 to  2
0196 '
0197 ' ex
0198 '   lcd_locate( 0, 0 )  <- home posision (upper left)
0199 '---------------------------------------------------------
0200 sub procedure lcd_locate( dim x as byte, dim y as byte )
0201   dim addr as byte
0202 
0203   addr = %10000000
0204   if y = 1 then
0205     addr = addr + 0x40
0206   end if
0207   addr = addr + x
0208 
0209   lcd_byte( 0, addr )
0210 end sub
0211 
0212 '---------------------------------------------------------
0213 ' Create original characters
0214 '
0215 ' no -> character No    0 to 5
0216 ' ch -> 8 x 5 character bit pattern
0217 '         ex) font 'A'
0218 '          ch[0] = %00001110
0219 '          ch[1] = %00010001
0220 '          ch[2] = %00010001
0221 '          ch[3] = %00010001
0222 '          ch[4] = %00011111
0223 '          ch[5] = %00010001
0224 '          ch[6] = %00010001
0225 '          ch[7] = %00000000
0226 '---------------------------------------------------------
0227 sub procedure lcd_create_char( dim no as byte, dim byref ch as string[8] )
0228   dim cgram_addr as byte
0229   dim i          as byte
0230   
0231   cgram_addr = %01000000 or (no << 3)
0232   lcd_byte( 0, cgram_addr )
0233   for i = 0 to 7
0234     lcd_byte( 1, ch[i] )
0235   next i
0236   
0237   lcd_locate(0,0)
0238 end sub
0239 
0240 '---------------------------------------------------------
0241 ' LCD test main routine
0242 '---------------------------------------------------------
0243 main:
0244   dim i as byte
0245   dim buf as string[17]
0246   
0247   dim org_char1 as string[8]
0248   dim org_char2 as string[8]
0249   dim org_char3 as string[8]
0250   
0251   org_char1[0] = %00010101
0252   org_char1[1] = %00010101
0253   org_char1[2] = %00010101
0254   org_char1[3] = %00010101
0255   org_char1[4] = %00010101
0256   org_char1[5] = %00010101
0257   org_char1[6] = %00010101
0258   org_char1[7] = %00000000
0259   
0260   org_char2[0] = %00011111
0261   org_char2[1] = %00000000
0262   org_char2[2] = %00011111
0263   org_char2[3] = %00000000
0264   org_char2[4] = %00011111
0265   org_char2[5] = %00000000
0266   org_char2[6] = %00011111
0267   org_char2[7] = %00000000
0268   
0269   while( True )
0270     my_lcd_init()
0271 
0272 
0273     ' <<display>>
0274     '   123_____________
0275     '   _____________ABC
0276     my_lcd_clear()
0277     lcd_char("1")
0278     lcd_char("2")
0279     lcd_char("3")
0280     lcd_locate(13,1)
0281     for i = 0x41 to 0x43
0282       lcd_char(i)
0283     next i
0284     Delay_ms(3000)
0285 
0286     ' <<display>>
0287     ' X_______________    <- Original Font No.0  TATEJIMA
0288     ' X_______________    <- Original Font No.1  YOKOJIMA
0289     my_lcd_clear()
0290     lcd_create_char( 0, org_char1 )
0291     lcd_create_char( 1, org_char2 )
0292     lcd_char(0)     'display original font No.0
0293     lcd_locate(0,1)
0294     lcd_char(1)     'display original font No.1
0295     lcd_locate(14,1)
0296     Delay_ms(3000)
0297 
0298     ' <<display>>
0299     ' X_______________    <- Original Font No.3  animation
0300     ' ________________
0301     for i = 0 to 7
0302       org_char3[i] = %00000000
0303     next i
0304 
0305     my_lcd_clear()
0306     lcd_create_char( 2, org_char3 )
0307     lcd_char(2)
0308     
0309     for i = 0 to 7
0310       Delay_ms(500)
0311       org_char3[i] = %11111111
0312       lcd_create_char( 2, org_char3 )
0313     next i
0314     
0315     Delay_ms(1000)
0316     
0317     ' <<display>>
0318     ' 2007-09-09______
0319     ' ________12:30:45
0320     my_lcd_clear()
0321     
0322     buf = "2007-09-09"
0323     lcd_string( buf )
0324     lcd_locate(8,1)
0325     buf = "12:30:45"
0326     lcd_string( buf )
0327     Delay_ms(3000)
0328     
0329     ' <<display>>
0330     ' ABC_____________    <- move cursor
0331     ' abc_____________
0332     my_lcd_clear()
0333 
0334     lcd_cursor( True, True )  'cursor blinking
0335     buf = "ABC"
0336     lcd_string( buf )
0337     lcd_locate(0,1)
0338     buf = "abc"
0339     lcd_string( buf )
0340     Delay_ms(2000)
0341 
0342     lcd_cursor( True, False )
0343     for i = 2 to 0 step -1
0344       Delay_ms(500)
0345       lcd_locate(i,1)
0346     next i
0347     Delay_ms(2000)
0348   wend
0349 end.


行番号のないソースリスト コピペ用 (上のものとまったく同じ)

'---------------------------------------------------------
' LCD TEST PROGRAM
'---------------------------------------------------------
program MY_LCD

#define LCD_4BIT                  ' <<EDIT 4bit>>

'---------------------------------------------------------
' LCD subroutines
'---------------------------------------------------------
symbol PORT_OUTPUT     = 0
symbol PORT_INPUT      = 1

'---- LCD --------------------------
symbol LCD_E_TRIS      = TRISA    ' <<EDIT 4bit & 8bit>>
symbol LCD_E_PORT      = PORTA    ' <<EDIT 4bit & 8bit>>
symbol LCD_E_BIT       = 3        ' <<EDIT 4bit & 8bit>>

symbol LCD_RS_TRIS     = TRISE    ' <<EDIT 4bit & 8bit>>
symbol LCD_RS_PORT     = PORTE    ' <<EDIT 4bit & 8bit>>
symbol LCD_RS_BIT      = 0        ' <<EDIT 4bit & 8bit>>

#ifdef LCD_4BIT then
symbol LCD_DB4_TRIS    = TRISD    ' <<EDIT 4bit>>
symbol LCD_DB5_TRIS    = TRISD    ' <<EDIT 4bit>>
symbol LCD_DB6_TRIS    = TRISD    ' <<EDIT 4bit>>
symbol LCD_DB7_TRIS    = TRISD    ' <<EDIT 4bit>>
symbol LCD_DB4_PORT    = PORTD    ' <<EDIT 4bit>>
symbol LCD_DB5_PORT    = PORTD    ' <<EDIT 4bit>>
symbol LCD_DB6_PORT    = PORTD    ' <<EDIT 4bit>>
symbol LCD_DB7_PORT    = PORTD    ' <<EDIT 4bit>>
symbol LCD_DB4_BIT     = 4        ' <<EDIT 4bit>>
symbol LCD_DB5_BIT     = 5        ' <<EDIT 4bit>>
symbol LCD_DB6_BIT     = 6        ' <<EDIT 4bit>>
symbol LCD_DB7_BIT     = 7        ' <<EDIT 4bit>>
#else
symbol LCD_DB_PORT     = PORTD    ' <<EDIT 8bit>>
symbol LCD_DB_TRIS     = TRISD    ' <<EDIT 8bit>>
#endif


'---------------------------------------------------------
' Private
'    SEND enable signal & delay
'---------------------------------------------------------
sub procedure lcd_enable_delay(dim delay as word)
  dim i as word

  LCD_E_PORT.LCD_E_BIT = 1
  Delay_us(1)
  LCD_E_PORT.LCD_E_BIT = 0
  for i = 0 to delay
    Delay_us(1)
  next i
end sub

'---------------------------------------------------------
' Private
'    SEND byte
'---------------------------------------------------------
sub procedure lcd_byte( dim rs as byte, dim ch as byte )
  if rs = 1 then
    LCD_RS_PORT.LCD_RS_BIT = 1
  else
    LCD_RS_PORT.LCD_RS_BIT = 0
  end if

#ifdef LCD_4BIT THEN
  LCD_DB7_PORT.LCD_DB7_BIT = ( ch and %10000000 )
  LCD_DB6_PORT.LCD_DB6_BIT = ( ch and %01000000 )
  LCD_DB5_PORT.LCD_DB5_BIT = ( ch and %00100000 )
  LCD_DB4_PORT.LCD_DB4_BIT = ( ch and %00010000 )
  LCD_E_PORT.LCD_E_BIT = 1
  Delay_us(1)
  LCD_E_PORT.LCD_E_BIT = 0
  LCD_DB7_PORT.LCD_DB7_BIT = ( ch and %00001000 )
  LCD_DB6_PORT.LCD_DB6_BIT = ( ch and %00000100 )
  LCD_DB5_PORT.LCD_DB5_BIT = ( ch and %00000010 )
  LCD_DB4_PORT.LCD_DB4_BIT = ( ch and %00000001 )
#else
  LCD_DB_PORT = ch
#endif
  LCD_E_PORT.LCD_E_BIT = 1
  Delay_us(1)
  LCD_E_PORT.LCD_E_BIT = 0
  if (ch <= %00000011) then
    Delay_us(1640)
  else
    Delay_us(  43)
  end if

  LCD_RS_PORT.LCD_RS_BIT = 0
end sub

'---------------------------------------------------------
' Clear display
'---------------------------------------------------------
sub procedure my_lcd_clear()
  lcd_byte( 0, %00000001 )
end sub

'---------------------------------------------------------
' return the cursor to the home position
'---------------------------------------------------------
sub procedure lcd_home()
  lcd_byte( 0, %00000010 )
end sub

'---------------------------------------------------------
' Cursor control
'
' cursor_on -> True:cursor on  False:cursor off
' blink     -> True:blink on   False:blink off
'---------------------------------------------------------
sub procedure lcd_cursor( dim cursor_on as boolean, dim blink as boolean )
  dim ch as byte

  ch = %00001100
  if cursor_on = True then
    ch = ch or %00000010
  end if
  if blink = True then
    ch = ch or %00000001
  end if
  lcd_byte( 0, ch )
end sub

'---------------------------------------------------------
' LCD initialize
'---------------------------------------------------------
sub procedure my_lcd_init()
  Delay_ms(15)
  LCD_E_TRIS.LCD_E_BIT         = PORT_OUTPUT
  LCD_RS_TRIS.LCD_RS_BIT       = PORT_OUTPUT
#ifdef LCD_4BIT THEN
  LCD_DB7_TRIS.LCD_DB7_BIT   = PORT_OUTPUT
  LCD_DB6_TRIS.LCD_DB6_BIT   = PORT_OUTPUT
  LCD_DB5_TRIS.LCD_DB5_BIT   = PORT_OUTPUT
  LCD_DB4_TRIS.LCD_DB4_BIT   = PORT_OUTPUT
#else
  LCD_DB_TRIS                = 0x00
#endif

  LCD_RS_PORT.LCD_RS_BIT = 0

#ifdef LCD_4BIT THEN
  LCD_DB7_PORT.LCD_DB7_BIT = 0
  LCD_DB6_PORT.LCD_DB6_BIT = 0
  LCD_DB5_PORT.LCD_DB5_BIT = 1
  LCD_DB4_PORT.LCD_DB4_BIT = 1
#else
  LCD_DB_PORT = %00110000
#endif
  lcd_enable_delay( 4100 )
  lcd_enable_delay(   40 )
  lcd_enable_delay(   40 )
#ifdef LCD_4BIT THEN
  LCD_DB4_PORT.LCD_DB4_BIT = 0
  lcd_enable_delay(   40 )
#endif

#ifdef LCD_4BIT THEN
  lcd_byte( 0, %00101000 )
#else
  lcd_byte( 0, %00111000 )
#endif
  lcd_cursor( False, False )
  Delay_ms(100)
end sub

'---------------------------------------------------------
' display character
'---------------------------------------------------------
sub procedure lcd_char( dim ch as byte )
  lcd_byte( 1, ch )
end sub

'---------------------------------------------------------
' display string
'---------------------------------------------------------
sub procedure lcd_string( dim byref buf as string[17] )
  dim i    as byte
  dim len2 as byte

  len2 = strlen(buf) - 1
  for i = 0 to len2
    lcd_char( buf[i] )
  next i
end sub

'---------------------------------------------------------
' Locate cursor
'
' x -> cusor x posision     range 0 to 15
' y -> cusor y posision     range 0 to  2
'
' ex
'   lcd_locate( 0, 0 )  <- home posision (upper left)
'---------------------------------------------------------
sub procedure lcd_locate( dim x as byte, dim y as byte )
  dim addr as byte

  addr = %10000000
  if y = 1 then
    addr = addr + 0x40
  end if
  addr = addr + x

  lcd_byte( 0, addr )
end sub

'---------------------------------------------------------
' Create original characters
'
' no -> character No    0 to 5
' ch -> 8 x 5 character bit pattern
'         ex) font 'A'
'          ch[0] = %00001110
'          ch[1] = %00010001
'          ch[2] = %00010001
'          ch[3] = %00010001
'          ch[4] = %00011111
'          ch[5] = %00010001
'          ch[6] = %00010001
'          ch[7] = %00000000
'---------------------------------------------------------
sub procedure lcd_create_char( dim no as byte, dim byref ch as string[8] )
  dim cgram_addr as byte
  dim i          as byte
  
  cgram_addr = %01000000 or (no << 3)
  lcd_byte( 0, cgram_addr )
  for i = 0 to 7
    lcd_byte( 1, ch[i] )
  next i
  
  lcd_locate(0,0)
end sub

'---------------------------------------------------------
' LCD test main routine
'---------------------------------------------------------
main:
  dim i as byte
  dim buf as string[17]
  
  dim org_char1 as string[8]
  dim org_char2 as string[8]
  dim org_char3 as string[8]
  
  org_char1[0] = %00010101
  org_char1[1] = %00010101
  org_char1[2] = %00010101
  org_char1[3] = %00010101
  org_char1[4] = %00010101
  org_char1[5] = %00010101
  org_char1[6] = %00010101
  org_char1[7] = %00000000
  
  org_char2[0] = %00011111
  org_char2[1] = %00000000
  org_char2[2] = %00011111
  org_char2[3] = %00000000
  org_char2[4] = %00011111
  org_char2[5] = %00000000
  org_char2[6] = %00011111
  org_char2[7] = %00000000
  
  while( True )
    my_lcd_init()


    ' <<display>>
    '   123_____________
    '   _____________ABC
    my_lcd_clear()
    lcd_char("1")
    lcd_char("2")
    lcd_char("3")
    lcd_locate(13,1)
    for i = 0x41 to 0x43
      lcd_char(i)
    next i
    Delay_ms(3000)

    ' <<display>>
    ' X_______________    <- Original Font No.0  TATEJIMA
    ' X_______________    <- Original Font No.1  YOKOJIMA
    my_lcd_clear()
    lcd_create_char( 0, org_char1 )
    lcd_create_char( 1, org_char2 )
    lcd_char(0)     'display original font No.0
    lcd_locate(0,1)
    lcd_char(1)     'display original font No.1
    lcd_locate(14,1)
    Delay_ms(3000)

    ' <<display>>
    ' X_______________    <- Original Font No.3  animation
    ' ________________
    for i = 0 to 7
      org_char3[i] = %00000000
    next i

    my_lcd_clear()
    lcd_create_char( 2, org_char3 )
    lcd_char(2)
    
    for i = 0 to 7
      Delay_ms(500)
      org_char3[i] = %11111111
      lcd_create_char( 2, org_char3 )
    next i
    
    Delay_ms(1000)
    
    ' <<display>>
    ' 2007-09-09______
    ' ________12:30:45
    my_lcd_clear()
    
    buf = "2007-09-09"
    lcd_string( buf )
    lcd_locate(8,1)
    buf = "12:30:45"
    lcd_string( buf )
    Delay_ms(3000)
    
    ' <<display>>
    ' ABC_____________    <- move cursor
    ' abc_____________
    my_lcd_clear()

    lcd_cursor( True, True )  'cursor blinking
    buf = "ABC"
    lcd_string( buf )
    lcd_locate(0,1)
    buf = "abc"
    lcd_string( buf )
    Delay_ms(2000)

    lcd_cursor( True, False )
    for i = 2 to 0 step -1
      Delay_ms(500)
      lcd_locate(i,1)
    next i
    Delay_ms(2000)
  wend
end.