放課後の電子工作 HOME > 超小型MP3プレーヤー [ Timpy ]
> Rev4.0 【FMチューナ付きヘッドフォン内蔵型+ワイヤレスリモコン】 > Timpy Rev4.0 技術情報

2007年6月9日 更新

超小型MP3プレーヤー [ Timpy ]
 
Timpy Rev4.0 技術情報

Timpy Rev4.0のテクニカルな部分を説明します。
(もしも著作権にかかわる部分を商用利用される場合はご連絡ください)

》MENU

★ 回路図
★ ファームウェア
★ 基板データ
★ FMチューナモジュール NS953M
★ カラーグラフィック液晶表示器 HDM1216C-2の制御
★ 日本語フォント
★ 本体−リモコン間の赤外線通信

--

》全回路図

全回路図

 → timpy-rev40b-sch.pdf (253KB)

上半分がヘッドフォン側、下半分がリモコン側です。

【2006年3月27日追記】ヘッドフォンアンプをLM4911からLM4924に変更しました。LM4911の出力形式(OCLか否か)識別回路の動作がどうも不確実なので、OCL専用のLM4924にしました。なんとマニュアルに記述がないのですが、実験によるとLM4924のMUTE端子はアクティブ"L"です。LM4911とは逆になっています。

--

》ファームウェア

★ヘッドフォン側 (プロセッサ:C8051F311)
 → timpy40-h_20060326.zip (35KB)

★リモコン側 (プロセッサ:C8051F310)
 → timpy40-r_20060115.zip (33KB)

--

》基板データ

(準備中)

--

》FMチューナモジュール NS953M

Rev4.0基板 - はんだ面

NS953Mの動作確認

FMチューナモジュールは新潟精密株式会社さんのNS953Mです。
わずか7mm角でチューナとしての機能を全て内蔵しており、IFTはじめ外付けのインダクタ類が一切不要な最新型のデバイスです。
I2Cインターフェースを通してデジタル的に制御できます。

写真左は動作確認のために組んだバラックです。
ボールピッチ0.8mm、7×7のBGAパッケージです。
裏返しにして、100μm位の極細線で配線してあります。

★ データシート
 → NS953M-36AW-01-F1_PRELIMINARY_Ver1_0.pdf (484KB)
このマニュアルは新潟精密さんから許可を頂いた上で公開しています。
転載禁止です。併せて、私のHP上の情報に関して新潟精密さんに問い合わせることはご遠慮ください。よろしくお願いします。

★ 基板への実装方法
BGAパッケージなのでリフローで実装するのが本来なのですが、個人の趣味ではそうもいきません。
でもNS953Mは、いくつかの幸運な条件がそろっていたため、手はんだでの実装が可能でした。

写真右はヘッドフォン用基板の裏面です。トランスフラッシュカードコネクタの右下にランドが正方形に並んでいますが、ここの表側にNS953Mが実装されています。
このように、BGAのボールの位置に合わせてスルホールを作っておくのがミソです。
チップを位置合わせした上で、裏側からスルホールにはんだを流し込み、表側のボールとはんだ接合します。

でも実際には、流し込んだはんだがボールまで届かない場合が発生します。
GNDのような熱容量の大きなパッドでは、裏からの加熱では表まではんだが回らないおそれがあるためです。BGAなので目視もできません。
そこで、あらかじめスルホールにAWG32くらいの単線を差し込んでおいて、そこへはんだを流し込み、加熱しながらそのワイヤで軽く突くようにして、確実にボールまではんだが到達するようにします。私の場合はこれでうまくいきました。

