« グラフィック・ディスプレイ表示の高速化 | トップページ | Arduinoで漢字表示(2) »

Arduinoで漢字表示

GLCD(SG12864A)を使って漢字の表示に挑戦中です。今回は試験的に作ったフォントデーター1文字をGLCDに表示するところまでです。漢字表示の目的としては以前にも書きましたが、RSSリーダーを作ることです。

基本構想

  1. Arduino標準であるks0108ライブラリを拡張する
    グラフィック・ディスプレイ表示の高速化で投稿した改造版をベースにする
  2. 漢字フォントに関しても、ks0108ライブラリのフォント構造を踏襲する
  3. RSSはUTF-8でエンコードされているため、漢字フォントはUnicode (UCS-2)で収録する
  4. フォントは「東雲(shinonome)ゴシック」の12ドットを使用
    → 12ドットフォントになるとArduino MegaのROMでも入らないですが、可読性を優先して外付けEEPROMにフォントを格納

SG12864AのDisplay Data RAMの構造

GLCDに漢字を表示するために、SG12864AのDisplay Data RAMの構造を調べました。

Glcd_vram_2

Display Data RAMのアドレスは、Chip番号、Colum Address(X座標)、Page Address(Y座標)で指定します。SG12864AではLCDコントローラーCHIPを2つ使用しており、X座標の63~64にかけて選択するCHIPの切り替えが必要となります。

SG12864Aでは、8-bitデーターバス経由でDisplay Data RAMにデーターを書き込むと、指定したPageに対応する縦方向8ドットに対して描画が行われます。例えば図に示すように、(x = 1, y = 0)座標に「N」を表示したい場合、(Chip = 1, Page = 0, Colum = 1)に0xFFを書き込みます。

SG12864Aはドットマトリクスディスプレイのため、Pageにまたがる描画も発生ししますが、その場合はks0108ライブラリの中で2つのPageに分割して描画を行っています(作者ではないですが、コードの解析より)。

フォントの構造

今回使用する東雲フォントは、BDF形式で配布されています。例えば、shnmk12min.bdfファイルでは、全角「あ」のビットマップは以下のようになっています。(こちらはゴシックではなく、明朝体でした)

 STARTCHAR 2422
 ENCODING 9250
 SWIDTH 960 0
 DWIDTH 12 0
 BBX 12 12 0 -2
 BITMAP
  1000
  0b00
  7c00
  1200
  1f00
  1280
  3440
  5440
  4840
  5080
  2300
  0000
 ENDCHAR

ビットマップ情報を画面イメージに展開すると以下のようになります。横方向(X軸方向)にビットマップを展開していることが分かります。

Bfd_font_6

Arduinoのks0108ライブラリはどうかというと、GLCDがPage単位(縦方向8ドット単位)の描画であることから、縦方向にビットマップを展開します。上記の「あ」のフォントデーターをks0108ライブラリのフォント形式に変換すると以下のようになります。12ドットフォントの描画は2 Pageに渡りますが、2 Page目のデーター4bitはMSB側にアラインして書き込み時にシフトを行っています。

Arduino_font_3

サンプルフォントの作成と表示の実験

ks0108ライブラリの形式に従って、先ほどの「あ」を示すフォントファイルをつくり、「あ」の文字を表示させてみます。まだ、ks0108ライブラリは2バイト文字が認識できませんので、文字コード0x21として定義します。

以下に、「あ」と「A」を手動でArduino形式のフォントイメージに変換したフォントファイル(sample.h)の内容を示します。

#include <inttypes.h>
#include <avr/pgmspace.h>

#ifndef SAMPLE_H
#define SAMPLE_H

#define SAMPLE_WIDTH 12
#define SAMPLE_HEIGHT 12

static uint8_t Sample[] PROGMEM = {
  0x0, 0x0, // size of zero indicates fixed width font, actual length is width * height
  0x0C, // width
  0x0C, // height
  0x20, // first char
  0x02, // char count

  // font data
  0x00, 0x00, 0x00, 0xE0, 0x98, 0x86, 0x98, 0xE0, 0x00, 0x00, 0x00, 0x00,    //A
  0x00, 0x40, 0x70, 0x40, 0x00, 0x00, 0x00, 0x40, 0x70, 0x40, 0x00, 0x00,
  0x00, 0x84, 0x44, 0xFD, 0x16, 0xD4, 0x7A, 0x12, 0x20, 0xC0, 0x00, 0x00,    //あ
  0x00, 0x30, 0x40, 0x20, 0x10, 0x00, 0x40, 0x40, 0x20, 0x10, 0x00, 0x00
};
#endif

上記のフォントファイルを展開して、「あ」を表示する試験スケッチを以下に示します。

#include <ks0108.h>  // library header
#include <Sample.h>
#include <MsTimer2.h>

#define REFRESH   24

void setup()
{
  Serial.begin(9600);
  GLCD.Init(NON_INVERTED);
  GLCD.SelectFont(Sample);
  MsTimer2::set(1000/REFRESH/8, GlcdUpdate);
  MsTimer2::start();
}

void GlcdUpdate()
{
  GLCD.Update();
}

void  loop()
{
  GLCD.ClearScreen(); 
  delay(500);
  showKanji(0x21, 0, 0, 12, 12);
  delay(5000);
}

