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

Dependencies:   mbed

main.cpp

Committer:
MikamiUitOpen
Date:
2021-12-01
Revision:
2:63fbcf115b88
Parent:
1:c8a0b045f010

File content as of revision 2:63fbcf115b88:

//-------------------------------------------------------------
//  中波 AM 放送用 SDR,CIC フィルタと通常の FIR フィルタ使用
//
//      1/9 にダウンサンプリング:CIC フィルタ使用
//      1/4 にダウンサンプリング:通常の FIR フィルタ使用
//
//      入力ピン: A1
//      出力ピン: A2
//
//  2021/12/01, Copyright (c) 2021 MIKAMI, Naoki
//-------------------------------------------------------------

#include "F446_ADC_Intr.hpp"    // ADC
#include "F446_DAC.hpp"         // DAC
#include "QuadOscIir.hpp"       // 直交信号発生器
#include "Cic3Stage.hpp"        // 3段 CIC フィルタ
#include "CoefficientsLpf.hpp"  // FIR フィルタの係数
#include "FirFastSymmetry.hpp"  // 係数対称 FIR フィルタ
#include "Iir1st.hpp"           // 一次の IIR フィルタ
#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;     // 直交信号発生器の出力の振幅

// 各放送局の搬送波の周波数,単位: Hz
const float F_C_[] = {  594.0e3f,   // NHK 第1
                        693.0e3f,   // NHK 第2
                        810.0e3f,   // AFN Tokyo
                        954.0e3f,   // TBS ラジオ
                       1134.0e3f,   // 文化放送
                       1242.0e3f,   // ニッポン放送
                       1422.0e3f};  // ラジオ日本

AdcF446_Intr adc_(FS_, A1);         // ADC オブジェクトの宣言
DacF446 dac_;                       // DAC オブジェクトの宣言
Serial pc_(USBTX, USBRX);           // ターミナルに対する受信割込み用

QuadOscIir nco_(F_C_[0], T0_, A0_); // NCO (numerically controlled oscillator)

Iir1st averaging_(0.9998f);         // 直流分を求めるためのフィルタ

const int DS_RATE1_ = 9;            // 1/9 にダウンサンプリング
Cic3Stage cic3I_(DS_RATE1_, A0_);   // CIC フィルタ,I 信号用
Cic3Stage cic3Q_(DS_RATE1_, A0_);   // CIC フィルタ,Q 信号用

const int DS_RATE2_ = 4;            // 1/4 にダウンサンプリング
FirFastSymmetry lpfI_(ORDER_FIR_, HN_); // FIR フィルタ,I 信号用
FirFastSymmetry lpfQ_(ORDER_FIR_, HN_); // FIR フィルタ,Q 信号用

// AD 変換終了割り込みに対する割り込みサービス・ルーチン
void AdcIsr()
{
    static int count = 0;

    float xn = adc_.Read();     // ADC の読込み
    float sinX, cosX;
    nco_.Generate(sinX, cosX);  // sin, cos 発生

    // cos/sin を乗算したデータに対する CIC フィルタの積分処理
    cic3I_.Integrate((int16_t)(xn*cosX));  // I 信号
    cic3Q_.Integrate((int16_t)(xn*sinX));  // Q 信号

    if (++count >= DS_RATE1_)
    {
        count = 0;
        NVIC->STIR = EXTI3_IRQn;    // ソフトウェア割り込み発生
    }
}

// EXTI3_IRQ に対する割込みサービス・ルーチン
//      CIC フィルタのくし形フィルタの処理と FIR フィルタの入力の処理
void IsrCIC()
{
    static int count = 0;

    float yI_n = cic3I_.CombFilter();   // くし形フィルタ
    float yQ_n = cic3Q_.CombFilter();   // くし形フィルタ

    lpfI_.Store(yI_n);  // FIR フィルタのバッファへ保存,I 信号
    lpfQ_.Store(yQ_n);  // FIR フィルタのバッファへ保存,Q 信号

    if (++count >= DS_RATE2_)
    {
        count = 0;
        NVIC->STIR = EXTI4_IRQn;    // ソフトウェア割り込み発生
    }
}

// EXTI4_IRQ に対する割込みサービス・ルーチン
//      FIR フィルタの実行とAM復調の処理
void IsrFIR()
{
    float yI_n = lpfI_.Execute();    // FIR フィルタによる LPF 実行
    float yQ_n = lpfQ_.Execute();    // FIR フィルタによる LPF 実行

    float yn = sqrtf(yI_n*yI_n + yQ_n*yQ_n);    // 包絡線成分を求める
    float dc = averaging_.Execute(yn);          // 直流分を求める
    yn = yn - dc;   // 直流分除去

    float gain = 0.8f/dc;
    if (gain > 200.0f) gain = 200.0f;
    dac_.Write(gain*yn);
}

// シリアル・ポートの受信割込みに対する割り込みサービス・ルーチン
void RxIsr()
{
    unsigned char chr = pc_.getc();
    // 受信した文字が '0' ~ '6' の場合のみ NCO の周波数を変える
    if (('0' <= chr) && (chr <= '6'))
    {
        nco_.Set(F_C_[chr & 0x07]);
        pc_.putc(chr);   // エコーバック
    }
    if (chr == '\r') pc_.printf("\r\n");
}

int main()
{
    InitialMessage("ダウンサンプリングに CIC フィルタと FIR フィルタを使用.", AM, pc_);

    NVIC_SetPriority(ADC_IRQn,    0);   // 最優先
    NVIC_SetPriority(EXTI3_IRQn,  1);   // 2番目に優先
    NVIC_SetPriority(USART2_IRQn, 2);   // 3番目に優先
    NVIC_SetPriority(EXTI4_IRQn,  3);   // 4番目に優先

    // ADC に対する割り込みサービス・ルーチンの設定
    adc_.SetIntrVec(&AdcIsr);

    // EXTI3 によるソフトウェア割り込みに対応する設定
    NVIC_SetVector(EXTI3_IRQn, (uint32_t)IsrCIC);
    NVIC_EnableIRQ(EXTI3_IRQn);

    // EXTI4 によるソフトウェア割り込みに対応する設定
    NVIC_SetVector(EXTI4_IRQn, (uint32_t)IsrFIR);
    NVIC_EnableIRQ(EXTI4_IRQn);

    // シリアル・ポートの受信割込みの設定
    pc_.format();    // default: 8 bits, nonparity, 1 stop bit
    pc_.attach(&RxIsr);

    while (true) {}
}