1 /*!
2 * \file LoRaMacAdr.c
3 *
4 * \brief LoRa MAC ADR implementation
5 *
6 * \copyright Revised BSD License, see section \ref LICENSE.
7 *
8 * \code
9 * ______ _
10 * / _____) _ | |
11 * ( (____ _____ ____ _| |_ _____ ____| |__
12 * \____ \| ___ | (_ _) ___ |/ ___) _ \
13 * _____) ) ____| | | || |_| ____( (___| | | |
14 * (______/|_____)_|_|_| \__)_____)\____)_| |_|
15 * (C)2013-2017 Semtech
16 *
17 * ___ _____ _ ___ _ _____ ___ ___ ___ ___
18 * / __|_ _/_\ / __| |/ / __/ _ \| _ \/ __| __|
19 * \__ \ | |/ _ \ (__| ' <| _| (_) | / (__| _|
20 * |___/ |_/_/ \_\___|_|\_\_| \___/|_|_\\___|___|
21 * embedded.connectivity.solutions===============
22 *
23 * \endcode
24 *
25 * \author Miguel Luis ( Semtech )
26 *
27 * \author Gregory Cristian ( Semtech )
28 *
29 * \author Daniel Jaeckle ( STACKFORCE )
30 *
31 * \author Johannes Bruder ( STACKFORCE )
32 */
33
34 #include "region/Region.h"
35 #include "LoRaMacAdr.h"
36
LoRaMacAdrCalcNext(CalcNextAdrParams_t * adrNext,int8_t * drOut,int8_t * txPowOut,uint8_t * nbTransOut,uint32_t * adrAckCounter)37 bool LoRaMacAdrCalcNext( CalcNextAdrParams_t* adrNext, int8_t* drOut, int8_t* txPowOut,
38 uint8_t* nbTransOut, uint32_t* adrAckCounter )
39 {
40 bool adrAckReq = false;
41 int8_t datarate = adrNext->Datarate;
42 int8_t txPower = adrNext->TxPower;
43 uint8_t nbTrans = adrNext->NbTrans;
44 int8_t minTxDatarate;
45 GetPhyParams_t getPhy;
46 PhyParam_t phyParam;
47
48 // Report back the adr ack counter
49 *adrAckCounter = adrNext->AdrAckCounter;
50
51 if( adrNext->AdrEnabled == true )
52 {
53 // Query minimum TX Datarate
54 getPhy.Attribute = PHY_MIN_TX_DR;
55 getPhy.UplinkDwellTime = adrNext->UplinkDwellTime;
56 phyParam = RegionGetPhyParam( adrNext->Region, &getPhy );
57 minTxDatarate = phyParam.Value;
58 datarate = MAX( datarate, minTxDatarate );
59
60 // Verify if ADR ack req bit needs to be set.
61 if( adrNext->AdrAckCounter >= adrNext->AdrAckLimit )
62 {
63 adrAckReq = true;
64 }
65
66 // Verify, if we need to set the TX power to default
67 if( adrNext->AdrAckCounter >= ( adrNext->AdrAckLimit + adrNext->AdrAckDelay ) )
68 {
69 // Set TX Power to default
70 getPhy.Attribute = PHY_DEF_TX_POWER;
71 phyParam = RegionGetPhyParam( adrNext->Region, &getPhy );
72 txPower = phyParam.Value;
73 }
74
75 // Verify, if we need to decrease the data rate
76 if( adrNext->AdrAckCounter >= ( uint32_t )( adrNext->AdrAckLimit + ( adrNext->AdrAckDelay << 1 ) ) )
77 {
78 // Perform actions with every adrNext->AdrAckDelay only
79 if( ( ( adrNext->AdrAckCounter - adrNext->AdrAckLimit ) % adrNext->AdrAckDelay ) == 0 )
80 {
81 if( datarate == minTxDatarate )
82 {
83 // Restore the channel mask
84 if( adrNext->UpdateChanMask == true )
85 {
86 InitDefaultsParams_t params;
87 params.Type = INIT_TYPE_ACTIVATE_DEFAULT_CHANNELS;
88 RegionInitDefaults( adrNext->Region, ¶ms );
89 }
90
91 // Restore NbTrans
92 nbTrans = 1;
93 }
94
95 // Decrease the datarate
96 getPhy.Attribute = PHY_NEXT_LOWER_TX_DR;
97 getPhy.Datarate = datarate;
98 getPhy.UplinkDwellTime = adrNext->UplinkDwellTime;
99 phyParam = RegionGetPhyParam( adrNext->Region, &getPhy );
100 datarate = phyParam.Value;
101 }
102 }
103 }
104
105 *drOut = datarate;
106 *txPowOut = txPower;
107 *nbTransOut = nbTrans;
108 return adrAckReq;
109 }
110