フォーラム


ゲスト  

ようこそ ゲスト さん。このフォーラムに投稿するには 登録が必要です。

ページ: [1] 2
トピック: TLCD5x7 (LCD コンポーネント)
DEKO
管理者
投稿数: 2690
TLCD5x7 (LCD コンポーネント)
on: 2013/08/03 18:00 Sat

5×7 Matrix LCD を持つ機器に関わるドキュメントを書く場合、LCD の画面そのままで表示された方が解り易いと思います。
…ですが、LCD 画面をドット打ちで作るのは非常に骨が折れる作業であるのも確かです。

そこで、コンポーネントを作って LCD 画面を表示できるようにしてみました。

初期表示で16×2 Character LCD ですが、桁数と行数は任意に変更できます。例えば SHARP の PC-E200 (G801) シリーズは 24×4 Character LCD ですので、以下のような表示になります。

LCD の色も任意に変更できます。標準の配色 (lcdcStandard) の他にもプリセットが用意されています。

[White on Blue (lcdcWhiteOnBlue)]

[White on Black (lcdcWhiteOnBlack)]

[Black on Orange (lcdcBlackOnOrange)]

[Black on White (lcdcBlackOnWhite)]

プリセットに不満があるのであれば、プロパティ (LCDForeColor / LCDBackColor / LCDPanelColor) を変更して、任意の配色にする事ができます。

LCD のフォントは Sunlike Display Technology 社の SC1602B シリーズのものを標準としていますが、フォントを差し替える事もできます。フォント部分は *.inc として外部ファイルにしてありますので、これを差し替えて使います。SHARP PC-E500 から起こしたフォントも作りました。

[Sunlike Display Technology SC1602B (Default)]

[SHARP PC-E500]

微妙に書体が異なります。いずれも ANK (JIS X 0201) 対応ですのでカナ文字も表示できます。

LCD のセル (ドット) の大きさや、セルギャップ (セル間の空白) も指定できます。最小の設定は CellSize=1、CellGap=0 ですが、正直小さすぎて何がなんだか判りません。下の画像は CellSize=2、CellGap=0 です。これが "実用限界の最小" だと思います。

# デフォルトの設定は CellSize=3、CellGap=1 です。

LCD に余白を持たせたい場合には Padding プロパティを設定します。Padding で指定する値はピクセル数ではなくセル数となっています。

  LCD5x7.Padding.Left   := 5;
LCD5x7.Padding.Right := 5;
LCD5x7.Padding.Top := 7;
LCD5x7.Padding.Bottom := 2;

 
このような指定で画像のような余白ができます。OnPaint イベントハンドラを記述すれば、バッテリーマーク等を独自に描画する事も可能です。

文字列の表示は LPrint() または APrint() で行います。

  procedure APrint(address: word; s: TRawString);
procedure LPrint(x, y: Byte; s: TRawString);

 
APrint() は LCD を 0 から連続するアドレスとみなし、address で指定した位置から文字列を書き込みます。例えば、下記のようなコードがあったとします。

  LCD5x7.APrint(0, Memo1.Lines.Text);

 
Memo1 に "ABCDEFG0123456789abcdefg" と入力した場合には以下のようになります。

LPrint() は XY 座標 (0 ベース) を指定して文字列を書き込みます。LCD をクリアするには CLS() メソッドを実行します。
# TRawString は ANSI 版 Delphi の時 AnsiString、
# Unicode 版 Delphi の時 RawByteString となります。

標準では 0×00~0x1F、0×80~0x9F、0xE0~0xFF にはフォント (文字パターン) が割り当てられていませんが、
指定コードに独自にフォントを割り当てる事は可能です。例えば、以下のコードは二行目に市松模様の文字を表示します。

  LCD5x7.SetFontImage($FF, $55, $AA, $55, $AA, $55);
