2017-04-13 13:09 | カテゴリ:PIC応用回路
ドットのビットマップデータの表示とスクロールまで出来ました!
次は、ASCIIコードを与えて、文字を表示、スクロールさせたいと思います。

(DTM061)
DMT061.jpg

前回は、あらかじめメモリーにマップしたビットマップのドットデータをLEDに表示し、スクロールする事ができました。



続きは、、、




ACIIコードを与えて、そのASCII文字を表示させようとするには、当然ですが、文字フォントが必要です。
WEBを検索していたら、7x5ドットのASCIIコードに対応したドットフォントがあり、それを使用させていただくことにしました。

ASCII文字の一文字ごとに、8ビットx5のフォントが、そろっています。

そのテキストファイルの内容の一部です。
ちょうど良いことに、XC8で直接読み込んで配列に取り込めるようなフォーマットで提供されています。

{ 0x7e, 0x11, 0x11, 0x11, 0x7e }, // A 0x41
{ 0x7f, 0x49, 0x49, 0x49, 0x36 }, // B 0x42
{ 0x3e, 0x41, 0x41, 0x41, 0x22 }, // C 0x43
..........


早速、このコード表をXC8のプログラムに取り込んで、表示用のバッファーに展開して、表示させてみました。


(DTM07)
DTM07.jpg


おー!
ちゃんとASCIIコードで与えた文字(@マーク)がLEDに表示されました。
あれー??

文字が寝転んでいます(笑)
今回使用させていただいたフォントデータは、5バイトにデータが収められていますが、バイトを縦に積み重ねて8x5を形成するか、横に並べて、形成するかで文字の向きが異なるんです。
つまり、

1バイト目のビット0のデータを、8バイト目のビットゼロに、
1バイト目のビット1のデータを、7バイト目のビットゼロに、、、、

という変換をして、結果的に90度文字を回転させる必要がありました。

WEBで何か既にそういう関数があるかと思っていろいろ探しましたがありません。
仕方がないので、自分で考えることに。

手順としては、上記の様に、元のデータを1ビットづつ変換して行けばよいのですが、なかなかスマートな方法を思い浮かびません。
あれこれ悩んで、何とかその方法を作り、テストしてみました。

(DTM08)
DTM08.jpg


あちゃー!!
どこでどう間違えたのか、今度は逆立ちしてしまいました。
回転方向が逆だったようです。

一部修正して、ようやく完成。

(DTM09)
DTM09.jpg



予想していたよりもシンプルなコードで組むことが出来ました。

その部分がこちらです。



unsigned long mtx_data[9] = 0; //LEDへ展開するデータの保管場所(8x32)
unsigned char buff_data[9] = 0; //回転させたデータを保管

unsigned char send_data = 0;// SPI送信データ
unsigned long carry_flg = 0;// スクロール時のCarry保持用

int FontP, BufP;// フォント回転用変数
unsigned char FontBC, BufBC;// フォント回転用変数



//----------------------
// フォントデータの回転
//----------------------

void Font_Rot(unsigned char Acode) {

FontP = 0;
FontBC = 0b00000001;
BufP = 8;
BufBC = 0b00000001;

for (i = 0; i <= 8; i++) {
buff_data[i] = 0; // buffエリアをクリア
}



Start_Loop:

if ((ASCII_font[Acode][FontP] & FontBC) == 0) {
buff_data[BufP] = buff_data[BufP] & (~BufBC);
} else {
buff_data[BufP] = buff_data[BufP] | (BufBC);
}

FontBC = FontBC << 1;
if (FontBC != 0) {
BufP = BufP - 1;
goto Start_Loop;
}

FontP = FontP + 1;
if (FontP >= 5) return;
BufBC = BufBC << 1;
FontBC = 0b00000001;
BufP = 8;

goto Start_Loop;

}


また、回転させたデータをバッファエリアから表示アリアに順次送り込んでスクロールさせるように修正して、ここまで出来ました。
文字は、「R」です。
ここでは、繰り返しでスクロールするのではなく、スクロールアウトにしています。

(DTM10)




次は、任意の文字列を送り込んで、スクロール表示するプログラムです。

プログラム中で任意の文字列を引数にして、スクロール表示ルーチンを呼び出します。


呼び出しは、


LED_msg("Welcome to VividHobby");


その表示ルーチンはこちら。


//--------------------------------------
// 文字列をスクロール表示する(1回のみ)
//--------------------------------------
void LED_msg(unsigned char *p) {
int n;
int scrl_c;
re_start:
A_code = (*p);
if (A_code == '\0') {
A_code = 0; //スペース
end_flg = 0;
scrl_c = 40;
} else {
if (A_code >= 191) {
A_code = 0;
} else {
A_code = A_code - 0x20;
}
Buff_clear();
Font_Rot(A_code); // フォントを得て、回転後buffにセット
}
for (n = 0; n <= scrl_c; n++) {
LED_disp();
LED_scrl();
//----------------------
// スクロールの速度調整
//----------------------
__delay_ms(20);
Moni_LED = 1;
__delay_ms(20);
Moni_LED = 0;
}
if (end_flg == 0) {
end_flg = 1;
scrl_c = scrl_n;
return;
} else {
p++;
goto re_start;
}
}



まだ、バグがあるかもしれませんが、一応動作します。


(DTM11)




面倒でしたが、制御プログラムが出来ました。
SPI通信も結構高速で、スムースな表示とスクロールが実現できました。
しかし、何故か起動時に、メッセージの最後の文字が最初に表示され、その後は正常に動作しました。


何か変なので、プログラムを見直しました。
おそらく、文字列を渡す際のポインターの初期設定や、受け渡し方に間違いが有るのでは無いかとマニュアルを参照したり、以前のプログラムを見直したりしましたが、わかりません。
いい加減、万策尽きたと、風呂に入って、出て、もう一度見直したら問題点が見えました。


//------------------------------------------
// 文字列をスクロール表示する(文字列の長さ分)
//------------------------------------------

void LED_msg(const char *p) {
int n;
int scrl_c;

re_start:
A_code = *p;
if (A_code == '\0') {
A_code = 0; //スペース
end_flg = 0;
scrl_c = 40;
} else {
if (A_code >= 191) {
A_code = 0;
} else {
A_code = A_code - 0x20;
}

Buff_clear();
Font_Rot(A_code); // フォントを得て、回転後buffにセット


scrl_c = scrl_n; <=== これが無かったので次のfor文の繰り返し回数が不定だった。

}
for (n = 0; n <= scrl_c; n++) {

//LED_disp();
//LED_scrl();

LED_scrl();
LED_disp();

//----------------------
// スクロールの速度調整
//----------------------
__delay_ms(20);
Moni_LED = 1;
__delay_ms(20);
Moni_LED = 0;
}
if (end_flg == 0) {
end_flg = 1;
scrl_c = scrl_n;
return;
} else {
p++;
goto re_start;
}
}





(DTM12)




というわけで、正常動作確認できました。
もっとLEDを増設しても、この速度ならPICで十分ドライブできそうです。



管理者のみに表示する