不韋 呂
/
SDR_FM_Rx_CIC
AM中波放送用SDR.CICフィルタのみを使用.CQ出版社「トランジスタ技術」誌,2021年5月号に掲載
main.cpp
- Committer:
- MikamiUitOpen
- Date:
- 2021-02-04
- Revision:
- 1:2b596eab04de
- Parent:
- 0:4037028ba61a
- Child:
- 2:fa94a6a917dd
File content as of revision 1:2b596eab04de:
//------------------------------------------------------------- // FM 用 SDR // 入力信号:SDR_FM_Tx で発生した信号 // 入力ピン: A1 // 出力ピン: A2 // ダウンサンプリングで CIC フィルタを使用 // // Tera Term から選局可能,0 と 1 // // 2021/02/04, Copyright (c) 2021 MIKAMI, Naoki //------------------------------------------------------------- #include "F446_ADC_Intr.hpp" #include "F446_DAC.hpp" #include "QuadOscIir.hpp" #include "Cic3Stage.hpp" #include "FastATan.hpp" #include "IirDcCut.hpp" #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; // 直交信号発生器の出力の振幅 const float F_C_[] = { 70.0e3f, 130.0e3f}; // 搬送波周波数 AdcF446_Intr adc_(FS_, A1); DacF446 dac_; Serial pc_(USBTX, USBRX); // ターミナルに対する受信割込み用 // 直流分除去用フィルタ // 高域通過フィルタ // バタワース特性 // 次数 : 1 次 // 標本化周波数: 36.00 kHz // 遮断周波数 : 0.05 kHz IirDcCut dcCut_(9.913112E-01f, 9.956556E-01f); // 入力の直流成分除去用フィルタ QuadOscIir nco_(F_C_[0], T0_, A0_); // NCO (numerically controlled oscillator) const int DS_RATE_ = 25; // 1/25 にダウンサンプリング Cic3Stage cic3I_(DS_RATE_, A0_); Cic3Stage cic3Q_(DS_RATE_, A0_); // AD 変換終了割り込みに対する割り込みサービス・ルーチン void AdcIsr() { static int count = 0; float xn = adc_.Read(); // ADC の読込み float sinX, cosX; nco_.Generate(sinX, cosX); // sin, cos 発生 cic3I_.Integrate((int16_t)(xn*cosX)); // I 信号 cic3Q_.Integrate((int16_t)(xn*sinX)); // Q 信号 if (++count >= DS_RATE_) { count = 0; NVIC->STIR |= EXTI4_IRQn; // ソフトウェア割り込み発生 } } // ダウンサンプラより後の処理に対する割り込みサービス・ルーチン void SwiIsr() { static const float PI = 3.141592654; static const float PI2 = 2.0f*PI; static float phi_nM1 = 0; // 一つ前の位相の値 float yI_n = cic3I_.CombFilter(); // くし形フィルタ処理で I 信号を生成 float yQ_n = cic3Q_.CombFilter(); // くし形フィルタ処理で Q 信号を生成 float phi_n = FastATan(yQ_n, yI_n); // 位相成分を求める float dif = phi_n - phi_nM1; // 位相の差分 if (dif > PI) dif -= PI2; // 差分処理の補正 if (dif < -PI) dif += PI2; // 差分処理の補正 float yn = dcCut_.Execute(dif); // 直流分除去 dac_.Write(yn); phi_nM1 = phi_n; } // シリアル・ポートの受信割込みに対する処理 void RxIsr() { unsigned char chr = pc_.getc(); // 受信した文字が '0', '1' の場合のみ NCO の周波数を変える if (('0' <= chr) && (chr <= '1')) { nco_.Set(F_C_[chr & 0x01]); pc_.putc(chr); // エコーバック } if (chr == '\r') pc_.printf("\r\n"); } int main() { InitialMessage("ダウンサンプリングに CIC フィルタ使用.", FM, pc_); NVIC_SetPriority(ADC_IRQn, 0); // 最優先 NVIC_SetPriority(EXTI4_IRQn, 1); // 2番目に優先 NVIC_SetPriority(USART2_IRQn, 2); // 3番目に優先 adc_.SetIntrVec(&AdcIsr); // ADC の割り込みサービス・ルーチンの設定 // EXTI4 によるソフトウェア割り込みに対応する設定 NVIC_SetVector(EXTI4_IRQn, (uint32_t)SwiIsr); NVIC_EnableIRQ(EXTI4_IRQn); // シリアル・ポートの受信割込みの設定 pc_.format(); // default: 8 bits, nonparity, 1 stop bit pc_.attach(&RxIsr); while (true) {} }