日本語フォント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」カテゴリの記事
- 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)
- NeoPixel(WS2812B)の制御 その5(2024.09.15)
「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) »
コメント