ところで、個人レベルでBGAという一般的な話になると、もうひとつ補足しないといけません。今回ラッキーだったのは、NS953Mのボールがチップの外周部のみに配置されていたことです。
例えばVS1011のBGAパッケージのように、チップ中央までびっしりとボールが配置されているチップだったなら、このはんだ付け法は難しくなります。
なぜかというと、グリッド状にスルホールを配置してしまうため、中央部の信号が引き出せなくなるからです。
NS953Mのボールピッチは0.8mm、P板の製造基準ではスルホールのランド径は最小0.6mmです。つまり隣接するランド間隔は0.2mmしかないので、ランド間に信号ラインが通りません。
もし仮に、このラインが通ったとしても、スルホール間に1本しか通らないのでは全部の信号を引き出すことはできません。

Rev4.0ではその辺の幸運もあって、BGAパッケージを両面板の手はんだで実装することができました。

★ 試してみませんか?
私の家から聞こえたFM局は、多少ノイズが混ざる所も含めると、InterFM、beyfm、FM-FUJI、NACK5、TOKYO FM、J-WAVE、NHK-FM、FMヨコハマの8局です。
ヘッドフォンを耳に掛けた状態でネックコードをいっぱいに出し、窓際で試しました。
私の家は見通しのいいところにあるので条件がいいとは思いますが、それにしてもこの性能には恐れ入ります。
何しろ無調整で、高周波部として他に必要なのはアンテナだけですから。

はんだ付けがとても難しいですが、試してみたい方はご連絡ください。多少の余分を持っておりますのでご希望の方にお譲りします。
なおこのデバイスはラジオではありませんので、別途低周波アンプが必要です。あとI2Cでの制御手段もお忘れなく。

○ゆきさんがHPで作品を発表されています。 → 「ゆきの研究室」へどうぞ。

--

》カラーグラフィック液晶表示器 HDM1216C-2の制御

液晶ディスプレイ

リモコンに搭載した液晶は、HantronixのHDM1216C-2という液晶モジュールです。
有効表示エリアの寸法が28.8mm×38.4mm、厚さ3.3mmと非常に小さいのが特徴です。
120×160ピクセルのカラーグラフィック表示が可能で、LEDによるバックライトが付いています。

本当は携帯の液晶とかが流用できればいいのですが、仮に入手できたとしてもマニュアルがまず手に入りません。
この液晶モジュールは、それに近い寸法のものとして有用ではないかと思います。
私はmouserで入手しました。

液晶モジュールのマニュアルはこちら。
 → s1216c-2.pdf (180KB)
内蔵コントローラのマニュアルはこちら。
 → S1D15G00_REV1_0.pdf (439KB)

ところで、実際には思ったように動作させるまでにかなりの試行錯誤が必要でした。
要はコントローラICへの設定の仕方なんですが、マニュアルの情報だけで一発で動作させることはかなり難しいように思います。
ただ、わかりにくいのは最初だけで、わかってしまえば問題ありません。十分な機能があり、使える液晶モジュールです。


参考までに、Timpyでの初期化コマンド列とそのパラメータをまとめたものをあげておきます。
 → init-lcd.txt (3KB)
この内容で初期化すると、左の図のように、
 ○液晶の向きは、制御部(右の写真にて左側の緑の部分)を下にした、縦長配置。
 ○表示画面左上隅のピクセルのカラムアドレスは12、ページアドレスは0になる。
  右下隅のカラムアドレスは131、ページアドレスは159になる。
となります。カラムアドレスが0からではなく12から始まりますので注意してください。

パラメータを変更すれば、アドレスの増加方向を逆にできます。
例えばTimpyとは逆に、制御部を上に持って来るならば、左上を(0,0)、右下を(119,159)にすることもできます。



次は描画です。
描画する際はまず、カラムアドレスセットコマンドCASET、およびページアドレスセットコマンドPASETにより、矩形の描画領域を設定します。
CASETコマンドの2つのパラメータP1、P2により、それぞれ描画開始カラム、描画終了カラムを指定します。
同様にPASETのP1、P2にて、それぞれ描画開始ページ、描画終了ページを指定します。

