Adaptive line enhancer (ALE) using leaky LMS algorithm. Step size parameter can be controled using input voltage of AD converter.
Dependencies: UITDSP_ADDA UIT_ACM1602NI UIT_AQM1602 mbed
main.cpp
- Committer:
- MikamiUitOpen
- Date:
- 2015-07-25
- Revision:
- 0:f81c448ea76b
File content as of revision 0:f81c448ea76b:
//-------------------------------------------------------------- // FIR フィルタによる適応線スペクトル強調器(ALE) // アルゴリズム: Leaky LMS // // VR でステップサイズ・パラメータを 10^-5 ~ 10^-2 の範囲で変更できます. // ステップサイズ・パラメータが大きすぎると出力が発散する場合があります. // そのような場合は,ステップサイズ・パラメータを小さくした後,リセットボタ // ンを押してください. // // A0: 雑音の混入した周期信号 // A2: ステップサイズ・パラメータ(μ)を変更するための入力 // 出力: MCP4921 または MCP4922 // 2015/07/13, Copyright (c) 2015 MIKAMI, Naoki //-------------------------------------------------------------- #include "ADC_Interrupt.hpp" // for ADC using interrupt #include "DAC_MCP4921.hpp" // for DAC MCP4921, MCP4922 using namespace Mikami; const int FS_ = 16000; // Sampling frequency: 16 kHz ADC_Intr myAdc_(A0, FS_, A1, A2); // for AD DAC_MCP4921 myDac_; // for DA DigitalIn sw_(D2, PullDown); // ACM1602Ni を使う場合は次の define 文をコメントにすること #define AQM1602 #ifdef AQM1602 #include "AQM1602.hpp" Aqm1602 Lcd_; #else #include "ACM1602NI.hpp" Acm1602Ni Lcd_; #endif const int ORDER_ = 100; // Order of FIR filter const int DELAY_ = 5; // Number of delay to reduce correlation const int N_ALL_ = ORDER_ + DELAY_ + 1; float mu_; // Step size parameter (μ) float err_mu_; // error*μ; uint16_t a2_ = 0; // Inputted data from A2 pin float xn_[N_ALL_], hm_[ORDER_+1]; // Interrupt service routine for ADC void AdcIsr() { const float GAMMA = 0.996f; xn_[0] = myAdc_.Read(); // Read from A0 myAdc_.Select3rdChannel(); // Select A2 myAdc_.SoftStart(); // ADC start for A2 input //----------------------------------------- // ALE の処理 // FIR フィルタの実行 float yn = 0; for (int k=0; k<=ORDER_; k++) yn = yn + hm_[k]*xn_[k+DELAY_]; // 係数の更新 err_mu_ = (xn_[0] - yn)*mu_; for (int k=0; k<=ORDER_; k++) hm_[k] = GAMMA*hm_[k] + err_mu_*xn_[k+DELAY_]; // FIR フィルタの遅延器および相関除去用遅延器のデータの移動 for (int k=N_ALL_-1; k>0; k--) xn_[k] = xn_[k-1]; //----------------------------------------- if ((sw_ & 0x01) == 0) myDac_.Write(xn_[0]); // 入力をそのまま出力 else myDac_.Write(yn); // ALE の結果を出力 // μを変更するための値を読み込む a2_ = myAdc_.ReadWait_u16(); myAdc_.Select1stChannel(); // Select A0 myAdc_.ClearPending_EnableIRQ();// Clear pending interrupt // and enable ADC_IRQn } int main() { myDac_.ScfClockTim3(500000); // cutoff frequency: 5 kHz Lcd_.Clear(); Lcd_.WriteStringXY("ALE", 0, 0); printf("\r\nAdaptive Line Enhancer\r\n"); for (int n=0; n<N_ALL_; n++) xn_[n] = 0; for (int n=0; n<=ORDER_; n++) hm_[n] = 0; myAdc_.SetIntrVec(AdcIsr); // Assign ISR for ADC interrupt while (true) { // VR から読み込んだ値でμを変更する float power = 3.0f*a2_/4095.0f - 5; mu_ = powf(10.0f, power); printf("mu = %8.2e, error*mu = %8.2e\r\n", mu_, err_mu_); char str[17]; sprintf(str, "mu: %8.2e", mu_); Lcd_.WriteStringXY(str, 0, 1); wait(0.5f); } }