ワンセグの仕様

日本のワンセグ放送の仕様。自分用のメモ。

  • セグメント帯域幅(Bws) = 6000/14 = 428.571..kHz
  • キャリア周波数間の間隔(Cs) = Bws/432 = 0.992…kHz
  • キャリア数 = 432 (Data 384, SP 36, TMCC 4, AC1 8の合計)
  • キャリアの変調方式: QPSK
  • 1フレームのシンボル数: 204
  • 実効シンボル長: 1008us
  • ガードインターバル: 126us (1/8)
  • シンボル長: 1134us (1/8)
  • フレーム長: 231.336ms (1/8) = 1134us * 204
  • Inner code: Convolutional code 2/3
  • Outer code: RS(204,188)

ワンセグのデータレート QPSK, Convolutional Code 2/3, Mode 3, フレーム内のTSP 64, ガードインターバル 1/8, 416.08kbps (= 64(# of TSPs) * 188 (bytes/TSP) * 8 (bits/byte) * 1/frame length)

MPEG2 TSPは、同期バイトが1 byte, データが187bytesの合計188bytes. Reed-Solomon符号16 bytesを付けて、Transmission TSP 204bytesとなる。

処理フロー (復号時には逆方向に処理)

RS Outer Code -> Energy dispersal -> Byte interleaving -> Convolutional coding -> Carrier modulation (Bit interleaving, Mapping) -> Time interleaving -> Frequency interleaving -> OFDM frame -> IFFT -> Add guard interval

Energy dispersal

TSPの同期バイト以外のデータはPRBSによって、ビットごとに排他的論理和を取る。OFDMフレーム毎にPRBSの初期値がロードされる。このとき、OFDMフレームの先頭はTSPの同期バイトの次のバイトである。 また、同期バイト期間中も(排他的論理和は取らないが)シフトは行われる。

Byte interleaving

同期バイトの次のバイトは遅延させられない(path 0)。path 0は0バイト遅延、path 1は17バイト遅延、… path 11は17*11バイト遅延。

Frequency interleaving

SP

SPはPRBSによりWiの系列を出力する。ここで、iはOFDMセグメント中のキャリア番号である。 セグメント毎にPRBS回路の初期値が定義されている。

TMCC

TMCCはDBPSKで変調される。B0はWiとする。TMCCの値0は(+4/3,0)を取り、1は(-4/3,0)を取る。

ARIB STD-B31より

FPGA FM受信機設計資料をGitHubに上げました

2年ほど前に実験していた、FPGAを使用したFM受信機の設計資料をGitHubに上げました。 SDR受信機とはどのように設計されるものなのか。実際のアナログ/デジタル回路含めて全体を理解したい、 という好奇心を満たすために始めたプロジェクトで、当初の目的はそれなりに達成できたと思います。

あまり詳しくドキュメントを書いていないので、実際に使用するのは難しいかと思いますが、 FM用のバンドパスフィルタ基板、ADC基板の回路図、ガーバー、BOMも含まれています。

ワンセグ生データをOFDM復調(4)

前回、パイロット信号が正しく取り出せないのはキャリア周波数オフセット(Carrier Frequency Offset, CFO)が原因ではないかと書きました。それ以後、 OFDM Baseband Receiver Design for Wireless Communicationsを参考に、 CFO, SCO(Sampling Clock Offset)を除去するためのPLLを実装してみたりもしましたが、どうにも思うとおりにはなりませんでした。

考え直してさらに調査した結果、DFTのデータを取り出すウィンドウが間違っていたということが判明しました。

これまでは、相関値が最大になる場所をDFTウィンドウの先頭としていましたが、 それだとCyclie Prefix(ガードインターバル)の先頭からOFDMシンボルを切り出してしまうことになります。 この領域は、信号に遅延波があるときに、他のシンボルからの干渉を避けるためのものなので、 本来DFTに使用するのは望ましくありません。

遅延波が全く無かったとしても、上記の文献の式(5.11)の通り、周波数領域の信号Zkは、送信信号Xk、チャンネル応答Hkに対して次のようになります。

“Symbol Timing Offset”

ここに、TdはDFTウィンドウがCyclic Prefixに入り込んでいる時間です。

これまでのTs=1, Td=128, N=1024で計算してみると、e^{-j2pi128k/1024}= e^{-jpi*k/4}となります。つまり、隣り合ったサブキャリアの間で-pi/4だけ位相が本来の信号からずれていくことになります。

これまでの結果を振り返ってみると、サブキャリア12本ごとにpi位相がずれている様子でした。 計算すると、-pi/4*12=-3pi=pi (modulo 2pi)ですので、ちょうどこの結果と一致します。

それで、CPの開始からDFTウィンドウを設定するのではなく、CPの終わりの少し前からDFTウィンドウを設定することで、ほぼ所望の結果が得られるようになりました。

“Symbols Before Channel Estimation”

上はチャンネル補正をする前の、生のDFT後のデータです。 これだけバラけていると、QPSKであることも疑わしい感じですね。

“SP”

SP自体は上のように、まだキャリアごとに、わずかに回転しています。このSPによって、残りのチャンネルは線形補間で推定します。推定結果でデータを補正すると、次になりました。

“Symbols After Channel Estimation”

このように、CFO, SCOのためのPLLは一切使用せずに、相関値を算出したときのガンマの値による回転と、整数倍のチャンネル周波数補正、SPによるチャンネル補正のみで、QPSKの信号がほぼ復元できました。

流石に、この程度のコンステレーションでは64QAMは無理ですが、4象限しか区別しないQPSK程度であれば、これでも十分に思われます。また、TMCC, ACに相当するI軸上の点も見つけられます。

ここまで来れば、TMCCのデコードをはじめ、ワンセグのデコード処理も規格書に則って進めれば完成まで持っていけそうな気がしてきました。

ワンセグ生データをOFDM復調(3)

前回までで、ワンセグの生データからのOFDMシンボル切り出し、パイロット信号を見つけるところまで実装しました。ところが、パイロット信号からチャンネル補正ができそうにない、というところで止まってしまいました。もう少し調査したところ、原因が分かってきました。 自分の理解の範囲でのまとめです。

OFDM Baseband Receiver Design for Wireless CommunicationsのChanter 5. Synchronizationの式(5.6)は次のようになっています。

“Z”

これは、キャリア周波数のオフセットが、FFTした結果に及ぼす影響を記述した式です。 左辺Z_{i, k}は、(時系列に並んだ)i番目のシンボルの、k番目のサブキャリアの(周波数領域の)値を示しています。また、ε_I, ε_fがそれぞれキャリア周波数オフセットの整数部、小数部です。 Hはそれぞれのサブキャリアに対応するチャンネルの周波数応答です。

ごちゃごちゃしていますが、とにかく、ε_I, ε_fが0でなければ、Z = X Hとは記述できず、他のキャリア周波数の影響を受けてしまうことを示しています。

右辺の第一項を見てみると、大きく4つの掛け算になっていますが、最後の2つのe^{…}の部分は純粋な回転です。 これまでの実装で、小数部のキャリア周波数補正はできていると思われます。 そのため、ε_fはほとんど0と考えます。

したがって、振幅だけを見るならば、受信したk番目のサブキャリアのFFT結果は、送信側のk-ε_I番目のサブキャリアの値に、チャンネル応答を掛けたものになっています(sinの項はε_f->0で1になるため)。 ですから、パイロット信号も含めてXの振幅は既知なので、振幅について積算することで、 ε_Iを求めることができたのでした。

問題は3番目のeの項による回転です。 この式を見るとε_Iが0でなければ、時間と共に盛大に回転します。 (2019/2/20追記:これ自体は正しいですが、kには依存していませんので、 Scattered Pilotがキャリアによって回転量が異なることの説明にはなりません。 それより(5.6)右辺第2項が寄与しているのかも知れません)

これの逆数を求めて回転を補正することもできるかも知れませんが、 上記の式では右辺には第2項以降も存在します。 そのため、基本的にはε_I, ε_fを0に収束させるような制御をしたほうが良さそうです。

上記の本の5.2.3節にも、周波数領域の推定アルゴリズムには限度があるので、同期エラーはその限界内に来ていることを確かめないといけない、といった記述があります。そのためには、時間領域で補正することができる、と書かれています。

時間領域での補正方法は下記の図のようになります(Figure 5.13より)。

“CFO compensation PLL”

求められたε_I, ε_fをloop filterを通してNCOに与え、その周波数でサンプリングしたデータを回転させる、というものです。 これまでの実装ではε_fのみしか考慮していませんでしたが、ε_Iも考慮する必要がある、ということです。

以上を参考にして、PLLでキャリア周波数オフセットを0に制御できるか試してみたいと思います。

ワンセグ生データをOFDM復調(2)

前回までで、ワンセグの生データからのOFDMシンボル切り出しあたりまで実装しました。今回はそれ以降の処理についてです。

前提知識

ワンセグも含めて、地上波デジタル放送は、ARIBにて規格書が配布されています。

標準規格(放送分野)一覧表のSTD-B31「地上デジタルテレビジョン放送の伝送方式」から入手可能です。私は会員でもないので、英語版を入手しています。

FFT以降の処理

前回の部分も少し修正して[11]については、次のようにしました。

“FFT”

重要なのはfftshiftを実施していることです。データ取得時のサンプリング周波数は、放送帯域の中心に設定しているので、(キャリア周波数オフセットが0であれば)fftshift後の配列中央の値が、放送帯域の中心キャリアになるはずです。

また、後でキャリア周波数の整数倍の補正をするために、周波数シフトをする必要があります。そのためのシフト量を保持するために、F_leftという変数を定義しています。シフト量が0であった場合に、FFT結果Fのうちキャリア番号0に対応する値を、初期値として設定しています。

“PRBSとTMCCの定義”

パイロット信号を検出するためにPRBSが必要になるので、その定義と、TMCC、ACという特別なパイロット信号のキャリア番号を定義しています。PRBSの最初の値がキャリア0に、次の値がキャリア1に、…というように、432本のキャリアにそれぞれ0, 1のいずれかが対応します。SP(Scattered Pilot)信号は、このキャリア周波数毎の0, 1の値がBPSKにより、IQ空間上のそれぞれ(+4/3, 0), (-4/3, 0)にマップされます。これを上記では配列Wiで定義しています。

“TMCCとAC推定”

上記は、TMCCとACの場所を推定するための関数です。G2では、引数mで指定された分だけ、キャリア周波数を移動した場所をTMCC, ACとみなして、絶対値の積算をしています。

Gs = [G2(i, Wi) for i in range(-20, 20)]

にて、キャリア周波数を-20から20まで整数倍シフトして、G2の積算値が最大になる場所を求めます。最大値が得られるインデックスでF_leftを調整しています。これでキャリア番号0から431までの場所が求まったことになるはずです。上記のプロット結果は省略します。

“SP推定”

次はSPの推定です。SP信号は12キャリアに1本あります。OFDMシンボル毎に場所が3キャリアずつ移動します。つまり、OFDMシンボル毎に、SPの場所はi12, i12+3, i12+6, i12+9, i*12,…のように巡回します。上記find_spでは、現OFDMシンボルでSPが何処に含まれているかを求めています。SPは、それ以外のデータキャリアに比べて4/3倍の絶対値を持っているので、上記のように積算した最大値を求めるという方法が使えます。

ここからがまだうまく行っていないと思われるのですが、上記では次のような出力が得られます(行が長くなりすぎるので、小数点以下は一部省略しています)。

[35.74547, 36.26827, 49.57394, 37.08745]
2
SPs:
6 1.0953 (-0.9832743533464458+0.482584084887267j) 1.3333
18 1.1773 (0.9411424714348882-0.7073685094875273j) 1.3333
30 1.2927 (0.9226357042956151-0.905485176200131j) -1.3333
42 1.3544 (-0.9451630023246448+0.9701050133998432j) -1.3333
54 1.3868 (-1.041607866189769+0.9155528236391836j) 1.3333
66 1.2944 (0.6906246945088386-1.0947704458085812j) 1.3333
78 1.0671 (0.6685409527954194-0.8316726977365281j) -1.3333
90 1.3859 (0.7967161344290873-1.1339926757265295j) 1.3333
102 1.1538 (-0.34105207413393135+1.102293053251151j) 1.3333
114 1.2401 (0.4762959068094629-1.144985106068488j) 1.3333
126 1.5607 (0.725557306133454-1.381834432391039j) -1.3333
138 1.2347 (-0.6547734652174335+1.0467712733713745j) -1.3333
150 1.3194 (-0.3329626554307+1.2767023965626096j) 1.3333
162 1.5988 (0.5091991640004263-1.5155690510396185j) 1.3333
174 1.3907 (-0.6562514301534865+1.2261640531390314j) 1.3333
186 1.6392 (-0.5092859972519473+1.5580715920605588j) -1.3333
198 1.5107 (0.26879055172568034-1.4866408415508643j) -1.3333
210 1.6382 (0.7524038499463859-1.4552230916819244j) 1.3333
222 1.3896 (0.44737449638796445-1.3156195604230028j) -1.3333
234 1.3833 (0.5356609612670982-1.2753992069341795j) 1.3333
246 1.559 (0.3497743406085074-1.5192501362727482j) -1.3333
258 1.1333 (-0.42997707286624176+1.048549775299747j) -1.3333
270 1.3702 (-0.2787479092644133+1.3415065163031206j) 1.3333
282 1.6204 (-0.5708941597565+1.5164865623719384j) -1.3333
294 1.4883 (0.6930350159378798-1.317100025661765j) -1.3333
306 1.5654 (-0.7261325631313592+1.3867477986830758j) -1.3333
318 1.5449 (0.4601928773417365-1.4747525850693373j) -1.3333
330 1.4912 (0.5746828035844906-1.3760673756943445j) 1.3333
342 1.4701 (0.825690594740095-1.2162618274644958j) -1.3333
354 1.4209 (0.24893414863314506-1.398884931842842j) 1.3333
366 1.3512 (-0.6292706725628592+1.1957269229318115j) 1.3333
378 1.4125 (-0.5413499265712505+1.3046784927444803j) -1.3333
390 1.4662 (0.7501030028129436-1.2598034492601253j) -1.3333
402 1.1753 (-0.7940964094918974+0.8664208985515854j) -1.3333
414 1.3589 (-0.7997872953740967+1.098570575241878j) 1.3333
426 1.0329 (-0.3727620060886928+0.96334271774669j) -1.3333

最初の行と次の行は、SPの場所と絶対値の積算値を表示しています。49は残りの3つの値36付近に比べると、ほぼ4/3倍となっているので、結果は正しそうに思われます。

ただ、それ以降、SPのキャリア番号と絶対値、その値、また、期待される値を各行表示していますが、 これがおかしいと思われます。例えば、キャリア番号6は、値が第2象限である一方、期待される値は(4/3, 0)です。次に、キャリア番号18では、値が第4象限である一方、こちらも期待される値は(4/3, 0)です。つまり、この結果が正しいのであれば、キャリア番号6と18とで、チャンネルの影響で回転した方向が逆になってしまっています。

しかも、よく観察すると、この結果は、キャリア番号6+24nと18+24nとでいつも成り立っているようです。つまり、回転方向がこれら2つの間でいつも逆です。

さらに、上記SPを実際にプロットした結果が次です。

“SP表示”

この表示自体は、実数軸上にあるSPがどちらかに回転したと考えれば、それなりの結果に見えます。 ただ、上記の通り、回転方向がいつも逆になっているので、恐らくどこかに間違いがあるはずです。 現在のところここで躓いています。これだと、単純に残りのキャリアの推定を線形補間で行うと、絶対値が0近辺の値が出てきてしまうことになり、正しく補正できません。チャンネル推定をして補正を行う前に、上記の問題を解決する必要があります。

1/8 »