あとは、ピクセルデータを連続して書き込むだけです。最初に書き込んだピクセルデータは、上で設定した描画開始カラム、描画開始ページの交点に表示されます。
以後書き込まれたピクセルデータは、描画開始カラム+1、描画開始カラム+2・・・と自動的にアドレスがインクリメントされた点に表示されていきます。
インクリメントされたカラムアドレスが描画終了カラムを超えると、ページアドレスがインクリメントされ、カラムアドレスは描画開始カラムへと戻ります。
これにより、設定した矩形領域に対して途中でアドレス設定を必要とせずに描画できるようになっています。
これはフォントデータの描画に適した便利な機能です。

この例ではアドレスのインクリメントがカラム→ページの順でしたが、設定を変えるとページ→カラムの順にもできます。リモコンの右端に90度回転した文字列が表示されていますが、その部分はこの機能を利用しています。


ピクセルデータは8ビットによる256色表示です。実際にはRGBSET8コマンドによって設定したパレットを介していますので、4096色中の256色表示(懐かしい響きですね)が正確でしょう。
具体的には赤3ビット+緑3ビット+青2ビットの8ビット構成です。この組み合わせによりピクセルの色を指定します。

--

》日本語フォント

フォントにはぞろよしさんによるフリーのビットマップフォント「k12x10」を使わせていただきました。
横12ドット×縦10ドットという横長サイズになっていて、小さいながら読みやすいフォントです。これを半角から第2水準まで全部使わせていただきました。
液晶が120×160ピクセルなので、全角でちょうど10文字×16行表示できます。

フォントはリモコン内のEEPROMに書き込んでおきます。描画時にはCPUがそれを読み出して、液晶へ送るようにします。
フォントデータだけで約140Kバイトあるので、EEPROMには1Mbitのものを2個、256Kバイト分用意しました。
フォントデータ以外の領域は曲データの保存などに使用します。

★ k12x10フォントのデータ構造
使用したのは、k12x10フォントの中でもFONTX2形式のものです。
FONTXについては、Leptonさんのページをご参照ください。テクニカルリファレンスの項に、データ構造の詳細が説明されています。

★ シフトJISコードとFONTXについての予備知識
フォントデータをそのままEEPROMに焼いてもいいのですが、処理の高速化と簡単化のため、少し手を入れることにしました。
ここではその変更部分に関して必要となる予備知識を説明します。

Shift-JISコードには多くの『歯抜け』領域が存在します。つまりコードの最小値から最大値までの間の、全ての値に文字が割り当てられているわけではありません。複数の未定義領域があります。
FONTX形式のk12x10フォントを例に挙げると、それに含まれている全角文字データの数は6962文字分です。一方、文字コードの範囲はシフトJISコードで8140h〜EAA4hの26981文字分です。つまり、文字コード8140h〜EAA4hのうち約26%しか使用されていません。

この関係を定義するため、FONTXの漢字フォントデータ構造では、フォントヘッダに続いて文字コードテーブルが用意されています。フォントビットマップ(Leptonさんのデータ構造ではフォントパターンと呼ばれている部分)が用意されている文字コード範囲をこのテーブルにリストしておくことにより、不連続な文字コードから連続したフォントビットマップへの対応付けができるようになっています。


左はk12x10フォントの先頭部分をダンプしたものです。
反転している領域が文字コードテーブルを示しています。

その1バイト目はテーブルのエントリ数です。よって文字コード領域は5Ch=92個に分断されていることがわかります。

2バイト目以降に、その各領域のコード範囲を示すテーブルが、4バイトずつ92個続いています。

この文字コードテーブルの後にフォントビットマップが続きます。フォントビットマップは、このテーブルで定義された分だけが存在します。
例えば左図では、最初の範囲は8140h〜817Ehで、2番目は8180h〜81AChです。したがって、その間の817Fhに対応するフォントビットマップは存在しません。817Ehのフォントビットマップの次は8180hのビットマップとなります。


