acid-drop- Hacking the planet from a LilyGo T-Deck using custom firmware |
git clone git://git.acid.vegas/acid-drop.git |
Log | Files | Refs | Archive | README | LICENSE |
Morse.cpp (9612B)
1 #include "Morse.h" 2 #if !defined(RADIOLIB_EXCLUDE_MORSE) 3 4 MorseClient::MorseClient(PhysicalLayer* phy) { 5 _phy = phy; 6 #if !defined(RADIOLIB_EXCLUDE_AFSK) 7 _audio = nullptr; 8 #endif 9 } 10 11 #if !defined(RADIOLIB_EXCLUDE_AFSK) 12 MorseClient::MorseClient(AFSKClient* audio) { 13 _phy = audio->_phy; 14 _audio = audio; 15 } 16 #endif 17 18 int16_t MorseClient::begin(float base, uint8_t speed) { 19 // calculate 24-bit frequency 20 _baseHz = base; 21 _base = (base * 1000000.0) / _phy->getFreqStep(); 22 23 // calculate tone period for decoding 24 _basePeriod = (1000000.0f/base)/2.0f; 25 26 // calculate symbol lengths (assumes PARIS as typical word) 27 _dotLength = 1200 / speed; 28 _dashLength = 3*_dotLength; 29 _letterSpace = 3*_dotLength; 30 _wordSpace = 4*_dotLength; 31 32 // configure for direct mode 33 return(_phy->startDirect()); 34 } 35 36 size_t MorseClient::startSignal() { 37 return(MorseClient::write('_')); 38 } 39 40 char MorseClient::decode(uint8_t symbol, uint8_t len) { 41 // add the guard bit 42 symbol |= (RADIOLIB_MORSE_DASH << len); 43 44 // iterate over the table 45 for(uint8_t i = 0; i < sizeof(MorseTable); i++) { 46 uint8_t code = RADIOLIB_NONVOLATILE_READ_BYTE(&MorseTable[i]); 47 if(code == symbol) { 48 // match, return the index + ASCII offset 49 return((char)(i + RADIOLIB_MORSE_ASCII_OFFSET)); 50 } 51 } 52 53 // nothing found 54 return(RADIOLIB_MORSE_UNSUPORTED); 55 } 56 57 #if !defined(RADIOLIB_EXCLUDE_AFSK) 58 int MorseClient::read(byte* symbol, byte* len, float low, float high) { 59 Module* mod = _phy->getMod(); 60 61 // measure pulse duration in us 62 uint32_t duration = mod->pulseIn(_audio->_pin, LOW, 4*_basePeriod); 63 64 // decide if this is a signal, or pause 65 if((duration > low*_basePeriod) && (duration < high*_basePeriod)) { 66 // this is a signal 67 signalCounter++; 68 } else if(duration == 0) { 69 // this is a pause 70 pauseCounter++; 71 } 72 73 // update everything 74 if((pauseCounter > 0) && (signalCounter == 1)) { 75 // start of dot or dash 76 pauseCounter = 0; 77 signalStart = mod->millis(); 78 uint32_t pauseLen = mod->millis() - pauseStart; 79 80 if((pauseLen >= low*(float)_letterSpace) && (pauseLen <= high*(float)_letterSpace)) { 81 return(RADIOLIB_MORSE_CHAR_COMPLETE); 82 } else if(pauseLen > _wordSpace) { 83 RADIOLIB_DEBUG_PRINTLN("\n<space>"); 84 return(RADIOLIB_MORSE_WORD_COMPLETE); 85 } 86 87 } else if((signalCounter > 0) && (pauseCounter == 1)) { 88 // end of dot or dash 89 signalCounter = 0; 90 pauseStart = mod->millis(); 91 uint32_t signalLen = mod->millis() - signalStart; 92 93 if((signalLen >= low*(float)_dotLength) && (signalLen <= high*(float)_dotLength)) { 94 RADIOLIB_DEBUG_PRINT('.'); 95 (*symbol) |= (RADIOLIB_MORSE_DOT << (*len)); 96 (*len)++; 97 } else if((signalLen >= low*(float)_dashLength) && (signalLen <= high*(float)_dashLength)) { 98 RADIOLIB_DEBUG_PRINT('-'); 99 (*symbol) |= (RADIOLIB_MORSE_DASH << (*len)); 100 (*len)++; 101 } else { 102 RADIOLIB_DEBUG_PRINT("<len="); 103 RADIOLIB_DEBUG_PRINT(signalLen); 104 RADIOLIB_DEBUG_PRINTLN("ms>"); 105 } 106 } 107 108 return(RADIOLIB_MORSE_INTER_SYMBOL); 109 } 110 #endif 111 112 size_t MorseClient::write(const char* str) { 113 if(str == NULL) { 114 return(0); 115 } 116 117 return(MorseClient::write((uint8_t*)str, strlen(str))); 118 } 119 120 size_t MorseClient::write(uint8_t* buff, size_t len) { 121 size_t n = 0; 122 for(size_t i = 0; i < len; i++) { 123 n += MorseClient::write(buff[i]); 124 } 125 return(n); 126 } 127 128 size_t MorseClient::write(uint8_t b) { 129 Module* mod = _phy->getMod(); 130 131 // check unprintable ASCII characters and boundaries 132 if((b < ' ') || (b == 0x60) || (b > 'z')) { 133 return(0); 134 } 135 136 // inter-word pause (space) 137 if(b == ' ') { 138 RADIOLIB_DEBUG_PRINTLN(F("space")); 139 standby(); 140 mod->delay(_wordSpace); 141 return(1); 142 } 143 144 // get morse code from lookup table 145 uint8_t code = RADIOLIB_NONVOLATILE_READ_BYTE(&MorseTable[(uint8_t)(toupper(b) - RADIOLIB_MORSE_ASCII_OFFSET)]); 146 147 // check unsupported characters 148 if(code == RADIOLIB_MORSE_UNSUPORTED) { 149 return(0); 150 } 151 152 // iterate through codeword until guard bit is reached 153 while(code > RADIOLIB_MORSE_GUARDBIT) { 154 155 // send dot or dash 156 if (code & RADIOLIB_MORSE_DASH) { 157 RADIOLIB_DEBUG_PRINT('-'); 158 transmitDirect(_base, _baseHz); 159 mod->delay(_dashLength); 160 } else { 161 RADIOLIB_DEBUG_PRINT('.'); 162 transmitDirect(_base, _baseHz); 163 mod->delay(_dotLength); 164 } 165 166 // symbol space 167 standby(); 168 mod->delay(_dotLength); 169 170 // move onto the next bit 171 code >>= 1; 172 } 173 174 // letter space 175 standby(); 176 mod->delay(_letterSpace - _dotLength); 177 RADIOLIB_DEBUG_PRINTLN(); 178 179 return(1); 180 } 181 182 size_t MorseClient::print(__FlashStringHelper* fstr) { 183 PGM_P p = reinterpret_cast<PGM_P>(fstr); 184 size_t n = 0; 185 while(true) { 186 char c = RADIOLIB_NONVOLATILE_READ_BYTE(p++); 187 if(c == '\0') { 188 break; 189 } 190 n += MorseClient::write(c); 191 } 192 return n; 193 } 194 195 size_t MorseClient::print(const String& str) { 196 return(MorseClient::write((uint8_t*)str.c_str(), str.length())); 197 } 198 199 size_t MorseClient::print(const char* str) { 200 return(MorseClient::write((uint8_t*)str, strlen(str))); 201 } 202 203 size_t MorseClient::print(char c) { 204 return(MorseClient::write(c)); 205 } 206 207 size_t MorseClient::print(unsigned char b, int base) { 208 return(MorseClient::print((unsigned long)b, base)); 209 } 210 211 size_t MorseClient::print(int n, int base) { 212 return(MorseClient::print((long)n, base)); 213 } 214 215 size_t MorseClient::print(unsigned int n, int base) { 216 return(MorseClient::print((unsigned long)n, base)); 217 } 218 219 size_t MorseClient::print(long n, int base) { 220 if(base == 0) { 221 return(MorseClient::write(n)); 222 } else if(base == DEC) { 223 if (n < 0) { 224 int t = MorseClient::print('-'); 225 n = -n; 226 return(MorseClient::printNumber(n, DEC) + t); 227 } 228 return(MorseClient::printNumber(n, DEC)); 229 } else { 230 return(MorseClient::printNumber(n, base)); 231 } 232 } 233 234 size_t MorseClient::print(unsigned long n, int base) { 235 if(base == 0) { 236 return(MorseClient::write(n)); 237 } else { 238 return(MorseClient::printNumber(n, base)); 239 } 240 } 241 242 size_t MorseClient::print(double n, int digits) { 243 return(MorseClient::printFloat(n, digits)); 244 } 245 246 size_t MorseClient::println(void) { 247 return(MorseClient::write('^')); 248 } 249 250 size_t MorseClient::println(__FlashStringHelper* fstr) { 251 size_t n = MorseClient::print(fstr); 252 n += MorseClient::println(); 253 return(n); 254 } 255 256 size_t MorseClient::println(const String& str) { 257 size_t n = MorseClient::print(str); 258 n += MorseClient::println(); 259 return(n); 260 } 261 262 size_t MorseClient::println(const char* str) { 263 size_t n = MorseClient::print(str); 264 n += MorseClient::println(); 265 return(n); 266 } 267 268 size_t MorseClient::println(char c) { 269 size_t n = MorseClient::print(c); 270 n += MorseClient::println(); 271 return(n); 272 } 273 274 size_t MorseClient::println(unsigned char b, int base) { 275 size_t n = MorseClient::print(b, base); 276 n += MorseClient::println(); 277 return(n); 278 } 279 280 size_t MorseClient::println(int num, int base) { 281 size_t n = MorseClient::print(num, base); 282 n += MorseClient::println(); 283 return(n); 284 } 285 286 size_t MorseClient::println(unsigned int num, int base) { 287 size_t n = MorseClient::print(num, base); 288 n += MorseClient::println(); 289 return(n); 290 } 291 292 size_t MorseClient::println(long num, int base) { 293 size_t n = MorseClient::print(num, base); 294 n += MorseClient::println(); 295 return(n); 296 } 297 298 size_t MorseClient::println(unsigned long num, int base) { 299 size_t n = MorseClient::print(num, base); 300 n += MorseClient::println(); 301 return(n); 302 } 303 304 size_t MorseClient::println(double d, int digits) { 305 size_t n = MorseClient::print(d, digits); 306 n += MorseClient::println(); 307 return(n); 308 } 309 310 size_t MorseClient::printNumber(unsigned long n, uint8_t base) { 311 char buf[8 * sizeof(long) + 1]; 312 char *str = &buf[sizeof(buf) - 1]; 313 314 *str = '\0'; 315 316 if(base < 2) { 317 base = 10; 318 } 319 320 do { 321 char c = n % base; 322 n /= base; 323 324 *--str = c < 10 ? c + '0' : c + 'A' - 10; 325 } while(n); 326 327 return(MorseClient::write(str)); 328 } 329 330 size_t MorseClient::printFloat(double number, uint8_t digits) { 331 size_t n = 0; 332 333 char code[] = {0x00, 0x00, 0x00, 0x00}; 334 if (isnan(number)) strcpy(code, "nan"); 335 if (isinf(number)) strcpy(code, "inf"); 336 if (number > 4294967040.0) strcpy(code, "ovf"); // constant determined empirically 337 if (number <-4294967040.0) strcpy(code, "ovf"); // constant determined empirically 338 339 if(code[0] != 0x00) { 340 return(MorseClient::write(code)); 341 } 342 343 // Handle negative numbers 344 if (number < 0.0) { 345 n += MorseClient::print('-'); 346 number = -number; 347 } 348 349 // Round correctly so that print(1.999, 2) prints as "2.00" 350 double rounding = 0.5; 351 for(uint8_t i = 0; i < digits; ++i) { 352 rounding /= 10.0; 353 } 354 number += rounding; 355 356 // Extract the integer part of the number and print it 357 unsigned long int_part = (unsigned long)number; 358 double remainder = number - (double)int_part; 359 n += MorseClient::print(int_part); 360 361 // Print the decimal point, but only if there are digits beyond 362 if(digits > 0) { 363 n += MorseClient::print('.'); 364 } 365 366 // Extract digits from the remainder one at a time 367 while(digits-- > 0) { 368 remainder *= 10.0; 369 unsigned int toPrint = (unsigned int)(remainder); 370 n += MorseClient::print(toPrint); 371 remainder -= toPrint; 372 } 373 374 return n; 375 } 376 377 int16_t MorseClient::transmitDirect(uint32_t freq, uint32_t freqHz) { 378 #if !defined(RADIOLIB_EXCLUDE_AFSK) 379 if(_audio != nullptr) { 380 return(_audio->tone(freqHz)); 381 } 382 #endif 383 return(_phy->transmitDirect(freq)); 384 } 385 386 int16_t MorseClient::standby() { 387 #if !defined(RADIOLIB_EXCLUDE_AFSK) 388 if(_audio != nullptr) { 389 return(_audio->noTone(true)); 390 } 391 #endif 392 return(_phy->standby()); 393 } 394 395 #endif