マイコン工作実験日記

Microcontroller を用いての工作、実験記録

再生画面を作ってみた

2009-08-02 23:36:57 | MP3プレーヤ
ID3タグ情報のデコードができたので、この情報をLCD画面に表示してみました。いちおう、カミさんのiPodの画面を真似てこさえてみたつもりです。LPC2388でLCD表示させるのもずいぶんと久しぶりだなぁ。



フォントは昨年W-SIMタッチパネル・ジャケットを製作した時に使ったIPAフォントから英字部分だけをビットマップ化したものを使っています。したがって、日本語の曲名とか歌手/演奏者名なんかはいまのところ表示できないわけです。もちろんIPAフォントには漢字も含まれていますが、LPC2388のフラッシュに収納できる容量ではないので、フォント用のストレージを用意せねばなりません。使用しているLCDにはフラッシュメモリが搭載されているので、これにフォントを保存して使ってみようかと考え中です。

LCDはタッチパネル搭載でもあるので、タッチ操作できるようにもするつもりでいますが、ゆくゆくはということで。。とりあえずは、フォントの方から検討を進めるつもりでいます。

ID3タグ

2009-07-31 23:32:29 | MP3プレーヤ
ひさしぶりにLPC2388基板を引っ張り出しました。

まがりなりにもMP3とFM放送の再生ができるようになり、最低限必要な基本機能は用意できましたが、あまりにもそっけないので、少しは見栄えのする一般機能も順次付け加えていこうかと思います。まずは、MP3で再生中の曲の情報でも表示できるようにしようと決めて、調べてみました。ID3タグと言うんですか。白状してしまうと、これまでMP3プレーヤを作るどころか使ったことも無いので、こういう知識が全くありません。

ID3にはバージョンもいくつかあるようですが、ファイルの頭に入っているID3v2をデコードしてみることにしました。MP3ファイルの再生時にいつも先頭を読み飛ばしていたのは、この領域だったのですね。表示するタグは、とりあえずTIT2(曲名), TLEN(長さ), TPE1(演奏者)の3つとしてみました。(32文字で切ってます)



文字列はUTF-8対応できる形式になっているようですが、実験に使っているMP3データではUTF-8は使っていないようです。びっくりしたのは、同じCDに入っている曲のデータなのにもかかわらず、トラックによって文字列データがシフトJISや半角ASCIIで入っていたりとメチャクチャなこと。「自分で編集しなおして使うもの」というのが常識なんでしょうか?それとも、たまたま題材にしたアルバムのデータの出来が悪かっただけ? いくつか半角に修正してみたものの、途中でメゲました。

最後に表示しているのは、演奏状態です。例では全20トラックの8トラック目を演奏中であり、およそ28%の位置ということです。コーデックのI2Sを12MHzのクロックで動かしている都合上、本来は44.1KHzのサンプリング・レートで再生すべきところを、実際には44.117KHzで再生しています。そのため、長い曲になると早めに再生が終わってしまうのがわかるかもしれません。

USBスピーカからのFM再生

2009-06-30 23:10:12 | MP3プレーヤ
FMチューナからの音声出力をCodec経由でI2Sで受けて、USBスピーカから出力できるようにしました。



USBスピーカへの出力はすでにpcmsender_taskとして用意してあるので、新たにI2S入力から受信したFM音声データをpcmsender_taskに渡すタスク(tuner_task)を作ってやっただけです。



player usbで出力先としてUSBスピーカを選択しておき、fm startコマンドにより、tuner_taskが起動されることでUSBスピーカからの出力ができます。pcmsender_taskは I2Sへの出力もできるので、結果的にI2Sで受けたFM音声データをI2Sへ送り戻すことでヘッドフォンから再生することも可能です。しかしながら、I2S受信も割り込み処理で受けているので、送受ともに割り込みで受けることになります。実際に試してみると、割り込み処理負荷が増えた結果、データのとりこぼしが発生してしまいます。割り込みでFIFOのデータを送受するのではなく、DMAを使ってデータの送受をした方が良さそうです。