1文字描画するたびにこのテーブルをスキャンするのはちょっと気が重い作業です。EEPROMとのインターフェースがI2Cなので、読み出しには相応の時間も必要です。
テーブルをいちいちEEPROMから読まずに、RAM上に置いておけば処理速度は改善されますが、貴重なメモリを368バイトも喰われるのは避けたいところです。
そこでこの文字コードテーブルを元に、文字コードからフォントビットマップのアドレスを簡単に求めることができる別のインデックステーブルをあらかじめ作っておき、それをEEPROMに書いておくようにしました。

★ EEPROM内のデータ構造

左はEEPROMのアドレスマップです。容量は256Kバイトです。
この中は大きく5つの領域で構成されています。

(A)半角文字フォントビットマップ
 ASCIIコード00h〜FFh、256文字分のフォントビットマップが収められています。

(B)全角文字フォントインデックス
 全角文字フォントビットマップへのインデックステーブルです。

(C)全角文字フォントビットマップ
 全角6962文字分のフォントビットマップです。

(D)パディング
 未使用領域です。

(E)曲データ
 液晶表示するための曲名やアルバム名、アーティスト名などの格納領域です。そのほか設定情報の保存領域なども含まれています。

(A)半角文字フォントビットマップ領域
ここにはASCIIコード00h〜FFhに対応する256文字分のフォントビットマップが収められています。
実際の内容は、半角文字フォントファイルk6x10.fntからフォントヘッダを取り除き、フォントビットマップだけにしたものです。
1文字あたり10バイトで、全部で2,560バイトです。
フォントビットマップのアドレスは下記の式で求められます。
    EEPROMアドレス=ASCIIコード×10d

例:半角文字"G"
"G"のASCIIコードは47hです。したがって、
    EEPROMアドレス=47h×10d
    =2C6h
このアドレスから10バイトが目的のフォントビットマップとなります。


上図で反転表示になっている10バイトがその該当部分です。
これを描画すると、左のようになります。


(C)全角文字フォントビットマップ領域
領域Bのインデックスの前に、まずこちらを説明しておきます。
ここは全角文字6962文字分のフォントビットマップが収められています。
k12x10では1文字あたり20バイトです。

(B)全角文字フォントインデックス領域
文字コードとフォントビットマップを対応付けるためのインデックステーブルです。大層なものではありません。力技です。
k12x10フォントがサポートする文字コード8140h〜EAA4h(EAA4h−8140h+1=26981文字分)と、6962文字分のフォントビットマップを、多対一で対応付けます。

このインデックスの実体は、文字コードの全範囲26981個の要素を持つ配列です。
そして各要素の内容は、対応付けるフォントビットマップの通し番号(0〜6961)です。番号のデータサイズは2バイトです。
対応するビットマップがないコードに対しては、フォントがないという意味で、下駄(〓)のフォントビットマップを指すようにしておきます。
下駄を指すために約40Kバイトも無駄使いすることになりますが、何にも使わずに空けておくほうがよっぽど無駄と割り切って、性能を優先することにします。

以上により、全角フォントビットマップを得るためには、次の2段階の手順を踏むことになります。

(B-1) シフトJISコードに基づいて、対応するインデックス値を読み出す
読み出すEEPROMアドレスは下記の式で求められます。
    インデックス値のEEPROMアドレス=(ShiftJISコード−8140h)×2+0A00h
ここで、2倍は要素のサイズ、0A00hはインデックス領域(B)の先頭アドレスです。
この式で求めたアドレスから、2バイトのインデックス値を読み出します。

(B-2) そのインデックス値に基づいて、対応するフォントビットマップを読み出す
読み出すEEPROMアドレスは下記の式で求められます。
    目的のフォントビットマップのEEPROMアドレス=インデックス値×20d+0DCCAh
ここで、20dは1文字あたりのバイト数、0DCCAhはフォントビットマップ領域(C)の先頭アドレスです。

以上のように、簡単なインデックスをあらかじめ作っておくことで、高速にフォントビットマップを読み出せます。
目的のフォントビットマップを得るためのオーバヘッドは、2バイトのインデックスを読むだけです。

例:全角文字"あ"

