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