不韋 呂
/
SDR_FM_Rx_CIC
AM中波放送用SDR.CICフィルタのみを使用.CQ出版社「トランジスタ技術」誌,2021年5月号に掲載
main.cpp@0:4037028ba61a, 2020-08-29 (annotated)
- Committer:
- MikamiUitOpen
- Date:
- Sat Aug 29 11:25:47 2020 +0000
- Revision:
- 0:4037028ba61a
- Child:
- 1:2b596eab04de
1
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
MikamiUitOpen | 0:4037028ba61a | 1 | //------------------------------------------------------------- |
MikamiUitOpen | 0:4037028ba61a | 2 | // FM 用 SDR |
MikamiUitOpen | 0:4037028ba61a | 3 | // 入力信号:SDR_FM_Tx で発生した信号 |
MikamiUitOpen | 0:4037028ba61a | 4 | // 入力ピン: A1 |
MikamiUitOpen | 0:4037028ba61a | 5 | // 出力ピン: A2 |
MikamiUitOpen | 0:4037028ba61a | 6 | // ダウンサンプリングで CIC フィルタを使用 |
MikamiUitOpen | 0:4037028ba61a | 7 | // |
MikamiUitOpen | 0:4037028ba61a | 8 | // Tera Term から選局可能,0 と 1 |
MikamiUitOpen | 0:4037028ba61a | 9 | // |
MikamiUitOpen | 0:4037028ba61a | 10 | // 2020/08/10, Copyright (c) 2020 MIKAMI, Naoki |
MikamiUitOpen | 0:4037028ba61a | 11 | //------------------------------------------------------------- |
MikamiUitOpen | 0:4037028ba61a | 12 | |
MikamiUitOpen | 0:4037028ba61a | 13 | #include "F446_ADC_Intr.hpp" |
MikamiUitOpen | 0:4037028ba61a | 14 | #include "F446_DAC.hpp" |
MikamiUitOpen | 0:4037028ba61a | 15 | #include "QuadOscIir.hpp" |
MikamiUitOpen | 0:4037028ba61a | 16 | #include "Cic3Stage.hpp" |
MikamiUitOpen | 0:4037028ba61a | 17 | #include "FastATan.hpp" |
MikamiUitOpen | 0:4037028ba61a | 18 | #include "IirDcCut.hpp" |
MikamiUitOpen | 0:4037028ba61a | 19 | #include "InitialMessage.hpp" // 最初のメーッセージ |
MikamiUitOpen | 0:4037028ba61a | 20 | using namespace Mikami; |
MikamiUitOpen | 0:4037028ba61a | 21 | #pragma diag_suppress 870 // マルチバイト文字使用の警告抑制のため |
MikamiUitOpen | 0:4037028ba61a | 22 | |
MikamiUitOpen | 0:4037028ba61a | 23 | const float FS_ = 900.0f; // 標本化周波数,単位: kHz |
MikamiUitOpen | 0:4037028ba61a | 24 | const float T0_ = 1000/FS_; // 標本化間隔,単位:μs |
MikamiUitOpen | 0:4037028ba61a | 25 | const float A0_ = 8192; // 直交信号発生器の出力の振幅 |
MikamiUitOpen | 0:4037028ba61a | 26 | |
MikamiUitOpen | 0:4037028ba61a | 27 | const float F_C_[] = { 70.0e3f, 130.0e3f}; // 搬送波周波数 |
MikamiUitOpen | 0:4037028ba61a | 28 | |
MikamiUitOpen | 0:4037028ba61a | 29 | AdcF446_Intr adc_(FS_, A1); |
MikamiUitOpen | 0:4037028ba61a | 30 | DacF446 dac_; |
MikamiUitOpen | 0:4037028ba61a | 31 | Serial pc_(USBTX, USBRX); // ターミナルに対する受信割込み用 |
MikamiUitOpen | 0:4037028ba61a | 32 | // 直流分除去用フィルタ |
MikamiUitOpen | 0:4037028ba61a | 33 | // 高域通過フィルタ |
MikamiUitOpen | 0:4037028ba61a | 34 | // バタワース特性 |
MikamiUitOpen | 0:4037028ba61a | 35 | // 次数 : 1 次 |
MikamiUitOpen | 0:4037028ba61a | 36 | // 標本化周波数: 36.00 kHz |
MikamiUitOpen | 0:4037028ba61a | 37 | // 遮断周波数 : 0.05 kHz |
MikamiUitOpen | 0:4037028ba61a | 38 | IirDcCut dcCut_(9.913112E-01f, 9.956556E-01f); // 入力の直流成分除去用フィルタ |
MikamiUitOpen | 0:4037028ba61a | 39 | |
MikamiUitOpen | 0:4037028ba61a | 40 | QuadOscIir nco_(F_C_[0], T0_, A0_); // NCO (numerically controlled oscillator) |
MikamiUitOpen | 0:4037028ba61a | 41 | |
MikamiUitOpen | 0:4037028ba61a | 42 | const int DS_RATE_ = 25; // 1/25 にダウンサンプリング |
MikamiUitOpen | 0:4037028ba61a | 43 | Cic3Stage cic3I_(DS_RATE_, A0_); |
MikamiUitOpen | 0:4037028ba61a | 44 | Cic3Stage cic3Q_(DS_RATE_, A0_); |
MikamiUitOpen | 0:4037028ba61a | 45 | |
MikamiUitOpen | 0:4037028ba61a | 46 | // AD 変換終了割り込みに対する割り込みサービス・ルーチン |
MikamiUitOpen | 0:4037028ba61a | 47 | void AdcIsr() |
MikamiUitOpen | 0:4037028ba61a | 48 | { |
MikamiUitOpen | 0:4037028ba61a | 49 | static int count = 0; |
MikamiUitOpen | 0:4037028ba61a | 50 | |
MikamiUitOpen | 0:4037028ba61a | 51 | float xn = adc_.Read(); // ADC の読込み |
MikamiUitOpen | 0:4037028ba61a | 52 | float sinX, cosX; |
MikamiUitOpen | 0:4037028ba61a | 53 | nco_.Generate(sinX, cosX); // sin, cos 発生 |
MikamiUitOpen | 0:4037028ba61a | 54 | |
MikamiUitOpen | 0:4037028ba61a | 55 | cic3I_.Integrate((int16_t)(xn*cosX)); // I 信号 |
MikamiUitOpen | 0:4037028ba61a | 56 | cic3Q_.Integrate((int16_t)(xn*sinX)); // Q 信号 |
MikamiUitOpen | 0:4037028ba61a | 57 | |
MikamiUitOpen | 0:4037028ba61a | 58 | if (++count >= DS_RATE_) |
MikamiUitOpen | 0:4037028ba61a | 59 | { |
MikamiUitOpen | 0:4037028ba61a | 60 | count = 0; |
MikamiUitOpen | 0:4037028ba61a | 61 | NVIC->STIR |= EXTI4_IRQn; // ソフトウェア割り込み発生 |
MikamiUitOpen | 0:4037028ba61a | 62 | } |
MikamiUitOpen | 0:4037028ba61a | 63 | } |
MikamiUitOpen | 0:4037028ba61a | 64 | |
MikamiUitOpen | 0:4037028ba61a | 65 | // ダウンサンプラより後の処理に対する割り込みサービス・ルーチン |
MikamiUitOpen | 0:4037028ba61a | 66 | void SwiIsr() |
MikamiUitOpen | 0:4037028ba61a | 67 | { |
MikamiUitOpen | 0:4037028ba61a | 68 | static const float PI = 3.141592654; |
MikamiUitOpen | 0:4037028ba61a | 69 | static const float PI2 = 2.0f*PI; |
MikamiUitOpen | 0:4037028ba61a | 70 | static float phi_nM1 = 0; // 一つ前の位相の値 |
MikamiUitOpen | 0:4037028ba61a | 71 | |
MikamiUitOpen | 0:4037028ba61a | 72 | float yI_n = cic3I_.CombFilter(); // くし形フィルタ処理で I 信号を生成 |
MikamiUitOpen | 0:4037028ba61a | 73 | float yQ_n = cic3Q_.CombFilter(); // くし形フィルタ処理で Q 信号を生成 |
MikamiUitOpen | 0:4037028ba61a | 74 | |
MikamiUitOpen | 0:4037028ba61a | 75 | float phi_n = FastATan(yQ_n, yI_n); // 位相成分を求める |
MikamiUitOpen | 0:4037028ba61a | 76 | float dif = phi_n - phi_nM1; // 位相の差分 |
MikamiUitOpen | 0:4037028ba61a | 77 | if (dif > PI) dif -= PI2; // 差分処理の補正 |
MikamiUitOpen | 0:4037028ba61a | 78 | if (dif < -PI) dif += PI2; // 差分処理の補正 |
MikamiUitOpen | 0:4037028ba61a | 79 | |
MikamiUitOpen | 0:4037028ba61a | 80 | float yn = dcCut_.Execute(dif); // 直流分除去 |
MikamiUitOpen | 0:4037028ba61a | 81 | dac_.Write(yn); |
MikamiUitOpen | 0:4037028ba61a | 82 | phi_nM1 = phi_n; |
MikamiUitOpen | 0:4037028ba61a | 83 | } |
MikamiUitOpen | 0:4037028ba61a | 84 | |
MikamiUitOpen | 0:4037028ba61a | 85 | // シリアル・ポートの受信割込みに対する処理 |
MikamiUitOpen | 0:4037028ba61a | 86 | void RxIsr() |
MikamiUitOpen | 0:4037028ba61a | 87 | { |
MikamiUitOpen | 0:4037028ba61a | 88 | unsigned char chr = pc_.getc(); |
MikamiUitOpen | 0:4037028ba61a | 89 | // 受信した文字が '0', '1' の場合のみ NCO の周波数を変える |
MikamiUitOpen | 0:4037028ba61a | 90 | if (('0' <= chr) && (chr <= '1')) |
MikamiUitOpen | 0:4037028ba61a | 91 | { |
MikamiUitOpen | 0:4037028ba61a | 92 | nco_.Set(F_C_[chr & 0x01]); |
MikamiUitOpen | 0:4037028ba61a | 93 | pc_.putc(chr); // エコーバック |
MikamiUitOpen | 0:4037028ba61a | 94 | } |
MikamiUitOpen | 0:4037028ba61a | 95 | if (chr == '\r') pc_.printf("\r\n"); |
MikamiUitOpen | 0:4037028ba61a | 96 | } |
MikamiUitOpen | 0:4037028ba61a | 97 | |
MikamiUitOpen | 0:4037028ba61a | 98 | int main() |
MikamiUitOpen | 0:4037028ba61a | 99 | { |
MikamiUitOpen | 0:4037028ba61a | 100 | InitialMessage("ダウンサンプリングに CIC フィルタ使用.", FM, pc_); |
MikamiUitOpen | 0:4037028ba61a | 101 | |
MikamiUitOpen | 0:4037028ba61a | 102 | NVIC_SetPriority(ADC_IRQn, 0); // 最優先 |
MikamiUitOpen | 0:4037028ba61a | 103 | NVIC_SetPriority(EXTI4_IRQn, 1); // 2番目に優先 |
MikamiUitOpen | 0:4037028ba61a | 104 | NVIC_SetPriority(USART2_IRQn, 2); // 3番目に優先 |
MikamiUitOpen | 0:4037028ba61a | 105 | |
MikamiUitOpen | 0:4037028ba61a | 106 | adc_.SetIntrVec(&AdcIsr); // ADC の割り込みサービス・ルーチンの設定 |
MikamiUitOpen | 0:4037028ba61a | 107 | |
MikamiUitOpen | 0:4037028ba61a | 108 | // EXTI4 によるソフトウェア割り込みに対応する設定 |
MikamiUitOpen | 0:4037028ba61a | 109 | NVIC_SetVector(EXTI4_IRQn, (uint32_t)SwiIsr); |
MikamiUitOpen | 0:4037028ba61a | 110 | NVIC_EnableIRQ(EXTI4_IRQn); |
MikamiUitOpen | 0:4037028ba61a | 111 | |
MikamiUitOpen | 0:4037028ba61a | 112 | // シリアル・ポートの受信割込みの設定 |
MikamiUitOpen | 0:4037028ba61a | 113 | pc_.format(); // default: 8 bits, nonparity, 1 stop bit |
MikamiUitOpen | 0:4037028ba61a | 114 | pc_.attach(&RxIsr); |
MikamiUitOpen | 0:4037028ba61a | 115 | |
MikamiUitOpen | 0:4037028ba61a | 116 | while (true) {} |
MikamiUitOpen | 0:4037028ba61a | 117 | } |