○まずインデックス値を得る
"あ"のシフトJISコードは82A0hです。したがって、
    インデックス値のEEPROMアドレス
    =(82A0h−8140h)×2+0A00h
    =0CC0h
このアドレスから2バイトがインデックス値です。
左に示したとおり、00D2hがその値となります。



○次にフォントビットマップを得る
B−2の式に従って、
    フォントビットマップのEEPROMアドレス
    =00D2h×20d+0DCCAh
    =0ED32h
となります。このアドレスから20バイトが目的のビットマップです。

上図で反転表示になっている20バイトがその該当部分です。
これを描画すると、左のようになります。めでたし、めでたし。



★ EEPROMにフォントを書き込むまでの手順
最後に、上記のような内容のEEPROMを作るまでの手順を簡単にまとめておきます。
記憶に頼っていますので、若干怪しいかも知れません。

(1)フォントファイルの入手
 ぞろよしさんのページから、k12x10フォントのDOS/V FONTX2形式(k12x10x.lzh, 83Kbyte)をダウンロード、解凍しておく。

(2)フォントファイル→EEPROMイメージデータファイル変換プログラムの準備
 変換プログラムmkromimg.cをコンパイル。私はフリーで使えるコンパイラbcc5.5を使用した。

(3)コマンドプロンプト上で変換実行
 > mkromimg.exe k6x10.fnt k12x10.fnt romimage.dat
 これにより、EEPROMへ書き込むデータファイルromimage.datが生成される。
 同時にこんなステータスが表示される。この値をメモっておき、描画プログラムの定数として使う。

(4)チェックサムデータ生成プログラムの準備
 mkimgsum.cをbcc5.5でコンパイル。

(5)チェックサムデータ生成
 > mkimgsum.exe romimage.dat imagesum.txt
 これにより、チェックサムデータimagesum.txtが生成される。

(6)EEPROMへの書き込み準備(ハードウェア)
 リモコン基板上のF310とPCを232Cで接続。もちろん直結はできないので、F310開発キットのターゲットボードに搭載されているレベルコンバータを利用する。
 ○リモコン基板のGNDと、ターゲットボードのGNDを接続。
 ○リモコン基板のF310のP0.4と、ターゲットボードのJ3のTXピンを接続。
 ○リモコン基板のF310のP0.5と、ターゲットボードのJ3のRXピンを接続。
 ○リモコン基板のVCC2と、ターゲットボードの+3VDを接続。
 ○リモコン基板とシリアルアダプタEC2を接続;。
 ○ターゲットボードの9ピンDサブコネクタと、PCのCOMポートを接続。
 ○ターゲットボードにACアダプタを接続(電源ON)。

(7)EEPROMへの書き込み準備(ソフトウェア)
 SiLabsのIDEでプロジェクトを作成し、ダウンロード用ファームウェアtimpy-r-eeprom.asmをアセンブルし、F310へダウンロード。
 このソースには不要な部分がたくさん残っているが、気にしない。

(8)PC側の準備
 ターミナルプログラムTeraTermをインストール。
 ターゲットボードと接続したCOMポートで接続。1200bps、8ビット、パリティなし、ストップ1、フロー制御なしに設定。

(9)書き込み実行
 ○IDEでF310の実行開始。
 ○TeraTermのメニュー"File"→"Send File..."にて、(3)で作成したromimage.datを送信。
 ○うまくいけば同時にTeraTermのターミナル上に、F310から返ってきたチェックサムデータが順次表示されていく。
 ○送信完了後、返ってきたチェックサム文字列をエディタへコピペし、テキストファイルとして保存。FCなどで(5)で作成したimagesum.txtと比較し、一致すればめでたく完了。

・・・と、こんな感じです。プログラムを多少いじれば、他のフォントにも使えます。組み込み用途で漢字表示が必要な場合の参考にどうぞ。

--

》本体−リモコン間の赤外線通信

