[RTTY] Added AFSK support

This commit is contained in:
jgromes 2020-04-30 17:11:09 +02:00
parent 0a705f5bb9
commit f7f81cd41e
3 changed files with 182 additions and 11 deletions

View file

@ -0,0 +1,133 @@
/*
RadioLib RTTY Transmit AFSK Example
This example sends RTTY message using SX1278's
FSK modem. The data is modulated as AFSK.
Other modules that can be used for RTTY:
- SX127x/RFM9x
- RF69
- SX1231
- CC1101
- Si443x/RFM2x
For full API reference, see the GitHub Pages
https://jgromes.github.io/RadioLib/
*/
// include the library
#include <RadioLib.h>
// SX1278 has the following connections:
// NSS pin: 10
// DIO0 pin: 2
// RESET pin: 9
// DIO1 pin: 3
SX1278 fsk = new Module(10, 2, 9, 3);
// or using RadioShield
// https://github.com/jgromes/RadioShield
//SX1278 fsk = RadioShield.ModuleA;
// create AFSK client instance using the FSK module
// pin 5 is connected to SX1278 DIO2
AFSKClient audio(&fsk, 5);
// create RTTY client instance using the AFSK instance
RTTYClient rtty(&audio);
void setup() {
Serial.begin(9600);
// initialize SX1278
Serial.print(F("[SX1278] Initializing ... "));
// carrier frequency: 434.0 MHz
// bit rate: 48.0 kbps
// frequency deviation: 50.0 kHz
// Rx bandwidth: 125.0 kHz
// output power: 13 dBm
// current limit: 100 mA
int state = fsk.beginFSK();
// when using one of the non-LoRa modules for RTTY
// (RF69, CC1101, Si4432 etc.), use the basic begin() method
// int state = fsk.begin();
if(state == ERR_NONE) {
Serial.println(F("success!"));
} else {
Serial.print(F("failed, code "));
Serial.println(state);
while(true);
}
// initialize RTTY client
// NOTE: Unlike FSK RTTY, AFSK requires no rounding of
// the frequency shift.
Serial.print(F("[RTTY] Initializing ... "));
// space frequency: 400 Hz
// frequency shift: 170 Hz
// baud rate: 45 baud
// encoding: ASCII (7-bit)
// stop bits: 1
state = rtty.begin(400, 170, 45);
if(state == ERR_NONE) {
Serial.println(F("success!"));
} else {
Serial.print(F("failed, code "));
Serial.println(state);
while(true);
}
/*
// RadioLib also provides ITA2 ("Baudot") support
rtty.begin(400, 170, 45, ITA2);
// All transmissions in loop() (strings and numbers)
// will now be encoded using ITA2 code
// ASCII characters that do not have ITA2 equivalent
// will be sent as NUL (including lower case letters!)
*/
}
void loop() {
Serial.print(F("[RTTY] Sending RTTY data ... "));
// send out idle condition for 500 ms
rtty.idle();
delay(500);
// RTTYClient supports all methods of the Serial class
// Arduino String class
String aStr = "Arduino String";
rtty.println(aStr);
// character array (C-String)
rtty.println("C-String");
// string saved in flash
rtty.println(F("Flash String"));
// character
rtty.println('c');
// byte
// formatting DEC/HEX/OCT/BIN is supported for
// any integer type (byte/int/long)
rtty.println(255, HEX);
// integer number
int i = 1000;
rtty.println(i);
// floating point number
float f = -3.1415;
rtty.println(f, 3);
Serial.println(F("done!"));
// wait for a second before transmitting again
delay(1000);
}

View file

