1 /*!
2 * \file RegionCN470A20.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 "RegionCN470A20.h"
34
RegionCN470A20GetDownlinkFrequency(uint8_t channel,uint8_t joinChannelIndex,bool isPingSlot)35 uint32_t RegionCN470A20GetDownlinkFrequency( uint8_t channel, uint8_t joinChannelIndex, bool isPingSlot )
36 {
37 return RegionCN470A20GetRx1Frequency( channel );
38 }
39
RegionCN470A20GetBeaconChannelOffset(uint8_t joinChannelIndex)40 uint8_t RegionCN470A20GetBeaconChannelOffset( uint8_t joinChannelIndex )
41 {
42 return ( joinChannelIndex * 8 );
43 }
44
RegionCN470A20LinkAdrChMaskUpdate(uint16_t * channelsMask,uint8_t chMaskCntl,uint16_t chanMask,ChannelParams_t * channels)45 uint8_t RegionCN470A20LinkAdrChMaskUpdate( uint16_t* channelsMask, uint8_t chMaskCntl,
46 uint16_t chanMask, ChannelParams_t* channels )
47 {
48 uint8_t status = 0x07;
49
50 if( ( chMaskCntl == 4 ) || ( chMaskCntl == 5 ) )
51 {
52 // RFU
53 status &= 0xFE; // Channel mask KO
54 }
55 else if( chMaskCntl == 6 )
56 {
57 // Enable all channels
58 channelsMask[0] = 0xFFFF;
59 channelsMask[1] = 0xFFFF;
60 channelsMask[2] = 0xFFFF;
61 channelsMask[3] = 0xFFFF;
62 channelsMask[4] = 0x0000;
63 channelsMask[5] = 0x0000;
64 }
65 else if( chMaskCntl == 7 )
66 {
67 // Disable all channels
68 channelsMask[0] = 0x0000;
69 channelsMask[1] = 0x0000;
70 channelsMask[2] = 0x0000;
71 channelsMask[3] = 0x0000;
72 channelsMask[4] = 0x0000;
73 channelsMask[5] = 0x0000;
74 }
75 else
76 {
77 // chMaskCntl 0 to 3
78 for( uint8_t i = 0; i < 16; i++ )
79 {
80 if( ( ( chanMask & ( 1 << i ) ) != 0 ) &&
81 ( channels[chMaskCntl * 16 + i].Frequency == 0 ) )
82 {// Trying to enable an undefined channel
83 status &= 0xFE; // Channel mask KO
84 }
85 }
86 channelsMask[chMaskCntl] = chanMask;
87 }
88 return status;
89 }
90
RegionCN470A20VerifyRfFreq(uint32_t freq)91 bool RegionCN470A20VerifyRfFreq( uint32_t freq )
92 {
93 // Downstream group 1 and 2
94 if( RegionBaseUSVerifyFrequencyGroup( freq, CN470_A20_FIRST_RX_CHANNEL,
95 CN470_A20_LAST_RX_CHANNEL,
96 CN470_A20_STEPWIDTH_RX_CHANNEL ) == false )
97 {
98 return false;
99 }
100 return true;
101 }
102
RegionCN470A20InitializeChannels(ChannelParams_t * channels)103 void RegionCN470A20InitializeChannels( ChannelParams_t* channels )
104 {
105 // Upstream group 1
106 for( uint8_t i = 0; i < 32; i++ )
107 {
108 channels[i].Frequency = CN470_A20_FIRST_TX1_CHANNEL + i * CN470_A20_STEPWIDTH_RX_CHANNEL;
109 channels[i].DrRange.Value = ( CN470_TX_MAX_DATARATE << 4 ) | CN470_TX_MIN_DATARATE;
110 channels[i].Band = 0;
111 }
112 // Upstream group 2
113 for( uint8_t i = 32; i < 64; i++ )
114 {
115 channels[i].Frequency = CN470_A20_FIRST_TX2_CHANNEL + ( i - 32 ) * CN470_A20_STEPWIDTH_RX_CHANNEL;
116 channels[i].DrRange.Value = ( CN470_TX_MAX_DATARATE << 4 ) | CN470_TX_MIN_DATARATE;
117 channels[i].Band = 0;
118 }
119 }
120
RegionCN470A20InitializeChannelsMask(uint16_t * channelsDefaultMask)121 void RegionCN470A20InitializeChannelsMask( uint16_t* channelsDefaultMask )
122 {
123 // Enable all possible channels
124 channelsDefaultMask[0] = 0xFFFF;
125 channelsDefaultMask[1] = 0xFFFF;
126 channelsDefaultMask[2] = 0xFFFF;
127 channelsDefaultMask[3] = 0xFFFF;
128 channelsDefaultMask[4] = 0x0000;
129 channelsDefaultMask[5] = 0x0000;
130 }
131
RegionCN470A20GetRx1Frequency(uint8_t channel)132 uint32_t RegionCN470A20GetRx1Frequency( uint8_t channel )
133 {
134 // Base frequency for downstream group 1
135 uint32_t baseFrequency = CN470_A20_FIRST_RX_CHANNEL;
136 uint8_t offset = 0;
137
138 if( channel >= 32 )
139 {
140 // Base frequency for downstream group 2
141 baseFrequency = 490300000;
142 offset = 32;
143 }
144 return ( baseFrequency + ( ( channel - offset ) * CN470_A20_STEPWIDTH_RX_CHANNEL ) );
145 }
146
RegionCN470A20GetRx2Frequency(uint8_t joinChannelIndex,bool isOtaaDevice)147 uint32_t RegionCN470A20GetRx2Frequency( uint8_t joinChannelIndex, bool isOtaaDevice )
148 {
149 uint32_t otaaFrequencies[] = CN470_A20_RX_WND_2_FREQ_OTAA;
150
151 if( isOtaaDevice == true )
152 {
153 return otaaFrequencies[joinChannelIndex];
154 }
155 // ABP device
156 return CN470_A20_RX_WND_2_FREQ_ABP;
157 }
158
159