#0 で RTL-SDR Blog V4 を母艦で動かすところまで来た。今回からいよいよ信号処理。復調器の最初の段、② OFDM同期を実装して、大阪の地デジ(関西テレビ)の生電波に実際にロックさせるところまでやる。…のだが、途中で GI=1/32 というもっともらしい嘘を一度つかまされた。その誤診と修正までが今回の本題。
② OFDM同期 = ガードインターバルの自己相関
OFDMは、各シンボルの頭にガードインターバル(GI / サイクリックプレフィックス, CP)を付ける。これは「有効シンボルの末尾Lサンプルをそのまま頭にコピーしたもの」だ。つまり受信列 r の中で、Nサンプル(有効シンボル長)離れた2点は、CP区間でそっくり相関する。
これを使うのが van de Beek らの最尤推定。各開始位置 d について、
γ(d) = Σ_{k=0..L-1} r[d+k]·conj(r[d+k+N]) ← CP区間の相関
Φ(d) = Σ_{k=0..L-1} (|r[d+k]|² + |r[d+k+N]|²)/2
M(d) = |γ(d)| / Φ(d) ← 0..1、1で完全相関
を計算し、M(d) が最大の d をシンボル境界とする。さらにそのときの位相から、小数キャリア周波数オフセット(CFO)が ε = -arg(γ) / 2π(キャリア間隔単位、±0.5)で同時に求まる。1パスのスライディング窓で全位置を O(N) で舐められる。これを Rust で書いた。
まず合成信号で土台を固める
実電波を録る前に、答えが分かっている合成OFDMで検証する。QPSK×1024キャリア+CPを生成し、わざと既知のCFO(0.17副搬送波)と前置きオフセットとノイズを混ぜ、同期が「境界を±2サンプルで当てる/CFOを復元する」かをテストにした。実IQが無くても土台を固められるのがいい。ここが緑になってから次へ進む。
実電波を録る ── アンテナが弱くて最大ゲインが要った
住んでいるのは堺市。送信所は生駒山。まず rtl_power で大阪のUHF帯をスイープして、どの局が拾えているか確かめた。最初は普通のゲインで回したらほぼノイズ床で何も見えない。アンテナがOTA信号をほとんど拾えていない。ゲインを最大(49.6dB)に上げて再スイープすると、ようやく出た:
強い順 TOP:
ch17 497.143MHz 床比+11.5dB ← 関西テレビ(カンテレ)
ch16 491.143MHz 床比+10.1dB ← 毎日放送(MBS)
ch18 503.143MHz 床比 +4.6dB
...

ch17(カンテレ)が一番強い。床+11dB は強くはないが、ワンセグはもともとモバイル前提で頑丈な変調なので十分いける。中心周波数 497142857 Hz を、サンプルレート 1015873 Hz で12秒キャプチャした。このヘンなレートには理由がある:フルセグの基準 fIFFT = 512/63 MHz の 1/8 がちょうどこの値で、これにすると 1seg Mode3 の有効シンボル長がきっかり1024サンプル(整数)になる。半端なレートで録ると r[j] と r[j+N] の N がズレてCP相関が鈍る。
timeout 13 rtl_sdr -f 497142857 -s 1015873 -g 49.6 cap.iq
コケた ── 「GI=1/32」というもっともらしい嘘
録ったIQを同期にかけたら、強烈なピーク(metric 0.957)が立った。ロックはした。が、推定されたGIが 1/32 と出た。日本の地デジ(ISDB-T Mode3)は普通 GI=1/8 のはず。おかしい。
裏を取るために「検出した周期 N+L ごとに、本当にピークが繰り返し立っているか」を見たら ── 隣のシンボル位置のメトリクスが低い。周期的に立っていない=その周期は偽物。
原因は判定ロジックだった。正規化メトリクス |γ|/Φ は、本物のCPより短いLで窓を取っても 1 付近に張り付く。だから「単発のメトリクスが最大のGIを選ぶ」とやると、たまたま尖った最短のGI(1/32)に引っ張られる。1点のピークの高さでGIを決めてはいけなかった。
直した ── 周期性でGIを選ぶ
正しい指標は「そのGIを仮定したとき、CPが周期 N+L ごとに繰り返し立っているか」だ。各GI候補についてメトリクス曲線を作り、周期 N+L で折り畳んで位相平均を取る。本物のGIなら真の境界位相で平均くしが高く尖り、偽のGIなら全位相で平坦になる。そのくしの高さ(周期性スコア)でGIを選ぶ。
書き直して同じIQにかけた結果がこれ:
=== GI周期性スコア(高いほど本物)===
G1_4 (sym=1280) score=0.130 #####
G1_8 (sym=1152) score=0.671 ########################## ★
G1_16 (sym=1088) score=0.196 #######
G1_32 (sym=1056) score=0.269 ##########
=== ② OFDM同期 結果 ===
GI推定 : G1_8
symbol_start : 258576
metric(0..1) : 0.910
小数CFO : -0.0540 副搬送波 = -53.5 Hz
周期性チェック(sym長 = 1152):
d= 256272 (#-2) M=0.905 ####################################
d= 258576 (#+0) M=0.910 ####################################
d= 260880 (#+2) M=0.657 ##########################
✅ CP相関ロック
GI=1/8 がスコア0.671で圧勝。今度は周期1152ごとにちゃんとピークが立っている。そして 1/8 は日本のISDB-T Mode3の仕様どおり。規格表を見て「1/8のはず」ではなく、生電波から自力で1/8を当てられたのが気持ちいい。

おまけに小数CFOは −53.5Hz しかなかった。V4は TCXO(温度補償水晶)を積んでいるので、周波数ずれが極小。スペック表の「Bias-T / TCXO / HF」のチェックが、こういうところで効いてくる。
いまの到達点
- ① RF入力(rtl_sdr の生IQ → 複素サンプル)… 済
- ② OFDM同期(CP自己相関+周期性GI判定)… 実電波でロック確認
- ③ チャネル等化(スキャッタードパイロット)… 次回
- ④ デマップ+デインターリーブ(要TMCC)/⑤ FEC /⑥ TS … この先
教訓:「ロックした」と「正しくロックした」は別物。ピークが立っても、それが周期的に繰り返しているかまで見ないと、もっともらしい嘘に足をすくわれる。合成信号でのテスト+実電波での周期性チェック、この二段構えがあって初めて信用できる。
次回 #2 は、ロックした symbol_start から1シンボルぶんFFTして、コンスタレーションを描く。点がちゃんと固まって見えたら、③チャネル等化の入口だ。

コメントを残す