diff --git a/examples/RF69/RF69_Transmit/RF69_Transmit.ino b/examples/RF69/RF69_Transmit/RF69_Transmit.ino index 05879c0b..5d39f6f2 100644 --- a/examples/RF69/RF69_Transmit/RF69_Transmit.ino +++ b/examples/RF69/RF69_Transmit/RF69_Transmit.ino @@ -43,6 +43,23 @@ void setup() { Serial.println(state); while (true); } + + // NOTE: some RF69 modules use high power output, + // those are usually marked RF69H(C/CW). + // To configure RadioLib for these modules, + // you must call setOutputPower() with + // second argument set to true. + /* + Serial.print(F("[RF69] Setting high power module ... ")); + state = rf.setOutputPower(20, true); + if (state == ERR_NONE) { + Serial.println(F("success!")); + } else { + Serial.print(F("failed, code ")); + Serial.println(state); + while (true); + } + */ } void loop() { diff --git a/examples/RF69/RF69_Transmit_Interrupt/RF69_Transmit_Interrupt.ino b/examples/RF69/RF69_Transmit_Interrupt/RF69_Transmit_Interrupt.ino index 3e83042a..e07b41ec 100644 --- a/examples/RF69/RF69_Transmit_Interrupt/RF69_Transmit_Interrupt.ino +++ b/examples/RF69/RF69_Transmit_Interrupt/RF69_Transmit_Interrupt.ino @@ -52,6 +52,23 @@ void setup() { // when packet transmission is finished rf.setDio0Action(setFlag); + // NOTE: some RF69 modules use high power output, + // those are usually marked RF69H(C/CW). + // To configure RadioLib for these modules, + // you must call setOutputPower() with + // second argument set to true. + /* + Serial.print(F("[RF69] Setting high power module ... ")); + state = rf.setOutputPower(20, true); + if (state == ERR_NONE) { + Serial.println(F("success!")); + } else { + Serial.print(F("failed, code ")); + Serial.println(state); + while (true); + } + */ + // start transmitting the first packet Serial.print(F("[RF69] Sending first packet ... ")); diff --git a/src/modules/RF69/RF69.cpp b/src/modules/RF69/RF69.cpp index 35bb2070..ba7bfcb7 100644 --- a/src/modules/RF69/RF69.cpp +++ b/src/modules/RF69/RF69.cpp @@ -239,9 +239,12 @@ int16_t RF69::startReceive() { clearIRQFlags(); // set mode to receive - state = _mod->SPIsetRegValue(RF69_REG_TEST_PA1, RF69_PA1_NORMAL); + state = _mod->SPIsetRegValue(RF69_REG_OCP, RF69_OCP_ON | RF69_OCP_TRIM); + state |= _mod->SPIsetRegValue(RF69_REG_TEST_PA1, RF69_PA1_NORMAL); state |= _mod->SPIsetRegValue(RF69_REG_TEST_PA2, RF69_PA2_NORMAL); - state |= setMode(RF69_RX); + RADIOLIB_ASSERT(state); + + state = setMode(RF69_RX); return(state); } @@ -303,10 +306,16 @@ int16_t RF69::startTransmit(uint8_t* data, size_t len, uint8_t addr) { // write packet to FIFO _mod->SPIwriteRegisterBurst(RF69_REG_FIFO, data, len); + // enable +20 dBm operation + if(_power > 17) { + state = _mod->SPIsetRegValue(RF69_REG_OCP, RF69_OCP_OFF | 0x0F); + state |= _mod->SPIsetRegValue(RF69_REG_TEST_PA1, RF69_PA1_20_DBM); + state |= _mod->SPIsetRegValue(RF69_REG_TEST_PA2, RF69_PA2_20_DBM); + RADIOLIB_ASSERT(state); + } + // set mode to transmit - state = _mod->SPIsetRegValue(RF69_REG_TEST_PA1, RF69_PA1_20_DBM); - state |= _mod->SPIsetRegValue(RF69_REG_TEST_PA2, RF69_PA2_20_DBM); - state |= setMode(RF69_TX); + state = setMode(RF69_TX); return(state); } @@ -493,22 +502,41 @@ int16_t RF69::setFrequencyDeviation(float freqDev) { return(state); } -int16_t RF69::setOutputPower(int8_t power) { - RADIOLIB_CHECK_RANGE(power, -18, 17, ERR_INVALID_OUTPUT_POWER); +int16_t RF69::setOutputPower(int8_t power, bool highPower) { + if(highPower) { + RADIOLIB_CHECK_RANGE(power, -2, 20, ERR_INVALID_OUTPUT_POWER); + } else { + RADIOLIB_CHECK_RANGE(power, -18, 13, ERR_INVALID_OUTPUT_POWER); + } // set mode to standby setMode(RF69_STANDBY); // set output power int16_t state; - if(power > 13) { - // requested output power is higher than 13 dBm, enable PA2 + PA1 on PA_BOOST - state = _mod->SPIsetRegValue(RF69_REG_PA_LEVEL, RF69_PA0_OFF | RF69_PA1_ON | RF69_PA2_ON | (power + 14), 7, 0); + if(highPower) { + // check if both PA1 and PA2 are needed + if(power <= 10) { + // -2 to 13 dBm, PA1 is enough + state = _mod->SPIsetRegValue(RF69_REG_PA_LEVEL, RF69_PA0_OFF | RF69_PA1_ON | RF69_PA2_OFF | (power + 18), 7, 0); + } else if(power <= 17) { + // 13 to 17 dBm, both PAs required + state = _mod->SPIsetRegValue(RF69_REG_PA_LEVEL, RF69_PA0_OFF | RF69_PA1_ON | RF69_PA2_ON | (power + 14), 7, 0); + } else { + // 18 - 20 dBm, both PAs and hig power settings required + state = _mod->SPIsetRegValue(RF69_REG_PA_LEVEL, RF69_PA0_OFF | RF69_PA1_ON | RF69_PA2_ON | (power + 11), 7, 0); + } + } else { - // requested output power is lower than 13 dBm, enable PA0 on RFIO + // low power module, use only PA0 state = _mod->SPIsetRegValue(RF69_REG_PA_LEVEL, RF69_PA0_ON | RF69_PA1_OFF | RF69_PA2_OFF | (power + 18), 7, 0); } + // cache the power value + if(state == ERR_NONE) { + _power = power; + } + return(state); } diff --git a/src/modules/RF69/RF69.h b/src/modules/RF69/RF69.h index 9f465df6..18aa8df4 100644 --- a/src/modules/RF69/RF69.h +++ b/src/modules/RF69/RF69.h @@ -188,7 +188,7 @@ // RF69_REG_OCP #define RF69_OCP_OFF 0b00000000 // 4 4 PA overload current protection disabled -#define RF69_OCP_ON 0b00100000 // 4 4 PA overload current protection enabled +#define RF69_OCP_ON 0b00010000 // 4 4 PA overload current protection enabled #define RF69_OCP_TRIM 0b00001010 // 3 0 OCP current: I_max(OCP_TRIM = 0b1010) = 95 mA // RF69_REG_LNA @@ -646,13 +646,15 @@ class RF69: public PhysicalLayer { int16_t setFrequencyDeviation(float freqDev); /*! - \brief Sets output power. Allowed values are -30, -20, -15, -10, 0, 5, 7 or 10 dBm. + \brief Sets output power. Allowed values range from -18 to 13 dBm for low power modules (RF69C/CW) or -2 to 20 dBm (RF69H/HC/HCW). \param power Output power to be set in dBm. + \param highPower Set to true when using modules high power port (RF69H/HC/HCW). Defaults to false (models without high power port - RF69C/CW). + \returns \ref status_codes */ - int16_t setOutputPower(int8_t power); + int16_t setOutputPower(int8_t power, bool highPower = false); /*! \brief Sets sync word. Up to 8 bytes can be set as sync word. @@ -801,6 +803,7 @@ class RF69: public PhysicalLayer { float _br; float _rxBw; int16_t _tempOffset; + int8_t _power; size_t _packetLength; bool _packetLengthQueried;