LCD5x7.LPrint(0, 0, '"Hello, world!"');
LCD5x7.LPrint(0, 1, #$FF#$FF#$FF#$FF#$FF);

 

PCG みたいなものですね。可読文字も差し替える事ができますので、(やろうと思えば) 擬似的なグラフィックを表示できない事もありません。

なお、TLCD5x7 は Delphi 2007 ~XE4 でコンパイルできる事を確認しており 64bit にも対応しています。特殊な事は何もやっていないので Delphi 6 とかでもコンパイルできるとは思います。

DEKO
管理者
投稿数: 2690
Re: TLCD5x7 (LCD コンポーネント)
on: 2013/08/03 19:14 Sat

またやっちまった…orz って話ですよ。

ドキュメント書くだけなら、コンポーネントにする必要も、こんなに多機能にする必要もなかった訳でして。ついつい楽しくなって機能を増やしてしまいました。反省はしていますが後悔はしていません (キリッ)

# このコンポーネントを公開するかどうかは未定です。

DEKO
管理者
投稿数: 2690
Re: TLCD5x7 (LCD コンポーネント)
on: 2013/08/03 20:28 Sat

Memo1 の内容をそのまま表示するには、

var
i: Integer;
begin
LCD5x7.CLS;
for i:=0 to Memo1.Lines.Count-1 do
LCD5x7.LPrint(0, i, Memo1.Lines[i]);
end;

 
このようなコードを記述します。

なんかそれっぽい BASIC のコードですね (w

DEKO
管理者
投稿数: 2690
Re: TLCD5x7 (LCD コンポーネント)
on: 2013/08/04 07:47 Sun

表示コストはそんなに高くないようです。Application.ProcessMessages を入れて描画が見えるようにした 10,000 回ループで 7 秒前後でした。コードは以下のような感じになります。

var
i: Integer;
begin
LCD5x7.CLS;
for i:=1 to 10000 do
begin
LCD5x7.APrint(0, IntToStr(i));
Application.ProcessMessages;
end;
end;

 
TLabel での同等のコードだと 5 秒弱でした。

var
i: Integer;
begin
Label1.Caption := '';
for i:=1 to 10000 do
begin
Label1.Caption := IntToStr(i);
Application.ProcessMessages;
end;
end;

 
しかしながら、TLabel の AutoSize を False にして TLCD5x7 と同じサイズにし、フォントを "MS ゴシック 24pt" にしたもので計測したら、7 秒前後になりました (TLCD5x7 の方が 200~300ms 遅い)…許容範囲内ですかね。
 
ちなみに実機 (PC-E500) で、同等の 1,000 回 ループコード (BASIC) を実行したら、大体 20 秒掛かりました。

10:FOR I=1 TO 1000
20:LOCATE 0,0
30:PRINT I
40:NEXT I

 
少なくともポケコン実機の LCD 表示よりは速い (描画コストはほぼ無視できる) ようなので、本来のスクリーンショット用途だけではなく、キャラグラのピコピコゲーム等も作れそうな感じですね。

# たかだか 2.304MHz の SC62015 と比較して悦に入っている訳ではありません。

DEKO
管理者
投稿数: 2690
Re: TLCD5x7 (LCD コンポーネント)
on: 2013/08/04 12:11 Sun

フォント (文字パターン) の格納方法は PC-E500 と似た方式になっています。PC-E500 は 6×8 フォント (可読文字は 5×7 の範囲に収まっています) で、

bit0 □■■■□□
bit1 ■□□□■□
bit2 ■□□■■□
bit3 ■□■□■□
bit4 ■■□□■□
bit5 ■□□□■□
bit6 □■■■□□
bit7 □□□□□□
1 2 3 4 5 6

 
このような配置になっていました (確か)。で、今回 5×7 Matrix なので、

bit0 □■■■□
bit1 ■□□□■
bit2 ■□□■■
bit3 ■□■□■
bit4 ■■□□■
bit5 ■□□□■
bit6 □■■■□
bit7 □□□□□
1 2 3 4 5

 
このような配置にしてあります。縦 7dot なので最上位ビットが無駄ですが、何かの属性ビットとして使えそうです (1 文字あたり 5bit も!)。

SC1602B は、

   b b b b b b b b
i i i i i i i i
t t t t t t t t
7 6 5 4 3 2 1 0
1 □□□□■■■□
2 □□□■□□□■
3 □□□■□□■■
4 □□□■□■□■
5 □□□■■□□■
6 □□□■□□□■
7 □□□□■■■□
8 □□□□□□□□

 
こんな感じです。こちらを採用しなかったのは、見ての通り上位 3bit が無駄だからです (実機ではなく TLCD5x7 で、という意味で)。

[SC1602B データシート]
http://akizukidenshi.com/download/ds/sunlike/SC1602BS-B-XA-GB-K.pdf#page=16

DEKO
管理者
投稿数: 2690
Re: TLCD5x7 (LCD コンポーネント)
on: 2013/08/05 03:01 Mon

フォント (文字パターン) をビットマップで持ってリソースに埋め込む方法も考えましたが、それだと…

1.ビットマップリソースを読み出し
2.ピクセルを判定して描画用文字パターンを生成
3.描画

 
なんて事になります。

最初からフォントを画像として持ってしまうとセルギャップや LCD カラーが設定できません。複数のビットマップをリソースで持つのは得策ではないでしょう。描画用文字パターンをバイナリで RCDATA でリソースに埋め込むというのも考えましたが、可読性が悪いですし差し替えも面倒です。

そこで、フォント指定部分を *.inc にして外部に出し、簡単に差し替えられるようにしてあります。

[uLCD5x7_sc1602b.inc] (一部抜粋)
  // ---------------------------------------------------------------------------
// Sunlike Display Technology SC1602B Series Font
// ---------------------------------------------------------------------------

{ 0x20 - 0x2F }
//SetFontImage($20, $00, $00, $00, $00, $00, False);
SetFontImage($21, $00, $00, $5F, $00, $00, False);
SetFontImage($22, $00, $07, $00, $07, $00, False);
SetFontImage($23, $14, $7F, $14, $7F, $14, False);
SetFontImage($24, $24, $2A, $7F, $2A, $12, False);
SetFontImage($25, $23, $13, $08, $64, $62, False);
SetFontImage($26, $36, $49, $55, $22, $50, False);
SetFontImage($27, $00, $05, $03, $00, $00, False);
SetFontImage($28, $00, $1C, $22, $41, $00, False);
SetFontImage($29, $00, $41, $22, $1C, $00, False);
SetFontImage($2A, $14, $08, $3E, $08, $14, False);
SetFontImage($2B, $08, $08, $3E, $08, $08, False);
SetFontImage($2C, $00, $50, $30, $00, $00, False);
SetFontImage($2D, $08, $08, $08, $08, $08, False);
SetFontImage($2E, $00, $60, $60, $00, $00, False);
SetFontImage($2F, $20, $10, $08, $04, $02, False);

...

 
これなら読みやすいです。このコードは 1,2,4,8…とドットを調べてチマチマ作ったのではなく、一旦画像として描いてそれを取り込んでいます。

[SC1602B]

[PC-E500]

最小の設定は CellSize=1、CellGap=0 ですが、正直小さすぎて何がなんだか判りません。

 
文字パターンの元データを見れば、上の方でこのように書いた理由がなんとなく理解できるかと思います。

この bmp2inc というのが *.inc ジェネレータです。

DEKO
管理者
投稿数: 2690
Re: TLCD5x7 (LCD コンポーネント)
on: 2013/08/11 08:27 Sun

デモアプリケーションができました。

ダウンロードして試す事ができます…バイナリのみですが。
https://ht-deko.minim.ne.jp/software/tlcd5x7_demo.zip

画像では伝わらないと思って書かなかったのですが、"カーソル" も実装してあります (デモアプリではなくコンポーネント側の実装です)。スクショにカーソルは不要な事が多いのですが、調子に乗ってカーソルブリンクまで実装してあります。ブリンク速度は PC-E500 とほぼ同じです (w

デモアプリで使っていないメソッドには "行クリア ClearLine(y: Byte)"、"行削除 DeleteLine(y, n: Byte)"、 "行挿入 InsertLine(y, n: Byte)"、"スクロールアップ ScrollUp(n: Byte)"、"スクロールダウン ScrollDown(n: Byte)" 等があります。フォーム上にあるのは TLCD5x7 のプロパティやメソッドをそのまま出したようなものばかりで、コードらしいコードを書いているのは ”LCD Font” のトコくらいのものです。

# 本来の用途のためだったら
# これだけで充分なのですよねぇ…。

DEKO
管理者
投稿数: 2690
TLCD5x7 ver 0.9.1
on: 2013/08/29 11:06 Thu

コンポーネントが DL できるようになりました。
使用に特に制限はありませんが、商用で使う場合にはゴハンでもおごってください。
http://ht-deko.minim.ne.jp/delphiforum/harahettaware/

[インストール方法]
適当なパッケージに LCD5x7Reg.pas を含めてください。コンポーネントアイコンが登録されない場合には、パッケージに uLCD5x7.dcr を含めてください ($R)。少なくとも Delphi 2007 またはそれ以降へインストール可能です。

DEKO
管理者
投稿数: 2690
TLCD5x7 暫定マニュアル
on: 2013/08/29 11:27 Thu

[BMP2INC]
自分でフォントを作成するのに使います。付属の BMP 画像を適当なペイントツールで編集し、BMP2INC へドラッグ&ドロップして食わせてください。[Generate] ボタンを押すと TLCD5x7 コンポーネント用の *.inc を生成します。

[フォントの切り替え]
デフォルトでは SC1602B (uLCD5x7_sc1602b.inc) のフォントが使われます。フォントを切り替えるには、TLCD5x7 のコンストラクタにある

{$I 'uLCD5x7_sc1602b.inc'}

 
を書き換えます。実行時にフォントが切り替えられるようにするメリットは殆どないので、コンポーネントに差し替え機構はありませんが、

procedure TForm1.ComboBox1Change(Sender: TObject);
begin
case ComboBox1.ItemIndex of
1:begin
with LCD5x7 do
begin
{$I 'uLCD5x7_e500.inc'}
end;
end;
else
with LCD5x7 do
begin
{$I 'uLCD5x7_sc1602b.inc'}
end;
end;
LCD5x7.GenerateFont;
LCD5x7.InValidate;
end;

 
このようなコードで切り替える事は可能です。

[プロパティ]

property CellGap: Byte read FCellGap write SetCellGap;

セルとセルの間隔です。0 に設定する事もできます。
property CellSize: Byte read FCellSize write SetCellSize;

セル (ドット) のサイズです。
property CursorPos: TLCDCursorPos read FLCDCursorPos write SetCursorPos;

カーソル位置です (X/Y)。
property CursorType: TLCDCursorType read FLCDCursorType write SetCursorType;

カーソルの種類です。
・lcduUnderline: アンダーライン
・lcduDoubleUnderLine: 二重アンダーライン
・lcduFullMark: 四角形
・lcduFullSpace: スペース
・lcduInsert: 三角
property CursorBlink: Boolean read FLCDCursorBlink write SetCursorBlink;

カーソルを点滅表示するかどうかです。
property LCDBackColor: TColor read FLCDBackColor write SetLCDBackColor;

LCD の文字の背景色です。
property LCDColor: TLCDColor read FLCDColor write SetLCDColor;

LCD 色です (プリセット)。
・lcdcCustom: LCDForeColor, LCDBackColor, LCDPanelColor をいじるとコレになります。
・lcdcStandard: 通常の緑色 LCD です。
・lcdcWhiteOnBlue: 青地に白文字の LCD です。
・lcdcWhiteOnBlack: 黒地に白文字の LCD です。
・lcdcBlackOnOrange: オレンジ地に黒文字の LCD です。
・lcdcBlackOnWhite: : 白地に黒文字の LCD です。
property LCDColumns: Byte read FLCDColumns write SetLCDColumns;

LCD の桁数です。
property LCDForeColor: TColor read FLCDForeColor write SetLCDForeColor;

LCD の文字色です。
property LCDPanelColor: TColor read FLCDPanelColor write SetLCDPanelColor;

LCD のパネルの色です。
property LCDRows: Byte read FLCDRows write SetLCDRows;

LCD の行数です。
property Padding: TPadding read FPadding write SetPadding;

LCD の余白です。
単位はピクセルではなく "セル数" です。
property ShowCursor: Boolean read FShowCursor write SetShowCursor;

カーソルを表示するかどうかです。
property Bitmap: TBitmap read GetBitmap;

読み取り専用の Bitmap プロパティです。
現在描画されている LCD を Bitmap に保持します。
property Canvas;
OnPaint イバントハンドラ等で使うための Canvas です。

 
[メソッド]

procedure APrint(address: word; const s: TRawString);

文字 s を address で指定した位置から表示します。
address は左上から 0, 1 ,2 ...LCDColumns*LCDRows-1 となります。
最大桁をはみ出した分は折り返されます。
procedure ClearLine(y: Byte);

y で指定した行をクリアします。
procedure ClearScreen;

LCD をすべてクリアします。
procedure DeleteLine(y: Byte; n: Byte);

y で指定した行から n 行を削除します。
削除された行は詰められます。
procedure GenerateFont(aIndex: Byte); overload;

aIndex で指定したコードのフォントイメージを実際に生成します。
procedure GenerateFont; overload;

カーソルイメージとフォントイメージを実際に生成します。
procedure InsertLine(y: Byte; n: Byte);

y で指定した行から n 行を挿入します。
procedure LPrint(x, y: Byte; const s: TRawString);

文字 s を (X, Y) で指定した座標に表示します。
最大桁をはみ出した分は無視されます。
procedure ScrollUp(n: Byte);

n 行スクロールアップします。
スクロールアウトした文字列は ScrollDown() しても描画されません。
procedure ScrollDown(n: Byte);

n 行スクロールダウンします。
スクロールアウトした文字列は ScrollUp() しても描画されません。
procedure SetCursorImage(aCursor: TLCDCursorType; Image1, Image2, 
Image3, Image4, Image5: Byte; Generate: Boolean = True);

aCursor で指定したカーソルのイメージを設定します。
既存のカーソルを任意のイメージで書き換える事ができます。
Generate が False だとイメージが生成されません。
procedure SetFontImage(aIndex: Byte; Image1, Image2, 
Image3, Image4, Image5: Byte; Generate: Boolean = True);

aIndex で指定したコードのフォントイメージを設定します。
既存の文字フォントを任意のイメージで書き換える事ができます。
Generate が False だとイメージが生成されません。
フォント書き換えが大量に行われる場合にはここを False にしておき、
最後に GenerateFont() で一気に作成すると効率的です。

 
[FAQ]
Q: TLCD5x7 がちらつくのですが?
A: TPaintBox のちらつき防止同様、親コンポーネント (或いはフォーム) の DoubleBuffered プロパティを True に設定してください。

Q: Unicode に対応していますか?
A: えーと、5×7 LCD で Unicode が表示できるものを見た事がないのですが。TLCD5x7 は ANK 表示用です。

Q: 漢字は表示できないのですか?
A: …えーと (以下略)

Q: バッテリーマークとかは表示できないのですか?
A: Padding を適切に設定し、OnPaint イベントハンドラ内で自前で描画してください。

LCDForeColor と LCDBackColor の色で描画すればそれっぽくできます。

Q: SetCursorImage() / SetFontImage() の Image1..Image5 って何?
A: こういう事です。

bit0 □■■■□
bit1 ■■■■■
bit2 ■□■□■
bit3 ■■■■■
bit4 ■■■■■
bit5 ■□■□■
bit6 □□□□□
bit7 □□□□□
1 2 3 4 5

 
5×7 なので bit7 の部分は描画されません。これをコードで書くと以下のようになります。

Lcd5x7.SetFontImage($41, $3E, $1B, $3F, $1B, $3E, True);

 
$41='A' の ASCII コードなので、'A' のフォントが書き換えられます。

DEKO
管理者
投稿数: 2690
TLCD5x7 ver 0.9.2
on: 2013/10/15 13:36 Tue

TLCD5x7 ver 0.9.2 をリリースしました。

  • コンポーネント登録用 LCD5x7Reg.pas の記述がおかしかったのを修正。
  • PC-E200 (PC-G801) フォントを同梱

※ 続きは ↓ の [2] をクリック。

ページ: [1] 2
WP Forum Server by ForumPress | LucidCrew
バージョン: 1.7.5 ; ページロード: 0.061 sec.