From 46a3ee4a24e960dc4341ebccadbdedd109af9ebf Mon Sep 17 00:00:00 2001 From: jgromes Date: Wed, 26 Dec 2018 11:19:30 +0100 Subject: [PATCH] [RTTY] Added support for CC1101 (#4) --- examples/RTTY_Transmit/RTTY_Transmit.ino | 9 ++- src/modules/RF69.cpp | 2 +- src/modules/RF69.h | 88 +++++++++++++----------- src/modules/SX127x.cpp | 4 +- src/modules/SX127x.h | 4 ++ src/protocols/PhysicalLayer.h | 7 +- src/protocols/RTTY.cpp | 30 ++++---- 7 files changed, 82 insertions(+), 62 deletions(-) diff --git a/examples/RTTY_Transmit/RTTY_Transmit.ino b/examples/RTTY_Transmit/RTTY_Transmit.ino index c6947dcf..28e2ed28 100644 --- a/examples/RTTY_Transmit/RTTY_Transmit.ino +++ b/examples/RTTY_Transmit/RTTY_Transmit.ino @@ -7,6 +7,7 @@ Other modules that can be used for RTTY: - SX1272/73/76/77/79 - RF69 + - CC1101 */ // include the library @@ -41,9 +42,13 @@ void setup() { // initialize RTTY client // 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 ... ")); - // low frequency: 434.0 MHz + // low ("space") frequency: 434.0 MHz // frequency shift: 183 Hz // baud rate: 45 baud // encoding: ASCII (7-bit) diff --git a/src/modules/RF69.cpp b/src/modules/RF69.cpp index b69ae1ad..1506ad43 100644 --- a/src/modules/RF69.cpp +++ b/src/modules/RF69.cpp @@ -1,6 +1,6 @@ #include "RF69.h" -RF69::RF69(Module* module) { +RF69::RF69(Module* module) : PhysicalLayer(RF69_CRYSTAL_FREQ, RF69_DIV_EXPONENT) { _mod = module; _tempOffset = 0; } diff --git a/src/modules/RF69.h b/src/modules/RF69.h index 2d42c66f..83682757 100644 --- a/src/modules/RF69.h +++ b/src/modules/RF69.h @@ -6,7 +6,11 @@ #include "../protocols/PhysicalLayer.h" -//RF69 register map +// RF69 physical layer properties +#define RF69_CRYSTAL_FREQ 32.0 +#define RF69_DIV_EXPONENT 19 + +// RF69 register map #define RF69_REG_FIFO 0x00 #define RF69_REG_OP_MODE 0x01 #define RF69_REG_DATA_MODUL 0x02 @@ -86,8 +90,8 @@ #define RF69_REG_TEST_PA2 0x5C #define RF69_REG_TEST_DAGC 0x6F -//RF69 modem settings -//RF69_REG_OP_MODE MSB LSB DESCRIPTION +// RF69 modem settings +// RF69_REG_OP_MODE MSB LSB DESCRIPTION #define RF69_SEQUENCER_OFF 0b00000000 // 7 7 disable automatic sequencer #define RF69_SEQUENCER_ON 0b10000000 // 7 7 enable automatic sequencer #define RF69_LISTEN_OFF 0b00000000 // 6 6 disable Listen mode @@ -99,7 +103,7 @@ #define RF69_TX 0b00001100 // 4 2 transmit #define RF69_RX 0b00010000 // 4 2 receive -//RF69_REG_DATA_MODUL +// RF69_REG_DATA_MODUL #define RF69_PACKET_MODE 0b00000000 // 6 5 packet mode (default) #define RF69_CONTINUOUS_MODE_WITH_SYNC 0b01000000 // 6 5 continuous mode with bit synchronizer #define RF69_CONTINUOUS_MODE 0b01100000 // 6 5 continuous mode without bit synchronizer @@ -112,29 +116,29 @@ #define RF69_OOK_FILTER_BR 0b00000001 // 1 0 OOK modulation filter, f_cutoff = BR #define RF69_OOK_FILTER_2BR 0b00000010 // 1 0 OOK modulation filter, f_cutoff = 2*BR -//RF69_REG_BITRATE_MSB + REG_BITRATE_LSB +// RF69_REG_BITRATE_MSB + REG_BITRATE_LSB #define RF69_BITRATE_MSB 0x1A // 7 0 bit rate setting: rate = F(XOSC) / BITRATE #define RF69_BITRATE_LSB 0x0B // 7 0 default value: 4.8 kbps 0x40 // 7 0 -//RF69_REG_FDEV_MSB + REG_FDEV_LSB +// RF69_REG_FDEV_MSB + REG_FDEV_LSB #define RF69_FDEV_MSB 0x00 // 5 0 frequency deviation: f_dev = f_step * FDEV #define RF69_FDEV_LSB 0x52 // 7 0 default value: 5 kHz -//RF69_REG_FRF_MSB + REG_FRF_MID + REG_FRF_LSB +// RF69_REG_FRF_MSB + REG_FRF_MID + REG_FRF_LSB #define RF69_FRF_MSB 0xE4 // 7 0 carrier frequency setting: f_RF = (F(XOSC) * FRF)/2^19 #define RF69_FRF_MID 0xC0 // 7 0 where F(XOSC) = 32 MHz #define RF69_FRF_LSB 0x00 // 7 0 default value: 915 MHz -//RF69_REG_OSC_1 +// RF69_REG_OSC_1 #define RF69_RC_CAL_START 0b10000000 // 7 7 force RC oscillator calibration #define RF69_RC_CAL_RUNNING 0b00000000 // 6 6 RC oscillator calibration is still running #define RF69_RC_CAL_DONE 0b00000000 // 5 5 RC oscillator calibration has finished -//RF69_REG_AFC_CTRL +// RF69_REG_AFC_CTRL #define RF69_AFC_LOW_BETA_OFF 0b00000000 // 5 5 standard AFC routine #define RF69_AFC_LOW_BETA_ON 0b00100000 // 5 5 improved AFC routine for signals with modulation index less than 2 -//RF69_REG_LISTEN_1 +// RF69_REG_LISTEN_1 #define RF69_LISTEN_RES_IDLE_64_US 0b01000000 // 7 6 resolution of Listen mode idle time: 64 us #define RF69_LISTEN_RES_IDLE_4_1_MS 0b10000000 // 7 6 4.1 ms (default) #define RF69_LISTEN_RES_IDLE_262_MS 0b11000000 // 7 6 262 ms @@ -147,13 +151,13 @@ #define RF69_LISTEN_END_KEEP_RX_TIMEOUT 0b00000010 // 2 1 stay in Rx mode until timeout (default) #define RF69_LISTEN_END_KEEP_RX_TIMEOUT_RESUME 0b00000100 // 2 1 stay in Rx mode until timeout, Listen mode will resume -//RF69_REG_LISTEN_2 +// RF69_REG_LISTEN_2 #define RF69_LISTEN_COEF_IDLE 0xF5 // 7 0 duration of idle phase in Listen mode -//RF69_REG_LISTEN_3 +// RF69_REG_LISTEN_3 #define RF69_LISTEN_COEF_RX 0x20 // 7 0 duration of Rx phase in Listen mode -//RF69_REG_PA_LEVEL +// RF69_REG_PA_LEVEL #define RF69_PA0_OFF 0b00000000 // 7 7 PA0 disabled #define RF69_PA0_ON 0b10000000 // 7 7 PA0 enabled (default) #define RF69_PA1_OFF 0b00000000 // 6 6 PA1 disabled (default) @@ -162,7 +166,7 @@ #define RF69_PA2_ON 0b00100000 // 5 5 PA2 enabled #define RF69_OUTPUT_POWER 0b00011111 // 4 0 output power: P_out = -18 + OUTPUT_POWER -//RF69_REG_PA_RAMP +// RF69_REG_PA_RAMP #define RF69_PA_RAMP_3_4_MS 0b00000000 // 3 0 PA ramp rise/fall time: 3.4 ms #define RF69_PA_RAMP_2_MS 0b00000001 // 3 0 2 ms #define RF69_PA_RAMP_1_MS 0b00000010 // 3 0 1 ms @@ -180,12 +184,12 @@ #define RF69_PA_RAMP_12_US 0b00001110 // 3 0 12 us #define RF69_PA_RAMP_10_US 0b00001111 // 3 0 10 us -//RF69_REG_OCP +// RF69_REG_OCP #define RF69_OCP_OFF 0b00000000 // 4 4 PA overload current protection disabled #define RF69_OCP_ON 0b00100000 // 4 4 PA overload current protection enabled #define RF69_OCP_TRIM 0b00001010 // 3 0 OCP current: I_max(OCP_TRIM = 0b1010) = 95 mA -//RF69_REG_LNA +// RF69_REG_LNA #define RF69_LNA_Z_IN_50_OHM 0b00000000 // 7 7 LNA input impedance: 50 ohm #define RF69_LNA_Z_IN_200_OHM 0b10000000 // 7 7 200 ohm #define RF69_LNA_CURRENT_GAIN 0b00001000 // 5 3 manually set LNA current gain @@ -197,19 +201,19 @@ #define RF69_LNA_GAIN_MAX_36_DB 0b00000101 // 2 0 max gain - 36 dB #define RF69_LNA_GAIN_MAX_48_DB 0b00000110 // 2 0 max gain - 48 dB -//RF69_REG_RX_BW +// RF69_REG_RX_BW #define RF69_DCC_FREQ 0b01000000 // 7 5 DC offset canceller cutoff frequency (4% Rx BW by default) #define RF69_RX_BW_MANT_16 0b00000000 // 4 3 Channel filter bandwidth FSK: RxBw = F(XOSC)/(RxBwMant * 2^(RxBwExp + 2)) #define RF69_RX_BW_MANT_20 0b00001000 // 4 3 OOK: RxBw = F(XOSC)/(RxBwMant * 2^(RxBwExp + 3)) #define RF69_RX_BW_MANT_24 0b00010000 // 4 3 #define RF69_RX_BW_EXP 0b00000101 // 2 0 default RxBwExp value = 5 -//RF69_REG_AFC_BW +// RF69_REG_AFC_BW #define RF69_DCC_FREQ_AFC 0b10000000 // 7 5 default DccFreq parameter for AFC #define RF69_DCC_RX_BW_MANT_AFC 0b00001000 // 4 3 default RxBwMant parameter for AFC #define RF69_DCC_RX_BW_EXP_AFC 0b00000011 // 2 0 default RxBwExp parameter for AFC -//RF69_REG_OOK_PEAK +// RF69_REG_OOK_PEAK #define RF69_OOK_THRESH_FIXED 0b00000000 // 7 6 OOK threshold type: fixed #define RF69_OOK_THRESH_PEAK 0b01000000 // 7 6 peak (default) #define RF69_OOK_THRESH_AVERAGE 0b10000000 // 7 6 average @@ -230,16 +234,16 @@ #define RF69_OOK_PEAK_THRESH_DEC_8_1_CHIP 0b00000110 // 2 0 8 times per chip #define RF69_OOK_PEAK_THRESH_DEC_16_1_CHIP 0b00000111 // 2 0 16 times per chip -//RF69_REG_OOK_AVG +// RF69_REG_OOK_AVG #define RF69_OOK_AVG_THRESH_FILT_32_PI 0b00000000 // 7 6 OOK average filter coefficient: chip rate / 32*pi #define RF69_OOK_AVG_THRESH_FILT_8_PI 0b01000000 // 7 6 chip rate / 8*pi #define RF69_OOK_AVG_THRESH_FILT_4_PI 0b10000000 // 7 6 chip rate / 4*pi (default) #define RF69_OOK_AVG_THRESH_FILT_2_PI 0b11000000 // 7 6 chip rate / 2*pi -//RF69_REG_OOK_FIX +// RF69_REG_OOK_FIX #define RF69_OOK_FIXED_THRESH 0b00000110 // 7 0 default OOK fixed threshold (6 dB) -//RF69_REG_AFC_FEI +// RF69_REG_AFC_FEI #define RF69_FEI_RUNNING 0b00000000 // 6 6 FEI status: on-going #define RF69_FEI_DONE 0b01000000 // 6 6 done #define RF69_FEI_START 0b00100000 // 5 5 force new FEI measurement @@ -252,12 +256,12 @@ #define RF69_AFC_CLEAR 0b00000010 // 1 1 clear AFC register #define RF69_AFC_START 0b00000001 // 0 0 start AFC -//RF69_REG_RSSI_CONFIG +// RF69_REG_RSSI_CONFIG #define RF69_RSSI_RUNNING 0b00000000 // 1 1 RSSI status: on-going #define RF69_RSSI_DONE 0b00000010 // 1 1 done #define RF69_RSSI_START 0b00000001 // 0 0 start RSSI measurement -//RF69_REG_DIO_MAPPING_1 +// RF69_REG_DIO_MAPPING_1 #define RF69_DIO0_CONT_MODE_READY 0b11000000 // 7 6 #define RF69_DIO0_CONT_PLL_LOCK 0b00000000 // 7 6 #define RF69_DIO0_CONT_SYNC_ADDRESS 0b00000000 // 7 6 @@ -283,7 +287,7 @@ #define RF69_DIO1_PACK_TIMEOUT 0b00110000 // 5 4 #define RF69_DIO2_CONT_DATA 0b00000000 // 3 2 -//RF69_REG_DIO_MAPPING_2 +// RF69_REG_DIO_MAPPING_2 #define RF69_CLK_OUT_FXOSC 0b00000000 // 2 0 ClkOut frequency: F(XOSC) #define RF69_CLK_OUT_FXOSC_2 0b00000001 // 2 0 F(XOSC) / 2 #define RF69_CLK_OUT_FXOSC_4 0b00000010 // 2 0 F(XOSC) / 4 @@ -293,7 +297,7 @@ #define RF69_CLK_OUT_RC 0b00000110 // 2 0 RC #define RF69_CLK_OUT_OFF 0b00000111 // 2 0 disabled (default) -//RF69_REG_IRQ_FLAGS_1 +// RF69_REG_IRQ_FLAGS_1 #define RF69_IRQ_MODE_READY 0b10000000 // 7 7 requested mode was set #define RF69_IRQ_RX_READY 0b01000000 // 6 6 Rx mode ready #define RF69_IRQ_TX_READY 0b00100000 // 5 5 Tx mode ready @@ -303,7 +307,7 @@ #define RF69_IRQ_AUTO_MODE 0b00000010 // 1 1 entered intermediate mode #define RF69_SYNC_ADDRESS_MATCH 0b00000001 // 0 0 sync address detected -//RF69_REG_IRQ_FLAGS_2 +// RF69_REG_IRQ_FLAGS_2 #define RF69_IRQ_FIFO_FULL 0b10000000 // 7 7 FIFO is full #define RF69_IRQ_FIFO_NOT_EMPTY 0b01000000 // 6 6 FIFO contains at least 1 byte #define RF69_IRQ_FIFO_LEVEL 0b00100000 // 5 5 FIFO contains more than FifoThreshold bytes @@ -312,22 +316,22 @@ #define RF69_IRQ_PAYLOAD_READY 0b00000100 // 2 2 last payload byte received and CRC check passed #define RF69_IRQ_CRC_OK 0b00000010 // 1 1 CRC check passed -//RF69_REG_RSSI_THRESH +// RF69_REG_RSSI_THRESH #define RF69_RSSI_THRESHOLD 0xE4 // 7 0 RSSI threshold level (2 dB by default) -//RF69_REG_RX_TIMEOUT_1 +// RF69_REG_RX_TIMEOUT_1 #define RF69_TIMEOUT_RX_START_OFF 0x00 // 7 0 RSSI interrupt timeout disabled (default) #define RF69_TIMEOUT_RX_START 0xFF // 7 0 timeout will occur if RSSI interrupt is not received -//RF69_REG_RX_TIMEOUT_2 +// RF69_REG_RX_TIMEOUT_2 #define RF69_TIMEOUT_RSSI_THRESH_OFF 0x00 // 7 0 PayloadReady interrupt timeout disabled (default) #define RF69_TIMEOUT_RSSI_THRESH 0xFF // 7 0 timeout will occur if PayloadReady interrupt is not received -//RF69_REG_PREAMBLE_MSB + REG_PREAMBLE_MSB +// RF69_REG_PREAMBLE_MSB + REG_PREAMBLE_MSB #define RF69_PREAMBLE_MSB 0x00 // 7 0 2-byte preamble size value #define RF69_PREAMBLE_LSB 0x03 // 7 0 -//RF69_REG_SYNC_CONFIG +// RF69_REG_SYNC_CONFIG #define RF69_SYNC_OFF 0b00000000 // 7 7 sync word detection off #define RF69_SYNC_ON 0b10000000 // 7 7 sync word detection on (default) #define RF69_FIFO_FILL_CONDITION_SYNC 0b00000000 // 6 6 FIFO fill condition: on SyncAddress interrupt (default) @@ -335,7 +339,7 @@ #define RF69_SYNC_SIZE 0b00001000 // 5 3 size of sync word: SyncSize + 1 bytes #define RF69_SYNC_TOL 0b00000000 // 2 0 number of tolerated errors in sync word -//RF69_REG_SYNC_VALUE_1 - SYNC_VALUE_8 +// RF69_REG_SYNC_VALUE_1 - SYNC_VALUE_8 #define RF69_SYNC_BYTE_1 0x01 // 7 0 sync word: 1st byte (MSB) #define RF69_SYNC_BYTE_2 0x01 // 7 0 2nd byte #define RF69_SYNC_BYTE_3 0x01 // 7 0 3rd byte @@ -345,7 +349,7 @@ #define RF69_SYNC_BYTE_7 0x01 // 7 0 7th byte #define RF69_SYNC_BYTE_8 0x01 // 7 0 8th byte (LSB) -//RF69_REG_PACKET_CONFIG_1 +// RF69_REG_PACKET_CONFIG_1 #define RF69_PACKET_FORMAT_FIXED 0b00000000 // 7 7 fixed packet length (default) #define RF69_PACKET_FORMAT_VARIABLE 0b10000000 // 7 7 variable packet length #define RF69_DC_FREE_NONE 0b00000000 // 6 5 DC-free encoding: none (default) @@ -359,10 +363,10 @@ #define RF69_ADDRESS_FILTERING_NODE 0b00000010 // 2 1 node #define RF69_ADDRESS_FILTERING_NODE_BROADCAST 0b00000100 // 2 1 node or broadcast -//RF69_REG_PAYLOAD_LENGTH +// RF69_REG_PAYLOAD_LENGTH #define RF69_PAYLOAD_LENGTH 0xFF // 7 0 payload length -//RF69_REG_AUTO_MODES +// RF69_REG_AUTO_MODES #define RF69_ENTER_COND_NONE 0b00000000 // 7 5 condition for entering intermediate mode: none, AutoModes disabled (default) #define RF69_ENTER_COND_FIFO_NOT_EMPTY 0b00100000 // 7 5 FifoNotEmpty rising edge #define RF69_ENTER_COND_FIFO_LEVEL 0b01000000 // 7 5 FifoLevel rising edge @@ -384,12 +388,12 @@ #define RF69_INTER_MODE_RX 0b00000010 // 1 0 Rx #define RF69_INTER_MODE_TX 0b00000011 // 1 0 Tx -//RF69_REG_FIFO_THRESH +// RF69_REG_FIFO_THRESH #define RF69_TX_START_CONDITION_FIFO_LEVEL 0b00000000 // 7 7 packet transmission start condition: FifoLevel #define RF69_TX_START_CONDITION_FIFO_NOT_EMPTY 0b10000000 // 7 7 FifoNotEmpty (default) #define RF69_FIFO_THRESHOLD 0b00001111 // 6 0 default threshold to trigger FifoLevel interrupt -//RF69_REG_PACKET_CONFIG_2 +// RF69_REG_PACKET_CONFIG_2 #define RF69_INTER_PACKET_RX_DELAY 0b00000000 // 7 4 delay between FIFO empty and start of new RSSI phase #define RF69_RESTART_RX 0b00000100 // 2 2 force receiver into wait mode #define RF69_AUTO_RX_RESTART_OFF 0b00000000 // 1 1 auto Rx restart disabled @@ -397,21 +401,21 @@ #define RF69_AES_OFF 0b00000000 // 0 0 AES encryption disabled (default) #define RF69_AES_ON 0b00000001 // 0 0 AES encryption enabled, payload size limited to 66 bytes -//RF69_REG_TEMP_1 +// RF69_REG_TEMP_1 #define RF69_TEMP_MEAS_START 0b00001000 // 3 3 trigger temperature measurement #define RF69_TEMP_MEAS_RUNNING 0b00000100 // 2 2 temperature measurement status: on-going #define RF69_TEMP_MEAS_DONE 0b00000000 // 2 2 done -//RF69_REG_TEST_DAGC +// RF69_REG_TEST_DAGC #define RF69_CONTINUOUS_DAGC_NORMAL 0x00 // 7 0 fading margin improvement: normal mode #define RF69_CONTINUOUS_DAGC_LOW_BETA_ON 0x20 // 7 0 improved mode for AfcLowBetaOn #define RF69_CONTINUOUS_DAGC_LOW_BETA_OFF 0x30 // 7 0 improved mode for AfcLowBetaOff (default) -//RF69_REG_TEST_PA1 +// RF69_REG_TEST_PA1 #define RF69_PA1_NORMAL 0x55 // 7 0 PA_BOOST: none #define RF69_PA1_20_DBM 0x5D // 7 0 +20 dBm -//RF69_REG_TEST_PA2 +// RF69_REG_TEST_PA2 #define RF69_PA2_NORMAL 0x70 // 7 0 PA_BOOST: none #define RF69_PA2_20_DBM 0x7C // 7 0 +20 dBm diff --git a/src/modules/SX127x.cpp b/src/modules/SX127x.cpp index b51e9357..bfb9a552 100644 --- a/src/modules/SX127x.cpp +++ b/src/modules/SX127x.cpp @@ -1,6 +1,6 @@ #include "SX127x.h" -SX127x::SX127x(Module* mod) { +SX127x::SX127x(Module* mod) : PhysicalLayer(SX127X_CRYSTAL_FREQ, SX127X_DIV_EXPONENT) { _mod = mod; } @@ -820,7 +820,7 @@ int16_t SX127x::setBitRate(float br) { // set bit rate 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 & 0x00FF, 7, 0); + state |= _mod->SPIsetRegValue(SX127X_REG_BITRATE_LSB, bitRate & 0x00FF, 7, 0); // TODO: fractional part of bit rate setting if(state == ERR_NONE) { SX127x::_br = br; diff --git a/src/modules/SX127x.h b/src/modules/SX127x.h index f2bc6cd7..02e7efc0 100644 --- a/src/modules/SX127x.h +++ b/src/modules/SX127x.h @@ -6,6 +6,10 @@ #include "../protocols/PhysicalLayer.h" +// SX127x physical layer properties +#define SX127X_CRYSTAL_FREQ 32.0 +#define SX127X_DIV_EXPONENT 19 + // SX127x series common LoRa registers #define SX127X_REG_FIFO 0x00 #define SX127X_REG_OP_MODE 0x01 diff --git a/src/protocols/PhysicalLayer.h b/src/protocols/PhysicalLayer.h index 21327295..efeb74a0 100644 --- a/src/protocols/PhysicalLayer.h +++ b/src/protocols/PhysicalLayer.h @@ -6,7 +6,7 @@ class PhysicalLayer { public: // constructor - // this class is purely virtual and does not require explicit constructor + PhysicalLayer(float crysFreq, uint8_t divExp) { _crystalFreq = crysFreq; _divExponent = divExp; } // basic methods virtual int16_t transmitDirect(uint32_t FRF = 0) = 0; @@ -17,7 +17,12 @@ class PhysicalLayer { // configuration methods virtual int16_t setFrequencyDeviation(float freqDev) = 0; + float getCrystalFreq() { return(_crystalFreq); } + uint8_t getDivExponent() { return(_divExponent); } + private: + float _crystalFreq; + uint8_t _divExponent; }; #endif diff --git a/src/protocols/RTTY.cpp b/src/protocols/RTTY.cpp index a40303a0..9a601e47 100644 --- a/src/protocols/RTTY.cpp +++ b/src/protocols/RTTY.cpp @@ -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) { - // 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 _encoding = encoding; _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 _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 - uint32_t mult = 1; - _base = (base * (mult << 19)) / 32.0; + _base = (base * (uint32_t(1) << _phy->getDivExponent())) / _phy->getCrystalFreq(); // set module frequency deviation to 0 int16_t state = _phy->setFrequencyDeviation(0);