Merge pull request #195 from brainelectronics/feature/additional-functions

Add new getter functions to RFM69 and RFM69 ATC
This commit is contained in:
Felix Rusu 2025-02-11 16:12:18 -05:00 committed by GitHub
commit e038dcfaa8
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 369 additions and 108 deletions

View File

@ -0,0 +1,159 @@
// Sample RFM69 sketch, with optional encryption, Automatic Transmission Control
// This will only init the radio module and print the values of all getter functions
// No data is transmitted or received. The device will only blink the onboard LED.
// **********************************************************************************
// Copyright Felix Rusu 2025, http://www.LowPowerLab.com/contact
// **********************************************************************************
// License
// **********************************************************************************
// This program is free software; you can redistribute it
// and/or modify it under the terms of the GNU General
// Public License as published by the Free Software
// Foundation; either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will
// be useful, but WITHOUT ANY WARRANTY; without even the
// implied warranty of MERCHANTABILITY or FITNESS FOR A
// PARTICULAR PURPOSE. See the GNU General Public
// License for more details.
//
// Licence can be viewed at
// http://www.gnu.org/licenses/gpl-3.0.txt
//
// Please maintain this license information along with authorship
// and copyright notices in any redistribution of this code
// **********************************************************************************
#include <RFM69.h> //get it here: https://www.github.com/lowpowerlab/rfm69
#include <RFM69_ATC.h> //get it here: https://www.github.com/lowpowerlab/rfm69
//*********************************************************************************************
//************ IMPORTANT SETTINGS - YOU MUST CHANGE/CONFIGURE TO FIT YOUR HARDWARE ************
//*********************************************************************************************
// Address IDs are 10bit, meaning usable ID range is 1..1023
// Address 0 is special (broadcast), messages to address 0 are received by all *listening* nodes (ie. active RX mode)
// Gateway ID should be kept at ID=1 for simplicity, although this is not a hard constraint
//*********************************************************************************************
#define NODEID 1 // keep UNIQUE for each node on same network
#define NETWORKID 100 // keep IDENTICAL on all nodes that talk to each other
//*********************************************************************************************
// Frequency should be set to match the radio module hardware tuned frequency,
// otherwise if say a "433mhz" module is set to work at 915, it will work but very badly.
// Moteinos and RF modules from LowPowerLab are marked with a colored dot to help identify their tuned frequency band,
// see this link for details: https://lowpowerlab.com/guide/moteino/transceivers/
// The below examples are predefined "center" frequencies for the radio's tuned "ISM frequency band".
// You can always set the frequency anywhere in the "frequency band", ex. the 915mhz ISM band is 902..928mhz.
//*********************************************************************************************
//#define FREQUENCY RF69_433MHZ
//#define FREQUENCY RF69_868MHZ
#define FREQUENCY RF69_915MHZ
//#define FREQUENCY_EXACT 916000000 // you may define an exact frequency/channel in Hz
#define ENCRYPTKEY "sampleEncryptKey" //exactly the same 16 characters/bytes on all nodes!
#define IS_RFM69HW_HCW //uncomment only for RFM69HW/HCW! Leave out if you have RFM69W/CW!
//*********************************************************************************************
//Auto Transmission Control - dials down transmit power to save battery
//Usually you do not need to always transmit at max output power
//By reducing TX power even a little you save a significant amount of battery power
//This setting enables this gateway to work with remote nodes that have ATC enabled to
//dial their power down to only the required level (ATC_RSSI)
#define ENABLE_ATC //comment out this line to disable AUTO TRANSMISSION CONTROL
#define ATC_RSSI -80
//*********************************************************************************************
#define SERIAL_BAUD 115200
#define DEBUG(input) Serial.print(input)
#define DEBUGln(input) Serial.println(input)
#define BLINK_INTERVAL 1000 //< [ms] LED heartbeat blink interval
uint32_t last_blink = 0;
#ifdef ENABLE_ATC
RFM69_ATC radio;
#else
RFM69 radio;
#endif
void setup() {
Serial.begin(SERIAL_BAUD);
pinMode(LED_BUILTIN, OUTPUT);
DEBUGln("START SETUP TEST!");
if (!radio.initialize(FREQUENCY,NODEID,NETWORKID))
DEBUGln("radio.init() FAIL");
else
DEBUGln("radio.init() SUCCESS");
#ifdef IS_RFM69HW_HCW
radio.setHighPower(); // must include this only for RFM69HW/HCW!
#endif
#ifdef ENCRYPTKEY
radio.encrypt(ENCRYPTKEY);
#endif
#ifdef FREQUENCY_EXACT
radio.setFrequency(FREQUENCY_EXACT); // set frequency to some custom frequency
#endif
// Auto Transmission Control - dials down transmit power to save battery (-100 is the noise floor, -90 is still pretty good)
// For indoor nodes that are pretty static and at pretty stable temperatures (like a MotionMote) -90dBm is quite safe
// For more variable nodes that can expect to move or experience larger temp drifts a lower margin like -70 to -80 would probably be better
// Always test your ATC mote in the edge cases in your own environment to ensure ATC will perform as you expect
#ifdef ENABLE_ATC
radio.enableAutoPower(ATC_RSSI);
#endif
test_config();
radio.readAllRegs();
}
void loop() {
uint32_t now = millis();
if (now > (last_blink + BLINK_INTERVAL)) {
last_blink = now;
digitalWrite(LED_BUILTIN, !digitalRead(LED_BUILTIN));
}
}
void test_config() {
/*
RFM version: 36
Node address: 2
Node network: 100
Frequency: 433MHz
Frequency deviation: 49987Hz
Bit rate: 55555bits/sec
Spy mode active: no
HCW module: yes
TX Power 20dBM, 100.00mW
Temperature: 24 Celsius
Sync active: yes
Sync size: 1
CRC on: yes
AES on: no
Target RSSI:-80
*/
DEBUG("RFM version: "); DEBUGln(radio.getVersion());
DEBUG("Node address: "); DEBUGln(radio.getAddress());
DEBUG("Node network: "); DEBUGln(radio.getNetwork());
DEBUG("Frequency: "); DEBUG(radio.getFrequency()/1000000L); DEBUGln("MHz");
DEBUG("Frequency deviation: "); DEBUG(radio.getFrequencyDeviation()); DEBUGln("Hz");
DEBUG("Bit rate: "); DEBUG(radio.getBitRate()); DEBUGln("bits/sec");
DEBUG("Spy mode active: "); DEBUGln(radio.getSpyMode()==1 ? "yes":"no");
DEBUG("HCW module: "); DEBUGln(radio.isHighPower()==1 ? "yes":"no");
uint8_t tx_power = radio.getPowerLevel();
DEBUG("TX Power "); DEBUG(tx_power); DEBUG("dBM, "); DEBUG(radio.dBm_to_mW(tx_power)); DEBUGln("mW");
DEBUG("Temperature: "); DEBUG(radio.readTemperature()); DEBUGln(" Celsius");
DEBUG("Sync active: "); DEBUGln(radio.isSyncOn()==1 ? "yes":"no");
DEBUG("Sync size: "); DEBUGln(radio.getSyncSize());
DEBUG("CRC on: "); DEBUGln(radio.isCrcOn()==1 ? "yes":"no");
DEBUG("AES on: "); DEBUGln(radio.isAesOn()==1 ? "yes":"no");
#ifdef ENABLE_ATC
DEBUG("Target RSSI by ATC: "); DEBUGln(radio.getTargetRssi());
#endif
}

