ADSP-2191に実装したSSB複素変復調を、Blackfinにも実装してみました。実行環境はTOPPERS/JSPで、AD1836A用のTalkthroughをもとに信号処理系のみ使っています。なお、STKも使用しています。
処理の方式は2191版とまったく同じで、PSNを複素フィルタで実装したものです。キャリア周波数は12KHzで、サンプル周波数はオーディオと同じ48KHzです。
必要MIPSはADSP-BF533 Rev 0.2用のビルドで73MIPS、Rev 0.4用のビルドで48MIPSです( VisualDSP++ 4.0 September Update )。
ダウロード(616KB) : ssb_complex.zip
#include "t_services.h" #include "kernel_id.h" #include "complex_ssb.h" #include "ad1836a.h" #include "stk.h" #define TAPS 256 static short sound[SAMPLE_PER_INTR], signal[SAMPLE_PER_INTR], sp[SAMPLE_PER_INTR]; static short temp_r[SAMPLE_PER_INTR], temp_i[SAMPLE_PER_INTR]; static short temp2_r[SAMPLE_PER_INTR], temp2_i[SAMPLE_PER_INTR]; static short lo_r[SAMPLE_PER_INTR], lo_i[SAMPLE_PER_INTR]; static short re_coeff[TAPS]={ #include "relpf.txt" }; static short im_coeff[TAPS]={ #include "imlpf.txt" }; static struct CODEC_BUFFER tx_buf; void modem_task(VP_INT extinf) { struct CODEC_BUFFER * rx_buf; // 変調器の複素フィルタ stk::CFilter * mod_re_fir = new stk::CFirFilter( re_coeff, TAPS ); stk::CFilter * mod_im_fir = new stk::CFirFilter( im_coeff, TAPS ); // 復調器の複素フィルタ stk::CFilter * demod_re_fir = new stk::CFirFilter( re_coeff, TAPS ); stk::CFilter * demod_im_fir = new stk::CFirFilter( im_coeff, TAPS ); // 12KHzの局発 stk::CDDS * lo = new stk::CDDS( 0x40000000 ); // 48KHz/4 = 12KHz // 11KHzの妨害波 stk::CDDS * spurious = new stk::CDDS( 984263339 ); // 2^32 / 48 * 11 = 11 KHz act_tsk( CODEC_TASK ); while( 1 ) { int sample, slot; rcv_dtq( CODEC_RX_DTQ, (VP_INT*)& rx_buf ); // 入力データからLとRを取り出して加算する。 // SLOT 0 : Internal L // SLOT 4 : Internal R // 24 bit データを加算後, 16bitに // 丸めるために9bitシフトする for ( sample = 0; sample < SAMPLE_PER_INTR; sample++ ) sound[sample] = ( rx_buf->data[sample][0] + rx_buf->data[sample][4] ) >> 17; // sound にはモノラルデータが入っている。 // ---------- USB 変調 ------------- // 複素フィルタを適用 mod_re_fir->run( temp_r, sound, SAMPLE_PER_INTR ); mod_im_fir->run( temp_i, sound, SAMPLE_PER_INTR ); // 複素局発(解析信号)を生成 lo->run( lo_r, lo_i, SAMPLE_PER_INTR ); // +12KHzのアップコンバート stk::mul( temp_r, temp_r, lo_r, SAMPLE_PER_INTR ); stk::mul( temp_i, temp_i, lo_i, SAMPLE_PER_INTR ); stk::sub( signal, temp_r, temp_i, SAMPLE_PER_INTR ); // 複素局発(+12KHz 解析信号)を生成 lo->run( lo_r, lo_i, SAMPLE_PER_INTR ); // ---------- 妨害波 ------------- // 妨害信号(11KHz cos波)を生成 spurious->run( sp, SAMPLE_PER_INTR ); stk::mul( sp, sp, 0x4000, SAMPLE_PER_INTR ); // 0.5倍 // 妨害信号の混入 stk::add( signal, signal, sp, SAMPLE_PER_INTR ); // ---------- USB 復調 ------------- // -12KHzでダウンコンバート stk::mul( temp_r, lo_i, signal, SAMPLE_PER_INTR ); // -12Khzにするために stk::mul( temp_i, lo_r, signal, SAMPLE_PER_INTR ); // sin/cosを入れ替える demod_re_fir->run( temp2_r, temp_r, SAMPLE_PER_INTR ); // 実部 demod_im_fir->run( temp2_i, temp_i, SAMPLE_PER_INTR ); // 虚部 stk::sub( sound, temp2_r, temp2_i, SAMPLE_PER_INTR ); // USB復調 // stk::add( sound, temp2_r, temp2_i, SAMPLE_PER_INTR ); // LSB復調 for ( sample = 0; sample < SAMPLE_PER_INTR; sample++ ) { tx_buf.data[sample][0] = sound[sample] << 16;//rx_buf->data[sample][0]; tx_buf.data[sample][4] = sound[sample] << 16;//rx_buf->data[sample][4]; } // ---------- 出力バッファにコピー ------------- snd_dtq( CODEC_TX_DTQ, (VP_INT) & tx_buf ); } }