« 2009年12月 | トップページ | 2010年2月 »

2010年1月の4件の記事

2010年1月27日 (水)

量産を目指したリニアPCMプレーヤー3号機完成

 Olimexに8枚も基板を発注して量産を目指しているSDカードを使ったリニアPCMプレーA1272647 ヤー(3号機)の1台目が遂に完成した。途中致命的な誤りを見つけて肝を冷やしたが、何とか想定どおりに実装が済んで動き出した。素直に嬉しい。ま、プロジェクトというものは必ずどこかで思わぬ障害にぶつかるもので、これを乗り越えてゴールに辿りつくからこそ、大きな感激になるというものだ。まあ今度もその顛末(てんまつ)を聞いてください。

1号機もハードでDACをドライブする(1/20/10)
 Olimexからfax received(FAX届いたよ)の2語メールが来て1週間後、1/15に例のshipped(出荷したよ)の1語メールが来た。いつもより遅い。発送から到着までは、前回の例や、ウェブなどを見ていると、航空便なのに12日から2週間ぐらいかかる。基板の到着は、今月末になりそうだ。時間があるので、ジッターのないDAC再生にもう少しこだわってみた。

 DACのデータ送り出しのタイミング(LRのトグル)をソフトでなく、タイマーのハードで制御することで、仕様上のジッターを0にする(勿論、水晶発振子のジッターは残るが)ことが出来るようになったのは、前回の記事のとおりだが、パラレルのLCDを使っている1号機には適用していない。

 このプレーヤーは自分がいつも持ち歩いており、音に慣れている。こいつを直すと、もしかしたら音が変わったことが分かるかも知れない。ブレッドボード上のプレーヤーはコンデンサーが違うし、配線が長いためか時々小さいビートが入ったりしてリファレンスにならない。

 変更はブレッドボードのようにジャンパー1本というわけにはいかない。久しぶりにねじ止めした基板をはずし、半田ごてでピンの位置を替える。パラレルのLCDの制御線とぶつかったが、このLCDのドライバーは以前、自由にピンを選べるようにした自信作である。ヘッダーファイルの変更だけで簡単に位置をずらせた。ソフトはこうあらねばと上機嫌で作業する。

 何事もなくファームの書き換えもすみ、1号機の改修は終わった。音を聞いてみる。正直なところ前と変わらない。しかし、何となく音が静かな感じがする。もちろん気のせいでしかないが、昔々、4~5万クラスの安物のCDプレーヤーから20万近い高級CDプレーヤーに替えたときに少し似ている。このときも始めは「おとなしい音になった」という印象があった。前のプレーヤーの賑やかな音に較べると派手さに欠けた。しかし、音の情報量、定位、解像度は格段に上がっていることが聞き込んで納得できた。

 今度も、何か、そんな気がする。落ち着いて音を聞いていられる。オーディオの怖さは、思い込みで聞いている音が変わるところで、ジッターがなくなったというだけでこれだけ音が違うように感じるのだから人間の思い込みというのは怖いものである。気のせいに違いないが、もしかしたら本当に音が変わっているのかもしれない。

Olimexの基板が予想より1週間早く着いた(1/22/10)
 基板が来るまで、まだ日にちがあるので、CDケースの角を利用した電池フォルダーをぼちぼち作り始めた。何しろ受注残は8台である。このあいだ買ったサーキュラーソー(丸鋸盤)が大活躍である。細刃は予想通り、きれいにプラスチックを切り出し、面白いようにフォルダーが出来ていった。A1232617

 ところがshippedのメールが来てからわずか1週間で、Olimexから基板が書き留めで届いてしまった。嬉しい誤算である。早速、梱包を解く。8枚の基板が何重にもラップにくるまれて出てきた。いやいや、これから忙しくなるぞ。

 今度の懸案は、新しいフォンジャックである。とるものもとりあえず沢山買って来てある現物をつけてみる。うーむ、A1272638 入らん。いや、端子がカーブしているからだ。ペンチで少し戻して慎重に入れていく。よーし、入った。位置決め用のホールもピッタリだ。

 他はすべて前の部品なので今度の基板はこれで大丈夫だ。組み立てに必要なリソースはすべて揃った。残る懸案は、これが予定したとおりケースに収まるかどうかである。