また、現在はtuner_taskはplayer_taskの配下にはないので、操作を間違えるとtuner_taskとmp3decoder_taskの両方を走らせることもできてしまいます。player_taskで一元的に管理して、操作性も良くするような改善が必要だと考えています。

FMを聴いてみる

2009-06-22 23:17:13 | MP3プレーヤ
FMチューナAR1010は、AR1000とソフト的にはほぼ同一であるので以前実験に使ったコードをそのまま流用します。もっとも、以前はAT91SAM7SでしたのでI2C部分はLPC2388に書き換え、I2C1を使うことにしました。

まずはI2Cを操作することでの選局です。受信感度の数字から、ちゃんと指定した周波数で選局できていることが確認できます。



続いて実際に音を聞いてみることにします。FMチューナの出力はMMcodec01のLINE入力につながっています。Codecの入力としてLINEを選択してやれば、CodecのI2S出力端子からはFMのステレオPCMデータが出力されるので、これをCodecのI2S入力に戻してやればヘッドフォンから再生することができるわけですが、そんなまどろこっしいことをしなくても、Codecのバイパス機能を使えばCodec内部で折り返すことができます。Codec内部での折り返しなので、LPC2388はaudioパスには直接は関与しないのですが、ヘッドフォンの音量をI2C経由で制御できますので、FMチューナ機能をサポートするにはこれだけでも用が足ります。

MP3再生の時と出力レベルの大きさに差異が生じないか心配でしたが、実際に実験してみると、FMチューナの出力を最大にしてCodecのライン入力では+0dBから+3dB程度を選択してやると、音量的にはちょうど具合が良いようです。

いちおうこれでヘッドフォンでのFM再生はできましたが、バイパス機能ではUSBスピーカからの再生はできません。そこで次はちゃんとI2S経由でFMチューナ出力を取り込んで、USBスピーカから再生させることにします。

FMチューナを追加

2009-06-18 23:12:13 | MP3プレーヤ
昨今のMP3プレーヤの自作にはFMチューナも欠かせないもののようですから、こいつ↓を追加してみました。



使用したのはSparkfun取り扱いのAR1010ボードです。すでに以前AR1000を使っての受信実験までは記事にしていますが、そのまま放置状態になっていました。そのAR1000を使っても良かったのですが、何ヶ月か前から使用チップがAR1000からAR1010に変更になったうえに2.54mmピッチのボードが用意されたので、これを新たに購入してみた次第です。AR1010になることで何かイイコトがあるのではないかと期待していたのですが、実際にデータシートを読んでみるとAR1000からRDS機能を削ったのがAR1010であり、むしろAR1000の廉価版のようです。日本国内ではRDS機能は使えないので機能的にはAR1010で充分なのですが、機能拡充を期待していたのでちょっとガッカリ。それでも、2.54mmピッチになって配線が容易になったので、今回はこちらのボードを使うことにしました。



FMチューナのオーディオ出力はそのまま直接MMCodecのLINE入力につなぎ、TLV320AIC23経由でヘッドフォンとUSBスピーカから出力することにします。MMcodec01にはオーディオ入力用のジャック(LINE)が載っているので、ボードに直接配線することはせずに、100円ショップで買ってきた2.5mmプラグの延長コードをぶった切ってつないでみました。配線は簡単でいいのですが、さらに不格好になってしまいました。

再生制御機能 -- その2

2009-06-15 22:53:55 | MP3プレーヤ
前回の記事で書いた再生制御機能を実際に使った様子を、掲載しておきます。



  • まず最初にplayer usbにより、出力デバイスとしてUSBスピーカを選択しています。
  • つぎに、player insertによりSDカードが挿入されていることをplayer_taskに通知してやります。するとplayer_taskではSDカードのディレクトリを走査し、MP3ファイル名を集め、その総数を表示します。
  • player playにて1曲目の再生が開始されます。この処理は、player_taskが1曲目のMP3ファイル名を渡してmp3decoer_taskを起動することで実現されています。
  • player pauseにより再生の一時休止が行われ、player playにより再開されます。これらの処理は、player_taskからmp3decoder_taskを休止(sus_tsk)ならびに再開(rsm_tsk)することで実現されています。
  • 停止操作は、mp3decoder_taskが参照するフラグをセットすることで停止を指示しています。


