« Arduinoで漢字表示 | トップページ | Arduinoで漢字表示(3) »

Arduinoで漢字表示(2)

前回の続編です。まだ最終的な方向性が定まっていないのですが、JISコードベースで漢字が表示できるようになりました。

漢字フォントデーター

RSSなどUTF-8でエンコードされたコンテンツを表示するためには(ちなみに、このブログもUTF-8です)、内部コードとしてUnicode(UCS-2)を使うと効率がよいと思われる点は前回記載しました。漢字をUnicode配列で収録したフリーのフォントデーターを探したところ、efontさんが東雲(Shinonome)フォントのUnicode版を配布していることを発見。また、efontさんからJISコードベースで収録した東雲フォントもダウンロード可能です。

問題は、Unicodeの場合ハングルや中国語固有の漢字など多数のフォントデーターが収録されており、JIS漢字の東雲フォントに比べるとデーター量が大きくなることです。以下にフォントファイルに収録されている文字数(bdfファイルのCHARS宣言の値)を示します:

  • shnmk12min.bdf(JIS): 6879文字
  • b12.bdf(Unicode):22759文字(半角英数字を含む)

12ドットフォントの場合、文字あたり24Bのデーター量になるため、2.2万文字のUnicodeフォントを格納するためには500KB程度のROM容量が必要です。日本語漢字コードが連続した領域に配置されている場合、そこだけ抜き取ってROMに書き込むことができますが、UnicodeではCJK(中国・日本・韓国)統合漢字として由来が同一の文字単位にまとめているせいか、JISに収録されている漢字だけを抜き取ると並びが不連続になってしまいます。そのため日本語漢字だけを抜き取った場合、文字コードからフォントの格納位置を一律に計算できないため、文字単位にアドレス変換テーブルが必要になります。

変換テーブルを置くくらいなら、CJK統合漢字全体をEEPROMに格納して文字コードで直接EEPROMアドレスをインデックスするのがよいのですが、手持ちのAT24C1024B(1Mbit I2C EEPROM)x2個には入りません。そのため、。先ずはJISの東雲フォントを使用することとしました。

漢字フォントは前述のI2C EEPROM x2個に格納しました。EEPROMを接続した全体の回路図を以下に示します。SCL/SDAのプルアップはAVRの内蔵プルアップ抵抗を使用(Wireライブラリを使用すると自動的に内部プルアップが有効になります)。

Glcd_eeprom

フォントデーターの変換

ArduinoのGLCDライブラリとしては、本家のwebで公開されているks0108 GLCDライブラリを使用します。先日Ver.2が公開されたため、V2をベースに漢字表示機能を追加します。V2への高速表示の移植は別途にします。(シリアル接続のEEPROMにフォントデーターを格納する時点で高速動作は期待できないため)。

先ずbdfフォントのビットマップデーターを、Arduinoのks0108 GLCDライブラリで使用しているビットマップデーターに変換します。変換の方法は前回の「Arduinoで漢字表示」に記載した通りです。ツールを作って変換を行ったファイルを以下に掲載します。
 「glcdfont_shnm12min.zip」をダウンロード

  • glcdfont_shnm12min.txt:外付けEEPROMに書き込む形式に変換した漢字フォントデーター(半角カナを含む)
  • shnm.h:東雲6x12の半角英数字フォントをks0108 GLCDライブラリのフォント形式に変換したファイル。スケッチ上で、shnm.hをincludeすることで使用可能(AVR内蔵Flashメモリにフォントデーターを格納)

JIS X 208の文字コードでは、「区(Row)」と呼ばれる面(ページのようなものでしょうか)に、94文字分のコードを割り当てます。例えば、「01区」は0x2121~0x217dのコードエリアを使用します。文字を割り当てていないコードポイント(例えば、0x2230~0x2238)にはフォントデーターが存在しないのですが、フォントを格納したEEPROMのアドレス計算を容易にするため、スペース相当のダミーデーターを挿入しています。

フォントデーターの転送

PCからシリアル通信を使ってArduinoにフォントデーターを転送します。PCのアップローダーアプリとArduino側の受信(およびEEPROMへの書き込み)スケッチを作成しました。アップローダーのバイナリファイルとArduinoのスケッチを以下に掲載します。
 「Upload.zip」をダウンロード

  • Upload.exe: PC側のアップローダー(.Net Framework 2.0以上が必要)
  • FrontWrite.pde: Arduino側のフォントデーター受信、書き込み用スケッチ

アップローダーの画面イメージを以下に示します。

Uploadapp_4

ファイルを選択して、Uploadボタンをクリックすると送信を開始します。プログラムを最初に動かした時は、シリアル通信が始まらない場合があります。その際は一旦プログラムを強制終了してやり直すとうまくいきます。Arduinoへデーター転送中に中断したい場合も、タスクマネージャーから強制終了する必要があります。このあたりは手抜きですが、、

フォントデーターのEEPROMへの書き込みは、当初はページ書き込み(24byte or 12byte単位)を使用したのですが、特定のアドレスで書き込みエラーが発生する問題を解決できず、byte単位の書き込みを行っています。読み出しは、24 or 12Byte単位のシーケンシャル読み出しができています。

ks0108ライブラリの改造

とりあえず、JISコードを直接指定して1文字を表示するPutUChar()関数を追加しました。改造版のソースコードを以下に掲載します。
 「ks0108_jisKanji.zip」をダウンロード

