diff --git a/RFM69.cpp b/RFM69.cpp index 746ddb9..4e55c34 100644 --- a/RFM69.cpp +++ b/RFM69.cpp @@ -140,14 +140,18 @@ bool RFM69::initialize(uint8_t freqBand, uint16_t nodeID, uint8_t networkID) { attachInterrupt(_interruptNum, RFM69::isr0, RISING); _address = nodeID; + _networkID = networkID; #if defined(RF69_LISTENMODE_ENABLE) selfPointer = this; _freqBand = freqBand; - _networkID = networkID; #endif return true; } +uint8_t RFM69::getVersion() { + return readReg(REG_VERSION); +} + // return the frequency (in Hz) uint32_t RFM69::getFrequency() { 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); } +// 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) { if (newMode == _mode) return; @@ -210,14 +223,23 @@ void RFM69::sleep() { // set this node's address void RFM69::setAddress(uint16_t addr) { _address = addr; - writeReg(REG_NODEADRS, _address); //unused in packet mode + writeReg(REG_NODEADRS, _address); // unused in packet mode +} + +uint16_t RFM69::getAddress() { + return _address; } // set this node's network id void RFM69::setNetwork(uint8_t networkID) { + _networkID = networkID; writeReg(REG_SYNCVALUE2, networkID); } +uint8_t RFM69::getNetwork() { + return _networkID; +} + // set user's ISR callback void RFM69::setIsrCallback(void (*callback)()) { _isrCallback = callback; @@ -263,8 +285,38 @@ void RFM69::setPowerLevel(uint8_t powerLevel) { writeReg(REG_PALEVEL, PA_SETTING | powerLevel); } -// return stored _powerLevel -uint8_t RFM69::getPowerLevel() { return _powerLevel; } +uint8_t RFM69::getOutputPower() { + // _RegisterBits(_REG_PA_LEVEL, offset=0, bits=5) + return readReg(REG_PALEVEL) & 0x1F; +} + +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 @@ -287,6 +339,10 @@ int8_t RFM69::setPowerDBm(int8_t dBm) { return dBm; } +double RFM69::dBm_to_mW(uint8_t dBm) { + return pow(10, (dBm / 10.0)); +} + bool RFM69::canSend() { if (_mode == RF69_MODE_RX && PAYLOADLEN == 0 && readRSSI() < CSMA_LIMIT) { // if signal stronger than -100dBm is detected assume channel activity setMode(RF69_MODE_STANDBY); @@ -568,6 +624,26 @@ void RFM69::spyMode(bool onOff) { //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 void RFM69::setHighPower(bool _isRFM69HW_HCW) { _isRFM69HW = _isRFM69HW_HCW; @@ -575,6 +651,10 @@ void RFM69::setHighPower(bool _isRFM69HW_HCW) { setPowerLevel(_powerLevel); } +bool RFM69::isHighPower() { + return _isRFM69HW; +} + // internal function - for HW/HCW only: // enables HiPower for 18-20dBm output // should only be used with PA1+PA2 diff --git a/RFM69.h b/RFM69.h index cb35b82..d7661e4 100644 --- a/RFM69.h +++ b/RFM69.h @@ -66,7 +66,7 @@ #elif defined(__APPLE__) // OSX #define RF69_PLATFORM RF69_PLATFORM_UNIX #else - #error Platform not defined! + #error Platform not defined! #endif #endif @@ -87,7 +87,7 @@ // Arduino Mega, Mega ADK, Mega Pro // 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))) - #elif defined(__AVR_ATmega1284__) || defined(__AVR_ATmega1284P__) + #elif defined(__AVR_ATmega1284__) || defined(__AVR_ATmega1284P__) // Arduino 1284 and 1284P - See Maniacbug and Optiboot // 10->0, 11->1, 2->2 #define digitalPinToInterrupt(p) ((p) == 10 ? 0 : ((p) == 11 ? 1 : ((p) == 2 ? 2 : NOT_AN_INTERRUPT))) @@ -163,6 +163,7 @@ #define RF69_BROADCAST_ADDR 0 #define RF69_CSMA_LIMIT_MS 1000 #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 @@ -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); bool initialize(uint8_t freqBand, uint16_t ID, uint8_t networkID=1); + uint8_t getVersion(); + uint16_t getAddress(); void setAddress(uint16_t addr); + uint8_t getNetwork(); void setNetwork(uint8_t networkID); void setIsrCallback(void (*callback)()); virtual bool canSend(); @@ -213,17 +217,27 @@ class RFM69 { virtual void sendACK(const void* buffer = "", uint8_t bufferSize=0); uint32_t getFrequency(); void setFrequency(uint32_t freqHz); + uint32_t getFrequencyDeviation(); + uint32_t getBitRate(); void encrypt(const char* key); void setCS(uint8_t newSPISlaveSelect); 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 + bool getSpyMode(); 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 + bool isHighPower(); 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 - virtual uint8_t getPowerLevel(); // get powerLevel + uint8_t getOutputPower(); + uint8_t getPowerLevel(); // get powerLevel 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] @@ -258,6 +272,7 @@ class RFM69 { uint8_t _interruptPin; uint8_t _interruptNum; uint16_t _address; + uint8_t _networkID; bool _spyMode; uint8_t _powerLevel; bool _isRFM69HW; @@ -280,17 +295,17 @@ class RFM69 { #if defined(RF69_LISTENMODE_ENABLE) static RFM69* selfPointer; //============================================================================= - // ListenMode specific declarations + // ListenMode specific declarations //============================================================================= public: // When we receive a packet in listen mode, this is the time left in the sender's burst. // You need to wait at least this long before trying to reply. static volatile uint16_t RF69_LISTEN_BURST_REMAINING_MS; - + void listenModeStart(void); void listenModeEnd(void); void listenModeHighSpeed(bool highSpeed) { _isHighSpeed = highSpeed; } - + // rx and idle duration in microseconds bool listenModeSetDurations(uint32_t& rxDuration, uint32_t& idleDuration); @@ -319,7 +334,6 @@ class RFM69 { // Save these so we can reinitialize the radio after sending a burst // or exiting listen mode. uint8_t _freqBand; - uint8_t _networkID; uint8_t _rxListenCoef; uint8_t _rxListenResolution; uint8_t _idleListenCoef; diff --git a/RFM69_ATC.cpp b/RFM69_ATC.cpp index 4313feb..f4c35c8 100644 --- a/RFM69_ATC.cpp +++ b/RFM69_ATC.cpp @@ -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 } +int16_t RFM69_ATC::getTargetRssi() { + return _targetRSSI; +} + //============================================================================= // getAckRSSI() - returns the RSSI value ack'd by the far end. //============================================================================= diff --git a/RFM69_ATC.h b/RFM69_ATC.h index 84dc580..c9b5dfe 100644 --- a/RFM69_ATC.h +++ b/RFM69_ATC.h @@ -44,6 +44,7 @@ class RFM69_ATC: public RFM69 { 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); 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 _targetRSSI; // if non-zero then this is the desired end point RSSI for our transmission