
前回の続きです。
スクロール表示の動作検証および、日本語フォントROM GT20L16J1Yを使ってみました。
割り込み処理とSPI通信の併用を心配していましたが、まったく問題なしでした。
動画の"こんにちは埼玉県"は、arduinoのSRAMにあるフォントデータを利用しています。
"色は..."のいろは歌はSPI接続のフォントROM
GT20L16J1Yを参照して文字を
表示しています。
スクロールをちょと速めにしてもちゃんと表示出来ています。
GT20L16J1Yは3.3V駆動なので、CD4050を使って5V -> 3.3Vのレベル調整をしました。

LED表示部は前回と変わらずですが、清書しました。
清書してD9接続の74HC595とTB62706のLATCHのタイミングが違うことに初めて気づきました。
まあ、動作しているのでOKということで..(タイミング的にも大丈夫なはず)。
プロフラムソースはこんな感じです。
//
// TB62706を使ったLEDの点灯サンプル
//
#include <arduino.h>
#include <MsTimer2.h>
#include <string.h>
#include <SPI.h>
///
#define ASC8x16S 255968 // 8x16 ASCII 粗体字符(半角)
#define ASC8x16N 257504 // 8x16 ASCII 日文假名(半角)
#define DATAPIN (7) // TB62706のSERIAL-INへ
#define LATCHPIN (9) // TB62706のLATCHへ
#define CLOCKPIN (8) // TB62706のCLOCKへ
#define ENABLEPIN (6) // TB62706のENABLEへ
uint16_t fbuf[16]; // 表示パターンバッファデータ
byte rowdata[32]; // 漢字ROM読み取り用バッファ
// 文字データ "こんにちは埼玉県"
uint16_t fnt[11][16]= {
{// ""
0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,
0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff },
{// こ
0x0000,0x0000,0x1ff8,0x0000,0x0000,0x0000,0x0000,0x0000,
0x0000,0x0000,0x2000,0x3000,0x1c00,0x07fc,0x0000,0x0000 },
{// ん
0x0200,0x0200,0x0600,0x0400,0x0c00,0x0800,0x0800,0x1b80,
0x1440,0x1840,0x3040,0x2042,0x2046,0x604c,0x4038,0x0000 },
{// に
0x0000,0x1000,0x1000,0x31fc,0x2000,0x2000,0x2000,0x2000,
0x2000,0x2000,0x2200,0x2200,0x2b00,0x31fe,0x1000,0x0000 },
{// ち
0x0100,0x0100,0x0100,0x7ffc,0x0200,0x0600,0x0400,0x0ff0,
0x1808,0x3004,0x0004,0x0004,0x000c,0x0038,0x07e0,0x0000 },
{// は
0x0000,0x2020,0x2020,0x6020,0x47fe,0x4020,0x4020,0x4020,
0x4020,0x4020,0x43e0,0x4438,0x542c,0x6466,0x23c0,0x0000 },
{// 埼
0x2020,0x2020,0x23fe,0x2050,0xf8d8,0x218c,0x2000,0x27ff,
0x2004,0x21e4,0x3924,0x6124,0xc124,0x01e4,0x0004,0x001c},
{// 玉
0x0000,0x7ffe,0x0100,0x0100,0x0100,0x0100,0x0100,0x3ffc,
0x0100,0x0100,0x0118,0x010c,0x0104,0x0100,0xffff,0x0000 },
{// 県
0x07f8,0x2408,0x2408,0x27f8,0x2408,0x2408,0x27f8,0x2408,
0x2408,0x27f8,0x2000,0x3fff,0x0888,0x188c,0x7087,0x0080 },
{// ""
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000 },
{// ""
0xAAAA,0x5555,0xAAAA,0x5555,0xAAAA,0x5555,0xAAAA,0x5555,
0xAAAA,0x5555,0xAAAA,0x5555,0xAAAA,0x5555,0xAAAA,0x5555 }
};
//いろは歌(JISコード文字列)
uint16_t iroha[] = {
0x3f27,0x244f,0x244b,0x245b,0x2458,0x2449,0x3b36,0x246a,//1
0x244c,0x246b,0x2472,0x3266,0x242c,0x4024,0x243f,0x246c,//2
0x243e,0x3e6f,0x244a,0x2469,0x2460,0x4d2d,0x3059,0x244e,//3
0x317c,0x3b33,0x3a23,0x467c,0x315b,0x2428,0x2446,0x4075,//4
0x242d,0x4c34,0x382b,0x2438,0x3f6c,0x2452,0x2462,0x243b,//5
0x243a
};
// 漢字ROM GT20L16J1Y用
// 全角JISコードからフォント格納先頭アドレスを求める
// GT20L16J1Y データシート VER 4.0 2013-3のサンプルを参照した
// (サンプルでは区点コードからの変換であることに注意)
unsigned long calcAddr(unsigned short jiscode) {
unsigned long MSB;
unsigned long LSB;
unsigned long Address;
char buf[32];
// 上位、下位を区点コードに変換
MSB = (jiscode >> 8) - 0x20;
LSB = (jiscode & 0xff) -0x20;
// データ格納アドレスを求める
if(MSB >=1 && MSB <= 15 && LSB >=1 && LSB <= 94)
Address =( (MSB - 1) * 94 + (LSB - 01))*32;
else if(MSB >=16 && MSB <= 47 && LSB >=1 && LSB <= 94)
Address =( (MSB - 16) * 94 + (LSB - 1))*32+43584;
else if(MSB >=48 && MSB <=84 && LSB >=1 && LSB <= 94)
Address = ((MSB - 48) * 94 + (LSB - 1))*32+ 138464;
else if(MSB ==85 && LSB >=0x01 && LSB <= 94)
Address = ((MSB - 85) * 94 + (LSB - 1))*32+ 246944;
else if(MSB >=88 && MSB <=89 && LSB >=1 && LSB <= 94)
Address = ((MSB - 88) * 94 + (LSB - 1))*32+ 249952;
return Address;
}
// 漢字ROM GT20L16J1Y用
// JISコードからキャラクタデータを得る
void getCharData(unsigned short code) {
byte data;
unsigned long addr=0;
byte n;
if (code > 0xFF) {
// 全角
addr =calcAddr(code);
n = 32;
} else {
// 半角
addr = ASC8x16N + (code<<4);
n = 16;
}
digitalWrite(10, HIGH);
//delayMicroseconds(10);
digitalWrite(10, LOW);
SPI.transfer(0x03);
SPI.transfer((addr>>16) & 0xff);
SPI.transfer((addr>>8) & 0xff);
SPI.transfer(addr & 0xff);
SPI.setBitOrder(LSBFIRST);
for(byte i = 0;i< n; i++)
rowdata[i] = SPI.transfer(0x00);
SPI.setBitOrder(MSBFIRST);
digitalWrite(10, HIGH);
}
// 漢字ROM GT20L16J1Y用
// 漢字ROMフォントを表示用形式に変換する
void rowtofont(uint16_t* fnt) {
for (byte i=0; i <16; i++)
fnt[i]=0;
for (byte i=0;i<8;i++)
for (byte j=0; j<16; j++) {
fnt[7-i] |= (rowdata[j] & 0x1<<i ? 0x8000: 0) >>j;
fnt[15-i] |= (rowdata[j+16] & 0x1<<i ? 0x8000: 0) >>j;
}
}
// 漢字ROM GT20L16J1Y用
// JIS漢字コートに対応するフォントデータの取得
//
void loadfontdata(uint16_t *fnt, unsigned short code) {
getCharData(code);
rowtofont(fnt);
}
// 漢字ROM GT20L16J1Y用
// 漢字ROMを参照してフォントを表示する
void test_iroha() {
uint16_t buf[16];
for (int i=0; i <41; i++) {
loadfontdata(buf, iroha[i]);
setfontscl(buf, 25);
}
}
//
// 行の指定
//
void selectRow(byte no) {
uint16_t val = _BV(15-no);
// ビット列データの出力
for( byte i = 0; i < 16; i++ ){
digitalWrite(DATAPIN, val & _BV(i) ? 1:0);
digitalWrite(CLOCKPIN, HIGH);
digitalWrite(CLOCKPIN, LOW);
}
}
//
// 行フォントパターンの送信
//
void dataOut(uint16_t val ) {
for( byte i = 0; i < 16; i++ ){
digitalWrite(DATAPIN, val & _BV(i) ? 1:0);
digitalWrite(CLOCKPIN, HIGH);
digitalWrite(CLOCKPIN, LOW);
}
}
//
// バッファ内データを表示する
//
void fontout() {
// 点灯LEDが移動するパターン
digitalWrite(ENABLEPIN,LOW); // OUTを有効にする
for( byte i = 0; i < 16; i++ ) {
digitalWrite(LATCHPIN, LOW); //送信開始
selectRow(i);
dataOut(fbuf[i]);
digitalWrite(LATCHPIN, HIGH); //送信開始
}
digitalWrite(ENABLEPIN,HIGH); // OUTを有効にする
}
//
// バッファにフォントパターンをセット
//
void setfont(uint16_t* fptr) {
memcpy(fbuf, fptr, 32);
}
//
// バッファ内の指定座標に点をセット
//
void setdot(uint8_t x, uint8_t y, byte dot) {
// uint16_t v = ;
fbuf[y] = dot ? fbuf[y]| (0x8000>>x): fbuf[y] & ~(0x8000>>x);
}
void testdotset() {
for (byte y=0; y<16; y++) {
for (byte x=0; x<16; x++) {
setdot(x,y,1);
delay(10);
}
}
for (byte y=0; y<16; y++) {
for (byte x=0; x<16; x++) {
setdot(x,y,0);
delay(10);
}
}
}
//
// 指定座標にフォントパターンをセット
//
void setfontat(uint16_t* fptr, uint8_t x, uint8_t y) {
uint16_t w;
if (x>15 || y >15)
return;
for (byte j=y,i=0; j < 16; j++,i++)
fbuf[j] = (fbuf[j]>>(16-x))<<(16-x) | fptr[i]>>x;
}
void test01() {
for (byte i=0; i <11; i++) {
for (byte x=15; x > 0; x--) {
setfontat(fnt[i],0,x);
delay(20);
}
}
}
//
// ドット表示チェック(デバッグ用)
//
void dottest() {
for (byte y=10; y < 11;y++)
for (byte x=0;x <16;x++) {
fbuf[y]= 0x8000>>x;
delay(50);
fbuf[y]= 0;
}
}
//
// バッファーデータのスクロール
// h_mode : 0 なし,1 左 ,2 右
// v_mode : 0 なし,1 上, 2 下
//
void scroll(uint8_t h_mode, uint8_t v_mode) {
if (h_mode ==1)
for (byte i = 0; i < 16; i++)
fbuf[i] = fbuf[i]<<1;
if (h_mode ==2)
for (byte i = 0; i < 16; i++)
fbuf[i] = fbuf[i]>>1;
if (v_mode ==1) {
for (byte i = 0; i < 15; i++)
fbuf[i]= fbuf[i+1];
fbuf[15]=0;
}
if (v_mode == 2) {
for (byte i = 15; i >0; i--)
fbuf[i]= fbuf[i-1];
fbuf[0] = 0;
}
}
// スクロールテスト
void test02() {
byte i;
setfont(fnt[6]);
for (i=0; i<16;i++) {
scroll(1,0);
delay(50);
}
delay(200);
setfont(fnt[6]);
for (i=0; i<16;i++) {
scroll(2,0);
delay(50);
}
delay(200);
setfont(fnt[6]);
for (i=0; i<16;i++) {
scroll(0,1);
delay(50);
}
delay(200);
setfont(fnt[6]);
for (i=0; i<16;i++) {
scroll(0,2);
delay(50);
}
delay(200);
setfont(fnt[6]);
for (i=0; i<16;i++) {
scroll(1,1);
delay(50);
}
delay(200);
setfont(fnt[6]);
for (i=0; i<16;i++) {
scroll(2,2);
delay(50);
}
delay(200);
}
//
// スクロールしながらパターンを表示
//
void setfontscl(uint16_t* fptr, uint16_t dly) {
for (byte i=0; i<16; i++) {
scroll(1, 0);
setfontat(fptr, 15-i, 0) ;
delay(dly);
}
}
void setup() {
pinMode(10,OUTPUT);
SPI.begin();
//SPI.setClockDivider(SPI_CLOCK_DIV4);
pinMode(ENABLEPIN,OUTPUT);
pinMode(DATAPIN, OUTPUT);
pinMode(LATCHPIN, OUTPUT);
pinMode(CLOCKPIN, OUTPUT);
digitalWrite(ENABLEPIN,HIGH);
digitalWrite(CLOCKPIN, LOW);
digitalWrite(LATCHPIN, HIGH);
digitalWrite(ENABLEPIN,LOW); // OUTを有効にする
setfont(fnt[9]); // フォントバッファに初期パターン設定
// 割り込み開始
MsTimer2::set(15, fontout); // 1/60秒程度で1文字を表示
MsTimer2::start();
}
void loop(){
test_iroha(); // いろは歌表示(漢字ROM利用)
delay(1000);
test02(); // スクロールテスト
testdotset(); // ドット単位アクセス表示
// 配列格納文字パターンを順番に表示する
for (byte i =0; i < 11; i++)
setfontscl(fnt[i],40);
}
arduinoの文字列がUTF8を使っているのに対して、漢字フォントROMはJISコードなので、
プログラムで「はいろは歌」の文字列をJISコードにて保持して表示しています。
この点はちょっと面倒です。
この対応を模索しています。
「Arduinoで16x16 LEDドットマトリックスを利用する(7)」 に続きます。
関連記事
・Arduinoで16x16 LEDドットマトリックスを利用する(1)
・Arduinoで16x16 LEDドットマトリックスを利用する(2)
・Arduinoで16x16 LEDドットマトリックスを利用する(3)
・Arduinoで16x16 LEDドットマトリックスを利用する(4)
・Arduinoで16x16 LEDドットマトリックスを利用する(5)
・Arduinoで16x16 LEDドットマトリックスを利用する(6) (この記事です)
・Arduinoで16x16 LEDドットマトリックスを利用する(7)
・Arduinoで16x16 LEDドットマトリックスを利用する(8)
再チャレンジ版
・aitendo 16x16LEDマトリックスの制御 (1)
・aitendo 16x16LEDマトリックスの制御 (2)
・aitendo 16x16LEDマトリックスの制御 (3)
・aitendo 16x16LEDマトリックスの制御 (4)
・aitendo 16x16LEDマトリックスの制御 (5)
・ESP-WROOM-02を始めました(2)
最近のコメント