add custom bitrate command
This commit is contained in:
parent
240306de6e
commit
034caf2f11
39
RFM69.cpp
39
RFM69.cpp
|
|
@ -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.
|
||||||
|
|
|
||||||
576
RFM69.h
576
RFM69.h
|
|
@ -1,23 +1,24 @@
|
||||||
// **********************************************************************************
|
// **********************************************************************************
|
||||||
// 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
|
||||||
// **********************************************************************************
|
// **********************************************************************************
|
||||||
// License
|
// License
|
||||||
// **********************************************************************************
|
// **********************************************************************************
|
||||||
// This program is free software; you can redistribute it
|
// This program is free software; you can redistribute it
|
||||||
// and/or modify it under the terms of the GNU General
|
// and/or modify it under the terms of the GNU General
|
||||||
// Public License as published by the Free Software
|
// Public License as published by the Free Software
|
||||||
// Foundation; either version 3 of the License, or
|
// Foundation; either version 3 of the License, or
|
||||||
// (at your option) any later version.
|
// (at your option) any later version.
|
||||||
//
|
//
|
||||||
// This program is distributed in the hope that it will
|
// This program is distributed in the hope that it will
|
||||||
// be useful, but WITHOUT ANY WARRANTY; without even the
|
// be useful, but WITHOUT ANY WARRANTY; without even the
|
||||||
// implied warranty of MERCHANTABILITY or FITNESS FOR A
|
// implied warranty of MERCHANTABILITY or FITNESS FOR A
|
||||||
// PARTICULAR PURPOSE. See the GNU General Public
|
// PARTICULAR PURPOSE. See the GNU General Public
|
||||||
// License for more details.
|
// License for more details.
|
||||||
//
|
//
|
||||||
// Licence can be viewed at
|
// Licence can be viewed at
|
||||||
// http://www.gnu.org/licenses/gpl-3.0.txt
|
// http://www.gnu.org/licenses/gpl-3.0.txt
|
||||||
//
|
//
|
||||||
// Please maintain this license information along with authorship
|
// Please maintain this license information along with authorship
|
||||||
|
|
@ -25,320 +26,385 @@
|
||||||
// **********************************************************************************
|
// **********************************************************************************
|
||||||
#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
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue