Arduinoで漢字表示
GLCD(SG12864A)を使って漢字の表示に挑戦中です。今回は試験的に作ったフォントデーター1文字をGLCDに表示するところまでです。漢字表示の目的としては以前にも書きましたが、RSSリーダーを作ることです。
基本構想
- Arduino標準であるks0108ライブラリを拡張する
→ グラフィック・ディスプレイ表示の高速化で投稿した改造版をベースにする - 漢字フォントに関しても、ks0108ライブラリのフォント構造を踏襲する
- RSSはUTF-8でエンコードされているため、漢字フォントはUnicode (UCS-2)で収録する
- フォントは「東雲(shinonome)ゴシック」の12ドットを使用
→ 12ドットフォントになるとArduino MegaのROMでも入らないですが、可読性を優先して外付けEEPROMにフォントを格納
SG12864AのDisplay Data RAMの構造
GLCDに漢字を表示するために、SG12864AのDisplay Data RAMの構造を調べました。
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軸方向)にビットマップを展開していることが分かります。
Arduinoのks0108ライブラリはどうかというと、GLCDがPage単位(縦方向8ドット単位)の描画であることから、縦方向にビットマップを展開します。上記の「あ」のフォントデーターをks0108ライブラリのフォント形式に変換すると以下のようになります。12ドットフォントの描画は2 Pageに渡りますが、2 Page目のデーター4bitはMSB側にアラインして書き込み時にシフトを行っています。

サンプルフォントの作成と表示の実験
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);
}
}
}
写真のフォーカスがいまいちですが、「あ」の文字が表示できました。
今後の課題
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」カテゴリの記事
- ArduinoでXMLを解析する(2009.08.25)
- Arduino RSSリーダー(2009.09.06)
- Arduino 0017(2009.08.14)
- SPIデバイスの混在とSS信号の初期状態(2009.08.31)
- Arduino Nano 3.0 Get(2009.08.12)



コメント
すごく期待大です。
「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分