Senet / LoRaWAN-lib

Fork of LoRaWAN-lib by canuck lehead

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?

UserRevisionLine numberNew 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 }