やっぱり間違えていた(1/23/10)
 早速、組み立てにかかる。今度の基板は、表裏をひっくりかえし、LCDパネルのある表側はハンダ面である。電池フォルダーを新設したので高さを確保するためだ。ケースがスケルトンなのにハンダ面が上に来て、折角のパーツが表から見えなくなって少しさびしいが、これまでの、ケースに電池接点基板を接着剤で固定する方法は、位置決め、接着の確認に時間がかかる上、とても神経を遣う。プレーヤーの量産のためには眼をつぶるしかない。それに高さが生まれたので低音増強のための200μFの大型パスコンが入れられる。

 例によって表面実装部品からハンダ付けしていく。LCDは裏側につくのでピンの位置も逆になっている。タクトスイッチも逆だが、これは左右対称なのでスイッチの順番を変えただけで問題ない。充電中を表示するLEDもハンダ面につける。

 LCDをつけようとピンを確認した時、とんでもない誤りに気がついた。裏につけるためLCDのピンアサインは逆にしたが、ピンヘッダーの位置は替えていない。あ、あ、もしかしてLCDの位置がおかしいか。LCDモジュールのピン位置は基板に対して左右対称でない。うはあ、いけない。逆につけられたLCDはケースから横にはみ出してしまった。

 発注する前から、基板を裏返しにした時の対応に何か抜けているのがあるかどうかどうも不安だった。その不安は的中した。これではケースに入らない。同じ基板が8枚もある。頭から血が引いていく。これからどうしたら良いか。

 気を取り直して、状況を調べる。はみ出した幅は、数ミリだ。幸い、液晶部分までは行っていない。LCDの基板部分を切り取れば入るかもしれない。おおお、はみ出ている部分は、このLCDモジュールで使っていないバックライトの配線部分だ。何やら横にチップ抵抗が乗っているが、そもそもバックライトがないのでこれを切り取っても本体に影響しない。

 しかも、サーキュラーソーを買ったので、基板を数ミリ幅で切り出すことはそう難しくない。これはなんとかなりそうだぞ。粉がかからないように液晶面をビニールでラップし、慎重にセットする。刃は基板切り出し用のダイヤモンド研磨刃である。A1272640

 見事に切れた。あっというまの作業である。液晶部分についた削り粉を刷毛で慎重に除去する。切り口もきれいで、何の問題もない。基板につけてみる。問題なくケースに入る。良かった、良かった。勢い込んで、手持ちのLCD全部を一緒に切り取る。

 いやいや俺もついている男である。液晶が載っている基板の横を数ミリ幅で切り取るなど、手でやることはほぼ不可能に近い。やすりで根気良く削れば出来るかもしれないが、削っているうちに部品を壊してしまう恐れが強い。サーキュラーソーを買っておいて本当に良かった。

何事もなく動いた(1/25/10)
 プリント基板のハンダ付けはいつもながら楽しい。プラモデルのように眼に見えて形になっていくのでつい夢中になる。新基板の3 号機は日曜半日の作業で完成した。ケースの加工をミニルーターで手早くすませてケースに入れてみる。これまで使っていたタクトスイッチの背が高すぎるのでこれは買い直す必要があるが、あとは順調だ。LRCKのジャンパーは最初に済ませてある。A1272641

 待ちきれなくなって、スイッチ部分も仮配線し、通電する。よーし、音が出た。あれ、ボリュームが逆だ。いけない。またここにもバグがあった。配線図を見たが、このボリュームは逆配線が出来ないことがわかった(2連抵抗の一方がコモンになっている)。このボリュームは部品面におかないと通常の左->小、右->大の状態にはならない。これは今さら無理だ。まあ、それほど致命的なミスではない。

 A1272644仕事の帰り、久しぶりに秋葉の千石によって適当な高さのタクトスイッチを調達する。ついでに秋月で、不足している3.3Vのレギュレーターを補充した。今度のプレーヤーは50mA程度しか消費しない。秋月で新しく出た、150mAの低ドロップ型のレギュレーターをこの先の量産用に入手した。いつもの500mAに較べれば半額だ。

 帰宅して最後の作業である。化粧面のタクトスイッチの穴 は用心して小さい穴をまず明けておき、カッターで広げる。このあたりの穴が不揃いだとA1272643みっともないものだ。ぴったりの穴が空いた。養生のテープをはがして、LCDの保護フィルムもとり、すべてを組み立てて、試聴する。至福の時間だ。ハンダ面のスケルトンも、まあこれはこれで趣のある感じがする。

 1台目が完成して、残りの生産の見通しが立った。2号機のような作業面での難しさはない。単純な作業の組み合わせで出来るはずである。そろそろ別のプロジェクトを立てる余裕が出てきた。やっぱり次は フォトフレームかなあ。しかし、先日、秋葉で\2000で5インチのA1272635液晶フォトフレームが安売りされているのを発見して少しがっくりしているところだ。

ここに、ハードでLRCKをトグルするバージョンV41のソースコードと、EAGLEの基板、回路ファイルをzipにかためたものを置きます。EAGLEのファイルは、上記の問題を解決したデータになっていますが、動作確認はしておりません。そのおつもりでお使いください。また、ソースコードはAVRstudioの形で、プロジェクトファイル名が前と変わっていないので注意してください。

(2011/2/12) WMPで作成したWAVファイルも再生するバージョンをV42として置きます。

***ご注意*** 以下のV41,V42版は、LRがpauseや再生中止のあと逆転するバグがあります。最近の記事にアップロードしたV43をお使い下さい(3/17/2013)

「mLPCM328V41.zip」をダウンロード

「mLPCM328V42.zip」をダウンロード

要望があったので、パラレルLCDを使った1号機のソースコードを下に置きます。形式はこれまでと同じAVRstudioのプロジェクトファイルです(2/6/10)。 下のV42も上のV42と同じです。

「SDPCM328V41.zip」をダウンロード

「SDPCM328V42.zip」をダウンロード

| | コメント (25) | トラックバック (0)

2010年1月18日 (月)

3号機のソフト改善とSTM32Primer2の改修

