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 );
}
}