
Raspberry Pi CM4とCSI-2接続HDMI入力基板で音も取る
- Mzyy94
- Multimedia
- 28 Feb, 2022
2年前に投稿したHDMI入力をRaspberry Piで取り込む記事では映像しか取得していませんでしたが、このHDMI入力基板には音声も取り込めるチップTC358743が搭載されています。 取り込める端子は購入したHDMI入力基板にもちゃんと用意されていたので、ピンヘッダを取り付けて信号を見たりしたものの、音声出力が正常に取得できませんでした。 この問題をあれこれ探し回って解決した記録を残しておきます。
HDMI入力をRaspberry Piで駆使する
昨今の衰えることのない技術トレンドに追従すべく、映像配信とかやりたいなーと思っていた2019年。 めっきり時間がなく何もできず、気付けば2020年になっていました。今年も時間がないだろうなぁと思っていたところ、連日の在宅勤務のおかげで通勤時間がゼロになり、余暇が生まれたので色々やってみることにしました。お題はHDMI入力で遊ぶ、です。...
- Mzyy94
- Multimedia
- 09 Apr, 2020
目次
Open 目次
HDMI入力基板で音声も取り出そうとした2020
実は当時、ブログ記事を投稿する直前まで音声出力が正しく得られないかどうかを色々と試行錯誤していました。参考リンクにその調査に使ったリンクが一部残してあります。 しかし一筋縄ではいかず音声出力を得ることはできなかったため、その時に書いていた下書きをボツにしていました。 しばらくして解決したものの、記事を完成させるモチベーションもなくお蔵入りになる予定でしたが、ちょうどreTerminal拡張モジュールコンテストにHDMI入力モジュールとして応募したこともあって、ゴミ箱から拾ってきて記事として完成させました。 なので内容としては2年前の記録になりますが、ブラッシュアップしてあります。
なお、当時はBullseyeベースの新しいRaspberry Pi OSは登場していなかったこともあり、この記事の内容は全てBusterベースのRaspberry Pi OSでの動作を記しています。また、本記事執筆時(2022/02/26)の最新版である以下の構成で動作確認をし直しています。
OS: Raspberry Pi OS
Raspberry Pi OS (Legacy) with desktop
Release date: January 28th 2022
ハードウェア: Raspberry Pi 4B
Hardware : BCM2711
Revision : c03112
Model : Raspberry Pi 4 Model B Rev 1.2
カーネル: 5.10.63-v7l+
Linux raspberrypi 5.10.63-v7l+ #1496 SMP Wed Dec 1 15:58:56 GMT 2021 armv7l GNU/Linux
ファームウェア: Dec 1 2021 15:02:46
Dec 1 2021 15:02:46
Copyright (c) 2012 Broadcom
version 71bd3109023a0c8575585ba87cbb374d2eeb038f (clean) (release) (start_x)
HDMI入力基板 H2C-RPI-B01とTC358743XBG
以前の記事で使ったHDMI入力基板、H2C-RPI-B01はRaspbianRaspberry Pi OSの標準ドライバで処理され、接続するだけでRaspberry Pi Camera Moduleと同様のV4L2デバイスとして認識され、映像入力を扱えました。
何もしなくても動いたのは良かったのですが、何もしなかったためにCamera Moduleと同様に映像しか扱えませんでした。
H2C-RPI-B01に搭載されているチップであるTC358743XBGは、実はHDMI音声入力が扱えます。データシートにはI2Sバス規格で音声データのやりとりをすると書かれています。
引用元: TC358743XBG_datasheet_en_20171026.pdf TC358743XBG | HDMI® インターフェースブリッジ | 東芝デバイス&ストレージ株式会社 | 日本
I2S (Inter-IC Sound Bus)
I2SはInter-IC Soundという音声通信バス規格のことです。
NXP Semiconductorsが1986年に仕様を定義したものですが、オリジナルの仕様書はインターネットの海に沈没してしまっていて、アーカイブしか見つけられません。
4つのピンでクロックとデータをやりとりするシリアルバス規格であり、日本語版Wikipediaの記事に要約が書かれています。
Raspberry PiのGPIO端子は音声入力と出力の両方に対応しており、PCM_で始まるラベルのついているピン(GPIO 18,19,20,21)がI2Sです。
引用元: GPIO and the 40-pin Header - Raspberry Pi Documentation
音声を取り出す最初の挑戦(2020年4月)
I2Sのハードウェア接続とファームウェア設定を行い、音声の取り込みに挑戦していきます。
ハードウェアの配線
HDMI入力基板の出力ピンとRaspberry Pi 40ピンヘッダーのI2Sのピンとを接続します。
HDMI入力基板には10ピンの入出力端子を取り付けられるスルーホールが用意されています。 H2C-RPI-B01以外の類似品をいくつも買ってみましたが、同じTC358743XBGを搭載する基板には大抵あります。
少し離れたところに各スルーホールの機能を記すシルクがありますが、それを参考にして下表の通り接続します。
HDMI入力基板シルク | Raspberry Pi ピン番号 | Raspberry Pi GPIO |
---|---|---|
SCK | 12 | PCM_CLK(GPIO 18) |
WFS | 35 | PCM_FS(GPIO 19) |
SD | 38 | PCM_DIN(GPIO 20) |
Raspberry Pi OSのファームウェア設定
I2Sの配線を済ませただけでは音声入力を扱えないので、ファームウェアの設定とドライバのロードをさせます。
Device Tree
Linuxがドライバをロードする時、接続されているデバイス情報を元に適切なドライバを選択しています。 接続デバイスを管理するのがDevice Treeというハードウェア構成情報です。Device Treeは /proc/device-tree のprocファイルシステムを覗くと、だいたいどんなものが認識されているかがわかります。文献は以下に詳しいです。
- Device Trees, overlays, and parameters - Raspberry Pi Documentation
- Device Tree Reference - eLinux.org
TC358743のドライバであるmedia/i2c/tc358743.cは、次のようにデバイスを見つけてドライバの初期化(probe)を行います。
static const struct of_device_id tc358743_of_match[] = {
{ .compatible = "toshiba,tc358743" },
{},
};
MODULE_DEVICE_TABLE(of, tc358743_of_match);
linux/drivers/media/i2c/tc358743.c#L2255-L2259
compatibleに”toshiba,tc358743”と記載のあるデバイスがあれば、tc358743のドライバが読み込まれるということです。 ただ、何も設定をしていないRaspberry Pi OSではそのような記載のあるデバイスはなく、Camera Moduleのvc04_services/bcm2835-camera.cがドライバとして読み込まれてしまっています。
linux/bcm2835-camera.c at 1.20220120 · raspberrypi/linux
Camera Moduleのドライバではなく、TC358743のドライバであるmedia/i2c/tc358743.cをロードさせるために、Device Treeを上書きしてファームウェアを設定します。
Device Tree Overlay
Device Treeを上書きする機能の名はDevice Tree Overlay。そのまんまです。
RaspbianRaspberry Pi OSではこれを読み込むことで、Device Treeを上書きできます。
Raspberry Pi OSには、 /boot/overlays にDevice Tree Overlayの構成ファイル、Device Tree Blob Overlay(.dtbo)が格納されています。
firmware/boot/overlays at 1.20220120 · raspberrypi/firmware
Blobと名前に含まれるように、バイナリファイルにコンパイルされたものですが、これらのソースコードはraspberrypi/linuxの /arch/arm/boot/dts/overlays にあります。
linux/arch/arm/boot/dts/overlays at 1.20220120 · raspberrypi/linux
この中にtc358743向けのoverlayが存在し、次のように書かれています。
__overlay__ {
#address-cells = <1>;
#size-cells = <0>;
status = "okay";
tc358743@0f {
compatible = "toshiba,tc358743";
reg = <0x0f>;
status = "okay";
linux/tc358743-overlay.dts at 1.20220120 · raspberrypi/linux
compatible = "toshiba,tc358743";
とあるので、このdtboを読み込めばtc358743がデバイスとして認識され、ドライバが読み込まれるということです。
ただ、これだけでは音声入力を扱うことはできません。
HDMI入力基板と音声をI2Sでやり取りするには、音声インターフェースのDevice Tree定義とドライバの読み込みが必要です。
TC358743XBGのI2S用の定義も、RaspbianRaspberry Pi OSのDevice Tree Overlayに用意されています。
linux/tc358743-audio-overlay.dts at 1.20220120 · raspberrypi/linux
これらのDevice Tree OverlayとI2Sを扱うパラメーター設定を/boot/config.txtに記述する方法を深く理解しながら/boot/config.txtに追記します。
dtparam=i2s=on
dtparam=audio=on
dtoverlay=tc358743
dtoverlay=tc358743-audio
これで再起動すると、lsmod
やdmesg
でmedia/i2c/tc358743.c のドライバーが読み込まれていることが確認できます。
overlayが正しく読み込まれているかどうかは、sudo vcdbg log msg
などで確認できます。
pi@raspberrypi:~ $ dmesg | grep tc358743
[ 4.137243] tc358743 0-000f: tc358743 found @ 0x1e (bcm2835 I2C adapter)
pi@raspberrypi:~ $ lsmod | grep tc358743
tc358743 40960 1
v4l2_dv_timings 36864 2 bcm2835_unicam,tc358743
v4l2_fwnode 20480 2 bcm2835_unicam,tc358743
v4l2_common 16384 3 bcm2835_unicam,bcm2835_v4l2,tc358743
videodev 200704 9 bcm2835_unicam,v4l2_fwnode,bcm2835_codec,v4l2_common,videobuf2_common,bcm2835_v4l2,v4l2_mem2mem,videobuf2_v4l2,tc358743
media 36864 5 bcm2835_unicam,bcm2835_codec,videodev,v4l2_mem2mem,tc358743
pi@raspberrypi:~ $ ls /dev/video*
/dev/video0 /dev/video10 /dev/video11 /dev/video12
pi@raspberrypi:~ $
音声出力信号の取り込み
ファームウェアとハードウェアの設定を済ませ、I2Sでの音声信号を取り出していきます。
TC358743は通常のI2Sオーディオデバイスとは違って、音声信号の制御などをCSI-2を通るI2Cで指示してあげる必要があります。 この制御に関してフォーラムに情報がありました。
HDMI to CSI-2 TC358743 I2S Audio - Raspberry Pi Forums
細かい操作はドライバでやってくれるので、v4l2で大体の設定をすれば良いようです。
pi@raspberrypi:~ $ wget https://raw.githubusercontent.com/mzyy94/ns-remote/master/720P30EDID.txt
pi@raspberrypi:~ $ v4l2-ctl --set-edid=file=720P30EDID.txt
pi@raspberrypi:~ $ v4l2-ctl --set-dv-bt-timings query
ここまでできたら、HDMIに接続しているデバイスから音声を出力してみると、v4l2-ctl --list-ctrls
のaudio_presentがvalue=1になってることが確認できるはずです。
pi@raspberrypi:~ $ v4l2-ctl --list-ctrls
User Controls
audio_sampling_rate 0x00981980 (int) : min=0 max=768000 step=1 default=0 value=48000 flags=read-only
audio_present 0x00981981 (bool) : default=0 value=1 flags=read-only
Digital Video Controls
power_present 0x00a00964 (bitmask): max=0x00000001 default=0x00000000 value=0x00000001 flags=read-only
この状態になったら、あとは取り込むだけ。ただ、いざI2Sオーディオ入力を録音しようと試みるも、一向にデータはやってきません。 そして何やらエラーが出ているようです。
pi@raspberrypi:~ $ sudo dmesg -C
pi@raspberrypi:~ $ arecord -D plughw:1 -c1 -r 48000 -f S32_LE -t wav -V mono rec.wav
Recording WAVE '/tmp/rec.wav' : Signed 32 bit Little Endian, Rate 48000 Hz, Mono
^CAborted by signal Interrupt...
arecord: pcm_read:2145: read error: Interrupted system call
pi@raspberrypi:~ $ dmesg
[ 560.152152] bcm2835-i2s fe203000.i2s: I2S SYNC error!
pi@raspberrypi:~ $
I2Sのクロック周りで同期が取れないようなエラーです。オシロスコープでI2S信号を観測したところ、確かに波形がおかしく基板上に問題がありそうだということがわかったのです。
ケーブル4本をはんだで繋げてみたんですが、I2S信号が期待通りではなくてALSAで取り込めませんでした😭
— MMP (@mzyy94) 2020年5月26日
色々と試行錯誤していた時にオシロスコープを燃やしてしまったのでHDMI入力基板からの音声入力は諦め、UAC Gadget経由でお茶を濁すことにしたのでした。
プローブがショートして白い煙出しながらオシロスコープ発火してモニター消えたので終わり。
— MMP (@mzyy94) May 21, 2020
UAC GadgetでNintendo Switchの音声出力をRaspberry Piに取り込む
前回の記事 でHDMI映像入力をRaspberry Piで扱う方法を紹介し、その最後に音声の取り込みについて、まだ課題が残っていると書きました。 HDMI入力からの音声取り込みといった、本質的な課題の解決を試みているものの、なかなかに難しい問題に直面しているので、対象を限定して部分的解決に挑みます。主に今HDMI入力の対象として使おうと思っているデバイスは、Nintendo Switchです。...
- Mzyy94
- Multimedia
- 17 Apr, 2020
音声を取り出すリベンジ
UAC Gadgetから音声入力をする記事でお茶を濁して数ヶ月経った頃、Raspberry Pi Forumsに類似品のHDMI入力基板で音声が取り込めない問題をハードウェア的にパッチを当てて解決する方法が投稿されました。
これによってパッチを当てれば信号が得られるということがわかったので、試すことにしました。
足りない配線とI2S APLLパッチ
TC358743でI2S信号を正しく扱うための配線は、Functional Specificationなる仕様書に書かれているらしいのです。 「らしい」というのは、その仕様書は東芝とNDAを結ばないと手に入れられないもので、現物を確認できていないからです。
NDA下にある書類ということで、インターネットの海にはなかなか流れていなんですが、数字の末尾が3→9になった兄弟チップであるTC358749XBGの仕様書はFireflyが放流してくれています。
これを参考にしてパッチを作っていきます。
Raspberry Pi Forumsの投稿によると、I2Sの信号がおかしいのは音声信号の位相同期回路(PLL)が実装されていないことによるとのこと。 このAudio PLLに関する機能仕様を兄弟チップのTC358749XBGの仕様書から探してみると、次のような回路を用意すればいいというのがわかりました。
抵抗値や静電容量は他のTC358シリーズの仕様をいくつも読み漁って推定したものです。
ユニバーサル基板に実装
先ほどの回路図のうち、C3とC6はH2C-RPI-B01に実装されているのでそれ以外の配線を行い、次のように配置しました。
これをユニバーサル基板に実装し、フォーラムにある類似基板の解析結果を参考にしながらH2C-RPI-B01につなげていきます。
再度録音に挑戦
前回の挑戦と同じくして、Device Tree Overlayの設定とv4l2の設定を済ませarecordで録音したところ、ちゃんとレベルメーターでも音声が入力していることを確認でき、きれいに録音されたファイルも出来上がって大成功でした。
reTerminalやCM4で使えるようにする
Raspberry Pi 4Bで無事に録音できたので、さてケースに収めてreTerminalの拡張モジュールにするぞ!と意気込んだものの、CSI-2に通るI2Cがうまく通信できずにreTerminalでは動作してくれませんでした。
pi@raspberrypi:~ $ dmesg | grep tc3
[ 10.534939] tc358743 10-000f: i2c_rd: reading register 0x0 from 0xf failed
[ 10.534957] tc358743 10-000f: not a TC358743 on address 0x1e
I2Cの設定を変えてみたりエラーメッセージやCompute Module特有の2つのCSI-2について調べてみたりすると、ずばり解決につながるフォーラムの投稿に行き当たりました。
Two B102 TC358743 simultaneously on CM4 - Raspberry Pi Forums
CM3/CM4ではMIPI CSI-2のバスが二つあり、そのうちCSI0で動作させるにはDevice TreeのI2Cバスを変更する必要があるとのことでした。 フォーラムの投稿はちょっと古いので最新のファームウェアに合うように修正してみたところ、ちゃんと認識され録音できるようになりました。 パッチはGitHubにおいておきました。
reTerminal-HDMI-input/overlays at master · mzyy94/reTerminal-HDMI-input
まとめ
やっとこれでHDMI入力拡張モジュールとして機能する形にできました。今回の成果も以下のリポジトリでまとめておいたので、興味ある物好きな人は参考にどうぞ。
mzyy94/reTerminal-HDMI-input: HDMI input expansion module for reTerminal
ちなみにこのパッチが組み込まれた音声も取れる格安HDMI入力基板が今年の1月に発売されていたことを、今まさにこの記事を書いている最中に知りました。 少しばかり高いですが、わざわざAPLLパッチを作る必要はありません。これまでの苦労とは一体。。。😭
南無

Hdmi対応にCSI 2モジュール、X630 hdmi CSI 2のためのラズベリーパイ4B/3B +/3B/パイゼロ|Demo Board Accessories| - AliExpress