ジッターを実測する(1/10/10)
 SDカードを使ったリニアPCMプレーヤー3号機のソフトの改善は、演奏中の経過表示に成功して一段落した。 ハードの方は、2回目の基板を発注したOlimexから、fax  receivedのメールを受け取ってもう1週間近くなるが、まだ出荷の知らせはない。正月明けなので遅れているのだろうか。

 当面やることがなくなったので、このあいだ入手したSTM32Primer2でもテストしてみようかと考えていた時、ふと思いついたことがある。リニアPCMプレーヤーのジッターの問題である。CPUのクロックのジッターより小さいということで、無視できるとしたが、やはり気にかかる。本当に無視できる遅れなのか実測することが出来ないか。

 DACの割込み用タイマーは、比較一致が起きて割込みルーチンに制御が渡ったとき、既に次のカウントがスタートしている。このカウンターの値は取得可能だ。DACのLRCKをトグルして、データを送り出した直後に、この値をどこかに記録して調べればよい。

 問題は、膨大なデータが出てくるので、それをどうするかである。データの殆どは同じ値で割込みが重複した時だけ1~2クロック遅れた数になるはずだ。こういう変動なら、直前のデータを残しておき、前と違ったらカウントしていってその合計を1/2すれば変動したおおよその回数が求められる。うまくいきそうだ。Oca_toggle

 思いついたらやらずにおれない性格である。早速、AVRstudioを立ち上げ、コードを入れてみた。値は、演奏を中断した時にLCDに出す。これが驚いたことに、予想よりはるかに大きな値があらわれた。10秒の演奏で数千回という数字だ。Tick割込みは1秒、3300回なので10回に1回は割り込みが被っている勘定になる。ええー、そんな馬鹿な。これはおかしい、そんなに多いはずがない。念のため、Tick割込みのない前のバージョンV3に戻って同じコードを入れて測ってみた。

 うひゃあ、同じ数字だ。何だ、何だ。これはどういうことだ。AVRのタイマーリソースはシステムクロックである。全く同じクロックで動いているのに、割込みのタイミングで既に1クロック以上のずれがある。わけがわからなくなってきた。割込みルーチンに条件分岐があるとは思えない。一体これはどういうことなんだろう。

 タイマーの値は、36と37であることがわかったので、今度は、これ以上の遅れのときだけ測ってみた。すると、さすがにTick割込みのないV3では、どれだけ長時間測っても、数回にとどまった。測った時間に比例しないので、これは恐らくスタートと中断の時のカウンターのずれだろう。

 いよいよ、Tick割込みを入れて経過時間を表示するバージョン4の測定だ。38以上のときのみカウントする。おお、数字がでてきた。秒をセクターから計算して正確な値を出す。メディアを替えて、数十回測る。平均では、1秒に20回から25回起きている。この数字は、DAC周波数(88.1khz)を、Tick割込みの周波数(300μsなので3.3khz)で割った数字、26.7に極めて近い。

 素晴らしい。このあいだの計算が合っていた。1秒間に8万8千回起きている割り込みの中での20数回は極めて小さい数字だ。やっぱり、UIは0.0004ではなくこれより2桁ほど小さい値になっていることが確かめられた。

ロジックアナライザーで確かめる(1/11/10)

 100ns(2ステップ)以上遅れるサンプリングの回数はわかったが、それがどれくらいの遅れになっているのかはわからない。ロジックアナライザーならサンプリング周波数を高くすれば、実際の眼で確かめられるが、膨大なサンプルから、ジッターのところを探し当てるのは不可能に近い。

 しかし、このジッター実測のカウントするところでI/Oポートを叩けば、目印になって見つけやすい。勢いに乗ってこれも実験してみた。ロジアナのサンプリング周波数を20Mhz以上にすれば分解能は50nsになるので1クロックの差が見える。Lpcmv4jitter

 測定の結果、遅れは予想通り、2クロック遅れが最大でそれ以上の遅れは出ていないことがわかった。そしてDAC割込みの遅れは31~35ms間隔で発生していることがわかった。良かった。頻度から言えば、3000サンプルに1回である。ソフトで実測した値とピッタリ一致する(理論値の1/2だが)。UIは、遅れを100nsとして平均では0.000003である。殆ど無視できる値だ。満足、満足である。

Tick割込みの影響を0にする方法があった(1/12/10)
 ところが、これまでの話を一挙にくつがえす有力な情報が入った。 いつも的確な助言をしてくれて、お世話になっているkugaさんからの前回記事への久しぶりのコメントである。

 コメントにもあるように、コンペアマッチのタイマーには、比較値と一致すると割り込みが起きるだけでなく、出力ポートを叩いてくれる機能があるが、これにトグルする機能もあるというのだ。PWMなどの制御に使うものらしい。0とか1にするというのは知っていたがトグルする機能があるとは知らなかった。

 えー、本当?あわててデータシートを見る。ちゃんと書いてある。いやあ知らなかったなあ。トグルできるのなら、これまでのジッターの検討もへったくれもない。これをLRCKに使えば、この動作はハードで動くのだから、Tick割込みの遅れの影響は仕様上ゼロになる。

 いやいや、知らないと言うことは恐ろしいことである。一気に解決してしまった。しかし、これを実現するためには、これまでのピンアサインを変える必要がある。恐る恐るソースコードを調べる。DAC割り込みに使っているタイマーは、TIMER2で、このコンペアマッチの出力ポートは、あー駄目だ。SDカードのSPIに使っている。

 いや、待てよ。TIMER0のトグル出力ポートOCA0はPD6 というロジアナのプローブに使っている空きポートだ。TIMER0は、現在SDカードや、タクトスイッチの監視に使っている。こいつをそっくりTIMER2(DAC割込み)ととりかえてしまえば良い。良かった。大幅な変更をしなくて済む。すっかりスワップしてしまえば、このポートは、今のLRCKの隣のピンだ。今発注している新基板の変更もジャンパー一本ですむ。

 それにしても、kugaさんの的確なコメントはとても有難い。いつも難関を切り開いてくれる。44.1khzサンプリングが可能になったのも、彼がもうひとつのSPIを教えてくれたおかげだし、ポートを出力にしていてADコンバーターの入力インピーダンスが低いと騒いでいた時も誤りを指摘していただいた。kugaさんには足を向けて寝られない。お住まいはどこなのだろうか。

改修したが、確かめられない(1/14/10)
 TIMER0とTIMER2をそっくり交換する改修にとりかかる。ハードの変更は、ブレッドボードならLRCKを隣のピンにうつすだけ。実にあっけない。

 ファームを書き込み、テストする。出た。あれ、連続演奏が効かない。これはタイマーの時間が変ってしまったせいに違いない。データシートを確かめる。うわあ、TIMER0とTIMER2ではPWMのついた同じ8ビットタイマーだけれど微妙に違う。

 プリスケールの定義が違っていた。TIMER0の1/1024のプリスケール設定は、TCCR0Bレジスタの0x05だが、TIMER2は、同じレジスタ(TCCR2B)の0x07だ。時間が1/8になっている。これでは同時押しが利かないわけだ。

 これを直して、プレーヤーはすっかり元に戻った。音は? いやこの違いは全くわからない。仕様上はTick割込みを使わないバージョンよりさらにジッターは少なくなっているはずである。これを確かめる? 残念ながら、これを確かめるためには大掛かりな測定器が必要だ。とてもそんなことはやっていられない。

 少し残念なのは、 2回目の基板が、出来上がる前から、ジャンパーが必要なことがわかってしまったということだけれど、背に腹は代えられない。殆ど音には効いて来ないと思うけれど、少なくともジッターの心配をしないで済む。

 ただ、気をつけなければいけないのはソフトの管理だ。これまでのように気楽にソフトのバージョンアップは出来なくなる。それに名前の付け方も難しい。すでに3号機と言っているソフトのバージョンはV4になっている。ソフトの内部では4.1としたがAVRstudioのフォルダーは分かりやすいようにV5にしてしまった。いずれ何とかしなければ自分でも間違えそうだ。 

STM32Primer2のコンデンサーを替える(1/15/10)A1172607
 プレーヤーの改善が一段落したので、懸案のSTM32Primer2の改修工作に入った。ねむいさんのブログなどで話題になっていた、STM32Primer2の電源周りの不具合の対策である。ブログなどによると、USBからの通電で、レギュレーターに定格を越える突入電圧がかかり、レギュレーターが焼損するという不具合である。

 製造元(Raisonance)では、レギュレーターの配線を太いのに替えて対策したということだが、対策済みの機器でも発生し、究極の解決策は、レギュレーター周りのコンデンサーをタンタルから積層セラミックに取り替えることだという。

 これにそなえて、既に積層セラミックのチップコンデンサーは、秋月で入手済みである。
本家のサイトでマニュアルなどを落とす。ここは回路図から、外形図まで全部ダウンロードできる。親切だ。交換対象のC23とC56の場所はすぐわかった。

 久しぶりのハンダ付けである。まず既存のコンデンサーを取り外す。慎重を期すため、例のサンハヤトの実装部品取り外しの特殊ハンダを使う。簡単にとれた。表と裏の部品を外し、秋月で売っている、10μFのチップコンデンサーを付け直す。

 無事2つとも交換。電源を入れ直す。気のせいか少し画面が明るくなったような気がする(そんなことはないか)。

 いずれにしても、先人が数々の実験の成果をウェブに上げてくれていることで、万全の対策がとれる。有難いことだ。これがなければ、こちらもレギュレーター焼損で泣いているところである。この場を借りて先人のみなさんにお礼を申し上げておかねばなるまい。

少しSTM32Primer2と遊んでみた(1/16/10)

 レギュレーターの不安が解消されたので、少しPrimer2を触ってみた。キットについていた小さなCD-ROMでドライバーをインストールする。これがうまくいかない。第一、最初のWelcome画面が消えない(日本版のWindowsではタスクマネージャーで止めるしかない)。Ride7

 こういうときも、ウェブが頼みだ。検索する。あった、あった。ここやここから沢山情報が手に入る。なんだ。そのままでは違うフォルダーに行ってしまって正しいINFファイルがあたらないようだ。WinXP用のフォルダーまで降りてインストールする。無事、ドライバーはインストールされた。

 あんまり沢山の開発環境を入れたくないのだが、OSをバージョンアップするのは、この環境が必要だということで、指定のARMtoolをウェブから落とした最新版でインストールした。XPでは不安定ということだったが、何事もなく開発環境Ride7が動いた。Eclipse風の盛り沢山なIDEだ。

 順調に、OSも最新の3.8に上げる。アプリケーションも一緒に入れる。10個以上のゲームやユーティリティが入った。興に任せて少しづつ動かしてみる。五目ならべやマンデルブロー図など盛りだくさんのアプリケーションがある。
