From f92e0e59d4ceb77bd7bb2d0326823418657587a3 Mon Sep 17 00:00:00 2001 From: StevenCellist Date: Wed, 1 Nov 2023 16:51:24 +0100 Subject: [PATCH] [LoRaWAN] Implement SX127x support, fix MAC uplinking, support clock drift --- src/ArduinoHal.cpp | 16 ++++ src/BuildOpt.h | 12 +++ src/Hal.h | 2 +- src/modules/SX127x/SX127x.cpp | 29 +++++++ src/modules/SX127x/SX127x.h | 22 +++++ src/protocols/LoRaWAN/LoRaWAN.cpp | 129 ++++++++++++++---------------- src/protocols/LoRaWAN/LoRaWAN.h | 13 ++- 7 files changed, 146 insertions(+), 77 deletions(-) diff --git a/src/ArduinoHal.cpp b/src/ArduinoHal.cpp index b1d4a92f..6beefa03 100644 --- a/src/ArduinoHal.cpp +++ b/src/ArduinoHal.cpp @@ -58,19 +58,35 @@ void inline ArduinoHal::detachInterrupt(uint32_t interruptNum) { } void inline ArduinoHal::delay(unsigned long ms) { +#if !defined(RADIOLIB_CLOCK_DRIFT_MS) ::delay(ms); +#else + ::delay(ms * (1000 - RADIOLIB_CLOCK_DRIFT_MS) / 1000); +#endif } void inline ArduinoHal::delayMicroseconds(unsigned long us) { +#if !defined(RADIOLIB_CLOCK_DRIFT_MS) ::delayMicroseconds(us); +#else + ::delayMicroseconds(us * (1000 - RADIOLIB_CLOCK_DRIFT_MS) / 1000); +#endif } unsigned long inline ArduinoHal::millis() { +#if !defined(RADIOLIB_CLOCK_DRIFT_MS) return(::millis()); +#else + return(::millis() * (1000 - RADIOLIB_CLOCK_DRIFT_MS) / 1000); +#endif } unsigned long inline ArduinoHal::micros() { +#if !defined(RADIOLIB_CLOCK_DRIFT_MS) return(::micros()); +#else + return(::micros() * (1000 - RADIOLIB_CLOCK_DRIFT_MS) / 1000); +#endif } long inline ArduinoHal::pulseIn(uint32_t pin, uint32_t state, unsigned long timeout) { diff --git a/src/BuildOpt.h b/src/BuildOpt.h index 1f8d952c..b3fdbe7f 100644 --- a/src/BuildOpt.h +++ b/src/BuildOpt.h @@ -446,6 +446,18 @@ #define RADIOLIB_HAL_PERSISTENT_STORAGE_SIZE (0x0180) #endif +/* + * Uncomment on boards whose clock runs too slow or too fast + * Set the value according to the following scheme: + * Enable timestamps on your terminal + * Print something to terminal, wait 1000 milliseconds, print something again + * If the difference is e.g. 1014 milliseconds between the prints, set this value to 14 + * Or, for more accuracy, wait for 100,000 milliseconds and divide the total drift by 100 + */ +#if !defined(RADIOLIB_CLOCK_DRIFT_MS) + //#define RADIOLIB_CLOCK_DRIFT_MS (0) +#endif + // This only compiles on STM32 boards with SUBGHZ module, but also // include when generating docs #if (!defined(ARDUINO_ARCH_STM32) || !defined(SUBGHZSPI_BASE)) && !defined(DOXYGEN) diff --git a/src/Hal.h b/src/Hal.h index 34930938..780c3483 100644 --- a/src/Hal.h +++ b/src/Hal.h @@ -9,7 +9,7 @@ // list of persistent parameters #define RADIOLIB_PERSISTENT_PARAM_LORAWAN_TABLE_VERSION_ID (0) // this is NOT the LoRaWAN version, but version of this table #define RADIOLIB_PERSISTENT_PARAM_LORAWAN_MAGIC_ID (1) -#define RADIOLIB_PERSISTENT_PARAM_LORAWAN_VERSION (2) +#define RADIOLIB_PERSISTENT_PARAM_LORAWAN_VERSION_ID (2) #define RADIOLIB_PERSISTENT_PARAM_LORAWAN_TXDR_RX2DR_ID (3) #define RADIOLIB_PERSISTENT_PARAM_LORAWAN_TXPWR_CUR_ID (4) #define RADIOLIB_PERSISTENT_PARAM_LORAWAN_RX1_DROFF_DEL_ID (5) diff --git a/src/modules/SX127x/SX127x.cpp b/src/modules/SX127x/SX127x.cpp index 1a8f2eaf..3f41c618 100644 --- a/src/modules/SX127x/SX127x.cpp +++ b/src/modules/SX127x/SX127x.cpp @@ -405,6 +405,13 @@ int16_t SX127x::startReceive(uint8_t len, uint8_t mode) { state |= this->mod->SPIsetRegValue(RADIOLIB_SX127X_REG_FIFO_ADDR_PTR, RADIOLIB_SX127X_FIFO_RX_BASE_ADDR_MAX); RADIOLIB_ASSERT(state); + // timeout is only used in RxSingle, so when a packet length is defined, force mode to RxSingle + // and set the timeout value to the expected number of symbols (usually preamble + header) + if(len > 0) { + mode = RADIOLIB_SX127X_RXSINGLE; + state = this->mod->SPIsetRegValue(RADIOLIB_SX127X_REG_SYMB_TIMEOUT_LSB, len); + } + } else if(modem == RADIOLIB_SX127X_FSK_OOK) { // set DIO pin mapping state = this->mod->SPIsetRegValue(RADIOLIB_SX127X_REG_DIO_MAPPING_1, RADIOLIB_SX127X_DIO0_PACK_PAYLOAD_READY, 7, 6); @@ -1237,6 +1244,28 @@ uint32_t SX127x::getTimeOnAir(size_t len) { } +uint32_t SX127x::calculateRxTimeout(uint8_t numSymbols, uint32_t timeoutUs) { + (void)numSymbols; // not used for these modules + // numSymbols += (109 / 4) + 1; + float symbolLength = (float) (uint32_t(1) << this->spreadingFactor) / (float) this->bandwidth; + numSymbols = timeoutUs / symbolLength + 1; + return(numSymbols); +} + +int16_t SX127x::irqRxDoneRxTimeout(uint16_t &irqFlags, uint16_t &irqMask) { + irqFlags = RADIOLIB_SX127X_MASK_IRQ_FLAG_RX_DONE; + irqMask = RADIOLIB_SX127X_MASK_IRQ_FLAG_RX_DONE; + irqFlags &= RADIOLIB_SX127X_MASK_IRQ_FLAG_RX_TIMEOUT; + irqMask &= RADIOLIB_SX127X_MASK_IRQ_FLAG_RX_TIMEOUT; + return(RADIOLIB_ERR_NONE); +} + +bool SX127x::isRxTimeout() { + uint16_t irq = getIRQFlags(); + bool rxTimedOut = irq & RADIOLIB_SX127X_CLEAR_IRQ_FLAG_RX_TIMEOUT; + return(rxTimedOut); +} + int16_t SX127x::setCrcFiltering(bool enable) { this->crcOn = enable; diff --git a/src/modules/SX127x/SX127x.h b/src/modules/SX127x/SX127x.h index 9ef2890f..bbfb3db8 100644 --- a/src/modules/SX127x/SX127x.h +++ b/src/modules/SX127x/SX127x.h @@ -1039,6 +1039,28 @@ class SX127x: public PhysicalLayer { */ uint32_t getTimeOnAir(size_t len) override; + /*! + \brief Calculate the timeout value for this specific module / series based on number of symbols or time + \param numSymbols Number of payload symbols to listen for + \param timeoutUs Timeout in microseconds to listen for + \returns Timeout value in a unit that is specific for the used module + */ + uint32_t calculateRxTimeout(uint8_t numSymbols, uint32_t timeoutUs); + + /*! + \brief Create the flags that make up RxDone and RxTimeout used for receiving downlinks + \param irqFlags The flags for which IRQs must be triggered + \param irqMask Mask indicating which IRQ triggers a DIO + \returns \ref status_codes + */ + int16_t irqRxDoneRxTimeout(uint16_t &irqFlags, uint16_t &irqMask); + + /*! + \brief Check whether the IRQ bit for RxTimeout is set + \returns \ref RxTimeout IRQ is set + */ + bool isRxTimeout(); + /*! \brief Enable CRC filtering and generation. \param enable Set or unset CRC filtering and generation. diff --git a/src/protocols/LoRaWAN/LoRaWAN.cpp b/src/protocols/LoRaWAN/LoRaWAN.cpp index 65359b33..6ff20c69 100644 --- a/src/protocols/LoRaWAN/LoRaWAN.cpp +++ b/src/protocols/LoRaWAN/LoRaWAN.cpp @@ -38,7 +38,7 @@ int16_t LoRaWANNode::restore() { // check the magic value Module* mod = this->phyLayer->getMod(); - uint16_t nvm_table_version = mod->hal->getPersistentParameter(RADIOLIB_PERSISTENT_PARAM_LORAWAN_TABLE_VERSION_ID); + uint8_t nvm_table_version = mod->hal->getPersistentParameter(RADIOLIB_PERSISTENT_PARAM_LORAWAN_TABLE_VERSION_ID); // if (RADIOLIB_PERSISTENT_PARAM_LORAWAN_TABLE_VERSION > nvm_table_version) { // // set default values for variables that are new or something // } @@ -58,7 +58,7 @@ int16_t LoRaWANNode::restore() { mod->hal->readPersistentStorage(mod->hal->getPersistentAddr(RADIOLIB_PERSISTENT_PARAM_LORAWAN_NWK_SENC_KEY_ID), this->nwkSEncKey, RADIOLIB_AES128_BLOCK_SIZE); // get session parameters - this->rev = mod->hal->getPersistentParameter(RADIOLIB_PERSISTENT_PARAM_LORAWAN_VERSION); + this->rev = mod->hal->getPersistentParameter(RADIOLIB_PERSISTENT_PARAM_LORAWAN_VERSION_ID); RADIOLIB_DEBUG_PRINTLN("LoRaWAN session: v1.%d", this->rev); this->devNonce = mod->hal->getPersistentParameter(RADIOLIB_PERSISTENT_PARAM_LORAWAN_DEV_NONCE_ID); this->joinNonce = mod->hal->getPersistentParameter(RADIOLIB_PERSISTENT_PARAM_LORAWAN_JOIN_NONCE_ID); @@ -217,6 +217,7 @@ int16_t LoRaWANNode::beginOTAA(uint64_t joinEUI, uint64_t devEUI, uint8_t* nwkKe // send it state = this->phyLayer->transmit(joinRequestMsg, RADIOLIB_LORAWAN_JOIN_REQUEST_LEN); this->rxDelayStart = mod->hal->millis(); + RADIOLIB_DEBUG_PRINTLN("Join-request sent <-- Rx Delay start"); RADIOLIB_ASSERT(state); // configure Rx delay for join-accept message - these are re-configured once a valid join-request is received @@ -356,8 +357,8 @@ int16_t LoRaWANNode::beginOTAA(uint64_t joinEUI, uint64_t devEUI, uint8_t* nwkKe // enqueue the RekeyInd MAC command to be sent in the next uplink LoRaWANMacCommand_t cmd = { .cid = RADIOLIB_LORAWAN_MAC_CMD_REKEY, - .len = sizeof(uint8_t), .payload = { this->rev }, + .len = sizeof(uint8_t), .repeat = 0x01 << RADIOLIB_LORAWAN_ADR_ACK_LIMIT_EXP, }; state = pushMacCommand(&cmd, &this->commandsUp); @@ -468,8 +469,8 @@ int16_t LoRaWANNode::saveSession() { Module* mod = this->phyLayer->getMod(); // store session configuration (MAC commands) - if(mod->hal->getPersistentParameter(RADIOLIB_PERSISTENT_PARAM_LORAWAN_VERSION) != this->rev) - mod->hal->setPersistentParameter(RADIOLIB_PERSISTENT_PARAM_LORAWAN_VERSION, this->rev); + if(mod->hal->getPersistentParameter(RADIOLIB_PERSISTENT_PARAM_LORAWAN_VERSION_ID) != this->rev) + mod->hal->setPersistentParameter(RADIOLIB_PERSISTENT_PARAM_LORAWAN_VERSION_ID, this->rev); if(mod->hal->getPersistentParameter(RADIOLIB_PERSISTENT_PARAM_LORAWAN_DEV_NONCE_ID) != this->devNonce) mod->hal->setPersistentParameter(RADIOLIB_PERSISTENT_PARAM_LORAWAN_DEV_NONCE_ID, this->devNonce); @@ -629,7 +630,7 @@ int16_t LoRaWANNode::uplink(uint8_t* data, size_t len, uint8_t port, bool isConf Module* mod = this->phyLayer->getMod(); // check if sufficient time has elapsed since the last uplink - if(mod->hal->millis() - this->rxDelayStart < rxDelays[1]) { + if(mod->hal->millis() - this->rxDelayStart < this->rxDelays[1]) { // not enough time elapsed since the last uplink, we may still be in an RX window return(RADIOLIB_ERR_UPLINK_UNAVAILABLE); } @@ -687,12 +688,14 @@ int16_t LoRaWANNode::uplink(uint8_t* data, size_t len, uint8_t port, bool isConf // 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) { this->dataRates[RADIOLIB_LORAWAN_CHANNEL_DIR_UPLINK]--; + this->dataRates[RADIOLIB_LORAWAN_CHANNEL_DIR_DOWNLINK]--; } else { // failed to decrease datarate, so enable all available channels for(size_t i = 0; i < RADIOLIB_LORAWAN_NUM_AVAILABLE_CHANNELS; i++) { if(this->availableChannels[RADIOLIB_LORAWAN_CHANNEL_DIR_UPLINK][i].idx != RADIOLIB_LORAWAN_CHANNEL_INDEX_NONE) { this->availableChannels[RADIOLIB_LORAWAN_CHANNEL_DIR_UPLINK][i].enabled = true; + this->availableChannels[RADIOLIB_LORAWAN_CHANNEL_DIR_DOWNLINK][i].enabled = true; } } } @@ -747,25 +750,31 @@ int16_t LoRaWANNode::uplink(uint8_t* data, size_t len, uint8_t port, bool isConf // check if we have some MAC commands to append if(foptsLen > 0) { - uint8_t foptsNum = this->commandsUp.numCommands; uint8_t foptsBuff[foptsBufSize]; - size_t idx = 0; - for (size_t i = 0; i < foptsNum; i++) { - LoRaWANMacCommand_t cmd = { .cid = 0, .len = 0, .payload = { 0 }, .repeat = 0, }; - popMacCommand(&cmd, &this->commandsUp, i); - if (cmd.cid == 0) { + uint8_t* foptsPtr = foptsBuff; + + // append all MAC replies into fopts buffer + size_t i = 0; + for (; i < this->commandsUp.numCommands; i++) { + LoRaWANMacCommand_t cmd = this->commandsUp.commands[i]; + memcpy(foptsPtr, &cmd, 1 + cmd.len); + foptsPtr += cmd.len + 1; + } + RADIOLIB_DEBUG_PRINTLN("Uplink MAC payload (%d commands):", this->commandsUp.numCommands); + RADIOLIB_DEBUG_HEXDUMP(foptsBuff, foptsLen); + + // pop the commands from back to front + for (; i >= 0; i--) { + if(this->commandsUp.commands[i].repeat > 0) { + this->commandsUp.commands[i].repeat--; + } else { + deleteMacCommand(this->commandsUp.commands[i].cid, &this->commandsUp); + } + if(i == 0) { break; } - foptsBuff[idx] = cmd.cid; - for(size_t i = 0; i < cmd.len; i++) { - foptsBuff[idx + 1 + i] = cmd.payload[i]; - } - idx += cmd.len + 1; } - RADIOLIB_DEBUG_PRINTLN("Uplink MAC payload (%d commands):", foptsNum); - RADIOLIB_DEBUG_HEXDUMP(foptsBuff, foptsBufSize); - uplinkMsgLen = RADIOLIB_LORAWAN_FRAME_LEN(len, foptsLen); uplinkMsg[RADIOLIB_LORAWAN_FHDR_FCTRL_POS] |= foptsLen; @@ -860,22 +869,22 @@ int16_t LoRaWANNode::downlinkCommon() { RADIOLIB_ASSERT(state); } - // calculate the Rx timeout - // according to the spec, this must be at least enough time to effectively detect a preamble - // but pad it a bit on both sides (start and end) to make sure it is wide enough - uint32_t timeoutHost = this->phyLayer->getTimeOnAir(0) + 2*scanGuard*1000; - uint32_t timeoutMod = this->phyLayer->calculateRxTimeout(0, timeoutHost); - // create the masks that are required for receiving downlinks uint16_t irqFlags; uint16_t irqMask; this->phyLayer->irqRxDoneRxTimeout(irqFlags, irqMask); - downlinkAction = false; this->phyLayer->setPacketReceivedAction(LoRaWANNodeOnDownlinkAction); // perform listening in the two Rx windows for(uint8_t i = 0; i < 2; i++) { + downlinkAction = false; + + // calculate the Rx timeout + // according to the spec, this must be at least enough time to effectively detect a preamble + // but pad it a bit on both sides (start and end) to make sure it is wide enough + uint32_t timeoutHost = this->phyLayer->getTimeOnAir(0) + 2*scanGuard*1000; + uint32_t timeoutMod = this->phyLayer->calculateRxTimeout(0, timeoutHost); // wait for the start of the Rx window // the waiting duration is shortened a bit to cover any possible timing errors @@ -886,15 +895,15 @@ int16_t LoRaWANNode::downlinkCommon() { mod->hal->delay(waitLen); // open Rx window by starting receive with specified timeout - state = this->phyLayer->startReceive(timeoutMod, irqFlags, irqMask, 0); + state = this->phyLayer->startReceive(timeoutMod, irqFlags, irqMask, timeoutMod); RADIOLIB_DEBUG_PRINTLN("Opening Rx%d window (%d us timeout)... <-- Rx Delay end ", i+1, timeoutHost); // wait for the timeout to complete (and a small additional delay) mod->hal->delay(timeoutHost / 1000 + scanGuard / 2); RADIOLIB_DEBUG_PRINTLN("closing"); - // check if the DIO has fired indicating a timeout; no timeout means a receive is ongoing - if(!downlinkAction) { + // check if the IRQ bit for Rx Timeout is set + if(!this->phyLayer->isRxTimeout()) { break; } else if(i == 0) { @@ -907,15 +916,12 @@ int16_t LoRaWANNode::downlinkCommon() { findDataRate(this->rx2.drMax, &dataRate); state = this->phyLayer->setDataRate(dataRate); RADIOLIB_ASSERT(state); - timeoutHost = this->phyLayer->getTimeOnAir(0) + 2*scanGuard*1000; - timeoutMod = this->phyLayer->calculateRxTimeout(0, timeoutHost); - downlinkAction = false; } } // if we got here due to a timeout, stop ongoing activities - if(downlinkAction) { + if(this->phyLayer->isRxTimeout()) { this->phyLayer->standby(); // TODO check: this should be done automagically due to RxSingle? if(!this->FSK) { this->phyLayer->invertIQ(false); @@ -1113,8 +1119,8 @@ int16_t LoRaWANNode::downlink(uint8_t* data, size_t* len) { while(remLen > 0) { LoRaWANMacCommand_t cmd = { .cid = *foptsPtr, - .len = (uint8_t)(remLen - 1), .payload = { 0 }, + .len = (uint8_t)(remLen - 1), .repeat = 0, }; memcpy(cmd.payload, foptsPtr + 1, cmd.len); @@ -1130,24 +1136,30 @@ int16_t LoRaWANNode::downlink(uint8_t* data, size_t* len) { // if FOptsLen for the next uplink is larger than can be piggybacked onto an uplink, send separate uplink if(this->commandsUp.len > 15) { - uint8_t foptsNum = this->commandsUp.numCommands; size_t foptsBufSize = this->commandsUp.len; uint8_t foptsBuff[foptsBufSize]; - size_t idx = 0; - for(size_t i = 0; i < foptsNum; i++) { - LoRaWANMacCommand_t cmd = { .cid = 0, .len = 0, .payload = { 0 }, .repeat = 0, }; - popMacCommand(&cmd, &this->commandsUp, i); - if(cmd.cid == 0) { + uint8_t* foptsPtr = foptsBuff; + // append all MAC replies into fopts buffer + size_t i = 0; + for (; i < this->commandsUp.numCommands; i++) { + LoRaWANMacCommand_t cmd = this->commandsUp.commands[i]; + memcpy(foptsPtr, &cmd, 1 + cmd.len); + foptsPtr += cmd.len + 1; + } + RADIOLIB_DEBUG_PRINTLN("Uplink MAC payload (%d commands):", this->commandsUp.numCommands); + RADIOLIB_DEBUG_HEXDUMP(foptsBuff, foptsBufSize); + + // pop the commands from back to front + for (; i >= 0; i--) { + if(this->commandsUp.commands[i].repeat > 0) { + this->commandsUp.commands[i].repeat--; + } else { + deleteMacCommand(this->commandsUp.commands[i].cid, &this->commandsUp); + } + if(i == 0) { break; } - foptsBuff[idx] = cmd.cid; - for(size_t i = 1; i < cmd.len; i++) { - foptsBuff[idx + i] = cmd.payload[i]; - } - idx += cmd.len + 1; } - RADIOLIB_DEBUG_PRINTLN("Uplink MAC payload (%d commands):", foptsNum); - RADIOLIB_DEBUG_HEXDUMP(foptsBuff, foptsBufSize); this->isMACPayload = true; this->uplink(foptsBuff, foptsBufSize, RADIOLIB_LORAWAN_FPORT_MAC_COMMAND); @@ -1484,24 +1496,6 @@ int16_t LoRaWANNode::pushMacCommand(LoRaWANMacCommand_t* cmd, LoRaWANMacCommandQ return(RADIOLIB_ERR_NONE); } -int16_t LoRaWANNode::popMacCommand(LoRaWANMacCommand_t* cmd, LoRaWANMacCommandQueue_t* queue, size_t index) { - if(queue->numCommands == 0) { - return(RADIOLIB_ERR_COMMAND_QUEUE_EMPTY); - } - - if(cmd) { - memcpy(cmd, &queue->commands[index], sizeof(LoRaWANMacCommand_t)); - } - - if(queue->commands[index].repeat > 0) { - queue->commands[index].repeat--; - } else { - deleteMacCommand(queue->commands[index].cid, queue); - } - - return(RADIOLIB_ERR_NONE); -} - int16_t LoRaWANNode::deleteMacCommand(uint8_t cid, LoRaWANMacCommandQueue_t* queue) { if(queue->numCommands == 0) { return(RADIOLIB_ERR_COMMAND_QUEUE_EMPTY); @@ -1512,7 +1506,7 @@ int16_t LoRaWANNode::deleteMacCommand(uint8_t cid, LoRaWANMacCommandQueue_t* que queue->len -= (1 + queue->commands[index].len); // 1 byte for command ID, len for payload // move all subsequent commands one forward in the queue if(index < RADIOLIB_LORAWAN_MAC_COMMAND_QUEUE_SIZE - 1) { - memmove(&queue->commands[index], &queue->commands[index + 1], (RADIOLIB_LORAWAN_MAC_COMMAND_QUEUE_SIZE - index) * sizeof(LoRaWANMacCommand_t)); + memmove(&queue->commands[index], &queue->commands[index + 1], (RADIOLIB_LORAWAN_MAC_COMMAND_QUEUE_SIZE - index - 1) * sizeof(LoRaWANMacCommand_t)); } // set the latest element to all 0 memset(&queue->commands[RADIOLIB_LORAWAN_MAC_COMMAND_QUEUE_SIZE - 1], 0x00, sizeof(LoRaWANMacCommand_t)); @@ -1526,7 +1520,6 @@ int16_t LoRaWANNode::deleteMacCommand(uint8_t cid, LoRaWANMacCommandQueue_t* que size_t LoRaWANNode::execMacCommand(LoRaWANMacCommand_t* cmd) { RADIOLIB_DEBUG_PRINTLN("exe MAC CID = %02x, len = %d", cmd->cid, cmd->len); - Module* mod = this->phyLayer->getMod(); if(cmd->cid >= RADIOLIB_LORAWAN_MAC_CMD_PROPRIETARY) { // TODO call user-provided callback for proprietary MAC commands? diff --git a/src/protocols/LoRaWAN/LoRaWAN.h b/src/protocols/LoRaWAN/LoRaWAN.h index ff1644ad..8eab3c81 100644 --- a/src/protocols/LoRaWAN/LoRaWAN.h +++ b/src/protocols/LoRaWAN/LoRaWAN.h @@ -295,12 +295,12 @@ struct LoRaWANMacCommand_t { /*! \brief The command ID */ uint8_t cid; - /*! \brief Length of the payload */ - uint8_t len; - /*! \brief Payload buffer (5 bytes is the longest possible) */ uint8_t payload[5]; + /*! \brief Length of the payload */ + uint8_t len; + /*! \brief Repetition counter (the command will be uplinked repeat + 1 times) */ uint8_t repeat; }; @@ -477,12 +477,12 @@ class LoRaWANNode { LoRaWANMacCommandQueue_t commandsUp = { .numCommands = 0, .len = 0, - .commands = { { .cid = 0, .len = 0, .payload = { 0 }, .repeat = 0, } }, + .commands = { { .cid = 0, .payload = { 0 }, .len = 0, .repeat = 0, } }, }; LoRaWANMacCommandQueue_t commandsDown = { .numCommands = 0, .len = 0, - .commands = { { .cid = 0, .len = 0, .payload = { 0 }, .repeat = 0, } }, + .commands = { { .cid = 0, .payload = { 0 }, .len = 0, .repeat = 0, } }, }; // the following is either provided by the network server (OTAA) @@ -570,9 +570,6 @@ class LoRaWANNode { // push MAC command to queue, done by copy int16_t pushMacCommand(LoRaWANMacCommand_t* cmd, LoRaWANMacCommandQueue_t* queue); - - // pop MAC command from queue, done by copy unless CMD is NULL - int16_t popMacCommand(LoRaWANMacCommand_t* cmd, LoRaWANMacCommandQueue_t* queue, size_t index); // delete a specific MAC command from queue, indicated by the command ID int16_t deleteMacCommand(uint8_t cid, LoRaWANMacCommandQueue_t* queue);