そこで,Raspberry piで録音できないかと考えました. Raspberry piなら上げっ放しでも良いですし, タイマーで立ち上げることもできます. 録音のためには,「S/PDIF→DAI→RaspiのI2S」というハードを作れば良いわけですが, 実はFMチューナー内部でのFPGAとDAC (PCM1781)の接続はI2Sですので, I2SでRaspiに直結できるのではと考えました. Raspberry piでのI2Sを使った再生(DAC)の情報は沢山あるのですが, 録音に使う話は少ないので,ちょっと詳しく書いてみます.
次に電圧.元々のPhilipsのI2Sの規格ではTTLレベルのようですが, Raspberry piのGPIOは3.3Vです. FPGAとPCM1781も3.3V接続ですので,電圧も問題なし.
最後に,I2Sのパラメータです. FPGAとPCM1781のI2S接続は,192,000Hzの24bitとなっていますが, ロジックアナライザで観測したところ,1ワードを32クロックで送信していました. これは特殊なことではなく,I2Sはこういうもののようです. 元々,I2Sにはワード長という概念はありません. I2SではWS信号の切り替わった直後(正確には切り替わった1クロック後)から, データをMSBからLSBの順で送信して行きます. 受信側は,16bitで十分なら16bitで打ち切ればよいわけです. (実際,今回は16bitしか使っていません.) I2Sの設定をしているプログラム (bcm2708-i2s.c) も確認しましたが, このような信号でもちゃんと受信できるようになっています.
接続回路ですが,オリジナルのFMチューナーは次のようになっています.
FPGA─抵抗(100オーム)─PCM1781今回はパターンカットしやすさから抵抗とPCM1781の間でカットしました. GPIOは双方向なので,出力が衝突した時の保護のため,更に500オームを挟みました. (何となく5mAくらいなら流れても大丈夫だべ,という適当な値.)
FPGA─抵抗(100+500オーム)─Raspberry pi I2S (=GPIO)という接続です.ピン対応は次の通りです.ハードは,とても簡単です.
DATA (=SD): 元のPCM1781の6番 → GPIO30 BCK (=SCLK): 同7番 → GPIO28 LRCK (=WS): 同8番 → GPIO29 GND: GND
それらの既存のドライバーを流用して新しいドライバープログラムを作ることも簡単です (Kconfig,Makefile,arch/arm/mach-bcm2708/bcm2708.cをチョコっといじる)が, 今回は横着して,RPI DACのドライバーをそのまま改造してしまうことにしました. (もちろん,これをやると本物のRPI DACは接続できなくなります.) RPI DACを選んだのは,このドライバーが一番シンプルそうだったからです.
RPI DACは,DACとしてpcm1794aを搭載していますので,そちらも修正します. つまり,以下の2つのファイルを修正します.
return snd_soc_dai_set_bclk_ratio(cpu_dai, 32*2);ここは既にこうなっているのですが,重要なところなので確認です. 上の第2引数は,32クロックで2ワード(2チャンネル)を受信するという意味です. 他のドライバーでは, この部分はワード長の2倍としているものもあります. RPI DACは32クロック固定方式のようです. FPGAもたまたま同じ方式だったので修正しなくて良いわけです.
.dai_fmt = 〜 SND_SOC_DAIFMT_CBS_CFS,これを次のように変更します.
.dai_fmt = 〜 SND_SOC_DAIFMT_CBM_CFM,これはcodec側から見て,bit clockとframe clockを駆動するかどうかの指定です. 元はS (Slave) になっていますが,今回はcodec側が駆動するのでM(Master)にします.
.playback = {この行を次のように変更します.
.capture = {もちろん,再生デバイスではなく,録音デバイスになるという意味です.
最後は不要なのですが,32bit録音したくなるかもという場合は,
.formats = 〜この行に次を追加します. これは,ドライバーが対応可能なフォーマットを指定しているだけで,動作とは関係ありません.
.formats = 〜 SNDRV_PCM_FMTBIT_S32_LE
あとはカーネルを普通に作成します.カーネルコンパイルの方法はWeb等を参照して下さい.
/etc/modprobe.d/rasp-blacklist.confの中の次の行をコメントアウトします.
(下の2行はコメントアウトしなくていいと思いますが.)
blacklist i2c-bcm2708 blacklist snd-soc-pcm512x blacklist snd-soc-wm88704
/etc/modulesに以下の行を追加します.
snd_soc_bcm2708 bcm2708_dmaengine snd_soc_rpi_dac snd_soc_pcm1794a/etc/asound.confを作成します.これはsoxしか使わないなら関係ないかも.
pcm.!default { type hw card 0 } ctl.!default { type hw card 0 }これでリブートして,
arecord -lとやってRPI DACが(入力デバイスとして)見えれば成功です.
arecord -c2 -r192000 -f S16_LE out.wavとすれば録音はできます.が,実際は音がブツブツと途切れて聞けたものではありません. バッファリング時間を調整して,--buffer-time=100000 とすると良いようです.
現在はarecordでなく,soxを使っています.
export AUDIODEV=hw:0,0 export AUDIODRIVER=alsa rec -q --buffer 50000 -c2 -b16 -r192000 out.wavbufferサイズを指定しなくても録音できますが,時々overrunが出ます. 上の値が一番良いようです.(この値が65535を越えると無限にエラーが出続けます.)
ただし,それでもSDカード (TranscendのSDHC Class10 16GB, カタログスペック 20MB/S) への保存だと1〜2分に一回程度のoverrunが出ます. USBメモリへ直接保存するとかなり減少し,2時間で0回ということもあります.
48,000Hzに落として,ついでにflacにします.
sox -q --buffer 50000 -c2 -b16 -r192000 -d -r48000 out.flac downsample 4これで2時間で500MBくらいでしょうか. overrunはほぼ出ません.
Raspi用のRTCとしては,DS3231を組み込んだモジュールが販売されています (例えばこちら). DS3231にはAlarm機能が付いていますので,これを使ってみます.
抵抗の値は,手元にある適当なものでだいたい動くと思います. 実際,今の回路は図の値とは少し違います.
リレーは OMRON G6B-1114P-US DC5V です.接点定格は30V 5A.
コンデンサは,Raspberry piがrebootする時にUART TxDが一秒程度落ちる間, 電源を維持するために必要です. 現在は220μが入っていますが,100μでも十分な気がしますので,回路図ではこの値にしてあります.
トランジスタ,特に前段の2SC1815はほとんど何でもいいと思います. それに2SC1815オリジナルは製造中止なので, 互換品(例えばKSC1815)を使うことになります.
電源オンのスイッチはチャタリングする可能性があるので,2SA1015のベースでなく, コンデンサのところに付けています. 今は220μなので,やや長目に押す必要がありますが,100μならチョン押しでいいはずです.
一旦立ち上がったら,Raspberry pi側でshutdownを実行するまで, INTの値に関係なく電源はオンのままでなければなりません. それには,Raspが生きていることをハード側で知る必要があります. いろいろ調べたところ, UART TxD(8番ピン)が内部でプルアップされていることを使うのが良さそうです. ただし,UARTは本来の用途には使えなくなってしまいます. (GPIO4を使うと良いという情報もありました.)
以上については,こちらを参考にしました.
なお,電源の容量ですが,安い5V 2AのACアダプタを使っていた時には, DS3231がリセットされる現象に悩みました. 突入電流で電圧が降下していたようです. 定常状態での電流は実測で0.9A(Raspi+チューナー+ファン)ですが, 突入電流は2A以上になると思われます.
現在は,次のような流れで録音しています.
i2cset -y 1 0x68 0x0e 0x1d i2cset -y 1 0x68 0x0f 0
全基板をシャープのBSチューナーTU-HD1のケースに入れてみました.
電源基板が傾いているのは,既存のホールを利用したためです. 電源は5V 10Aなので,ちょっと大き過ぎです.そのうち小型のものに変えます. FMチューナー基板はアンテナコネクタがリアパネルに出るように, Raspberry pi基板はLANケーブルがリアから挿せるように配置しました. I2S接続基板は再利用品なので汚いです.
POWER ONのスイッチと電源オン表示のLEDは,TU-HD1のフロントパネルのものを利用しています. また,USBメモリは頻繁に使うので, Raspberry piのUSBコネクタをフロントパネルに移設しました.