[はじめてのSoftware Defined Radio:アナログテレビ放送を送信する | kuriuzublog](https://kuriuzublog.wordpress.com/2017/10/14/sdr-ntsc-tv/)
PCでNTSCをRFに変調して、FPGAに転送し、DACでアナログ化。FPGAとDACは任意波形発生機として使っていて、NTSCとかの処理はPCで完結。
ソースコードちゃんと読んでないけど、ざっと眺めた感じだとフィールドIからIVの内、一つしか作ってないんじゃないかなぁ。
処理が遅いのもBitmap.GetPixelの影響と思われ。2.5Gspsというと膨大なデータ量を想像しがちだけど、1フレーム分なら40Mポイントちょっとだから、それくらいのデータ量ならC#ならサクッと作れそうな気がする。
まぁ、ソフトウェアを高速化したところで、LANで転送してるのがボトルネックっぽいので、あんまり早くならないか。それでも転送に4分前後は時間かかり過ぎじゃないか、という気がする。UARTじゃないんだからもっと速度出ても良さそう。
そーいえば、osqzssの人がVGAアダプタでRFを出してたけど、150Msps弱で出せるらしい。もうちょっと高いところまで出せたら直接VHFのAM変調でNTSCを飛ばせそう。
しかし、VGA端子ってXGAでもピクセルクロック65MHzとかになるので、150Mspsってちょっと低くないか?
ワンセグチューナーしかり、VGAアダプタしかり、「専用LSI設計するのメンドクセ。汎用IC組み合わせて信号処理でゴリゴリやって成立させて安く作って儲けようぜ!」みたいな人が作ってるんだろうなぁ。いいぞもっとやれ。
***
サンプリングした生データをハフマン符号化しようと試行錯誤中。
前ポイントとの差を符号化するために、差のスペクトルをグラフ化してみた。

一番短い符号で3bit、長いやつで28bit。ウギャー。
それでも、圧縮率0.65くらいは行けるので、1フィールド150kポイントを溜め込むなら、98kくらいのバッファがあれば足りる。98kポイントならギリギリ確保できる。
ただ、このスペクトルはテスト画像に最適化されたもののはずだから、実際にはもっと特性が悪化するはず。Xbox360のホーム画面って比較的低周波な感じだから、ゴリゴリのカラー画像とかだともっと高周波成分が増えるはず。
十分なメモリがあれば、一旦データを読み込んで、最初から最後までカウントした後にツリーを作って、みたいな手順が踏めるし、そもそもハフマン符号ってそうやって使うものなんだけど、メモリが足りないから圧縮しようという話になっているわけで。
なんとなく名前聞いたことがあるという理由でハフマン符号を選択してるけど、別の圧縮方法も考えたほうがいいかもなぁ。
今の所PCで処理してるのでシーケンシャルにやってるけど、STM32F4ならSIMDが使えるから、4バイト1単位で処理したほうが早くできそう。少なくとも差分の計算は4倍早くなる。16サイクル/バイト未満で処理しなきゃいけないので、1命令でも小さく処理できる方が良い。
ただ、そうすると波形の連続性が失われるので、差のスペクトルが広がる傾向になる。圧縮率も若干下がる。
まぁ、実際に試してみないことには、という感じなので、もう少しPC側で動かしてみて、ちゃんと動くようになってきたらマイコン側で圧縮処理をやってみよう。
***
追記
PC/gccでハフマンのプログラムを試作中。エンコード/デコードを通して元データが復元できるので、一応動いているはず。途中のビット列もなんとなくそれっぽくなってるし。
今回、出現回数が低いデータは、ハフマン符号でフラグを立てて、直後にデータ自体を直接書き込む、という方法を使っている。これを行わない場合はワーストで1バイトあたり25bitが必要になるが、フラグ+生データでは17bitと、若干少データ化できる。
ただ、そのためのコードが結構面倒なので、低頻度で発生する大容量のデータは許容して、1つでもifを減らす、という方向に行くべきかもしれない。
ハフマン木を保持するROMは、今の所十分に空きがあるし、ROMをケチってサイクル数を増やすような事は、少なくとも今回はやりたくない。ROMにテーブル埋め込んで高速化できるなら喜んで容量を確保する。とはいえ、さすがに2^32x2^32のテーブルなんて持つのは不可能だから、全部をROMに入れることはできない。もっとも、256x256のテーブルくらいなら持てるだろうから、SIMDでの高速化と、テーブルアクセスと、どっちが早いかは比較する必要がある。
今の所forとかifとかでゴリゴリやってるので、かなり冗長なコードになってる。どこまで命令数減らせるかなぁ。。。
32bitデータとビット長を与えたらバッファにどんどん詰め込んでいってくれるアクセラレータ、とか欲しい。
***
追記
深夜のテンションで考えてたけど、よくよく考えたら、256x256のテーブルって65536だし、1データあたり8バイトだから、それだけで512KiBになるんだな。ROMは1MiBあるから足りるとはいえ、DFU転送とか考えると実用的じゃない。
符号32bit+符号長8bitで64bit/符号だけど、符号を27bit未満にすれば、27bit+5bit=32bitで扱える。ただし32bitをマスクして分離する必要があるので処理速度が大幅に悪化するはず。
あるいは、符号のテーブルと符号長のテーブルを分ける、という手段もある。キャッシュメモリを積んでるわけじゃないのでデータが分散してても問題ないし(そもそもテーブルアクセスしてる時点でキャッシュヒットなんてはなから期待できないが)。
ところで、「あるデータの符号を(任意ビット長の)0に固定する」って、どうやってやればいいんだろうか。
今の所、データ終端は専用の符号で識別しているけど、連続した0を終端符号に割り当てることができれば、明示的に終端を示さなくても、ゼロクリアしたバッファを使うだけで自動的に終端してくれる。
なんとなく「こうすればいいんじゃないか」というのは見えてるけど、うまく再現できない。ツリー生成の実装の問題かも。あるいは、そもそも根本的に考え方を間違えているか。
0 件のコメント:
コメントを投稿