takanaka kouzou
/
SDR_AM_Rx_CIC_FIR
AM中波放送用SDR.CICフィルタと通常のFIRフィルタを組み合わせて使用.CQ出版社「トランジスタ技術」誌に掲載予定
main.cpp
- Committer:
- MikamiUitOpen
- Date:
- 2020-08-29
- Revision:
- 0:9c28f5905a1a
- Child:
- 1:ca43ee5ea802
File content as of revision 0:9c28f5905a1a:
//------------------------------------------------------------- // 中波 AM 放送用 SDR,CIC フィルタと通常の FIR フィルタ使用 // // 1/9 にダウンサンプリング:CIC フィルタ使用 // 1/4 にダウンサンプリング:通常の FIR フィルタ使用 // // 入力ピン: A1 // 出力ピン: A2 // // 2020/08/08, Copyright (c) 2020 MIKAMI, Naoki //------------------------------------------------------------- #include "F446_ADC_Intr.hpp" // ADC #include "F446_DAC.hpp" // DAC #include "QuadOscIir.hpp" // 直交信号発生器 #include "Cic3Stage.hpp" // 3段 CIC フィルタ #include "CoefficientsLpf.hpp" // FIR フィルタの係数 #include "FirFastSymmetry.hpp" // 係数対称 FIR フィルタ #include "Iir1st.hpp" // 一次の IIR フィルタ #include "InitialMessage.hpp" // 最初のメーッセージ using namespace Mikami; #pragma diag_suppress 870 // マルチバイト文字使用の警告抑制のため const float FS_ = 900.0f; // 標本化周波数,単位: kHz const float T0_ = 1000/FS_; // 標本化間隔,単位:μs const float A0_ = 8192; // 直交信号発生器の出力の振幅 // 各放送局の搬送波の周波数,単位: Hz const float F_C_[] = { 594.0e3f, // NHK 第1 693.0e3f, // NHK 第2 810.0e3f, // AFN Tokyo 954.0e3f, // TBS ラジオ 1134.0e3f, // 文化放送 1242.0e3f, // ニッポン放送 1422.0e3f}; // ラジオ日本 AdcF446_Intr adc_(FS_, A1); // ADC オブジェクトの宣言 DacF446 dac_; // DAC オブジェクトの宣言 Serial pc_(USBTX, USBRX); // ターミナルに対する受信割込み用 QuadOscIir nco_(F_C_[0], T0_, A0_); // NCO (numerically controlled oscillator) Iir1st averaging_(0.9998f); // 直流分を求めるためのフィルタ const int DS_RATE1_ = 9; // 1/9 にダウンサンプリング Cic3Stage cic3I_(DS_RATE1_, A0_); // CIC フィルタ,I 信号用 Cic3Stage cic3Q_(DS_RATE1_, A0_); // CIC フィルタ,Q 信号用 const int DS_RATE2_ = 4; // 1/4 にダウンサンプリング FirFastSymmetry lpfI_(ORDER_FIR_, HN_); // FIR フィルタ,I 信号用 FirFastSymmetry lpfQ_(ORDER_FIR_, HN_); // FIR フィルタ,Q 信号用 // AD 変換終了割り込みに対する割り込みサービス・ルーチン void AdcIsr() { static int count = 0; float xn = adc_.Read(); // ADC の読込み float sinX, cosX; nco_.Generate(sinX, cosX); // sin, cos 発生 // cos/sin を乗算したデータに対する CIC フィルタの積分処理 cic3I_.Integrate((int16_t)(xn*cosX)); // I 信号 cic3Q_.Integrate((int16_t)(xn*sinX)); // Q 信号 if (++count >= DS_RATE1_) { count = 0; NVIC->STIR |= EXTI3_IRQn; // ソフトウェア割り込み発生 } } // EXTI3_IRQ に対する割込みサービス・ルーチン // CIC フィルタのくし形フィルタの処理と FIR フィルタの入力の処理 void IsrCIC() { static int count = 0; float yI_n = cic3I_.CombFilter(); // くし形フィルタ float yQ_n = cic3Q_.CombFilter(); // くし形フィルタ lpfI_.Store(yI_n); // FIR フィルタのバッファへ保存,I 信号 lpfQ_.Store(yQ_n); // FIR フィルタのバッファへ保存,Q 信号 if (++count >= DS_RATE2_) { count = 0; NVIC->STIR |= EXTI4_IRQn; // ソフトウェア割り込み発生 } } // EXTI4_IRQ に対する割込みサービス・ルーチン // FIR フィルタの実行とAM復調の処理 void IsrFIR() { float yI_n = lpfI_.Execute(); // FIR フィルタによる LPF 実行 float yQ_n = lpfQ_.Execute(); // FIR フィルタによる LPF 実行 float yn = sqrtf(yI_n*yI_n + yQ_n*yQ_n); // 包絡線成分を求める float dc = averaging_.Execute(yn); // 直流分を求める yn = yn - dc; // 直流分除去 float gain = 0.8f/dc; if (gain > 200.0f) gain = 200.0f; dac_.Write(gain*yn); } // シリアル・ポートの受信割込みに対する割り込みサービス・ルーチン void RxIsr() { unsigned char chr = pc_.getc(); // 受信した文字が '0' ~ '6' の場合のみ NCO の周波数を変える if (('0' <= chr) && (chr <= '6')) { nco_.Set(F_C_[chr & 0x07]); pc_.putc(chr); // エコーバック } if (chr == '\r') pc_.printf("\r\n"); } int main() { InitialMessage("ダウンサンプリングに CIC フィルタと FIR フィルタを使用.", AM, pc_); NVIC_SetPriority(ADC_IRQn, 0); // 最優先 NVIC_SetPriority(EXTI3_IRQn, 1); // 2番目に優先 NVIC_SetPriority(USART2_IRQn, 2); // 3番目に優先 NVIC_SetPriority(EXTI4_IRQn, 3); // 4番目に優先 // ADC に対する割り込みサービス・ルーチンの設定 adc_.SetIntrVec(&AdcIsr); // EXTI3 によるソフトウェア割り込みに対応する設定 NVIC_SetVector(EXTI3_IRQn, (uint32_t)IsrCIC); NVIC_EnableIRQ(EXTI3_IRQn); // EXTI4 によるソフトウェア割り込みに対応する設定 NVIC_SetVector(EXTI4_IRQn, (uint32_t)IsrFIR); NVIC_EnableIRQ(EXTI4_IRQn); // シリアル・ポートの受信割込みの設定 pc_.format(); // default: 8 bits, nonparity, 1 stop bit pc_.attach(&RxIsr); while (true) {} }