[RTTY] Implemented basic RTTY support
This commit is contained in:
parent
c8aa9f57fd
commit
f4344af3c5
6 changed files with 224 additions and 0 deletions
78
examples/SX127x_RTTY_Transmit/SX127x_RTTY_Transmit.ino
Normal file
78
examples/SX127x_RTTY_Transmit/SX127x_RTTY_Transmit.ino
Normal file
|
@ -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 <KiteLib.h>
|
||||||
|
|
||||||
|
// 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);
|
||||||
|
}
|
|
@ -26,6 +26,7 @@ XBeeSerial KEYWORD1
|
||||||
|
|
||||||
MQTTClient KEYWORD1
|
MQTTClient KEYWORD1
|
||||||
HTTPClient KEYWORD1
|
HTTPClient KEYWORD1
|
||||||
|
RTTYClient KEYWORD1
|
||||||
|
|
||||||
#######################################
|
#######################################
|
||||||
# Methods and Functions (KEYWORD2)
|
# Methods and Functions (KEYWORD2)
|
||||||
|
@ -92,6 +93,9 @@ unsubscribe KEYWORD2
|
||||||
ping KEYWORD2
|
ping KEYWORD2
|
||||||
check KEYWORD2
|
check KEYWORD2
|
||||||
|
|
||||||
|
# RTTY
|
||||||
|
leadIn KEYWORD2
|
||||||
|
|
||||||
# TransportLayer
|
# TransportLayer
|
||||||
openTransportConnection KEYWORD2
|
openTransportConnection KEYWORD2
|
||||||
closeTransportConnection KEYWORD2
|
closeTransportConnection KEYWORD2
|
||||||
|
|
|
@ -17,6 +17,9 @@
|
||||||
#include "modules/SX1279.h"
|
#include "modules/SX1279.h"
|
||||||
#include "modules/XBee.h"
|
#include "modules/XBee.h"
|
||||||
|
|
||||||
|
#include "protocols/PhysicalLayer.h"
|
||||||
|
#include "protocols/RTTY.h"
|
||||||
|
|
||||||
#include "protocols/TransportLayer.h"
|
#include "protocols/TransportLayer.h"
|
||||||
#include "protocols/HTTP.h"
|
#include "protocols/HTTP.h"
|
||||||
#include "protocols/MQTT.h"
|
#include "protocols/MQTT.h"
|
||||||
|
|
|
@ -80,6 +80,7 @@
|
||||||
#define ERR_INVALID_PREAMBLE_LENGTH -18
|
#define ERR_INVALID_PREAMBLE_LENGTH -18
|
||||||
#define ERR_INVALID_GAIN -19
|
#define ERR_INVALID_GAIN -19
|
||||||
#define ERR_WRONG_MODEM -20
|
#define ERR_WRONG_MODEM -20
|
||||||
|
#define ERR_INVALID_RTTY_SHIFT -21
|
||||||
|
|
||||||
// RF69-specific status codes
|
// RF69-specific status codes
|
||||||
#define ERR_INVALID_BIT_RATE -101
|
#define ERR_INVALID_BIT_RATE -101
|
||||||
|
|
89
src/protocols/RTTY.cpp
Normal file
89
src/protocols/RTTY.cpp
Normal file
|
@ -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);
|
||||||
|
}
|
49
src/protocols/RTTY.h
Normal file
49
src/protocols/RTTY.h
Normal file
|
@ -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
|
Loading…
Add table
Reference in a new issue