void showKanji(char c, uint8_t posX, uint8_t posY, uint8_t fontWidth, uint8_t fontHight)
{
  for (posY = 0; posY < 63 - fontHight; posY += fontHight)
  {
    for (posX = 0; posX < 127 - fontWidth; posX += fontWidth)
    {
      GLCD.GotoXY(posX, posY);
      GLCD.PutChar(c);
    }
  }
}

写真のフォーカスがいまいちですが、「あ」の文字が表示できました。

Kanjidispfirst_3

今後の課題

1. 東雲(shinonome)ゴシックの12ドットフォント全体を今回示したArduino形式にコンバートする必要があります。こちらは機械的な処理ですので、PC側で処理ができそうです。

2. BDF形式で配布されている東雲フォントのデーターは、JISX 0208のコード体系で収録されています。最終的にUTF-8の文字コードから表示を行うためには、UCS-2のコード体系でフォントデーターを格納しておくと表示の際のコード変換処理が楽になりそうです。UTF-8では漢字コートは3バイトで表現されてしまうため、2バイトで表現できるUCS-2のコード体系でフォントデーターを作ることを考えています(UTF-8からUCS-2へのコード変換は簡単なビット演算で可能)。

ただ、UCS-2の漢字コードは、CJK統合漢字と呼ばれる体系になっており、JIS漢字とは全く異なる文字配置のため、機械的にUCS-2コード順に並び替えができるかが分かっていません。またCJK統合漢字では、中国・日本・韓国で使用する類似の漢字を同一コードにマッピングしていますが、中国のみの漢字コードが混在するようなので、その部分はフォントデーターをブランクにするなどの処理が必要になりそうです。

3. 手持ちのI2C EEPROMは1M bit(128KB)ものが2個です。一文字あたり24Bのデーター量となり、JISの8800文字を収録すると200KB程度ですので容量的には入ると思うのですが、場合によってはフォントデーターの圧縮を考えないとだめかも。12ドットフォントの場合4bitは使っていない(常に0)のため、その部分を詰めることもできそうですが、Arduino ks0108ライブラリの描画ルーチンをそのまま使う基本方針をとった場合、データー量が増えても今回示したフォントデーターで通してしまうのが楽ちんです。

どこかに、UCS-2(もしくは、何らかのUnicode)形式で収録されたフリーの漢字フォントデーターがあるとよいのですが。

2009/7/5更新: 続編として、Arduinoで漢字表示(2)を公開

2009/7/12更新Arduinoで漢字表示(3)を公開

2009/7/21更新Arduinoで漢字表示(4)を公開

|

« グラフィック・ディスプレイ表示の高速化 | トップページ | Arduinoで漢字表示(2) »

Arduino」カテゴリの記事

コメント

すごく期待大です。
「RSSでお天気情報を表示して置きたい」と思っている人も、私も含めて多いと思います。

私も昔このLCDの縦方向で半分のサイズの物用に、フォントデータを作成した事が有ります。
http://hamayan.ddo.jp/~hamayan/so-net/font.html
なんでこんな配置にorz。

投稿: hamayan | 2009年6月22日 (月) 09時02分

まだまだ先は長いのですが、最後までたどり着けるようにがんばらねばです。フォントを変換するために、文字コード体系を勉強中なのですが、今はまさにsjis/eucからUnicodeへの移行期なので、どちらを使うかが悩ましいです。

nkfのソースをざっと眺めたのですが、euc<->utf-8変換の巨大な変換表が入っており、全て表を使って変換しているように見えます(単純なビット演算では不可)。RSSのようなXML文書を扱うのならUnicodeが基本ですので、Unicode配列で収録と思っているのですが、その場合はsjis文書の表示には巨大な変換表を抱く必要が出てきます。漢字ROMは外付けのI2C or SPIのEEPROMに置いて、変換表はAVRのFlash ROM (Arduino Megaクラスが必要だと思いますが)に格納することで対応はできると思いますが、先ずはXML文書(Unicode)専用で動くモノを作りたいと思います。

インタフェース5月号付属のAVRマイコンのように、ROM 512KB, SRAM 32KBものメモリーが乗っているマイコンがうらやましいです。浮気しちゃうか?いや、8-bitでどこまでがんばれるかですね。

投稿: todotani | 2009年6月22日 (月) 23時34分

Twitterでoomloutさんが「unicodeを印刷できるタイプライタ知ってる?」って言ってたので、表示する方法があるみたいだよってここを紹介しました。それにしてもこれ(http://oomlout.co.uk/?p=79)には驚きました。古いプリンター(ImageWriterとか)でunicodeを印刷できたら代替品になりそうですが。

投稿: beagleboard | 2009年6月24日 (水) 08時13分

Twitter Monitoring Typewriter (TwypeWriter)すごいですね。Twitterのことは初めて知りました。現在進行中のMy ProjectはUnicodeといっても、日本語漢字のみではありますが(中国語、韓国語、タイ語のフォントなどは当面未対応)がんばって作ります。

投稿: todotani | 2009年6月25日 (木) 07時47分

コメントを書く



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




« グラフィック・ディスプレイ表示の高速化 | トップページ | Arduinoで漢字表示(2) »