Update: Sep. 22, 2018
有機EL (OLED)をPICマイコンで制御
秋月から販売されている64x128dotの有機EL (OLED ) をPICマイコンで制御する実験を行いましたで紹介します。
回路図
64x128dot OLED と ドライバIC SSD1306
今回試用したSSD1306内蔵のOLEDモジュールは I2Cで制御を行います。色の制御は出来ず、白色の発光のみとなりますが、明るさの制御は出来ます。
チャージポンプが内蔵されており、OLEDの駆動に必要な7.5Vが内部で生成されるため、モジュールとしては3.3Vの単一電源で使用できます。
また、Aitendo や Amazon などでも似たようなモジュールが販売されており、上部のSegmentだけ黄色で発光する物もあるようです。
ただ、秋月の物とは電源とグランドのピン配が逆になっていたりしますので注意して下さい。
SSD1306は64x128dot のOLED を縦方向にPage 0~7, 横方向に Segment0~127
で制御します。
各Segmentは縦に8dot (1byte、上がLSB) となっています。
表示データをI2CでSSD1306 のGDDRAM へSegment単位(1byte)で書込むことによりOLEDに表示されますが、書込んだGDDRAMの内容を読み出すことは出来ません。
同じSegment内に前のデータは保持したまま、別のデータを書込もうとした場合、一旦GDDRAMのデータを読出して新たなデータとORをとり、再びGDDRAMへ書き戻す必要がありますが、SSD1306の場合は新しいデータを上書きすることしか出来ません。
これを回避するため、Arduino などのプログラムではGDDRAMと同じサイズのメモリー
( 7pagex128seg=1kbye)をマイコンのSRAMに確保してSRAM上で表示データを加工してからSSD1306のGDDRAMへ転送するというようなことをやっているようです。
ところが、PIC16F1827などのミドルレンジのPICマイコンではSRAMは256byte程度しか搭載されていませんので、このような手法は使えません。
(最近は、PIC16F18326 など SRAMが2kバイトも搭載されているものもリリースされているようですが。ハイエンドのPICとの差が無くなってきていますネ)
ただ、画面の表示デザインが絶えず変わるアプリケーションで無ければ、画面の配置を工夫すればなんとかなりますので、今回はPIC16F1827を使って制御してみることにしました。
SSD1306の制御プログラム
SSD1306 の I2C フォーマットは以下のようになっています。
SSD1306のスレーブアドレスは 0x78 です。(Arduino ではこれを 0x3Cと表現しているようです。R/W#の部分をアドレスと見るかどうかの違いです。)
Co は仕様書では Continuation bit と表現されていますが、どうもこの意味が判りにくい説明になっています。
このビットの意味は、 Co を 0 とすると以後、連続して1バイトづつ送ることが出来るようになります。
Co を 1 にすると1バイト送るごとにストップコンディションを入れて再びスレーブアドレスから送る必要があります。
Co=0のとき、D/C# を 0 とすると次から順次送る1バイトづつはコマンドを意味します。
Co=0のとき、D/C# を 1 とすると次から順次送る1バイトづつは表示データとしてGDDRAMへ書込まれていきます。
OLED (実際には SSD1306のGDDRAM)へのデータ書込みにはページ内のSegmentへ順番に書込むPage
addressing mode、水平方向へ順番にSegmentへ書込む Horizontal addressing
mode、垂直方向へ順番にSegmentへ書込む Vartical addressing mode があります。
Page Addressing Mode
Horizontal Addressing Mode
Vertical Addressing Mode
今回のプログラムでは、基本的にPage addressing mode を使用していますが、OLEDクリア関数には
Horizontal addressing mode を使っています。
Page addressing mode ではSSD1306のGDDRAMへ1バイトずつ表示データを書き込んでゆくと自動的にSegment (上の図ではCOLと表現されています)順に書込まれます。
最後のSegment127 (COL127)に達すると同じページ内の初めのSegmentへ戻ります。
Horizontal addressing mode では1バイトずつ水平方向に順番にSegmentへ書込まれ、Segment127
(COL127)に達すると次のページの最初のSegmentに自動的に移動して行き、表示エリアを最後まで書替えます。
今回のプログラムで表示するフォントは、6x8ドットのものと12x16ドットのものです。(隣接文字とのスペースも含めたドット数となっています)
6x8ドットフォントは、1ページ内で文字を表示しますので、かなり小さい表示となります。
12x16ドットフォントは、2ページにまたがり表示します。
例として’4’の場合のドット配置を示します。
6x8 ドットフォント
配列データ { 0x18, 0x14, 0x12, 0x7f, 0x10, 0x00 },
12x16ドットフォント
配列データ {0x00, 0x00, 0x00, 0x80, 0xC0, 0x60, 0x30, 0x18, 0xFC, 0xFC,
0x00, 0x00, 0x00, 0x0E, 0x0F, 0x0D, 0x0C, 0x0C, 0x0C, 0x0C, 0x3F, 0x3F,
0x0C, 0x00},
12x16ドットフォントは上半分を nページに表示し、下半分をn+1ページに表示します。
最初に上半分のデータ (12バイト)を転送し、次に下半分のデータ (12バイト)を転送します。
フォントデータはデータサイズが大きいので、データに const修飾子を付けることにより読出し専用のデータとしてプログラムメモリーへ配置しています。
プログラムメモリーへのデータの配置は、実際には RETLW命令としてプログラムの形で書込まれます。
文字列は、printf 関数で表示できるように、プログラムの最後にprintf 関数で使用するpuchを定義してあります。
制御プログラムのソースリスト
/******************************************************************
OLED Ver 0.0
I2C 接続 OLED テスト
Author JR3TGS
I2Cモジュールは、SSP1を使用
XC8 Ver 1.30
PIC16F1827
Sep. 9, 2018
********************************************************************/
/*
秋月 OLED(64 x 128 dot)は 原点を左上 (0,0)として縦方向に Page 0?7, 横方向に Column 0?127。
(1columnは縦方向に8bit (上がLSB))
このソフトウェアでは、OLEDをPage addressing mode で動作させるので、データ書込みに従いcolumn方向
に自動的にインクルメントされ、同Page内でcolumnゼロに戻り、表示を繰り返す。
(ただし oled_clr()関数, oled_fill()関数は Horizontal addressing mode で動作する)
6x8dotフォントは、1Page 内での表示。12x16dotフォントは2Pageにまたがり、フォントの上半分を
n Pageに表示、フォントの下半分を n+1 Page に表示する。
*/
#include <xc.h>
#include <stdio.h>
#include "font6.h"
#include "font12.h"
#define _XTAL_FREQ 16000000
#pragma config CPD = OFF, BOREN = OFF, IESO = OFF, FOSC = INTOSC, FCMEN = OFF
#pragma config MCLRE = ON, WDTE = OFF, CP = OFF, PWRTE = ON, CLKOUTEN = OFF
#pragma config PLLEN = OFF, WRT = OFF, STVREN = OFF, BORV = LO, LVP = OFF
void i2c_start();
void i2c_stop();
void i2c_write(unsigned char byte);
void font6_posi(unsigned char page, unsigned char column); // 5x8dotフォントの表示開始位置指定
void font12_posi(unsigned char page, unsigned char column); // 12x16dotフォントの表示開始位置指定
void chr5(unsigned char c); // 5x8dotフォントの1文字表示関数
void chr12(unsigned char c); // 12x16dotフォントの1文字表示関数
void oled_ini(void); // OLED イニシャライズ
void oled_clr(void); // OLED 画面消去
void h_line(unsigned char page, unsigned char start_column, unsigned char end_column, unsigned x_position); // 水平線描画
void v_line(unsigned char page, unsigned char column, unsigned char pattern); // 垂直線描画
void sig_bar(unsigned char sig_strong); // Signalバー表示
unsigned char Page;
unsigned char Column;
unsigned char Low_col;
unsigned char Hi_col;
unsigned char Size;
//************* h_line (水平線描画用 1columnデータ配列 ) ************************
char line[8] = {0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80};
// 0x01はcolumnの1番上(LSB)にだけdot表示、0x80はColumnの1番下(MSB)にだけdot表示
//************ sig (Signalバー用 1columnデータ配列 6x8dot) **********************
char sig[2][6] =
{
{0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00},
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00}
};
//********************************************************************************
void main(void)
{
unsigned char i;
unsigned char j;
TRISA = 0b00000000;
TRISB = 0b00010010; // SCL, SDA input (I2C(SSP1モジュール)使用するので入力に設定必要)
PORTA = 0b00000000;
PORTB = 0b00000000;
ANSELA = 0b00000000;
ANSELB = 0b00000000;
OSCCON = 0b01111100; // INTOSC 16MHz
SSP1CON1 = 0b00101000; // I2C master mode, Clock 100kHz = Fosc / ( 4 * (SSPADD + 1 ))
SSP1STAT = 0b00000000; // Slew rate control Enabled
SSP1ADD = 0b00100111; // SSPADD 39d, Clock = Fosc / ( 4 * (SSPADD + 1 )) = 100kHz
oled_ini();
oled_clr();
font6_posi(1, 70);
printf("12.34 [V]");
font12_posi(3, 4);
printf("50.2346MHz");
font6_posi(6, 0);
printf("ABCDEFGHIJklmnopqrstu");
//枠の表示
h_line(2, 2, 125, 7); //上の横線
h_line(5, 2, 125, 0); //下の横線
h_line(3, 1, 1, 0); //左上隅
v_line(3, 0, 0xFE);
h_line(4, 1, 1, 7); //左下隅
v_line(4, 0, 0x7F);
h_line(3, 126, 126, 0); //右上隅
v_line(3, 127, 0xFE);
h_line(4, 126, 126, 7); //右下隅
v_line(4, 127, 0x7F);
//Signalバーの表示
for(i=0; i<2; i++)
{
for(j=14; j>0; j--)
{
sig_bar(j);
__delay_ms(200);
}
for(j=0; j<15; j++)
{
sig_bar(j);
__delay_ms(200);
}
}
while(1)
{
PORTAbits.RA0 = 1;
for(j=5; j<10; j++)
sig_bar(j);
PORTAbits.RA0 = 0;
for(j=9; j>4; j--)
sig_bar(j);
}
}// main
//*************************************************************************************
void oled_ini(void) // OLED イニシャライズ
{
i2c_start();
i2c_write(0x78); // OLED slave address
i2c_write(0x00); // Control byte Co=0, D/C#=0
// Co=0 とすると以後連続して1バイトづつ送れる
// Co=1 とすると1バイト送る毎にControl byte を入れる必要がある
i2c_write(0x8D); // Set charge pump
i2c_write(0x14); // Enable charge pump
i2c_write(0xAF); // Display ON
i2c_stop();
// その他の初期設定値はパワーオンリセット時のディフォルト値のままとする
}
void oled_clr(void) // OLED 画面消去
{
unsigned int i;
i2c_start();
i2c_write(0x78); // OLED slave address
i2c_write(0x00); // Control byte Co=0, D/C#=0
i2c_write(0x20); // Set memory addressing mode
i2c_write(0x00); // Horizontal addressing mode
i2c_write(0x21); // Set column address
i2c_write(0x00); // Column start address 0
i2c_write(0x7F); // Column end address 127d
i2c_write(0x22); // Set page address
i2c_write(0x00); // Page start address 0
i2c_write(0x07); // Page end address 7d
i2c_stop();
i2c_start();
i2c_write(0x78); // OLED slave address
i2c_write(0x40); // Control byte Co=0, D/C#=1 (The following data bytes are stored at the GDDRAM)
for(i=0; i<1024; i++) // 128culomn * 8page
i2c_write(0x00); // filled with 0 (OLED clear)
i2c_stop();
}
void h_line(unsigned char page, unsigned char start_column, unsigned char end_column, unsigned x_position) // 水平線描画
{ // x_position はカラム上のdotを表示するビット位置
//(一番上がLSBで0, 一番下がMSBで7)
char low_col;
char hi_col;
char i;
i = end_column - start_column;
page = page + 0xB0; // ページ情報をコマンドにする為に 0xB0 を加算
low_col = start_column & 0x0F;
start_column = start_column >> 4;
hi_col = start_column + 0x10;
i2c_start();
i2c_write(0x78); // OLED slave address
i2c_write(0x00); // Control byte Co=0, D/C#=0
i2c_write(0x20); // Set memory addressing mode
i2c_write(0x02); // Page addressing mode
i2c_write(page); // Set page start addres
i2c_write(low_col);// Set lower column start address
i2c_write(hi_col); // Set higher column start address
i2c_stop();
i2c_start();
i2c_write(0x78); // OLED slave address
i2c_write(0x40); // Control byte Co=0, D/C#=1 (The following data bytes are stored at the GDDRAM)
do
{
i2c_write(line[x_position]);
}
while(i--);
i2c_stop();
}
void v_line(unsigned char page, unsigned char column, unsigned char pattern) // 垂直線描画
{ // pattern はカレントページ内で表示する垂直線のパターン
//(一番上がLSB。 pattern 0x1E なら 上から2番目のビットから上から5番目のビットまでdot表示)
char low_col;
char hi_col;
page = page + 0xB0; // ページ情報をコマンドにする為に 0xB0 を加算
low_col = column & 0x0F;
column = column >> 4;
hi_col = column + 0x10;
i2c_start();
i2c_write(0x78); // OLED slave address
i2c_write(0x00); // Control byte Co=0, D/C#=0
i2c_write(0x20); // Set memory addressing mode
i2c_write(0x02); // Page addressing mode
i2c_write(page); // Set page start addres
i2c_write(low_col);// Set lower column start address
i2c_write(hi_col); // Set higher column start address
i2c_stop();
i2c_start();
i2c_write(0x78); // OLED slave address
i2c_write(0x40); // Control byte Co=0, D/C#=1 (The following data bytes are stored at the GDDRAM)
i2c_write(pattern);
i2c_stop();
}
void font6_posi(unsigned char page, unsigned char column) // 6x8dotフォントの表示開始位置指定
{
char low_col;
char hi_col;
Size = 0; // printf で使用するputch のフォントサイズ指定
Page = page; // ページ情報をfont12用にグローバル変数に保存しておく
Column = column; // カラム情報をfont12用にグローバル変数に保存しておく
page = page + 0xB0; // ページ情報をコマンドにする為に 0xB0 を加算
low_col = column & 0x0F;
column = column >> 4;
hi_col = column + 0x10;
i2c_start();
i2c_write(0x78); // OLED slave address
i2c_write(0x00); // Control byte Co=0, D/C#=0
i2c_write(0x20); // Set memory addressing mode
i2c_write(0x02); // Page addressing mode
i2c_write(page); // Set page start addres
i2c_write(low_col);// Set lower column start address
i2c_write(hi_col); // Set higher column start address
i2c_stop();
}
void font12_posi(unsigned char page, unsigned char column) // 12x16dotフォントの表示開始位置指定
{
char low_col;
char hi_col;
Size = 1; // printf で使用するputch のフォントサイズ指定
Page = page; // ページ情報をfont12用にグローバル変数に保存しておく
Column = column; // カラム情報をfont12用にグローバル変数に保存しておく
page = page + 0xB0; // ページ情報をコマンドにする為に 0xB0 を加算
low_col = column & 0x0F;
column = column >> 4;
hi_col = column + 0x10;
i2c_start();
i2c_write(0x78); // OLED slave address
i2c_write(0x00); // Control byte Co=0, D/C#=0
i2c_write(0x20); // Set memory addressing mode
i2c_write(0x02); // Page addressing mode
i2c_write(page); // Set page start addres
i2c_write(low_col);// Set lower column start address
i2c_write(hi_col); // Set higher column start address
i2c_stop();
}
void chr6(unsigned char c) // 6x8dotフォントの1文字表示関数
{
unsigned char i;
c = c - 0x20;
i2c_start();
i2c_write(0x78); // OLED slave address
i2c_write(0x40); // Control byte Co=0, D/C#=1 (The following data bytes are stored at the GDDRAM)
for(i=0; i<6; i++)
{
i2c_write(font6[c][i]);
}
i2c_stop();
}
void chr12(unsigned char c) // 12x16dotフォントの1文字表示関数
{
unsigned char i;
unsigned char temp;
c = c + 6 - 0x30;
Page = Page + 0xB0;
Low_col = Column & 0x0F;
temp = Column >> 4;
Hi_col = temp + 0x10;
i2c_start();
i2c_write(0x78); // OLED slave address
i2c_write(0x00); // Control byte Co=0, D/C#=0
i2c_write(0x20); // Set memory addressing mode
i2c_write(0x02); // Page addressing mode
i2c_write(Page); // Set page start addres
i2c_write(Low_col);// Set lower column start address
i2c_write(Hi_col); // Set higher column start address
i2c_stop();
i2c_start();
i2c_write(0x78); // OLED slave address
i2c_write(0x40); // Control byte Co=0, D/C#=1 (The following data bytes are stored at the GDDRAM)
for(i=0; i<12; i++)
{
i2c_write(font12[c][i]);
}
i2c_stop();
Page = Page + 1; // グローバル変数ペーシ情報 Page を次の lower 12bytes 描画の為に 1 進める
i2c_start();
i2c_write(0x78); // OLED slave address
i2c_write(0x00); // Control byte Co=0, D/C#=0
i2c_write(0x20); // Set memory addressing mode
i2c_write(0x02); // Page addressing mode
i2c_write(Page); // Set page start addres
i2c_write(Low_col);// Set lower column start address
i2c_write(Hi_col); // Set higher column start address
i2c_stop();
i2c_start();
i2c_write(0x78); // OLED slave address
i2c_write(0x40); // Control byte Co=0, D/C#=1 (The following data bytes are stored at the GDDRAM)
for(i=12; i<24; i++)
{
i2c_write(font12[c][i]);
}
i2c_stop();
Page = Page - 1 - 0xB0; // グローバル変数ページ番号 Page を次の1文字描画の為、進めたページ番号を元に戻す (0xB0はコマンドをページ情報に戻す為)
Column = Column + 12; // グローバル変数カラム情報を次の次の1文字描画の為、12アドレス進める
}
void sig_bar(unsigned char sig_strong) // Signalバー表示 ( Sig_strong の範囲は 0 ? 14 )
{
unsigned char i;
unsigned char j;
i2c_start(); // Signal bar 書込みアドレスリセット (page 7, column 30d)
i2c_write(0x78); // OLED slave address
i2c_write(0x00); // Control byte Co=0, D/C#=0
i2c_write(0x20); // Set memory addressing mode
i2c_write(0x02); // Page addressing mode
i2c_write(0xB7); // Set page start addres : page 7
i2c_write(0x0E); // Set lower column start address : column 30d (0x1E)
i2c_write(0x11); // Set higher column start address
i2c_stop();
if(sig_strong == 0) // Signal レベル 0 の時の処理
{
i2c_start(); // Signal bar 全消去
i2c_write(0x78); // OLED slave address
i2c_write(0x40); // Control byte Co=0, D/C#=1 (The following data bytes are stored at the GDDRAM)
for(i=0; i<15; i++)
{
for(j=0; j<6; j++)
{
i2c_write(sig[1][j]); // Signal bar にブランク書込み
}
}
i2c_stop();
}
else // Signal レベル 1 以上の場合
{
for(i=0; i<sig_strong; i++) // Signal bar 書込み
{
i2c_start();
i2c_write(0x78); // OLED slave address
i2c_write(0x40); // Control byte Co=0, D/C#=1 (The following data bytes are stored at the GDDRAM)
for(j=0; j<6; j++)
{
i2c_write(sig[0][j]); // Signal bar 書込み
}
}
for(i=sig_strong; i<15; i++)
{
for(j=0; j<6; j++)
{
i2c_write(sig[1][j]); // 表示レベルより上のエリアに Signal bar をブランク書込み、表示レベルより上のエリアを消去する
}
}
i2c_stop();
}
}
void i2c_start()
{
SSP1CON2bits.SEN = 1;
while(SSP1CON2bits.SEN);
}
void i2c_stop()
{
SSP1CON2bits.PEN = 1;
while(SSP1CON2bits.PEN);
}
void i2c_write(unsigned char byte)
{
PIR1bits.SSP1IF = 0;
SSP1BUF = byte;
while(!PIR1bits.SSP1IF);
SSP1CON1bits.CKP = 1;
}
//********* printfで使用するputchの定義 ***********
void putch(unsigned char c)
{
if(Size)
{
if(c==0x20)
c = 0x2A; // " "
if(c==0x2E) // .
c = 0x2B;
if(c==0x48) // H
c = 0x2C;
if(c==0x4D) // M
c = 0x2D;
if(c==0x6B) // k
c = 0x2E;
if(c==0x7A) // z
c = 0x2F;
chr12(c);
}
else
chr6(c);
}
//*************************************************
//******************** font6 (6x8dotフォント) ***********************
const char font6[91][6] =
{
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // " " 0x20
{ 0x00, 0x00, 0x4f, 0x00, 0x00, 0x00 }, // ! 0x21
{ 0x00, 0x07, 0x00, 0x07, 0x00, 0x00 }, // " 0x22
{ 0x14, 0x7f, 0x14, 0x7f, 0x14, 0x00 }, // # 0x23
{ 0x24, 0x2a, 0x7f, 0x2a, 0x12, 0x00 }, // $ 0x24
{ 0x23, 0x13, 0x08, 0x64, 0x62, 0x00 }, // % 0x25
{ 0x36, 0x49, 0x55, 0x22, 0x50, 0x00 }, // & 0x26
{ 0x00, 0x05, 0x03, 0x00, 0x00, 0x00 }, // ' 0x27
{ 0x00, 0x1c, 0x22, 0x41, 0x00, 0x00 }, // ( 0x28
{ 0x00, 0x41, 0x22, 0x1c, 0x00, 0x00 }, // ) 0x29
{ 0x14, 0x08, 0x3e, 0x08, 0x14, 0x00 }, // * 0x2A
{ 0x08, 0x08, 0x3e, 0x08, 0x08, 0x00 }, // + 0x2B
{ 0x00, 0x50, 0x30, 0x00, 0x00, 0x00 }, // , 0x2C
{ 0x08, 0x08, 0x08, 0x08, 0x08, 0x00 }, // - 0x2D
{ 0x00, 0x60, 0x60, 0x00, 0x00, 0x00 }, // . 0x2E
{ 0x20, 0x10, 0x08, 0x04, 0x02, 0x00 }, // / 0x2F
{ 0x3e, 0x51, 0x49, 0x45, 0x3e, 0x00 }, // 0 0x30
{ 0x00, 0x42, 0x7f, 0x40, 0x00, 0x00 }, // 1 0x31
{ 0x42, 0x61, 0x51, 0x49, 0x46, 0x00 }, // 2 0x32
{ 0x21, 0x41, 0x45, 0x4b, 0x31, 0x00 }, // 3 0x33
{ 0x18, 0x14, 0x12, 0x7f, 0x10, 0x00 }, // 4 0x34
{ 0x27, 0x45, 0x45, 0x45, 0x39, 0x00 }, // 5 0x35
{ 0x3c, 0x4a, 0x49, 0x49, 0x30, 0x00 }, // 6 0x36
{ 0x01, 0x71, 0x09, 0x05, 0x03, 0x00 }, // 7 0x37
{ 0x36, 0x49, 0x49, 0x49, 0x36, 0x00 }, // 8 0x38
{ 0x06, 0x49, 0x49, 0x29, 0x1e, 0x00 }, // 9 0x39
{ 0x00, 0x36, 0x36, 0x00, 0x00, 0x00 }, // : 0x3A
{ 0x00, 0x56, 0x36, 0x00, 0x00, 0x00 }, // ; 0x3B
{ 0x08, 0x14, 0x22, 0x41, 0x00, 0x00 }, // < 0x3C
{ 0x14, 0x14, 0x14, 0x14, 0x14, 0x00 }, // = 0x3D
{ 0x00, 0x41, 0x22, 0x14, 0x08, 0x00 }, // > 0x3E
{ 0x02, 0x01, 0x51, 0x09, 0x06, 0x00 }, // ? 0x3F
{ 0x32, 0x49, 0x79, 0x41, 0x3e, 0x00 }, // @ 0x40
{ 0x7e, 0x11, 0x11, 0x11, 0x7e, 0x00 }, // A 0x41
{ 0x7f, 0x49, 0x49, 0x49, 0x36, 0x00 }, // B 0x42
{ 0x3e, 0x41, 0x41, 0x41, 0x22, 0x00 }, // C 0x43
{ 0x7f, 0x41, 0x41, 0x22, 0x1c, 0x00 }, // D 0x44
{ 0x7f, 0x49, 0x49, 0x49, 0x41, 0x00 }, // E 0x45
{ 0x7f, 0x09, 0x09, 0x09, 0x01, 0x00 }, // F 0x46
{ 0x3e, 0x41, 0x49, 0x49, 0x7a, 0x00 }, // G 0x47
{ 0x7f, 0x08, 0x08, 0x08, 0x7f, 0x00 }, // H 0x48
{ 0x00, 0x41, 0x7f, 0x41, 0x00, 0x00 }, // I 0x49
{ 0x20, 0x40, 0x41, 0x3f, 0x01, 0x00 }, // J 0x4A
{ 0x7f, 0x08, 0x14, 0x22, 0x41, 0x00 }, // K 0x4B
{ 0x7f, 0x40, 0x40, 0x40, 0x40, 0x00 }, // L 0x4C
{ 0x7f, 0x02, 0x0c, 0x02, 0x7f, 0x00 }, // M 0x4D
{ 0x7f, 0x04, 0x08, 0x10, 0x7f, 0x00 }, // N 0x4E
{ 0x3e, 0x41, 0x41, 0x41, 0x3e, 0x00 }, // O 0x4F
{ 0x7f, 0x09, 0x09, 0x09, 0x06, 0x00 }, // P 0x50
{ 0x3e, 0x41, 0x51, 0x21, 0x5e, 0x00 }, // Q 0x51
{ 0x7f, 0x09, 0x19, 0x29, 0x46, 0x00 }, // R 0x52
{ 0x46, 0x49, 0x49, 0x49, 0x31, 0x00 }, // S 0x53
{ 0x01, 0x01, 0x7f, 0x01, 0x01, 0x00 }, // T 0x54
{ 0x3f, 0x40, 0x40, 0x40, 0x3f, 0x00 }, // U 0x55
{ 0x1f, 0x20, 0x40, 0x20, 0x1f, 0x00 }, // V 0x56
{ 0x3f, 0x40, 0x38, 0x40, 0x3f, 0x00 }, // W 0x57
{ 0x63, 0x14, 0x08, 0x14, 0x63, 0x00 }, // X 0x58
{ 0x07, 0x08, 0x70, 0x08, 0x07, 0x00 }, // Y 0x59
{ 0x61, 0x51, 0x49, 0x45, 0x43, 0x00 }, // Z 0x5A
{ 0x00, 0x7f, 0x41, 0x41, 0x00, 0x00 }, // [ 0x5B
{ 0x02, 0x04, 0x08, 0x10, 0x20, 0x00 }, // "\" 0x5C
{ 0x00, 0x41, 0x41, 0x7f, 0x00, 0x00 }, // ] 0x5D
{ 0x04, 0x02, 0x01, 0x02, 0x04, 0x00 }, // ^ 0x5E
{ 0x40, 0x40, 0x40, 0x40, 0x40, 0x00 }, // _ 0x5F
{ 0x00, 0x01, 0x02, 0x04, 0x00, 0x00 }, // ` 0x60
{ 0x20, 0x54, 0x54, 0x54, 0x78, 0x00 }, // a 0x61
{ 0x7f, 0x48, 0x44, 0x44, 0x38, 0x00 }, // b 0x62
{ 0x38, 0x44, 0x44, 0x44, 0x20, 0x00 }, // c 0x63
{ 0x38, 0x44, 0x44, 0x48, 0x7f, 0x00 }, // d 0x64
{ 0x38, 0x54, 0x54, 0x54, 0x18, 0x00 }, // e 0x65
{ 0x08, 0x7e, 0x09, 0x01, 0x02, 0x00 }, // f 0x66
{ 0x0c, 0x52, 0x52, 0x52, 0x3e, 0x00 }, // g 0x67
{ 0x7f, 0x08, 0x04, 0x04, 0x78, 0x00 }, // h 0x68
{ 0x00, 0x44, 0x7d, 0x40, 0x00, 0x00 }, // i 0x69
{ 0x20, 0x40, 0x44, 0x3d, 0x00, 0x00 }, // j 0x6A
{ 0x7f, 0x10, 0x28, 0x44, 0x00, 0x00 }, // k 0x6B
{ 0x00, 0x41, 0x7f, 0x40, 0x00, 0x00 }, // l 0x6C
{ 0x7c, 0x04, 0x18, 0x04, 0x78, 0x00 }, // m 0x6D
{ 0x7c, 0x08, 0x04, 0x04, 0x78, 0x00 }, // n 0x6E
{ 0x38, 0x44, 0x44, 0x44, 0x38, 0x00 }, // o 0x6F
{ 0x7c, 0x14, 0x14, 0x14, 0x08, 0x00 }, // p 0x70
{ 0x08, 0x14, 0x14, 0x18, 0x7c, 0x00 }, // q 0x71
{ 0x7c, 0x08, 0x04, 0x04, 0x08, 0x00 }, // r 0x72
{ 0x48, 0x54, 0x54, 0x54, 0x20, 0x00 }, // s 0x73
{ 0x04, 0x3f, 0x44, 0x40, 0x20, 0x00 }, // t 0x74
{ 0x3c, 0x40, 0x40, 0x20, 0x7c, 0x00 }, // u 0x75
{ 0x1c, 0x20, 0x40, 0x20, 0x1c, 0x00 }, // v 0X76
{ 0x3c, 0x40, 0x30, 0x40, 0x3c, 0x00 }, // w 0x77
{ 0x44, 0x28, 0x10, 0x28, 0x44, 0x00 }, // x 0x78
{ 0x0c, 0x50, 0x50, 0x50, 0x3c, 0x00 }, // y 0x79
{ 0x44, 0x64, 0x54, 0x4c, 0x44, 0x00 } // z 0x7A
}; // 6x8dot
//******************** font12(12x16dotフォント) ***********************
const char font12[16][24] =
{
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // " " 0x20
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1C, 0x1C, 0x1C, 0x00, 0x00, 0x00, 0x00, 0x00}, // . 0x2E
{0x00, 0xFC, 0xFC, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0xFC, 0xFC, 0x00, 0x00, 0x3F, 0x3F, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x3F, 0x3F, 0x00}, // H 0x48
{0x00, 0xFC, 0xFC, 0x78, 0xE0, 0xC0, 0xC0, 0xE0, 0x78, 0xFC, 0xFC, 0x00, 0x00, 0x3F, 0x3F, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x3F, 0x3F, 0x00}, // M 0x4D
{0x00, 0xFC, 0xFC, 0x00, 0x80, 0xC0, 0x60, 0x30, 0x10, 0x00, 0x00, 0x00, 0x00, 0x3F, 0x3F, 0x03, 0x03, 0x06, 0x0C, 0x18, 0x30, 0x20, 0x00, 0x00}, // k 0x6B
{0x00, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0xF0, 0x70, 0x30, 0x00, 0x00, 0x00, 0x30, 0x38, 0x3C, 0x36, 0x33, 0x31, 0x30, 0x30, 0x30, 0x00, 0x00}, // z 0x7A
{0x00, 0xF0, 0xF8, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0xF8, 0xF0, 0x00, 0x00, 0x0F, 0x1F, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x1F, 0x0F, 0x00}, // 0 0x30
{0x00, 0x00, 0x00, 0x00, 0x0C, 0xFC, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x3F, 0x3F, 0x30, 0x00, 0x00, 0x00, 0x00}, // 1 0x31
{0x00, 0x30, 0x38, 0x0C, 0x0C, 0x0C, 0x8C, 0x8C, 0xCC, 0xF8, 0x70, 0x00, 0x00, 0x38, 0x3C, 0x3E, 0x37, 0x33, 0x31, 0x31, 0x30, 0x30, 0x30, 0x00}, // 2 0x32
{0x00, 0x18, 0x1C, 0x0C, 0x8C, 0x8C, 0x8C, 0x8C, 0xCC, 0xF8, 0x70, 0x00, 0x00, 0x18, 0x38, 0x30, 0x31, 0x31, 0x31, 0x31, 0x33, 0x1F, 0x0E, 0x00}, // 3 0x33
{0x00, 0x00, 0x00, 0x80, 0xC0, 0x60, 0x30, 0x18, 0xFC, 0xFC, 0x00, 0x00, 0x00, 0x0E, 0x0F, 0x0D, 0x0C, 0x0C, 0x0C, 0x0C, 0x3F, 0x3F, 0x0C, 0x00}, // 4 0x34
{0x00, 0xFC, 0xFC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0x8C, 0x0C, 0x00, 0x00, 0x18, 0x38, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x1F, 0x0F, 0x00}, // 5 0x35
{0x00, 0xF0, 0xF8, 0x9C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x18, 0x18, 0x00, 0x00, 0x0F, 0x1F, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x1F, 0x0E, 0x00}, // 6 0x36
{0x00, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x8C, 0xCC, 0x7C, 0x3C, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3E, 0x3F, 0x01, 0x00, 0x00, 0x00, 0x00}, // 7 0x37
{0x00, 0x70, 0xF8, 0x88, 0x8C, 0x8C, 0x8C, 0x8C, 0x88, 0xF8, 0x70, 0x00, 0x00, 0x0E, 0x1F, 0x11, 0x31, 0x31, 0x31, 0x31, 0x11, 0x1F, 0x0E, 0x00}, // 8 0x38
{0x00, 0x78, 0xFC, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0xF8, 0xF0, 0x00, 0x00, 0x00, 0x30, 0x31, 0x31, 0x31, 0x31, 0x31, 0x39, 0x1F, 0x0F, 0x00}, // 9 0x39
}; // 12x16dot