不韋 呂
/
SDR_AM_Rx_CIC
AM中波放送用SDR.CICフィルタのみを使用.CQ出版社「トランジスタ技術」誌,2021年4月号に掲載
main.cpp@1:30d9fb51dec1, 2019-09-23 (annotated)
- Committer:
- MikamiUitOpen
- Date:
- Mon Sep 23 07:32:10 2019 +0000
- Revision:
- 1:30d9fb51dec1
- Parent:
- 0:6906f8616429
- Child:
- 2:4bec6b2be809
2
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
MikamiUitOpen | 0:6906f8616429 | 1 | //------------------------------------------------------------- |
MikamiUitOpen | 1:30d9fb51dec1 | 2 | // 中波 AM 放送用 SDR,CIC フィルタを使用 |
MikamiUitOpen | 1:30d9fb51dec1 | 3 | // |
MikamiUitOpen | 1:30d9fb51dec1 | 4 | // ダウンサンプリング(1/90)で使う LPF として CIC フィルタを使用 |
MikamiUitOpen | 1:30d9fb51dec1 | 5 | // |
MikamiUitOpen | 0:6906f8616429 | 6 | // 入力ピン: A1 |
MikamiUitOpen | 0:6906f8616429 | 7 | // 出力ピン: A2 |
MikamiUitOpen | 0:6906f8616429 | 8 | // |
MikamiUitOpen | 1:30d9fb51dec1 | 9 | // 2019/09/18, Copyright (c) 2019 MIKAMI, Naoki |
MikamiUitOpen | 0:6906f8616429 | 10 | //------------------------------------------------------------- |
MikamiUitOpen | 0:6906f8616429 | 11 | |
MikamiUitOpen | 0:6906f8616429 | 12 | #include "F446_ADC_Intr.hpp" // ADC |
MikamiUitOpen | 0:6906f8616429 | 13 | #include "F446_DAC.hpp" // DAC |
MikamiUitOpen | 0:6906f8616429 | 14 | #include "QuadOscIir.hpp" // 二相発振器 |
MikamiUitOpen | 0:6906f8616429 | 15 | #include "Cic3Stage.hpp" // 3段 CIC フィルタ |
MikamiUitOpen | 0:6906f8616429 | 16 | #include "Iir1st.hpp" // 一次の IIR フィルタ |
MikamiUitOpen | 1:30d9fb51dec1 | 17 | #include "InitialMessage.hpp" // 最初のメーッセージ |
MikamiUitOpen | 0:6906f8616429 | 18 | using namespace Mikami; |
MikamiUitOpen | 0:6906f8616429 | 19 | #pragma diag_suppress 870 // マルチバイト文字使用の警告抑制のため |
MikamiUitOpen | 0:6906f8616429 | 20 | |
MikamiUitOpen | 0:6906f8616429 | 21 | const float FS_ = 900.0f; // 標本化周波数,単位: kHz |
MikamiUitOpen | 0:6906f8616429 | 22 | const float T0_ = 1000/FS_; // 標本化間隔,単位:μs |
MikamiUitOpen | 0:6906f8616429 | 23 | const float A0_ = 8192; // 二相発振器の出力の振幅 |
MikamiUitOpen | 0:6906f8616429 | 24 | |
MikamiUitOpen | 0:6906f8616429 | 25 | // 各放送局の搬送波の周波数,単位: kHz |
MikamiUitOpen | 0:6906f8616429 | 26 | const float F_C_[] = { 594.0e3f, // NHK 第1 |
MikamiUitOpen | 0:6906f8616429 | 27 | 693.0e3f, // NHK 第2 |
MikamiUitOpen | 0:6906f8616429 | 28 | 810.0e3f, // AFN Tokyo |
MikamiUitOpen | 0:6906f8616429 | 29 | 954.0e3f, // TBS ラジオ |
MikamiUitOpen | 0:6906f8616429 | 30 | 1134.0e3f, // 文化放送 |
MikamiUitOpen | 0:6906f8616429 | 31 | 1242.0e3f, // ニッポン放送 |
MikamiUitOpen | 0:6906f8616429 | 32 | 1422.0e3f}; // ラジオ日本 |
MikamiUitOpen | 0:6906f8616429 | 33 | |
MikamiUitOpen | 0:6906f8616429 | 34 | AdcF446_Intr adc_(FS_, A1); // ADC オブジェクトの宣言 |
MikamiUitOpen | 0:6906f8616429 | 35 | DacF446 dac_; // DAC オブジェクトの宣言 |
MikamiUitOpen | 0:6906f8616429 | 36 | Serial pc_(USBTX, USBRX); // ターミナルに対する受信割込み用 |
MikamiUitOpen | 0:6906f8616429 | 37 | |
MikamiUitOpen | 0:6906f8616429 | 38 | QuadOscIir nco_(F_C_[0], T0_, A0_); // NCO (numerically controlled oscillator) |
MikamiUitOpen | 0:6906f8616429 | 39 | |
MikamiUitOpen | 0:6906f8616429 | 40 | Iir1st comp_(-0.525f); // CIC フィルタの補償用フィルタ |
MikamiUitOpen | 0:6906f8616429 | 41 | Iir1st averaging_(0.9995f); // 直流分を求めるためのフィルタ |
MikamiUitOpen | 0:6906f8616429 | 42 | |
MikamiUitOpen | 0:6906f8616429 | 43 | const int DS_RATE_ = 90; // 1/90 にダウンサンプリング |
MikamiUitOpen | 0:6906f8616429 | 44 | Cic3Stage cic3I_(DS_RATE_, A0_); // CIC フィルタ,I 信号用 |
MikamiUitOpen | 0:6906f8616429 | 45 | Cic3Stage cic3Q_(DS_RATE_, A0_); // CIC フィルタ,Q 信号用 |
MikamiUitOpen | 0:6906f8616429 | 46 | |
MikamiUitOpen | 0:6906f8616429 | 47 | // AD 変換終了割り込みに対する割り込みサービス・ルーチン |
MikamiUitOpen | 0:6906f8616429 | 48 | void AdcIsr() |
MikamiUitOpen | 0:6906f8616429 | 49 | { |
MikamiUitOpen | 0:6906f8616429 | 50 | static int count = 0; |
MikamiUitOpen | 0:6906f8616429 | 51 | |
MikamiUitOpen | 0:6906f8616429 | 52 | float xn = adc_.Read(); // ADC の読込み |
MikamiUitOpen | 0:6906f8616429 | 53 | float sinX, cosX; |
MikamiUitOpen | 0:6906f8616429 | 54 | nco_.Generate(sinX, cosX); // sin, cos 発生 |
MikamiUitOpen | 0:6906f8616429 | 55 | |
MikamiUitOpen | 0:6906f8616429 | 56 | // cos/sin を乗算したデータに対する CIC フィルタの累算処理 |
MikamiUitOpen | 0:6906f8616429 | 57 | cic3I_.Accumulate((int16_t)(xn*cosX)); // I 信号用 |
MikamiUitOpen | 0:6906f8616429 | 58 | cic3Q_.Accumulate((int16_t)(xn*sinX)); // Q 信号用 |
MikamiUitOpen | 0:6906f8616429 | 59 | |
MikamiUitOpen | 0:6906f8616429 | 60 | if (++count >= DS_RATE_) |
MikamiUitOpen | 0:6906f8616429 | 61 | { |
MikamiUitOpen | 0:6906f8616429 | 62 | count = 0; |
MikamiUitOpen | 0:6906f8616429 | 63 | NVIC->STIR |= EXTI4_IRQn; // ソフトウェア割り込み発生 |
MikamiUitOpen | 0:6906f8616429 | 64 | } |
MikamiUitOpen | 0:6906f8616429 | 65 | } |
MikamiUitOpen | 0:6906f8616429 | 66 | |
MikamiUitOpen | 0:6906f8616429 | 67 | // ダウンサンプラより後の処理に対する割り込みサービス・ルーチン |
MikamiUitOpen | 0:6906f8616429 | 68 | void SwiIsr() |
MikamiUitOpen | 0:6906f8616429 | 69 | { |
MikamiUitOpen | 0:6906f8616429 | 70 | // CIC フィルタの差分処理 |
MikamiUitOpen | 0:6906f8616429 | 71 | float yI_n = cic3I_.Difference(); // 差分処理で I 信号を生成 |
MikamiUitOpen | 0:6906f8616429 | 72 | float yQ_n = cic3Q_.Difference(); // 差分処理で Q 信号を生成 |
MikamiUitOpen | 0:6906f8616429 | 73 | |
MikamiUitOpen | 0:6906f8616429 | 74 | float yn = sqrtf(yI_n*yI_n + yQ_n*yQ_n); // 包絡線成分を求める |
MikamiUitOpen | 0:6906f8616429 | 75 | yn = comp_.Execute(yn); // 補償フィルタ |
MikamiUitOpen | 0:6906f8616429 | 76 | float dc = averaging_.Execute(yn); // 直流分を求める |
MikamiUitOpen | 0:6906f8616429 | 77 | |
MikamiUitOpen | 0:6906f8616429 | 78 | float gain = 0.8f/dc; // AGC 処理の準備 |
MikamiUitOpen | 0:6906f8616429 | 79 | if (gain > 200.0f) gain = 200.0f; |
MikamiUitOpen | 0:6906f8616429 | 80 | |
MikamiUitOpen | 0:6906f8616429 | 81 | // DAC への出力は,直流分を除去し,AGC 処理をしたもの |
MikamiUitOpen | 0:6906f8616429 | 82 | dac_.Write(gain*(yn - dc)); |
MikamiUitOpen | 0:6906f8616429 | 83 | } |
MikamiUitOpen | 0:6906f8616429 | 84 | |
MikamiUitOpen | 0:6906f8616429 | 85 | // シリアル・ポートの受信割込みに対する処理 |
MikamiUitOpen | 0:6906f8616429 | 86 | void RxIsr() |
MikamiUitOpen | 0:6906f8616429 | 87 | { |
MikamiUitOpen | 0:6906f8616429 | 88 | unsigned char chr = pc_.getc(); |
MikamiUitOpen | 0:6906f8616429 | 89 | // 受信した文字が '0' ~ '6' の場合のみ NCO の周波数を変える |
MikamiUitOpen | 0:6906f8616429 | 90 | if (('0' <= chr) && (chr <= '6')) |
MikamiUitOpen | 0:6906f8616429 | 91 | { |
MikamiUitOpen | 0:6906f8616429 | 92 | nco_.Set(F_C_[chr & 0x07]); |
MikamiUitOpen | 0:6906f8616429 | 93 | pc_.putc(chr); // エコーバック |
MikamiUitOpen | 0:6906f8616429 | 94 | } |
MikamiUitOpen | 0:6906f8616429 | 95 | if (chr == '\r') pc_.printf("\r\n"); |
MikamiUitOpen | 0:6906f8616429 | 96 | } |
MikamiUitOpen | 0:6906f8616429 | 97 | |
MikamiUitOpen | 0:6906f8616429 | 98 | int main() |
MikamiUitOpen | 0:6906f8616429 | 99 | { |
MikamiUitOpen | 1:30d9fb51dec1 | 100 | InitialMessage("ダウンサンプリングに CIC フィルタ使用.", AM, pc_); |
MikamiUitOpen | 0:6906f8616429 | 101 | |
MikamiUitOpen | 0:6906f8616429 | 102 | NVIC_SetPriority(ADC_IRQn, 0); // 最優先 |
MikamiUitOpen | 0:6906f8616429 | 103 | NVIC_SetPriority(EXTI4_IRQn, 1); // 2番目に優先 |
MikamiUitOpen | 0:6906f8616429 | 104 | NVIC_SetPriority(USART2_IRQn, 2); |
MikamiUitOpen | 0:6906f8616429 | 105 | |
MikamiUitOpen | 0:6906f8616429 | 106 | // ADC に対する割り込みサービス・ルーチンの設定 |
MikamiUitOpen | 0:6906f8616429 | 107 | adc_.SetIntrVec(&AdcIsr); |
MikamiUitOpen | 0:6906f8616429 | 108 | |
MikamiUitOpen | 0:6906f8616429 | 109 | // EXTI4 によるソフトウェア割り込みに対応する設定 |
MikamiUitOpen | 0:6906f8616429 | 110 | NVIC_SetVector(EXTI4_IRQn, (uint32_t)SwiIsr); |
MikamiUitOpen | 0:6906f8616429 | 111 | NVIC_EnableIRQ(EXTI4_IRQn); |
MikamiUitOpen | 0:6906f8616429 | 112 | |
MikamiUitOpen | 0:6906f8616429 | 113 | // シリアル・ポートの受信割込みの設定 |
MikamiUitOpen | 0:6906f8616429 | 114 | pc_.format(); // default: 8 bits, nonparity, 1 stop bit |
MikamiUitOpen | 0:6906f8616429 | 115 | pc_.attach(&RxIsr); |
MikamiUitOpen | 0:6906f8616429 | 116 | |
MikamiUitOpen | 0:6906f8616429 | 117 | while (true) {} |
MikamiUitOpen | 0:6906f8616429 | 118 | } |