8x8ドットマトリクスで文字表示

2013-02-23

ドットマトリクスの制御はダイナミック接続の7セグと同じで、8本のカソードのピンでどのラインに表示するかをえらんで、8本のアノードで横1列のどのドットを光らすかを指定する。

dot-matrix

使った部品はOSL641501-ARAというもの。 ピンの説明は第5回 ドットマトリクスLED 第4章 – ダイナミック点灯の仕組みの理解 | Arduino & Android 入門講座、配線は第5回 ドットマトリクスLED 第5章 – 配線図の説明 | Arduino & Android 入門講座に書いてある。

なにをさせようかと、とりあえず電光掲示板でスクロールするもの。 フォントは美咲フォントを使ってます。 配布しているPC-E500 SCRNJPN.FNT 形式とかX11 BDF 形式、TrueType、Ruputer ELISAR10.FNT、FONTX2のフォーマットをまるで知らなかったため、PNGファイルを2値のバイナリデータに変換してソースに埋め込んだ。

メモリが少ないので、あまり長い文章は出せなかった。 フォントも使う文字だけ切り出してる。 小さい画面でも美咲フォントは結構読みやすいけど、それは前後のつながりから文字を推測しているからであって、スクロールしてる状態だとちと辛いね…。

ソース:
/*
8x8 Dot matrix
*/

const uint8_t cathode_pin = 2;
const uint8_t anode_pin = 10;

void clearAnodes() {
for (uint8_t i = 0; i < 8; ++i) {
digitalWrite(anode_pin + i, LOW);
}
}

void showMatrix(const uint8_t* matrix) {
for (uint8_t i = 0; i < 8; ++i) {
uint8_t v = *matrix++;
for (uint8_t j = 0; j < 8; ++j) {
digitalWrite(anode_pin + j, (v & 1) ? HIGH : LOW);
v >>= 1;
}
digitalWrite(cathode_pin + i, LOW);
delayMicroseconds(100);

digitalWrite(cathode_pin + i, HIGH);
//clearAnodes();
}
}

uint8_t buffer[8];
const uint8_t* pattern = buffer;

void setPattern(const uint8_t* p) {
pattern = p;
}

ISR(TIMER2_COMPA_vect) {
showMatrix(pattern);
}

void setup() {
for (int i = 0; i < 8; ++i) {
pinMode(anode_pin + i, OUTPUT);
pinMode(cathode_pin + i, OUTPUT);
}

// f = クロック周波数 / ( 2 * 分周比 * ( 1 + 比較レジスタの値))
// 分周比=32, 比較レジスタの1値=255 -> f = 16000000 / (2 * 32 * 256) = 976 Hz
OCR2A = 255; // 255クロックごとに割り込みをかける
TCCR2B = 0b100; // 分周比を32に設定する
bitWrite(TIMSK2, OCIE2A, 1); // TIMER2を
}