A1172605
 暫く、遊んでみた。苦心して開発した人に申し訳ないが、所詮は128×160の液晶画面だ。どうあがいてみても玩具の域を超えることは難しい。自分が開発していないでこういうことを言うのも失礼だが、どうもむなしい。わくわくする感動がない。

 昔から、モバイルには余り興味がなかった。GPSや通信、音楽プレーヤーなどならわかるが、携帯の小さな画面でチマチマとゲームをやったり、苦労して小さな文字を入力するのが何が面白いのか理解できない。実際の何かの役に立つならともかく、野外に出て、何もわざわざ小さな画面でゲームをすることもないだろう。まあこれは、「システムは役に立たなければならない」という当研究所長の一方的な偏見でもあるが。

 ということで、Primer2のテストはこれくらいにする。ここでも、これを何に使うか具体的に決まっていないという問題が一番大きい。一体何に使えるのだろう。

| | コメント (2) | トラックバック (0)

2010年1月 8日 (金)

SDカードプレーヤーの演奏中の時間表示に成功

 昨年初めから取り組んでいた、SDカードを使った8ビットマイコンAVRによるリニアPCMプレーヤーは、ついに、演奏中にLCD(液晶ディスプレイ)へ経過時間を表示できるところまで成長した。

 OSは使っていない。タスクを3段構造にし、SDカード読み込みのバッファー空き待ち時間を利用して、LCDに残り時間と、プログレスバー(もどき)を表示する。

 今年のお正月は近親に不幸があったりして、気分が暗かったが、これですっかり明るさを取り戻した。典型的な躁鬱質なので今は意気軒昂、矢でも鉄砲でも持って来いという爽快な気分である(落ち込むのも早いが)。

OlimexからPOフォームが来た。ドリルサイズの割り増しをとられる(1/6/10)
 年末にボードファイルを送ったOlimexのプリント基板のPO(購入依頼)フォームが届いた。営業日数から言えば4日しかかかっていない。優秀である。Tsvetan君にちょっといやみなことを書いたので心配していたけれど、ちゃんと送られてきた。Olimexholidays

 しかし、POフォームを見ると、規格外のドリルサイズを使ったということで1ユーロの割り増しがついている。何い、そんなわけないぞ。あわててEAGLEを開いて、例のドリルサイズをチェックするコマンドを入れる(run drillcfg)。うむ、大丈夫なはずなのにどうして?

 念のため、ウェブを開いてOlimexがサポートするドリルサイズを再確認。ありゃあ、32milは駄目なんだ。そうだ、EAGLEのライブラリは、大抵の部品のドリルサイズが32milで、パッケージにするとき修正しまくったことを思い出した。

 違反の32milのドリルサイズは予想通り、新しく入れたパスコンのパッケージファイルだった。修正もれだ。やれやれ。ドリルサイズは、発送前にチェックしたが、32は大丈夫だとばっかり勘違いしていた。まあ1ユーロだから\140程度、たいしたペナルティではない。でも何となく腹が立つ。

 PDFファイルになったPOフォームを印刷し、カード番号を記入して早速ファックスした。2回目なので発注作業は、10分もかからない。これは楽だ。最近、ブログのメールにEAGLEを使っている人を対象に、「Olimexより安く基板を作ります。試しませんか」というメールが届いている。しかし、Webサイトもなく、メールだけというのが少し気味が悪い。それと少しでもOlimexに慣れてしまうと他に移りたくない気持ちもある。誰か試した人がいたら状況をWebに上げてもらいたいものだ。

 ファックスの次の日、例のfax receivedの2語メールが届いた。こいつはいつも恐ろしく早い。このまま行くと、1月下旬には基板が送られてくるだろう。そろそろ年末に成功したマルチタスクにしたソフトの仕上げを急がねばなるまい。

リニアPCMプレーヤーは、ついに経過時間を表示するようになった(1/8/10)
 前記事でマルチタスクが出来たと書いたが、出来ているのは読み出したセクターの数を表示しているだけである。このセクターの数から、時間表示にしなければいけない。それにプログレス(進捗)バーのようなものも出したい。

 LCDは、たったの2行16文字のキャラクターディスプレイである。しかも相当遅い。そのうえSRAMがもうぎりぎりだ。いつスタックのオーバーフローが起きるか分からない状況だ。フラッシュの方はまだ余裕があるが、メモリを消費しないコードにする必要がある。

 このミニLCDは、一般の5VドライブのLCDに較べると明らかに表示速度が遅く、コマンドを立て続けに送ると全く表示されなくなってしまう。少なくとも100ms以上間隔をあける必要があり、それでも薄くなる。この待ち時間のロジックも組まなければならない。結構面倒である。

 それに、今度のプレーヤーは、WAVファイルの沢山の形式に対応している(サンプリング周波数44.1、22.05、16.0khz、ステレオ、モノ、データ長16、8ビット)ので、
