Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependencies: BSP_DISCO_F746NG F746_GUI F746_SAI_IO LCD_DISCO_F746NG TS_DISCO_F746NG UIT_FFT_Real mbed
Revision 0:e608fc311e4e, committed 2017-02-05
- Comitter:
- kenjiArai
- Date:
- Sun Feb 05 07:49:54 2017 +0000
- Commit message:
- CW Decoder (Morse code decoder) 1st release version. mbed = 131 revision (Not latest) is used. Only run on DISCO-F746NG mbed board.
Changed in this revision
diff -r 000000000000 -r e608fc311e4e BSP_DISCO_F746NG.lib --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/BSP_DISCO_F746NG.lib Sun Feb 05 07:49:54 2017 +0000 @@ -0,0 +1,1 @@ +http://mbed.org/teams/ST/code/BSP_DISCO_F746NG/#fe313c53cdb5
diff -r 000000000000 -r e608fc311e4e F746_GUI.lib --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/F746_GUI.lib Sun Feb 05 07:49:54 2017 +0000 @@ -0,0 +1,1 @@ +http://mbed.org/users/MikamiUitOpen/code/F746_GUI/#551a5f1b52b9
diff -r 000000000000 -r e608fc311e4e F746_SAI_IO.lib --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/F746_SAI_IO.lib Sun Feb 05 07:49:54 2017 +0000 @@ -0,0 +1,1 @@ +http://mbed.org/users/MikamiUitOpen/code/F746_SAI_IO/#25a9655d6a0e
diff -r 000000000000 -r e608fc311e4e LCD_DISCO_F746NG.lib --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/LCD_DISCO_F746NG.lib Sun Feb 05 07:49:54 2017 +0000 @@ -0,0 +1,1 @@ +https://developer.mbed.org/teams/ST/code/LCD_DISCO_F746NG/#d44525b1de98
diff -r 000000000000 -r e608fc311e4e MySpectrogram/AnalysisBase.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MySpectrogram/AnalysisBase.cpp	Sun Feb 05 07:49:54 2017 +0000
@@ -0,0 +1,27 @@
+//-------------------------------------------------------
+//  Base abstract class for spectrum analysis
+//
+//  2016/07/23, Copyright (c) 2016 MIKAMI, Naoki
+//-------------------------------------------------------
+
+#include "AnalysisBase.hpp"
+
+namespace Mikami
+{
+    AnalyzerBase::AnalyzerBase(int nData, int nFft, int nUse)
+        : N_DATA_(nData), N_FFT_(nFft),
+          fft_(nFft), wHm_(nData-1, nUse),
+          xData_(nUse), wData_(nUse) {}
+
+    void AnalyzerBase::Execute(const float xn[], float db[])
+    {
+        // Differencing
+        for (int n=0; n<N_DATA_-1; n++)
+            xData_[n] = xn[n+1] - 0.8f*xn[n];
+            
+        // Windowing
+        wHm_.Execute(xData_, wData_);
+            
+        Analyze(wData_, db);
+    }
+}
diff -r 000000000000 -r e608fc311e4e MySpectrogram/AnalysisBase.hpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MySpectrogram/AnalysisBase.hpp	Sun Feb 05 07:49:54 2017 +0000
@@ -0,0 +1,50 @@
+//-------------------------------------------------------
+//  Base abstract class for spectrum analysis (Header)
+//
+//  2016/07/23, Copyright (c) 2016 MIKAMI, Naoki
+//-------------------------------------------------------
+
+#ifndef BASE_ANALYZER_HPP
+#define BASE_ANALYZER_HPP
+
+#include "Array.hpp"
+#include "fftReal.hpp"
+#include "Hamming.hpp"
+
+namespace Mikami
+{
+    class AnalyzerBase
+    {
+    public:
+        // nData: Number of data to be analyzed
+        // nFft:  Number of FFT points
+        // nUse:  FFT, cepstrum: window width + zero padding
+        //        Linear prediction: window width
+        AnalyzerBase(int nData, int nFft, int nUse);
+        virtual ~AnalyzerBase() {}
+        void Execute(const float xn[], float db[]);
+
+    protected:
+        const int N_DATA_;
+        const int N_FFT_;
+
+        FftReal fft_;
+                
+        float Norm(Complex x)
+        { return x.real()*x.real() + x.imag()*x.imag(); }
+
+    private:
+        HammingWindow wHm_;
+
+        Array<float> xData_;    // data to be analyzed
+        Array<float> wData_;    // windowd data
+
+        virtual void Analyze(const float wData[], float db[]) = 0;
+
+        // disallow copy constructor and assignment operator
+        AnalyzerBase(const AnalyzerBase& );
+        AnalyzerBase& operator=(const AnalyzerBase& );
+    };
+}
+#endif  // BASE_ANALYZER_HPP
+
diff -r 000000000000 -r e608fc311e4e MySpectrogram/FFT_Analysis.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MySpectrogram/FFT_Analysis.cpp	Sun Feb 05 07:49:54 2017 +0000
@@ -0,0 +1,23 @@
+//-------------------------------------------------------
+//  Class for spectrum analysis using FFT
+//
+//  2016/07/23, Copyright (c) 2015 MIKAMI, Naoki
+//-------------------------------------------------------
+
+#include "FFT_Analysis.hpp"
+
+namespace Mikami
+{
+    FftAnalyzer::FftAnalyzer(int nData, int nFft)
+        : AnalyzerBase(nData, nFft, nFft),
+          yFft_(nFft/2+1) {}
+
+    void FftAnalyzer::Analyze(const float xn[], float yn[])
+    {
+        fft_.Execute(xn, yFft_);    // Execute FFT
+        
+        // Translate to dB
+        for (int n=0; n<=N_FFT_/2; n++)
+            yn[n] = 10.0f*log10f(Norm(yFft_[n]));
+    }
+}
diff -r 000000000000 -r e608fc311e4e MySpectrogram/FFT_Analysis.hpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MySpectrogram/FFT_Analysis.hpp	Sun Feb 05 07:49:54 2017 +0000
@@ -0,0 +1,31 @@
+//-------------------------------------------------------
+//  Class for spectrum analysis using FFT (Header)
+//
+//  2016/07/23, Copyright (c) 2016 MIKAMI, Naoki
+//-------------------------------------------------------
+
+#ifndef FFT_ANALYZER_HPP
+#define FFT_ANALYZER_HPP
+
+#include "AnalysisBase.hpp"
+
+namespace Mikami
+{
+    class FftAnalyzer : public AnalyzerBase
+    {
+    public:
+        FftAnalyzer(int nData, int nFft);
+        virtual ~FftAnalyzer() {}
+
+    private:
+        Array<Complex> yFft_;   // output of FFT
+
+        virtual void Analyze(const float xn[], float yn[]);
+
+        // disallow copy constructor and assignment operator
+        FftAnalyzer(const FftAnalyzer& );
+        FftAnalyzer& operator=(const FftAnalyzer& );
+    };
+}
+
+#endif  // FFT_ANALYZER_HPP
diff -r 000000000000 -r e608fc311e4e MySpectrogram/Hamming.hpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MySpectrogram/Hamming.hpp	Sun Feb 05 07:49:54 2017 +0000
@@ -0,0 +1,48 @@
+//-------------------------------------------------------------------
+//  Hamming windowing with zero-padding
+//
+//  2016/07/23, Copyright (c) 2016 MIKAMI, Naoki
+//-------------------------------------------------------------------
+
+#ifndef HAMMING_WINDOW_HPP
+#define HAMMING_WINDOW_HPP
+
+#include "mbed.h"
+#include "Array.hpp"
+
+namespace Mikami
+{
+    class HammingWindow
+    {
+    public:
+        // Constructor
+        HammingWindow(uint16_t nData, uint16_t nFft)
+                : N_(nData), NFFT_(nFft), w_(nData)
+        {
+            float pi2L = 6.283185f/(float)nData;
+            for (int k=0; k<nData; k++)
+                w_[k] = 0.54f - 0.46f*cosf(k*pi2L);
+        }
+        
+        // Destructor
+        virtual ~HammingWindow() {}
+        
+        // Windowing
+        void Execute(const float x[], float y[])
+        {
+            for (int n=0; n<N_; n++) y[n] = x[n]*w_[n];
+            for (int n=N_; n<NFFT_; n++) y[n] = 0;
+        }
+
+    private:
+        const int N_;
+        const int NFFT_;
+                
+        Array<float> w_;
+
+        // disallow copy constructor and assignment operator
+        HammingWindow(const HammingWindow& );
+        HammingWindow& operator=(const HammingWindow& );
+    };
+}
+#endif  // HAMMING_WINDOW_HPP
diff -r 000000000000 -r e608fc311e4e MySpectrogram/MethodCollection.hpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MySpectrogram/MethodCollection.hpp	Sun Feb 05 07:49:54 2017 +0000
@@ -0,0 +1,104 @@
+//--------------------------------------------------------------
+//  スペクトログラムで使う大域関数
+//
+//  2016/08/11, Copyright (c) 2016 MIKAMI, Naoki
+//--------------------------------------------------------------
+
+#ifndef METHOD_COLLECTION_HPP
+#define METHOD_COLLECTION_HPP
+
+#include "mbed.h"
+#include "NumericLabel.hpp"
+#include "Matrix.hpp"
+#include "FFT_Analysis.hpp"
+
+namespace Mikami
+{
+    // 色相の違いで表示
+    //      0.0 <= x <= 1.0
+    uint32_t HueScale(float x)
+    {
+        if (x >= 1) return LCD_COLOR_WHITE;
+        int r = 0;
+        int b = 0;
+
+        if (x<0.5f) b = (x<0.33f) ? 255 : -(int)(1500.0f*x) + 750;
+        else        r = (0.67f<x) ? 255 :  (int)(1500.0f*x) - 750;
+        int g = 255 - (int)(1020.0f*(x - 0.5f)*(x - 0.5f));
+
+        return 0xFF000000 | (((r << 8) | g) << 8) | b;
+    }
+
+    // 座標軸
+    void DrawAxis(int x0, int y0, int w0, int h0, uint32_t axisColor,
+                  uint16_t ms100, uint16_t px1kHz, LCD_DISCO_F746NG *lcd)
+    {
+        const uint16_t TICK = 5;    // 目盛線の長さ
+        // 横標軸
+        lcd->SetTextColor(axisColor);
+        lcd->DrawHLine(x0, y0+TICK, w0);
+        for (int n=0; n<=w0/ms100; n++)
+            if ((n % 10)== 0) lcd->DrawVLine(x0+n*ms100, y0, 5);
+            else              lcd->DrawVLine(x0+n*ms100, y0+3, 2);
+        for (int n=0; n<=w0/ms100; n+=10)
+            NumericLabel<int> num(x0+n*ms100, y0+TICK+3,
+                                  "%1d", (int)(n*0.1f), Label::CENTER);
+        Label time(x0+w0/2, y0+22, "TIME [s]", Label::CENTER);
+    
+        // 縦標軸
+        lcd->SetTextColor(axisColor);
+        lcd->DrawVLine(x0-TICK, y0-h0, h0);
+        for (int n=0; n<=h0/px1kHz; n++)
+            lcd->DrawHLine(x0-TICK, y0-n*px1kHz, TICK);
+        for (int n=0; n<=h0/px1kHz; n++)
+            NumericLabel<int> num(x0-TICK-12, y0-n*px1kHz-5, "%1d", n);
+        Label hz(x0-32, y0-5*px1kHz-20, "[kHz]");
+    }
+
+    // 色と dB の関係の表示
+    void ColorDb(int y0, uint32_t axisColor, LCD_DISCO_F746NG *lcd)
+    {
+        lcd->SetTextColor(axisColor);
+        lcd->DrawVLine(455, y0-100, 100);
+        for (int n=0; n<=8; n++)
+            lcd->DrawHLine(455, y0-(n*100)/8, 4);
+        for (int n=0; n<=4; n++)
+            NumericLabel<int> num(440, y0-(n*100)/4-5, "%2d", n*20);
+        Label dB(432, y0-120, "[dB]");
+
+        for (int n=0; n<=100; n++)
+        {
+            lcd->SetTextColor(HueScale(n/100.0f));
+            lcd->DrawHLine(460, y0-n, 16);
+        }
+    }
+
+    // スペクトルの更新
+    void SpectrumUpdate(Matrix<uint32_t> &x, FftAnalyzer &analyzer,
+                        const Array<float> &sn, const Array<float> &db)
+    {
+        // 過去のスペクトルを一つずらす
+        for (int n=0; n<x.Rows()-1; n++)
+            for (int k=0; k<x.Cols(); k++)
+                x[n][k] = x[n+1][k];
+
+        // 新しいスペクトル
+        analyzer.Execute(sn, db);
+        const float FACTOR = 1.0f/80.0f;    // 表示範囲: 0 ~ 80 dB
+        for (int k=0; k<=x.Cols(); k++)
+            x[x.Rows()-1][k] = HueScale(FACTOR*((db[k] > 20) ? db[k]-20 : 0));
+    }
+
+    // スペクトルの表示
+    void DisplaySpectrum(const Matrix<uint32_t> &x, int x0, int y0,
+                         int hBar, LCD_DISCO_F746NG *lcd)
+    {
+        for (int n=0; n<x.Rows(); n++)
+            for (int k=0; k<x.Cols(); k++)
+            {
+                lcd->SetTextColor(x[n][k]);
+                lcd->DrawHLine(x0+n*hBar, y0-k, hBar);
+            }
+    }
+}
+#endif  // METHOD_COLLECTION_HPP
diff -r 000000000000 -r e608fc311e4e TS_DISCO_F746NG.lib --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/TS_DISCO_F746NG.lib Sun Feb 05 07:49:54 2017 +0000 @@ -0,0 +1,1 @@ +https://developer.mbed.org/teams/ST/code/TS_DISCO_F746NG/#fe0cf5e2960f
diff -r 000000000000 -r e608fc311e4e UIT_FFT_Real.lib --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/UIT_FFT_Real.lib Sun Feb 05 07:49:54 2017 +0000 @@ -0,0 +1,1 @@ +http://mbed.org/users/MikamiUitOpen/code/UIT_FFT_Real/#9649d0e2bb4a
diff -r 000000000000 -r e608fc311e4e main.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/main.cpp	Sun Feb 05 07:49:54 2017 +0000
@@ -0,0 +1,564 @@
+/*
+ * mbed program / cwdecoder using the FFT Algorithm
+ *   tested on DISCO-F746G mbed board
+ *
+ *  Modified by Kenji Arai
+ *      http://www.page.sannet.ne.jp/kenjia/index.html
+ *      http://mbed.org/users/kenjiArai/
+ *
+ *      Started:  January  28th, 2017
+ *      Revised:  Feburary  5th, 2017
+ *
+ *  Reference program:
+ *  1)  2016/10/02, Copyright (c) 2016 MIKAMI, Naoki
+ *      https://developer.mbed.org/users/MikamiUitOpen/code/F746_Spectrogram/
+ *  2)  http://skovholm.com/cwdecoder
+ *      by Hjalmar Skovholm Hansen OZ1JHM
+ */
+ 
+//  Include --------------------------------------------------------------------
+#include "mbed.h"
+#include "SAI_InOut.hpp"
+#include "F746_GUI.hpp"
+#include "Matrix.hpp"
+#include "NumericLabel.hpp"
+#include "FFT_Analysis.hpp"
+#include "MethodCollection.hpp"
+
+#warning "If you would like to run this program, you need modify mbed revision."
+#warning "Please set mbed revision 131 (dated on Dec. 15, 2016)"
+
+//  Definition -----------------------------------------------------------------
+//#define METHOD_COLLECTION_HPP   // MethodCollection.hpp will NOT use
+
+#define HIGH            1
+#define LOW             0
+#define MILLIS()        t.read_ms()
+
+#define ONE_LINE        34
+#define LINES           11
+#define WORK_LINE       LINES
+#define TOTAL_CHAR      (ONE_LINE * LINES)
+
+#define USE_COM
+//#define USE_DEBUG
+
+#ifdef USE_COM
+#define BAUD(x)         pc.baud(x)
+#define GETC(x)         pc.getc(x)
+#define PUTC(x)         pc.putc(x)
+#define PRINTF(...)     pc.printf(__VA_ARGS__)
+#define READABLE(x)     pc.readable(x)
+#else
+#define BAUD(x)         {;}
+#define GETC(x)         {;}
+#define PUTC(x)         {;}
+#define PRINTF(...)     {;}
+#define READABLE(x)     {;}
+#endif
+
+#ifdef USE_DEBUG
+#define DEBUG(...)      pc.printf(__VA_ARGS__)
+#else
+#define DEBUG(...)      {;}
+#endif
+
+using namespace Mikami;
+
+//  ROM / Constant data --------------------------------------------------------
+const int FS     = I2S_AUDIOFREQ_32K;
+const int N_FFT  = 512;
+#define SLOT_750HZ 12       // 32KHz /512 * 12 = 750Hz
+
+char *const open_msg[] = {
+    "Center freq.:       750 Hz",
+    "Sampling freq.       32 kHz",   
+    "FFT / # of points:  512",
+    "Two modes ",
+    "(1) CW / MORSE Decoder",
+    "(2) Show Spectram"
+};
+
+//  RAM ------------------------------------------------------------------------
+float       magnitude ;
+int16_t     magnitudelimit      = 100;
+int16_t     magnitudelimit_low  = 100;
+int16_t     realstate = LOW;
+int16_t     realstatebefore     = LOW;
+int16_t     filteredstate       = LOW;
+int16_t     filteredstatebefore = LOW;
+int16_t     nbtime              = 2;         // ms noise blanker         
+int32_t     starttimehigh;
+int32_t     highduration;
+int32_t     lasthighduration;
+int32_t     hightimesavg;
+int32_t     lowtimesavg;
+int32_t     startttimelow;
+int32_t     lowduration;
+int32_t     laststarttime       = 0;
+char        code[32];
+int16_t     stop                = LOW;
+int16_t     wpm;
+uint32_t    cycle               = 0;
+uint8_t     msg_lcd[LINES + 1][48];
+uint8_t     num_last_line       = 0;
+Array<float> sn(N_FFT+1);
+Array<float> db(N_FFT/2+1);
+LCD_DISCO_F746NG *lcd = GuiBase::GetLcdPtr();
+
+//  Object ---------------------------------------------------------------------
+Timer       t;
+DigitalOut  myled(LED1);
+DigitalOut  data_in(D5);
+DigitalOut  loop_trg(D6);
+DigitalOut  out_code(D7);
+Serial      pc(USBTX, USBRX);
+SaiIO       mySai(SaiIO::INPUT, N_FFT+1, FS, INPUT_DEVICE_DIGITAL_MICROPHONE_2);
+FftAnalyzer fftAnalyzer(N_FFT+1, N_FFT);
+
+//  Function prototypes --------------------------------------------------------
+void    setup(void);
+void    loop(void);
+void    docode(void);
+void    printascii(char);
+void    adc_convert(void);
+float   SpectrumUpdate(FftAnalyzer &analyzer,
+        const Array<float> &sn, const Array<float> &db);
+void    cw_decoder(void);
+void    spectrogram(void);
+uint8_t mode_slect(void);
+void    spectrum(void);
+//------------------------------------------------------------------------------
+//  Control Program
+//------------------------------------------------------------------------------
+int main()
+{
+    while (true){
+        lcd->Clear(GuiBase::ENUM_BACK);
+        uint8_t n = mode_slect();
+        switch (n){
+            case 0:
+                cw_decoder();
+                break;
+            case 1:
+                spectrum();
+                break;
+            default:
+                break;
+        }
+    }
+}
+
+uint8_t mode_slect()
+{
+    Label obj0(240, 2, "Operationg Mode",
+               Label::CENTER, Font24, LCD_COLOR_LIGHTGREEN);
+    Label obj1(40,  30, open_msg[0], Label::LEFT, Font20);
+    Label obj2(40,  50, open_msg[1], Label::LEFT, Font20);
+    Label obj3(40,  70, open_msg[2], Label::LEFT, Font20);
+    Label obj4(40, 100, open_msg[3], Label::LEFT, Font20, LCD_COLOR_LIGHTGREEN);
+    Label obj5(70, 120, open_msg[4], Label::LEFT, Font20, LCD_COLOR_LIGHTGREEN);
+    Label obj6(70, 140, open_msg[5], Label::LEFT, Font20, LCD_COLOR_LIGHTGREEN);
+    Button button0( 50, 200, 180, 50, "CW/MORSE", Font24);
+    Button button1(260, 200, 180, 50, "SPECTRAM", Font24);
+    while (true){
+        if (button0.Touched()){     return 0UL;}
+        if (button1.Touched()){     return 1UL;}
+        wait(0.02f);
+    }
+}
+
+void spectrogram()
+{
+    lcd->Clear(GuiBase::ENUM_BACK);
+    PRINTF("\r\nFFT Spectroram\r\n");
+    Button button10(380, 240, 80, 30, "MENUE", Font16);
+        spectrum();
+        if (button10.Touched()){     return;}
+}
+
+void cw_decoder()
+{
+    lcd->Clear(GuiBase::ENUM_BACK);
+    PRINTF("\r\nCW Decoder(FFT) by JH1PJL\r\n");
+    Label myLabel1(120, 250, "CW Decoder(FFT) by JH1PJL",
+                    Label::CENTER, Font16);
+    Button button20(380, 240, 80, 30, "MENUE", Font16);
+    printf("Sys=%u\r\n", SystemCoreClock);
+    lcd->SetTextColor(LCD_COLOR_GREEN);
+    lcd->SetFont(&Font20);
+    mySai.RecordIn();
+    t.start();
+    while (true){
+        loop_trg = !loop_trg;
+        data_in = 1;
+        while (mySai.IsCaptured() == false){;}
+        for (int n=0; n<mySai.GetLength(); n++){
+            int16_t xL, xR;
+            mySai.Input(xL, xR);
+            sn[n] = (float)xL;
+        }
+        data_in = 0;
+        //magnitude = SpectrumUpdate(spectra, fftAnalyzer, sn, db);
+        magnitude = SpectrumUpdate(fftAnalyzer, sn, db);
+        //printf("%f\r\n", magnitude);
+        if (magnitude > magnitudelimit_low){ // magnitude limit automatic
+            magnitudelimit =    // moving average filter
+                    (magnitudelimit +((magnitude - magnitudelimit) / 6.0f));
+        }
+        if (magnitudelimit < magnitudelimit_low){
+            magnitudelimit = magnitudelimit_low;
+        }
+        // check for the magnitude
+        if(magnitude > magnitudelimit * 0.9f){ // just to have some space up 
+            realstate = HIGH; 
+        } else {
+            realstate = LOW;
+        }
+        // clean up the state with a noise blanker
+        if (realstate != realstatebefore){
+            laststarttime = MILLIS();
+        }
+        if ((MILLIS()-laststarttime)> nbtime){
+            if (realstate != filteredstate){
+                filteredstate = realstate;
+            }
+        }
+        // durations on high and low
+        if (filteredstate != filteredstatebefore){
+            if (filteredstate == HIGH){
+                starttimehigh = MILLIS();
+                lowduration = (MILLIS() - startttimelow);
+            }
+            if (filteredstate == LOW){
+                startttimelow = MILLIS();
+                highduration = (MILLIS() - starttimehigh);
+                if (highduration < (2.0f *hightimesavg) || hightimesavg == 0.0f){
+                    // now we know avg dit time ( rolling 3 avg)
+                    hightimesavg = (highduration+hightimesavg+hightimesavg) / 3.0f;
+                }
+                if (highduration > (5.0f * hightimesavg) ){
+                    // if speed decrease fast ..
+                    hightimesavg = highduration+hightimesavg;
+                }
+            }
+        }
+        // now we will check which kind of baud we have - dit or dah
+        // and what kind of pause we do have 1 - 3 or 7 pause
+        // we think that hightimeavg = 1 bit
+        if (filteredstate != filteredstatebefore){
+            stop = LOW;
+            if (filteredstate == LOW){  //// we did end a HIGH
+                // 0.6 filter out false dits
+                if (highduration < (hightimesavg * 2.0f)
+                     && highduration > (hightimesavg * 0.6f)){ 
+                    strcat(code,".");
+                    DEBUG(".");
+                }
+                if (highduration > (hightimesavg*2)
+                     && highduration < (hightimesavg * 6.0f)){ 
+                    strcat(code,"-");
+                    DEBUG("-");
+                    wpm = (wpm + (1200/((highduration)/3)))/2;
+                }
+            }
+            if (filteredstate == HIGH){  // we did end a LOW
+                float lacktime = 1;
+                //  when high speeds we have to have a little more pause
+                //  before new letter or new word
+                if(wpm > 25){   lacktime = 1.0f;} 
+                if(wpm > 30){   lacktime = 1.2f;}
+                if(wpm > 35){   lacktime = 1.5f;}
+                if(wpm > 40){   lacktime = 1.7f;}
+                if(wpm > 45){   lacktime = 1.9f;}
+                if(wpm > 50){   lacktime = 2.0f;}
+                if (lowduration > (hightimesavg*(2.0f * lacktime))
+                            && lowduration < hightimesavg*(5.0f * lacktime)){
+                    docode();
+                    code[0] = '\0';
+                    DEBUG("/");
+                }
+                if (lowduration >= hightimesavg*(5.0f * lacktime)){ // word space
+                    docode();
+                    code[0] = '\0';
+                    printascii(' ');
+                    DEBUG("\r\n");
+                }
+            }
+        }
+        // write if no more letters
+        if ((MILLIS() - startttimelow) > (highduration * 6.0f) && stop == LOW){
+            docode();
+            code[0] = '\0';
+            stop = HIGH;
+        }
+        // we will turn on and off the LED
+        // and the speaker
+        if(filteredstate == HIGH){ 
+            myled = HIGH;
+        } else {
+            myled = LOW;
+        }
+        // the end of main loop clean up
+        realstatebefore = realstate;
+        lasthighduration = highduration;
+        filteredstatebefore = filteredstate;
+        DEBUG("%d\r\n", t.read_ms());
+        // return to menue or continue
+        if (button20.Touched()){     return;}
+    }
+}
+
+float SpectrumUpdate(FftAnalyzer &analyzer,
+                    const Array<float> &sn, const Array<float> &db)
+{
+    analyzer.Execute(sn, db);
+    return (db[SLOT_750HZ] - 20) * 2;
+}
+
+// translate cw code to ascii
+void docode()
+{
+    //PRINTF("decording<%s>", code);
+    if (code[0] == '.'){             // .
+        if (code[1] == '.'){         // ..
+            if (code[2] == '.'){     // ...
+                if (code[3] == '.'){ // ....
+                    if (strcmp(code,"...."   ) == 0){ printascii('H'); return;}
+                    if (strcmp(code,"....."  ) == 0){ printascii('5'); return;}
+                    if (strcmp(code,"....-"  ) == 0){ printascii('4'); return;}
+                } else if (code[3] == '-'){     // ...-
+                    if (code[4] == '.'){        // ...-.
+                        if (strcmp(code,"...-."  ) == 0)
+                                                    { printascii(126); return;}
+                        if (strcmp(code,"...-.-" ) == 0)
+                                                    { printascii(62);  return;}
+                        if (strcmp(code,"...-..-") == 0)
+                                                    { printascii(36);  return;}
+                    } else if (code[4] == '-'){ // ...--
+                        if (strcmp(code,"...--"  ) == 0)
+                                                    { printascii('3'); return;}
+                    } else {
+                        if (strcmp(code,"...-"   ) == 0)
+                                                    { printascii('V'); return;} 
+                    }
+                } else {                        // ...
+                    if (strcmp(code,"..."    ) == 0){ printascii('S'); return;}
+                }
+            } else if (code[2] == '-'){ // ..-
+                if (strcmp(code,"..-"    ) == 0){ printascii('U');  return;}
+                if (strcmp(code,"..-."   ) == 0){ printascii('F');  return;}
+                if (strcmp(code,"..---"  ) == 0){ printascii('2');  return;}
+                if (strcmp(code,"..--.." ) == 0){ printascii(63);   return;}
+            } else {                    // ..
+                if (strcmp(code,".."      ) == 0){ printascii('I');  return;}
+            }
+        } else if (code[1] == '-'){         // .-
+            if (code[2] == '.'){            // .-.
+                if (code[3] == '.'){        // .-..
+                    if (strcmp(code,".-.."   ) == 0){ printascii('L'); return;}
+                    if (strcmp(code,".-..."  ) == 0){ printascii(95);  return;}
+                } else if (code[3] == '-'){ // .-.-
+                    if (strcmp(code,".-.-"   ) == 0){ printascii(3);   return;}
+                    if (strcmp(code,".-.-."  ) == 0){ printascii(60);  return;}
+                    if (strcmp(code,".-.-.-" ) == 0){ printascii(46);  return;}
+                } else {                    // .-.
+                    if (strcmp(code,".-."    ) == 0){ printascii('R'); return;}
+                }
+            } else if (code[2] == '-'){     // .--
+                if (code[3] == '.'){        // .--.
+                    if (strcmp(code,".--."   ) == 0){ printascii('P'); return;}
+                    if (strcmp(code,".--.-"  ) == 0){ printascii('-'); return;}
+                    if (strcmp(code,".--.-." ) == 0){ printascii(64);  return;}
+                } else if (code[3] == '-'){ // .---
+                    if (strcmp(code,".---"   ) == 0){ printascii('J'); return;}
+                    if (strcmp(code,".----"  ) == 0){ printascii('1'); return;}
+                } else {                    // .--
+                    if (strcmp(code,".--"    ) == 0){ printascii('W'); return;}
+                }
+            } else {                        // .-
+                if (strcmp(code,".-") == 0){ printascii('A'); return;}
+            }
+        } else {    // .
+            if (strcmp(code,".") == 0){ printascii('E'); return;}
+        }
+    } else if (code[0] == '-'){             // -
+        if (code[1] == '.'){                // -.
+            if (code[2] == '.'){            // -..
+                if (code[3] == '.'){        // -...
+                    if (strcmp(code,"-..."   ) == 0){ printascii('B'); return;}
+                    if (strcmp(code,"-...."  ) == 0){ printascii('6'); return;}
+                    if (strcmp(code,"-....-" ) == 0){ printascii('-'); return;}
+                } else if (code[3] == '-'){ // -..-
+                    if (strcmp(code,"-..-"   ) == 0){ printascii('X'); return;}
+                    if (strcmp(code,"-..-."  ) == 0){ printascii(47);  return;}
+                } else {
+                    if (strcmp(code,"-.."    ) == 0){ printascii('D'); return;}
+                }
+            } else if (code[2] == '-'){     // -.-
+                if (code[3] == '.'){        // -.-.
+                    if (strcmp(code,"-.-."   ) == 0){ printascii('C'); return;}
+                    if (strcmp(code,"-.-.--" ) == 0){ printascii(33);  return;}
+                } else if (code[3] == '-'){ // -.--
+                    if (strcmp(code,"-.--"   ) == 0){ printascii('Y'); return;}
+                    if (strcmp(code,"-.--."  ) == 0){ printascii(40);  return;}
+                    if (strcmp(code,"-.--.-" ) == 0){ printascii(41);  return;}
+                } else {                    // -.-
+                    if (strcmp(code,"-.-"    ) == 0){ printascii('K'); return;}
+                }
+            } else {                        // -.
+                if (strcmp(code,"-.") == 0){ printascii('N'); return;}
+            }
+        } else if (code[1] == '-'){         // -
+            if (code[2] == '.'){            // --.
+                if (strcmp(code,"--."    ) == 0){ printascii('G'); return;}
+                if (strcmp(code,"--.."   ) == 0){ printascii('Z'); return;}
+                if (strcmp(code,"--.-"   ) == 0){ printascii('Q'); return;}
+                if (strcmp(code,"--..."  ) == 0){ printascii('7'); return;}
+                if (strcmp(code,"--..--" ) == 0){ printascii(44);  return;}                                         
+            } else if (code[2] == '-'){     // ---
+                if (code[3] == '.'){        // ---.
+                    if (strcmp(code,"---.."  ) == 0){ printascii('8'); return;}
+                    if (strcmp(code,"---."   ) == 0){ printascii(4);   return;}
+                    if (strcmp(code,"---..." ) == 0){ printascii(58);  return;}
+                } else if (code[3] == '-'){ // ----
+                    if (strcmp(code,"----."  ) == 0){ printascii('9'); return;}
+                    if (strcmp(code,"-----"  ) == 0){ printascii('0'); return;}
+                } else {                    // ---
+                    if (strcmp(code,"---"    ) == 0){ printascii('O'); return;}
+                } 
+            } else {        // --
+                if (strcmp(code,"--") == 0){ printascii('M'); return;}
+            }
+        } else {    // -
+            if (strcmp(code,"-") == 0){ printascii('T'); return;}
+        }
+    }   
+}
+
+void printascii(char c)
+{
+    uint8_t i,j;
+
+    out_code = 1;
+    PRINTF("%c", c);
+    msg_lcd[WORK_LINE][num_last_line++] = c;
+    if (num_last_line == ONE_LINE){
+        for (j = 0; j < LINES; j++){ // scroll one line
+            for (i =0; i < ONE_LINE; i++){
+                msg_lcd[j][i] = msg_lcd[j+1][i];
+            }
+        }
+        for (i =0; i < ONE_LINE; i++){  // Clear last line
+            msg_lcd[WORK_LINE][i] = ' ';
+        }
+        num_last_line = 0;
+        for (i =0; i < (WORK_LINE + 1); i++){
+            lcd->DisplayStringAtLine( i, &msg_lcd[i][0]);
+        }
+    } else {
+        lcd->DisplayStringAtLine(WORK_LINE, &msg_lcd[WORK_LINE][0]);
+    }
+    out_code = 0;
+}
+
+//------------------------------------------------
+//  リアルタイム・スペクトログラム
+//      入力: MEMS マイク
+//
+//  2016/10/02, Copyright (c) 2016 MIKAMI, Naoki
+//  modified by JH1PJL
+//------------------------------------------------
+void spectrum()
+{
+    const int FS = I2S_AUDIOFREQ_16K;   // 標本化周波数: 16 kHz
+    const int N_FFT = 512;              // FFT の点数
+    const float FRAME = (N_FFT/(float)FS)*1000.0f;  // 1 フレームに対応する時間(単位:ms)
+
+    const int X0    = 40;           // 表示領域の x 座標の原点
+    const int Y0    = 200;          // 表示領域の y 座標の原点
+    const int H0    = 160;          // 表示する際の周波数軸の長さ(5 kHz に対応)
+    const uint16_t PX_1KHZ = H0/5;  // 1 kHz に対応するピクセル数
+    const int W0    = 360;          // 横方向の全体の表示の幅(単位:ピクセル)
+    const int H_BAR = 2;            // 表示する際の 1 フレームに対応する横方向のピクセル数
+    const int SIZE_X = W0/H_BAR;
+    const uint16_t MS100 = 100*H_BAR/FRAME; // 100 ms に対応するピクセル数
+    const uint32_t AXIS_COLOR = LCD_COLOR_WHITE;//0xFFCCFFFF;
+    
+    Matrix<uint32_t> spectra(SIZE_X, H0+1, GuiBase::ENUM_BACK);
+
+    SaiIO mySai(SaiIO::INPUT, N_FFT+1, FS,
+                INPUT_DEVICE_DIGITAL_MICROPHONE_2);
+
+    LCD_DISCO_F746NG *lcd = GuiBase::GetLcdPtr();   // LCD 表示器のオブジェクト
+    lcd->Clear(GuiBase::ENUM_BACK);
+    Label myLabel1(240, 2, "Real-time spectrogram", Label::CENTER, Font16);
+
+    // ButtonGroup の設定
+    const uint16_t B_W = 50;
+    const uint16_t B_Y = 242;
+    const uint16_t B_H = 30;
+    const string RUN_STOP[3] = {"MENUE","RUN", "STOP"};
+    ButtonGroup runStop(285, B_Y, B_W, B_H, 3, RUN_STOP, 0, 0, 3, 1);
+    
+    Button clear(430, B_Y, B_W, B_H, "CLEAR");
+    clear.Inactivate();
+    // ButtonGroup の設定(ここまで)
+
+    // 座標軸
+    DrawAxis(X0, Y0, W0, H0, AXIS_COLOR, MS100, PX_1KHZ, lcd);
+
+    Array<float> sn(N_FFT+1);
+    Array<float> db(N_FFT/2+1);
+
+    // 色と dB の関係の表示
+    ColorDb(Y0, AXIS_COLOR, lcd);
+        
+    FftAnalyzer fftAnalyzer(N_FFT+1, N_FFT);
+
+    // ループ内で使う変数の初期化
+    int stop = 1;       // 0: run, 1: stop
+
+    while(!runStop.GetTouchedNumber(stop)) {}
+    // データ読み込み開始
+    mySai.RecordIn();
+  
+    while (true)
+    {
+        runStop.GetTouchedNumber(stop);
+
+        if (stop == 0){
+            NVIC_SystemReset();
+        }
+        else if (stop == 1)
+        {
+            clear.Inactivate();
+            if (mySai.IsCaptured())
+            {
+                // 1フレーム分の信号の入力
+                for (int n=0; n<mySai.GetLength(); n++)
+                {
+                    int16_t xL, xR;
+                    mySai.Input(xL, xR);
+                    sn[n] = (float)xL;
+                }
+                //mySai.ResetCaptured();
+
+                // スペクトルの更新
+                SpectrumUpdate(spectra, fftAnalyzer, sn, db);
+                // スペクトルの表示
+                DisplaySpectrum(spectra, X0, Y0, H_BAR, lcd);
+            }
+        }
+        else if (stop == 2)
+        {
+            if (!clear.IsActive()) clear.Activate();
+            if (clear.Touched())
+            {
+                spectra.Fill(GuiBase::ENUM_BACK);   // スペクトルの表示をクリア
+                DisplaySpectrum(spectra, X0, Y0, H_BAR, lcd);
+                clear.Draw();
+            }
+        }
+    }
+}
diff -r 000000000000 -r e608fc311e4e mbed.bld --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mbed.bld Sun Feb 05 07:49:54 2017 +0000 @@ -0,0 +1,1 @@ +http://mbed.org/users/mbed_official/code/mbed/builds/faff56e089b2 \ No newline at end of file