From 4272b0ff305d97403e1efa1fc4c94de8a0cc67a6 Mon Sep 17 00:00:00 2001 From: Marco Campinoti <42536065+IU5HKU@users.noreply.github.com> Date: Sun, 22 Dec 2019 22:07:46 +0100 Subject: [PATCH 1/2] Reorganized morsecode symbols array and updated the MorseClient::write(uint8_t b) method The whole idea was taken from the CubeSat way of doing morsecode, --- src/protocols/Morse/Morse.cpp | 205 +++++++++++++++++----------------- src/protocols/Morse/Morse.h | 6 +- 2 files changed, 107 insertions(+), 104 deletions(-) diff --git a/src/protocols/Morse/Morse.cpp b/src/protocols/Morse/Morse.cpp index 83137abf..e943199b 100644 --- a/src/protocols/Morse/Morse.cpp +++ b/src/protocols/Morse/Morse.cpp @@ -4,68 +4,79 @@ /*! \cond RADIOLIB_DOXYGEN_HIDDEN */ -struct Morse_t { - char c; // ASCII character - char m[7]; // Morse code representation -}; -/*! - \endcond -*/ -// array of all Morse code characters -const Morse_t MorseTable[MORSE_LENGTH] PROGMEM = { - {'A', ".-"}, - {'B',"-..."}, - {'C', "-.-."}, - {'D',"-.."}, - {'E',"."}, - {'F',"..-."}, - {'G',"--."}, - {'H',"...."}, - {'I',".."}, - {'J',".---"}, - {'K',"-.-"}, - {'L',".-.."}, - {'M',"--"}, - {'N',"-."}, - {'O',"---"}, - {'P',".--."}, - {'Q',"--.-"}, - {'R',".-."}, - {'S',"..."}, - {'T',"-"}, - {'U',"..-"}, - {'V',"...-"}, - {'W',".--"}, - {'X',"-..-"}, - {'Y',"-.--"}, - {'Z',"--.."}, - {'1',".----"}, - {'2',"..---"}, - {'3',"...--"}, - {'4',"....-"}, - {'5',"....."}, - {'6',"-...."}, - {'7',"--..."}, - {'8',"---.."}, - {'9',"----."}, - {'0',"-----"}, - {'.',".-.-.-"}, - {',',"--..--"}, - {':',"---..."}, - {'?',"..--.."}, - {'\'',".----."}, - {'-',"-....-"}, - {'/',"-..-."}, - {'(',"-.--."}, - {')',"-.--.-"}, - {'\"',".-..-."}, - {'=',"-...-"}, - {'+',".-.-."}, - {'@',".--.-."}, - {' ',"_"}, // space is used to separate words - {0x01,"-.-.-"}, // ASCII SOH (start of heading) is used as alias for start signal - {0x02,".-.-."} // ASCII EOT (end of transmission) is used as alias for stop signal +//---------------------------------------------------------------------------------------- +// In the below array we represent dots as 0 and dashes as 1, using a further bit as +// 'guard' who tell us when we must stop in decoding our symbols. +// Some bytes are zeroed because there isn't a morse code representation of that char. +// The ascii code of the letter is the search index into the array for the correspondent +// morse code representation. +//---------------------------------------------------------------------------------------- +const uint8_t morse_lookuptable[64] PROGMEM = { + 0b00, // space 0x00 + 0b1110101, // ! 117 + 0b1010010, // " 82 + 0b00, // # (doesn't exists)<-- + 0b11001000, // $ 200 + 0b00, // % (doesn't exists)<-- + 0b100010, // & 34 + 0b1011110, // ' 94 + 0b101101, // ( 45 + 0b1101101, // ) 109 + 0b00, // * (doesn't exists)<-- + 0b101010, // + 42 + 0b1110011, // , 115 + 0b1100001, // - 97 + 0b1101010, // . 106 + 0b101001, // / 41 + 0b111111, // 0 63 + 0b111110, // 1 62 + 0b111100, // 2 60 + 0b111000, // 3 56 + 0b110000, // 4 48 + 0b100000, // 5 32 + 0b100001, // 6 33 + 0b100011, // 7 35 + 0b100111, // 8 39 + 0b101111, // 9 47 + 0b1000111, // : 71 + 0b1101010, // ; 106 + 0b00, // < (doesn't exists)<-- + 0b110001, // = 49 + 0b00, // > (doesn't exists)<-- + 0b1001100, // ? 76 + 0b1010110, // @ 86 + 0b110, // A 6 + 0b10001, // B 17 + 0b10101, // C 21 + 0b1001, // D 9 + 0b10, // E 2 + 0b10100, // F 20 + 0b1011, // G 11 + 0b10000, // H 16 + 0b100, // I 4 + 0b11110, // J 30 + 0b1101, // K 13 + 0b10010, // L 18 + 0b111, // M 7 + 0b101, // N 5 + 0b1111, // O 15 + 0b10110, // P 22 + 0b11011, // Q 27 + 0b1010, // R 10 + 0b1000, // S 8 + 0b11, // T 3 + 0b1100, // U 12 + 0b11000, // V 24 + 0b1110, // W 14 + 0b11001, // X 25 + 0b11101, // Y 29 + 0b10011, // Z 19 + 0b00, // [ (doesn't exists)<-- + 0b00, // \ (doesn't exists)<-- + 0b00, // ] (doesn't exists)<-- + 0b00, // ^ (doesn't exists)<-- + 0b1101100 // _ 108 }; MorseClient::MorseClient(PhysicalLayer* phy) { @@ -106,52 +117,40 @@ size_t MorseClient::write(uint8_t* buff, size_t len) { } size_t MorseClient::write(uint8_t b) { - // find the correct Morse code in array - Morse_t mc; - bool found = false; - for(uint8_t pos = 0; pos < MORSE_LENGTH; pos++) { - memcpy_P(&mc, &MorseTable[pos], sizeof(Morse_t)); - if(mc.c == toupper(b)) { - found = true; - break; - } - } + + //Note: using toupper() you always find a char, because all possible chars are included in this array! + uint8_t ditdah_code = 0x00; - // check if the requested code was found in the array - if(found) { - RADIOLIB_DEBUG_PRINT(mc.c); - RADIOLIB_DEBUG_PRINT('\t'); - RADIOLIB_DEBUG_PRINTLN(mc.m); - - // iterate over Morse code representation and output appropriate tones - for(uint8_t i = 0; i < strlen(mc.m); i++) { - switch(mc.m[i]) { - case '.': - _phy->transmitDirect(_base); - delay(_dotLength); - break; - case '-': - _phy->transmitDirect(_base); - delay(_dotLength * 3); - break; - case '_': - // do nothing (word space) - break; - } - - // symbol space - _phy->standby(); - delay(_dotLength); - } - - // letter space - RADIOLIB_DEBUG_PRINTLN(); + if (b == ' ') { + RADIOLIB_DEBUG_PRINTLN('space'); // inter-words pause (space) + // symbol space + _phy->standby(); delay(_dotLength * 3); - - return(1); } - return(0); + ditdah_code = morse_lookuptable[(uint8_t)(toupper(b) - 32)]; // retrieve morse code from lookuptable + + //do it until 'guardbit' is reached + while (ditdah_code > GUARDBIT) { + if (ditdah_code & DAH) { + RADIOLIB_DEBUG_PRINT('-'); // tx a 'dah' + _phy->transmitDirect(_base); + delay(_dotLength * 3); + } + else{ + RADIOLIB_DEBUG_PRINT('.'); // tx a 'dit' + _phy->transmitDirect(_base); + delay(_dotLength); + } + ditdah_code >>= 1; // analyze next bit + } + + // letter space + RADIOLIB_DEBUG_PRINTLN(); + _phy->standby(); + delay(_dotLength); + + return(0); } size_t MorseClient::print(__FlashStringHelper* fstr) { diff --git a/src/protocols/Morse/Morse.h b/src/protocols/Morse/Morse.h index 317a8066..f482a6c0 100644 --- a/src/protocols/Morse/Morse.h +++ b/src/protocols/Morse/Morse.h @@ -4,7 +4,11 @@ #include "../../TypeDef.h" #include "../PhysicalLayer/PhysicalLayer.h" -#define MORSE_LENGTH 52 +//#define MORSE_LENGTH 52 +#define MORSE_LENGTH 64 +#define DIT 0b0 +#define DAH 0b1 +#define GUARDBIT 0b1 /*! \class MorseClient From 41f4848b9e4df7e098f92e911b179161c7dbc7eb Mon Sep 17 00:00:00 2001 From: jgromes Date: Mon, 23 Dec 2019 14:25:34 +0100 Subject: [PATCH 2/2] [Morse] Formatting fixes, added missing symbol space --- .../Morse/Morse_Transmit/Morse_Transmit.ino | 2 +- src/protocols/Morse/Morse.cpp | 154 +++++------------- src/protocols/Morse/Morse.h | 80 ++++++++- 3 files changed, 121 insertions(+), 115 deletions(-) diff --git a/examples/Morse/Morse_Transmit/Morse_Transmit.ino b/examples/Morse/Morse_Transmit/Morse_Transmit.ino index 611ffd93..a835f8a5 100644 --- a/examples/Morse/Morse_Transmit/Morse_Transmit.ino +++ b/examples/Morse/Morse_Transmit/Morse_Transmit.ino @@ -104,7 +104,7 @@ void loop() { // floating point number // NOTE: When using println(), the transmission will be - // terminated with cross signal (.-.-.). + // terminated with end-of-work signal (...-.-). float f = -3.1415; morse.println(f, 3); diff --git a/src/protocols/Morse/Morse.cpp b/src/protocols/Morse/Morse.cpp index e943199b..0dbfd768 100644 --- a/src/protocols/Morse/Morse.cpp +++ b/src/protocols/Morse/Morse.cpp @@ -1,84 +1,5 @@ #include "Morse.h" -// structure to save data about character Morse code -/*! - \cond RADIOLIB_DOXYGEN_HIDDEN -*/ - -//---------------------------------------------------------------------------------------- -// In the below array we represent dots as 0 and dashes as 1, using a further bit as -// 'guard' who tell us when we must stop in decoding our symbols. -// Some bytes are zeroed because there isn't a morse code representation of that char. -// The ascii code of the letter is the search index into the array for the correspondent -// morse code representation. -//---------------------------------------------------------------------------------------- -const uint8_t morse_lookuptable[64] PROGMEM = { - 0b00, // space 0x00 - 0b1110101, // ! 117 - 0b1010010, // " 82 - 0b00, // # (doesn't exists)<-- - 0b11001000, // $ 200 - 0b00, // % (doesn't exists)<-- - 0b100010, // & 34 - 0b1011110, // ' 94 - 0b101101, // ( 45 - 0b1101101, // ) 109 - 0b00, // * (doesn't exists)<-- - 0b101010, // + 42 - 0b1110011, // , 115 - 0b1100001, // - 97 - 0b1101010, // . 106 - 0b101001, // / 41 - 0b111111, // 0 63 - 0b111110, // 1 62 - 0b111100, // 2 60 - 0b111000, // 3 56 - 0b110000, // 4 48 - 0b100000, // 5 32 - 0b100001, // 6 33 - 0b100011, // 7 35 - 0b100111, // 8 39 - 0b101111, // 9 47 - 0b1000111, // : 71 - 0b1101010, // ; 106 - 0b00, // < (doesn't exists)<-- - 0b110001, // = 49 - 0b00, // > (doesn't exists)<-- - 0b1001100, // ? 76 - 0b1010110, // @ 86 - 0b110, // A 6 - 0b10001, // B 17 - 0b10101, // C 21 - 0b1001, // D 9 - 0b10, // E 2 - 0b10100, // F 20 - 0b1011, // G 11 - 0b10000, // H 16 - 0b100, // I 4 - 0b11110, // J 30 - 0b1101, // K 13 - 0b10010, // L 18 - 0b111, // M 7 - 0b101, // N 5 - 0b1111, // O 15 - 0b10110, // P 22 - 0b11011, // Q 27 - 0b1010, // R 10 - 0b1000, // S 8 - 0b11, // T 3 - 0b1100, // U 12 - 0b11000, // V 24 - 0b1110, // W 14 - 0b11001, // X 25 - 0b11101, // Y 29 - 0b10011, // Z 19 - 0b00, // [ (doesn't exists)<-- - 0b00, // \ (doesn't exists)<-- - 0b00, // ] (doesn't exists)<-- - 0b00, // ^ (doesn't exists)<-- - 0b1101100 // _ 108 -}; - MorseClient::MorseClient(PhysicalLayer* phy) { _phy = phy; } @@ -97,7 +18,7 @@ int16_t MorseClient::begin(float base, uint8_t speed) { } size_t MorseClient::startSignal() { - return(MorseClient::write(0x01)); + return(MorseClient::write('_')); } size_t MorseClient::write(const char* str) { @@ -117,40 +38,55 @@ size_t MorseClient::write(uint8_t* buff, size_t len) { } size_t MorseClient::write(uint8_t b) { - - //Note: using toupper() you always find a char, because all possible chars are included in this array! - uint8_t ditdah_code = 0x00; - - if (b == ' ') { - RADIOLIB_DEBUG_PRINTLN('space'); // inter-words pause (space) - // symbol space - _phy->standby(); - delay(_dotLength * 3); + // check unprintable ASCII characters and boundaries + if((b < ' ') || (b == 0x60) || (b > 'z')) { + return(0); } - ditdah_code = morse_lookuptable[(uint8_t)(toupper(b) - 32)]; // retrieve morse code from lookuptable - - //do it until 'guardbit' is reached - while (ditdah_code > GUARDBIT) { - if (ditdah_code & DAH) { - RADIOLIB_DEBUG_PRINT('-'); // tx a 'dah' + // inter-word pause (space) + if(b == ' ') { + RADIOLIB_DEBUG_PRINTLN(F("space")); + _phy->standby(); + delay(4 * _dotLength); + return(1); + } + + // get morse code from lookup table + uint8_t code = pgm_read_byte(&MorseTable[(uint8_t)(toupper(b) - 32)]); + + // check unsupported characters + if(code == MORSE_UNSUPORTED) { + return(0); + } + + // iterate through codeword until guard bit is reached + while(code > MORSE_GUARDBIT) { + + // send dot or dash + if (code & MORSE_DASH) { + RADIOLIB_DEBUG_PRINT('-'); _phy->transmitDirect(_base); - delay(_dotLength * 3); - } - else{ - RADIOLIB_DEBUG_PRINT('.'); // tx a 'dit' + delay(3 * _dotLength); + } else { + RADIOLIB_DEBUG_PRINT('.'); _phy->transmitDirect(_base); delay(_dotLength); - } - ditdah_code >>= 1; // analyze next bit - } - - // letter space - RADIOLIB_DEBUG_PRINTLN(); - _phy->standby(); - delay(_dotLength); + } - return(0); + // symbol space + _phy->standby(); + delay(_dotLength); + + // move onto the next bit + code >>= 1; + } + + // letter space + _phy->standby(); + delay(2 * _dotLength); + RADIOLIB_DEBUG_PRINTLN(); + + return(1); } size_t MorseClient::print(__FlashStringHelper* fstr) { @@ -218,7 +154,7 @@ size_t MorseClient::print(double n, int digits) { } size_t MorseClient::println(void) { - return(MorseClient::write(0x02)); + return(MorseClient::write('^')); } size_t MorseClient::println(__FlashStringHelper* fstr) { diff --git a/src/protocols/Morse/Morse.h b/src/protocols/Morse/Morse.h index f482a6c0..66df3280 100644 --- a/src/protocols/Morse/Morse.h +++ b/src/protocols/Morse/Morse.h @@ -4,11 +4,81 @@ #include "../../TypeDef.h" #include "../PhysicalLayer/PhysicalLayer.h" -//#define MORSE_LENGTH 52 -#define MORSE_LENGTH 64 -#define DIT 0b0 -#define DAH 0b1 -#define GUARDBIT 0b1 +#define MORSE_DOT 0b0 +#define MORSE_DASH 0b1 +#define MORSE_GUARDBIT 0b1 +#define MORSE_UNSUPORTED 0xFF + +// Morse character table: - using codes defined in ITU-R M.1677-1 +// - Morse code representation is saved LSb first, using additional bit as guard +// - position in array corresponds ASCII code minus MORSE_ASCII_OFFSET +// - ASCII characters marked MORSE_UNSUPORTED do not have ITU-R M.1677-1 equivalent +static const uint8_t MorseTable[] PROGMEM = { + 0b00, // space + 0b110101, // ! (unsupported) + 0b1010010, // " + MORSE_UNSUPORTED, // # (unsupported) + MORSE_UNSUPORTED, // $ (unsupported) + MORSE_UNSUPORTED, // % (unsupported) + MORSE_UNSUPORTED, // & (unsupported) + 0b1011110, // ' + 0b101101, // ( + 0b1101101, // ) + MORSE_UNSUPORTED, // * (unsupported) + 0b101010, // + + 0b1110011, // , + 0b1100001, // - + 0b1101010, // . + 0b101001, // / + 0b111111, // 0 + 0b111110, // 1 + 0b111100, // 2 + 0b111000, // 3 + 0b110000, // 4 + 0b100000, // 5 + 0b100001, // 6 + 0b100011, // 7 + 0b100111, // 8 + 0b101111, // 9 + 0b1000111, // : + MORSE_UNSUPORTED, // ; (unsupported) + MORSE_UNSUPORTED, // < (unsupported) + 0b110001, // = + MORSE_UNSUPORTED, // > (unsupported) + 0b1001100, // ? + 0b1010110, // @ + 0b110, // A + 0b10001, // B + 0b10101, // C + 0b1001, // D + 0b10, // E + 0b10100, // F + 0b1011, // G + 0b10000, // H + 0b100, // I + 0b11110, // J + 0b1101, // K + 0b10010, // L + 0b111, // M + 0b101, // N + 0b1111, // O + 0b10110, // P + 0b11011, // Q + 0b1010, // R + 0b1000, // S + 0b11, // T + 0b1100, // U + 0b11000, // V + 0b1110, // W + 0b11001, // X + 0b11101, // Y + 0b10011, // Z + MORSE_UNSUPORTED, // [ (unsupported) + MORSE_UNSUPORTED, // \ (unsupported) + MORSE_UNSUPORTED, // ] (unsupported) + 0b1101000, // ^ (unsupported, used as alias for end of work) + 0b110101 // _ (unsupported, used as alias for starting signal) +}; /*! \class MorseClient