セクター数だけで時間が決まらない。あらかじめ計算しておかないといけない。

 SRAMを増やさないコードにするため、慎重にロジックを考える。プログレスバーは、時間を表示したあとの10キャラクター分を#や>などの文字で表示していけば、それらしい感じになるだろう。全体の演奏時間は、ファイルをオープンしたときにファイルサイズを取得しているので、ここから換算できる。10で割った数を基準にして1つづつ増やしていけば進捗が表せる。

 問題は、表示するタイミングである。バックグラウンドタスクは、ファイルがEOFになるまでループしつづける。的確なタイミングで表示間隔を明けていかないと、LCDは真っ白になってしまう。

 さらに、ファイルサイズはバイト数なので、下手をすると8桁台(数百万バイト)である。一方、セクター(512バイト)をDACが処理する時間はミリセカンドオーダー、この両極端な数字を使って、正確な分、秒にもどすのは神経を遣う。4バイトのデータは8ビットマイコンには荷が重い。うっかりすると有効数字が消えてしまうのは周波数カウンターのとき経験済みである。

 色々考えているうち、ふとアイデアを思いついた。進捗の単位をすべて表示する秒まで求めてこれに統一し、この数値が変わったときのみ表示すれば、表示間隔を気にする必要がない。そのためには一旦、表示した時の値はセーブしておいて、これが変わったときのみ次のデータを表示する。これだと表示は秒1回、または進捗が10%増えた時だけしか表示しない。これはうまいぞ。A1082601

 このアイデアを思いついてからは早かった。タイマーなどは必要ない。念入りにロジックを検討したお陰で、実際のコーディングはすぐ済んだ。表示部だけなら、わずか7行、初期設定を入れて全体でも10行余りの追加におさまった。

 秒まで出てくれば、分に直すのは60で割るだけである。最初、経過時間を表示しようとしたが、残りの演奏時間を表示する方が情報量が多いので、こちらにする。 A1082604

 わくわくしながらファームに書き込み、早速テスト。おおお、出た出た。市販のCDプレーヤーと同じように時間がカウントダウンしていき、プログレスバーの文字が少しづつ増えていく。嬉しい。単位を、#にしたり>にしたりしてチェックする。いやあ、もうこれは完全なプレーヤーだ。今の表示ディバイス(キャラクタLCD)ではこれ以上のことは望めない。

 22khz、8bitのWAVファイルや、短いファイルを入れてテストする。22khzは問題なかったが、短いファイルはプログレスバーが止まらない。暴走する。考えてみたら、演奏が終わっても表示の処理が残り、際限なくバーが延びていくためである。対症療法だが、ストッパーをつけて止める。

 昔から「段取り8分」という。計画を万全に立てたら80%は出来たも同じという意味だ。慎重に検討したお陰でプログラムはあっという間に動いてしまい、意気込んでいた肩の力がすっかり抜けてしまった。力が余ってしまって、ついでに前の5VのLCDを入れた1号機まで改修してしまう。これも問題なく動いた。いやいや今回はあまり楽しめなかったな。A1082603

 2号機の一台目は、娘がユーザーだ。こいつもバージョンアップしてやる。娘が喜んでくれた。こちらの苦労も知らないで今度は、「早送り」の機能もつけろと言われる。うーむ、出来ないことはないけれど、もっと他にやりたいこともあるからなあ。

ここに、演奏の経過表示をするリニアPCMプレーヤー2号機(ストロベリーリナックスのミニLCD使用)と、1号機(秋月などの定番LCDを使用)のソースコードを、AVRstudioのフォルダーをzipにして置きます。
1号機は、SDPCM328V4.zip  2号機は、mLPCM328V4.zip です。
ソフトのバージョンはV4です。
回路図等は、以前の記事を参照してください。なお、1号機の回路図には音量調整のVRがついていません。フォンジャックの直前につけてください。

「mLPCM328V4.zip」をダウンロード

「SDPCM328V4.zip」をダウンロード

| | コメント (6) | トラックバック (0)

2010年1月 4日 (月)

マルチタスクにしたプレーヤー3号機の開発状況

あけましておめでとうございます。
 がた老AVR研究所も発足以来2年が経過し、おかげさまでアクセスが月に1万アクセスを超える、そこそこのブログに育ちました。組み込みコンピューターを中心とした電子工作の気ままな制作の過程をなるべく詳しくご紹介することをモットーにしています。

 これは、所長が現役時代に大規模システムの開発を職業としていた経験から、自分のやっている試行錯誤は、たとえどんなくだらないことでも必ず誰かの何かの参考になるという自信にもとづくものです。

 このブログを知る知人からは、「レベルが高いのか低いのかわからない」「文章が長すぎる」などのご批評をいただいていますが、技術的な情報を提供するブログをもともと目指しているわけではありません。少し偉そうに言えば、所長のかっての専門分野である「問題解決」のさまざまなアプローチを、電子工作を通じて楽しみながら紹介できれば望外の幸せというものです。

 これからもよろしくお願い申し上げます。

さて、本記ですが、現在のプロジェクト、リニアPCMプレーヤー第三版の制作は、年末に身内に不幸があったりして目だった進展はありません。備忘録的にこれまでの出来事をご紹介しておきます。

2回目のOlimex基板発注(12/21/09)
 リニアPCMプレーヤーの2つ目の基板は、12/21にEAGLEのボードファイルを添付してOlimexに注文申請メールを発送した。すると親切にも例のTsvetan君から、

Did you read about our Holidays?
Tsvetan / Olimex

と返事が来た。
あわててOlimexのトップページを読み直す。

お休みは12/24から1/4までだよ、12/17以降の発注(PO)は、出荷が1月になるよ。というメッセージしかない。
(We are closed 24-th of December to 4th of January.  PO forms sent after December 17th will be shipped in January)

別に年内に基板が欲しいわけではない。
「お宅の休みが24日からなのは知っている。17日以降のPOが来月送りになるのもね。
何か言うことある?(Do you have any other suggestion?)」とちょっといやみな返事を出す。