この他にも、次の曲へスキップするnext, 曲の最初から再生し直すrewind, そして前の曲へ戻る prevコマンドを用意したので、最低限の選曲/再生操作がおこなえるようになりました。現状ではSDカードのルート・ディレクトリにMP3データが入っていることを想定しており、アルバムをディレクトリ配下に入れることを想定していません。この点は、今後の課題のひとつです。

再生制御機能

2009-06-13 21:50:32 | MP3プレーヤ
LPC2388でI2S経由のCodecとUSBホスト経由のスピーカのどちらからもMP3を再生出力できるようになったのはいいのですが、まだまだ実験的な操作性ですので、これをちょっとは改善していこうかと思います。現状はシリアル・コンソールから再生を開始してしまうと、曲の最後までの再生が終了するまでの間、音量調節や再生の停止すらできません。とっても不便なので、まずはこの問題から改善することにしました。

考え方としてはプレーヤ制御を担うタスクを新たに用意して、シリアル・コンソールタスクから分離させればいいだろうということで、全体のタスク構成を次のようにしてみました。



mp3decoder_taskがMP3のファイルをひとつデコードして再生するタスクの本体です。このタスクを制御するのが、新たに用意するplayer_taskです。このタスクは外部から再生操作指示のイベントをもらい、その指示に応じてmp3_playerタスクを起動/終了させたり、休止/再開させることとします。操作指示を与えるためのボタンとかはまだ存在していませんので、当面はシリアル・コンソールからのコマンド入力により操作指示イベントを生成させることとします。

mp3player_taskではSDカードからMP3ファイルを読み込み、そのデコード結果をダブル・バッファに書き込んでいきます。mp3player_taskがデコード作業中にpcmsender_taskは、すでにデコードされたPCMデータを別のバッファから読み込んで、出力先のCODECあるいはUSBスピーカへ出力できるようにリングバッファに詰め込み直しています。USBスピーカの場合には、OHCIの出力のためにTD(Transfer Descriptor)の作成もおこなっていますので、実際には両者が使用するバッファの形式は異なっていますが、アドレス空間としては同一のDMA可能な空間を利用しています。

SDカードからの再生

2009-06-07 18:57:06 | MP3プレーヤ
LPC2388のUSBホスト機能を用いてスピーカを鳴らす作業はいくつかの点でつまづいたものの、スピーカが鳴り始めています。この点については次回にでも記事にすることとして、きょうはSDカードからMP3ファイルを読み込んで再生する部分についてです。

SDカードのアクセス部分については、基本的にChaNさんのコードを流用させていだきました。FatFs R0.07を使っていますが、今回はLFNのサポートは落とし、読み取り専用にコンフィグして利用することとしました。MCIのドライバ部分については、コマンドの終了待ちと転送の終了待ちの部分でポーリング待ちするようになっていたので、これらについてはTOPPPERS/JSPのSemaphoreを使って待ち合わせするように変更しています。

MP3の再生部分のコードも、メモリ内の配列データの再生ではなくSD上のファイルから読み込んだデータを再生するように修正。これでようやくと、1曲まるまるデコードしてMMcodec01から再生出力できるようになりました。実際に聞いてみると、1曲の再生中に数回「ブツッ」と音がすることに気がつきました。どうやら、Codecへの出力処理が間に合わないことがあるようです。調べてみると、codecの割り込み優先度がMCIからの割り込みより低くなっていたので、codecからの割り込みを最優先にしたところ問題解決。



