基板や配線の写真、回路図、より詳しい解説は自分のサイトのブログに載せています。画像つきで見たい方はこちらをどうぞ。
https://ikko-labs.com/blog/ms2109でhdmiキャプチャボードを自作した記録
はじめに
MacroSilicon MS2109(HDMI入力 → USB2.0 UVC出力)でキャプチャボードを設計し、JLCPCBで4層基板を作って動かすまでの記録です。
部品はすべてJLCPCBに在庫のあるもので揃えました。基板は一発でHigh-Speed認識して1080p30の映像が出ましたが、画面にノイズが乗っていたので、キャプチャ画像の画素値を測って原因を切り分けました。結論から言うと基板の不良ではなくMJPEG圧縮でした。
同じICを使う人向けというより、データシートからどう設計意図を読むかと、不具合の切り分けをどうやるかに重点を置いて書いています。
作ったもの
HDMI-019S ─[ESD ×2]─ TMDS 4ペア ─→ MS2109 ─→ USB 2.0 (4ピンヘッダ)
↑
24MHz水晶 / REXT / EEPROM / 降圧DC-DC ×2
| 役割 | 部品 | LCSC | 備考 |
|---|---|---|---|
| キャプチャSoC | MS2109 | C961325 | QFN-48-EP 7×7mm |
| ファーム格納 | AT24C16 | C561263 | I2C EEPROM |
| 降圧DC-DC ×2 | SY8089A1AAC | C479074 | 3.3V / 1.2V |
| ESDアレイ ×2 | TPD4E05U06DQAR | C138714 | 0.5pF 4ch |
| HDMIコネクタ | HDMI-019S | C111617 | Type-A |
| 水晶 | X322524MOB4SI | C70590 | 24MHz CL=12pF |
4層基板(JLC04161H-7628、1.6mm)、全20種51点、部品代は1枚あたり約$5.5です。
IC選定:JLCPCBの在庫から逆算する
MacroSiliconのキャプチャICを、JLCPCBの実装用在庫と合わせて並べました。
| 型番 | 入出力 | パッケージ | 在庫 | 単価 |
|---|---|---|---|---|
| MS2109 | HDMI → USB2.0 | QFN-48-EP 7×7 | 776 | $2.26〜3.65 |
| MS2130 | HDMI → USB3.0 | QFN-64-EP 9×9 | 663 | $3.08〜4.73 |
| MS2131 | HDMI → USB3.0 | LQFP-100 | 41 | $4.31〜6.15 |
| MS2106E | アナログ → USB2.0 | LQFP-48 | 実装在庫なし | $1.12〜1.91 |
USB3.0のMS2130も在庫はありますが、QFN-64の9mm角で難易度が上がるため、まずMS2109にしました。
参考にしたのはこの2つです。
- 写真・回路図つきの詳細版(自分のブログ)
- YuzukiHD/YuzukiHCC ─ MS2109のオープンソース設計(CERN-OHL-P)
- BertoldVdb/ms-tools ─ EEPROM読み書きツール(MIT)
データシートから読み取れた設計意図
この手のチップは応用回路が1枚載っているだけですが、ネット名の付け方に設計意図が表れます。
1.2Vは1本、3.3Vは3本
MS2109の電源ピンを、データシートの応用回路でのネット名ごとに分けるとこうなります。
| ネット | ピン | 生成 |
|---|---|---|
VDD12 |
19, 41(DVDD12)+ 27, 33(AVDD12) | 降圧DC-DC出力 |
DVDD33 |
16, 23, 44 | 降圧DC-DC出力 |
AVDD33 |
24, 30, 47 | 3V3 → フェライト |
V33USB |
6, 7, 8 | 3V3 → フェライト |
AVDD12とDVDD12は同じネットです。名前が分かれているので分離したくなりますが、メーカーの応用回路が1本にしています。
一方3.3Vは分かれています。AVDD33はTMDS入力段のアナログ電源なので、デジタルI/Oのノイズから切り離す意図です。V33USBはUSB PHY専用で、データシートが「100nF + 10µFをピン直近に(CLOSE TO PIN)」と明記しています。
つまり「アナログとデジタルを分ける」のは3.3V系だけで、1.2Vコアは分けなくていい、という設計者の判断が読み取れます。
デカップリングは「レール単位」ではなく「ピン単位」
ここは最初に間違えました。
同じレールでも、コンデンサは電源ピン1本につき1個置きます。目的はレールの平均電圧を保つことではなく、そのピンから見た電流ループのインダクタンスを潰すことなので、ピンから数mm離れただけで高周波では効きません。
MS2109の電源ピンがQFNのどの辺にあるかを並べるとこうなります。
| レール | ピン | QFN上の辺 | 100nF |
|---|---|---|---|
| V33USB | 6, 7, 8 | 左のみ | 1(連続ピンで実質1ノード) |
| DVDD33 | 16, 23, 44 | 下・下・上 | 3 |
| AVDD33 | 24, 30, 47 | 下・右・上 | 3 |
| DVDD12 | 19, 41 | 下・上 | 2 |
| AVDD12 | 27, 33 | 右・右 | 2 |
1.2Vは単一レールですが、pin 19が下辺・pin 41が上辺とパッケージの反対側なので4個必要です。AVDD33も3辺に散っているので3個。
データシート§11.1も「電源は先にコンデンサを通してからチップのピンへ入れ、コンデンサのGNDは直近でビアを打って落とす」と、明確にピン単位の書き方をしています。
DDCのプルアップは3.3Vに引かない
| HDMIピン | 接続 |
|---|---|
| 15, 16 (DDC) | 47kΩでHDMI +5V(pin 18)へプルアップ |
| 18 (+5V) | 1kΩ → HDRXDET、100nF → GND |
| 19 (HPD) | 1kΩ ← HDRXHPD |
HDMI規格では、シンク側がソースの供給する+5Vに対してプルアップを持ちます。ただしMS2109のDDCピンは3.3Vなので、規格が想定する1.5〜2kΩではなく47kΩという弱いプルアップをデータシートが指定しています。
+5V検出(HDRXDET)は分圧しません。コネクタpin 18の5Vを1kΩ経由でそのまま入れます。MS2109側の内部クランプと1kΩで電流を制限する設計です。
ハマりどころ
水晶は4パッド品
X322524MOB4SI はSMD3225-4Pです。2端子だと思って描いていて、途中で気づきました。
| パッド | 機能 |
|---|---|
| 1 | 水晶端子 → XTIN |
| 2 | ケース(金属リッド)→ GND |
| 3 | 水晶端子 → XTOUT |
| 4 | ケース(金属リッド)→ GND |
2と4は金属リッドに内部接続されたシールド端子です。浮かせたままにするとリッドがアンテナとして働き、発振の安定度が落ちます。
負荷容量の12pF×2は、データシートの応用回路がNC表記だったので最初はDNPにするつもりでしたが、結局実装しました。CL=12pFの水晶に12pFの負荷容量だと周波数が数十ppm高めに出ますが、USB映像では問題になりません。
基板設計:効くのは最小線幅ではなくインピーダンス
JLCPCBの製造限界と、追加費用がかからない実用ラインは別物です。
| 項目 | 2層 | 4層 |
|---|---|---|
| 配線幅 / 間隔(1oz) | 0.1 / 0.1 mm | 0.09 / 0.09 mm |
| ビア(穴 / パッド) | 0.15 / 0.25 mm | 同左 |
追加費用の境界は 配線3.0〜3.5mil で +20%、ビア0.3mm未満で割高です。5mil/5mil・ビア0.3mmに収めれば追加費用なしです。
ただし実際に効くのはインピーダンスでした。4層標準スタックアップJLC04161H-7628はL1-L2間のプリプレグが0.2104mm(Dk=4.4)で、必要な線幅はこうなります。
| 用途 | 目標 | W | S |
|---|---|---|---|
| TMDS差動 | 100Ω | 約0.22 mm | 約0.18 mm |
| USB D±差動 | 90Ω | 約0.24 mm | 約0.13 mm |
| 単線 | 50Ω | 約0.35 mm | — |
最小値の0.09mmよりはるかに太いので、細く引けることより、規定の太さで引けるスペースの確保が課題になります。
2層では物理的に無理
| 構成 | 誘電体厚 | 100Ω差動に必要な線幅 |
|---|---|---|
| 2層 1.6mm | 約1.53 mm | 約2.0 mm |
| 2層 0.6mm | 約0.53 mm | 約0.7 mm |
| 4層 1.6mm | 0.21 mm | 約0.22 mm |
MS2109はQFN-48の0.5mmピッチでパッド幅が0.25mmです。2層だとパッドの8倍幅の配線を0.25mmのパッドに繋ぐことになり、描けません。
さらにデータシートが「差動線の直下層は配線を通さずベタGNDを確保」と要求しているので、2層で信号面の裏を全部GNDにすると電源を通す層がなくなります。
動作確認
測定器はテスタのみでした。
通電前
抵抗レンジで、電源を入れない状態で測ります。
| 測定点 | 期待値 | 根拠 |
|---|---|---|
| VBUS ↔ GND | 数百kΩ以上 | DC経路なし |
| 3V3 ↔ GND | 約12kΩ | FB分圧 10k + 2.2k |
| 1V2 ↔ GND | 約20kΩ | FB分圧 10k + 10k |
導通レンジで、3V3↔A3V3と3V3↔V33USBが鳴ること(フェライトのDCR)、3V3↔1V2が鳴らないことを確認します。
初回通電はUSB充電器で、HDMIは挿さない
この基板の電源はUSB VBUSだけです。HDMI側の+5Vは検出入力とDDCプルアップ源にしか使っていないので、HDMIだけ挿しても何も起きません。
むしろHDMIを先に挿すと、MS2109の電源が0Vのままソース側の+5Vが1kΩ経由でHDRXDETに入ります。無給電のICに電圧が加わる状態で、ラッチアップの原因になります。
電流制限電源がなかったので、PCに挿す前にUSB充電器で通電しました。電源系の確認はVBUSがあればできるので、データ線が繋がらない充電器で十分です。
| 測定点 | 設計値 | 実測 |
|---|---|---|
| 3V3 | 3.327 V | 範囲内 |
| 1V2 | 1.200 V | 範囲内 |
USB認識
EEPROMは空のまま実装したので、ROM内蔵のデフォルト設定で立ち上がるかを見ます。
Vendor ID : 0x534D (Hefei Macrosilicon Technology Co., Ltd.)
Product ID : 0x2109
Manufacturer String : "MACROSILICON"
Product String : ---
USB Version : 2.0 (480 Mbit/s)
Device Connection Speed : High-Speed
Video : UVC Version 1.00
-------- Default Video Modes --------
1920 x 1080 @ 30 fps : MJPEG
1920 x 1080 @ 5 fps : YUY2
1280 x 720 @ 30 fps : MJPEG
1280 x 720 @ 10 fps : YUY2
640 x 480 @ 30 fps : MJPEG, YUY2
(他、計11種)
読み取れること。
- High-Speed ─ D±の配線とインピーダンスが正常
- Product Stringが空 ─ EEPROM未書き込みの確認(予定どおり)
- 解像度リストがデータシート§6.4 表6.3と完全一致 ─ ROMが正常にブートしている
映像ノイズを画素値で切り分ける
1080p30の映像は出たのですが、PCのデスクトップを映すと小さな文字がマゼンタとシアンに染まりました。TMDSの配線が悪いのか、USBの転送エラーなのかを切り分けたくて、キャプチャ画像の画素値を測りました。
from PIL import Image
import numpy as np
im = Image.open('capture.png').convert('RGB')
a = np.asarray(im).astype(int)
R, G, B = a[:,:,0], a[:,:,1], a[:,:,2]
dark = (R+G+B)/3 < 170 # 文字の部分
mag = ((R+B)/2 - G > 40) # マゼンタに寄った部分
print("暗部 RGB:", R[dark].mean(), G[dark].mean(), B[dark].mean())
print("マゼンタ RGB:", R[mag].mean(), G[mag].mean(), B[mag].mean())
print("R-B 平均:", (R-B).mean())
結果です。
| 測定 | 結果 |
|---|---|
| 黒い文字のRGB | (22, 22, 23) |
| マゼンタ部のRGB | (246, 167, 247) |
| R − B の平均 | −0.2 |
読み方
黒い文字が完全な無彩色です。TMDSのチャンネルが1本落ちていれば、ここに色が付きます。
マゼンタ部はRとBがほぼ同値(246と247)でGだけが80低い。R−Bの平均が−0.2、つまりRとBが完璧に連動しています。これは単一チャンネルの欠損では起こりません。
さらに大きな文字を拡大すると、エッジまで真っ黒で色にじみがなく、白背景も純白でした。
つまり 輝度(Y)は正常で、色差(Cb/Cr)だけが細かい部分で崩れている。
- TMDSの問題なら → 大きな黒ベタやエッジにもスパークルや横スジが出る
- USB転送エラーなら → 平坦な白い部分もブロック単位で壊れる
どちらも起きていないので、伝送路ではなく圧縮が原因と絞り込めました。
帯域で裏が取れる
MS2109は1920×1080@30をUSB 2.0に押し込むためMJPEGで圧縮しています。
- 非圧縮なら
1920×1080×2byte×30fps = 124 MB/s(約1Gbps) - USB 2.0 High-Speedの実効帯域は約 20 MB/s
- 圧縮率は約6:1
実写なら6:1はほぼ無劣化ですが、細かい文字には効きます。そこにクロマサブサンプリングが乗るので、色情報が最初に犠牲になります。
決定的だったのは、UVCの解像度リストのfpsの付き方です。
| モード | データレート |
|---|---|
| 1920×1080 @5 YUY2 | 20.7 MB/s |
| 1280×720 @10 YUY2 | 18.4 MB/s |
| 640×480 @30 YUY2 | 18.4 MB/s |
どれも約18〜21 MB/sに揃っています。 これがUSB 2.0 High-Speedの実効上限で、MacroSiliconはそこに収まるようにfpsを決めていました。
対策
YUY2(非圧縮)モードを使えば無劣化です。
| 用途 | 推奨モード |
|---|---|
| PC画面・文字を読む | 1920×1080 @5 YUY2 |
| PC画面・多少動く | 1280×720 @10 YUY2 |
| ゲーム・動画 | 1920×1080 @30 MJPEG |
市販のMS2109ドングルも同じ症状が出ます。根本的に解決するにはUSB 3.0のMS2130にするしかありません。
おまけ:4系統を同時にキャプチャできるか
MS2109を4個並べれば4系統いけそうに思えますが、UVCのisochronous帯域予約が壁になります。
- USB 2.0 High-Speedでisochronousに割ける帯域: 384 Mbps(規格上、全体の80%まで)
- UVCデバイス1台が申告する最大値: 196 Mbps(3072バイト/マイクロフレーム)
384 ÷ 196 ≒ 1.9。1台で枠のほぼ半分を持っていくので、2台目でギリギリ、3台目は確実に弾かれます。LinuxならENOSPCです。
厄介なのは、実際の消費量ではなく申告値で予約されることです。MJPEGは圧縮後のサイズが読めないため、カーネルは申告値を信じるしかありません。640×480に落としても、申告値が下がらなければ意味がありません。
現実的な解は、前段にHDMIマルチビューア(4画面分割器)を置いて、1つのUVCデバイスとして取り込むことです。
参考: Multiple UVC cameras on Linux: an unexpected challenge
まとめ
- データシートの応用回路は、ネット名の付け方に設計意図が出る。
VDD12が1本でAVDD33とDVDD33が別、という事実から分離の方針が読める - デカップリングはレール単位ではなくピン単位。パッケージのどの辺にピンがあるかまで見る
- 初回通電はUSB充電器で。HDMIは後
- 不具合の切り分けは画素値を測る。輝度と色差のどちらが壊れているかで、伝送路か圧縮かが分かる
HDMIくらいの速度なら、差動インピーダンス・ビアの本数・GNDベタを分割しないことの3つを守れば通せました。
