1 /*!
2  * \file      RegionCN470B20.c
3  *
4  * \brief
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    Daniel Jaeckle ( STACKFORCE )
28  *
29  * \defgroup  REGIONCN470
30  */
31 #include "RegionCN470.h"
32 #include "RegionBaseUS.h"
33 #include "RegionCN470B20.h"
34 #include "RegionCN470A20.h"
35 
RegionCN470B20GetDownlinkFrequency(uint8_t channel,uint8_t joinChannelIndex,bool isPingSlot)36 uint32_t RegionCN470B20GetDownlinkFrequency( uint8_t channel, uint8_t joinChannelIndex, bool isPingSlot )
37 {
38     if( isPingSlot == true)
39     {
40         return RegionCN470B20GetRx1Frequency( channel );
41     }
42     else
43     {
44         if( joinChannelIndex == 8 )
45         {
46             return RegionCN470B20GetRx1Frequency( 23 );
47         }
48         else
49         {
50             return RegionCN470B20GetRx1Frequency( 55 );
51         }
52     }
53 }
54 
RegionCN470B20GetBeaconChannelOffset(uint8_t joinChannelIndex)55 uint8_t RegionCN470B20GetBeaconChannelOffset( uint8_t joinChannelIndex )
56 {
57     return ( joinChannelIndex - 8 ) * 32;
58 }
59 
RegionCN470B20LinkAdrChMaskUpdate(uint16_t * channelsMask,uint8_t chMaskCntl,uint16_t chanMask,ChannelParams_t * channels)60 uint8_t RegionCN470B20LinkAdrChMaskUpdate( uint16_t* channelsMask, uint8_t chMaskCntl,
61                                               uint16_t chanMask, ChannelParams_t* channels )
62 {
63     // It follows the same implementation as type A
64     return RegionCN470A20LinkAdrChMaskUpdate( channelsMask, chMaskCntl,
65                                                  chanMask, channels );
66 }
67 
RegionCN470B20VerifyRfFreq(uint32_t freq)68 bool RegionCN470B20VerifyRfFreq( uint32_t freq )
69 {
70     bool group1Status = false;
71     bool group2Status = false;
72 
73     // Downstream group 1
74     group1Status = RegionBaseUSVerifyFrequencyGroup( freq, CN470_B20_FIRST_RX1_CHANNEL,
75                                                      CN470_B20_LAST_RX1_CHANNEL,
76                                                      CN470_B20_STEPWIDTH_RX1_CHANNEL );
77     // Downstream group 2
78     group2Status = RegionBaseUSVerifyFrequencyGroup( freq, CN470_B20_FIRST_RX2_CHANNEL,
79                                                      CN470_B20_LAST_RX2_CHANNEL,
80                                                      CN470_B20_STEPWIDTH_RX2_CHANNEL );
81 
82     // The frequency must be available in one of the groups
83     if( ( group1Status == false ) && ( group2Status == false ) )
84     {
85         return false;
86     }
87     return true;
88 }
89 
RegionCN470B20InitializeChannels(ChannelParams_t * channels)90 void RegionCN470B20InitializeChannels( ChannelParams_t* channels )
91 {
92     // Upstream group 1
93     for( uint8_t i = 0; i < 32; i++ )
94     {
95         channels[i].Frequency = CN470_B20_FIRST_TX1_CHANNEL + i * CN470_B20_STEPWIDTH_TX1_CHANNEL;
96         channels[i].DrRange.Value = ( CN470_TX_MAX_DATARATE << 4 ) | CN470_TX_MIN_DATARATE;
97         channels[i].Band = 0;
98     }
99     // Upstream group 2
100     for( uint8_t i = 32; i < 64; i++ )
101     {
102         channels[i].Frequency = CN470_B20_FIRST_TX2_CHANNEL + ( i - 32 ) * CN470_B20_STEPWIDTH_TX2_CHANNEL;
103         channels[i].DrRange.Value = ( CN470_TX_MAX_DATARATE << 4 ) | CN470_TX_MIN_DATARATE;
104         channels[i].Band = 0;
105     }
106 }
107 
RegionCN470B20InitializeChannelsMask(uint16_t * channelsDefaultMask)108 void RegionCN470B20InitializeChannelsMask( uint16_t* channelsDefaultMask )
109 {
110     RegionCN470A20InitializeChannelsMask( channelsDefaultMask );
111 }
112 
RegionCN470B20GetRx1Frequency(uint8_t channel)113 uint32_t RegionCN470B20GetRx1Frequency( uint8_t channel )
114 {
115     // Base frequency for downstream group 1
116     uint32_t baseFrequency = CN470_B20_FIRST_RX1_CHANNEL;
117     uint8_t offset = 0;
118 
119     if( channel >= 32 )
120     {
121         // Base frequency for downstream group 2
122         baseFrequency = CN470_B20_FIRST_RX2_CHANNEL;
123         offset = 32;
124     }
125     return ( baseFrequency + ( ( channel - offset ) * CN470_B20_STEPWIDTH_RX1_CHANNEL ) );
126 }
127 
RegionCN470B20GetRx2Frequency(uint8_t joinChannelIndex,bool isOtaaDevice)128 uint32_t RegionCN470B20GetRx2Frequency( uint8_t joinChannelIndex, bool isOtaaDevice )
129 {
130     uint32_t otaaFrequencies[] = CN470_B20_RX_WND_2_FREQ_OTAA;
131 
132     if( isOtaaDevice == true )
133     {
134         return otaaFrequencies[joinChannelIndex - 8];
135     }
136     // ABP device
137     return CN470_B20_RX_WND_2_FREQ_ABP;
138 }
139 
140