Raspberry Piで外付けI2SのADCを動かせるのか
Pi基板に外付けの単機能のADCをつなげられないかと検討してみた。
ネットで調べて見るとADC/DAC
のWM8731を使ったPROTO audio codec board基板を使って再生録音できたとい記載がある。
関係するソースを見てみると、
PROTO board with WM8731
snd_soc_wm8731 wm8731.c
snd_soc_rpi_proto rpi-proto.c
.dai_fmt = SND_SOC_DAIFMT_I2S
| SND_SOC_DAIFMT_NB_NF
| SND_SOC_DAIFMT_CBM_CFM,
これに対して、昔のDACのTDA1541aの設定を見てみると、
.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
SND_SOC_DAIFMT_CBS_CFS,
となっており、発振子付きのPROTO audio codec board基板のWM8731がマスターとして(Piはスレーブで)動く設定になっているようだ。
****
さて、手持ちのPiのオーディオのIN/OUTの状況を見てみると、
pi@raspberrypi ~ $ pactl list short sources
0 alsa_output.usb-C-Media_Electronics_Inc._USB_PnP_Sound_Device-00-Device.analog-stereo.monitor
module-alsa-card.c s16le 2ch
44100Hz SUSPENDED
1
alsa_input.usb-C-Media_Electronics_Inc._USB_PnP_Sound_Device-00-Device.analog-mono
module-alsa-card.c s16le 1ch
44100Hz SUSPENDED
2 alsa_output.platform-bcm2835_AUD0.0.analog-stereo.monitor
module-alsa-card.c s16le 2ch
44100Hz SUSPENDED
3 alsa_output.platform-snd-hifiberry-dac.0.analog-stereo.monitor
module-alsa-card.c s16le 2ch
44100Hz SUSPENDED
となっており、I2Sに相当するalsa_input.platform-snd****は存在しない。当たり前のことだが、I2S用のモジュールがないとI2SのADCは動かせないことに気づく。 今回の話題には関係ないが、2番目のalsa_input.usb-は、USB-MICである。
カーネルイメージの 2014-01-07-wheezy-raspbianを使うと、2種類のI2S DAC基板用のモジュール
HifiBerry DAC ----- hifiberry_dac.c / pcm5102a.c ICの内部にPLLがありマスタークロックが不要。
RPi-DAC -----
rpi-dac.c
/pcm1794a.c PCM_CLK(BCK)が64fsの固定になっている。 マスタークロックが必要。
がデフォルトで入っている。
とりあえず、手っ取り早い方法として、RPi-DAC用のpcm1794a.c rpi-dac.cをADC用に一部変更して、様子を見てみることにした。
RPi-DAC用の
モジュール変更のため、カーネルの再構築(コンパイル)を行う。自分の環境(8GのSDカード)だと、約10時間ほどかかる。新しくつくったモジュールとカーネルのイメージをインストールしておく。
cd /usr/src/linux/
sudo make modules_install
sudo cp /usr/src/linux/arch/arm/boot/zImage /boot/kernel.img
リブートして、新しいカーネルが動くことを確認する。
次にRPi-DAC用のモジュールの変更を行う。
/usr/src/linux/soundsoc/codecs/pcm1794a.c の中のplaybackをcaptureに変更、
/usr/src/linux/soundsoc/bcm/rpi-dac.c の中で
return snd_soc_dai_set_bclk_ratio(cpu_dai, 32*2); <--- bck=64fs 固定。そのままにしてみる。これを32に変更するとbck=32fsになった。
に変更して、モジュールのコンパイルを行う。
cd /usr/src/linux/
sudo nohup make modules&
nohup.outのログの中身を見てエラーがなければ、
sudo make modules_install
でモジュールの(全部の)インストールを行う。
/etc/modules の中身は以下のように変更してある。
snd-bcm2835
i2c-dev
snd_soc_bcm2708 <--- 実際にはこれは存在していない。lsmod しても出てこない。
snd_soc_bcm2708_i2s
bcm2708_dmaengine
snd_soc_pcm5102a
snd_soc_hifiberry_dac
snd-soc-pcm1794a <--- playback を capture に変更したもの。
snd-soc-rpi-dac <--- bclkのレートを変更したもの。
ここで、オーディオのIN/OUTの状況を見てみると
pi@raspberrypi ~ $ pactl list short sources
0
alsa_output.platform-bcm2835_AUD0.0.analog-stereo.monitor
module-alsa-card.c s16le 2ch
44100Hz IDLE
1
alsa_output.platform-snd-hifiberry-dac.0.analog-stereo.monitor
module-alsa-card.c s16le 2ch
44100Hz IDLE
2
alsa_input.platform-snd-rpi-dac.0.analog-stereo
module-alsa-card.c s16le 2ch
44100Hz IDLE
となり、 変更したものは3番目の alsa_input.platform-snd-rpi-dac となって入力デバイスとして表示されている。
arecordを起動させると、PCM_FSとPCM_CLK端子のDC?電圧を測ると 約1.6Vになっているので、何らかの信号が出力されているようだ。ADCはスレーブ動作となっている。
通常、現在のADCはデルタシグマでオーバーサンプリングしているため、マスタークロック(システムクロック)が必要だ。例えば、256fsなど。
ADCとPiの間に、SRC(サンプリングコンバーター)のICを挟むことも考えてはみたが、・・・・
****
結局、WM8731の例にならって、 ADCがマスターとして(Piはスレーブで)動くように変更してみることにした。
/usr/src/linux/soundsoc/bcm/rpi-dac.c の中で
.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
SND_SOC_DAIFMT_CBM_CFM, <--- マスターに変更。
水晶発振で48kHzの512倍の周波数 24.576MHz(=48KHz x 512 = 96KHz x 256)をADCに供給して、PCM_FS,PCM_CLK(=64fs)をADCからPi側へ供給する。サンプリングレートは48KHz固定になる。
(ADCをマスターにしてPiに接続する回路図)
サンプリングレート48KHzで録音ができることは確認できたが、Piのヘッドフォンジャックで再生すると、やらたノイズ感が多い。
しかし、録音したWAVファイルをUSBメモリーで取り込んでPCで再生すると、それほどでもない。もしかしたら サンプリングレート48KHzだと、Piのヘッドフォン出力の方に何か悪いところがあるのかもしれないね!?
Raspberry Pi I2Sをスレーブ設定にして外部クロック同期でDACを再生
(Linux上のコマンドのメモ)
arecord -vD hw:2,0 -c 2 -r 48000 -f S16_LE name.wav name.wavファイルを指定して I2S 入力から録音する。
Recording WAVE 'name.wav' : Signed 16 bit Little Endian, Rate 48000 Hz, Stereo
Hardware PCM card 2 'snd_rpi_rpi_dac' device 0 subdevice 0
Its setup is:
stream : CAPTURE
access : RW_INTERLEAVED
format : S16_LE
subformat : STD
channels : 2
rate : 48000
exact rate : 48000 (48000/1)
msbits : 16
buffer_size : 24000
period_size : 6000
period_time : 125000
tstamp_mode : NONE
period_step : 1
avail_min : 6000
period_event : 0
start_threshold : 1
stop_threshold : 24000
silence_threshold: 0
silence_size : 0
boundary : 1572864000
appl_ptr : 0
hw_ptr : 0
arecord -l 接続されているサウンドカードが表示される。
**** List of CAPTURE Hardware Devices ****
card 2: sndrpirpidac [snd_rpi_rpi_dac], device 0: HifiBerry Mini HiFi pcm1794a-hifi-0 [] <--- playback を capture に変更したもの。
Subdevices: 1/1
Subdevice #0: subdevice #0
amixer cset numid=3 1 音声出力をオーディオ出力端子に設定する。
amixer cset numid=1 77% ボリュームを調整する。
amixer set Capture 100% 録音レベルの設定。
amixer sset Mic 16 MIC入力レベルの最大にする。
alsamixer F*キーを使ってデバイスを選んで調整できる。
■致命的な問題
①ALSAが上手く起動できない。 amixerを何度か起動させる。 aplay *.wav で何かを再生させて応答が得られるか試してみる。 何度か試みていると、そのうちに応答するようになる?(応答しない場合は ctrl-cで強制終了させている。)
②arecordが上手く起動できない。 audio open error: Device or resource busyが表示される。
⇒ 途中で中断したつもりでも、裏ではまだ動作しているためにおきる。 起動時、前回の設定でまだドライバーが動いていると停止動作が入るようなので、数回起動すればできるようになるのかな?
■参考になる資料
■
警告
PI基板をつかって接続する場合は、電気的なことをよく理解した上でお
使いください。そうしないと、PI基板と接続した相手などを破壊する危険があります。
■免責
(1)回路図やプログラムやデータの使用により、使用者に損失が生じたとしても、その責任
を負いません。
(2)回路図やプログラムやデータにバグや欠陥があったとしても、修正や改良の義務を負い
ません。