const uint8_t Font[] = {
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // \0
0x00,0x00,0x00,0x92,0x00,0x00,0x00,0x00, // …
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, //  
0x00,0x00,0x00,0x00,0x00,0x80,0x40,0x00, // 、
0x00,0x00,0x00,0x00,0x40,0xa0,0x40,0x00, // 。
0x20,0x7c,0x20,0x3c,0x6a,0xb2,0x64,0x00, // あ
0x00,0x88,0x84,0x82,0x82,0x50,0x20,0x00, // い
0x3c,0x00,0x3c,0x42,0x02,0x04,0x38,0x00, // う
0x2a,0x20,0xf4,0x2a,0x4a,0x48,0xb0,0x00, // が
0x88,0x88,0xbe,0x88,0x88,0x88,0x10,0x00, // け
0x08,0x08,0x7e,0x04,0x24,0x40,0x3c,0x00, // さ
0x20,0x20,0x20,0x20,0x20,0x22,0x1c,0x00, // し
0x08,0xfe,0x18,0x28,0x18,0x08,0x10,0x00, // す
0x24,0x24,0xfe,0x24,0x2c,0x20,0x1e,0x00, // せ
0x2a,0xf0,0x2e,0x40,0x48,0x50,0x8e,0x00, // だ
0x08,0x7e,0x10,0x1c,0x22,0x02,0x1c,0x00, // ち
0x00,0x00,0x00,0x18,0x64,0x04,0x18,0x00, // っ
0x0e,0x74,0x08,0x10,0x10,0x08,0x06,0x00, // て
0x0e,0x74,0x0a,0x10,0x10,0x08,0x06,0x00, // で
0x20,0x20,0x26,0x18,0x20,0x40,0x3e,0x00, // と
0x2a,0x20,0x26,0x18,0x20,0x40,0x3e,0x00, // ど
0x20,0xf4,0x22,0x44,0x9c,0x26,0x18,0x00, // な
0x20,0x2c,0xf2,0x22,0x66,0xaa,0x24,0x00, // ね
0x00,0x38,0x54,0x92,0xa2,0x44,0x18,0x00, // の
0x84,0x84,0xbe,0x84,0x9c,0xa4,0x9a,0x00, // は
0x08,0x7e,0x08,0x7e,0x08,0x7c,0x7a,0x00, // ま
0x70,0x10,0x24,0x7c,0xa6,0xc4,0x18,0x00, // み
0x10,0x7c,0x20,0x7c,0x22,0x22,0x1c,0x00, // も
0x48,0x5c,0xe2,0x24,0x20,0x10,0x10,0x00, // や
0x58,0x64,0x44,0x44,0x04,0x08,0x30,0x00, // り
0x3c,0x08,0x10,0x3c,0x42,0x32,0x3c,0x00, // る
0x10,0x7c,0x20,0x76,0x98,0x28,0x1e,0x00, // を
0x10,0x10,0x20,0x20,0x50,0x52,0x8c,0x00, // ん
0x00,0x00,0x08,0x7c,0x18,0x68,0x18,0x00, // ォ
0x10,0x1e,0x22,0x42,0x04,0x08,0x30,0x00, // ク
0x00,0x7c,0x04,0x08,0x08,0x34,0xc2,0x00, // ス
0x00,0x00,0x00,0x54,0x54,0x08,0x30,0x00, // ッ
0x20,0x20,0x20,0x38,0x24,0x20,0x20,0x00, // ト
0x2a,0x20,0x20,0x38,0x24,0x20,0x20,0x00, // ド
0x00,0x7e,0x02,0x02,0x04,0x08,0x30,0x00, // フ
0x00,0xfe,0x02,0x04,0x28,0x10,0x08,0x00, // マ
0x04,0x04,0x74,0x08,0x14,0x24,0xc0,0x00, // メ
0x3c,0x10,0x10,0x7e,0x10,0x10,0x0e,0x00, // モ
0x44,0x44,0x44,0x44,0x04,0x08,0x30,0x00, // リ
0x08,0x28,0x28,0x28,0x2a,0x4c,0x88,0x00, // ル
0x00,0x7e,0x42,0x42,0x42,0x42,0x7e,0x00, // ロ
0x40,0x20,0x02,0x02,0x04,0x08,0x70,0x00, // ン
0x00,0x00,0x80,0x7e,0x00,0x00,0x00,0x00, // ー
0x28,0x7e,0xda,0x5e,0x78,0x48,0x76,0x00, // 使
0x10,0x54,0x54,0x7c,0x92,0x92,0xfe,0x00, // 出
0x5e,0x4a,0xea,0x4a,0x4a,0x6a,0x16,0x00, // 切
0x14,0xe0,0xbe,0xa8,0xfe,0x08,0x36,0x00, // 咲
0x10,0xfe,0xba,0x08,0xfe,0x10,0x30,0x00, // 字
0x10,0x10,0x54,0x52,0x92,0x10,0x30,0x00, // 小
0x10,0x54,0x52,0x90,0x34,0x18,0xe0,0x00, // 少
0x54,0xf6,0x50,0x74,0x56,0xc8,0xba,0x00, // 態
0x10,0xfe,0x28,0x28,0x10,0x28,0xc6,0x00, // 文
0x54,0xfe,0x54,0xfe,0xdc,0x7e,0x54,0x00, // 構
0x4a,0x48,0xfe,0x48,0xc8,0x54,0x62,0x00, // 状
0xfe,0x10,0xba,0xba,0xba,0x82,0xfe,0x00, // 画
0x7c,0x00,0xfe,0x10,0x54,0x92,0x30,0x00, // 示
0x10,0x7c,0x28,0xfe,0x44,0xfe,0x10,0x00, // 章
0x48,0xbe,0x48,0x9c,0x40,0xdc,0x5c,0x00, // 結
0x24,0xfe,0x7c,0x10,0xfe,0x10,0xee,0x00, // 美
0x10,0x7c,0x10,0xfc,0x2a,0xe4,0x32,0x00, // 表
0x48,0xfe,0x08,0xbe,0x22,0xd4,0xe6,0x00, // 読
0x10,0x7c,0x28,0xfe,0x10,0x7c,0x10,0x00, // 辛
0x3c,0x20,0x38,0x20,0xfe,0x28,0x76,0x00, // 長
0xfe,0x10,0xfe,0xaa,0xba,0xaa,0xfe,0x00, // 面
0x3c,0x42,0x42,0x3c,0x42,0x42,0x3c,0x00, // 8
0x00,0x00,0x44,0x28,0x10,0x28,0x44,0x00, // x
};

const uint8_t Text[] = {
69,70,69,38,36,37,40,37,43,34,35,18,56,52,64,60,2,
39,33,46,37,24,63,51,39,33,46,37,31,48,16,17,25,12,4,2,
41,42,43,8,54,21,6,23,18,3,5,25,29,67,6,56,61,24,49,13,25,13,32,4,2,
39,33,46,37,27,3,48,7,56,52,14,9,50,29,49,11,17,25,12,4,2,
53,10,6,59,68,18,27,63,51,39,33,46,37,24,62,57,65,26,28,12,6,9,20,3,
35,34,45,47,44,11,17,30,58,55,14,19,15,19,66,6,22,1,2,
0
};

void scrollDown(uint8_t* buffer, uint8_t pat) {
memmove(&buffer[1], &buffer[0], 7);
buffer[0] = pat;
}

uint8_t sliceFontPattern(const uint8_t* font, uint8_t bit) {
uint8_t pat = 0;
for (uint8_t i = 0; i < 8; ++i) {
pat = (pat << 1) | ((font[i] >> bit) & 1);
}
return pat;
}

const uint8_t* pstr = Text;
int chr = 0;
uint8_t bit = 0;

void loop() {
uint8_t pat = 0;
if (*pstr != 0) {
uint8_t c = *pstr;
if (0 <= c && c < sizeof(Font)/8) {
pat = sliceFontPattern(&Font[c * 8], 7 - bit);
}
if (++bit >= 8) {
bit = 0;
++pstr;
if (*pstr == 0) {
pstr = Text;
}
}
}
scrollDown(buffer, pat);
setPattern(buffer);
delay(100);
}