1 /*!
2 * \file sx1272-board.c
3 *
4 * \brief Target board SX1272 driver 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 * \endcode
18 *
19 * \author Miguel Luis ( Semtech )
20 *
21 * \author Gregory Cristian ( Semtech )
22 */
23 #include <stdlib.h>
24 #include "utilities.h"
25 #include "board-config.h"
26 #include "delay.h"
27 #include "radio.h"
28 #include "sx1272-board.h"
29
30 /*!
31 * Flag used to set the RF switch control pins in low power mode when the radio is not active.
32 */
33 static bool RadioIsActive = false;
34
35 /*!
36 * Radio driver structure initialization
37 */
38 const struct Radio_s Radio =
39 {
40 SX1272Init,
41 SX1272GetStatus,
42 SX1272SetModem,
43 SX1272SetChannel,
44 SX1272IsChannelFree,
45 SX1272Random,
46 SX1272SetRxConfig,
47 SX1272SetTxConfig,
48 SX1272CheckRfFrequency,
49 SX1272GetTimeOnAir,
50 SX1272Send,
51 SX1272SetSleep,
52 SX1272SetStby,
53 SX1272SetRx,
54 SX1272StartCad,
55 SX1272SetTxContinuousWave,
56 SX1272ReadRssi,
57 SX1272Write,
58 SX1272Read,
59 SX1272WriteBuffer,
60 SX1272ReadBuffer,
61 SX1272SetMaxPayloadLength,
62 SX1272SetPublicNetwork,
63 SX1272GetWakeupTime,
64 NULL, // void ( *IrqProcess )( void )
65 NULL, // void ( *RxBoosted )( uint32_t timeout ) - SX126x Only
66 NULL, // void ( *SetRxDutyCycle )( uint32_t rxTime, uint32_t sleepTime ) - SX126x Only
67 };
68
69 /*!
70 * Antenna switch GPIO pins objects
71 */
72 Gpio_t RadioSwitchCtrl1;
73 Gpio_t RadioSwitchCtrl2;
74 Gpio_t RadioPwrAmpCtrl;
75
76 /*!
77 * Debug GPIO pins objects
78 */
79 #if defined( USE_RADIO_DEBUG )
80 Gpio_t DbgPinTx;
81 Gpio_t DbgPinRx;
82 #endif
83
84 /*
85 PD_2=0 PD_2=1
86 op PaB rfo rfo
87 0 4.6 18.5 27.0
88 1 5.6 21.1 28.1
89 2 6.7 23.3 29.1
90 3 7.7 25.3 30.1
91 4 8.8 26.2 30.7
92 5 9.8 27.3 31.2
93 6 10.7 28.1 31.6
94 7 11.7 28.6 32.2
95 8 12.8 29.2 32.4
96 9 13.7 29.9 32.9
97 10 14.7 30.5 33.1
98 11 15.6 30.8 33.4
99 12 16.4 30.9 33.6
100 13 17.1 31.0 33.7
101 14 17.8 31.1 33.7
102 15 18.4 31.1 33.7
103 */
104 // txpow: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
105 static const uint8_t PaBTable[20] = { 0, 0, 0, 0, 0, 1, 2, 3, 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 14, 15 };
106
107 // txpow: 20 21 22 23 24 25 26 27 28 29 30
108 static const uint8_t RfoTable[11] = { 1, 1, 1, 2, 2, 3, 4, 5, 6, 8, 9 };
109
SX1272IoInit(void)110 void SX1272IoInit( void )
111 {
112 GpioInit( &SX1272.Spi.Nss, RADIO_NSS, PIN_OUTPUT, PIN_PUSH_PULL, PIN_NO_PULL, 1 );
113
114 GpioInit( &SX1272.DIO0, RADIO_DIO_0, PIN_INPUT, PIN_PUSH_PULL, PIN_PULL_UP, 0 );
115 GpioInit( &SX1272.DIO1, RADIO_DIO_1, PIN_INPUT, PIN_PUSH_PULL, PIN_PULL_UP, 0 );
116 GpioInit( &SX1272.DIO2, RADIO_DIO_2, PIN_INPUT, PIN_PUSH_PULL, PIN_PULL_UP, 0 );
117 GpioInit( &SX1272.DIO3, RADIO_DIO_3, PIN_INPUT, PIN_PUSH_PULL, PIN_PULL_UP, 0 );
118 GpioInit( &SX1272.DIO4, RADIO_DIO_4, PIN_INPUT, PIN_PUSH_PULL, PIN_PULL_UP, 0 );
119 GpioInit( &SX1272.DIO5, RADIO_DIO_5, PIN_INPUT, PIN_PUSH_PULL, PIN_PULL_UP, 0 );
120 }
121
SX1272IoIrqInit(DioIrqHandler ** irqHandlers)122 void SX1272IoIrqInit( DioIrqHandler **irqHandlers )
123 {
124 GpioSetInterrupt( &SX1272.DIO0, IRQ_RISING_EDGE, IRQ_HIGH_PRIORITY, irqHandlers[0] );
125 GpioSetInterrupt( &SX1272.DIO1, IRQ_RISING_FALLING_EDGE, IRQ_HIGH_PRIORITY, irqHandlers[1] );
126 GpioSetInterrupt( &SX1272.DIO2, IRQ_RISING_EDGE, IRQ_HIGH_PRIORITY, irqHandlers[2] );
127 GpioSetInterrupt( &SX1272.DIO3, IRQ_RISING_EDGE, IRQ_HIGH_PRIORITY, irqHandlers[3] );
128 GpioSetInterrupt( &SX1272.DIO4, IRQ_RISING_EDGE, IRQ_HIGH_PRIORITY, irqHandlers[4] );
129 GpioSetInterrupt( &SX1272.DIO5, IRQ_RISING_EDGE, IRQ_HIGH_PRIORITY, irqHandlers[5] );
130 }
131
SX1272IoDeInit(void)132 void SX1272IoDeInit( void )
133 {
134 GpioInit( &SX1272.Spi.Nss, RADIO_NSS, PIN_OUTPUT, PIN_PUSH_PULL, PIN_NO_PULL, 1 );
135
136 GpioInit( &SX1272.DIO0, RADIO_DIO_0, PIN_INPUT, PIN_PUSH_PULL, PIN_NO_PULL, 0 );
137 GpioInit( &SX1272.DIO1, RADIO_DIO_1, PIN_INPUT, PIN_PUSH_PULL, PIN_NO_PULL, 0 );
138 GpioInit( &SX1272.DIO2, RADIO_DIO_2, PIN_INPUT, PIN_PUSH_PULL, PIN_NO_PULL, 0 );
139 GpioInit( &SX1272.DIO3, RADIO_DIO_3, PIN_INPUT, PIN_PUSH_PULL, PIN_NO_PULL, 0 );
140 GpioInit( &SX1272.DIO4, RADIO_DIO_4, PIN_INPUT, PIN_PUSH_PULL, PIN_NO_PULL, 0 );
141 GpioInit( &SX1272.DIO5, RADIO_DIO_5, PIN_INPUT, PIN_PUSH_PULL, PIN_NO_PULL, 0 );
142 }
143
SX1272IoDbgInit(void)144 void SX1272IoDbgInit( void )
145 {
146 #if defined( USE_RADIO_DEBUG )
147 GpioInit( &DbgPinTx, RADIO_DBG_PIN_TX, PIN_OUTPUT, PIN_PUSH_PULL, PIN_NO_PULL, 0 );
148 GpioInit( &DbgPinRx, RADIO_DBG_PIN_RX, PIN_OUTPUT, PIN_PUSH_PULL, PIN_NO_PULL, 0 );
149 #endif
150 }
151
SX1272IoTcxoInit(void)152 void SX1272IoTcxoInit( void )
153 {
154 // No TCXO component available on this board design.
155 }
156
SX1272SetBoardTcxo(uint8_t state)157 void SX1272SetBoardTcxo( uint8_t state )
158 {
159 // No TCXO component available on this board design.
160 #if 0
161 if( state == true )
162 {
163 TCXO_ON( );
164 DelayMs( BOARD_TCXO_WAKEUP_TIME );
165 }
166 else
167 {
168 TCXO_OFF( );
169 }
170 #endif
171 }
172
SX1272GetBoardTcxoWakeupTime(void)173 uint32_t SX1272GetBoardTcxoWakeupTime( void )
174 {
175 return BOARD_TCXO_WAKEUP_TIME;
176 }
177
SX1272Reset(void)178 void SX1272Reset( void )
179 {
180 // Enables the TCXO if available on the board design
181 SX1272SetBoardTcxo( true );
182
183 // Set RESET pin to 1
184 GpioInit( &SX1272.Reset, RADIO_RESET, PIN_OUTPUT, PIN_PUSH_PULL, PIN_NO_PULL, 1 );
185
186 // Wait 1 ms
187 DelayMs( 1 );
188
189 // Configure RESET as input
190 GpioInit( &SX1272.Reset, RADIO_RESET, PIN_INPUT, PIN_PUSH_PULL, PIN_NO_PULL, 1 );
191
192 // Wait 6 ms
193 DelayMs( 6 );
194 }
195
SX1272SetRfTxPower(int8_t power)196 void SX1272SetRfTxPower( int8_t power )
197 {
198 uint8_t paConfig = 0;
199 uint8_t paDac = 0;
200
201 paConfig = Radio.Read( REG_PACONFIG );
202 paDac = Radio.Read( REG_PADAC );
203
204 if( power > 19 )
205 {
206 paConfig = ( paConfig & RF_PACONFIG_PASELECT_MASK ) | RF_PACONFIG_PASELECT_RFO;
207 paConfig = ( paConfig & RFLR_PACONFIG_OUTPUTPOWER_MASK ) | RfoTable[power - 20];
208 }
209 else
210 {
211 paConfig = ( paConfig & RF_PACONFIG_PASELECT_MASK ) | RF_PACONFIG_PASELECT_PABOOST;
212 paConfig = ( paConfig & RFLR_PACONFIG_OUTPUTPOWER_MASK ) | PaBTable[MAX( power, 0 )];
213 }
214 Radio.Write( REG_PACONFIG, paConfig );
215 Radio.Write( REG_PADAC, paDac );
216 }
217
SX1272SetAntSwLowPower(bool status)218 void SX1272SetAntSwLowPower( bool status )
219 {
220 if( RadioIsActive != status )
221 {
222 RadioIsActive = status;
223
224 if( status == false )
225 {
226 SX1272AntSwInit( );
227 }
228 else
229 {
230 SX1272AntSwDeInit( );
231 }
232 }
233 }
234
SX1272AntSwInit(void)235 void SX1272AntSwInit( void )
236 {
237 GpioInit( &RadioSwitchCtrl1, RADIO_SWITCH_CTRL1, PIN_OUTPUT, PIN_PUSH_PULL, PIN_PULL_UP, 0 );
238 GpioInit( &RadioSwitchCtrl2, RADIO_SWITCH_CTRL2, PIN_OUTPUT, PIN_PUSH_PULL, PIN_PULL_UP, 0 );
239 GpioInit( &RadioPwrAmpCtrl , RADIO_PWRAMP_CTRL , PIN_OUTPUT, PIN_PUSH_PULL, PIN_PULL_UP, 0 );
240 }
241
SX1272AntSwDeInit(void)242 void SX1272AntSwDeInit( void )
243 {
244 GpioInit( &RadioSwitchCtrl1, RADIO_SWITCH_CTRL1, PIN_OUTPUT, PIN_PUSH_PULL, PIN_PULL_UP, 0 );
245 GpioInit( &RadioSwitchCtrl2, RADIO_SWITCH_CTRL2, PIN_OUTPUT, PIN_PUSH_PULL, PIN_PULL_UP, 0 );
246 GpioInit( &RadioPwrAmpCtrl , RADIO_PWRAMP_CTRL , PIN_OUTPUT, PIN_PUSH_PULL, PIN_PULL_UP, 0 );
247 }
248
SX1272SetAntSw(uint8_t opMode)249 void SX1272SetAntSw( uint8_t opMode )
250 {
251 switch( opMode )
252 {
253 case RFLR_OPMODE_TRANSMITTER:
254 if( ( Radio.Read( REG_PACONFIG ) & RF_PACONFIG_PASELECT_PABOOST ) == RF_PACONFIG_PASELECT_PABOOST )
255 {
256 GpioWrite( &RadioSwitchCtrl1, 1 );
257 GpioWrite( &RadioSwitchCtrl2, 0 );
258 }
259 else
260 {
261 GpioWrite( &RadioSwitchCtrl1, 0 );
262 GpioWrite( &RadioSwitchCtrl2, 1 );
263 }
264 break;
265 case RFLR_OPMODE_RECEIVER:
266 case RFLR_OPMODE_RECEIVER_SINGLE:
267 case RFLR_OPMODE_CAD:
268 GpioWrite( &RadioSwitchCtrl1, 1 );
269 GpioWrite( &RadioSwitchCtrl2, 1 );
270 break;
271 default:
272 GpioWrite( &RadioSwitchCtrl1, 0 );
273 GpioWrite( &RadioSwitchCtrl2, 0 );
274 GpioWrite( &RadioPwrAmpCtrl, 0 );
275 break;
276 }
277 }
278
SX1272CheckRfFrequency(uint32_t frequency)279 bool SX1272CheckRfFrequency( uint32_t frequency )
280 {
281 // Implement check. Currently all frequencies are supported
282 return true;
283 }
284
SX1272GetDio1PinState(void)285 uint32_t SX1272GetDio1PinState( void )
286 {
287 return GpioRead( &SX1272.DIO1 );
288 }
289
290 #if defined( USE_RADIO_DEBUG )
SX1272DbgPinTxWrite(uint8_t state)291 void SX1272DbgPinTxWrite( uint8_t state )
292 {
293 GpioWrite( &DbgPinTx, state );
294 }
295
SX1272DbgPinRxWrite(uint8_t state)296 void SX1272DbgPinRxWrite( uint8_t state )
297 {
298 GpioWrite( &DbgPinRx, state );
299 }
300 #endif
301