diff --git a/examples/SX127x_RTTY_Transmit/SX127x_RTTY_Transmit.ino b/examples/SX127x_RTTY_Transmit/SX127x_RTTY_Transmit.ino new file mode 100644 index 00000000..8312fb74 --- /dev/null +++ b/examples/SX127x_RTTY_Transmit/SX127x_RTTY_Transmit.ino @@ -0,0 +1,78 @@ +/* + KiteLib SX127x RTTY Transmit Example + + This example sends RTTY message using SX1278's + FSK modem. + + Other modules from SX127x family can also be used. + SX1272 lora = Kite.ModuleA; + SX1273 lora = Kite.ModuleA; + SX1276 lora = Kite.ModuleA; + SX1277 lora = Kite.ModuleA; + SX1279 lora = Kite.ModuleA; +*/ + +// include the library +#include + +// SX1278 module is in slot A on the shield +SX1278 fsk = Kite.ModuleA; + +// create RTTY client instance using the FSK module +RTTYClient rtty(&fsk); + +void setup() { + Serial.begin(9600); + + // initialize SX1278 + Serial.print("[SX1278] Initializing ... "); + // carrier frequency: 434.4 MHz + // bandwidth: 125.0 kHz + // spreading factor: 9 + // coding rate: 7 + // sync word: 0x12 + // output power: 17 dBm + // current limit: 100 mA + // preamble length: 8 symbols + // amplifier gain: 0 (automatic gain control) + int state = fsk.beginFSK(434.4); + if(state == ERR_NONE) { + Serial.println("success!"); + } else { + Serial.print("failed, code "); + Serial.println(state); + while(true); + } + + // initialize RTTY client + Serial.print("[RTTY] Initializing ... "); + state = rtty.begin(434.4, 183, 45); + // low frequency: 434.4 MHz + // frequency shift: 183 Hz (must be divisible by 61!) + // baud rate: 45 baud + // data bits: 8 + // stop bits: 1 + if(state == ERR_NONE) { + Serial.println("success!"); + } else { + Serial.print("failed, code "); + Serial.println(state); + while(true); + } +} + +void loop() { + // send 500 ms high frequency beep + rtty.leadIn(500); + + // RTTYClient supports all methods of the Serial class + // send the string "Hello World!", followed by + // carriage return and line feed chracters + rtty.println("Hello World!"); + + // turn transmitter off + fsk.standby(); + + // wait for a second before transmitting again + delay(1000); +} diff --git a/keywords.txt b/keywords.txt index 9d43ab99..dfcbec0a 100644 --- a/keywords.txt +++ b/keywords.txt @@ -26,6 +26,7 @@ XBeeSerial KEYWORD1 MQTTClient KEYWORD1 HTTPClient KEYWORD1 +RTTYClient KEYWORD1 ####################################### # Methods and Functions (KEYWORD2) @@ -92,6 +93,9 @@ unsubscribe KEYWORD2 ping KEYWORD2 check KEYWORD2 +# RTTY +leadIn KEYWORD2 + # TransportLayer openTransportConnection KEYWORD2 closeTransportConnection KEYWORD2 diff --git a/src/KiteLib.h b/src/KiteLib.h index 03401aba..e2e8863f 100644 --- a/src/KiteLib.h +++ b/src/KiteLib.h @@ -17,6 +17,9 @@ #include "modules/SX1279.h" #include "modules/XBee.h" +#include "protocols/PhysicalLayer.h" +#include "protocols/RTTY.h" + #include "protocols/TransportLayer.h" #include "protocols/HTTP.h" #include "protocols/MQTT.h" diff --git a/src/TypeDef.h b/src/TypeDef.h index 88e41be6..4212b58a 100644 --- a/src/TypeDef.h +++ b/src/TypeDef.h @@ -80,6 +80,7 @@ #define ERR_INVALID_PREAMBLE_LENGTH -18 #define ERR_INVALID_GAIN -19 #define ERR_WRONG_MODEM -20 +#define ERR_INVALID_RTTY_SHIFT -21 // RF69-specific status codes #define ERR_INVALID_BIT_RATE -101 diff --git a/src/protocols/RTTY.cpp b/src/protocols/RTTY.cpp new file mode 100644 index 00000000..14457a1c --- /dev/null +++ b/src/protocols/RTTY.cpp @@ -0,0 +1,89 @@ +#include "RTTY.h" + +RTTYClient::RTTYClient(PhysicalLayer* phy) { + _phy = phy; +} + +int16_t RTTYClient::begin(float base, uint16_t shift, uint16_t rate, uint8_t dataBits, uint8_t stopBits) { + // check supplied values + if(shift % 61 != 0) { + return(ERR_INVALID_RTTY_SHIFT); + } + + // save configuration + _shift = shift / 61; + _dataBits = dataBits; + _stopBits = stopBits; + + // calculate duration of 1 bit + _bitDuration = (uint32_t)1000000/rate; + + // calculate 24-bit frequency + uint32_t mult = 1; + _base = (base * (mult << 19)) / 32.0; + + // set module frequency deviation to 0 + int16_t state = _phy->setFrequencyDeviation(0); + + return(state); +} + +void RTTYClient::leadIn(uint16_t length) { + _phy->directMode(); + + mark(); + delay(length); +} + +size_t RTTYClient::print(const String& str) { + return(RTTYClient::print(str.c_str())); +} + +size_t RTTYClient::print(const char* str) { + size_t len = 0; + for(size_t i = 0; i < strlen(str); i++) { + len += write(str[i]); + } + return(len); +} + +size_t RTTYClient::println(const String& str) { + return(RTTYClient::println(str.c_str())); +} + +size_t RTTYClient::println(const char* str) { + size_t len = print(str); + len += write('\r'); + len += write('\n'); + return(len); +} + +size_t RTTYClient::write(uint8_t b) { + space(); + + for(uint8_t mask = 0x01; mask; mask <<= 1) { + if(b & mask) { + mark(); + } else { + space(); + } + } + + for(uint8_t i = 0; i < _stopBits; i++) { + mark(); + } + + return(1); +} + +void RTTYClient::mark() { + uint32_t start = micros(); + _phy->directMode(_base + _shift); + while(micros() - start < _bitDuration); +} + +void RTTYClient::space() { + uint32_t start = micros(); + _phy->directMode(_base); + while(micros() - start < _bitDuration); +} diff --git a/src/protocols/RTTY.h b/src/protocols/RTTY.h new file mode 100644 index 00000000..89c390b2 --- /dev/null +++ b/src/protocols/RTTY.h @@ -0,0 +1,49 @@ +#ifndef _KITELIB_RTTY_H +#define _KITELIB_RTTY_H + +#include "TypeDef.h" +#include "PhysicalLayer.h" + +class RTTYClient { + public: + RTTYClient(PhysicalLayer* phy); + + // basic methods + int16_t begin(float base, uint16_t shift, uint16_t rate, uint8_t dataBits = 8, uint8_t stopBits = 1); + void leadIn(uint16_t length); + size_t write(uint8_t b); + + size_t print(const String &); + size_t print(const char[]); + size_t print(char); + size_t print(unsigned char, int = DEC); + size_t print(int, int = DEC); + size_t print(unsigned int, int = DEC); + size_t print(long, int = DEC); + size_t print(unsigned long, int = DEC); + size_t print(double, int = 2); + + size_t println(const String &s); + size_t println(const char[]); + size_t println(char); + size_t println(unsigned char, int = DEC); + size_t println(int, int = DEC); + size_t println(unsigned int, int = DEC); + size_t println(long, int = DEC); + size_t println(unsigned long, int = DEC); + size_t println(double, int = 2); + + private: + PhysicalLayer* _phy; + + uint32_t _base; + uint16_t _shift; + uint16_t _bitDuration; + uint8_t _dataBits; + uint8_t _stopBits; + + void mark(); + void space(); +}; + +#endif