View File

@ -21,22 +21,26 @@ GPL 3.0, please see the [License.txt](https://github.com/LowPowerLab/RFM69/blob/
- 61 bytes max message length (limited to 61 to support AES hardware encryption) - 61 bytes max message length (limited to 61 to support AES hardware encryption)
- customizable transmit power (32 levels) for low-power transmission control - customizable transmit power (32 levels) for low-power transmission control
- sleep function for power saving - sleep function for power saving
- automatic ACKs with the sendWithRetry() function - automatic ACKs with the `sendWithRetry()` function
- hardware 128bit AES encryption - hardware 128bit AES encryption
- hardware preamble, synch recognition and CRC check - hardware preamble, synch recognition and CRC check
- digital RSSI can be read at any time with readRSSI() - digital RSSI can be read at any time with `readRSSI()`
- interrupt driven - interrupt driven
- tested on [all Moteinos & many custom boards designed by LowPowerLab](https://lowpowerlab.com/shop/moteino) - tested on [all Moteinos & many custom boards designed by LowPowerLab](https://lowpowerlab.com/shop/moteino)
- works with RFM69W, RFM69HW, RFM69CW, RFM69HCW, Semtech SX1231/SX1231H transceivers - works with RFM69W, RFM69HW, RFM69CW, RFM69HCW, Semtech SX1231/SX1231H transceivers
- promiscuous mode allows any node to listen to any packet on same network - promiscuous mode allows any node to listen to any packet on same network
### Library Installation (Arduino IDE) ### Library Installation
Copy the content of this library in the "Arduino/libraries/RFM69" folder. #### Arduino IDE
Copy the content of this library in the `Arduino/libraries/RFM69` folder.
<br /> <br />
To find your Arduino folder go to File>Preferences in the Arduino IDE. To find your Arduino folder go to `File -> Preferences` in the Arduino IDE.
<br/> <br/>
See [this tutorial](https://www.arduino.cc/en/Guide/Libraries) on Arduino libraries. See [this tutorial](https://www.arduino.cc/en/Guide/Libraries) on Arduino libraries.
#### PlatformIO
See [PlatformIO registry](https://registry.platformio.org/libraries/lowpowerlab/RFM69) for latest installation details.
### Hardware & programming ### Hardware & programming
The easiest way to get started is with the well documented and supported [Moteino](http://moteino.com) microcontroller platform which is [easily programmable](https://lowpowerlab.com/programming) from the Arduino IDE. This includes the [Moteino, MoteinoUSB & MoteinoMEGA](https://lowpowerlab.com/shop/Moteino). RFM69 transceivers were extensively tested on Moteinos for the purpose of building internet of things (IoT) devices that can be controlled wirelessly. This platform has matured over time and there is now a [dedicated page](https://lowpowerlab.com/gateway) where you can review how these devices can interact with each other via a RaspberryPi gateway interface. Here's a video overview:<br/> The easiest way to get started is with the well documented and supported [Moteino](http://moteino.com) microcontroller platform which is [easily programmable](https://lowpowerlab.com/programming) from the Arduino IDE. This includes the [Moteino, MoteinoUSB & MoteinoMEGA](https://lowpowerlab.com/shop/Moteino). RFM69 transceivers were extensively tested on Moteinos for the purpose of building internet of things (IoT) devices that can be controlled wirelessly. This platform has matured over time and there is now a [dedicated page](https://lowpowerlab.com/gateway) where you can review how these devices can interact with each other via a RaspberryPi gateway interface. Here's a video overview:<br/>
https://www.youtube.com/watch?v=YUUZ6k0pBHg https://www.youtube.com/watch?v=YUUZ6k0pBHg

233
RFM69.cpp
View File

@ -108,7 +108,7 @@ bool RFM69::initialize(uint8_t freqBand, uint16_t nodeID, uint8_t networkID) {
digitalWrite(_slaveSelectPin, HIGH); digitalWrite(_slaveSelectPin, HIGH);
pinMode(_slaveSelectPin, OUTPUT); pinMode(_slaveSelectPin, OUTPUT);
if(_spi == nullptr){ if (_spi == nullptr) {
_spi = &SPI; _spi = &SPI;
} }
_spi->begin(); _spi->begin();
@ -140,14 +140,18 @@ bool RFM69::initialize(uint8_t freqBand, uint16_t nodeID, uint8_t networkID) {
attachInterrupt(_interruptNum, RFM69::isr0, RISING); attachInterrupt(_interruptNum, RFM69::isr0, RISING);
_address = nodeID; _address = nodeID;
_networkID = networkID;
#if defined(RF69_LISTENMODE_ENABLE) #if defined(RF69_LISTENMODE_ENABLE)
selfPointer = this; selfPointer = this;
_freqBand = freqBand; _freqBand = freqBand;
_networkID = networkID;
#endif #endif
return true; return true;
} }
uint8_t RFM69::getVersion() {
return readReg(REG_VERSION);
}
// return the frequency (in Hz) // return the frequency (in Hz)
uint32_t RFM69::getFrequency() { uint32_t RFM69::getFrequency() {
return RF69_FSTEP * (((uint32_t) readReg(REG_FRFMSB) << 16) + ((uint16_t) readReg(REG_FRFMID) << 8) + readReg(REG_FRFLSB)); return RF69_FSTEP * (((uint32_t) readReg(REG_FRFMSB) << 16) + ((uint16_t) readReg(REG_FRFMID) << 8) + readReg(REG_FRFLSB));
@ -169,6 +173,15 @@ void RFM69::setFrequency(uint32_t freqHz) {
setMode(oldMode); setMode(oldMode);
} }
// return the frequency deviation (in Hz)
uint32_t RFM69::getFrequencyDeviation() {
return RF69_FSTEP * ((readReg(REG_FDEVMSB) << 8) | readReg(REG_FDEVLSB));
}
uint32_t RFM69::getBitRate() {
return RF69_FXOSC / ((readReg(REG_BITRATEMSB) << 8) | readReg(REG_BITRATELSB));
}
void RFM69::setMode(uint8_t newMode) { void RFM69::setMode(uint8_t newMode) {
if (newMode == _mode) if (newMode == _mode)
return; return;
@ -202,23 +215,32 @@ void RFM69::setMode(uint8_t newMode) {
_mode = newMode; _mode = newMode;
} }
//put transceiver in sleep mode to save battery - to wake or resume receiving just call receiveDone() // put transceiver in sleep mode to save battery - to wake or resume receiving just call receiveDone()
void RFM69::sleep() { void RFM69::sleep() {
setMode(RF69_MODE_SLEEP); setMode(RF69_MODE_SLEEP);
} }
//set this node's address // set this node's address
void RFM69::setAddress(uint16_t addr) { void RFM69::setAddress(uint16_t addr) {
_address = addr; _address = addr;
writeReg(REG_NODEADRS, _address); //unused in packet mode writeReg(REG_NODEADRS, _address); // unused in packet mode
} }
//set this node's network id uint16_t RFM69::getAddress() {
return _address;
}
// set this node's network id
void RFM69::setNetwork(uint8_t networkID) { void RFM69::setNetwork(uint8_t networkID) {
_networkID = networkID;
writeReg(REG_SYNCVALUE2, networkID); writeReg(REG_SYNCVALUE2, networkID);
} }
//set user's ISR callback uint8_t RFM69::getNetwork() {
return _networkID;
}
// set user's ISR callback
void RFM69::setIsrCallback(void (*callback)()) { void RFM69::setIsrCallback(void (*callback)()) {
_isrCallback = callback; _isrCallback = callback;
} }
@ -238,7 +260,7 @@ void RFM69::setIsrCallback(void (*callback)()) {
void RFM69::setPowerLevel(uint8_t powerLevel) { void RFM69::setPowerLevel(uint8_t powerLevel) {
uint8_t PA_SETTING; uint8_t PA_SETTING;
if (_isRFM69HW) { if (_isRFM69HW) {
if (powerLevel>23) powerLevel = 23; if (powerLevel > 23) powerLevel = 23;
_powerLevel = powerLevel; _powerLevel = powerLevel;
//now set Pout value & active PAs based on _powerLevel range as outlined in summary above //now set Pout value & active PAs based on _powerLevel range as outlined in summary above
@ -254,7 +276,7 @@ void RFM69::setPowerLevel(uint8_t powerLevel) {
} }
setHighPowerRegs(true); //always call this in case we're crossing power boundaries in TX mode setHighPowerRegs(true); //always call this in case we're crossing power boundaries in TX mode
} else { //this is a W/CW, register value is the same as _powerLevel } else { //this is a W/CW, register value is the same as _powerLevel
if (powerLevel>31) powerLevel = 31; if (powerLevel > 31) powerLevel = 31;
_powerLevel = powerLevel; _powerLevel = powerLevel;
PA_SETTING = RF_PALEVEL_PA0_ON; // enable PA0 only PA_SETTING = RF_PALEVEL_PA0_ON; // enable PA0 only
} }
@ -263,30 +285,64 @@ void RFM69::setPowerLevel(uint8_t powerLevel) {
writeReg(REG_PALEVEL, PA_SETTING | powerLevel); writeReg(REG_PALEVEL, PA_SETTING | powerLevel);
} }
// return stored _powerLevel uint8_t RFM69::getOutputPower() {
uint8_t RFM69::getPowerLevel() { return _powerLevel; } // _RegisterBits(_REG_PA_LEVEL, offset=0, bits=5)
return readReg(REG_PALEVEL) & 0x1F;
}
//Set TX Output power in dBm: uint8_t RFM69::getPowerLevel() {
uint8_t val = readReg(REG_PALEVEL);
uint8_t outputPower = getOutputPower();
bool pa0 = (val & 0b10000000) > 0;
bool pa1 = (val & 0b01000000) > 0;
bool pa2 = (val & 0b00100000) > 0;
if (pa0 && !pa1 && !pa2) {
// -18 to 13 dBm range
return -18 + outputPower;
}
if (!pa0 && pa1 && !pa2) {
// -2 to 13 dBm range
return -18 + outputPower;
}
if (!pa0 && pa1 && pa2 && !_isRFM69HW) {
// 2 to 17 dBm range
return -14 + outputPower;
}
if (!pa0 && pa1 && pa2 && _isRFM69HW) {
// 5 to 20 dBm range
return -11 + outputPower;
}
return 255;
}
// Set TX Output power in dBm:
// [-18..+13]dBm in RFM69 W/CW // [-18..+13]dBm in RFM69 W/CW
// [ -2..+20]dBm in RFM69 HW/HCW // [ -2..+20]dBm in RFM69 HW/HCW
int8_t RFM69::setPowerDBm(int8_t dBm) { int8_t RFM69::setPowerDBm(int8_t dBm) {
if (_isRFM69HW) { if (_isRFM69HW) {
//fix any out of bounds //fix any out of bounds
if (dBm<-2) dBm=-2; if (dBm < -2) dBm=-2;
else if (dBm>20) dBm=20; else if (dBm>20) dBm=20;
//map dBm to _powerLevel according to implementation in setPowerLevel() //map dBm to _powerLevel according to implementation in setPowerLevel()
if (dBm<12) setPowerLevel(2+dBm); if (dBm < 12) setPowerLevel(2+dBm);
else if (dBm<16) setPowerLevel(4+dBm); else if (dBm < 16) setPowerLevel(4+dBm);
else setPowerLevel(3+dBm); else setPowerLevel(3+dBm);
} else { //W/CW } else { //W/CW
if (dBm<-18) dBm=-18; if (dBm < -18) dBm=-18;
else if (dBm>13) dBm=13; else if (dBm > 13) dBm=13;
setPowerLevel(18+dBm); setPowerLevel(18+dBm);
} }
return dBm; return dBm;
} }
double RFM69::dBm_to_mW(uint8_t dBm) {
return pow(10, (dBm / 10.0));
}
bool RFM69::canSend() { bool RFM69::canSend() {
if (_mode == RF69_MODE_RX && PAYLOADLEN == 0 && readRSSI() < CSMA_LIMIT) { // if signal stronger than -100dBm is detected assume channel activity if (_mode == RF69_MODE_RX && PAYLOADLEN == 0 && readRSSI() < CSMA_LIMIT) { // if signal stronger than -100dBm is detected assume channel activity
setMode(RF69_MODE_STANDBY); setMode(RF69_MODE_STANDBY);
@ -370,8 +426,8 @@ void RFM69::sendFrame(uint16_t toAddress, const void* buffer, uint8_t bufferSize
else if (requestACK) else if (requestACK)
CTLbyte = RFM69_CTL_REQACK; CTLbyte = RFM69_CTL_REQACK;
if (toAddress > 0xFF) CTLbyte |= (toAddress & 0x300) >> 6; //assign last 2 bits of address if > 255 if (toAddress > 0xFF) CTLbyte |= (toAddress & 0x300) >> 6; // assign last 2 bits of address if > 255
if (_address > 0xFF) CTLbyte |= (_address & 0x300) >> 8; //assign last 2 bits of address if > 255 if (_address > 0xFF) CTLbyte |= (_address & 0x300) >> 8; // assign last 2 bits of address if > 255
// write to FIFO // write to FIFO
select(); select();
@ -404,8 +460,8 @@ void RFM69::interruptHandler() {
TARGETID = _spi->transfer(0); TARGETID = _spi->transfer(0);
SENDERID = _spi->transfer(0); SENDERID = _spi->transfer(0);
uint8_t CTLbyte = _spi->transfer(0); uint8_t CTLbyte = _spi->transfer(0);
TARGETID |= (uint16_t(CTLbyte) & 0x0C) << 6; //10 bit address (most significant 2 bits stored in bits(2,3) of CTL byte TARGETID |= (uint16_t(CTLbyte) & 0x0C) << 6; // 10 bit address (most significant 2 bits stored in bits(2,3) of CTL byte
SENDERID |= (uint16_t(CTLbyte) & 0x03) << 8; //10 bit address (most sifnigicant 2 bits stored in bits(0,1) of CTL byte SENDERID |= (uint16_t(CTLbyte) & 0x03) << 8; // 10 bit address (most sifnigicant 2 bits stored in bits(0,1) of CTL byte
if(!(_spyMode || TARGETID == _address || TARGETID == RF69_BROADCAST_ADDR) // match this node's address, or broadcast address or anything in spy mode if(!(_spyMode || TARGETID == _address || TARGETID == RF69_BROADCAST_ADDR) // match this node's address, or broadcast address or anything in spy mode
|| PAYLOADLEN < 3) // address situation could receive packets that are malformed and don't fit this libraries extra fields || PAYLOADLEN < 3) // address situation could receive packets that are malformed and don't fit this libraries extra fields
@ -419,7 +475,7 @@ void RFM69::interruptHandler() {
DATALEN = PAYLOADLEN - 3; DATALEN = PAYLOADLEN - 3;
ACK_RECEIVED = CTLbyte & RFM69_CTL_SENDACK; // extract ACK-received flag ACK_RECEIVED = CTLbyte & RFM69_CTL_SENDACK; // extract ACK-received flag
ACK_REQUESTED = CTLbyte & RFM69_CTL_REQACK; // extract ACK-requested flag ACK_REQUESTED = CTLbyte & RFM69_CTL_REQACK; // extract ACK-requested flag
uint8_t _pl = _powerLevel; //interruptHook() can change _powerLevel so remember it uint8_t _pl = _powerLevel; // interruptHook() can change _powerLevel so remember it
interruptHook(CTLbyte); // TWS: hook to derived class interrupt function interruptHook(CTLbyte); // TWS: hook to derived class interrupt function
for (uint8_t i = 0; i < DATALEN; i++) DATA[i] = _spi->transfer(0); for (uint8_t i = 0; i < DATALEN; i++) DATA[i] = _spi->transfer(0);
@ -427,7 +483,7 @@ void RFM69::interruptHandler() {
DATA[DATALEN] = 0; // add null at end of string // add null at end of string DATA[DATALEN] = 0; // add null at end of string // add null at end of string
unselect(); unselect();
setMode(RF69_MODE_RX); setMode(RF69_MODE_RX);
if (_pl != _powerLevel) setPowerLevel(_powerLevel); //set new _powerLevel if changed if (_pl != _powerLevel) setPowerLevel(_powerLevel); // set new _powerLevel if changed
} }
RSSI = readRSSI(); RSSI = readRSSI();
} }
@ -568,13 +624,37 @@ void RFM69::spyMode(bool onOff) {
//writeReg(REG_PACKETCONFIG1, (readReg(REG_PACKETCONFIG1) & 0xF9) | (onOff ? RF_PACKET1_ADRSFILTERING_OFF : RF_PACKET1_ADRSFILTERING_NODEBROADCAST)); //writeReg(REG_PACKETCONFIG1, (readReg(REG_PACKETCONFIG1) & 0xF9) | (onOff ? RF_PACKET1_ADRSFILTERING_OFF : RF_PACKET1_ADRSFILTERING_NODEBROADCAST));
} }
bool RFM69::getSpyMode() {
return _spyMode;
}
bool RFM69::isSyncOn() {
return readReg(REG_SYNCCONFIG) >> 7;
}
uint8_t RFM69::getSyncSize() {
return (readReg(REG_SYNCCONFIG) & 0b00111000) >> 3;
}
bool RFM69::isCrcOn() {
return (readReg(REG_PACKETCONFIG1) & 0b00010000) >> 4;
}
bool RFM69::isAesOn() {
return readReg(REG_PACKETCONFIG2) & 0b00000001;
}
// for RFM69 HW/HCW only: you must call setHighPower(true) after initialize() or else transmission won't work // for RFM69 HW/HCW only: you must call setHighPower(true) after initialize() or else transmission won't work
void RFM69::setHighPower(bool _isRFM69HW_HCW) { void RFM69::setHighPower(bool _isRFM69HW_HCW) {
_isRFM69HW = _isRFM69HW_HCW; _isRFM69HW = _isRFM69HW_HCW;
writeReg(REG_OCP, _isRFM69HW ? RF_OCP_OFF : RF_OCP_ON); //disable OverCurrentProtection for HW/HCW writeReg(REG_OCP, _isRFM69HW ? RF_OCP_OFF : RF_OCP_ON); // disable OverCurrentProtection for HW/HCW
setPowerLevel(_powerLevel); setPowerLevel(_powerLevel);
} }
bool RFM69::isHighPower() {
return _isRFM69HW;
}
// internal function - for HW/HCW only: // internal function - for HW/HCW only:
// enables HiPower for 18-20dBm output // enables HiPower for 18-20dBm output
// should only be used with PA1+PA2 // should only be used with PA1+PA2
@ -606,14 +686,14 @@ bool RFM69::setIrq(uint8_t newIRQPin) {
return true; return true;
} }
//for debugging // for debugging
#define REGISTER_DETAIL 0 #define REGISTER_DETAIL 0
#if REGISTER_DETAIL #if REGISTER_DETAIL
// SERIAL PRINT // SERIAL PRINT
// replace Serial.print("string") with SerialPrint("string") // replace Serial.print("string") with SerialPrint("string")
#define SerialPrint(x) SerialPrint_P(PSTR(x)) #define SerialPrint(x) SerialPrint_P(PSTR(x))
void SerialWrite ( uint8_t c ) { void SerialWrite(uint8_t c) {
Serial.write ( c ); Serial.write(c);
} }
void SerialPrint_P(PGM_P str, void (*f)(uint8_t) = SerialWrite ) { void SerialPrint_P(PGM_P str, void (*f)(uint8_t) = SerialWrite ) {
@ -643,12 +723,12 @@ void RFM69::readAllRegs() {
Serial.print(regAddr, HEX); Serial.print(regAddr, HEX);
Serial.print(" - "); Serial.print(" - ");
Serial.print(regVal,HEX); Serial.print(regVal, HEX);
Serial.print(" - "); Serial.print(" - ");
Serial.println(regVal,BIN); Serial.println(regVal, BIN);
#if REGISTER_DETAIL #if REGISTER_DETAIL
switch ( regAddr ){ switch (regAddr){
case 0x1 : { case 0x1 : {
SerialPrint("Controls the automatic Sequencer ( see section 4.2 )\nSequencerOff : "); SerialPrint("Controls the automatic Sequencer ( see section 4.2 )\nSequencerOff : ");
if (0x80 & regVal) { if (0x80 & regVal) {
@ -673,16 +753,16 @@ void RFM69::readAllRegs() {
capVal = (regVal >> 2) & 0x7; capVal = (regVal >> 2) & 0x7;
if (capVal == 0b000) { if (capVal == 0b000) {
SerialPrint("000 -> Sleep mode (SLEEP)\n"); SerialPrint("000 -> Sleep mode (SLEEP)\n");
} else if ( capVal == 0b001 ) { } else if (capVal == 0b001) {
SerialPrint("001 -> Standby mode (STDBY)\n"); SerialPrint("001 -> Standby mode (STDBY)\n");
} else if ( capVal == 0b010 ) { } else if (capVal == 0b010) {
SerialPrint("010 -> Frequency Synthesizer mode (FS)\n"); SerialPrint("010 -> Frequency Synthesizer mode (FS)\n");
} else if ( capVal == 0b011 ) { } else if (capVal == 0b011) {
SerialPrint("011 -> Transmitter mode (TX)\n"); SerialPrint("011 -> Transmitter mode (TX)\n");
} else if ( capVal == 0b100 ) { } else if (capVal == 0b100) {
SerialPrint("100 -> Receiver Mode (RX)\n"); SerialPrint("100 -> Receiver Mode (RX)\n");
} else { } else {
Serial.print( capVal, BIN ); Serial.print(capVal, BIN);
SerialPrint(" -> RESERVED\n"); SerialPrint(" -> RESERVED\n");
} }
SerialPrint("\n"); SerialPrint("\n");
@ -716,7 +796,7 @@ void RFM69::readAllRegs() {
} }
SerialPrint("\nData shaping: "); SerialPrint("\nData shaping: ");
if ( modeFSK ) { if (modeFSK) {
SerialPrint("in FSK:\n"); SerialPrint("in FSK:\n");
} else { } else {
SerialPrint("in OOK:\n"); SerialPrint("in OOK:\n");
@ -726,11 +806,11 @@ void RFM69::readAllRegs() {
if (modeFSK) { if (modeFSK) {
if (capVal == 0b00) { if (capVal == 0b00) {
SerialPrint("00 -> no shaping\n"); SerialPrint("00 -> no shaping\n");
} else if ( capVal == 0b01 ) { } else if (capVal == 0b01) {
SerialPrint("01 -> Gaussian filter, BT = 1.0\n"); SerialPrint("01 -> Gaussian filter, BT = 1.0\n");
} else if ( capVal == 0b10 ) { } else if (capVal == 0b10) {
SerialPrint("10 -> Gaussian filter, BT = 0.5\n"); SerialPrint("10 -> Gaussian filter, BT = 0.5\n");
} else if ( capVal == 0b11 ) { } else if (capVal == 0b11) {
SerialPrint("11 -> Gaussian filter, BT = 0.3\n"); SerialPrint("11 -> Gaussian filter, BT = 0.3\n");
} }
} else { } else {
@ -758,13 +838,13 @@ void RFM69::readAllRegs() {
bitRate |= regVal; bitRate |= regVal;
SerialPrint("Bit Rate (Chip Rate when Manchester encoding is enabled)\nBitRate : "); SerialPrint("Bit Rate (Chip Rate when Manchester encoding is enabled)\nBitRate : ");
unsigned long val = 32UL * 1000UL * 1000UL / bitRate; unsigned long val = 32UL * 1000UL * 1000UL / bitRate;
Serial.println( val ); Serial.println(val);
SerialPrint("\n"); SerialPrint("\n");
break; break;
} }
case 0x5 : { case 0x5 : {
freqDev = ( (regVal & 0x3f) << 8 ); freqDev = ((regVal & 0x3f) << 8);
break; break;
} }
@ -772,20 +852,20 @@ void RFM69::readAllRegs() {
freqDev |= regVal; freqDev |= regVal;
SerialPrint("Frequency deviation\nFdev : "); SerialPrint("Frequency deviation\nFdev : ");
unsigned long val = RF69_FSTEP * freqDev; unsigned long val = RF69_FSTEP * freqDev;
Serial.println( val ); Serial.println(val);
SerialPrint("\n"); SerialPrint("\n");
break; break;
} }
case 0x7 : { case 0x7 : {
unsigned long tempVal = regVal; unsigned long tempVal = regVal;
freqCenter = ( tempVal << 16 ); freqCenter = (tempVal << 16);
break; break;
} }
case 0x8 : { case 0x8 : {
unsigned long tempVal = regVal; unsigned long tempVal = regVal;
freqCenter = freqCenter | ( tempVal << 8 ); freqCenter = freqCenter | (tempVal << 8);
break; break;
} }
@ -793,14 +873,14 @@ void RFM69::readAllRegs() {
freqCenter = freqCenter | regVal; freqCenter = freqCenter | regVal;
SerialPrint("RF Carrier frequency\nFRF : "); SerialPrint("RF Carrier frequency\nFRF : ");
unsigned long val = RF69_FSTEP * freqCenter; unsigned long val = RF69_FSTEP * freqCenter;
Serial.println( val ); Serial.println(val);
SerialPrint("\n"); SerialPrint("\n");
break; break;
} }
case 0xa : { case 0xa : {
SerialPrint("RC calibration control & status\nRcCalDone : "); SerialPrint("RC calibration control & status\nRcCalDone : ");
if ( 0x40 & regVal ) { if (0x40 & regVal) {
SerialPrint("1 -> RC calibration is over\n"); SerialPrint("1 -> RC calibration is over\n");
} else { } else {
SerialPrint("0 -> RC calibration is in progress\n"); SerialPrint("0 -> RC calibration is in progress\n");
@ -812,7 +892,7 @@ void RFM69::readAllRegs() {
case 0xb : { case 0xb : {
SerialPrint("Improved AFC routine for signals with modulation index lower than 2. Refer to section 3.4.16 for details\nAfcLowBetaOn : "); SerialPrint("Improved AFC routine for signals with modulation index lower than 2. Refer to section 3.4.16 for details\nAfcLowBetaOn : ");
if ( 0x20 & regVal ) { if (0x20 & regVal) {
SerialPrint("1 -> Improved AFC routine\n"); SerialPrint("1 -> Improved AFC routine\n");
} else { } else {
SerialPrint("0 -> Standard AFC routine\n"); SerialPrint("0 -> Standard AFC routine\n");
@ -885,8 +965,8 @@ void RFM69::readAllRegs() {
void RFM69::readAllRegsCompact() { void RFM69::readAllRegsCompact() {
// Print the header row and first register entry // Print the header row and first register entry
Serial.println();Serial.print(" "); Serial.println(); Serial.print(" ");
for ( uint8_t reg = 0x00; reg<0x10; reg++ ) { for (uint8_t reg = 0x00; reg < 0x10; reg++) {
Serial.print(reg, HEX); Serial.print(reg, HEX);
Serial.print(" "); Serial.print(" ");
} }
@ -894,17 +974,17 @@ void RFM69::readAllRegsCompact() {
Serial.print("00: -- "); Serial.print("00: -- ");
// Loop over the registers from 0x01 to 0x7F and print their values // Loop over the registers from 0x01 to 0x7F and print their values
for ( uint8_t reg = 0x01; reg<0x80; reg++ ) { for (uint8_t reg = 0x01; reg < 0x80; reg++) {
if ( reg % 16 == 0 ) { // Print the header column entries if (reg % 16 == 0) { // Print the header column entries
Serial.println(); Serial.println();
Serial.print( reg, HEX ); Serial.print(reg, HEX);
Serial.print(": "); Serial.print(": ");
} }
// Print the actual register values // Print the actual register values
uint8_t ret = readReg( reg ); uint8_t ret = readReg(reg);
if ( ret < 0x10 ) Serial.print("0"); // Handle values less than 10 if (ret < 0x10) Serial.print("0"); // Handle values less than 10
Serial.print( ret, HEX); Serial.print(ret, HEX);
Serial.print(" "); Serial.print(" ");
} }
} }
@ -964,21 +1044,21 @@ void RFM69::listenModeSleep(uint16_t millisInterval) {
detachInterrupt( _interruptNum ); detachInterrupt( _interruptNum );
//attachInterrupt( _interruptNum, delayIrq, RISING); //attachInterrupt( _interruptNum, delayIrq, RISING);
writeReg( REG_DIOMAPPING1, RF_DIOMAPPING1_DIO0_11 ); writeReg(REG_DIOMAPPING1, RF_DIOMAPPING1_DIO0_11);
writeReg( REG_BITRATEMSB, RF_BITRATEMSB_200000); writeReg(REG_BITRATEMSB, RF_BITRATEMSB_200000);
writeReg( REG_BITRATELSB, RF_BITRATELSB_200000); writeReg(REG_BITRATELSB, RF_BITRATELSB_200000);
writeReg( REG_FDEVMSB, RF_FDEVMSB_100000 ); writeReg(REG_FDEVMSB, RF_FDEVMSB_100000);
writeReg( REG_FDEVLSB, RF_FDEVLSB_100000 ); writeReg(REG_FDEVLSB, RF_FDEVLSB_100000);
writeReg( REG_RXBW, RF_RXBW_DCCFREQ_000 | RF_RXBW_MANT_16 | RF_RXBW_EXP_0 ); writeReg(REG_RXBW, RF_RXBW_DCCFREQ_000 | RF_RXBW_MANT_16 | RF_RXBW_EXP_0);
uint8_t idleResol; uint8_t idleResol;
uint32_t divisor; uint32_t divisor;
uint32_t microInterval = millisInterval * 1000L; uint32_t microInterval = millisInterval * 1000L;
if( microInterval > 255 * 4100L ) { if(microInterval > 255 * 4100L) {
idleResol = RF_LISTEN1_RESOL_IDLE_262000; idleResol = RF_LISTEN1_RESOL_IDLE_262000;
divisor = 262000; divisor = 262000;
} else if( microInterval > 255 * 64L ) { } else if(microInterval > 255 * 64L) {
idleResol = RF_LISTEN1_RESOL_IDLE_4100; idleResol = RF_LISTEN1_RESOL_IDLE_4100;
divisor = 4100; divisor = 4100;
} else { } else {
@ -986,14 +1066,14 @@ void RFM69::listenModeSleep(uint16_t millisInterval) {
divisor = 64; divisor = 64;
} }
writeReg( REG_LISTEN1, RF_LISTEN1_RESOL_RX_64 | idleResol | RF_LISTEN1_CRITERIA_RSSI | RF_LISTEN1_END_10 ); writeReg(REG_LISTEN1, RF_LISTEN1_RESOL_RX_64 | idleResol | RF_LISTEN1_CRITERIA_RSSI | RF_LISTEN1_END_10);
writeReg( REG_LISTEN2, (microInterval + (divisor >> 1 ) ) / divisor ); writeReg(REG_LISTEN2, (microInterval + (divisor >> 1 ) ) / divisor);
writeReg( REG_LISTEN3, 4 ); writeReg(REG_LISTEN3, 4);
writeReg( REG_RSSITHRESH, 255 ); writeReg(REG_RSSITHRESH, 255);
writeReg( REG_RXTIMEOUT2, 1 ); writeReg(REG_RXTIMEOUT2, 1);
writeReg( REG_OPMODE, RF_OPMODE_SEQUENCER_ON | RF_OPMODE_STANDBY ); writeReg(REG_OPMODE, RF_OPMODE_SEQUENCER_ON | RF_OPMODE_STANDBY );
writeReg( REG_OPMODE, RF_OPMODE_SEQUENCER_ON | RF_OPMODE_STANDBY | RF_OPMODE_LISTEN_ON ); writeReg(REG_OPMODE, RF_OPMODE_SEQUENCER_ON | RF_OPMODE_STANDBY | RF_OPMODE_LISTEN_ON );
attachInterrupt( _interruptNum, delayIrq, RISING); attachInterrupt(_interruptNum, delayIrq, RISING);
//must call sleep + interrupt handler 3 times here, then endListenModeSleep() - see ListenModeSleep example! //must call sleep + interrupt handler 3 times here, then endListenModeSleep() - see ListenModeSleep example!
} }
@ -1002,10 +1082,10 @@ void RFM69::listenModeSleep(uint16_t millisInterval) {
//============================================================================= //=============================================================================
void RFM69::endListenModeSleep() { void RFM69::endListenModeSleep() {
detachInterrupt( _interruptNum ); detachInterrupt( _interruptNum );
writeReg( REG_OPMODE, RF_OPMODE_SEQUENCER_ON | RF_OPMODE_LISTENABORT | RF_OPMODE_STANDBY ); writeReg(REG_OPMODE, RF_OPMODE_SEQUENCER_ON | RF_OPMODE_LISTENABORT | RF_OPMODE_STANDBY);
writeReg( REG_OPMODE, RF_OPMODE_SEQUENCER_ON | RF_OPMODE_STANDBY ); writeReg(REG_OPMODE, RF_OPMODE_SEQUENCER_ON | RF_OPMODE_STANDBY);
writeReg( REG_RXTIMEOUT2, 0 ); writeReg(REG_RXTIMEOUT2, 0);
setMode( RF69_MODE_STANDBY ); setMode(RF69_MODE_STANDBY);
while ((readReg(REG_IRQFLAGS1) & RF_IRQFLAGS1_MODEREADY) == 0x00); // wait for ModeReady while ((readReg(REG_IRQFLAGS1) & RF_IRQFLAGS1_MODEREADY) == 0x00); // wait for ModeReady
} }
@ -1161,7 +1241,6 @@ out:
// listenModeStart() - switch radio to Listen Mode in prep for sleep until burst // listenModeStart() - switch radio to Listen Mode in prep for sleep until burst
//============================================================================= //=============================================================================
void RFM69::listenModeStart(void) { void RFM69::listenModeStart(void) {
//pRadio = this;
while (readReg(REG_IRQFLAGS2) & RF_IRQFLAGS2_PACKETSENT == 0x00); // wait for ModeReady while (readReg(REG_IRQFLAGS2) & RF_IRQFLAGS2_PACKETSENT == 0x00); // wait for ModeReady
listenModeReset(); listenModeReset();
@ -1207,7 +1286,7 @@ void RFM69::listenModeApplyHighSpeedSettings() {
writeReg(REG_BITRATELSB, RF_BITRATELSB_200000); writeReg(REG_BITRATELSB, RF_BITRATELSB_200000);
writeReg(REG_FDEVMSB, RF_FDEVMSB_100000); writeReg(REG_FDEVMSB, RF_FDEVMSB_100000);
writeReg(REG_FDEVLSB, RF_FDEVLSB_100000); writeReg(REG_FDEVLSB, RF_FDEVLSB_100000);
writeReg( REG_RXBW, RF_RXBW_DCCFREQ_000 | RF_RXBW_MANT_20 | RF_RXBW_EXP_0 ); writeReg(REG_RXBW, RF_RXBW_DCCFREQ_000 | RF_RXBW_MANT_20 | RF_RXBW_EXP_0);
// Force LNA to the highest gain // Force LNA to the highest gain
//writeReg(REG_LNA, (readReg(REG_LNA) << 2) | RF_LNA_GAINSELECT_MAX); //writeReg(REG_LNA, (readReg(REG_LNA) << 2) | RF_LNA_GAINSELECT_MAX);

56
RFM69.h
View File

@ -153,33 +153,34 @@
#define RF69_MODE_TX 4 // TX 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 -90 // puts the temperature reading in the ballpark, user can fine tune the returned value
#define RF69_BROADCAST_ADDR 0 #define RF69_BROADCAST_ADDR 0
#define RF69_CSMA_LIMIT_MS 1000 #define RF69_CSMA_LIMIT_MS 1000
#define RF69_TX_LIMIT_MS 1000 #define RF69_TX_LIMIT_MS 1000
#define RF69_FSTEP 61.03515625 // == FXOSC / 2^19 = 32MHz / 2^19 (p13 in datasheet) #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
@ -201,7 +202,10 @@ class RFM69 {
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();
uint16_t getAddress();
void setAddress(uint16_t addr); void setAddress(uint16_t addr);
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();
@ -213,17 +217,27 @@ class RFM69 {
virtual void sendACK(const void* buffer = "", uint8_t bufferSize=0); virtual void sendACK(const void* buffer = "", uint8_t bufferSize=0);
uint32_t getFrequency(); uint32_t getFrequency();
void setFrequency(uint32_t freqHz); void setFrequency(uint32_t freqHz);
uint32_t getFrequencyDeviation();
uint32_t getBitRate();
void encrypt(const char* key); void encrypt(const char* key);
void setCS(uint8_t newSPISlaveSelect); void setCS(uint8_t newSPISlaveSelect);
bool setIrq(uint8_t newIRQPin); bool setIrq(uint8_t newIRQPin);
int16_t readRSSI(bool forceTrigger=false); // *current* signal strength indicator; e.g. < -90dBm says the frequency channel is free + ready to transmit int16_t readRSSI(bool forceTrigger=false); // *current* signal strength indicator; e.g. < -90dBm says the frequency channel is free + ready to transmit
bool getSpyMode();
void spyMode(bool onOff=true); void spyMode(bool onOff=true);
//void promiscuous(bool onOff=true); //replaced with spyMode() bool isSyncOn();
uint8_t getSyncSize();
bool isCrcOn();
bool isAesOn();
//void promiscuous(bool onOff=true); // replaced with spyMode()
virtual void setHighPower(bool _isRFM69HW_HCW=true); // has to be called after initialize() for RFM69 HW/HCW virtual void setHighPower(bool _isRFM69HW_HCW=true); // has to be called after initialize() for RFM69 HW/HCW
bool isHighPower();
virtual void setPowerLevel(uint8_t level); // reduce/increase transmit power level 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 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
virtual uint8_t getPowerLevel(); // get powerLevel uint8_t getOutputPower();
uint8_t getPowerLevel(); // get powerLevel
void sleep(); void sleep();
uint8_t readTemperature(uint8_t calFactor=0); // get CMOS temperature (8bit) 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 rcCalibration(); // calibrate the internal RC oscillator for use in wide temperature variations - see datasheet section [4.3.5. RC Timer Accuracy]
@ -258,6 +272,7 @@ class RFM69 {
uint8_t _interruptPin; uint8_t _interruptPin;
uint8_t _interruptNum; uint8_t _interruptNum;
uint16_t _address; uint16_t _address;
uint8_t _networkID;
bool _spyMode; bool _spyMode;
uint8_t _powerLevel; uint8_t _powerLevel;
bool _isRFM69HW; bool _isRFM69HW;
@ -319,7 +334,6 @@ class RFM69 {
// 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 _networkID;
uint8_t _rxListenCoef; uint8_t _rxListenCoef;
uint8_t _rxListenResolution; uint8_t _rxListenResolution;
uint8_t _idleListenCoef; uint8_t _idleListenCoef;

View File

@ -174,6 +174,10 @@ void RFM69_ATC::enableAutoPower(int16_t targetRSSI){ // TomWS1: New method t
_targetRSSI = targetRSSI; // no logic here, just set the value (if non-zero, then enabled), caller's responsibility to use a reasonable value _targetRSSI = targetRSSI; // no logic here, just set the value (if non-zero, then enabled), caller's responsibility to use a reasonable value
} }
int16_t RFM69_ATC::getTargetRssi() {
return _targetRSSI;
}
//============================================================================= //=============================================================================
// getAckRSSI() - returns the RSSI value ack'd by the far end. // getAckRSSI() - returns the RSSI value ack'd by the far end.
//============================================================================= //=============================================================================

View File

@ -44,6 +44,7 @@ class RFM69_ATC: public RFM69 {
void sendACK(const void* buffer = "", uint8_t bufferSize=0); void sendACK(const void* buffer = "", uint8_t bufferSize=0);
bool sendWithRetry(uint16_t toAddress, const void* buffer, uint8_t bufferSize, uint8_t retries=2, uint8_t retryWaitTime=RFM69_ACK_TIMEOUT); bool sendWithRetry(uint16_t toAddress, const void* buffer, uint8_t bufferSize, uint8_t retries=2, uint8_t retryWaitTime=RFM69_ACK_TIMEOUT);
void enableAutoPower(int16_t targetRSSI=-90); // TWS: New method to enable/disable auto Power control void enableAutoPower(int16_t targetRSSI=-90); // TWS: New method to enable/disable auto Power control
int16_t getTargetRssi();
int16_t getAckRSSI(void); // TWS: New method to retrieve the ack'd RSSI (if any) int16_t getAckRSSI(void); // TWS: New method to retrieve the ack'd RSSI (if any)
int16_t _targetRSSI; // if non-zero then this is the desired end point RSSI for our transmission int16_t _targetRSSI; // if non-zero then this is the desired end point RSSI for our transmission