diff --git a/examples/SX127x_RTTY_Transmit/SX127x_RTTY_Transmit.ino b/examples/SX127x_RTTY_Transmit/SX127x_RTTY_Transmit.ino index 5823f969..37181f1a 100644 --- a/examples/SX127x_RTTY_Transmit/SX127x_RTTY_Transmit.ino +++ b/examples/SX127x_RTTY_Transmit/SX127x_RTTY_Transmit.ino @@ -92,6 +92,20 @@ void loop() { float f = -3.1415; rtty.println(f, 3); + /* + // KiteLib also provides ITA2 ("Baudot") code support + // RTTY client must be configured to 5 bits + rtty.begin(434, 183, 45, 5); + + // create ITA2-encoded string + // NOTE: ASCII characters that do not have ITA2 + // equivalent will be replaced with NUL + ITA2 itaStr = "HELLO WORLD\n"; + + // send the ITA2 string + rtty.write(itaStr.byteArr(), itaStr.length()); + */ + // turn transmitter off fsk.standby(); diff --git a/keywords.txt b/keywords.txt index 898ab9cb..8d4b2fbc 100644 --- a/keywords.txt +++ b/keywords.txt @@ -27,6 +27,7 @@ XBeeSerial KEYWORD1 MQTTClient KEYWORD1 HTTPClient KEYWORD1 RTTYClient KEYWORD1 +ITA2 KEYWORD1 ####################################### # Methods and Functions (KEYWORD2) @@ -96,6 +97,7 @@ check KEYWORD2 # RTTY idle KEYWORD2 +byteArr KEYWORD2 # TransportLayer openTransportConnection KEYWORD2 diff --git a/src/protocols/RTTY.cpp b/src/protocols/RTTY.cpp index afa67120..434b4dfa 100644 --- a/src/protocols/RTTY.cpp +++ b/src/protocols/RTTY.cpp @@ -1,5 +1,62 @@ #include "RTTY.h" +ITA2::ITA2(const char* str) { + _len = strlen(str); + _str = new char[_len]; + strcpy(_str, str); +} + +ITA2::~ITA2() { + delete[] _str; +} + +size_t ITA2::length() { + return(_len); +} + +uint8_t* ITA2::byteArr() { + // create temporary array 3x the string length (figures may be 3 bytes) + uint8_t* temp = new uint8_t[_len*3]; + + size_t arrayLen = 0; + for(size_t i = 0; i < _len; i++) { + uint16_t code = getBits(_str[i]); + // check if the code is letter or figure + if(code & (ITA2_FIGS << 10)) { + temp[arrayLen] = ITA2_FIGS; + temp[arrayLen + 1] = (code >> 5) & ITA2_LTRS; + temp[arrayLen + 2] = ITA2_LTRS; + arrayLen += 3; + } else { + temp[arrayLen] = code; + arrayLen += 1; + } + } + + uint8_t* arr = new uint8_t[arrayLen]; + memcpy(arr, temp, arrayLen); + delete[] temp; + return(arr); +} + +uint16_t ITA2::getBits(char c) { + // search ITA2 table + uint16_t code = 0x0000; + for(uint8_t i = 0; i < ITA2_LENGTH; i++) { + if(ITA2Table[i][0] == c) { + // character is in letter shift + code = i; + break; + } else if(ITA2Table[i][1] == c) { + // character is in figures shift + code = (ITA2_FIGS << 10) | (i << 5) | ITA2_LTRS; + break; + } + } + + return(code); +} + RTTYClient::RTTYClient(PhysicalLayer* phy) { _phy = phy; } @@ -68,11 +125,11 @@ size_t RTTYClient::write(uint8_t b) { } size_t RTTYClient::print(const String& str) { - return(RTTYClient::write(str.c_str(), str.length())); + return(RTTYClient::write((uint8_t*)str.c_str(), str.length())); } size_t RTTYClient::print(const char str[]) { - return(RTTYClient::write(str, strlen(str))); + return(RTTYClient::write((uint8_t*)str, strlen(str))); } size_t RTTYClient::print(char c) { diff --git a/src/protocols/RTTY.h b/src/protocols/RTTY.h index 696d075c..4d40e35c 100644 --- a/src/protocols/RTTY.h +++ b/src/protocols/RTTY.h @@ -4,6 +4,33 @@ #include "TypeDef.h" #include "PhysicalLayer.h" +#define ITA2_FIGS 0x1B +#define ITA2_LTRS 0x1F +#define ITA2_LENGTH 32 + +// ITA2 character table: - position in array corresponds to 5-bit ITA2 code +// - characters to the left are in letters shift, characters to the right in figures shift +// - characters marked 0x7F do not have ASCII equivalent +const char ITA2Table[ITA2_LENGTH][2] = {{'\0', '\0'}, {'E', '3'}, {'\n', '\n'}, {'A', '-'}, {' ', ' '}, {'S', '\''}, {'I', '8'}, {'U', '7'}, + {'\r', '\r'}, {'D', 0x05}, {'R', '4'}, {'J', '\a'}, {'N', ','}, {'F', '!'}, {'C', ':'}, {'K', '('}, + {'T', '5'}, {'Z', '+'}, {'L', ')'}, {'W', '2'}, {'H', 0x7F}, {'Y', '6'}, {'P', '0'}, {'Q', '1'}, + {'O', '9'}, {'B', '?'}, {'G', '&'}, {0x7F, 0x7F}, {'M', '.'}, {'X', '/'}, {'V', ';'}, {0x7F, 0x7F}}; + +class ITA2 { + public: + ITA2(const char* str); + ~ITA2(); + + size_t length(); + uint8_t* byteArr(); + + private: + char* _str; + size_t _len; + + uint16_t getBits(char c); +}; + class RTTYClient { public: RTTYClient(PhysicalLayer* phy);