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

Revision:
0:f81c448ea76b
diff -r 000000000000 -r f81c448ea76b main.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/main.cpp	Sat Jul 25 12:54:37 2015 +0000
@@ -0,0 +1,111 @@
+//--------------------------------------------------------------
+// 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);
+    }
+}
+