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
--- /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
--- /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
--- /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
--- /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
--- /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);
+ }
+}
--- /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
+
--- /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]));
+ }
+}
--- /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
--- /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
--- /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
--- /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
--- /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
--- /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();
+ }
+ }
+ }
+}
--- /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