やりました! とうとうやりました。
PLLではなく、外部クロックでラズベリーパイを鳴らせることができました!
bckも外部クロックで駆動しています。
使ったクロックは、キョーセラの7050k(22.5792MHz),7050a(24.576MHz)です。「Innocent Key Blog」さんの各種クロック&オシレータの比較測定で7050kが高評価だったので、入手性の観点から、これらを選びました。写真手前のGPIO端子に見える2つの小さい長方形が、外部クロックのオシレータです。
FPGAのde0-socの回路図から、PLLをすべて取っ払いました。notを2つ重ねているのは、LEDのみならずオシレータにも同じ線で電源を供給しているので、負荷を減らすためです(どれほど効果があるかはわかりません)。
プロジェクトをここに置きます。
exclock.zip
ただし、gpioのどこにオシレータを配置するかは、かなりの自由度があり、ボードにより違うでしょうから、参考程度にしかなりません。pinplannerで適宜ご人心の環境に合わせていただければと思います。ただ言えるのはgpioのグラウンドピンが配置されていればその近傍に置くのが良いのではないかと思います。
パッドがいずれも1mm四方ぐらいしかないので、リード線をつけるのに苦労しました。クッション性のある両面テープで机の上に仮固定し、リード線を1mmだけ剥いて予備はんだをつけ、はんだこてにはんだを乗せて固めました。慣れれば容易な作業です。
オシロでもパッシブプローブでは観測しにくい高周波を扱うので、リード線は短くするほうがインダクタンスの観点から好ましく、短くすることを心掛けました。
このクロックのブロックを取り去ると・・・・当然音は出ません。ということは・・・このクロックで、音が鳴っているということです。
ラズパイからサンプリング周波数の情報を出力しているので、44.1kのCD形式のwavと、24ビット96kでは、使用する外部クロックが物理的に異なりますが、自動的に切り換えてくれます。
初めて原理的に納得できる再生ができたと思います。
オシレータクロックをブロックに固めたので、「Innocent Key」さんと同じように交換ができます。まるでレゴのようです。
私もこのサイトを見てこういうことをしてみたいと思って7050kなどを入手しましたが、その小ささと表面実装であることから途方もない気がしていましたが、ようやく音が聞くことができて感無量です。
今回は、今まで頑張ってきたことを土台にしているので、比較的あっさり1日で、音出しができるようになりましたが、今回も若干苦労しました。
dmesgを出しても、サンプリング周波数のprintkのメッセージが表示されません。
おかしい。おかしい。。。
いろいろやって、わかりました。aplayで設定すべきデバイスの番号は、立ち上がるたびに、変わる可能性があります。
hw:0,0だったのが、hw:1,0に変ったりします。
音は??
ラズベリーパイが作成したクロックを利用した場合(ラズベリーパイがクロックマスターの場合)には、なんとなくハモリが多くて、湯船につかったような感じでしたが、
de0-cv内部のPLLから外部オシレータへと変更していくと、手前味噌かもしれませんが、強いて言えば、若干、よりしっかりした方向へ(克明になった、リズムがしっかりして音楽の骨格が感じられるような方向へ)変わったように思います。
(2018.5.5 追記)
やっぱり、おかしい。電源を入れなおすと。。。dmesgでみてみるとgpioが出ていない。。。うーーん。
試行錯誤を続けるうちに、もう一度、rmmod,insmodをすればgpioが出るようになることがわかった。
結論として、rmmod,insmodをしても、メモリー上にドライバーがロードされるだけで、電源を切ると忘れてしまう。
しかし、毎回、rmmod,insmodはめんどくさすぎる。。。
この対策としては、古いドライバーが電源を入れた状態ではロードされるから、その古いドライバーを見つけて、直接上書きをするしかない。
そこで、以下のコマンドで、古いsnd-soc-2835-i2s.koを見つけ出す。なお、スーパーユーザー権限(sudo su)が必要。
root@raspberrypi:/home/pi/nas_all# find / -name “snd-soc-bcm2835-i2s.ko”
/root/linux-80a14a56dacb7cc2b40d5f37d00bedb0ceace130/sound/soc/bcm/snd-soc-bcm2835-i2s.ko
/lib/modules/4.9.80+/kernel/sound/soc/bcm/snd-soc-bcm2835-i2s.ko
/lib/modules/4.14.24-v7+/extra/snd-soc-bcm2835-i2s.ko
/lib/modules/4.9.80-v7+/kernel/sound/soc/bcm/snd-soc-bcm2835-i2s.ko
/lib/modules/4.9.80-v7+/extra/snd-soc-bcm2835-i2s.ko
root/linux内のものが、ソースファイルのある場所で、新しくコンパイルして出来たもの。それを、現在のカーネル(4.9.80-v7+)がある場所へコピーする。なお、4.14.24-v7+は、カーネルヘッダーズをインストールしないときにコンパイルして、バージョン違いのエラーが出たときに生じたものでここでは関係がない。4.9.80-v7+は、$(uname -r)に置き換えられる。他のバージョンでも通用するので、以下のコマンド。
cp $bcm/snd-soc-bcm2835-i2s.ko /lib/modules/$(uname -r)/extra/snd-soc-bcm2835-i2s.ko
以上を実行してもだめなら、ほかのファイルも更新する。更新されたかどうかは、以下のコマンドで日付を確認。
ls -l /lib/modules/$(uname -r)/extra/snd-soc-bcm2835-i2s.ko
更新された場合には、電源を入れなおすと。。。dmesgでみてみるとgpioが出ていることを確認できた。
しかし、・・・やはりおかしい。砂嵐のようなノイズがでる。聞くに堪えない。。。
オシロで見てみると、bckの波形が崩れている。
変な電荷がたまっているのかと思って、ケーブルを全部抜き、数分放置。
しかし、やはり治らない。前にやった時は、ノイズが乗らなかったのになあ。。
ノイズが混じるのは経験上、クロックの設定がおかしいときだった。
試行錯誤、試行錯誤、だめもとで、rmmod,insmodをしてみるか。。。
なぜかノイズが消えた!! もしかして、ドライバーが古い?
ls -l /lib/modules/$(uname -r)/kernel/sound/soc/bcm/snd-soc-rpi-dac.ko
ls -l /lib/modules/$(uname -r)/extra/snd-soc-rpi-dac.ko
上記のコマンドで確認すると、インストールしたときのドライバーが入っていた。これはまずい。一度も更新してなかったっけ?
だんだんと、わかってきました。オーアイシー。。なるほど。ようやくわかりました。
改造後のsnd-soc-rpi-dac.koは、ラズパイマスターを、ラズパイスレーブに変更するという任務を担っていたので、
snd-soc-rpi-dac.koは、電源を入れなおした時にラズパイマスターに戻り、マスタークロックを出力しているにもかかわらず、その状態で、外部から強制的に、位相や周波数が若干異なるマスタークロックを入力され、混ざり合った状態になっていた。これは、クロックがぐちゃぐちゃでノイズが出ても仕方がない。
こちらのドライバーも、上記と同様、電源を切ると忘れてしまうので、本来のドライバーの位置に、直接コピー。
cp $bcm/snd-soc-rpi-dac.ko /lib/modules/$(uname -r)/extra/snd-soc-rpi-dac.ko
ようやく、sudo suをしなくても、まともな音でなり始めました。。