AM中波放送用SDR.CICフィルタと通常のFIRフィルタを組み合わせて使用.CQ出版社「トランジスタ技術」誌に掲載予定

Dependencies:   mbed

Committer:
MikamiUitOpen
Date:
Sat Aug 29 11:25:01 2020 +0000
Revision:
0:9c28f5905a1a
Child:
1:ca43ee5ea802
1

Who changed what in which revision?

UserRevisionLine numberNew contents of line
MikamiUitOpen 0:9c28f5905a1a 1 //-------------------------------------------------------------
MikamiUitOpen 0:9c28f5905a1a 2 // 中波 AM 放送用 SDR,CIC フィルタと通常の FIR フィルタ使用
MikamiUitOpen 0:9c28f5905a1a 3 //
MikamiUitOpen 0:9c28f5905a1a 4 // 1/9 にダウンサンプリング:CIC フィルタ使用
MikamiUitOpen 0:9c28f5905a1a 5 // 1/4 にダウンサンプリング:通常の FIR フィルタ使用
MikamiUitOpen 0:9c28f5905a1a 6 //
MikamiUitOpen 0:9c28f5905a1a 7 // 入力ピン: A1
MikamiUitOpen 0:9c28f5905a1a 8 // 出力ピン: A2
MikamiUitOpen 0:9c28f5905a1a 9 //
MikamiUitOpen 0:9c28f5905a1a 10 // 2020/08/08, Copyright (c) 2020 MIKAMI, Naoki
MikamiUitOpen 0:9c28f5905a1a 11 //-------------------------------------------------------------
MikamiUitOpen 0:9c28f5905a1a 12
MikamiUitOpen 0:9c28f5905a1a 13 #include "F446_ADC_Intr.hpp" // ADC
MikamiUitOpen 0:9c28f5905a1a 14 #include "F446_DAC.hpp" // DAC
MikamiUitOpen 0:9c28f5905a1a 15 #include "QuadOscIir.hpp" // 直交信号発生器
MikamiUitOpen 0:9c28f5905a1a 16 #include "Cic3Stage.hpp" // 3段 CIC フィルタ
MikamiUitOpen 0:9c28f5905a1a 17 #include "CoefficientsLpf.hpp" // FIR フィルタの係数
MikamiUitOpen 0:9c28f5905a1a 18 #include "FirFastSymmetry.hpp" // 係数対称 FIR フィルタ
MikamiUitOpen 0:9c28f5905a1a 19 #include "Iir1st.hpp" // 一次の IIR フィルタ
MikamiUitOpen 0:9c28f5905a1a 20 #include "InitialMessage.hpp" // 最初のメーッセージ
MikamiUitOpen 0:9c28f5905a1a 21 using namespace Mikami;
MikamiUitOpen 0:9c28f5905a1a 22 #pragma diag_suppress 870 // マルチバイト文字使用の警告抑制のため
MikamiUitOpen 0:9c28f5905a1a 23
MikamiUitOpen 0:9c28f5905a1a 24 const float FS_ = 900.0f; // 標本化周波数,単位: kHz
MikamiUitOpen 0:9c28f5905a1a 25 const float T0_ = 1000/FS_; // 標本化間隔,単位:μs
MikamiUitOpen 0:9c28f5905a1a 26 const float A0_ = 8192; // 直交信号発生器の出力の振幅
MikamiUitOpen 0:9c28f5905a1a 27
MikamiUitOpen 0:9c28f5905a1a 28 // 各放送局の搬送波の周波数,単位: Hz
MikamiUitOpen 0:9c28f5905a1a 29 const float F_C_[] = { 594.0e3f, // NHK 第1
MikamiUitOpen 0:9c28f5905a1a 30 693.0e3f, // NHK 第2
MikamiUitOpen 0:9c28f5905a1a 31 810.0e3f, // AFN Tokyo
MikamiUitOpen 0:9c28f5905a1a 32 954.0e3f, // TBS ラジオ
MikamiUitOpen 0:9c28f5905a1a 33 1134.0e3f, // 文化放送
MikamiUitOpen 0:9c28f5905a1a 34 1242.0e3f, // ニッポン放送
MikamiUitOpen 0:9c28f5905a1a 35 1422.0e3f}; // ラジオ日本
MikamiUitOpen 0:9c28f5905a1a 36
MikamiUitOpen 0:9c28f5905a1a 37 AdcF446_Intr adc_(FS_, A1); // ADC オブジェクトの宣言
MikamiUitOpen 0:9c28f5905a1a 38 DacF446 dac_; // DAC オブジェクトの宣言
MikamiUitOpen 0:9c28f5905a1a 39 Serial pc_(USBTX, USBRX); // ターミナルに対する受信割込み用
MikamiUitOpen 0:9c28f5905a1a 40
MikamiUitOpen 0:9c28f5905a1a 41 QuadOscIir nco_(F_C_[0], T0_, A0_); // NCO (numerically controlled oscillator)
MikamiUitOpen 0:9c28f5905a1a 42
MikamiUitOpen 0:9c28f5905a1a 43 Iir1st averaging_(0.9998f); // 直流分を求めるためのフィルタ
MikamiUitOpen 0:9c28f5905a1a 44
MikamiUitOpen 0:9c28f5905a1a 45 const int DS_RATE1_ = 9; // 1/9 にダウンサンプリング
MikamiUitOpen 0:9c28f5905a1a 46 Cic3Stage cic3I_(DS_RATE1_, A0_); // CIC フィルタ,I 信号用
MikamiUitOpen 0:9c28f5905a1a 47 Cic3Stage cic3Q_(DS_RATE1_, A0_); // CIC フィルタ,Q 信号用
MikamiUitOpen 0:9c28f5905a1a 48
MikamiUitOpen 0:9c28f5905a1a 49 const int DS_RATE2_ = 4; // 1/4 にダウンサンプリング
MikamiUitOpen 0:9c28f5905a1a 50 FirFastSymmetry lpfI_(ORDER_FIR_, HN_); // FIR フィルタ,I 信号用
MikamiUitOpen 0:9c28f5905a1a 51 FirFastSymmetry lpfQ_(ORDER_FIR_, HN_); // FIR フィルタ,Q 信号用
MikamiUitOpen 0:9c28f5905a1a 52
MikamiUitOpen 0:9c28f5905a1a 53 // AD 変換終了割り込みに対する割り込みサービス・ルーチン
MikamiUitOpen 0:9c28f5905a1a 54 void AdcIsr()
MikamiUitOpen 0:9c28f5905a1a 55 {
MikamiUitOpen 0:9c28f5905a1a 56 static int count = 0;
MikamiUitOpen 0:9c28f5905a1a 57
MikamiUitOpen 0:9c28f5905a1a 58 float xn = adc_.Read(); // ADC の読込み
MikamiUitOpen 0:9c28f5905a1a 59 float sinX, cosX;
MikamiUitOpen 0:9c28f5905a1a 60 nco_.Generate(sinX, cosX); // sin, cos 発生
MikamiUitOpen 0:9c28f5905a1a 61
MikamiUitOpen 0:9c28f5905a1a 62 // cos/sin を乗算したデータに対する CIC フィルタの積分処理
MikamiUitOpen 0:9c28f5905a1a 63 cic3I_.Integrate((int16_t)(xn*cosX)); // I 信号
MikamiUitOpen 0:9c28f5905a1a 64 cic3Q_.Integrate((int16_t)(xn*sinX)); // Q 信号
MikamiUitOpen 0:9c28f5905a1a 65
MikamiUitOpen 0:9c28f5905a1a 66 if (++count >= DS_RATE1_)
MikamiUitOpen 0:9c28f5905a1a 67 {
MikamiUitOpen 0:9c28f5905a1a 68 count = 0;
MikamiUitOpen 0:9c28f5905a1a 69 NVIC->STIR |= EXTI3_IRQn; // ソフトウェア割り込み発生
MikamiUitOpen 0:9c28f5905a1a 70 }
MikamiUitOpen 0:9c28f5905a1a 71 }
MikamiUitOpen 0:9c28f5905a1a 72
MikamiUitOpen 0:9c28f5905a1a 73 // EXTI3_IRQ に対する割込みサービス・ルーチン
MikamiUitOpen 0:9c28f5905a1a 74 // CIC フィルタのくし形フィルタの処理と FIR フィルタの入力の処理
MikamiUitOpen 0:9c28f5905a1a 75 void IsrCIC()
MikamiUitOpen 0:9c28f5905a1a 76 {
MikamiUitOpen 0:9c28f5905a1a 77 static int count = 0;
MikamiUitOpen 0:9c28f5905a1a 78
MikamiUitOpen 0:9c28f5905a1a 79 float yI_n = cic3I_.CombFilter(); // くし形フィルタ
MikamiUitOpen 0:9c28f5905a1a 80 float yQ_n = cic3Q_.CombFilter(); // くし形フィルタ
MikamiUitOpen 0:9c28f5905a1a 81
MikamiUitOpen 0:9c28f5905a1a 82 lpfI_.Store(yI_n); // FIR フィルタのバッファへ保存,I 信号
MikamiUitOpen 0:9c28f5905a1a 83 lpfQ_.Store(yQ_n); // FIR フィルタのバッファへ保存,Q 信号
MikamiUitOpen 0:9c28f5905a1a 84
MikamiUitOpen 0:9c28f5905a1a 85 if (++count >= DS_RATE2_)
MikamiUitOpen 0:9c28f5905a1a 86 {
MikamiUitOpen 0:9c28f5905a1a 87 count = 0;
MikamiUitOpen 0:9c28f5905a1a 88 NVIC->STIR |= EXTI4_IRQn; // ソフトウェア割り込み発生
MikamiUitOpen 0:9c28f5905a1a 89 }
MikamiUitOpen 0:9c28f5905a1a 90 }
MikamiUitOpen 0:9c28f5905a1a 91
MikamiUitOpen 0:9c28f5905a1a 92 // EXTI4_IRQ に対する割込みサービス・ルーチン
MikamiUitOpen 0:9c28f5905a1a 93 // FIR フィルタの実行とAM復調の処理
MikamiUitOpen 0:9c28f5905a1a 94 void IsrFIR()
MikamiUitOpen 0:9c28f5905a1a 95 {
MikamiUitOpen 0:9c28f5905a1a 96 float yI_n = lpfI_.Execute(); // FIR フィルタによる LPF 実行
MikamiUitOpen 0:9c28f5905a1a 97 float yQ_n = lpfQ_.Execute(); // FIR フィルタによる LPF 実行
MikamiUitOpen 0:9c28f5905a1a 98
MikamiUitOpen 0:9c28f5905a1a 99 float yn = sqrtf(yI_n*yI_n + yQ_n*yQ_n); // 包絡線成分を求める
MikamiUitOpen 0:9c28f5905a1a 100 float dc = averaging_.Execute(yn); // 直流分を求める
MikamiUitOpen 0:9c28f5905a1a 101 yn = yn - dc; // 直流分除去
MikamiUitOpen 0:9c28f5905a1a 102
MikamiUitOpen 0:9c28f5905a1a 103 float gain = 0.8f/dc;
MikamiUitOpen 0:9c28f5905a1a 104 if (gain > 200.0f) gain = 200.0f;
MikamiUitOpen 0:9c28f5905a1a 105 dac_.Write(gain*yn);
MikamiUitOpen 0:9c28f5905a1a 106 }
MikamiUitOpen 0:9c28f5905a1a 107
MikamiUitOpen 0:9c28f5905a1a 108 // シリアル・ポートの受信割込みに対する割り込みサービス・ルーチン
MikamiUitOpen 0:9c28f5905a1a 109 void RxIsr()
MikamiUitOpen 0:9c28f5905a1a 110 {
MikamiUitOpen 0:9c28f5905a1a 111 unsigned char chr = pc_.getc();
MikamiUitOpen 0:9c28f5905a1a 112 // 受信した文字が '0' ~ '6' の場合のみ NCO の周波数を変える
MikamiUitOpen 0:9c28f5905a1a 113 if (('0' <= chr) && (chr <= '6'))
MikamiUitOpen 0:9c28f5905a1a 114 {
MikamiUitOpen 0:9c28f5905a1a 115 nco_.Set(F_C_[chr & 0x07]);
MikamiUitOpen 0:9c28f5905a1a 116 pc_.putc(chr); // エコーバック
MikamiUitOpen 0:9c28f5905a1a 117 }
MikamiUitOpen 0:9c28f5905a1a 118 if (chr == '\r') pc_.printf("\r\n");
MikamiUitOpen 0:9c28f5905a1a 119 }
MikamiUitOpen 0:9c28f5905a1a 120
MikamiUitOpen 0:9c28f5905a1a 121 int main()
MikamiUitOpen 0:9c28f5905a1a 122 {
MikamiUitOpen 0:9c28f5905a1a 123 InitialMessage("ダウンサンプリングに CIC フィルタと FIR フィルタを使用.", AM, pc_);
MikamiUitOpen 0:9c28f5905a1a 124
MikamiUitOpen 0:9c28f5905a1a 125 NVIC_SetPriority(ADC_IRQn, 0); // 最優先
MikamiUitOpen 0:9c28f5905a1a 126 NVIC_SetPriority(EXTI3_IRQn, 1); // 2番目に優先
MikamiUitOpen 0:9c28f5905a1a 127 NVIC_SetPriority(USART2_IRQn, 2); // 3番目に優先
MikamiUitOpen 0:9c28f5905a1a 128 NVIC_SetPriority(EXTI4_IRQn, 3); // 4番目に優先
MikamiUitOpen 0:9c28f5905a1a 129
MikamiUitOpen 0:9c28f5905a1a 130 // ADC に対する割り込みサービス・ルーチンの設定
MikamiUitOpen 0:9c28f5905a1a 131 adc_.SetIntrVec(&AdcIsr);
MikamiUitOpen 0:9c28f5905a1a 132
MikamiUitOpen 0:9c28f5905a1a 133 // EXTI3 によるソフトウェア割り込みに対応する設定
MikamiUitOpen 0:9c28f5905a1a 134 NVIC_SetVector(EXTI3_IRQn, (uint32_t)IsrCIC);
MikamiUitOpen 0:9c28f5905a1a 135 NVIC_EnableIRQ(EXTI3_IRQn);
MikamiUitOpen 0:9c28f5905a1a 136
MikamiUitOpen 0:9c28f5905a1a 137 // EXTI4 によるソフトウェア割り込みに対応する設定
MikamiUitOpen 0:9c28f5905a1a 138 NVIC_SetVector(EXTI4_IRQn, (uint32_t)IsrFIR);
MikamiUitOpen 0:9c28f5905a1a 139 NVIC_EnableIRQ(EXTI4_IRQn);
MikamiUitOpen 0:9c28f5905a1a 140
MikamiUitOpen 0:9c28f5905a1a 141 // シリアル・ポートの受信割込みの設定
MikamiUitOpen 0:9c28f5905a1a 142 pc_.format(); // default: 8 bits, nonparity, 1 stop bit
MikamiUitOpen 0:9c28f5905a1a 143 pc_.attach(&RxIsr);
MikamiUitOpen 0:9c28f5905a1a 144
MikamiUitOpen 0:9c28f5905a1a 145 while (true) {}
MikamiUitOpen 0:9c28f5905a1a 146 }