@ -106,12 +106,20 @@ uint16_t ITA2String::getBits(char c) {
RTTYClient::RTTYClient(PhysicalLayer* phy) {
_phy = phy;
_audio = nullptr;
}
RTTYClient::RTTYClient(AFSKClient* audio) {
_phy = audio->_phy;
_audio = audio;
}
int16_t RTTYClient::begin(float base, uint32_t shift, uint16_t rate, uint8_t encoding, uint8_t stopBits) {
// save configuration
_encoding = encoding;
_stopBits = stopBits;
_baseHz = base;
_shiftHz = shift;
switch(encoding) {
case ASCII:
@ -148,15 +156,17 @@ int16_t RTTYClient::begin(float base, uint32_t shift, uint16_t rate, uint8_t enc
// calculate 24-bit frequency
_base = (base * 1000000.0) / _phy->getFreqStep();
// set module frequency deviation to 0
int16_t state = _phy->setFrequencyDeviation(0);
// set module frequency deviation to 0 if using FSK
int16_t state = ERR_NONE;
if(_audio == nullptr) {
state = _phy->setFrequencyDeviation(0);
}
return(state);
}
void RTTYClient::idle() {
_phy->transmitDirect();
transmitDirect();
mark();
}
@ -190,7 +200,7 @@ size_t RTTYClient::write(uint8_t b) {
mark();
}
_phy->standby();
standby();
return(1);
}
@ -391,7 +401,7 @@ size_t RTTYClient::println(double d, int digits) {
void RTTYClient::mark() {
uint32_t start = micros();
_phy->transmitDirect(_base + _shift);
transmitDirect(_base + _shift, _baseHz + _shiftHz);
while(micros() - start < _bitDuration) {
yield();
}
@ -399,7 +409,7 @@ void RTTYClient::mark() {
void RTTYClient::space() {
uint32_t start = micros();
_phy->transmitDirect(_base);
transmitDirect(_base, _baseHz);
while(micros() - start < _bitDuration) {
yield();
}
@ -505,3 +515,19 @@ size_t RTTYClient::printFloat(double number, uint8_t digits) {
return n;
}
int16_t RTTYClient::transmitDirect(uint32_t freq, uint32_t freqHz) {
if(_audio != nullptr) {
return(_audio->tone(freqHz));
} else {
return(_phy->transmitDirect(freq));
}
}
int16_t RTTYClient::standby() {
if(_audio != nullptr) {
return(_audio->noTone());
} else {
return(_phy->standby());
}
}

View file

@ -3,6 +3,7 @@
#include "../../TypeDef.h"
#include "../PhysicalLayer/PhysicalLayer.h"
#include "../AFSK/AFSK.h"
#define ITA2_FIGS 0x1B
#define ITA2_LTRS 0x1F
@ -84,18 +85,25 @@ class ITA2String {
class RTTYClient {
public:
/*!
\brief Default constructor.
\brief Constructor for 2-FSK mode.
\param phy Pointer to the wireless module providing PhysicalLayer communication.
*/
RTTYClient(PhysicalLayer* phy);
/*!
\brief Constructor for AFSK mode.
\param audio Pointer to the AFSK instance providing audio.
*/
RTTYClient(AFSKClient* audio);
// basic methods
/*!
\brief Initialization method.
\param base Base (space) RF frequency to be used in MHz.
\param base Base (space) frequency to be used in MHz (in 2-FSK mode), or the space tone frequency in Hz (in AFSK mode)
\param shift Frequency shift between mark and space in Hz.
@ -147,10 +155,11 @@ class RTTYClient {
private:
#endif
PhysicalLayer* _phy;
AFSKClient* _audio;
uint8_t _encoding;
uint32_t _base;
uint32_t _shift;
uint32_t _base, _baseHz;
uint32_t _shift, _shiftHz;
uint32_t _bitDuration;
uint8_t _dataBits;
uint8_t _stopBits;
@ -160,6 +169,9 @@ class RTTYClient {
size_t printNumber(unsigned long, uint8_t);
size_t printFloat(double, uint8_t);
int16_t transmitDirect(uint32_t freq = 0, uint32_t freqHz = 0);
int16_t standby();
};
#endif