add custom bitrate command

This commit is contained in:
franchioping 2026-04-02 16:29:51 +01:00
parent 240306de6e
commit 034caf2f11
2 changed files with 360 additions and 255 deletions

View File

@ -551,6 +551,7 @@ void RFM69::sendFrame(uint16_t toAddress, const void *buffer,
} }
if (success) { if (success) {
ESP_LOGI("RADIO_TX", "SENT.");
} else { } else {
ESP_LOGE("RADIO_TX", "Step 5: FAILED - PACKETSENT bit never flipped!"); ESP_LOGE("RADIO_TX", "Step 5: FAILED - PACKETSENT bit never flipped!");
// Check IRQ Flags to see what state it's stuck in // Check IRQ Flags to see what state it's stuck in
@ -1168,6 +1169,44 @@ void RFM69::set300KBPS() {
// ^^->DC: 00=none, 01=manchester, 10=whitening // ^^->DC: 00=none, 01=manchester, 10=whitening
} }
void RFM69::setCustomBitrate(uint32_t targetBitrate) {
// 1. Calculate Bitrate Divider
// Formula: 32,000,000 / targetBitrate
uint16_t bitrateField = 32000000 / targetBitrate;
writeReg(0x03, (bitrateField >> 8) & 0xFF); // MSB
writeReg(0x04, bitrateField & 0xFF); // LSB
// 2. Calculate Frequency Deviation (FDEV)
// We want FDEV to be roughly 0.5 to 1.0 times the Bitrate for reliability
// Formula: FDEV = targetBitrate / 2 (narrower) or targetBitrate (wider)
// Register Value = FDEV / 61.035
uint32_t fdev = targetBitrate / 1; // 1:1 ratio is robust
uint16_t fdevField = fdev / 61;
writeReg(0x05, (fdevField >> 8) & 0xFF); // MSB
writeReg(0x06, fdevField & 0xFF); // LSB
// 3. Set Receiver Bandwidth (RXBW)
// This must be larger than (2 * FDEV) + Bitrate.
// We use a simplified lookup for common bandwidths (0x19 register)
byte bwValue = 0x02; // Default 125kHz
if (targetBitrate <= 1200)
bwValue = 0x07; // 7.8 kHz
else if (targetBitrate <= 4800)
bwValue = 0x05; // 31.3 kHz
else if (targetBitrate <= 19200)
bwValue = 0x03; // 62.5 kHz
else if (targetBitrate <= 38400)
bwValue = 0x02; // 125.0 kHz
else if (targetBitrate <= 100000)
bwValue = 0x01; // 250.0 kHz
else
bwValue = 0x00; // 500.0 kHz (Max)
writeReg(0x19, 0x40 | bwValue); // 0x40 maintains DCC setting
writeReg(0x1A, 0x40 | bwValue); // Set AFC Bandwidth same as RXBW
}
//============================================================================= //=============================================================================
// setLNA() - disable the AGC and set a manual gain to attenuate input signal // setLNA() - disable the AGC and set a manual gain to attenuate input signal
// Makes receiver hear a "weaker" signal. // Makes receiver hear a "weaker" signal.

548
RFM69.h
View File

@ -1,5 +1,6 @@
// ********************************************************************************** // **********************************************************************************
// Driver definition for HopeRF RFM69W/RFM69HW/RFM69CW/RFM69HCW, Semtech SX1231/1231H // Driver definition for HopeRF RFM69W/RFM69HW/RFM69CW/RFM69HCW, Semtech
// SX1231/1231H
// ********************************************************************************** // **********************************************************************************
// Copyright LowPowerLab LLC 2018, https://www.LowPowerLab.com/contact // Copyright LowPowerLab LLC 2018, https://www.LowPowerLab.com/contact
// ********************************************************************************** // **********************************************************************************
@ -25,319 +26,384 @@
// ********************************************************************************** // **********************************************************************************
#ifndef RFM69_h #ifndef RFM69_h
#define RFM69_h #define RFM69_h
#include <Arduino.h> // assumes Arduino IDE v1.0 or greater #include <Arduino.h> // assumes Arduino IDE v1.0 or greater
#include <SPI.h> #include <SPI.h>
////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////
//Platform and digitalPinToInterrupt definitions credit to RadioHead// // Platform and digitalPinToInterrupt definitions credit to RadioHead//
////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////
// Select platform automatically, if possible // Select platform automatically, if possible
#ifndef RF69_PLATFORM #ifndef RF69_PLATFORM
#if (MPIDE>=150 && defined(ARDUINO)) #if (MPIDE >= 150 && defined(ARDUINO))
// Using ChipKIT Core on Arduino IDE // Using ChipKIT Core on Arduino IDE
#define RF69_PLATFORM RF69_PLATFORM_CHIPKIT_CORE #define RF69_PLATFORM RF69_PLATFORM_CHIPKIT_CORE
#elif defined(MPIDE) #elif defined(MPIDE)
// Uno32 under old MPIDE, which has been discontinued: // Uno32 under old MPIDE, which has been discontinued:
#define RF69_PLATFORM RF69_PLATFORM_UNO32 #define RF69_PLATFORM RF69_PLATFORM_UNO32
#elif defined(NRF51) #elif defined(NRF51)
#define RF69_PLATFORM RF69_PLATFORM_NRF51 #define RF69_PLATFORM RF69_PLATFORM_NRF51
#elif defined(NRF52) #elif defined(NRF52)
#define RF69_PLATFORM RF69_PLATFORM_NRF52 #define RF69_PLATFORM RF69_PLATFORM_NRF52
#elif defined(ESP8266) #elif defined(ESP8266)
#define RF69_PLATFORM RF69_PLATFORM_ESP8266 #define RF69_PLATFORM RF69_PLATFORM_ESP8266
#elif defined(ESP32) #elif defined(ESP32)
#define RF69_PLATFORM RF69_PLATFORM_ESP32 #define RF69_PLATFORM RF69_PLATFORM_ESP32
#elif defined(ARDUINO) #elif defined(ARDUINO)
#define RF69_PLATFORM RF69_PLATFORM_ARDUINO #define RF69_PLATFORM RF69_PLATFORM_ARDUINO
#elif defined(AVR_ATtinyxy7) || defined(AVR_ATtinyxy6) // MegaTinyCore AVR Series-1 #elif defined(AVR_ATtinyxy7) || \
#define RF69_PLATFORM RF69_PLATFORM_ARDUINO defined(AVR_ATtinyxy6) // MegaTinyCore AVR Series-1
#elif defined(__MSP430G2452__) || defined(__MSP430G2553__) #define RF69_PLATFORM RF69_PLATFORM_ARDUINO
#define RF69_PLATFORM RF69_PLATFORM_MSP430 #elif defined(__MSP430G2452__) || defined(__MSP430G2553__)
#elif defined(MCU_STM32F103RE) #define RF69_PLATFORM RF69_PLATFORM_MSP430
#define RF69_PLATFORM RF69_PLATFORM_STM32 #elif defined(MCU_STM32F103RE)
#elif defined(STM32F2XX) #define RF69_PLATFORM RF69_PLATFORM_STM32
#define RF69_PLATFORM RF69_PLATFORM_STM32F2 #elif defined(STM32F2XX)
#elif defined(USE_STDPERIPH_DRIVER) #define RF69_PLATFORM RF69_PLATFORM_STM32F2
#define RF69_PLATFORM RF69_PLATFORM_STM32STD #elif defined(USE_STDPERIPH_DRIVER)
#elif defined(RASPBERRY_PI) #define RF69_PLATFORM RF69_PLATFORM_STM32STD
#define RF69_PLATFORM RF69_PLATFORM_RASPI #elif defined(RASPBERRY_PI)
#elif defined(__unix__) // Linux #define RF69_PLATFORM RF69_PLATFORM_RASPI
#define RF69_PLATFORM RF69_PLATFORM_UNIX #elif defined(__unix__) // Linux
#elif defined(__APPLE__) // OSX #define RF69_PLATFORM RF69_PLATFORM_UNIX
#define RF69_PLATFORM RF69_PLATFORM_UNIX #elif defined(__APPLE__) // OSX
#else #define RF69_PLATFORM RF69_PLATFORM_UNIX
#error Platform not defined! #else
#endif #error Platform not defined!
#endif
#endif #endif
#if defined(ESP8266) || defined(ESP32) #if defined(ESP8266) || defined(ESP32)
#define ISR_PREFIX ICACHE_RAM_ATTR #define ISR_PREFIX ICACHE_RAM_ATTR
#else #else
#define ISR_PREFIX #define ISR_PREFIX
#endif #endif
// digitalPinToInterrupt is not available prior to Arduino 1.5.6 and 1.0.6 // digitalPinToInterrupt is not available prior to Arduino 1.5.6 and 1.0.6
// See http://arduino.cc/en/Reference/attachInterrupt // See http://arduino.cc/en/Reference/attachInterrupt
#ifndef NOT_AN_INTERRUPT #ifndef NOT_AN_INTERRUPT
#define NOT_AN_INTERRUPT -1 #define NOT_AN_INTERRUPT -1
#endif #endif
#ifndef digitalPinToInterrupt #ifndef digitalPinToInterrupt
#if (RF69_PLATFORM == RF69_PLATFORM_ARDUINO) && !defined(__arm__) #if (RF69_PLATFORM == RF69_PLATFORM_ARDUINO) && !defined(__arm__)
#if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) #if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
// Arduino Mega, Mega ADK, Mega Pro // Arduino Mega, Mega ADK, Mega Pro
// 2->0, 3->1, 21->2, 20->3, 19->4, 18->5 // 2->0, 3->1, 21->2, 20->3, 19->4, 18->5
#define digitalPinToInterrupt(p) ((p) == 2 ? 0 : ((p) == 3 ? 1 : ((p) >= 18 && (p) <= 21 ? 23 - (p) : NOT_AN_INTERRUPT))) #define digitalPinToInterrupt(p) \
#elif defined(__AVR_ATmega1284__) || defined(__AVR_ATmega1284P__) ((p) == 2 \
// Arduino 1284 and 1284P - See Maniacbug and Optiboot ? 0 \
// 10->0, 11->1, 2->2 : ((p) == 3 ? 1 \
#define digitalPinToInterrupt(p) ((p) == 10 ? 0 : ((p) == 11 ? 1 : ((p) == 2 ? 2 : NOT_AN_INTERRUPT))) : ((p) >= 18 && (p) <= 21 ? 23 - (p) : NOT_AN_INTERRUPT)))
#elif defined(__AVR_ATmega32U4__) #elif defined(__AVR_ATmega1284__) || defined(__AVR_ATmega1284P__)
// Leonardo, Yun, Micro, Pro Micro, Flora, Esplora // Arduino 1284 and 1284P - See Maniacbug and Optiboot
// 3->0, 2->1, 0->2, 1->3, 7->4 // 10->0, 11->1, 2->2
#define digitalPinToInterrupt(p) ((p) == 0 ? 2 : ((p) == 1 ? 3 : ((p) == 2 ? 1 : ((p) == 3 ? 0 : ((p) == 7 ? 4 : NOT_AN_INTERRUPT))))) #define digitalPinToInterrupt(p) \
#else ((p) == 10 ? 0 : ((p) == 11 ? 1 : ((p) == 2 ? 2 : NOT_AN_INTERRUPT)))
// All other arduino except Due: #elif defined(__AVR_ATmega32U4__)
// Serial Arduino, Extreme, NG, BT, Uno, Diecimila, Duemilanove, Nano, Menta, Pro, Mini 04, Fio, LilyPad, Ethernet etc // Leonardo, Yun, Micro, Pro Micro, Flora, Esplora
// 2->0, 3->1 // 3->0, 2->1, 0->2, 1->3, 7->4
#define digitalPinToInterrupt(p) ((p) == 2 ? 0 : ((p) == 3 ? 1 : NOT_AN_INTERRUPT)) #define digitalPinToInterrupt(p) \
#endif ((p) == 0 \
#elif (RF69_PLATFORM == RF69_PLATFORM_UNO32) || (RF69_PLATFORM == RF69_PLATFORM_CHIPKIT_CORE) ? 2 \
// Hmmm, this is correct for Uno32, but what about other boards on ChipKIT Core? : ((p) == 1 \
#define digitalPinToInterrupt(p) ((p) == 38 ? 0 : ((p) == 2 ? 1 : ((p) == 7 ? 2 : ((p) == 8 ? 3 : ((p) == 735 ? 4 : NOT_AN_INTERRUPT))))) ? 3 \
#else : ((p) == 2 \
// Everything else (including Due and Teensy) interrupt number the same as the interrupt pin number ? 1 \
#define digitalPinToInterrupt(p) (p) : ((p) == 3 ? 0 : ((p) == 7 ? 4 : NOT_AN_INTERRUPT)))))
#endif #else
#elif defined(__SAMD21__) || defined (__SAMD51__) //Arduino.h in most/all cores wrongly "#define digitalPinToInterrupt(P) (P)" after calling variant.h // All other arduino except Due:
#define digitalPinToInterrupt(P) (g_APinDescription[P].ulExtInt) // Serial Arduino, Extreme, NG, BT, Uno, Diecimila, Duemilanove, Nano, Menta,
// Pro, Mini 04, Fio, LilyPad, Ethernet etc 2->0, 3->1
#define digitalPinToInterrupt(p) \
((p) == 2 ? 0 : ((p) == 3 ? 1 : NOT_AN_INTERRUPT))
#endif
#elif (RF69_PLATFORM == RF69_PLATFORM_UNO32) || \
(RF69_PLATFORM == RF69_PLATFORM_CHIPKIT_CORE)
// Hmmm, this is correct for Uno32, but what about other boards on ChipKIT Core?
#define digitalPinToInterrupt(p) \
((p) == 38 \
? 0 \
: ((p) == 2 \
? 1 \
: ((p) == 7 \
? 2 \
: ((p) == 8 ? 3 : ((p) == 735 ? 4 : NOT_AN_INTERRUPT)))))
#else
// Everything else (including Due and Teensy) interrupt number the same as the
// interrupt pin number
#define digitalPinToInterrupt(p) (p)
#endif
#elif defined(__SAMD21__) || \
defined( \
__SAMD51__) // Arduino.h in most/all cores wrongly "#define
// digitalPinToInterrupt(P) (P)" after calling variant.h
#define digitalPinToInterrupt(P) (g_APinDescription[P].ulExtInt)
#endif #endif
// On some platforms, attachInterrupt() takes a pin number, not an interrupt number // On some platforms, attachInterrupt() takes a pin number, not an interrupt
#if (defined(TEENSYDUINO))||((RF69_PLATFORM == RF69_PLATFORM_ARDUINO) && defined (__arm__) && (defined(ARDUINO_ARCH_SAMD) || defined(ARDUINO_SAM_DUE))) // number
#define RF69_ATTACHINTERRUPT_TAKES_PIN_NUMBER #if (defined(TEENSYDUINO)) || \
((RF69_PLATFORM == RF69_PLATFORM_ARDUINO) && defined(__arm__) && \
(defined(ARDUINO_ARCH_SAMD) || defined(ARDUINO_SAM_DUE)))
#define RF69_ATTACHINTERRUPT_TAKES_PIN_NUMBER
#endif #endif
//////////////////////////////////////////////////// ////////////////////////////////////////////////////
#define RF69_SPI_CS SS // SS is the SPI slave select pin, for instance D10 on ATmega328 #define RF69_SPI_CS \
SS // SS is the SPI slave select pin, for instance D10 on ATmega328
// INT0 on AVRs should be connected to RFM69's DIO0 (ex on ATmega328 it's D2, on ATmega644/1284 it's D2) // INT0 on AVRs should be connected to RFM69's DIO0 (ex on ATmega328 it's D2, on
#if defined(__AVR_ATmega168__) || defined(__AVR_ATmega328P__) || defined(__AVR_ATmega88) || defined(__AVR_ATmega8__) || defined(__AVR_ATmega88__) // ATmega644/1284 it's D2)
#define RF69_IRQ_PIN 2 #if defined(__AVR_ATmega168__) || defined(__AVR_ATmega328P__) || \
defined(__AVR_ATmega88) || defined(__AVR_ATmega8__) || \
defined(__AVR_ATmega88__)
#define RF69_IRQ_PIN 2
#elif defined(__AVR_ATmega644P__) || defined(__AVR_ATmega1284P__) #elif defined(__AVR_ATmega644P__) || defined(__AVR_ATmega1284P__)
#define RF69_IRQ_PIN 2 #define RF69_IRQ_PIN 2
#elif defined(__AVR_ATmega32U4__) #elif defined(__AVR_ATmega32U4__)
#define RF69_IRQ_PIN 7 #define RF69_IRQ_PIN 7
#elif defined(__STM32F1__) || defined(STM32F1) #elif defined(__STM32F1__) || defined(STM32F1)
#define RF69_IRQ_PIN PA3 #define RF69_IRQ_PIN PA3
#define RF69_ATTACHINTERRUPT_TAKES_PIN_NUMBER #define RF69_ATTACHINTERRUPT_TAKES_PIN_NUMBER
#elif defined(MOTEINO_M0) #elif defined(MOTEINO_M0)
#define RF69_IRQ_PIN 9 #define RF69_IRQ_PIN 9
#elif defined(__SAMD51__) #elif defined(__SAMD51__)
#define RF69_IRQ_PIN 18 #define RF69_IRQ_PIN 18
#elif defined(ARDUINO_SAMD_ZERO) //includes Feather SAMD #elif defined(ARDUINO_SAMD_ZERO) // includes Feather SAMD
#define RF69_IRQ_PIN 3 #define RF69_IRQ_PIN 3
#elif defined(ESP8266) #elif defined(ESP8266)
#define RF69_IRQ_PIN 4 #define RF69_IRQ_PIN 4
#elif defined(ESP32) #elif defined(ESP32)
#define RF69_IRQ_PIN 2 #define RF69_IRQ_PIN 2
#else #else
#define RF69_IRQ_PIN 2 #define RF69_IRQ_PIN 2
#endif #endif
#define RF69_MAX_DATA_LEN 61 // to take advantage of the built in AES/CRC we want to limit the frame size to the internal FIFO size (66 bytes - 3 bytes overhead - 2 bytes crc) #define RF69_MAX_DATA_LEN \
#define CSMA_LIMIT -90 // upper RX signal sensitivity threshold in dBm for carrier sense access 61 // to take advantage of the built in AES/CRC we want to limit the frame
#define RF69_MODE_SLEEP 0 // XTAL OFF // size to the internal FIFO size (66 bytes - 3 bytes overhead - 2 bytes
#define RF69_MODE_STANDBY 1 // XTAL ON // crc)
#define RF69_MODE_SYNTH 2 // PLL ON #define CSMA_LIMIT \
#define RF69_MODE_RX 3 // RX MODE -90 // upper RX signal sensitivity threshold in dBm for carrier sense access
#define RF69_MODE_TX 4 // TX MODE #define RF69_MODE_SLEEP 0 // XTAL OFF
#define RF69_MODE_STANDBY 1 // XTAL ON
#define RF69_MODE_SYNTH 2 // PLL ON
#define RF69_MODE_RX 3 // RX MODE
#define RF69_MODE_TX 4 // TX MODE
// available frequency bands // available frequency bands
#define RF69_315MHZ 31 // non trivial values to avoid misconfiguration #define RF69_315MHZ 31 // non trivial values to avoid misconfiguration
#define RF69_433MHZ 43 #define RF69_433MHZ 43
#define RF69_868MHZ 86 #define RF69_868MHZ 86
#define RF69_915MHZ 91 #define RF69_915MHZ 91
#define null 0 #define null 0
#define COURSE_TEMP_COEF -90 // puts the temperature reading in the ballpark, user can fine tune the returned value #define COURSE_TEMP_COEF \
#define RF69_BROADCAST_ADDR 0 -90 // puts the temperature reading in the ballpark, user can fine tune the
#define RF69_CSMA_LIMIT_MS 1000 // returned value
#define RF69_TX_LIMIT_MS 1000 #define RF69_BROADCAST_ADDR 0
#define RF69_FXOSC 32000000L #define RF69_CSMA_LIMIT_MS 1000
#define RF69_FSTEP 61.03515625 // == FXOSC / 2^19 = 32MHz / 2^19 (p13 in datasheet) #define RF69_TX_LIMIT_MS 1000
#define RF69_FXOSC 32000000L
#define RF69_FSTEP \
61.03515625 // == FXOSC / 2^19 = 32MHz / 2^19 (p13 in datasheet)
// TWS: define CTLbyte bits // TWS: define CTLbyte bits
#define RFM69_CTL_SENDACK 0x80 #define RFM69_CTL_SENDACK 0x80
#define RFM69_CTL_REQACK 0x40 #define RFM69_CTL_REQACK 0x40
#define RFM69_ACK_TIMEOUT 30 // 30ms roundtrip req for 61byte packets #define RFM69_ACK_TIMEOUT 30 // 30ms roundtrip req for 61byte packets
// Native hardware ListenMode is experimental // Native hardware ListenMode is experimental
// It was determined to be buggy and unreliable, see https://lowpowerlab.com/forum/low-power-techniques/ultra-low-power-listening-mode-for-battery-nodes/msg20261/#msg20261 // It was determined to be buggy and unreliable, see
// https://lowpowerlab.com/forum/low-power-techniques/ultra-low-power-listening-mode-for-battery-nodes/msg20261/#msg20261
// uncomment to try ListenMode, adds ~1K to compiled size // uncomment to try ListenMode, adds ~1K to compiled size
// FYI - 10bit addressing is not supported in ListenMode // FYI - 10bit addressing is not supported in ListenMode
//#define RF69_LISTENMODE_ENABLE // #define RF69_LISTENMODE_ENABLE
#if defined(RF69_LISTENMODE_ENABLE) #if defined(RF69_LISTENMODE_ENABLE)
// By default, receive for 256uS in listen mode and idle for ~1s // By default, receive for 256uS in listen mode and idle for ~1s
#define DEFAULT_LISTEN_RX_US 256 #define DEFAULT_LISTEN_RX_US 256
#define DEFAULT_LISTEN_IDLE_US 1000000 #define DEFAULT_LISTEN_IDLE_US 1000000
#endif #endif
class RFM69 { class RFM69 {
public: public:
static uint8_t DATA[RF69_MAX_DATA_LEN+1]; // RX/TX payload buffer, including end of string NULL char static uint8_t DATA[RF69_MAX_DATA_LEN + 1]; // RX/TX payload buffer, including
static uint8_t DATALEN; // end of string NULL char
static uint16_t SENDERID; static uint8_t DATALEN;
static uint16_t TARGETID; // should match _address static uint16_t SENDERID;
static uint8_t PAYLOADLEN; static uint16_t TARGETID; // should match _address
static uint8_t ACK_REQUESTED; static uint8_t PAYLOADLEN;
static uint8_t ACK_RECEIVED; // should be polled immediately after sending a packet with ACK request static uint8_t ACK_REQUESTED;
static int16_t RSSI; // most accurate RSSI during reception (closest to the reception). RSSI of last packet. static uint8_t ACK_RECEIVED; // should be polled immediately after sending a
static uint8_t _mode; // should be protected? // packet with ACK request
static int16_t RSSI; // most accurate RSSI during reception (closest to the
// reception). RSSI of last packet.
static uint8_t _mode; // should be protected?
RFM69(uint8_t slaveSelectPin, uint8_t interruptPin, bool isRFM69HW, uint8_t interruptNum __attribute__((unused))) //interruptNum is now deprecated RFM69(uint8_t slaveSelectPin, uint8_t interruptPin, bool isRFM69HW,
: RFM69(slaveSelectPin, interruptPin, isRFM69HW){}; uint8_t interruptNum
__attribute__((unused))) // interruptNum is now deprecated
: RFM69(slaveSelectPin, interruptPin, isRFM69HW) {};
RFM69(uint8_t slaveSelectPin=RF69_SPI_CS, uint8_t interruptPin=RF69_IRQ_PIN, bool isRFM69HW_HCW=false, SPIClass *spi=nullptr); RFM69(uint8_t slaveSelectPin = RF69_SPI_CS,
uint8_t interruptPin = RF69_IRQ_PIN, bool isRFM69HW_HCW = false,
SPIClass *spi = nullptr);
bool initialize(uint8_t freqBand, uint16_t ID, uint8_t networkID=1); bool initialize(uint8_t freqBand, uint16_t ID, uint8_t networkID = 1);
uint8_t getVersion(); uint8_t getVersion();
uint16_t getAddress(); uint16_t getAddress();
void setAddress(uint16_t addr); void setAddress(uint16_t addr);
uint8_t getNetwork(); uint8_t getNetwork();
void setNetwork(uint8_t networkID); void setNetwork(uint8_t networkID);
void setIsrCallback(void (*callback)()); void setIsrCallback(void (*callback)());
virtual bool canSend(); virtual bool canSend();
virtual void send(uint16_t toAddress, const void* buffer, uint8_t bufferSize, bool requestACK=false); virtual void send(uint16_t toAddress, const void *buffer, uint8_t bufferSize,
virtual bool sendWithRetry(uint16_t toAddress, const void* buffer, uint8_t bufferSize, uint8_t retries=2, uint8_t retryWaitTime=RFM69_ACK_TIMEOUT); bool requestACK = false);
virtual bool receiveDone(); virtual bool sendWithRetry(uint16_t toAddress, const void *buffer,
bool ACKReceived(uint16_t fromNodeID); uint8_t bufferSize, uint8_t retries = 2,
bool ACKRequested(); uint8_t retryWaitTime = RFM69_ACK_TIMEOUT);
virtual void sendACK(const void* buffer = "", uint8_t bufferSize=0); virtual bool receiveDone();
uint32_t getFrequency(); bool ACKReceived(uint16_t fromNodeID);
void setFrequency(uint32_t freqHz); bool ACKRequested();
uint32_t getFrequencyDeviation(); virtual void sendACK(const void *buffer = "", uint8_t bufferSize = 0);
uint32_t getBitRate(); uint32_t getFrequency();
void encrypt(const char* key); void setFrequency(uint32_t freqHz);
void setCS(uint8_t newSPISlaveSelect); uint32_t getFrequencyDeviation();
bool setIrq(uint8_t newIRQPin); uint32_t getBitRate();
int16_t readRSSI(bool forceTrigger=false); // *current* signal strength indicator; e.g. < -90dBm says the frequency channel is free + ready to transmit void encrypt(const char *key);
bool getSpyMode(); void setCS(uint8_t newSPISlaveSelect);
void spyMode(bool onOff=true); bool setIrq(uint8_t newIRQPin);
bool isSyncOn(); int16_t
uint8_t getSyncSize(); readRSSI(bool forceTrigger =
bool isCrcOn(); false); // *current* signal strength indicator; e.g. < -90dBm
bool isAesOn(); // says the frequency channel is free + ready to transmit
//void promiscuous(bool onOff=true); // replaced with spyMode() bool getSpyMode();
virtual void setHighPower(bool _isRFM69HW_HCW=true); // has to be called after initialize() for RFM69 HW/HCW void spyMode(bool onOff = true);
bool isHighPower(); bool isSyncOn();
virtual uint8_t getPowerLevel(); // get powerLevel uint8_t getSyncSize();
virtual void setPowerLevel(uint8_t level); // reduce/increase transmit power level bool isCrcOn();
virtual int8_t setPowerDBm(int8_t dBm); // reduce/increase transmit power level, in dBm bool isAesOn();
double dBm_to_mW(uint8_t dBm); // convert dBm to mW // void promiscuous(bool onOff=true); // replaced with spyMode()
uint8_t getOutputPower(); virtual void setHighPower(
void sleep(); bool _isRFM69HW_HCW =
uint8_t readTemperature(uint8_t calFactor=0); // get CMOS temperature (8bit) true); // has to be called after initialize() for RFM69 HW/HCW
void rcCalibration(); // calibrate the internal RC oscillator for use in wide temperature variations - see datasheet section [4.3.5. RC Timer Accuracy] bool isHighPower();
void set300KBPS(); virtual uint8_t getPowerLevel(); // get powerLevel
uint8_t setLNA(uint8_t newReg); virtual void
setPowerLevel(uint8_t level); // reduce/increase transmit power level
virtual int8_t
setPowerDBm(int8_t dBm); // reduce/increase transmit power level, in dBm
double dBm_to_mW(uint8_t dBm); // convert dBm to mW
uint8_t getOutputPower();
void sleep();
uint8_t readTemperature(uint8_t calFactor = 0); // get CMOS temperature (8bit)
void rcCalibration(); // calibrate the internal RC oscillator for use in wide
// temperature variations - see datasheet section
// [4.3.5. RC Timer Accuracy]
void set300KBPS();
// allow hacking registers by making these public void setCustomBitrate(uint32_t targetBitrate);
uint8_t readReg(uint8_t addr); uint8_t setLNA(uint8_t newReg);
void writeReg(uint8_t addr, uint8_t val);
void readAllRegs();
void readAllRegsCompact();
// ListenMode sleep/timer // allow hacking registers by making these public
void listenModeSleep(uint16_t millisInterval); uint8_t readReg(uint8_t addr);
void endListenModeSleep(); void writeReg(uint8_t addr, uint8_t val);
virtual void setMode(uint8_t mode); void readAllRegs();
virtual void select(); void readAllRegsCompact();
virtual void unselect();
protected: // ListenMode sleep/timer
static void isr0(); void listenModeSleep(uint16_t millisInterval);
void interruptHandler(); void endListenModeSleep();
virtual void interruptHook(uint8_t CTLbyte __attribute__((unused))) {}; virtual void setMode(uint8_t mode);
static volatile bool _haveData; virtual void select();
static RFM69 *_instance; virtual void unselect();
virtual void sendFrame(uint16_t toAddress, const void* buffer, uint8_t size, bool requestACK=false, bool sendACK=false);
// for ListenMode sleep/timer protected:
static void delayIrq(); static void isr0();
void interruptHandler();
virtual void interruptHook(uint8_t CTLbyte __attribute__((unused))) {};
static volatile bool _haveData;
static RFM69 *_instance;
virtual void sendFrame(uint16_t toAddress, const void *buffer, uint8_t size,
bool requestACK = false, bool sendACK = false);
uint8_t _slaveSelectPin; // for ListenMode sleep/timer
uint8_t _interruptPin; static void delayIrq();
uint8_t _interruptNum;
uint16_t _address; uint8_t _slaveSelectPin;
uint8_t _networkID; uint8_t _interruptPin;
bool _spyMode; uint8_t _interruptNum;
uint8_t _powerLevel; uint16_t _address;
bool _isRFM69HW; uint8_t _networkID;
SPIClass *_spi; bool _spyMode;
void (*_isrCallback)() = nullptr; uint8_t _powerLevel;
#if defined (SPCR) && defined (SPSR) bool _isRFM69HW;
uint8_t _SPCR; SPIClass *_spi;
uint8_t _SPSR; void (*_isrCallback)() = nullptr;
#if defined(SPCR) && defined(SPSR)
uint8_t _SPCR;
uint8_t _SPSR;
#endif #endif
#ifdef SPI_HAS_TRANSACTION #ifdef SPI_HAS_TRANSACTION
SPISettings _settings; SPISettings _settings;
#endif #endif
virtual void receiveBegin(); virtual void receiveBegin();
//virtual void setMode(uint8_t mode); // virtual void setMode(uint8_t mode);
virtual void setHighPowerRegs(bool enable); virtual void setHighPowerRegs(bool enable);
//virtual void select(); // virtual void select();
//virtual void unselect(); // virtual void unselect();
#if defined(RF69_LISTENMODE_ENABLE) #if defined(RF69_LISTENMODE_ENABLE)
static RFM69* selfPointer; static RFM69 *selfPointer;
//============================================================================= //=============================================================================
// ListenMode specific declarations // ListenMode specific declarations
//============================================================================= //=============================================================================
public: public:
// When we receive a packet in listen mode, this is the time left in the sender's burst. // When we receive a packet in listen mode, this is the time left in the
// You need to wait at least this long before trying to reply. // sender's burst. You need to wait at least this long before trying to reply.
static volatile uint16_t RF69_LISTEN_BURST_REMAINING_MS; static volatile uint16_t RF69_LISTEN_BURST_REMAINING_MS;
void listenModeStart(void); void listenModeStart(void);
void listenModeEnd(void); void listenModeEnd(void);
void listenModeHighSpeed(bool highSpeed) { _isHighSpeed = highSpeed; } void listenModeHighSpeed(bool highSpeed) { _isHighSpeed = highSpeed; }
// rx and idle duration in microseconds // rx and idle duration in microseconds
bool listenModeSetDurations(uint32_t& rxDuration, uint32_t& idleDuration); bool listenModeSetDurations(uint32_t &rxDuration, uint32_t &idleDuration);
// The values passed to listenModeSetDurations() may be slightly different to accomodate // The values passed to listenModeSetDurations() may be slightly different to
// what is allowed by the radio. This function returns the actual values used. // accomodate what is allowed by the radio. This function returns the actual
void listenModeGetDurations(uint32_t& rxDuration, uint32_t& idleDuration); // values used.
void listenModeGetDurations(uint32_t &rxDuration, uint32_t &idleDuration);
// This repeatedly sends the message to the target node for the duration // This repeatedly sends the message to the target node for the duration
// of an entire listen cycle. The amount of time remaining in the burst // of an entire listen cycle. The amount of time remaining in the burst
// is transmitted to the receiver, and it is expected that the receiver // is transmitted to the receiver, and it is expected that the receiver
// wait for the burst to end before attempting a reply. // wait for the burst to end before attempting a reply.
// See RF69_LISTEN_BURST_REMAINING_MS above. // See RF69_LISTEN_BURST_REMAINING_MS above.
void listenModeSendBurst(uint8_t targetNode, const void* buffer, uint8_t size); void listenModeSendBurst(uint8_t targetNode, const void *buffer,
uint8_t size);
protected: protected:
void listenModeInterruptHandler(void); void listenModeInterruptHandler(void);
void listenModeApplyHighSpeedSettings(); void listenModeApplyHighSpeedSettings();
void listenModeReset(); //resets variables used on the receiving end void listenModeReset(); // resets variables used on the receiving end
bool reinitRadio(void); bool reinitRadio(void);
static void listenModeIrq(); static void listenModeIrq();
bool _isHighSpeed; bool _isHighSpeed;
bool _haveEncryptKey; bool _haveEncryptKey;
char _encryptKey[16]; char _encryptKey[16];
// Save these so we can reinitialize the radio after sending a burst // Save these so we can reinitialize the radio after sending a burst
// or exiting listen mode. // or exiting listen mode.
uint8_t _freqBand; uint8_t _freqBand;
uint8_t _rxListenCoef; uint8_t _rxListenCoef;
uint8_t _rxListenResolution; uint8_t _rxListenResolution;
uint8_t _idleListenCoef; uint8_t _idleListenCoef;
uint8_t _idleListenResolution; uint8_t _idleListenResolution;
uint32_t _listenCycleDurationUs; uint32_t _listenCycleDurationUs;
#endif #endif
}; };