Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Fork of LoRaWAN-lib by
region/RegionCommon.cpp@38:182ba91524e4, 2017-08-09 (annotated)
- Committer:
- Shaun Nelson
- Date:
- Wed Aug 09 16:20:21 2017 -0400
- Branch:
- class_b
- Revision:
- 38:182ba91524e4
Synchronized with https://github.com/Senetco/LoRaMac-node/commit/6cb21de99eaa65caad9d911318df8875867a6e60
Who changed what in which revision?
| User | Revision | Line number | New contents of line |
|---|---|---|---|
| Shaun Nelson |
38:182ba91524e4 | 1 | /* |
| Shaun Nelson |
38:182ba91524e4 | 2 | / _____) _ | | |
| Shaun Nelson |
38:182ba91524e4 | 3 | ( (____ _____ ____ _| |_ _____ ____| |__ |
| Shaun Nelson |
38:182ba91524e4 | 4 | \____ \| ___ | (_ _) ___ |/ ___) _ \ |
| Shaun Nelson |
38:182ba91524e4 | 5 | _____) ) ____| | | || |_| ____( (___| | | | |
| Shaun Nelson |
38:182ba91524e4 | 6 | (______/|_____)_|_|_| \__)_____)\____)_| |_| |
| Shaun Nelson |
38:182ba91524e4 | 7 | (C)2013 Semtech |
| Shaun Nelson |
38:182ba91524e4 | 8 | ___ _____ _ ___ _ _____ ___ ___ ___ ___ |
| Shaun Nelson |
38:182ba91524e4 | 9 | / __|_ _/_\ / __| |/ / __/ _ \| _ \/ __| __| |
| Shaun Nelson |
38:182ba91524e4 | 10 | \__ \ | |/ _ \ (__| ' <| _| (_) | / (__| _| |
| Shaun Nelson |
38:182ba91524e4 | 11 | |___/ |_/_/ \_\___|_|\_\_| \___/|_|_\\___|___| |
| Shaun Nelson |
38:182ba91524e4 | 12 | embedded.connectivity.solutions=============== |
| Shaun Nelson |
38:182ba91524e4 | 13 | |
| Shaun Nelson |
38:182ba91524e4 | 14 | Description: LoRa MAC common region implementation |
| Shaun Nelson |
38:182ba91524e4 | 15 | |
| Shaun Nelson |
38:182ba91524e4 | 16 | License: Revised BSD License, see LICENSE.TXT file include in the project |
| Shaun Nelson |
38:182ba91524e4 | 17 | |
| Shaun Nelson |
38:182ba91524e4 | 18 | Maintainer: Miguel Luis ( Semtech ), Gregory Cristian ( Semtech ) and Daniel Jaeckle ( STACKFORCE ) |
| Shaun Nelson |
38:182ba91524e4 | 19 | */ |
| Shaun Nelson |
38:182ba91524e4 | 20 | |
| Shaun Nelson |
38:182ba91524e4 | 21 | #include <stdbool.h> |
| Shaun Nelson |
38:182ba91524e4 | 22 | #include <string.h> |
| Shaun Nelson |
38:182ba91524e4 | 23 | #include <stdint.h> |
| Shaun Nelson |
38:182ba91524e4 | 24 | #include <math.h> |
| Shaun Nelson |
38:182ba91524e4 | 25 | |
| Shaun Nelson |
38:182ba91524e4 | 26 | #include "board.h" |
| Shaun Nelson |
38:182ba91524e4 | 27 | #include "radio.h" |
| Shaun Nelson |
38:182ba91524e4 | 28 | #include "timer.h" |
| Shaun Nelson |
38:182ba91524e4 | 29 | #include "utilities.h" |
| Shaun Nelson |
38:182ba91524e4 | 30 | #include "LoRaMac.h" |
| Shaun Nelson |
38:182ba91524e4 | 31 | #include "RegionCommon.h" |
| Shaun Nelson |
38:182ba91524e4 | 32 | |
| Shaun Nelson |
38:182ba91524e4 | 33 | |
| Shaun Nelson |
38:182ba91524e4 | 34 | |
| Shaun Nelson |
38:182ba91524e4 | 35 | #define BACKOFF_DC_1_HOUR 100 |
| Shaun Nelson |
38:182ba91524e4 | 36 | #define BACKOFF_DC_10_HOURS 1000 |
| Shaun Nelson |
38:182ba91524e4 | 37 | #define BACKOFF_DC_24_HOURS 10000 |
| Shaun Nelson |
38:182ba91524e4 | 38 | |
| Shaun Nelson |
38:182ba91524e4 | 39 | |
| Shaun Nelson |
38:182ba91524e4 | 40 | |
| Shaun Nelson |
38:182ba91524e4 | 41 | static uint8_t CountChannels( uint16_t mask, uint8_t nbBits ) |
| Shaun Nelson |
38:182ba91524e4 | 42 | { |
| Shaun Nelson |
38:182ba91524e4 | 43 | uint8_t nbActiveBits = 0; |
| Shaun Nelson |
38:182ba91524e4 | 44 | |
| Shaun Nelson |
38:182ba91524e4 | 45 | for( uint8_t j = 0; j < nbBits; j++ ) |
| Shaun Nelson |
38:182ba91524e4 | 46 | { |
| Shaun Nelson |
38:182ba91524e4 | 47 | if( ( mask & ( 1 << j ) ) == ( 1 << j ) ) |
| Shaun Nelson |
38:182ba91524e4 | 48 | { |
| Shaun Nelson |
38:182ba91524e4 | 49 | nbActiveBits++; |
| Shaun Nelson |
38:182ba91524e4 | 50 | } |
| Shaun Nelson |
38:182ba91524e4 | 51 | } |
| Shaun Nelson |
38:182ba91524e4 | 52 | return nbActiveBits; |
| Shaun Nelson |
38:182ba91524e4 | 53 | } |
| Shaun Nelson |
38:182ba91524e4 | 54 | |
| Shaun Nelson |
38:182ba91524e4 | 55 | |
| Shaun Nelson |
38:182ba91524e4 | 56 | |
| Shaun Nelson |
38:182ba91524e4 | 57 | uint16_t RegionCommonGetJoinDc( TimerTime_t elapsedTime ) |
| Shaun Nelson |
38:182ba91524e4 | 58 | { |
| Shaun Nelson |
38:182ba91524e4 | 59 | uint16_t dutyCycle = 0; |
| Shaun Nelson |
38:182ba91524e4 | 60 | |
| Shaun Nelson |
38:182ba91524e4 | 61 | if( elapsedTime < 3600000 ) |
| Shaun Nelson |
38:182ba91524e4 | 62 | { |
| Shaun Nelson |
38:182ba91524e4 | 63 | dutyCycle = BACKOFF_DC_1_HOUR; |
| Shaun Nelson |
38:182ba91524e4 | 64 | } |
| Shaun Nelson |
38:182ba91524e4 | 65 | else if( elapsedTime < ( 3600000 + 36000000 ) ) |
| Shaun Nelson |
38:182ba91524e4 | 66 | { |
| Shaun Nelson |
38:182ba91524e4 | 67 | dutyCycle = BACKOFF_DC_10_HOURS; |
| Shaun Nelson |
38:182ba91524e4 | 68 | } |
| Shaun Nelson |
38:182ba91524e4 | 69 | else |
| Shaun Nelson |
38:182ba91524e4 | 70 | { |
| Shaun Nelson |
38:182ba91524e4 | 71 | dutyCycle = BACKOFF_DC_24_HOURS; |
| Shaun Nelson |
38:182ba91524e4 | 72 | } |
| Shaun Nelson |
38:182ba91524e4 | 73 | return dutyCycle; |
| Shaun Nelson |
38:182ba91524e4 | 74 | } |
| Shaun Nelson |
38:182ba91524e4 | 75 | |
| Shaun Nelson |
38:182ba91524e4 | 76 | bool RegionCommonChanVerifyDr( uint8_t nbChannels, uint16_t* channelsMask, int8_t dr, int8_t minDr, int8_t maxDr, ChannelParams_t* channels ) |
| Shaun Nelson |
38:182ba91524e4 | 77 | { |
| Shaun Nelson |
38:182ba91524e4 | 78 | if( RegionCommonValueInRange( dr, minDr, maxDr ) == 0 ) |
| Shaun Nelson |
38:182ba91524e4 | 79 | { |
| Shaun Nelson |
38:182ba91524e4 | 80 | return false; |
| Shaun Nelson |
38:182ba91524e4 | 81 | } |
| Shaun Nelson |
38:182ba91524e4 | 82 | |
| Shaun Nelson |
38:182ba91524e4 | 83 | for( uint8_t i = 0, k = 0; i < nbChannels; i += 16, k++ ) |
| Shaun Nelson |
38:182ba91524e4 | 84 | { |
| Shaun Nelson |
38:182ba91524e4 | 85 | for( uint8_t j = 0; j < 16; j++ ) |
| Shaun Nelson |
38:182ba91524e4 | 86 | { |
| Shaun Nelson |
38:182ba91524e4 | 87 | if( ( ( channelsMask[k] & ( 1 << j ) ) != 0 ) ) |
| Shaun Nelson |
38:182ba91524e4 | 88 | {// Check datarate validity for enabled channels |
| Shaun Nelson |
38:182ba91524e4 | 89 | if( RegionCommonValueInRange( dr, ( channels[i + j].DrRange.Fields.Min & 0x0F ), |
| Shaun Nelson |
38:182ba91524e4 | 90 | ( channels[i + j].DrRange.Fields.Max & 0x0F ) ) == 1 ) |
| Shaun Nelson |
38:182ba91524e4 | 91 | { |
| Shaun Nelson |
38:182ba91524e4 | 92 | // At least 1 channel has been found we can return OK. |
| Shaun Nelson |
38:182ba91524e4 | 93 | return true; |
| Shaun Nelson |
38:182ba91524e4 | 94 | } |
| Shaun Nelson |
38:182ba91524e4 | 95 | } |
| Shaun Nelson |
38:182ba91524e4 | 96 | } |
| Shaun Nelson |
38:182ba91524e4 | 97 | } |
| Shaun Nelson |
38:182ba91524e4 | 98 | return false; |
| Shaun Nelson |
38:182ba91524e4 | 99 | } |
| Shaun Nelson |
38:182ba91524e4 | 100 | |
| Shaun Nelson |
38:182ba91524e4 | 101 | uint8_t RegionCommonValueInRange( int8_t value, int8_t min, int8_t max ) |
| Shaun Nelson |
38:182ba91524e4 | 102 | { |
| Shaun Nelson |
38:182ba91524e4 | 103 | if( ( value >= min ) && ( value <= max ) ) |
| Shaun Nelson |
38:182ba91524e4 | 104 | { |
| Shaun Nelson |
38:182ba91524e4 | 105 | return 1; |
| Shaun Nelson |
38:182ba91524e4 | 106 | } |
| Shaun Nelson |
38:182ba91524e4 | 107 | return 0; |
| Shaun Nelson |
38:182ba91524e4 | 108 | } |
| Shaun Nelson |
38:182ba91524e4 | 109 | |
| Shaun Nelson |
38:182ba91524e4 | 110 | bool RegionCommonChanDisable( uint16_t* channelsMask, uint8_t id, uint8_t maxChannels ) |
| Shaun Nelson |
38:182ba91524e4 | 111 | { |
| Shaun Nelson |
38:182ba91524e4 | 112 | uint8_t index = id / 16; |
| Shaun Nelson |
38:182ba91524e4 | 113 | |
| Shaun Nelson |
38:182ba91524e4 | 114 | if( ( index > ( maxChannels / 16 ) ) || ( id >= maxChannels ) ) |
| Shaun Nelson |
38:182ba91524e4 | 115 | { |
| Shaun Nelson |
38:182ba91524e4 | 116 | return false; |
| Shaun Nelson |
38:182ba91524e4 | 117 | } |
| Shaun Nelson |
38:182ba91524e4 | 118 | |
| Shaun Nelson |
38:182ba91524e4 | 119 | // Deactivate channel |
| Shaun Nelson |
38:182ba91524e4 | 120 | channelsMask[index] &= ~( 1 << ( id % 16 ) ); |
| Shaun Nelson |
38:182ba91524e4 | 121 | |
| Shaun Nelson |
38:182ba91524e4 | 122 | return true; |
| Shaun Nelson |
38:182ba91524e4 | 123 | } |
| Shaun Nelson |
38:182ba91524e4 | 124 | |
| Shaun Nelson |
38:182ba91524e4 | 125 | uint8_t RegionCommonCountChannels( uint16_t* channelsMask, uint8_t startIdx, uint8_t stopIdx ) |
| Shaun Nelson |
38:182ba91524e4 | 126 | { |
| Shaun Nelson |
38:182ba91524e4 | 127 | uint8_t nbChannels = 0; |
| Shaun Nelson |
38:182ba91524e4 | 128 | |
| Shaun Nelson |
38:182ba91524e4 | 129 | if( channelsMask == NULL ) |
| Shaun Nelson |
38:182ba91524e4 | 130 | { |
| Shaun Nelson |
38:182ba91524e4 | 131 | return 0; |
| Shaun Nelson |
38:182ba91524e4 | 132 | } |
| Shaun Nelson |
38:182ba91524e4 | 133 | |
| Shaun Nelson |
38:182ba91524e4 | 134 | for( uint8_t i = startIdx; i < stopIdx; i++ ) |
| Shaun Nelson |
38:182ba91524e4 | 135 | { |
| Shaun Nelson |
38:182ba91524e4 | 136 | nbChannels += CountChannels( channelsMask[i], 16 ); |
| Shaun Nelson |
38:182ba91524e4 | 137 | } |
| Shaun Nelson |
38:182ba91524e4 | 138 | |
| Shaun Nelson |
38:182ba91524e4 | 139 | return nbChannels; |
| Shaun Nelson |
38:182ba91524e4 | 140 | } |
| Shaun Nelson |
38:182ba91524e4 | 141 | |
| Shaun Nelson |
38:182ba91524e4 | 142 | void RegionCommonChanMaskCopy( uint16_t* channelsMaskDest, uint16_t* channelsMaskSrc, uint8_t len ) |
| Shaun Nelson |
38:182ba91524e4 | 143 | { |
| Shaun Nelson |
38:182ba91524e4 | 144 | if( ( channelsMaskDest != NULL ) && ( channelsMaskSrc != NULL ) ) |
| Shaun Nelson |
38:182ba91524e4 | 145 | { |
| Shaun Nelson |
38:182ba91524e4 | 146 | for( uint8_t i = 0; i < len; i++ ) |
| Shaun Nelson |
38:182ba91524e4 | 147 | { |
| Shaun Nelson |
38:182ba91524e4 | 148 | channelsMaskDest[i] = channelsMaskSrc[i]; |
| Shaun Nelson |
38:182ba91524e4 | 149 | } |
| Shaun Nelson |
38:182ba91524e4 | 150 | } |
| Shaun Nelson |
38:182ba91524e4 | 151 | } |
| Shaun Nelson |
38:182ba91524e4 | 152 | |
| Shaun Nelson |
38:182ba91524e4 | 153 | void RegionCommonSetBandTxDone( bool joined, Band_t* band, TimerTime_t lastTxDone ) |
| Shaun Nelson |
38:182ba91524e4 | 154 | { |
| Shaun Nelson |
38:182ba91524e4 | 155 | if( joined == true ) |
| Shaun Nelson |
38:182ba91524e4 | 156 | { |
| Shaun Nelson |
38:182ba91524e4 | 157 | band->LastTxDoneTime = lastTxDone; |
| Shaun Nelson |
38:182ba91524e4 | 158 | } |
| Shaun Nelson |
38:182ba91524e4 | 159 | else |
| Shaun Nelson |
38:182ba91524e4 | 160 | { |
| Shaun Nelson |
38:182ba91524e4 | 161 | band->LastTxDoneTime = lastTxDone; |
| Shaun Nelson |
38:182ba91524e4 | 162 | band->LastJoinTxDoneTime = lastTxDone; |
| Shaun Nelson |
38:182ba91524e4 | 163 | } |
| Shaun Nelson |
38:182ba91524e4 | 164 | } |
| Shaun Nelson |
38:182ba91524e4 | 165 | |
| Shaun Nelson |
38:182ba91524e4 | 166 | TimerTime_t RegionCommonUpdateBandTimeOff( bool joined, bool dutyCycle, Band_t* bands, uint8_t nbBands ) |
| Shaun Nelson |
38:182ba91524e4 | 167 | { |
| Shaun Nelson |
38:182ba91524e4 | 168 | TimerTime_t nextTxDelay = ( TimerTime_t )( -1 ); |
| Shaun Nelson |
38:182ba91524e4 | 169 | |
| Shaun Nelson |
38:182ba91524e4 | 170 | // Update bands Time OFF |
| Shaun Nelson |
38:182ba91524e4 | 171 | for( uint8_t i = 0; i < nbBands; i++ ) |
| Shaun Nelson |
38:182ba91524e4 | 172 | { |
| Shaun Nelson |
38:182ba91524e4 | 173 | if( joined == false ) |
| Shaun Nelson |
38:182ba91524e4 | 174 | { |
| Shaun Nelson |
38:182ba91524e4 | 175 | uint32_t txDoneTime = MAX( TimerGetElapsedTime( bands[i].LastJoinTxDoneTime ), |
| Shaun Nelson |
38:182ba91524e4 | 176 | ( dutyCycle == true ) ? TimerGetElapsedTime( bands[i].LastTxDoneTime ) : 0 ); |
| Shaun Nelson |
38:182ba91524e4 | 177 | |
| Shaun Nelson |
38:182ba91524e4 | 178 | if( bands[i].TimeOff <= txDoneTime ) |
| Shaun Nelson |
38:182ba91524e4 | 179 | { |
| Shaun Nelson |
38:182ba91524e4 | 180 | bands[i].TimeOff = 0; |
| Shaun Nelson |
38:182ba91524e4 | 181 | } |
| Shaun Nelson |
38:182ba91524e4 | 182 | if( bands[i].TimeOff != 0 ) |
| Shaun Nelson |
38:182ba91524e4 | 183 | { |
| Shaun Nelson |
38:182ba91524e4 | 184 | nextTxDelay = MIN( bands[i].TimeOff - txDoneTime, nextTxDelay ); |
| Shaun Nelson |
38:182ba91524e4 | 185 | } |
| Shaun Nelson |
38:182ba91524e4 | 186 | } |
| Shaun Nelson |
38:182ba91524e4 | 187 | else |
| Shaun Nelson |
38:182ba91524e4 | 188 | { |
| Shaun Nelson |
38:182ba91524e4 | 189 | if( dutyCycle == true ) |
| Shaun Nelson |
38:182ba91524e4 | 190 | { |
| Shaun Nelson |
38:182ba91524e4 | 191 | if( bands[i].TimeOff <= TimerGetElapsedTime( bands[i].LastTxDoneTime ) ) |
| Shaun Nelson |
38:182ba91524e4 | 192 | { |
| Shaun Nelson |
38:182ba91524e4 | 193 | bands[i].TimeOff = 0; |
| Shaun Nelson |
38:182ba91524e4 | 194 | } |
| Shaun Nelson |
38:182ba91524e4 | 195 | if( bands[i].TimeOff != 0 ) |
| Shaun Nelson |
38:182ba91524e4 | 196 | { |
| Shaun Nelson |
38:182ba91524e4 | 197 | nextTxDelay = MIN( bands[i].TimeOff - TimerGetElapsedTime( bands[i].LastTxDoneTime ), |
| Shaun Nelson |
38:182ba91524e4 | 198 | nextTxDelay ); |
| Shaun Nelson |
38:182ba91524e4 | 199 | } |
| Shaun Nelson |
38:182ba91524e4 | 200 | } |
| Shaun Nelson |
38:182ba91524e4 | 201 | else |
| Shaun Nelson |
38:182ba91524e4 | 202 | { |
| Shaun Nelson |
38:182ba91524e4 | 203 | nextTxDelay = 0; |
| Shaun Nelson |
38:182ba91524e4 | 204 | bands[i].TimeOff = 0; |
| Shaun Nelson |
38:182ba91524e4 | 205 | } |
| Shaun Nelson |
38:182ba91524e4 | 206 | } |
| Shaun Nelson |
38:182ba91524e4 | 207 | } |
| Shaun Nelson |
38:182ba91524e4 | 208 | return nextTxDelay; |
| Shaun Nelson |
38:182ba91524e4 | 209 | } |
| Shaun Nelson |
38:182ba91524e4 | 210 | |
| Shaun Nelson |
38:182ba91524e4 | 211 | uint8_t RegionCommonParseLinkAdrReq( uint8_t* payload, RegionCommonLinkAdrParams_t* linkAdrParams ) |
| Shaun Nelson |
38:182ba91524e4 | 212 | { |
| Shaun Nelson |
38:182ba91524e4 | 213 | uint8_t retIndex = 0; |
| Shaun Nelson |
38:182ba91524e4 | 214 | |
| Shaun Nelson |
38:182ba91524e4 | 215 | if( payload[0] == SRV_MAC_LINK_ADR_REQ ) |
| Shaun Nelson |
38:182ba91524e4 | 216 | { |
| Shaun Nelson |
38:182ba91524e4 | 217 | // Parse datarate and tx power |
| Shaun Nelson |
38:182ba91524e4 | 218 | linkAdrParams->Datarate = payload[1]; |
| Shaun Nelson |
38:182ba91524e4 | 219 | linkAdrParams->TxPower = linkAdrParams->Datarate & 0x0F; |
| Shaun Nelson |
38:182ba91524e4 | 220 | linkAdrParams->Datarate = ( linkAdrParams->Datarate >> 4 ) & 0x0F; |
| Shaun Nelson |
38:182ba91524e4 | 221 | // Parse ChMask |
| Shaun Nelson |
38:182ba91524e4 | 222 | linkAdrParams->ChMask = ( uint16_t )payload[2]; |
| Shaun Nelson |
38:182ba91524e4 | 223 | linkAdrParams->ChMask |= ( uint16_t )payload[3] << 8; |
| Shaun Nelson |
38:182ba91524e4 | 224 | // Parse ChMaskCtrl and nbRep |
| Shaun Nelson |
38:182ba91524e4 | 225 | linkAdrParams->NbRep = payload[4]; |
| Shaun Nelson |
38:182ba91524e4 | 226 | linkAdrParams->ChMaskCtrl = ( linkAdrParams->NbRep >> 4 ) & 0x07; |
| Shaun Nelson |
38:182ba91524e4 | 227 | linkAdrParams->NbRep &= 0x0F; |
| Shaun Nelson |
38:182ba91524e4 | 228 | |
| Shaun Nelson |
38:182ba91524e4 | 229 | // LinkAdrReq has 4 bytes length + 1 byte CMD |
| Shaun Nelson |
38:182ba91524e4 | 230 | retIndex = 5; |
| Shaun Nelson |
38:182ba91524e4 | 231 | } |
| Shaun Nelson |
38:182ba91524e4 | 232 | return retIndex; |
| Shaun Nelson |
38:182ba91524e4 | 233 | } |
| Shaun Nelson |
38:182ba91524e4 | 234 | |
| Shaun Nelson |
38:182ba91524e4 | 235 | uint8_t RegionCommonLinkAdrReqVerifyParams( RegionCommonLinkAdrReqVerifyParams_t* verifyParams, int8_t* dr, int8_t* txPow, uint8_t* nbRep ) |
| Shaun Nelson |
38:182ba91524e4 | 236 | { |
| Shaun Nelson |
38:182ba91524e4 | 237 | uint8_t status = verifyParams->Status; |
| Shaun Nelson |
38:182ba91524e4 | 238 | int8_t datarate = verifyParams->Datarate; |
| Shaun Nelson |
38:182ba91524e4 | 239 | int8_t txPower = verifyParams->TxPower; |
| Shaun Nelson |
38:182ba91524e4 | 240 | int8_t nbRepetitions = verifyParams->NbRep; |
| Shaun Nelson |
38:182ba91524e4 | 241 | |
| Shaun Nelson |
38:182ba91524e4 | 242 | // Handle the case when ADR is off. |
| Shaun Nelson |
38:182ba91524e4 | 243 | if( verifyParams->AdrEnabled == false ) |
| Shaun Nelson |
38:182ba91524e4 | 244 | { |
| Shaun Nelson |
38:182ba91524e4 | 245 | // When ADR is off, we are allowed to change the channels mask and the NbRep, |
| Shaun Nelson |
38:182ba91524e4 | 246 | // if the datarate and the TX power of the LinkAdrReq are set to 0x0F. |
| Shaun Nelson |
38:182ba91524e4 | 247 | if( ( verifyParams->Datarate != 0x0F ) || ( verifyParams->TxPower != 0x0F ) ) |
| Shaun Nelson |
38:182ba91524e4 | 248 | { |
| Shaun Nelson |
38:182ba91524e4 | 249 | status = 0; |
| Shaun Nelson |
38:182ba91524e4 | 250 | nbRepetitions = verifyParams->CurrentNbRep; |
| Shaun Nelson |
38:182ba91524e4 | 251 | } |
| Shaun Nelson |
38:182ba91524e4 | 252 | // Get the current datarate and tx power |
| Shaun Nelson |
38:182ba91524e4 | 253 | datarate = verifyParams->CurrentDatarate; |
| Shaun Nelson |
38:182ba91524e4 | 254 | txPower = verifyParams->CurrentTxPower; |
| Shaun Nelson |
38:182ba91524e4 | 255 | } |
| Shaun Nelson |
38:182ba91524e4 | 256 | |
| Shaun Nelson |
38:182ba91524e4 | 257 | if( status != 0 ) |
| Shaun Nelson |
38:182ba91524e4 | 258 | { |
| Shaun Nelson |
38:182ba91524e4 | 259 | // Verify datarate. The variable phyParam. Value contains the minimum allowed datarate. |
| Shaun Nelson |
38:182ba91524e4 | 260 | if( RegionCommonChanVerifyDr( verifyParams->NbChannels, verifyParams->ChannelsMask, datarate, |
| Shaun Nelson |
38:182ba91524e4 | 261 | verifyParams->MinDatarate, verifyParams->MaxDatarate, verifyParams->Channels ) == false ) |
| Shaun Nelson |
38:182ba91524e4 | 262 | { |
| Shaun Nelson |
38:182ba91524e4 | 263 | status &= 0xFD; // Datarate KO |
| Shaun Nelson |
38:182ba91524e4 | 264 | } |
| Shaun Nelson |
38:182ba91524e4 | 265 | |
| Shaun Nelson |
38:182ba91524e4 | 266 | // Verify tx power |
| Shaun Nelson |
38:182ba91524e4 | 267 | if( RegionCommonValueInRange( txPower, verifyParams->MaxTxPower, verifyParams->MinTxPower ) == 0 ) |
| Shaun Nelson |
38:182ba91524e4 | 268 | { |
| Shaun Nelson |
38:182ba91524e4 | 269 | // Verify if the maximum TX power is exceeded |
| Shaun Nelson |
38:182ba91524e4 | 270 | if( verifyParams->MaxTxPower > txPower ) |
| Shaun Nelson |
38:182ba91524e4 | 271 | { // Apply maximum TX power. Accept TX power. |
| Shaun Nelson |
38:182ba91524e4 | 272 | txPower = verifyParams->MaxTxPower; |
| Shaun Nelson |
38:182ba91524e4 | 273 | } |
| Shaun Nelson |
38:182ba91524e4 | 274 | else |
| Shaun Nelson |
38:182ba91524e4 | 275 | { |
| Shaun Nelson |
38:182ba91524e4 | 276 | status &= 0xFB; // TxPower KO |
| Shaun Nelson |
38:182ba91524e4 | 277 | } |
| Shaun Nelson |
38:182ba91524e4 | 278 | } |
| Shaun Nelson |
38:182ba91524e4 | 279 | } |
| Shaun Nelson |
38:182ba91524e4 | 280 | |
| Shaun Nelson |
38:182ba91524e4 | 281 | // If the status is ok, verify the NbRep |
| Shaun Nelson |
38:182ba91524e4 | 282 | if( status == 0x07 ) |
| Shaun Nelson |
38:182ba91524e4 | 283 | { |
| Shaun Nelson |
38:182ba91524e4 | 284 | if( nbRepetitions == 0 ) |
| Shaun Nelson |
38:182ba91524e4 | 285 | { // Keep the current one |
| Shaun Nelson |
38:182ba91524e4 | 286 | nbRepetitions = verifyParams->CurrentNbRep; |
| Shaun Nelson |
38:182ba91524e4 | 287 | } |
| Shaun Nelson |
38:182ba91524e4 | 288 | } |
| Shaun Nelson |
38:182ba91524e4 | 289 | |
| Shaun Nelson |
38:182ba91524e4 | 290 | // Apply changes |
| Shaun Nelson |
38:182ba91524e4 | 291 | *dr = datarate; |
| Shaun Nelson |
38:182ba91524e4 | 292 | *txPow = txPower; |
| Shaun Nelson |
38:182ba91524e4 | 293 | *nbRep = nbRepetitions; |
| Shaun Nelson |
38:182ba91524e4 | 294 | |
| Shaun Nelson |
38:182ba91524e4 | 295 | return status; |
| Shaun Nelson |
38:182ba91524e4 | 296 | } |
| Shaun Nelson |
38:182ba91524e4 | 297 | |
| Shaun Nelson |
38:182ba91524e4 | 298 | double RegionCommonComputeSymbolTimeLoRa( uint8_t phyDr, uint32_t bandwidth ) |
| Shaun Nelson |
38:182ba91524e4 | 299 | { |
| Shaun Nelson |
38:182ba91524e4 | 300 | return ( ( double )( 1 << phyDr ) / ( double )bandwidth ) * 1000; |
| Shaun Nelson |
38:182ba91524e4 | 301 | } |
| Shaun Nelson |
38:182ba91524e4 | 302 | |
| Shaun Nelson |
38:182ba91524e4 | 303 | double RegionCommonComputeSymbolTimeFsk( uint8_t phyDr ) |
| Shaun Nelson |
38:182ba91524e4 | 304 | { |
| Shaun Nelson |
38:182ba91524e4 | 305 | return ( 8.0 / ( double )phyDr ); // 1 symbol equals 1 byte |
| Shaun Nelson |
38:182ba91524e4 | 306 | } |
| Shaun Nelson |
38:182ba91524e4 | 307 | |
| Shaun Nelson |
38:182ba91524e4 | 308 | void RegionCommonComputeRxWindowParameters( double tSymbol, uint8_t minRxSymbols, uint32_t rxError, uint32_t wakeUpTime, uint32_t* windowTimeout, int32_t* windowOffset ) |
| Shaun Nelson |
38:182ba91524e4 | 309 | { |
| Shaun Nelson |
38:182ba91524e4 | 310 | *windowTimeout = MAX( ( uint32_t )ceil( ( ( 2 * minRxSymbols - 8 ) * tSymbol + 2 * rxError ) / tSymbol ), minRxSymbols ); // Computed number of symbols |
| Shaun Nelson |
38:182ba91524e4 | 311 | *windowOffset = ( int32_t )ceil( ( 4.0 * tSymbol ) - ( ( *windowTimeout * tSymbol ) / 2.0 ) - wakeUpTime ); |
| Shaun Nelson |
38:182ba91524e4 | 312 | } |
| Shaun Nelson |
38:182ba91524e4 | 313 | |
| Shaun Nelson |
38:182ba91524e4 | 314 | int8_t RegionCommonComputeTxPower( int8_t txPowerIndex, float maxEirp, float antennaGain ) |
| Shaun Nelson |
38:182ba91524e4 | 315 | { |
| Shaun Nelson |
38:182ba91524e4 | 316 | int8_t phyTxPower = 0; |
| Shaun Nelson |
38:182ba91524e4 | 317 | |
| Shaun Nelson |
38:182ba91524e4 | 318 | phyTxPower = ( int8_t )floor( ( maxEirp - ( txPowerIndex * 2U ) ) - antennaGain ); |
| Shaun Nelson |
38:182ba91524e4 | 319 | |
| Shaun Nelson |
38:182ba91524e4 | 320 | return phyTxPower; |
| Shaun Nelson |
38:182ba91524e4 | 321 | } |
| Shaun Nelson |
38:182ba91524e4 | 322 | |
| Shaun Nelson |
38:182ba91524e4 | 323 | void RegionCommonCalcBackOff( RegionCommonCalcBackOffParams_t* calcBackOffParams ) |
| Shaun Nelson |
38:182ba91524e4 | 324 | { |
| Shaun Nelson |
38:182ba91524e4 | 325 | uint8_t bandIdx = calcBackOffParams->Channels[calcBackOffParams->Channel].Band; |
| Shaun Nelson |
38:182ba91524e4 | 326 | uint16_t dutyCycle = calcBackOffParams->Bands[bandIdx].DCycle; |
| Shaun Nelson |
38:182ba91524e4 | 327 | uint16_t joinDutyCycle = 0; |
| Shaun Nelson |
38:182ba91524e4 | 328 | |
| Shaun Nelson |
38:182ba91524e4 | 329 | // Reset time-off to initial value. |
| Shaun Nelson |
38:182ba91524e4 | 330 | calcBackOffParams->Bands[bandIdx].TimeOff = 0; |
| Shaun Nelson |
38:182ba91524e4 | 331 | |
| Shaun Nelson |
38:182ba91524e4 | 332 | if( calcBackOffParams->Joined == false ) |
| Shaun Nelson |
38:182ba91524e4 | 333 | { |
| Shaun Nelson |
38:182ba91524e4 | 334 | // Get the join duty cycle |
| Shaun Nelson |
38:182ba91524e4 | 335 | joinDutyCycle = RegionCommonGetJoinDc( calcBackOffParams->ElapsedTime ); |
| Shaun Nelson |
38:182ba91524e4 | 336 | // Apply the most restricting duty cycle |
| Shaun Nelson |
38:182ba91524e4 | 337 | dutyCycle = MAX( dutyCycle, joinDutyCycle ); |
| Shaun Nelson |
38:182ba91524e4 | 338 | // Reset the timeoff if the last frame was not a join request and when the duty cycle is not enabled |
| Shaun Nelson |
38:182ba91524e4 | 339 | if( ( calcBackOffParams->DutyCycleEnabled == false ) && ( calcBackOffParams->LastTxIsJoinRequest == false ) ) |
| Shaun Nelson |
38:182ba91524e4 | 340 | { |
| Shaun Nelson |
38:182ba91524e4 | 341 | // This is the case when the duty cycle is off and the last uplink frame was not a join. |
| Shaun Nelson |
38:182ba91524e4 | 342 | // This could happen in case of a rejoin, e.g. in compliance test mode. |
| Shaun Nelson |
38:182ba91524e4 | 343 | // In this special case we have to set the time off to 0, since the join duty cycle shall only |
| Shaun Nelson |
38:182ba91524e4 | 344 | // be applied after the first join request. |
| Shaun Nelson |
38:182ba91524e4 | 345 | calcBackOffParams->Bands[bandIdx].TimeOff = 0; |
| Shaun Nelson |
38:182ba91524e4 | 346 | } |
| Shaun Nelson |
38:182ba91524e4 | 347 | else |
| Shaun Nelson |
38:182ba91524e4 | 348 | { |
| Shaun Nelson |
38:182ba91524e4 | 349 | // Apply band time-off. |
| Shaun Nelson |
38:182ba91524e4 | 350 | calcBackOffParams->Bands[bandIdx].TimeOff = calcBackOffParams->TxTimeOnAir * dutyCycle - calcBackOffParams->TxTimeOnAir; |
| Shaun Nelson |
38:182ba91524e4 | 351 | } |
| Shaun Nelson |
38:182ba91524e4 | 352 | } |
| Shaun Nelson |
38:182ba91524e4 | 353 | else |
| Shaun Nelson |
38:182ba91524e4 | 354 | { |
| Shaun Nelson |
38:182ba91524e4 | 355 | if( calcBackOffParams->DutyCycleEnabled == true ) |
| Shaun Nelson |
38:182ba91524e4 | 356 | { |
| Shaun Nelson |
38:182ba91524e4 | 357 | calcBackOffParams->Bands[bandIdx].TimeOff = calcBackOffParams->TxTimeOnAir * dutyCycle - calcBackOffParams->TxTimeOnAir; |
| Shaun Nelson |
38:182ba91524e4 | 358 | } |
| Shaun Nelson |
38:182ba91524e4 | 359 | else |
| Shaun Nelson |
38:182ba91524e4 | 360 | { |
| Shaun Nelson |
38:182ba91524e4 | 361 | calcBackOffParams->Bands[bandIdx].TimeOff = 0; |
| Shaun Nelson |
38:182ba91524e4 | 362 | } |
| Shaun Nelson |
38:182ba91524e4 | 363 | } |
| Shaun Nelson |
38:182ba91524e4 | 364 | } |
| Shaun Nelson |
38:182ba91524e4 | 365 | |
| Shaun Nelson |
38:182ba91524e4 | 366 | |
| Shaun Nelson |
38:182ba91524e4 | 367 | void RegionCommonRxBeaconSetup( RegionCommonRxBeaconSetupParams_t* rxBeaconSetupParams, bool *beaconChannelSet ) |
| Shaun Nelson |
38:182ba91524e4 | 368 | { |
| Shaun Nelson |
38:182ba91524e4 | 369 | bool rxContinuous = true; |
| Shaun Nelson |
38:182ba91524e4 | 370 | uint32_t frequency = rxBeaconSetupParams->CustomFrequency; |
| Shaun Nelson |
38:182ba91524e4 | 371 | uint8_t datarate; |
| Shaun Nelson |
38:182ba91524e4 | 372 | |
| Shaun Nelson |
38:182ba91524e4 | 373 | // Set the radio into sleep mode |
| Shaun Nelson |
38:182ba91524e4 | 374 | Radio.Sleep( ); |
| Shaun Nelson |
38:182ba91524e4 | 375 | |
| Shaun Nelson |
38:182ba91524e4 | 376 | // If no custom frequency is enabled, use the default floor plan frequency |
| Shaun Nelson |
38:182ba91524e4 | 377 | if( rxBeaconSetupParams->CustomFrequencyEnabled == false ) |
| Shaun Nelson |
38:182ba91524e4 | 378 | { |
| Shaun Nelson |
38:182ba91524e4 | 379 | // Restore floor plan |
| Shaun Nelson |
38:182ba91524e4 | 380 | frequency = rxBeaconSetupParams->ChannelPlanFrequency; |
| Shaun Nelson |
38:182ba91524e4 | 381 | } |
| Shaun Nelson |
38:182ba91524e4 | 382 | |
| Shaun Nelson |
38:182ba91524e4 | 383 | // Set the frequency which was provided by BeaconTimingAns MAC command |
| Shaun Nelson |
38:182ba91524e4 | 384 | if( rxBeaconSetupParams->BeaconChannelSet == true ) |
| Shaun Nelson |
38:182ba91524e4 | 385 | { |
| Shaun Nelson |
38:182ba91524e4 | 386 | // Take the frequency of the next beacon |
| Shaun Nelson |
38:182ba91524e4 | 387 | *beaconChannelSet = false; |
| Shaun Nelson |
38:182ba91524e4 | 388 | frequency = rxBeaconSetupParams->BeaconTimingAnsFrequency; |
| Shaun Nelson |
38:182ba91524e4 | 389 | } |
| Shaun Nelson |
38:182ba91524e4 | 390 | |
| Shaun Nelson |
38:182ba91524e4 | 391 | // Setup frequency and payload length |
| Shaun Nelson |
38:182ba91524e4 | 392 | Radio.SetChannel( frequency ); |
| Shaun Nelson |
38:182ba91524e4 | 393 | Radio.SetMaxPayloadLength( MODEM_LORA, rxBeaconSetupParams->BeaconSize ); |
| Shaun Nelson |
38:182ba91524e4 | 394 | |
| Shaun Nelson |
38:182ba91524e4 | 395 | // Check the RX continuous mode |
| Shaun Nelson |
38:182ba91524e4 | 396 | if( rxBeaconSetupParams->RxTime != 0 ) |
| Shaun Nelson |
38:182ba91524e4 | 397 | { |
| Shaun Nelson |
38:182ba91524e4 | 398 | rxContinuous = false; |
| Shaun Nelson |
38:182ba91524e4 | 399 | } |
| Shaun Nelson |
38:182ba91524e4 | 400 | |
| Shaun Nelson |
38:182ba91524e4 | 401 | // Get region specific datarate |
| Shaun Nelson |
38:182ba91524e4 | 402 | datarate = rxBeaconSetupParams->Datarates[rxBeaconSetupParams->BeaconDatarate]; |
| Shaun Nelson |
38:182ba91524e4 | 403 | |
| Shaun Nelson |
38:182ba91524e4 | 404 | // Setup radio |
| Shaun Nelson |
38:182ba91524e4 | 405 | Radio.SetRxConfig( MODEM_LORA, rxBeaconSetupParams->BeaconChannelBW, datarate, |
| Shaun Nelson |
38:182ba91524e4 | 406 | 1, 0, 10, rxBeaconSetupParams->SymbolTimeout, true, rxBeaconSetupParams->BeaconSize, false, 0, 0, false, rxContinuous ); |
| Shaun Nelson |
38:182ba91524e4 | 407 | |
| Shaun Nelson |
38:182ba91524e4 | 408 | Radio.Rx( rxBeaconSetupParams->RxTime ); |
| Shaun Nelson |
38:182ba91524e4 | 409 | } |

