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@0:f81c448ea76b, 2015-07-25 (annotated)
- Committer:
- MikamiUitOpen
- Date:
- Sat Jul 25 12:54:37 2015 +0000
- Revision:
- 0:f81c448ea76b
1
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
MikamiUitOpen | 0:f81c448ea76b | 1 | //-------------------------------------------------------------- |
MikamiUitOpen | 0:f81c448ea76b | 2 | // FIR フィルタによる適応線スペクトル強調器(ALE) |
MikamiUitOpen | 0:f81c448ea76b | 3 | // アルゴリズム: Leaky LMS |
MikamiUitOpen | 0:f81c448ea76b | 4 | // |
MikamiUitOpen | 0:f81c448ea76b | 5 | // VR でステップサイズ・パラメータを 10^-5 ~ 10^-2 の範囲で変更できます. |
MikamiUitOpen | 0:f81c448ea76b | 6 | // ステップサイズ・パラメータが大きすぎると出力が発散する場合があります. |
MikamiUitOpen | 0:f81c448ea76b | 7 | // そのような場合は,ステップサイズ・パラメータを小さくした後,リセットボタ |
MikamiUitOpen | 0:f81c448ea76b | 8 | // ンを押してください. |
MikamiUitOpen | 0:f81c448ea76b | 9 | // |
MikamiUitOpen | 0:f81c448ea76b | 10 | // A0: 雑音の混入した周期信号 |
MikamiUitOpen | 0:f81c448ea76b | 11 | // A2: ステップサイズ・パラメータ(μ)を変更するための入力 |
MikamiUitOpen | 0:f81c448ea76b | 12 | // 出力: MCP4921 または MCP4922 |
MikamiUitOpen | 0:f81c448ea76b | 13 | // 2015/07/13, Copyright (c) 2015 MIKAMI, Naoki |
MikamiUitOpen | 0:f81c448ea76b | 14 | //-------------------------------------------------------------- |
MikamiUitOpen | 0:f81c448ea76b | 15 | |
MikamiUitOpen | 0:f81c448ea76b | 16 | #include "ADC_Interrupt.hpp" // for ADC using interrupt |
MikamiUitOpen | 0:f81c448ea76b | 17 | #include "DAC_MCP4921.hpp" // for DAC MCP4921, MCP4922 |
MikamiUitOpen | 0:f81c448ea76b | 18 | |
MikamiUitOpen | 0:f81c448ea76b | 19 | using namespace Mikami; |
MikamiUitOpen | 0:f81c448ea76b | 20 | const int FS_ = 16000; // Sampling frequency: 16 kHz |
MikamiUitOpen | 0:f81c448ea76b | 21 | ADC_Intr myAdc_(A0, FS_, A1, A2); // for AD |
MikamiUitOpen | 0:f81c448ea76b | 22 | DAC_MCP4921 myDac_; // for DA |
MikamiUitOpen | 0:f81c448ea76b | 23 | DigitalIn sw_(D2, PullDown); |
MikamiUitOpen | 0:f81c448ea76b | 24 | |
MikamiUitOpen | 0:f81c448ea76b | 25 | // ACM1602Ni を使う場合は次の define 文をコメントにすること |
MikamiUitOpen | 0:f81c448ea76b | 26 | #define AQM1602 |
MikamiUitOpen | 0:f81c448ea76b | 27 | |
MikamiUitOpen | 0:f81c448ea76b | 28 | #ifdef AQM1602 |
MikamiUitOpen | 0:f81c448ea76b | 29 | #include "AQM1602.hpp" |
MikamiUitOpen | 0:f81c448ea76b | 30 | Aqm1602 Lcd_; |
MikamiUitOpen | 0:f81c448ea76b | 31 | #else |
MikamiUitOpen | 0:f81c448ea76b | 32 | #include "ACM1602NI.hpp" |
MikamiUitOpen | 0:f81c448ea76b | 33 | Acm1602Ni Lcd_; |
MikamiUitOpen | 0:f81c448ea76b | 34 | #endif |
MikamiUitOpen | 0:f81c448ea76b | 35 | |
MikamiUitOpen | 0:f81c448ea76b | 36 | const int ORDER_ = 100; // Order of FIR filter |
MikamiUitOpen | 0:f81c448ea76b | 37 | const int DELAY_ = 5; // Number of delay to reduce correlation |
MikamiUitOpen | 0:f81c448ea76b | 38 | const int N_ALL_ = ORDER_ + DELAY_ + 1; |
MikamiUitOpen | 0:f81c448ea76b | 39 | |
MikamiUitOpen | 0:f81c448ea76b | 40 | float mu_; // Step size parameter (μ) |
MikamiUitOpen | 0:f81c448ea76b | 41 | float err_mu_; // error*μ; |
MikamiUitOpen | 0:f81c448ea76b | 42 | uint16_t a2_ = 0; // Inputted data from A2 pin |
MikamiUitOpen | 0:f81c448ea76b | 43 | float xn_[N_ALL_], hm_[ORDER_+1]; |
MikamiUitOpen | 0:f81c448ea76b | 44 | |
MikamiUitOpen | 0:f81c448ea76b | 45 | // Interrupt service routine for ADC |
MikamiUitOpen | 0:f81c448ea76b | 46 | void AdcIsr() |
MikamiUitOpen | 0:f81c448ea76b | 47 | { |
MikamiUitOpen | 0:f81c448ea76b | 48 | const float GAMMA = 0.996f; |
MikamiUitOpen | 0:f81c448ea76b | 49 | xn_[0] = myAdc_.Read(); // Read from A0 |
MikamiUitOpen | 0:f81c448ea76b | 50 | |
MikamiUitOpen | 0:f81c448ea76b | 51 | myAdc_.Select3rdChannel(); // Select A2 |
MikamiUitOpen | 0:f81c448ea76b | 52 | myAdc_.SoftStart(); // ADC start for A2 input |
MikamiUitOpen | 0:f81c448ea76b | 53 | |
MikamiUitOpen | 0:f81c448ea76b | 54 | //----------------------------------------- |
MikamiUitOpen | 0:f81c448ea76b | 55 | // ALE の処理 |
MikamiUitOpen | 0:f81c448ea76b | 56 | |
MikamiUitOpen | 0:f81c448ea76b | 57 | // FIR フィルタの実行 |
MikamiUitOpen | 0:f81c448ea76b | 58 | float yn = 0; |
MikamiUitOpen | 0:f81c448ea76b | 59 | for (int k=0; k<=ORDER_; k++) |
MikamiUitOpen | 0:f81c448ea76b | 60 | yn = yn + hm_[k]*xn_[k+DELAY_]; |
MikamiUitOpen | 0:f81c448ea76b | 61 | |
MikamiUitOpen | 0:f81c448ea76b | 62 | // 係数の更新 |
MikamiUitOpen | 0:f81c448ea76b | 63 | err_mu_ = (xn_[0] - yn)*mu_; |
MikamiUitOpen | 0:f81c448ea76b | 64 | for (int k=0; k<=ORDER_; k++) |
MikamiUitOpen | 0:f81c448ea76b | 65 | hm_[k] = GAMMA*hm_[k] + err_mu_*xn_[k+DELAY_]; |
MikamiUitOpen | 0:f81c448ea76b | 66 | |
MikamiUitOpen | 0:f81c448ea76b | 67 | // FIR フィルタの遅延器および相関除去用遅延器のデータの移動 |
MikamiUitOpen | 0:f81c448ea76b | 68 | for (int k=N_ALL_-1; k>0; k--) |
MikamiUitOpen | 0:f81c448ea76b | 69 | xn_[k] = xn_[k-1]; |
MikamiUitOpen | 0:f81c448ea76b | 70 | //----------------------------------------- |
MikamiUitOpen | 0:f81c448ea76b | 71 | if ((sw_ & 0x01) == 0) |
MikamiUitOpen | 0:f81c448ea76b | 72 | myDac_.Write(xn_[0]); // 入力をそのまま出力 |
MikamiUitOpen | 0:f81c448ea76b | 73 | else |
MikamiUitOpen | 0:f81c448ea76b | 74 | myDac_.Write(yn); // ALE の結果を出力 |
MikamiUitOpen | 0:f81c448ea76b | 75 | |
MikamiUitOpen | 0:f81c448ea76b | 76 | // μを変更するための値を読み込む |
MikamiUitOpen | 0:f81c448ea76b | 77 | a2_ = myAdc_.ReadWait_u16(); |
MikamiUitOpen | 0:f81c448ea76b | 78 | |
MikamiUitOpen | 0:f81c448ea76b | 79 | myAdc_.Select1stChannel(); // Select A0 |
MikamiUitOpen | 0:f81c448ea76b | 80 | myAdc_.ClearPending_EnableIRQ();// Clear pending interrupt |
MikamiUitOpen | 0:f81c448ea76b | 81 | // and enable ADC_IRQn |
MikamiUitOpen | 0:f81c448ea76b | 82 | } |
MikamiUitOpen | 0:f81c448ea76b | 83 | |
MikamiUitOpen | 0:f81c448ea76b | 84 | int main() |
MikamiUitOpen | 0:f81c448ea76b | 85 | { |
MikamiUitOpen | 0:f81c448ea76b | 86 | myDac_.ScfClockTim3(500000); // cutoff frequency: 5 kHz |
MikamiUitOpen | 0:f81c448ea76b | 87 | Lcd_.Clear(); |
MikamiUitOpen | 0:f81c448ea76b | 88 | Lcd_.WriteStringXY("ALE", 0, 0); |
MikamiUitOpen | 0:f81c448ea76b | 89 | printf("\r\nAdaptive Line Enhancer\r\n"); |
MikamiUitOpen | 0:f81c448ea76b | 90 | |
MikamiUitOpen | 0:f81c448ea76b | 91 | for (int n=0; n<N_ALL_; n++) xn_[n] = 0; |
MikamiUitOpen | 0:f81c448ea76b | 92 | for (int n=0; n<=ORDER_; n++) hm_[n] = 0; |
MikamiUitOpen | 0:f81c448ea76b | 93 | |
MikamiUitOpen | 0:f81c448ea76b | 94 | myAdc_.SetIntrVec(AdcIsr); // Assign ISR for ADC interrupt |
MikamiUitOpen | 0:f81c448ea76b | 95 | |
MikamiUitOpen | 0:f81c448ea76b | 96 | while (true) |
MikamiUitOpen | 0:f81c448ea76b | 97 | { |
MikamiUitOpen | 0:f81c448ea76b | 98 | // VR から読み込んだ値でμを変更する |
MikamiUitOpen | 0:f81c448ea76b | 99 | float power = 3.0f*a2_/4095.0f - 5; |
MikamiUitOpen | 0:f81c448ea76b | 100 | mu_ = powf(10.0f, power); |
MikamiUitOpen | 0:f81c448ea76b | 101 | |
MikamiUitOpen | 0:f81c448ea76b | 102 | printf("mu = %8.2e, error*mu = %8.2e\r\n", mu_, err_mu_); |
MikamiUitOpen | 0:f81c448ea76b | 103 | |
MikamiUitOpen | 0:f81c448ea76b | 104 | char str[17]; |
MikamiUitOpen | 0:f81c448ea76b | 105 | sprintf(str, "mu: %8.2e", mu_); |
MikamiUitOpen | 0:f81c448ea76b | 106 | Lcd_.WriteStringXY(str, 0, 1); |
MikamiUitOpen | 0:f81c448ea76b | 107 | |
MikamiUitOpen | 0:f81c448ea76b | 108 | wait(0.5f); |
MikamiUitOpen | 0:f81c448ea76b | 109 | } |
MikamiUitOpen | 0:f81c448ea76b | 110 | } |
MikamiUitOpen | 0:f81c448ea76b | 111 |