[RTTY] Added support for CC1101 (#4)

This commit is contained in:
jgromes 2018-12-26 11:19:30 +01:00
parent 092559122b
commit 46a3ee4a24
7 changed files with 82 additions and 62 deletions

View file

@ -7,6 +7,7 @@
Other modules that can be used for RTTY: Other modules that can be used for RTTY:
- SX1272/73/76/77/79 - SX1272/73/76/77/79
- RF69 - RF69
- CC1101
*/ */
// include the library // include the library
@ -41,9 +42,13 @@ void setup() {
// initialize RTTY client // initialize RTTY client
// NOTE: RTTY frequency shift will be rounded // NOTE: RTTY frequency shift will be rounded
// to multiples of 61 Hz (hardware limitation) // to the nearest multiple of frequency step size.
// The exact value depends on the module:
// SX127x - 61 Hz
// RF69 - 61 Hz
// CC1101 - 397 Hz
Serial.print(F("[RTTY] Initializing ... ")); Serial.print(F("[RTTY] Initializing ... "));
// low frequency: 434.0 MHz // low ("space") frequency: 434.0 MHz
// frequency shift: 183 Hz // frequency shift: 183 Hz
// baud rate: 45 baud // baud rate: 45 baud
// encoding: ASCII (7-bit) // encoding: ASCII (7-bit)

View file

@ -1,6 +1,6 @@
#include "RF69.h" #include "RF69.h"
RF69::RF69(Module* module) { RF69::RF69(Module* module) : PhysicalLayer(RF69_CRYSTAL_FREQ, RF69_DIV_EXPONENT) {
_mod = module; _mod = module;
_tempOffset = 0; _tempOffset = 0;
} }

View file

@ -6,6 +6,10 @@
#include "../protocols/PhysicalLayer.h" #include "../protocols/PhysicalLayer.h"
// RF69 physical layer properties
#define RF69_CRYSTAL_FREQ 32.0
#define RF69_DIV_EXPONENT 19
// RF69 register map // RF69 register map
#define RF69_REG_FIFO 0x00 #define RF69_REG_FIFO 0x00
#define RF69_REG_OP_MODE 0x01 #define RF69_REG_OP_MODE 0x01

View file

@ -1,6 +1,6 @@
#include "SX127x.h" #include "SX127x.h"
SX127x::SX127x(Module* mod) { SX127x::SX127x(Module* mod) : PhysicalLayer(SX127X_CRYSTAL_FREQ, SX127X_DIV_EXPONENT) {
_mod = mod; _mod = mod;
} }
@ -820,7 +820,7 @@ int16_t SX127x::setBitRate(float br) {
// set bit rate // set bit rate
uint16_t bitRate = 32000 / br; uint16_t bitRate = 32000 / br;
state = _mod->SPIsetRegValue(SX127X_REG_BITRATE_MSB, (bitRate & 0xFF00) >> 8, 7, 0); state = _mod->SPIsetRegValue(SX127X_REG_BITRATE_MSB, (bitRate & 0xFF00) >> 8, 7, 0);
state |= _mod->SPIsetRegValue(SX127X_REG_BITRATE_MSB, bitRate & 0x00FF, 7, 0); state |= _mod->SPIsetRegValue(SX127X_REG_BITRATE_LSB, bitRate & 0x00FF, 7, 0);
// TODO: fractional part of bit rate setting // TODO: fractional part of bit rate setting
if(state == ERR_NONE) { if(state == ERR_NONE) {
SX127x::_br = br; SX127x::_br = br;

View file

@ -6,6 +6,10 @@
#include "../protocols/PhysicalLayer.h" #include "../protocols/PhysicalLayer.h"
// SX127x physical layer properties
#define SX127X_CRYSTAL_FREQ 32.0
#define SX127X_DIV_EXPONENT 19
// SX127x series common LoRa registers // SX127x series common LoRa registers
#define SX127X_REG_FIFO 0x00 #define SX127X_REG_FIFO 0x00
#define SX127X_REG_OP_MODE 0x01 #define SX127X_REG_OP_MODE 0x01

View file

@ -6,7 +6,7 @@
class PhysicalLayer { class PhysicalLayer {
public: public:
// constructor // constructor
// this class is purely virtual and does not require explicit constructor PhysicalLayer(float crysFreq, uint8_t divExp) { _crystalFreq = crysFreq; _divExponent = divExp; }
// basic methods // basic methods
virtual int16_t transmitDirect(uint32_t FRF = 0) = 0; virtual int16_t transmitDirect(uint32_t FRF = 0) = 0;
@ -17,7 +17,12 @@ class PhysicalLayer {
// configuration methods // configuration methods
virtual int16_t setFrequencyDeviation(float freqDev) = 0; virtual int16_t setFrequencyDeviation(float freqDev) = 0;
float getCrystalFreq() { return(_crystalFreq); }
uint8_t getDivExponent() { return(_divExponent); }
private:
float _crystalFreq;
uint8_t _divExponent;
}; };
#endif #endif

View file

@ -103,18 +103,6 @@ RTTYClient::RTTYClient(PhysicalLayer* phy) {
} }
int16_t RTTYClient::begin(float base, uint16_t shift, uint16_t rate, uint8_t encoding, uint8_t stopBits) { int16_t RTTYClient::begin(float base, uint16_t shift, uint16_t rate, uint8_t encoding, uint8_t stopBits) {
// check supplied values
if(shift < 30) {
return(ERR_INVALID_RTTY_SHIFT);
}
// clamp shift to multiples of 61 Hz (SX127x synthesis resolution)
if(shift % 61 < 31) {
_shift = shift / 61;
} else {
_shift = (shift / 61) + 1;
}
// save configuration // save configuration
_encoding = encoding; _encoding = encoding;
_stopBits = stopBits; _stopBits = stopBits;
@ -136,9 +124,23 @@ int16_t RTTYClient::begin(float base, uint16_t shift, uint16_t rate, uint8_t enc
// calculate duration of 1 bit // calculate duration of 1 bit
_bitDuration = (uint32_t)1000000/rate; _bitDuration = (uint32_t)1000000/rate;
// calculate module carrier frequency resolution
uint16_t step = round((_phy->getCrystalFreq() * 1000000) / (uint32_t(1) << _phy->getDivExponent()));
// check minimum shift value
if(shift < step / 2) {
return(ERR_INVALID_RTTY_SHIFT);
}
// round shift to multiples of frequency step size
if(shift % step < (step / 2)) {
_shift = shift / step;
} else {
_shift = (shift / step) + 1;
}
// calculate 24-bit frequency // calculate 24-bit frequency
uint32_t mult = 1; _base = (base * (uint32_t(1) << _phy->getDivExponent())) / _phy->getCrystalFreq();
_base = (base * (mult << 19)) / 32.0;
// set module frequency deviation to 0 // set module frequency deviation to 0
int16_t state = _phy->setFrequencyDeviation(0); int16_t state = _phy->setFrequencyDeviation(0);