改造版ライブラリで漢字を表示した画面を以下に示します。

Jiskanji

今後の計画

まだまだ先は長いです。次にやることの選択肢として以下があります。

1)Unicode→ JISコード変換テーブルの作成

このURLにJIS - Unicodeの対応表があるのですが、全く一貫性・法則性がなくビット演算レベルでの変換は無理そうです。そのため、力業ですが、文字コード毎に変換テーブルを作る方法が考えられます。Unicode側のコード・スペースを2万として、16bitのJISコードに変換するテーブルを作る場合、テーブルサイズは 2万 x 2≒ 40KBになります。

アクセス速度を考えると、このテーブルはシリアルEEPROMではなく、AVRの内蔵Flash ROMに格納する必要があります。Arduino MegaのATMega 1280なら容量的には格納できる範囲ではあります。

2)大容量メモリーにUnicodeフォントを格納

1MB程度のメモリーがあればUnicodeフォントを格納できますが、I2CのEEPROMでは1Mbit以上の製品はなさそうです。スイッチサイエンスさんのSPI接続フラッシュメモリAT45DB161Dあたりを使ってデーターを格納する解がありそうですが、以下が気になる点です:

  • AT24C1024B(I2C)よりアクセスのオーバーヘッドがあるかも
    → 当初は512Byteのページ単位アクセスのみかと思ったのですが、データーシートを見直すと開始アドレスを指定したシーケンシャル読み出しもあるため、アドレス指定が長くなる以外は(I2C EEPROMに比べて)特にオーバーヘッドはなさそうです
  • 動作電圧が3.3V。Arduinoと接続するためにはレベル変換回路が必要。スイッチサイエンスさんの「ロジックレベル変換モジュール」が使えそう。3.3V電源は、Flashメモリーを駆動するだけならArduinoの3V出力(50mA)が使えそうです

次は、AT45DB161D(SPI版、2MB)を使って、どの程度の表示速度が得られるかを実験してみます。現在使用しているAT24C1024B(I2C版、128KB)では、AVR内蔵Flashに比べるとかなり表示が遅くなりますが、RSSビューワー的な使い方なら許容範囲です。

2009/7/7追記:
AT45DB161Dのデーターシートを見直すと、DC特性表の注釈にI/O(SI, SCK, CS)は5-Volt tolerantという記述を発見(こういう情報はサマリーページに書いて欲しい!)。上記信号はArduinoと直結出来ることが分かりました。

SO(AT45DB161Dのデーター出力)は、3.3V駆動時のV-OH(min) が3.1Vとなるため、Arduinoに直結してもぎりぎりHレベルの認識は可能。SOに関してはレベルシフターをかまして、5Vにきっちり上げてやった方が安定性の点では望ましいですが、実力的には直結でも動きそうです(以前3.3V駆動のシリアルをArduinoに直結した際は正常に動作しました)。

直結・レベルシフター経由の双方で動作を試してみたいと思います。

2009/7/10追記:
GLCD DB0~7のピン番号(回路図)に誤りがあったため修正。

2009/7/12追記:
AT45DB161Dの接続結果を「Arduinoで漢字表示(3)」に記載しました。

|

« Arduinoで漢字表示 | トップページ | Arduinoで漢字表示(3) »

Arduino」カテゴリの記事

コメント

Arduino用の大容量記憶装置としてはSDカードのシールドが2社から出てますね。
http://www.libelium.com/tienda/catalog/product_info.php?cPath=21&products_id=66
http://www.seeedstudio.com/depot/sd-card-shield-for-arduino-v10-p-412.html
Libeliumの方が高いけど定評はあるみたいです。
あと、Adafruitの2製品がSDカードのスロットを搭載してます。
http://www.adafruit.com/index.php?main_page=product_info&cPath=17_21&products_id=94
http://www.adafruit.com/index.php?main_page=product_info&cPath=17_21&products_id=98
最近のではSDカードスロットが搭載されていないですがethernetシールドには接続することの出来るパターンが残ってます。分圧抵抗をつける必要があります。
http://www.geocities.jp/jun930/etc/arduinosd.html
海外でもSDは増えてきてますね。
あと、TwitterでAdafruitさんがKS0180ライブラリをリライトしてると言ってました。LiquidCrystalの新ライブラリはRC3をTwitterで既に公開してます。凄く使い易くなってました。

投稿: beagleboard | 2009年7月 6日 (月) 00時58分

色々と情報ありがとうございました。

漢字フォントを格納するメモリーとしては、メモリー空間の任意アドレスから24 or 12Byteの連続データーを取り出せる必要があります。SDカードは、512Byte等のセクター単位の読み出ししかできず効率が悪いと思っていました。
Webの情報を漁ってみると、読み出し開始アドレスは任意で、ブロック長はデフォルト512Byteですが可変とありました(一部のメモリーカードでは512Byte固定の場合もあるのでしょうか)。

そのためご指摘の通り、SDメモリーカードも使用可能ですね。実は、AT45DB161Dを注文してしまいまして、先ずはAT45DB161Dで動かしてみてSDメモリーカードについてもどこかで試すことができればと思います。

AdafruitさんのLiquidCrystalライブラリ情報ありがとうございました。今度使ってみます。

投稿: todotani | 2009年7月 6日 (月) 23時46分

コメントを書く



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




« Arduinoで漢字表示 | トップページ | Arduinoで漢字表示(3) »