AM中波放送用SDR.CICフィルタのみを使用.CQ出版社「トランジスタ技術」誌,2021年4月号に掲載

Dependencies:   mbed

Committer:
MikamiUitOpen
Date:
Mon Sep 16 14:20:17 2019 +0000
Revision:
0:6906f8616429
Child:
1:30d9fb51dec1
1

Who changed what in which revision?

UserRevisionLine numberNew contents of line
MikamiUitOpen 0:6906f8616429 1 //-------------------------------------------------------------
MikamiUitOpen 0:6906f8616429 2 // 中波 AM 放送用 SDR
MikamiUitOpen 0:6906f8616429 3 // 入力ピン: A1
MikamiUitOpen 0:6906f8616429 4 // 出力ピン: A2
MikamiUitOpen 0:6906f8616429 5 //
MikamiUitOpen 0:6906f8616429 6 // ダウンサンプリングで使う LPF として CIC フィルタを使用
MikamiUitOpen 0:6906f8616429 7 // CIC フィルタの段数:3段
MikamiUitOpen 0:6906f8616429 8 // CIC フィルタをクラスにする
MikamiUitOpen 0:6906f8616429 9 //
MikamiUitOpen 0:6906f8616429 10 // 2019/09/16, Copyright (c) 2019 MIKAMI, Naoki
MikamiUitOpen 0:6906f8616429 11 //-------------------------------------------------------------
MikamiUitOpen 0:6906f8616429 12
MikamiUitOpen 0:6906f8616429 13 #include "F446_ADC_Intr.hpp" // ADC
MikamiUitOpen 0:6906f8616429 14 #include "F446_DAC.hpp" // DAC
MikamiUitOpen 0:6906f8616429 15 #include "QuadOscIir.hpp" // 二相発振器
MikamiUitOpen 0:6906f8616429 16 #include "Cic3Stage.hpp" // 3段 CIC フィルタ
MikamiUitOpen 0:6906f8616429 17 #include "Iir1st.hpp" // 一次の IIR フィルタ
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 0:6906f8616429 100 printf("\r\n");
MikamiUitOpen 0:6906f8616429 101 printf("SDR (CIC フィルタ使用) を実行します.\r\n");
MikamiUitOpen 0:6906f8616429 102 printf("0: NHK 第1\r\n1: NHK 第2\r\n2: AFN Tokyo\r\n3: TBS ラジオ\r\n"
MikamiUitOpen 0:6906f8616429 103 "4: 文化放送\r\n5: ニッポン放送\r\n6: ラジオ日本\r\n\n");
MikamiUitOpen 0:6906f8616429 104 printf("'0' ~ '6' のキーで選局できます.\r\n");
MikamiUitOpen 0:6906f8616429 105 printf("'Enter' キーは CR/LF するだけです.\r\n");
MikamiUitOpen 0:6906f8616429 106 printf("'0' ~ '6', 'Enter' キー以外は何も反応しません.\r\n\n");
MikamiUitOpen 0:6906f8616429 107 pc_.putc('0');
MikamiUitOpen 0:6906f8616429 108
MikamiUitOpen 0:6906f8616429 109 NVIC_SetPriority(ADC_IRQn, 0); // 最優先
MikamiUitOpen 0:6906f8616429 110 NVIC_SetPriority(EXTI4_IRQn, 1); // 2番目に優先
MikamiUitOpen 0:6906f8616429 111 NVIC_SetPriority(USART2_IRQn, 2);
MikamiUitOpen 0:6906f8616429 112
MikamiUitOpen 0:6906f8616429 113 // ADC に対する割り込みサービス・ルーチンの設定
MikamiUitOpen 0:6906f8616429 114 adc_.SetIntrVec(&AdcIsr);
MikamiUitOpen 0:6906f8616429 115
MikamiUitOpen 0:6906f8616429 116 // EXTI4 によるソフトウェア割り込みに対応する設定
MikamiUitOpen 0:6906f8616429 117 NVIC_SetVector(EXTI4_IRQn, (uint32_t)SwiIsr);
MikamiUitOpen 0:6906f8616429 118 NVIC_EnableIRQ(EXTI4_IRQn);
MikamiUitOpen 0:6906f8616429 119
MikamiUitOpen 0:6906f8616429 120 // シリアル・ポートの受信割込みの設定
MikamiUitOpen 0:6906f8616429 121 pc_.format(); // default: 8 bits, nonparity, 1 stop bit
MikamiUitOpen 0:6906f8616429 122 pc_.attach(&RxIsr);
MikamiUitOpen 0:6906f8616429 123
MikamiUitOpen 0:6906f8616429 124 while (true) {}
MikamiUitOpen 0:6906f8616429 125 }