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