日本語フォントROM GT20L16J1Y Breakoutを試してみました
スイッチサイエンスさんでarduinoで使えそうな日本語フォントROMが販売されていたので、
購入して試してみました。
製品:日本語フォントROM GT20L16J1Y Breakout
16x16日本語フォント(JIS208) ROM
3.3V動作
SPIアクセス
販売サイトおよび委託者さんのホームページにデータシートがあるのですが、
資料的に不十分です。フォントデータの取り出し方法が分かりません。
こちらのデータシートを参考にした方が良いでしょう。ただし中国語です。
本製品の情報があまりないのですが、SE組込人さんのホームページが大変参考に
なりました。参考記事: 漢字フォントROM(GT20L16J1Y)
動作電圧が3.3Vなのですが、幸いにして私のArduino UNO互換機は3.3Vモードがあるので
単純な配線で利用できました。
取りあえずフォントデータの取り出しはできました。

フォントデータの格納形式がちょっと特殊です(データシートより抜粋)。
(B0がMSB、B7がLSBです)
フォントの格納アドレス
"起始地址"はROM内の格納アドレスです。
電子回路の掲載を省略します。
通常のArduinoでは3.3Vのレベル変換する必要があります。
ソースはこんな感じです。
修正 2014/03/05
変数の型の定義が間違っており、一部のフォントが正しく表示できませんでした。
ソースファイルを修正しました。
修正前
byte MSB;
byte LSB;
修正後
unsigned long MSB;
unsigned long LSB;
また、calcAddr()関数中で計算するオフセット値は138463ではなく138464が
正しいと思われるので修正しました。サンプルのミスだと思われます。
#include <SPI.h>
#include <string.h>
#define ASC8x16S 255968 // 8x16 ASCII 粗体字符(半角)
#define ASC8x16N 257504 // 8x16 ASCII 日文假名(半角)
byte rowdata[32];
// 全角JISコードからフォント格納先頭アドレスを求める
// GT20L16J1Y データシート VER 4.0 2013-3のサンプルを参照した
// (サンプルでは区点コードからの変換であることに注意)
unsigned long calcAddr(unsigned short jiscode) {
unsigned long MSB;
unsigned long LSB;
unsigned long Address;
// 上位、下位を区点コードに変換
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;
}
// JISコードからキャラクタデータを得る
void getCharData(unsigned short code) {
byte data;
unsigned long addr=0;
byte n;
if (code > 0xFF) {
// 全角
addr =calcAddr(code);
n = 32;
} else {
// 半角
addr = ASC8x16S + (code*16);
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);
delay(10);
}
SPI.setBitOrder(MSBFIRST);
digitalWrite(10, HIGH);
}
void displayChar(unsigned short code) {
getCharData(code);
if (code > 0xff) {
for (byte y = 0; y <8; y++) {
for (byte x = 0; x < 16; x++) {
if (rowdata[x] & (0x80>>y)) {
Serial.print("#");
} else {
Serial.print(".");
}
}
Serial.println("");
}
for (byte y = 0; y <8; y++) {
for (byte x = 16; x < 32; x++) {
if (rowdata[x] & (0x80>>y)) {
Serial.print("#");
} else {
Serial.print(".");
}
}
Serial.println("");
}
} else {
for (byte y = 0; y <8; y++) {
for (byte x = 0; x < 8; x++) {
if (rowdata[x] & (0x80>>y)) {
Serial.print("#");
} else {
Serial.print(".");
}
}
Serial.println("");
}
for (byte y = 0; y <8; y++) {
for (byte x = 8; x < 16; x++) {
if (rowdata[x] & (0x80>>y)) {
Serial.print("#");
} else {
Serial.print(".");
}
}
Serial.println("");
}
}
}
void setup() {
pinMode(10,OUTPUT);
SPI.begin();
Serial.begin(19200);
displayChar(0x41);
displayChar(0x2422);
displayChar(0x3a6b);
displayChar(0x364c);
}
void loop() {
}
本製品、良いのですがarduinoで使う場合はちょっと不便です。
arduinoは文字のコード系にunucodeを使っているので、JISコードへの変換が必要と
なります。スケッチ上では文字を16進数で指定しないとダメです。
unucodeからJISコードへの変換には1対1対応のテーブルが必要です。
テーブルだけで32Kバイトの容量となります。
まあ、パソコンから直接データを送り込むような利用では使えそうです。
あるようです。データシートはここ。日本も使えるはは不明ですが..

Aliexpressで入手可能のようですが、5個で$8.84。試して見ようかと思ったのですが、
今回はやめます。
2014/03/05 追記
本漢字ROMの全角JIS0208のデータは次のフォントを詰めて格納しているようです。
(区、点)であらわすとこんな感じで格納されています。
(01,01) - (15,46) 1362文字(#0 - #1361) が連続で格納
(16,01) - (47,51) 2965文字 (#1362 - #4326) が連続で格納
(48,01) - (84,06) 3390文字 (#4327 - #7716) が連続で格納
(85,01) - (85,94) 94文字 (#7717 - #7810) が連続で格納
(88,01) - (89,86) 180文字 (#7811 - #7990) が連続で格納
ここで#数字は先頭からの通番です。全角16x16は#0 - #7990の7991文字があります。
(資料では7999文字ですが、8文字足りない?)
それぞれの区の格納先頭アドレスは通番先頭に32を掛けた値になります。
サンプルソースの関数calcAddr()ではこの割り付けを元に計算できます。
ちなみに区点コードとJISコードの関係は
区コード = JISコード上位1バイト - 0x20
点コード = JISコード下位1バイト - 0x20
例: 埼:JISコード: 3A6B 区点コード: (26, 75) = (0x1A, 0x4B) = (0x3A-0x20, 0x6B-0x20)
« arduinoがシリアル通信時にリセットされる原因が分かりました | トップページ | Arduinoで美咲フォントを使った8x8ドットマトリクスLED(4) »
「arduino」カテゴリの記事
- Freenove Mecanum ホイール カー キットを購入しました(2025.05.28)
- Arduino IDE+Arduino STM32環境で指定と異なるgccが使われてしまう(2025.01.23)
- Zorin OSでArduino Uno互換機(CH340)が認識しない(2025.01.19)
- Arduino IDE 2.3.4でArduino STM32を利用する(2025.01.12)
- Arduino用 SKK日本語変換ライブラリの開発 その1(2024.12.28)
「AVR」カテゴリの記事
- NeoPixel(WS2812B)の制御 その5(2024.09.15)
- Arduino用SJIS漢字フォントライブラリ SDカード版を作成しました(2018.10.30)
- ATtiny13AでI2C接続キャラクタLCDを利用する(4)(2018.04.16)
- ATtiny13Aで赤外線リモコン受信センサーを使う(2)(2018.04.15)
- ATtiny13AでHC-SR04を使った距離計測(2018.04.14)
« arduinoがシリアル通信時にリセットされる原因が分かりました | トップページ | Arduinoで美咲フォントを使った8x8ドットマトリクスLED(4) »

コメント