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.
main.cpp@6:5e21ac9f0550, 2017-02-05 (annotated)
- 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?
User | Revision | Line number | New 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 | } |