★ 赤外線による双方向通信
ヘッドフォンとリモコン間は赤外線で通信します。
通信距離として50cmは確保したいことや、蛍光灯や日光などの外乱が多い電車の中で方向に関係なく通信したいことを考慮して、IrDAではなく変調光を使うことにしました。
ただしヘッドフォン→リモコンへの通信では、曲名データなどかなり情報量が多いので、一般に良く使われる38kHz近辺の変調光ではビットレートが不十分です。
そこでいろいろ探していたところ、運よく455kHz変調のリモコン用受光素子を見つけました。
データシート上では20kbpsまでOKとなっています。
とりあえず9600bpsで実際に試してみました。室内ではありますが、問題なく通信できました。これならあまり大きなLED電流を設定しなくても実現できそうです。
送信側のLEDには、寸法の制限からφ3の砲弾型が欲しいところです。発光波長も合っていなくてはなりません。これも探しに探してようやく2個入手できました。

リモコン→ヘッドフォンの方向にはそれほどの情報量はいらないので、一般的な38kHz変調のデバイスを使います。
でも、一般的なのは変調周波数だけで、ここでもひとつ問題が。それは受光素子の大きさです。
普通に入手できる受光デバイスでは、とてもヘッドフォンの空きスペースに収まりそうもありません。
これもいろいろ探して、ようやく4.5mm×2.8mmという超小型の受光素子を見つけました。
個人なので入手できるかどうか不安だったのですが、何とかお願いして分けてもらうことができました。

★ 赤外線通信と消費電力
携帯機器において、低消費電力化は重要なテーマです。
しかし赤外線通信に必要な電力はばかになりません。
変調光方式なので、通信距離を考えるとIrDAほどは必要ありませんが、それでもLEDに相応の電流を流す必要があります。

ところで、Rev4.0の構成を考えると、いくつかの特徴が挙げられます。
 ・赤外線通信が必要なのはリモコンを使うときだけです。また、リモコンがいつ使われるかは分かりません。
 ・受光モジュールでの消費電流は、LEDに流す電流よりもずっと小さいです。
 ・リモコンを使っている時間より、ヘッドフォンを使っている時間のほうがずっと長いです。したがってヘッドフォン側の方をより節約できることが望ましいです。
これらを考慮して、通信の開始は常にリモコン側から行うプロトコルにしました。

ヘッドフォン本体側は、通常受信可能状態にしておきます。
ユーザがポケットからリモコンを出して電源を入れ、何らかの操作をすると、リモコンはそれに応じたコマンドを発行(発光?)します。
受信状態にあるヘッドフォン本体は、正常なフォーマットでコマンドを受信できたら、実行結果のデータを返すようにします。
これにより、ヘッドフォン側でのLED発光を最小限に抑えることができます。
さらに、受光モジュールの電源もポートI/OでON/OFFできるようにしてあります。
このプロトコルと回路構成によって、赤外線通信による電力消費を極力低減しました。

もちろんプロトコルにはエラーチェックや、エラー時のデータの再送手順、タイムアウト処理などを盛り込んであります。

★ リモコンに表示する曲名などの情報は、ヘッドフォン側から転送する
TimpyでのMP3データは、ヘッドフォン本体側のカード内にあります。リモコン側には何もありません。
リモコンの液晶に曲名やアルバム名、アーティスト名などを表示するためには、ヘッドフォン側からそのデータを全て送る必要があります。

Rev4.0では、リモコンに『シンク(Sync)コマンド』を用意しました。
これは、カード内にある全てのMP3ファイルのID3タグを読み取り、リモコンに転送するコマンドです。
これにより、リモコンで表示するためのデータが準備されます。

カードを入れ替えた時にはシンクコマンドを実行するようにします。
リモコンに送られたそれらのデータは、リモコン内のEEPROMに保存されます。
電源を切っても残っていますので、シンクコマンドはカードを入れ替えたときだけでOKです。


Rev4.0のページへ戻る

ページの先頭へ戻る

ご質問などは掲示板へお願いします

HOME