それきり返事はなかった。もしかすると怒らせてPOformが送られてこないかもしれない。少し心配する。

 とにかく、これでLPCMプレーヤー3号機のハード工程は一段落した。電池基板ケースも2個分の切り出しが終わった。ミニサーキュラソーは快調だが、標準の丸鋸の刃でプラスティックを切ると荒らすぎて切り口がきたなくなり整形が面倒だ。あさりのない細い刃の方が綺麗に切れそうなので、入手するまでそれ以上の作業は中止することにした。しかし、お正月の準備が忙しく、なかなか買い物にいけない。

マルチタスク化はジッターが心配(12/24/09)
 演奏中に経過時間などを表示するマルチタスク化は、実現の見通しがたったが、いざ実際の開発に入ろうとして、マルチタスクのTick割り込みによって起きる、DACの割込みのゆらぎが気になってきた。いわゆるジッター(サンプリング周波数のゆらぎ)である。

 少なくとも、これまでのリニアPCMプレーヤーにはDACの割り込みを妨げる処理はない。理論上はCPUクロックのゆらぎ以外にジッターは起きない理屈である。音質が売り物の今度のプレーヤーだ。いくら発生頻度が低くても、マルチタスクにして経過時間を表示した結果、折角の音質が損なわれてしまうのでは改善の意味がない。

 CDプレーヤーから直接聞くより、一旦PCにリッピングしてディスクからWAVファイルを聞くほうが音が良いというのは、CDプレーヤーのドライブでエラーなどでジッターが起きるからだと言われている。高級な音楽CDドライブは必ずバッファーを設けてクロックを揃えたりする。

 しかし、今度のマルチタスク化によって、DACの割り込みは、SDカード読み込みの割込みで少ない確率ながら遅れる可能性が出てきた。これが音質を左右するほどの遅れになるのかが問題だ。

 ウェブの情報を漁る。まずジッターの単位が良く分からない。UIというのはUnit Intervalの略で、サンプリング時間を1としたときの、ゆらぎの時間だという。一方、psという単位もある。ピコセカンドという秒の単位だ。これは絶対値で、サンプリング周波数が変われば当然変化するので同じサンプリング周波数でないと意味がない。

 デジタルオーディオの世界で有名な、シーラスロジックのCS8416というトランシーバーICのジッターは、業界最高水準という200psを謳っている。この石のサンプリング周波数は192khzなので、UIに換算すれば、0.00004UIということになる。

 一方、現在のリニアPCMプレーヤーのクロックの水晶発振子の精度は数百ppm(百万分の1)で、DAC(BU9480F)のサンプリング周波数、88.2khz(2倍オーバーサンプリング)も、これに比例して変動し、UIでいうと0.0002(200ppmとする)、psで言えば、1/(88.2*1000)*200/100000=22000psである。かなり大きい。

 現在既にこの程度のジッターは出ている。従ってこれより少ないジッターに押さえることが出来れば、今回のマルチタスク化による割込み遅れは無視できると言えるだろう。業界最高水準と争うのは無意味だ。

 恐る恐る計算を始める。まず、割込みによって遅れる時間の見積もりである。WINAVRの説明によれば、割込みが起きて割込みプログラムにジャンプするとき、CPUはハードウエアでSREGレジスターをリセットし、ここで割込みが禁止になる。このあとレジスターなどをセーブし実際のユーザーの割込みプログラムに制御が渡るが、ISR_NOBLOCKオプションではジャンプの直後にSEI命令を置いて、すぐに割込みを許可にする。つまりジャンプ1命令とSEI命令の2命令分、クロック20Mhzで100ns遅れる計算である。

 DACのサンプリング間隔、11.33μsからみると、100nsは、UIで0.01となる。相当大きい。しかし、この遅れは常に起きるわけではない。ファイルアクセスが割込みによって2.9msごとに512バイトのセクターを読む時と、その前のバッファーが空くまで空振りする割込みの数回しかおきない。これが11.33μs間隔のDAC割込みとぶつかる確率は、相当低いはずだ。Dack_tick_2

 このぶつかる確率を正しく計算しようとして、このところずっと悩んでいた。まず、ファイルアクセスの開始を監視するTick割り込みは、これまでのチャートから見て、300から500μs間隔で十分余裕があると考えられる。クロック20Mhzの一命令の時間は50nsで、割込みの頻度は、Tickを300μsとして、300/0.05=6000命令に1回である。とても少ない頻度に見えるが、DACの割込みは11.33μsで226命令に一回、この割込みに先ほどのTick割込みが、どれくらいの頻度でぶつかるのかが計算できない。

 単純に考えれば、DAC割込みの26.54回に1回(6000/226=26.54)、Tick割込みがやってくるが、必ずしも常にDAC割込みと重複するわけではない。楽観的に考えれば、DAC割り込みは226命令に1回の頻度なので、1/(26.54×226)のような気もするが、この頻度は、Tick割込みの頻度と同じで、何か0=0を計算している感じだ。

 間違いないところでは、最悪で26.54回に1回(Tick割込みの度に必ずDACとぶつかる)、なので、この頻度をUIに適用するとそのUIは、0.01/26.54 = 0.0003で、水晶発振子のジッターとほぼ同じだ。Tick割込みの度に必ずDACの割込みと被るというのは、ちょっと考えられないので実際にはもっと低い。さっきの計算では、その1/226まで下がる。

 歯切れは悪いが、一応、割込みによるジッターは殆ど無視できるレベルにあると考えることにした。あとは実際に動かして聞いて見るしかない。ジッターの音に対する影響も明確な基準があるわけでもない。あまりこれにこだわることは止めることにする。

バックグラウンドタスクが動いた(12/30/09)
 ジッターの問題があって、実際のコーディングには、なかなか踏み切れなかった。折角苦労して作ってもジッターで音質が台無しになるかもしれない。うまく動いているのをいじりたくない気持ちも邪魔をしている。

 しかし、ハードの方は、Olimexに基板を発注してしまったので、やることがない。少しづつメモに書き出しながら、ロジックを練った。鉛筆で何度も書き直す。細かいフラグまで擬似コーディングし、満を持してAVRStudioに新プロジェクトを定義し、ソースコードを移す。

 バックグラウンドタスクの時間表示は手間がかかるので当面はアクセス回数を表示することにする。擬似コーディングを入念にやったお陰で、ソースの変更は簡単にすんだ。しかし、すぐ音を出す勇気がない。ぐずぐずしていたが意を決してファームを書き込み、祈る気持ちで電源を入れた。

 「LPCM PlayerV4」というWelcomeメッセージが出る。ソフトのバージョンはV4だ。ここまでは何も変えていないから動くのは当然だ。演奏開始ボタンを押す。鳴り出さない。心臓が鼓動を打ってきた。演奏中断を押し、再開ボタンを押す。おおお、SDカードのアクセスLEDが点き、演奏を開始した。

 しかし音は歪みだらけである。この前のアンダーランと同じ現象だ。全く動かないのならともかく、歪むと言うのはどういうことだ。Tickインターバルが想定どおりの時間ではないのか。考えたとおりに動いていないのか。

 時間的な要因なのでUARTで調べるわけにはいかない。ロジアナで実際のタイミングチャートを出した方が早い。I/Oポートに状態を出力するステートメントを要所に入れ、調べることにする。

 久しぶりにロジアナに火を入れる。プローブを割込みルーチンとファイルアクセス部分に入れてタイミングチャートを出す。出た出た。おやあ、ちゃんと想定どおりの動きをしているぞ。正確に300us単位に割り込みがあがり、バッファーが空くとファイルのアクセスを始めている。考えたとおりのタイミングチャートだ。何の問題もない。バッファーのアンダーランもない。何だ何だこれは。Lpcm4

 これで歪むというなら、この読んだデータが正しくないということだ。もう一度ソースを見直す。あっあっあ、割込みルーチンの書き出すバッファーがテレコになっている。これではDACが動いているときに、そこへ書き出してしまうことになる。こりゃ音が歪むのは当たり前だ。あわてて修正し、再度電源ON。おおお、綺麗な音に戻った。音質も全く前と変わらない。

 喜んでいたのも束の間、突然、演奏中の音楽が別の曲に変わる。何だ何だ、これは。こんな器用なことを誰がやる。SDカードを変えても同じように起きる。しかも同じところでは起きない。SDカードのアクセスがおかしい。  読み込むセクター位置が突然変わる感じである。これはどうもスタックのオーバーフローの疑いが強い。

 SRAMの使用バイト数は、1890バイトを越えて、90%を軽く越えている。うーむ、やっぱりこれだ。割込みプログラムは大量のスタックを消費する。こんどのSDカードアクセスの関数は、割込みプログラム上だ。ここのレジスターが破壊されれば、簡単に別のセクターを読む可能性はある。うむ、これに違いない。

 SRAMを減らす作業を開始する。これがなかなか減らない。1バイト変数を節約してもらちがあかない。結局、10ヶあるディレクトリリストを6ヶまで減らして、やっとこの現象は解消された。SRAMの使用率が90%を越えるとスタックオーバーフローが起きるようだ。

 曲リストをスクロールするときディレクトリの読み込みの頻度が多くなるが実用的には全く問題がない。定数ひとつの変更だけでリストの大きさを変えられるようにしておいて助かった。最初は面倒だがこういうときには威力を発揮する。

 演奏は正しくなった。しかし肝腎のバックグラウンドが動いていない。ファイルアクセス数は0のままである。試しに*を移動させるコードに変えてみる。少し待ち時間を入れてLCDが見えるようにする。

 おう、これは動いた。いや素晴らしい。バックグラウンドタスクをこなしながら演奏が続く。しかしコードをカウンター表示に戻すと0のままだ。xprintfがおかしいのか。そんなわけはない。気を落ち着けて調べ直す。変数をグローバル変数に替えている。

 あああ、なーんだ。わかった。ローカル変数にも同じ名前を定義している。これだこれだ。ファイルアクセス部分を割込みプログラムにして、変数をグローバル化したとき、ローカル変数の定義を移すのを忘れていた。良くあるバグのひとつである。A1042600

 ローカル変数の定義を削除してテスト。うむ、音楽を演奏しながら読み込んだセクター数が順調に増えていく。良いぞ。このLCDは表示時間が遅いので余り早くデータを送ると表示コマンドが立て続けに送られて結局何も映らない状態になる。ある程度、表示間隔を長めに(最低50ms)とる必要があるようだ。

 マルチタスク化は、これで峠を越した。あとは経過時間表示の計算と、プログレスバーなどの表示のロジックを考えるだけだ。このあたりはソフト開発でも最も楽で面白いところである。良い年を迎えられそうだ。

| | コメント (0) | トラックバック (0)

« 2009年12月 | トップページ | 2010年2月 »