CW Decoder (Morse code decoder) 1st release version. Only run on Nucleo-F446RE mbed board.

Dependencies:   Array_Matrix F446_AD_DA ST7565_SPI_LCD TextLCD UIT_FFT_Real

Fork of F446_MySoundMachine by 不韋 呂

Base on F446_MySoundMachine program created by 不韋 呂-san.
Thanks to 不韋 呂-san making fundamental part such as FFT and ADC high speed interrupt driven program.
I just combined LCD and show CW code.

Committer:
kenjiArai
Date:
Sun Feb 05 08:02:54 2017 +0000
Revision:
6:5e21ac9f0550
Parent:
5:503bd366fd73
CW Decoder (Morse code decoder) 1st release version.  Only run on Nucleo-F446RE mbed board.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
kenjiArai 6:5e21ac9f0550 1 /*
kenjiArai 6:5e21ac9f0550 2 * mbed program / cwdecoder using the FFT Algorithm
kenjiArai 6:5e21ac9f0550 3 * tested on Nucleo-F446RE mbed board
kenjiArai 6:5e21ac9f0550 4 *
kenjiArai 6:5e21ac9f0550 5 * Modified by Kenji Arai
kenjiArai 6:5e21ac9f0550 6 * http://www.page.sannet.ne.jp/kenjia/index.html
kenjiArai 6:5e21ac9f0550 7 * http://mbed.org/users/kenjiArai/
kenjiArai 6:5e21ac9f0550 8 *
kenjiArai 6:5e21ac9f0550 9 * Started: Feburary 1st, 2017
kenjiArai 6:5e21ac9f0550 10 * Revised: Feburary 5th, 2017
kenjiArai 6:5e21ac9f0550 11 *
kenjiArai 6:5e21ac9f0550 12 * Reference program:
kenjiArai 6:5e21ac9f0550 13 * 1) 2016/10/02, Copyright (c) 2016 MIKAMI, Naoki
kenjiArai 6:5e21ac9f0550 14 * https://developer.mbed.org/users/MikamiUitOpen/code/F746_Spectrogram/
kenjiArai 6:5e21ac9f0550 15 * 2017/01/31, Copyright (c) 2017 MIKAMI, Naoki
kenjiArai 6:5e21ac9f0550 16 * https://developer.mbed.org/users/MikamiUitOpen/code/F446_MySoundMachine/
kenjiArai 6:5e21ac9f0550 17 * 2) http://skovholm.com/cwdecoder
kenjiArai 6:5e21ac9f0550 18 * by Hjalmar Skovholm Hansen OZ1JHM
kenjiArai 6:5e21ac9f0550 19 */
kenjiArai 6:5e21ac9f0550 20
kenjiArai 6:5e21ac9f0550 21 // Include --------------------------------------------------------------------
kenjiArai 6:5e21ac9f0550 22 #include "mbed.h"
kenjiArai 6:5e21ac9f0550 23 #include "Matrix.hpp"
kenjiArai 6:5e21ac9f0550 24 #include "FFT_Analysis.hpp"
kenjiArai 6:5e21ac9f0550 25 #include "F446_ADC_Interrupt.hpp"
kenjiArai 6:5e21ac9f0550 26 #include "TextLCD.h"
kenjiArai 6:5e21ac9f0550 27 #include "ST7565_SPI_LCD.h"
kenjiArai 6:5e21ac9f0550 28
kenjiArai 6:5e21ac9f0550 29 // Definition -----------------------------------------------------------------
kenjiArai 6:5e21ac9f0550 30 #define METHOD_COLLECTION_HPP // MethodCollection.hpp will NOT use
MikamiUitOpen 0:fa74b1130cc3 31
kenjiArai 6:5e21ac9f0550 32 #define HIGH 1
kenjiArai 6:5e21ac9f0550 33 #define LOW 0
kenjiArai 6:5e21ac9f0550 34 #define MILLIS() t.read_ms()
kenjiArai 6:5e21ac9f0550 35
kenjiArai 6:5e21ac9f0550 36 #define ONE_LINE 20
kenjiArai 6:5e21ac9f0550 37 #define LINES 4
kenjiArai 6:5e21ac9f0550 38
kenjiArai 6:5e21ac9f0550 39 #define USE_COM
kenjiArai 6:5e21ac9f0550 40 //#define USE_DEBUG
kenjiArai 6:5e21ac9f0550 41
kenjiArai 6:5e21ac9f0550 42 #ifdef USE_COM
kenjiArai 6:5e21ac9f0550 43 #define BAUD(x) pc.baud(x)
kenjiArai 6:5e21ac9f0550 44 #define GETC(x) pc.getc(x)
kenjiArai 6:5e21ac9f0550 45 #define PUTC(x) pc.putc(x)
kenjiArai 6:5e21ac9f0550 46 #define PRINTF(...) pc.printf(__VA_ARGS__)
kenjiArai 6:5e21ac9f0550 47 #define READABLE(x) pc.readable(x)
kenjiArai 6:5e21ac9f0550 48 #else
kenjiArai 6:5e21ac9f0550 49 #define BAUD(x) {;}
kenjiArai 6:5e21ac9f0550 50 #define GETC(x) {;}
kenjiArai 6:5e21ac9f0550 51 #define PUTC(x) {;}
kenjiArai 6:5e21ac9f0550 52 #define PRINTF(...) {;}
kenjiArai 6:5e21ac9f0550 53 #define READABLE(x) {;}
kenjiArai 6:5e21ac9f0550 54 #endif
kenjiArai 6:5e21ac9f0550 55
kenjiArai 6:5e21ac9f0550 56 #ifdef USE_DEBUG
kenjiArai 6:5e21ac9f0550 57 #define DEBUG(...) pc.printf(__VA_ARGS__)
kenjiArai 6:5e21ac9f0550 58 #else
kenjiArai 6:5e21ac9f0550 59 #define DEBUG(...) {;}
kenjiArai 6:5e21ac9f0550 60 #endif
kenjiArai 6:5e21ac9f0550 61
MikamiUitOpen 0:fa74b1130cc3 62 using namespace Mikami;
MikamiUitOpen 0:fa74b1130cc3 63
kenjiArai 6:5e21ac9f0550 64 // ROM / Constant data --------------------------------------------------------
kenjiArai 6:5e21ac9f0550 65 const int FS = 48000;
kenjiArai 6:5e21ac9f0550 66 const int N_FFT = 512;
kenjiArai 6:5e21ac9f0550 67 #define SLOT_750HZ 8 // 48KHz /512 * 8 = 750Hz
kenjiArai 6:5e21ac9f0550 68
kenjiArai 6:5e21ac9f0550 69 /* Tried other conditions
kenjiArai 6:5e21ac9f0550 70 #if 0
kenjiArai 6:5e21ac9f0550 71 const int FS = 24000;
kenjiArai 6:5e21ac9f0550 72 const int N_FFT = 256;
kenjiArai 6:5e21ac9f0550 73 #define SLOT_750HZ 8 // 24KHz /256 * 8 = 750Hz
kenjiArai 6:5e21ac9f0550 74 #endif
kenjiArai 6:5e21ac9f0550 75 #if 0
kenjiArai 6:5e21ac9f0550 76 const int FS = 48000;
kenjiArai 6:5e21ac9f0550 77 const int N_FFT = 256;
kenjiArai 6:5e21ac9f0550 78 #define SLOT_750HZ 4 // 48KHz /256 * 4 = 750Hz
kenjiArai 6:5e21ac9f0550 79 #endif
kenjiArai 6:5e21ac9f0550 80 */
MikamiUitOpen 0:fa74b1130cc3 81
kenjiArai 6:5e21ac9f0550 82 // RAM ------------------------------------------------------------------------
kenjiArai 6:5e21ac9f0550 83 float magnitude ;
kenjiArai 6:5e21ac9f0550 84 int16_t magnitudelimit = 100;
kenjiArai 6:5e21ac9f0550 85 int16_t magnitudelimit_low = 100;
kenjiArai 6:5e21ac9f0550 86 int16_t realstate = LOW;
kenjiArai 6:5e21ac9f0550 87 int16_t realstatebefore = LOW;
kenjiArai 6:5e21ac9f0550 88 int16_t filteredstate = LOW;
kenjiArai 6:5e21ac9f0550 89 int16_t filteredstatebefore = LOW;
kenjiArai 6:5e21ac9f0550 90 int16_t nbtime = 2; // ms noise blanker
kenjiArai 6:5e21ac9f0550 91 int32_t starttimehigh;
kenjiArai 6:5e21ac9f0550 92 int32_t highduration;
kenjiArai 6:5e21ac9f0550 93 int32_t lasthighduration;
kenjiArai 6:5e21ac9f0550 94 int32_t hightimesavg;
kenjiArai 6:5e21ac9f0550 95 int32_t lowtimesavg;
kenjiArai 6:5e21ac9f0550 96 int32_t startttimelow;
kenjiArai 6:5e21ac9f0550 97 int32_t lowduration;
kenjiArai 6:5e21ac9f0550 98 int32_t laststarttime = 0;
kenjiArai 6:5e21ac9f0550 99 char code[32];
kenjiArai 6:5e21ac9f0550 100 int16_t stop = LOW;
kenjiArai 6:5e21ac9f0550 101 int16_t wpm;
kenjiArai 6:5e21ac9f0550 102 uint32_t cycle = 0;
kenjiArai 6:5e21ac9f0550 103 Array<float> sn(N_FFT+1);
kenjiArai 6:5e21ac9f0550 104 Array<float> db(N_FFT/2+1);
kenjiArai 6:5e21ac9f0550 105 uint16_t adc_bf0[N_FFT + 8];
kenjiArai 6:5e21ac9f0550 106 uint16_t adc_bf1[N_FFT + 8];
kenjiArai 6:5e21ac9f0550 107 uint8_t adc_select = 0;
kenjiArai 6:5e21ac9f0550 108 uint16_t bf0_n = 0;
kenjiArai 6:5e21ac9f0550 109 uint16_t bf1_n = 0;
kenjiArai 6:5e21ac9f0550 110 volatile bool adc_bf0_full = false;
kenjiArai 6:5e21ac9f0550 111 volatile bool adc_bf1_full = false;
kenjiArai 6:5e21ac9f0550 112 volatile bool adc_data_full = false;
kenjiArai 6:5e21ac9f0550 113 uint8_t msg_lcd[LINES][36];
kenjiArai 6:5e21ac9f0550 114 uint8_t num_last_line = 0;
MikamiUitOpen 0:fa74b1130cc3 115
kenjiArai 6:5e21ac9f0550 116
kenjiArai 6:5e21ac9f0550 117 // Object ---------------------------------------------------------------------
kenjiArai 6:5e21ac9f0550 118 Timer t;
kenjiArai 6:5e21ac9f0550 119 DigitalOut myled(LED1);
kenjiArai 6:5e21ac9f0550 120 DigitalOut morse(PC_4);
kenjiArai 6:5e21ac9f0550 121 DigitalOut irq_job(D4);
kenjiArai 6:5e21ac9f0550 122 DigitalOut data_in(D5);
kenjiArai 6:5e21ac9f0550 123 DigitalOut loop_trg(D6);
kenjiArai 6:5e21ac9f0550 124 DigitalOut out_code(D7);
kenjiArai 6:5e21ac9f0550 125 Serial pc(USBTX, USBRX);
kenjiArai 6:5e21ac9f0550 126 FftAnalyzer fftAnalyzer(N_FFT+1, N_FFT);
kenjiArai 6:5e21ac9f0550 127 AdcSingle_Intr Adc_in(FS);
kenjiArai 6:5e21ac9f0550 128 // rs, e, d4, d5, d6, d7
kenjiArai 6:5e21ac9f0550 129 TextLCD lcd(PB_0, PH_1, PC_0, PC_1, PC_2, PC_3, TextLCD::LCD20x4);
kenjiArai 6:5e21ac9f0550 130 // mosi, sck, reset, a0, ncs
kenjiArai 6:5e21ac9f0550 131 ST7565 glcd(PB_5, PB_3, PB_13, PB_14, PB_15, ST7565::AD12864SPI);
kenjiArai 6:5e21ac9f0550 132
kenjiArai 6:5e21ac9f0550 133 // Function prototypes --------------------------------------------------------
kenjiArai 6:5e21ac9f0550 134 void setup(void);
kenjiArai 6:5e21ac9f0550 135 void loop(void);
kenjiArai 6:5e21ac9f0550 136 void docode(void);
kenjiArai 6:5e21ac9f0550 137 void printascii(char);
kenjiArai 6:5e21ac9f0550 138 void adc_convert(void);
kenjiArai 6:5e21ac9f0550 139 float SpectrumUpdate(FftAnalyzer &analyzer,
kenjiArai 6:5e21ac9f0550 140 const Array<float> &sn, const Array<float> &db);
kenjiArai 6:5e21ac9f0550 141
kenjiArai 6:5e21ac9f0550 142 //------------------------------------------------------------------------------
kenjiArai 6:5e21ac9f0550 143 // Control Program
kenjiArai 6:5e21ac9f0550 144 //------------------------------------------------------------------------------
MikamiUitOpen 0:fa74b1130cc3 145 void AdcIsr()
MikamiUitOpen 0:fa74b1130cc3 146 {
kenjiArai 6:5e21ac9f0550 147 irq_job = 1;
kenjiArai 6:5e21ac9f0550 148 if (adc_select == 0){
kenjiArai 6:5e21ac9f0550 149 Adc_in.Read(adc_bf0[bf0_n]);
kenjiArai 6:5e21ac9f0550 150 bf0_n++;
kenjiArai 6:5e21ac9f0550 151 if (bf0_n >= N_FFT){
kenjiArai 6:5e21ac9f0550 152 adc_bf0_full = true;
kenjiArai 6:5e21ac9f0550 153 adc_select = 1;
kenjiArai 6:5e21ac9f0550 154 bf1_n = 0;
kenjiArai 6:5e21ac9f0550 155 }
kenjiArai 6:5e21ac9f0550 156 } else {
kenjiArai 6:5e21ac9f0550 157 Adc_in.Read(adc_bf1[bf1_n]);
kenjiArai 6:5e21ac9f0550 158 bf1_n++;
kenjiArai 6:5e21ac9f0550 159 if (bf1_n >= N_FFT){
kenjiArai 6:5e21ac9f0550 160 adc_bf1_full = true;
kenjiArai 6:5e21ac9f0550 161 adc_select = 0;
kenjiArai 6:5e21ac9f0550 162 bf0_n = 0;
kenjiArai 6:5e21ac9f0550 163 }
kenjiArai 6:5e21ac9f0550 164 }
kenjiArai 6:5e21ac9f0550 165 irq_job = 0;
MikamiUitOpen 0:fa74b1130cc3 166 }
MikamiUitOpen 0:fa74b1130cc3 167
MikamiUitOpen 0:fa74b1130cc3 168 int main()
MikamiUitOpen 0:fa74b1130cc3 169 {
kenjiArai 6:5e21ac9f0550 170 wait(1.0);
kenjiArai 6:5e21ac9f0550 171 lcd.locate(0, 0);
kenjiArai 6:5e21ac9f0550 172 lcd.printf("CW DECODER(FFT) V0.1");
kenjiArai 6:5e21ac9f0550 173 lcd.locate(0, 1);
kenjiArai 6:5e21ac9f0550 174 lcd.printf(" by JH1PJL Feb. 2017");
kenjiArai 6:5e21ac9f0550 175 lcd.locate(0, 2);
kenjiArai 6:5e21ac9f0550 176 lcd.printf("Center Freq = 750Hz ");
kenjiArai 6:5e21ac9f0550 177 lcd.locate(0, 3);
kenjiArai 6:5e21ac9f0550 178 lcd.printf(" ");
kenjiArai 6:5e21ac9f0550 179 glcd.cls();
kenjiArai 6:5e21ac9f0550 180 glcd.locate(0, 0);
kenjiArai 6:5e21ac9f0550 181 glcd.printf(" ----- CW DECODER -----\r\n");
kenjiArai 6:5e21ac9f0550 182 glcd.printf(" "__DATE__"("__TIME__")\r\n");
kenjiArai 6:5e21ac9f0550 183 glcd.printf(" Center freq. = 750Hz\r\n");
kenjiArai 6:5e21ac9f0550 184 glcd.printf(" mbed Nucleo-F446RE\r\n");
kenjiArai 6:5e21ac9f0550 185 glcd.printf(" Base: Demo_F446_AD_DA\r\n");
kenjiArai 6:5e21ac9f0550 186 glcd.printf(" Kenji Arai / JH1PJL\r\n" );
kenjiArai 6:5e21ac9f0550 187 glcd.printf(" kenjia@sannet.ne.jp ");
kenjiArai 6:5e21ac9f0550 188 PRINTF("\r\nCW Decoder(FFT) by JH1PJL\r\n");
kenjiArai 6:5e21ac9f0550 189 printf("Sys=%u\r\n", SystemCoreClock);
kenjiArai 6:5e21ac9f0550 190 Adc_in.SetIntrVec(&AdcIsr);
kenjiArai 6:5e21ac9f0550 191 t.start();
kenjiArai 6:5e21ac9f0550 192 while (true){
kenjiArai 6:5e21ac9f0550 193 loop_trg = !loop_trg;
kenjiArai 6:5e21ac9f0550 194 data_in = 1;
kenjiArai 6:5e21ac9f0550 195 adc_data_full = false;
kenjiArai 6:5e21ac9f0550 196 while (adc_data_full == false){
kenjiArai 6:5e21ac9f0550 197 if (adc_bf0_full == true){
kenjiArai 6:5e21ac9f0550 198 for (int n=0; n < N_FFT; n++){
kenjiArai 6:5e21ac9f0550 199 int32_t xData;
kenjiArai 6:5e21ac9f0550 200 xData = (int32_t)adc_bf0[n] - 0x00007fff;
kenjiArai 6:5e21ac9f0550 201 sn[n] = (float)xData;
kenjiArai 6:5e21ac9f0550 202 }
kenjiArai 6:5e21ac9f0550 203 adc_bf0_full = false;
kenjiArai 6:5e21ac9f0550 204 adc_data_full = true;
kenjiArai 6:5e21ac9f0550 205 } else if (adc_bf1_full == true){
kenjiArai 6:5e21ac9f0550 206 for (int n=0; n < N_FFT; n++){
kenjiArai 6:5e21ac9f0550 207 int32_t xData;
kenjiArai 6:5e21ac9f0550 208 xData = (int32_t)adc_bf1[n] - 0x00007fff;
kenjiArai 6:5e21ac9f0550 209 sn[n] = (float)xData;
MikamiUitOpen 0:fa74b1130cc3 210 }
kenjiArai 6:5e21ac9f0550 211 adc_bf1_full = false;
kenjiArai 6:5e21ac9f0550 212 adc_data_full = true;
kenjiArai 6:5e21ac9f0550 213 }
kenjiArai 6:5e21ac9f0550 214 }
kenjiArai 6:5e21ac9f0550 215 data_in = 0;
kenjiArai 6:5e21ac9f0550 216 //magnitude = SpectrumUpdate(spectra, fftAnalyzer, sn, db);
kenjiArai 6:5e21ac9f0550 217 magnitude = SpectrumUpdate(fftAnalyzer, sn, db);
kenjiArai 6:5e21ac9f0550 218 //printf("%f\r\n", magnitude);
kenjiArai 6:5e21ac9f0550 219 if (magnitude > magnitudelimit_low){ // magnitude limit automatic
kenjiArai 6:5e21ac9f0550 220 magnitudelimit = // moving average filter
kenjiArai 6:5e21ac9f0550 221 (magnitudelimit +((magnitude - magnitudelimit) / 6.0f));
kenjiArai 6:5e21ac9f0550 222 }
kenjiArai 6:5e21ac9f0550 223 if (magnitudelimit < magnitudelimit_low){
kenjiArai 6:5e21ac9f0550 224 magnitudelimit = magnitudelimit_low;
kenjiArai 6:5e21ac9f0550 225 }
kenjiArai 6:5e21ac9f0550 226 // check for the magnitude
kenjiArai 6:5e21ac9f0550 227 if(magnitude > magnitudelimit * 0.9f){ // just to have some space up
kenjiArai 6:5e21ac9f0550 228 realstate = HIGH;
kenjiArai 6:5e21ac9f0550 229 } else {
kenjiArai 6:5e21ac9f0550 230 realstate = LOW;
kenjiArai 6:5e21ac9f0550 231 }
kenjiArai 6:5e21ac9f0550 232 // clean up the state with a noise blanker
kenjiArai 6:5e21ac9f0550 233 if (realstate != realstatebefore){
kenjiArai 6:5e21ac9f0550 234 laststarttime = MILLIS();
kenjiArai 6:5e21ac9f0550 235 }
kenjiArai 6:5e21ac9f0550 236 if ((MILLIS()-laststarttime)> nbtime){
kenjiArai 6:5e21ac9f0550 237 if (realstate != filteredstate){
kenjiArai 6:5e21ac9f0550 238 filteredstate = realstate;
kenjiArai 6:5e21ac9f0550 239 }
kenjiArai 6:5e21ac9f0550 240 }
kenjiArai 6:5e21ac9f0550 241 // durations on high and low
kenjiArai 6:5e21ac9f0550 242 if (filteredstate != filteredstatebefore){
kenjiArai 6:5e21ac9f0550 243 if (filteredstate == HIGH){
kenjiArai 6:5e21ac9f0550 244 starttimehigh = MILLIS();
kenjiArai 6:5e21ac9f0550 245 lowduration = (MILLIS() - startttimelow);
kenjiArai 6:5e21ac9f0550 246 }
kenjiArai 6:5e21ac9f0550 247 if (filteredstate == LOW){
kenjiArai 6:5e21ac9f0550 248 startttimelow = MILLIS();
kenjiArai 6:5e21ac9f0550 249 highduration = (MILLIS() - starttimehigh);
kenjiArai 6:5e21ac9f0550 250 if (highduration < (2.0f *hightimesavg) || hightimesavg == 0.0f){
kenjiArai 6:5e21ac9f0550 251 // now we know avg dit time ( rolling 3 avg)
kenjiArai 6:5e21ac9f0550 252 hightimesavg = (highduration+hightimesavg+hightimesavg) / 3.0f;
kenjiArai 6:5e21ac9f0550 253 }
kenjiArai 6:5e21ac9f0550 254 if (highduration > (5.0f * hightimesavg) ){
kenjiArai 6:5e21ac9f0550 255 // if speed decrease fast ..
kenjiArai 6:5e21ac9f0550 256 hightimesavg = highduration+hightimesavg;
MikamiUitOpen 0:fa74b1130cc3 257 }
kenjiArai 6:5e21ac9f0550 258 }
kenjiArai 6:5e21ac9f0550 259 }
kenjiArai 6:5e21ac9f0550 260 // now we will check which kind of baud we have - dit or dah
kenjiArai 6:5e21ac9f0550 261 // and what kind of pause we do have 1 - 3 or 7 pause
kenjiArai 6:5e21ac9f0550 262 // we think that hightimeavg = 1 bit
kenjiArai 6:5e21ac9f0550 263 if (filteredstate != filteredstatebefore){
kenjiArai 6:5e21ac9f0550 264 stop = LOW;
kenjiArai 6:5e21ac9f0550 265 if (filteredstate == LOW){ //// we did end a HIGH
kenjiArai 6:5e21ac9f0550 266 // 0.6 filter out false dits
kenjiArai 6:5e21ac9f0550 267 if (highduration < (hightimesavg * 2.0f)
kenjiArai 6:5e21ac9f0550 268 && highduration > (hightimesavg * 0.6f)){
kenjiArai 6:5e21ac9f0550 269 strcat(code,".");
kenjiArai 6:5e21ac9f0550 270 DEBUG(".");
kenjiArai 6:5e21ac9f0550 271 }
kenjiArai 6:5e21ac9f0550 272 if (highduration > (hightimesavg*2)
kenjiArai 6:5e21ac9f0550 273 && highduration < (hightimesavg * 6.0f)){
kenjiArai 6:5e21ac9f0550 274 strcat(code,"-");
kenjiArai 6:5e21ac9f0550 275 DEBUG("-");
kenjiArai 6:5e21ac9f0550 276 wpm = (wpm + (1200/((highduration)/3)))/2;
kenjiArai 6:5e21ac9f0550 277 DEBUG("<%dwpm>", wpm);
MikamiUitOpen 0:fa74b1130cc3 278 }
kenjiArai 6:5e21ac9f0550 279 }
kenjiArai 6:5e21ac9f0550 280 if (filteredstate == HIGH){ // we did end a LOW
kenjiArai 6:5e21ac9f0550 281 float lacktime = 1;
kenjiArai 6:5e21ac9f0550 282 // when high speeds we have to have a little more pause
kenjiArai 6:5e21ac9f0550 283 // before new letter or new word
kenjiArai 6:5e21ac9f0550 284 if(wpm > 25){ lacktime = 1.0f;}
kenjiArai 6:5e21ac9f0550 285 if(wpm > 30){ lacktime = 1.2f;}
kenjiArai 6:5e21ac9f0550 286 if(wpm > 35){ lacktime = 1.5f;}
kenjiArai 6:5e21ac9f0550 287 if(wpm > 40){ lacktime = 1.8f;}
kenjiArai 6:5e21ac9f0550 288 if(wpm > 45){ lacktime = 2.2f;}
kenjiArai 6:5e21ac9f0550 289 if(wpm > 50){ lacktime = 2.5f;}
kenjiArai 6:5e21ac9f0550 290 if (lowduration > (hightimesavg*(2.0f * lacktime))
kenjiArai 6:5e21ac9f0550 291 && lowduration < hightimesavg*(5.0f * lacktime)){
kenjiArai 6:5e21ac9f0550 292 docode();
kenjiArai 6:5e21ac9f0550 293 code[0] = '\0';
kenjiArai 6:5e21ac9f0550 294 DEBUG("/");
kenjiArai 6:5e21ac9f0550 295 }
kenjiArai 6:5e21ac9f0550 296 if (lowduration >= hightimesavg*(5.0f * lacktime)){ // word space
kenjiArai 6:5e21ac9f0550 297 docode();
kenjiArai 6:5e21ac9f0550 298 code[0] = '\0';
kenjiArai 6:5e21ac9f0550 299 printascii(' ');
kenjiArai 6:5e21ac9f0550 300 DEBUG("\r\n");
kenjiArai 6:5e21ac9f0550 301 }
kenjiArai 6:5e21ac9f0550 302 }
MikamiUitOpen 0:fa74b1130cc3 303 }
kenjiArai 6:5e21ac9f0550 304 // write if no more letters
kenjiArai 6:5e21ac9f0550 305 if ((MILLIS() - startttimelow) > (highduration * 6.0f) && stop == LOW){
kenjiArai 6:5e21ac9f0550 306 docode();
kenjiArai 6:5e21ac9f0550 307 code[0] = '\0';
kenjiArai 6:5e21ac9f0550 308 stop = HIGH;
kenjiArai 6:5e21ac9f0550 309 }
kenjiArai 6:5e21ac9f0550 310 // we will turn on and off the LED
kenjiArai 6:5e21ac9f0550 311 // and the speaker
kenjiArai 6:5e21ac9f0550 312 if(filteredstate == HIGH){
kenjiArai 6:5e21ac9f0550 313 morse = HIGH;
kenjiArai 6:5e21ac9f0550 314 } else {
kenjiArai 6:5e21ac9f0550 315 morse = LOW;
kenjiArai 6:5e21ac9f0550 316 }
kenjiArai 6:5e21ac9f0550 317 // the end of main loop clean up
kenjiArai 6:5e21ac9f0550 318 realstatebefore = realstate;
kenjiArai 6:5e21ac9f0550 319 lasthighduration = highduration;
kenjiArai 6:5e21ac9f0550 320 filteredstatebefore = filteredstate;
kenjiArai 6:5e21ac9f0550 321 //DEBUG("%d\r\n", t.read_ms());
MikamiUitOpen 0:fa74b1130cc3 322 }
MikamiUitOpen 0:fa74b1130cc3 323 }
kenjiArai 6:5e21ac9f0550 324
kenjiArai 6:5e21ac9f0550 325 float SpectrumUpdate(FftAnalyzer &analyzer,
kenjiArai 6:5e21ac9f0550 326 const Array<float> &sn, const Array<float> &db)
kenjiArai 6:5e21ac9f0550 327 {
kenjiArai 6:5e21ac9f0550 328 analyzer.Execute(sn, db);
kenjiArai 6:5e21ac9f0550 329 return (db[SLOT_750HZ] - 20) * 2;
kenjiArai 6:5e21ac9f0550 330 }
kenjiArai 6:5e21ac9f0550 331
kenjiArai 6:5e21ac9f0550 332 // translate cw code to ascii
kenjiArai 6:5e21ac9f0550 333 void docode()
kenjiArai 6:5e21ac9f0550 334 {
kenjiArai 6:5e21ac9f0550 335 //PRINTF("decording<%s>", code);
kenjiArai 6:5e21ac9f0550 336 if (code[0] == '.'){ // .
kenjiArai 6:5e21ac9f0550 337 if (code[1] == '.'){ // ..
kenjiArai 6:5e21ac9f0550 338 if (code[2] == '.'){ // ...
kenjiArai 6:5e21ac9f0550 339 if (code[3] == '.'){ // ....
kenjiArai 6:5e21ac9f0550 340 if (strcmp(code,"...." ) == 0){ printascii('H'); return;}
kenjiArai 6:5e21ac9f0550 341 if (strcmp(code,"....." ) == 0){ printascii('5'); return;}
kenjiArai 6:5e21ac9f0550 342 if (strcmp(code,"....-" ) == 0){ printascii('4'); return;}
kenjiArai 6:5e21ac9f0550 343 } else if (code[3] == '-'){ // ...-
kenjiArai 6:5e21ac9f0550 344 if (code[4] == '.'){ // ...-.
kenjiArai 6:5e21ac9f0550 345 if (strcmp(code,"...-." ) == 0)
kenjiArai 6:5e21ac9f0550 346 { printascii(126); return;}
kenjiArai 6:5e21ac9f0550 347 if (strcmp(code,"...-.-" ) == 0)
kenjiArai 6:5e21ac9f0550 348 { printascii(62); return;}
kenjiArai 6:5e21ac9f0550 349 if (strcmp(code,"...-..-") == 0)
kenjiArai 6:5e21ac9f0550 350 { printascii(36); return;}
kenjiArai 6:5e21ac9f0550 351 } else if (code[4] == '-'){ // ...--
kenjiArai 6:5e21ac9f0550 352 if (strcmp(code,"...--" ) == 0)
kenjiArai 6:5e21ac9f0550 353 { printascii('3'); return;}
kenjiArai 6:5e21ac9f0550 354 } else {
kenjiArai 6:5e21ac9f0550 355 if (strcmp(code,"...-" ) == 0)
kenjiArai 6:5e21ac9f0550 356 { printascii('V'); return;}
kenjiArai 6:5e21ac9f0550 357 }
kenjiArai 6:5e21ac9f0550 358 } else { // ...
kenjiArai 6:5e21ac9f0550 359 if (strcmp(code,"..." ) == 0){ printascii('S'); return;}
kenjiArai 6:5e21ac9f0550 360 }
kenjiArai 6:5e21ac9f0550 361 } else if (code[2] == '-'){ // ..-
kenjiArai 6:5e21ac9f0550 362 if (strcmp(code,"..-" ) == 0){ printascii('U'); return;}
kenjiArai 6:5e21ac9f0550 363 if (strcmp(code,"..-." ) == 0){ printascii('F'); return;}
kenjiArai 6:5e21ac9f0550 364 if (strcmp(code,"..---" ) == 0){ printascii('2'); return;}
kenjiArai 6:5e21ac9f0550 365 if (strcmp(code,"..--.." ) == 0){ printascii(63); return;}
kenjiArai 6:5e21ac9f0550 366 } else { // ..
kenjiArai 6:5e21ac9f0550 367 if (strcmp(code,".." ) == 0){ printascii('I'); return;}
kenjiArai 6:5e21ac9f0550 368 }
kenjiArai 6:5e21ac9f0550 369 } else if (code[1] == '-'){ // .-
kenjiArai 6:5e21ac9f0550 370 if (code[2] == '.'){ // .-.
kenjiArai 6:5e21ac9f0550 371 if (code[3] == '.'){ // .-..
kenjiArai 6:5e21ac9f0550 372 if (strcmp(code,".-.." ) == 0){ printascii('L'); return;}
kenjiArai 6:5e21ac9f0550 373 if (strcmp(code,".-..." ) == 0){ printascii(95); return;}
kenjiArai 6:5e21ac9f0550 374 } else if (code[3] == '-'){ // .-.-
kenjiArai 6:5e21ac9f0550 375 if (strcmp(code,".-.-" ) == 0){ printascii(3); return;}
kenjiArai 6:5e21ac9f0550 376 if (strcmp(code,".-.-." ) == 0){ printascii(60); return;}
kenjiArai 6:5e21ac9f0550 377 if (strcmp(code,".-.-.-" ) == 0){ printascii(46); return;}
kenjiArai 6:5e21ac9f0550 378 } else { // .-.
kenjiArai 6:5e21ac9f0550 379 if (strcmp(code,".-." ) == 0){ printascii('R'); return;}
kenjiArai 6:5e21ac9f0550 380 }
kenjiArai 6:5e21ac9f0550 381 } else if (code[2] == '-'){ // .--
kenjiArai 6:5e21ac9f0550 382 if (code[3] == '.'){ // .--.
kenjiArai 6:5e21ac9f0550 383 if (strcmp(code,".--." ) == 0){ printascii('P'); return;}
kenjiArai 6:5e21ac9f0550 384 if (strcmp(code,".--.-" ) == 0){ printascii('-'); return;}
kenjiArai 6:5e21ac9f0550 385 if (strcmp(code,".--.-." ) == 0){ printascii(64); return;}
kenjiArai 6:5e21ac9f0550 386 } else if (code[3] == '-'){ // .---
kenjiArai 6:5e21ac9f0550 387 if (strcmp(code,".---" ) == 0){ printascii('J'); return;}
kenjiArai 6:5e21ac9f0550 388 if (strcmp(code,".----" ) == 0){ printascii('1'); return;}
kenjiArai 6:5e21ac9f0550 389 } else { // .--
kenjiArai 6:5e21ac9f0550 390 if (strcmp(code,".--" ) == 0){ printascii('W'); return;}
kenjiArai 6:5e21ac9f0550 391 }
kenjiArai 6:5e21ac9f0550 392 } else { // .-
kenjiArai 6:5e21ac9f0550 393 if (strcmp(code,".-") == 0){ printascii('A'); return;}
kenjiArai 6:5e21ac9f0550 394 }
kenjiArai 6:5e21ac9f0550 395 } else { // .
kenjiArai 6:5e21ac9f0550 396 if (strcmp(code,".") == 0){ printascii('E'); return;}
kenjiArai 6:5e21ac9f0550 397 }
kenjiArai 6:5e21ac9f0550 398 } else if (code[0] == '-'){ // -
kenjiArai 6:5e21ac9f0550 399 if (code[1] == '.'){ // -.
kenjiArai 6:5e21ac9f0550 400 if (code[2] == '.'){ // -..
kenjiArai 6:5e21ac9f0550 401 if (code[3] == '.'){ // -...
kenjiArai 6:5e21ac9f0550 402 if (strcmp(code,"-..." ) == 0){ printascii('B'); return;}
kenjiArai 6:5e21ac9f0550 403 if (strcmp(code,"-...." ) == 0){ printascii('6'); return;}
kenjiArai 6:5e21ac9f0550 404 if (strcmp(code,"-....-" ) == 0){ printascii('-'); return;}
kenjiArai 6:5e21ac9f0550 405 } else if (code[3] == '-'){ // -..-
kenjiArai 6:5e21ac9f0550 406 if (strcmp(code,"-..-" ) == 0){ printascii('X'); return;}
kenjiArai 6:5e21ac9f0550 407 if (strcmp(code,"-..-." ) == 0){ printascii(47); return;}
kenjiArai 6:5e21ac9f0550 408 } else {
kenjiArai 6:5e21ac9f0550 409 if (strcmp(code,"-.." ) == 0){ printascii('D'); return;}
kenjiArai 6:5e21ac9f0550 410 }
kenjiArai 6:5e21ac9f0550 411 } else if (code[2] == '-'){ // -.-
kenjiArai 6:5e21ac9f0550 412 if (code[3] == '.'){ // -.-.
kenjiArai 6:5e21ac9f0550 413 if (strcmp(code,"-.-." ) == 0){ printascii('C'); return;}
kenjiArai 6:5e21ac9f0550 414 if (strcmp(code,"-.-.--" ) == 0){ printascii(33); return;}
kenjiArai 6:5e21ac9f0550 415 } else if (code[3] == '-'){ // -.--
kenjiArai 6:5e21ac9f0550 416 if (strcmp(code,"-.--" ) == 0){ printascii('Y'); return;}
kenjiArai 6:5e21ac9f0550 417 if (strcmp(code,"-.--." ) == 0){ printascii(40); return;}
kenjiArai 6:5e21ac9f0550 418 if (strcmp(code,"-.--.-" ) == 0){ printascii(41); return;}
kenjiArai 6:5e21ac9f0550 419 } else { // -.-
kenjiArai 6:5e21ac9f0550 420 if (strcmp(code,"-.-" ) == 0){ printascii('K'); return;}
kenjiArai 6:5e21ac9f0550 421 }
kenjiArai 6:5e21ac9f0550 422 } else { // -.
kenjiArai 6:5e21ac9f0550 423 if (strcmp(code,"-.") == 0){ printascii('N'); return;}
kenjiArai 6:5e21ac9f0550 424 }
kenjiArai 6:5e21ac9f0550 425 } else if (code[1] == '-'){ // -
kenjiArai 6:5e21ac9f0550 426 if (code[2] == '.'){ // --.
kenjiArai 6:5e21ac9f0550 427 if (strcmp(code,"--." ) == 0){ printascii('G'); return;}
kenjiArai 6:5e21ac9f0550 428 if (strcmp(code,"--.." ) == 0){ printascii('Z'); return;}
kenjiArai 6:5e21ac9f0550 429 if (strcmp(code,"--.-" ) == 0){ printascii('Q'); return;}
kenjiArai 6:5e21ac9f0550 430 if (strcmp(code,"--..." ) == 0){ printascii('7'); return;}
kenjiArai 6:5e21ac9f0550 431 if (strcmp(code,"--..--" ) == 0){ printascii(44); return;}
kenjiArai 6:5e21ac9f0550 432 } else if (code[2] == '-'){ // ---
kenjiArai 6:5e21ac9f0550 433 if (code[3] == '.'){ // ---.
kenjiArai 6:5e21ac9f0550 434 if (strcmp(code,"---.." ) == 0){ printascii('8'); return;}
kenjiArai 6:5e21ac9f0550 435 if (strcmp(code,"---." ) == 0){ printascii(4); return;}
kenjiArai 6:5e21ac9f0550 436 if (strcmp(code,"---..." ) == 0){ printascii(58); return;}
kenjiArai 6:5e21ac9f0550 437 } else if (code[3] == '-'){ // ----
kenjiArai 6:5e21ac9f0550 438 if (strcmp(code,"----." ) == 0){ printascii('9'); return;}
kenjiArai 6:5e21ac9f0550 439 if (strcmp(code,"-----" ) == 0){ printascii('0'); return;}
kenjiArai 6:5e21ac9f0550 440 } else { // ---
kenjiArai 6:5e21ac9f0550 441 if (strcmp(code,"---" ) == 0){ printascii('O'); return;}
kenjiArai 6:5e21ac9f0550 442 }
kenjiArai 6:5e21ac9f0550 443 } else { // --
kenjiArai 6:5e21ac9f0550 444 if (strcmp(code,"--") == 0){ printascii('M'); return;}
kenjiArai 6:5e21ac9f0550 445 }
kenjiArai 6:5e21ac9f0550 446 } else { // -
kenjiArai 6:5e21ac9f0550 447 if (strcmp(code,"-") == 0){ printascii('T'); return;}
kenjiArai 6:5e21ac9f0550 448 }
kenjiArai 6:5e21ac9f0550 449 }
kenjiArai 6:5e21ac9f0550 450 }
kenjiArai 6:5e21ac9f0550 451
kenjiArai 6:5e21ac9f0550 452 void printascii(char c)
kenjiArai 6:5e21ac9f0550 453 {
kenjiArai 6:5e21ac9f0550 454 uint8_t i,j;
kenjiArai 6:5e21ac9f0550 455
kenjiArai 6:5e21ac9f0550 456 out_code = 1;
kenjiArai 6:5e21ac9f0550 457 PRINTF("%c", c);
kenjiArai 6:5e21ac9f0550 458 if (num_last_line == ONE_LINE){
kenjiArai 6:5e21ac9f0550 459 for (j = 0; j < LINES; j++){ // scroll one line
kenjiArai 6:5e21ac9f0550 460 for (i =0; i < ONE_LINE; i++){
kenjiArai 6:5e21ac9f0550 461 msg_lcd[j][i] = msg_lcd[j+1][i];
kenjiArai 6:5e21ac9f0550 462 }
kenjiArai 6:5e21ac9f0550 463 }
kenjiArai 6:5e21ac9f0550 464 for (i =0; i < ONE_LINE; i++){ // Clear last line
kenjiArai 6:5e21ac9f0550 465 msg_lcd[3][i] = ' ';
kenjiArai 6:5e21ac9f0550 466 }
kenjiArai 6:5e21ac9f0550 467 num_last_line = 0;
kenjiArai 6:5e21ac9f0550 468 for (i =0; i < 4; i++){
kenjiArai 6:5e21ac9f0550 469 lcd.locate(0, i);
kenjiArai 6:5e21ac9f0550 470 lcd.printf("%s", &msg_lcd[i][0]);
kenjiArai 6:5e21ac9f0550 471 }
kenjiArai 6:5e21ac9f0550 472 }
kenjiArai 6:5e21ac9f0550 473 if (!(num_last_line == 0 && c == ' ')){
kenjiArai 6:5e21ac9f0550 474 msg_lcd[3][num_last_line++] = c;
kenjiArai 6:5e21ac9f0550 475 lcd.locate(0, 3);
kenjiArai 6:5e21ac9f0550 476 lcd.printf("%s", &msg_lcd[3][0]);
kenjiArai 6:5e21ac9f0550 477 }
kenjiArai 6:5e21ac9f0550 478 out_code = 0;
kenjiArai 6:5e21ac9f0550 479 }