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, &params );
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