はじめに
MSX0 (MSX-DOS) で使える Liquid Crystal Display (LCD) ライブラリを作ってみました。
ライブラリ
ライブラリは Arduino の Liquid Crystal ライブラリ互換となっています。
- LiquidCrystal (Github)
- LiquidCrystal (arduino.cc)
- Liquid Crystal Displays (LCD) with Arduino (Arduino Documentation)
LCD.LIB
LCD ライブラリです。
- I2C タイプの LCD に対応しています
- LCD モジュールを PortA に接続して使います
- 一般的な 1602 LCD の他に 2004 LCD も使えます
- 別途、IOT.LIB が必要です
ファイル名 | 依存ライブラリ |
---|---|
LCD.LIB | SYSUTILS.LIB, IOT.LIB |
LCD.LIB
{
LCD.LIB
}
type
LCDStr = string[40];
TChrDef = array [0..7] of byte;
TLCDRec = record
Node: LibStr;
Cols: byte;
Rows: byte;
CharSize: byte;
Backlight: byte;
Display: byte;
DispFunc: byte;
EntryMode: byte;
end;
var
_lcd: TLCDRec;
procedure LCD_Send(data, m: byte);
procedure WriteData(data: byte);
const
En = 4;
var
s: string[2];
begin
s[0] := Chr(2); { SetLength(s, 2) }
s[1] := Chr(data or En);
s[2] := Chr(data);
IoTPutStr(_lcd.Node, s);
end;
begin
WriteData(data and $F0 or _lcd.Backlight or m);
WriteData(data shl 4 or _lcd.Backlight or m);
end;
procedure LCD_Command(data: byte);
begin
LCD_Send(data, 0);
end;
procedure LCD_WriteData(data: byte);
begin
LCD_Send(data, 1);
end;
function LCD_ColsInRange(col: byte): byte;
begin
if col < 0 then
col := 0;
if col > Pred(_lcd.Cols) then
col := Pred(_lcd.Cols);
LCD_ColsInRange := col;
end;
function LCD_RowsInRange(row: byte): byte;
begin
if row < 0 then
row := 0;
if row > Pred(_lcd.Rows) then
row := Pred(_lcd.Rows);
LCD_RowsInRange := row;
end;
procedure LCD_Begin(Node: LibStr; Cols, Rows: byte; Use5x10: boolean);
const
FS = $20;
CS: array [boolean] of byte = ($00, $04);
begin
_lcd.Node := Node;
_lcd.CharSize := CS[Use5x10];
_lcd.Cols := Pred(40);
_lcd.Cols := Succ(LCD_ColsInRange(Pred(Cols)));
_lcd.Rows := Pred(4);
_lcd.Rows := Succ(LCD_RowsInRange(Pred(Rows)));
_lcd.BackLight := $08; { ON }
_lcd.Display := $0C; { ON }
_lcd.EntryMode := $06; { Inclement }
_lcd.DispFunc := $00;
if _lcd.Rows > 1 then
_lcd.DispFunc := _lcd.DispFunc or $08; { 2 Line }
if (_lcd.CharSize <> 0) and (_lcd.Rows = 1) then
_lcd.DispFunc := _lcd.DispFunc or $04; { 5x10 }
LCD_Command($33); { Function Set: 8bit }
LCD_Command($32); { Function Set: 8bit }
LCD_Command(FS or _lcd.DispFunc); { Function Set: 4bit }
LCD_Command(_lcd.Display);
LCD_Command($01);
LCD_Command(_lcd.EntryMode);
end;
procedure LCD_Clear;
begin
LCD_Command($01);
end;
procedure LCD_Home;
begin
LCD_Command($02);
end;
procedure LCD_SetCursor(col, row: byte);
const
Offset: array [0..3] of byte = ($00, $40, $14, $54);
begin
col := LCD_ColsInRange(col);
row := LCD_RowsInRange(row);
LCD_Command($80 or (Offset[row] + col));
end;
procedure LCD_Write(s: LCDStr);
var
i: integer;
begin
for i:=1 to Length(s) do
LCD_WriteData(Ord(s[i]));
end;
procedure LCD_Cursor;
begin
_lcd.Display := _lcd.Display or $02;
LCD_Command(_lcd.Display)
end;
procedure LCD_NoCursor;
begin
_lcd.Display := _lcd.Display and not $02;
LCD_Command(_lcd.Display);
end;
procedure LCD_Blink;
begin
_lcd.Display := _lcd.Display or $01;
LCD_Command(_lcd.Display);
end;
procedure LCD_NoBlink;
begin
_lcd.Display := _lcd.Display and not $01;
LCD_Command(_lcd.Display);
end;
procedure LCD_Display;
begin
_lcd.Display := _lcd.Display or $04;
LCD_Command(_lcd.Display);
end;
procedure LCD_NoDisplay;
begin
_lcd.Display := _lcd.Display and not $04;
LCD_Command(_lcd.Display);
end;
procedure LCD_ScrollDisplayLeft;
begin
LCD_Command($18);
end;
procedure LCD_ScrollDisplayRight;
begin
LCD_Command($1C);
end;
procedure LCD_Autoscroll;
begin
_lcd.EntryMode := _lcd.EntryMode or $01;
LCD_Command(_lcd.EntryMode);
end;
procedure LCD_NoAutoscroll;
begin
_lcd.EntryMode := _lcd.EntryMode and not $01;
LCD_Command(_lcd.EntryMode);
end;
procedure LCD_LeftToRight;
begin
_lcd.EntryMode := _lcd.EntryMode and not $02;
LCD_Command(_lcd.EntryMode);
end;
procedure LCD_RightToLeft;
begin
_lcd.EntryMode := _lcd.EntryMode or $02;
LCD_Command(_lcd.EntryMode);
end;
procedure LCD_CreateChar(loc: byte; data: TChrDef);
var
i: integer;
begin
loc := loc and $07;
LCD_Command($40 or (loc shl 3));
for i:=0 to 7 do
LCD_WriteData(data[i]);
end;
ルーチン
名前 | 定義 | 説明 |
---|---|---|
LCD_Begin | procedure LCD_Begin(Node: LibStr; Cols, Rows: byte; Use5x10: boolean); | LCD の使用を開始します |
LCD_Clear | procedure LCD_Clear; | LCD の 画面をクリアし、カーソルをホームポジションに移動します |
LCD_Home | procedure LCD_Home; | カーソルをホームポジション (左上) へ移動します |
LCD_SetCursor | procedure LCD_SetCursor(col, row: byte); | カーソルの位置を指定します (0 オリジン) |
LCD_Write | procedure LCD_Write(s: LCDStr); | カーソル位置に文字列を表示します |
LCD_Cursor | procedure LCD_Cursor; | カーソルを表示します |
LCD_NoCursor | procedure LCD_NoCursor; | カーソルを非表示にします |
LCD_Blink | procedure LCD_Blink; | カーソルの点滅を開始します |
LCD_NoBlink | procedure LCD_NoBlink; | カーソルの点滅を停止します |
LCD_Display | procedure LCD_Display; | 画面を表示します |
LCD_NoDisplay | procedure LCD_NoDisplay; | 画面を非表示にします |
LCD_ScrollDisplayLeft | procedure LCD_ScrollDisplayLeft; | 画面を 1 文字分左へスクロールします |
LCD_ScrollDisplayRight | procedure LCD_ScrollDisplayRight; | 画面を 1 文字分右へスクロールします |
LCD_Autoscroll | procedure LCD_Autoscroll; | 自動スクロール機能を有効にします |
LCD_NoAutoscroll | procedure LCD_NoAutoscroll; | 自動スクロール機能を無効にします |
LCD_LeftToRight | procedure LCD_LeftToRight; | テキスト表示の向きを左から右に設定します |
LCD_RightToLeft | procedure LCD_RightToLeft; | テキスト表示の向きを右から左に設定します |
LCD_CreateChar | procedure LCD_CreateChar(loc: byte; data: TChrDef); | カスタム文字の字形を指定します。ASCII コード表の 0x00~0x07 の文字を書き替えられます |
Arduino の LiquidCrystal ライブラリにある print()
は実装されていません。print()
には数値表示、書式、基数変換等の機能があります。Write()
はシンプルな文字列出力のみです。
型
名前 | 定義 | 説明 |
---|---|---|
LCDStr | type LCDStr = string[40]; | 文字列出力用 |
TChrDef | type TChrDef = array [0..7] of byte; | カスタム文字の定義用 |
TLCDRec |
type TLCDRec = record Node: LibStr; Cols: byte; Rows: byte; CharSize: byte; Backlight: byte; Display: byte; DispFunc: byte; EntryMode: byte; end; |
ステータス保存用 |
変数
名前 | 定義 | 説明 |
---|---|---|
_lcd | var _lcd: TLCDRec; | ステータス保存用 |
サンプル
冒頭の画像と同じものを出力するサンプルです。
LCDTEST.pas
program LCDTEST;
type
LibStr = string[80];
{$I SYSUTILS.LIB}
{$I IOT.LIB}
{$I LCD.LIB}
const
Monster: TChrDef = ($00, $0E, $1F, $15, $1F, $1F, $15, $00);
Pacman: TChrDef = ($0E, $0F, $1E, $1C, $1E, $0F, $0E, $00);
begin
LCD_Begin('device/i2c_a/27', 16, 2, False); { I2C Address 0x27 / 1602 Display}
LCD_Write('Hello,MSX0world!');
LCD_CreateChar($00, Monster);
LCD_CreateChar($01, Pacman);
LCD_SetCursor(1, 1);
LCD_Write(#$00#$00' '#$00' '#$01);
end.
サンプル例では I2C アドレス が 0x27 の LCD を使っています。お手持ちの LCD の I2C アドレスが判らない場合には I2C スキャナを使って調べてください。
See also:
参考資料
ライブラリを作るにあたって参考にしたサイトです。
- LiquidCrystal (Github)
- Arduino LiquidCrystal I2C library (Github: @fdebrabander)
- 【PIC】I2CでLCDに文字を表示する (rikeden.net)
- Raspberry Pi Python I2C LCD1602表示テスト (jh7ubc.web.fc2.com)
おわりに
簡単に I2C 接続 LCD が使えて便利ですね。
See also: