前回の記事の通りFPGAを用いてラズパイのi2s出力からのDoP信号を取り出してDSD64の再生に成功したところで、ラズパイが壊れてしまった。
仕方ないのでラズパイを調達することにしたが、ラズパイ4や5はラズパイ3より値段が上がってしまったので値ごろ感が無い。
Amazonを覗いているとラズパイ3Bが4000円で中古品で出ていた。
壊れたラズパイが3B+であったがそのまま動くだろうと安易に考え購入した。
ところが、3B+用に作ってあったマイクロSDカードを挿入しても立ち上がらない。
3Bと3B+の互換性の問題か・・・と、仕方なく新しくvolumioのイメージファイルを別のマイクロSDカードに焼きこみ中古で購入した3Bを立ち上げてみると、起動はできたので一安心。
そこで、以前したためた手順書に従いi2sの外部クロック入力対応を行う手順を実行してみたが、gpioの制御ができず、BCKとLRCKの外部入力ができなかった。信号を見るとラズパイからはBCKとLRCKが出力されているようで、FPGAから出力している同信号と見事にぶつかっているような波形が見て取れた。
また、ストリームのレートに応じてgpio制御でBCKとLRCKを切り替えるロジックを制御する信号を出すことができない。つまり以前作った手順書が役に立たなくなっていることを知った。
ここから1週間、gpioの制御方法をいろいろと試したがどれをやってもうまくいかないかった。
以前確立した手順は既存のプログラムに記述されているRpi-DAC用のプログラムを無理やり外部入力に書き換えて使用する手法を取っていたのでイレギュラーな方法だという思いはあった。
改善するかわからなかったが、自作したDACにあわせてカーネルドライバーを作成することにした。rpi-simple-soundcard.cを参考に、不要部分を削除、自作DACの名称に関数や構造体の名称を変え、以下4つのファイルを作成した。
・ソースコード本体
・Codecのファイル(pcm1794aのものを元にpcm1792aのものを作成)
・dtsファイル
・Makefile
以前の手順書ではbcm2835-i2s.cとrpi-simle-soundcard.cの2つのファイルにまたがっていた変更を自作DACの1つのソースコードファイルにまとめた。
以下、変更の概略のメモです。
snd_soc_dai_link snd_xxxxxxxxx_dai[]
(xxxxxxxxxのところは、今回作成したdacの名前)
こちらの構造体の.dai_fmtを以下のように変更(CBS_CFSをCBM_CFMに)
.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
SND_SOC_DAIFMT_CBM_CFM,
snd_rpi_xxxxxxxxx_hw_params()
こちらの関数に再生するオーディオファイルのビットレートが引数として来ているようなので、以下の記述を追加した。
(gpio17が44k or 48k系のクロック切り替え、gpio27, 22をレート切り替えに使用)
int sampling_rate;
sampling_rate = params_rate(params);
gpio_free(17);
gpio_free(27);
gpio_free(22);
gpio_request_one(17, GPIOF_OUT_INIT_LOW, "test");
printk("samping rate = %d\n", sampling_rate);
if (sampling_rate == 48000 || sampling_rate == 96000 || sampling_rate == 192000 || sampling_rate == 384000){
gpio_set_value(17, 0);
}else{
gpio_set_value(17, 1);
}
}
gpio_request_one(27, GPIOF_OUT_INIT_LOW, "test");
gpio_request_one(22, GPIOF_OUT_INIT_LOW, "test");
if (sampling_rate == 44100 || sampling_rate == 48000){
gpio_set_value(27, 0);
gpio_set_value(22, 1);
}else if (sampling_rate == 88200 || sampling_rate == 96000){
gpio_set_value(27, 1);
gpio_set_value(22, 0);
}else if (sampling_rate == 176400 || sampling_rate == 192000){
gpio_set_value(27, 0);
gpio_set_value(22, 0);
}else if (sampling_rate == 352800 || sampling_rate == 384000){
gpio_set_value(27, 1);
gpio_set_value(22, 1);
}else{
gpio_set_value(27, 0);
gpio_set_value(22, 0);
}
コンパイルを通すまでにデバッグに少し時間を費やしたが、コンパイルができ、インストールした。
かくして、aplay -lをしてみると、自作DACが無事に認識されることに成功。
printkでサンプリングレートをデバッグ用にdmesgで表示してみた。
さらに、volumioの設定画面から自作DACを選択できるように、以下2つの.jsonファイルも書き換えた。
/volumio/app/plugins/system_controller/i2s_dacs/dacs.json
/volumio/app/plugins/audio_interface/alsa_controller/cards.json
volumioのi2s dacの切り替え画面で自分が追加したPCM1792 DACが選択できるようになった。
これをやるとvolumioのほうで/boot/config.txtに選択したDACを追記してくれるようだった。
今回作成したファイルの記載方法とドライバー組み込みまでの手順は以下の文献のお世話になった。dtbとソースコードの関連付けやmakefileの記載方法などが丁寧に記載されており、流用元のrpi-simple-soundcard.c, .dtsなどと照らし合わせてみてやりかたがわかった。
コンピュータ搭載! Linuxオーディオの作り方 (ボード・コンピュータ・シリーズ) | Interface編集部 |本 | 通販 | Amazon
こうやって出来たことだけ淡々と書くとどうという事はないように見えるが、ラズパイとFPGAの組み合わせでDSD再生できるまでに、年明けからveriogの開発環境を立ち上げて、週末のみの作業でのんびり進めたこともあって、だいたい2か月ぐらいかかった。
foobar2000のリアルタイムDSD変換+UPnPによるDoP出力は一応できるようで、特にPCMファイルからDSDファイルを作らなくともDSDとして再生ができている。
最後に、DSD128が出力できるようにFPGAのプログラムを変更してみたが、foobar2000からDSD128のファイルを再生しても、volumioのほうでsampling rateを192000と判断するらしく、思ったようにFPGAとの組み合わせ動作ができず再生は出来なかった。
volumioを使用している以上は、現状DoPによる再生はDSD64が限界なんだろうか。