From 594d8cbba11add408844950f6f726bc31c9138b8 Mon Sep 17 00:00:00 2001
From: StevenCellist <steven@boonstoppel.nu>
Date: Mon, 27 Nov 2023 12:39:14 +0100
Subject: [PATCH] [LoRaWAN] Move TX power logic to function

---
 src/protocols/LoRaWAN/LoRaWAN.cpp | 50 +++++++++++++++++--------------
 src/protocols/LoRaWAN/LoRaWAN.h   | 11 +++++--
 2 files changed, 37 insertions(+), 24 deletions(-)

diff --git a/src/protocols/LoRaWAN/LoRaWAN.cpp b/src/protocols/LoRaWAN/LoRaWAN.cpp
index af930be9..a8f1fd2b 100644
--- a/src/protocols/LoRaWAN/LoRaWAN.cpp
+++ b/src/protocols/LoRaWAN/LoRaWAN.cpp
@@ -698,6 +698,8 @@ int16_t LoRaWANNode::uplink(uint8_t* data, size_t len, uint8_t port, bool isConf
     this->isMACPayload = false;
   }
 
+  int16_t state = RADIOLIB_ERR_NONE;
+
   // check if there are some MAC commands to piggyback (only when piggybacking onto a application-frame)
   uint8_t foptsLen = 0;
   size_t foptsBufSize = 0;
@@ -722,18 +724,16 @@ int16_t LoRaWANNode::uplink(uint8_t* data, size_t len, uint8_t port, bool isConf
   if((this->fcntUp - this->adrFcnt) >= adrLimit) {
     adrAckReq = true;
   }
+  // if we hit the Limit + Delay, try one of three, in order: 
+  // set TxPower to max, set DR to min, enable all defined channels
   if ((this->fcntUp - this->adrFcnt) == (adrLimit + adrDelay)) {
-    // try one of three, in order: set TxPower to max, set DR to min, enable all defined channels
 
     // set the maximum power supported by both the module and the band
-    int8_t pwr = this->band->powerMax;
-    int16_t state = RADIOLIB_ERR_INVALID_OUTPUT_POWER;
-    while(state == RADIOLIB_ERR_INVALID_OUTPUT_POWER) {
-      // go from the highest power in band and lower it until we hit one supported by the module
-      state = this->phyLayer->setOutputPower(pwr--);
-    }
+    int8_t pwrPrev = this->txPwrCur;
+    state = this->setTxPower(this->band->powerMax);
     RADIOLIB_ASSERT(state);
-    if(pwr == this->txPwrCur) {
+
+    if(this->txPwrCur == pwrPrev) {
 
       // failed to increase Tx power, so try to decrease the datarate
       if(this->dataRates[RADIOLIB_LORAWAN_CHANNEL_DIR_UPLINK] > this->currentChannels[RADIOLIB_LORAWAN_CHANNEL_DIR_UPLINK].drMin) {
@@ -750,8 +750,6 @@ int16_t LoRaWANNode::uplink(uint8_t* data, size_t len, uint8_t port, bool isConf
         }
       }
 
-    } else {
-      this->txPwrCur = pwr;
     }
 
     // we tried something to improve the range, so increase the ADR frame counter by 'ADR delay'
@@ -760,7 +758,7 @@ int16_t LoRaWANNode::uplink(uint8_t* data, size_t len, uint8_t port, bool isConf
 
   // configure for uplink
   this->selectChannels();
-  int16_t state = this->configureChannel(RADIOLIB_LORAWAN_CHANNEL_DIR_UPLINK);
+  state = this->configureChannel(RADIOLIB_LORAWAN_CHANNEL_DIR_UPLINK);
   RADIOLIB_ASSERT(state);
 
   // build the uplink message
@@ -1366,15 +1364,8 @@ bool LoRaWANNode::verifyMIC(uint8_t* msg, size_t len, uint8_t* key) {
 
 int16_t LoRaWANNode::setPhyProperties() {
   // set the physical layer configuration
-
-  // set the maximum power supported by both the module and the band
-  int16_t state = RADIOLIB_ERR_INVALID_OUTPUT_POWER;
-  while(state == RADIOLIB_ERR_INVALID_OUTPUT_POWER) {
-    // go from the highest power in band and lower it until we hit one supported by the module
-    state = this->phyLayer->setOutputPower(this->txPwrCur--);
-  }
+  int16_t state = this->setTxPower(this->txPwrCur);
   RADIOLIB_ASSERT(state);
-  this->txPwrCur++;
 
   uint8_t syncWord[3] = { 0 };
   uint8_t syncWordLen = 0;
@@ -1688,6 +1679,19 @@ void LoRaWANNode::setADR(bool enable) {
   this->adrEnabled = enable;
 }
 
+int16_t LoRaWANNode::setTxPower(int8_t txPower) {
+  int16_t state = RADIOLIB_ERR_INVALID_OUTPUT_POWER;
+  while(state == RADIOLIB_ERR_INVALID_OUTPUT_POWER) {
+    // go from the highest power and lower it until we hit one supported by the module
+    state = this->phyLayer->setOutputPower(txPower--);
+  }
+  if(state == RADIOLIB_ERR_NONE) {
+    txPower++;
+    this->txPwrCur = txPower;
+  }
+  return(state);
+}
+
 int16_t LoRaWANNode::findDataRate(uint8_t dr, DataRate_t* dataRate) {
   uint8_t dataRateBand = this->band->dataRates[dr];
 
@@ -1838,13 +1842,15 @@ size_t LoRaWANNode::execMacCommand(LoRaWANMacCommand_t* cmd) {
       uint8_t pwrAck = 0;
       if(txPower == 0x0F) {
         pwrAck = 1;
+
       } else {
         int8_t pwr = this->band->powerMax - 2*txPower;
-        if(this->phyLayer->setOutputPower(pwr) == RADIOLIB_ERR_NONE) {
-          RADIOLIB_DEBUG_PRINTLN("ADR set pwr = %d", pwr);
+        int16_t state = this->setTxPower(pwr);
+        // only acknowledge if the requested datarate was succesfully configured
+        if((state == RADIOLIB_ERR_NONE) && (this->txPwrCur == pwr)) {
           pwrAck = 1;
         }
-        this->txPwrCur = pwr;
+
       }
 
       uint8_t chMaskAck = 1;
diff --git a/src/protocols/LoRaWAN/LoRaWAN.h b/src/protocols/LoRaWAN/LoRaWAN.h
index da1a4356..6e4523d0 100644
--- a/src/protocols/LoRaWAN/LoRaWAN.h
+++ b/src/protocols/LoRaWAN/LoRaWAN.h
@@ -532,11 +532,18 @@ class LoRaWANNode {
     int16_t setDatarate(uint8_t drUp);
 
     /*!
-      \brief Toggle ADR to on or off
-      \param enable Whether to disable ADR or not
+      \brief Toggle ADR to on or off.
+      \param enable Whether to disable ADR or not.
     */
     void setADR(bool enable = true);
 
+    /*!
+      \brief Configure TX power of the radio module.
+      \param txPower Output power during TX mode to be set in dBm.
+      \returns \ref status_codes
+    */
+    int16_t setTxPower(int8_t txPower);
+
     /*!
       \brief Select a single subband (8 channels) for fixed bands such as US915.
       Only available before joining a network.