cplayコマンドで再生するファイル名を指定しているのですが、全文字指定するのも面倒なので、指定した文字数分だけマッチする最初のファイル名が見つかった時点で、再生ファイル名を決定しています。WMPでエンコードするとトラック番号がファイル名の最初に付くようですね。



SDカード・ソケット基板

2009-05-31 21:44:20 | MP3プレーヤ
これまでフラッシュに曲データを書き込むことで、SDカードを使わずにMP3再生の実験を進めてきましたが、やはりここらでSDカードをつなげることにしました。フラッシュの書き込み待ちに耐えられなくなってきたためです。



なにしろ曲データだけで400KBあったので、プログラムを合わせると書き込みサイズは500KBを超えています。JTAGを使って書き込んでいるのですが、(1) ELFファイルの読み込み、(2)フラッシュへの書き込み、(3)ベリファイの3つの段階を合計すると3分ほどかかるようになってしまったのです。曲データを小さくすれば時間かかりませんが、再生時間も短くなってしまい、おもしろくありませんし。



インターフェース6月号というかChaNさんHPの記事のとおりの回路です。手持ちの部品で作ったとはいえ、とてもわたしにはChaNさんように小さくきれいにまとめることはできません。


LPC2388の I2C と I2Sを使う

2009-05-20 23:40:29 | MP3プレーヤ
MMcodec01をつなげるハードの準備(と、言ってもコネクタだけですが)ができたので、ソフトの作成です。MMcodec01に載っているTLV320AIC23Bを使うには、レジスタの設定に使用するI2CとPCMデータ出力に使用するI2Sのふたつのインタフェースのドライバを用意してやる必要があります。

まずはI2Cから。LPC2388のI2Cの使い方は、AVRとほぼ同じだったのですぐに理解できました。TLV320AIC23Bのレジスタへの書き込みは、16bitでレジスタ番号と書き込むデータを指定するのですが、レジスタ番号を7ビット、データを9ビットで指定します。ついつい、8ビットづつだと勝手に思い込んでしまい、しばらくハマッテいました。

いつもの手順だと、まずI2Cを動かしてレジスタの読み書きができることを確認して一安心するのですが、TLV320AIC23Bのレジスタは書き込み専用で読み出しができません。そこでI2Sマスターに設定した後、Sample Rate Controlレジスタを書き込んでクロックを生成させてみることで動作確認しました。Sample Rateを44.1Kに設定すると、BLCKから12MHz, LRCIN/LRCOUTから44.1KHzが出てくることが確認できて、一安心です。

続いてI2S。こちらは44.1KHzとか48KHzというクロックに同期してPCMデータを送出するインタフェースです。したがって、このレートに間に合うようにデータを次々と書き込んでやらねばなりません。割り込みで処理するにしてもこのペースはつらいので、LPC2388では8レベルのFIFOが用意されています。FIFOに溜められたデータが順次送出されていき、FIFOの残りが指定されたレベル以下に達すると割り込みをかけることができます。FIFOの残りレベル数もレジスタで確認できるので、割り込み処理ではFIFOがいっぱいになるまで送出データを書き込んでやります。送出するデータがなくなったら、割り込みを禁止して演奏終了となります。今回は、レベルが3になったら割り込みをかけるように設定してみました。

MP3デコーダとつなげてやって、再生実験です。本来であればMP3のデコード結果から検出したサンプリングデータに基づいてTLV320AIC23Bの設定をする必要があるのですが、今のところCDから取り込んだ固定曲データですので、44.1Kで決め打ちにしています。以下、実行の様子。最初のmp3コマンドは、前回と同じダミー再生です。その後、codec init によりTLV320AIC23Bを初期化。playコマンドでデコードの結果生成された16bit PCMをI2SでTLV320AIC23Bに送っています。



MMcodec01につなげたヘッドホンからきれいに音が出てきました。嬉しい! 再生時間も元データと同じ16秒程度になり、割り込み処理も問題なく間に合っているようです。