SSB変調器(2)

前回のSSB変調器(1)では中心周波数が12KHzでした。これではあまりにつまらないので455KHzのSSBを生成するプログラムを組んでみました。例によってMCMを使って音声を入力し、副搬送波をかけてLPFを通した後に32倍のインターポレーションを行います。

実装

以下にhandleBuffer()を示します。入力音声帯域は24KHzですがLPFで絞ることはせず、第一MIX後のLPFで不要帯域といっしょに切り落としています。このような処理をするとナイキスト周波数付近で折り返し雑音が発生しますが、どうせLPFで切り落とすのですから問題ありません。

ブロックダイアグラム

図1 ブロックダイアグラム

void CModulator::handleBuffer( struct mcm::sample * bufTx, 
                               struct mcm::sample * bufRx )
{
        short step;
        
        step = sizeof(mcm::sample);
                                
                        // make stereo to monoral
        stk::copy( in, &bufRx[0].r, bufSize, 1, step );
        
        osc1->run( lo_i, lo_q, bufSize );               // 副搬送波生成
        stk::mul( temp_i, in, lo_i, bufSize );          // 第一MIX
        stk::mul( temp_q, in, lo_q, bufSize );

        lpf_i->run( temp_i, temp_i, bufSize );          // 高域カット
        lpf_q->run( temp_q, temp_q, bufSize );

        up8_i->run( temp_ia, temp_i, bufSize );         // 8倍インターポレーション 
        up8_q->run( temp_qa, temp_q, bufSize );         // カットオフ=0.06

        up4_i->run( temp_i, temp_ia, bufSize*8 );       // 4倍インターポレーション 
        up4_q->run( temp_q, temp_qa, bufSize*8 );       // カットオフ=0.06
        
        osc2->run( lo_i, lo_q, bufSize*32 );            // 搬送波生成 
        stk::mul( temp_i, temp_i, lo_i, bufSize*32 );   // 第二MIX
        stk::mul( temp_q, temp_q, lo_q, bufSize*32 );
        
        stk::add( temp_i, temp_i, temp_q, bufSize*32);

}

実際に走らせて驚いたのは計算量の大きさです。30%ほどあるかと思っていたアイドル時間はわずか5%で、偶然とは思えないほどぎりぎりの余裕で動いていました。

もっとも演算量が大きいのはアップサンプル部で35%以上を消費しています。この部分はアセンブリ言語による最適化コードですが、改めてコードを見直したところ面白いことがわかりました。この部分はポリフェーズ フィルタを使用することで実際のタップ数の1/L(Lはアップサンプル比)の畳み込みで済ませています。ところが見かけのタップ数が1/Lになるために相対的なオーバーヘッドが無視できなくなっています。ざっと見たところでは最内側ループは64タップ、L=4のときに8サイクルを消費しますが、その外のループが7サイクル程消費しているため、全体の計算量は2倍近くになっています。この部分はループの構成を少しいじって性能を向上させることができそうです。ただしメモリー消費量が増えます。

次に演算量が大きいのは搬送波の生成を行っている部分です。ここはサンプル周波数1.5MHzで動作しており、繰り返しあたり20サイクルも消費していることから1秒あたり30Mサイクルを食いつぶしています。およそ全体の20%です。

また、高域カット用のFIRフィルタも次数が高いため15%程度消費しています。その他乗算器の7%、加算器の3.5%なども目に付きます。

以上の演算量評価に基づく最適化は、455KHzで動作させるのであれば不要です。なにしろきちんと動いているのですからこれ以上最適化する必要はありません。あくまで検討です。

実際にこのプログラムでDACを駆動して455KHzを出力して特性を図ってみたいものです。その場合は改めて高域カット用LPFを見直す必要があるでしょう。USBによる接続が遅い上にVisualDSP++のFFT画面があまりよくないので帯域外阻止特性はそれほど見ていません。電波を出すのならここは十分に抑えるべきです。評価の結果、現在のフィルタで不十分なようならより急峻な特性が必要ですが、その場合は音声サンプリングを48KHzから12KHzに落とすといいでしょう。これはAC97コーデックにコマンドを送ればすみます。もちろん後段に4倍のアップサンプラが必要です。

最後に、ソフトウェアをダウンロードできるようにしておきます。

ssb2.zip : 36KB

補足

この件を勉強するにあたって、随分WEB上のアマチュア無線士のページを漁りました。日本では70年代に実験された方が多くいらっしゃるようです。あちこちにCQ出版社の「SSBハンドブック」にWeaver方式が紹介されていたとの証言があります。私も持っていた本ですが、回路図が紹介されていた程度じゃないかと思います。多くの方が記述が少なかったと書いていらっしゃいます。

このプログラムに挑戦する直接のきっかけは、Weaver式イメージ抑圧受信機に関する情報を探すうち、IV3NWVによるA 9MHz Digital SSB Modulatorに行き当たったことです。FPGAを使った実装で、原理説明もあります。この技術を使った送信機、Digimit 2002も紹介されています。

このプログラムを書くときには「どうやら日本でディジタル実装した例はなさそうだ、しめしめ」とほくそえんでいたのですが、実は直前に浦和アマチュア無線クラブにJA1VCWによる投稿がなされていたのでした。どうやら投稿されていたのがそのままアップロードされずにいたようです。慌ててアップロードするにいたった経緯を想像するのはなかなか楽しかったです。

この方式のDSPによる実用化ですが、600MHzのBlackfinを持ってしてもこのままでは7MHzを出せるかどうか怪しい限りです。手を惜しまなければDDSによるオーバーヘッドは大幅に削減できます。しかしながら、最終的にはインターポレーターの演算量がすべての上限を決めます。インターポレーターの実装は苦しい限りで、酔狂さにこだわらなければおとなしくハードウェアに追い出すのが合理的でしょう。

2003年9月28日

後日、ハイフェッツさんから掲示板で教えていただいた複素フィルタの考え方を用いると、IV3NWVの説明のほうが明快であることがわかりました。奥が深い。

2003年9月30日

IV3NWVの説明に対する言及が明らかに間違っていたため削除しました。

次は⇒包絡線復調器

2191空挺団 | プログラム | EZ-KIT | こぼれ話 | アーキテクチャー | 命令 | レジスタ | DSP掲示板 | FAQ |