フォト
2017年3月
      1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31  
無料ブログはココログ

« arduinoがシリアル通信時にリセットされる原因が分かりました | トップページ | Arduinoで美咲フォントを使った8x8ドットマトリクスLED(4) »

2014年3月 4日 (火)

日本語フォントROM GT20L16J1Y Breakoutを試してみました

スイッチサイエンスさんでarduinoで使えそうな日本語フォントROMが販売されていたので、
購入して試してみました。

製品:日本語フォントROM GT20L16J1Y Breakout

16x16日本語フォント(JIS208) ROM
3.3V動作
SPIアクセス

販売サイトおよび委託者さんのホームページにデータシートがあるのですが、
資料的に不十分です。フォントデータの取り出し方法が分かりません。
こちらのデータシートを参考にした方が良いでしょう。ただし中国語です。

本製品の情報があまりないのですが、SE組込人さんのホームページが大変参考に
なりました。参考記事:  漢字フォントROM(GT20L16J1Y)

動作電圧が3.3Vなのですが、幸いにして私のArduino UNO互換機は3.3Vモードがあるので
単純な配線で利用できました。

Dscn2441

取りあえずフォントデータの取り出しはできました。

01

フォントデータの格納形式がちょっと特殊です(データシートより抜粋)。
(B0がMSB、B7がLSBです)
03

フォントの格納アドレス
02

  "起始地址"は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バイトの容量となります。
まあ、パソコンから直接データを送り込むような利用では使えそうです。

unicodeで格納されていればなぁと、類似品を調べると GT20L16P1YというROMも
あるようです。データシートはここ。日本も使えるはは不明ですが..

04
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」カテゴリの記事

AVR」カテゴリの記事

コメント

コメントを書く

(ウェブ上には掲載しません)

トラックバック

この記事のトラックバックURL:
http://app.cocolog-nifty.com/t/trackback/571408/59238567

この記事へのトラックバック一覧です: 日本語フォントROM GT20L16J1Y Breakoutを試してみました:

« arduinoがシリアル通信時にリセットされる原因が分かりました | トップページ | Arduinoで美咲フォントを使った8x8ドットマトリクスLED(4) »