1 /*!
2 * \file sx1262mbxdas-board.c
3 *
4 * \brief Target board SX1262MBXDAS shield driver implementation
5 *
6 * \remark This target board is only available with the SX126xDVK1xAS
7 * development kit.
8 *
9 * \copyright Revised BSD License, see section \ref LICENSE.
10 *
11 * \code
12 * ______ _
13 * / _____) _ | |
14 * ( (____ _____ ____ _| |_ _____ ____| |__
15 * \____ \| ___ | (_ _) ___ |/ ___) _ \
16 * _____) ) ____| | | || |_| ____( (___| | | |
17 * (______/|_____)_|_|_| \__)_____)\____)_| |_|
18 * (C)2013-2017 Semtech
19 *
20 * \endcode
21 *
22 * \author Miguel Luis ( Semtech )
23 *
24 * \author Gregory Cristian ( Semtech )
25 */
26 #include <stdlib.h>
27 #include "utilities.h"
28 #include "board-config.h"
29 #include "board.h"
30 #include "delay.h"
31 #include "radio.h"
32 #include "sx126x-board.h"
33
34 #if defined( USE_RADIO_DEBUG )
35 /*!
36 * \brief Writes new Tx debug pin state
37 *
38 * \param [IN] state Debug pin state
39 */
40 static void SX126xDbgPinTxWrite( uint8_t state );
41
42 /*!
43 * \brief Writes new Rx debug pin state
44 *
45 * \param [IN] state Debug pin state
46 */
47 static void SX126xDbgPinRxWrite( uint8_t state );
48 #endif
49
50 /*!
51 * \brief Holds the internal operating mode of the radio
52 */
53 static RadioOperatingModes_t OperatingMode;
54
55 /*!
56 * Antenna switch GPIO pins objects
57 */
58 Gpio_t AntPow;
59 Gpio_t DeviceSel;
60
61 /*!
62 * Debug GPIO pins objects
63 */
64 #if defined( USE_RADIO_DEBUG )
65 Gpio_t DbgPinTx;
66 Gpio_t DbgPinRx;
67 #endif
68
SX126xIoInit(void)69 void SX126xIoInit( void )
70 {
71 GpioInit( &SX126x.Spi.Nss, RADIO_NSS, PIN_OUTPUT, PIN_PUSH_PULL, PIN_NO_PULL, 1 );
72 GpioInit( &SX126x.BUSY, RADIO_BUSY, PIN_INPUT, PIN_PUSH_PULL, PIN_NO_PULL, 0 );
73 GpioInit( &SX126x.DIO1, RADIO_DIO_1, PIN_INPUT, PIN_PUSH_PULL, PIN_NO_PULL, 0 );
74 GpioInit( &DeviceSel, RADIO_DEVICE_SEL, PIN_INPUT, PIN_PUSH_PULL, PIN_NO_PULL, 0 );
75 }
76
SX126xIoIrqInit(DioIrqHandler dioIrq)77 void SX126xIoIrqInit( DioIrqHandler dioIrq )
78 {
79 GpioSetInterrupt( &SX126x.DIO1, IRQ_RISING_EDGE, IRQ_HIGH_PRIORITY, dioIrq );
80 }
81
SX126xIoDeInit(void)82 void SX126xIoDeInit( void )
83 {
84 GpioInit( &SX126x.Spi.Nss, RADIO_NSS, PIN_OUTPUT, PIN_PUSH_PULL, PIN_NO_PULL, 1 );
85 GpioInit( &SX126x.BUSY, RADIO_BUSY, PIN_INPUT, PIN_PUSH_PULL, PIN_NO_PULL, 0 );
86 GpioInit( &SX126x.DIO1, RADIO_DIO_1, PIN_INPUT, PIN_PUSH_PULL, PIN_NO_PULL, 0 );
87 }
88
SX126xIoDbgInit(void)89 void SX126xIoDbgInit( void )
90 {
91 #if defined( USE_RADIO_DEBUG )
92 GpioInit( &DbgPinTx, RADIO_DBG_PIN_TX, PIN_OUTPUT, PIN_PUSH_PULL, PIN_NO_PULL, 0 );
93 GpioInit( &DbgPinRx, RADIO_DBG_PIN_RX, PIN_OUTPUT, PIN_PUSH_PULL, PIN_NO_PULL, 0 );
94 #endif
95 }
96
SX126xIoTcxoInit(void)97 void SX126xIoTcxoInit( void )
98 {
99 CalibrationParams_t calibParam;
100
101 SX126xSetDio3AsTcxoCtrl( TCXO_CTRL_1_7V, SX126xGetBoardTcxoWakeupTime( ) << 6 ); // convert from ms to SX126x time base
102 calibParam.Value = 0x7F;
103 SX126xCalibrate( calibParam );
104 }
105
SX126xGetBoardTcxoWakeupTime(void)106 uint32_t SX126xGetBoardTcxoWakeupTime( void )
107 {
108 return BOARD_TCXO_WAKEUP_TIME;
109 }
110
SX126xIoRfSwitchInit(void)111 void SX126xIoRfSwitchInit( void )
112 {
113 SX126xSetDio2AsRfSwitchCtrl( true );
114 }
115
SX126xGetOperatingMode(void)116 RadioOperatingModes_t SX126xGetOperatingMode( void )
117 {
118 return OperatingMode;
119 }
120
SX126xSetOperatingMode(RadioOperatingModes_t mode)121 void SX126xSetOperatingMode( RadioOperatingModes_t mode )
122 {
123 OperatingMode = mode;
124 #if defined( USE_RADIO_DEBUG )
125 switch( mode )
126 {
127 case MODE_TX:
128 SX126xDbgPinTxWrite( 1 );
129 SX126xDbgPinRxWrite( 0 );
130 break;
131 case MODE_RX:
132 case MODE_RX_DC:
133 SX126xDbgPinTxWrite( 0 );
134 SX126xDbgPinRxWrite( 1 );
135 break;
136 default:
137 SX126xDbgPinTxWrite( 0 );
138 SX126xDbgPinRxWrite( 0 );
139 break;
140 }
141 #endif
142 }
143
SX126xReset(void)144 void SX126xReset( void )
145 {
146 DelayMs( 10 );
147 GpioInit( &SX126x.Reset, RADIO_RESET, PIN_OUTPUT, PIN_PUSH_PULL, PIN_NO_PULL, 0 );
148 DelayMs( 20 );
149 GpioInit( &SX126x.Reset, RADIO_RESET, PIN_ANALOGIC, PIN_PUSH_PULL, PIN_NO_PULL, 0 ); // internal pull-up
150 DelayMs( 10 );
151 }
152
SX126xWaitOnBusy(void)153 void SX126xWaitOnBusy( void )
154 {
155 while( GpioRead( &SX126x.BUSY ) == 1 );
156 }
157
SX126xWakeup(void)158 void SX126xWakeup( void )
159 {
160 CRITICAL_SECTION_BEGIN( );
161
162 GpioWrite( &SX126x.Spi.Nss, 0 );
163
164 SpiInOut( &SX126x.Spi, RADIO_GET_STATUS );
165 SpiInOut( &SX126x.Spi, 0x00 );
166
167 GpioWrite( &SX126x.Spi.Nss, 1 );
168
169 // Wait for chip to be ready.
170 SX126xWaitOnBusy( );
171
172 // Update operating mode context variable
173 SX126xSetOperatingMode( MODE_STDBY_RC );
174
175 CRITICAL_SECTION_END( );
176 }
177
SX126xWriteCommand(RadioCommands_t command,uint8_t * buffer,uint16_t size)178 void SX126xWriteCommand( RadioCommands_t command, uint8_t *buffer, uint16_t size )
179 {
180 SX126xCheckDeviceReady( );
181
182 GpioWrite( &SX126x.Spi.Nss, 0 );
183
184 SpiInOut( &SX126x.Spi, ( uint8_t )command );
185
186 for( uint16_t i = 0; i < size; i++ )
187 {
188 SpiInOut( &SX126x.Spi, buffer[i] );
189 }
190
191 GpioWrite( &SX126x.Spi.Nss, 1 );
192
193 if( command != RADIO_SET_SLEEP )
194 {
195 SX126xWaitOnBusy( );
196 }
197 }
198
SX126xReadCommand(RadioCommands_t command,uint8_t * buffer,uint16_t size)199 uint8_t SX126xReadCommand( RadioCommands_t command, uint8_t *buffer, uint16_t size )
200 {
201 uint8_t status = 0;
202
203 SX126xCheckDeviceReady( );
204
205 GpioWrite( &SX126x.Spi.Nss, 0 );
206
207 SpiInOut( &SX126x.Spi, ( uint8_t )command );
208 status = SpiInOut( &SX126x.Spi, 0x00 );
209 for( uint16_t i = 0; i < size; i++ )
210 {
211 buffer[i] = SpiInOut( &SX126x.Spi, 0 );
212 }
213
214 GpioWrite( &SX126x.Spi.Nss, 1 );
215
216 SX126xWaitOnBusy( );
217
218 return status;
219 }
220
SX126xWriteRegisters(uint16_t address,uint8_t * buffer,uint16_t size)221 void SX126xWriteRegisters( uint16_t address, uint8_t *buffer, uint16_t size )
222 {
223 SX126xCheckDeviceReady( );
224
225 GpioWrite( &SX126x.Spi.Nss, 0 );
226
227 SpiInOut( &SX126x.Spi, RADIO_WRITE_REGISTER );
228 SpiInOut( &SX126x.Spi, ( address & 0xFF00 ) >> 8 );
229 SpiInOut( &SX126x.Spi, address & 0x00FF );
230
231 for( uint16_t i = 0; i < size; i++ )
232 {
233 SpiInOut( &SX126x.Spi, buffer[i] );
234 }
235
236 GpioWrite( &SX126x.Spi.Nss, 1 );
237
238 SX126xWaitOnBusy( );
239 }
240
SX126xWriteRegister(uint16_t address,uint8_t value)241 void SX126xWriteRegister( uint16_t address, uint8_t value )
242 {
243 SX126xWriteRegisters( address, &value, 1 );
244 }
245
SX126xReadRegisters(uint16_t address,uint8_t * buffer,uint16_t size)246 void SX126xReadRegisters( uint16_t address, uint8_t *buffer, uint16_t size )
247 {
248 SX126xCheckDeviceReady( );
249
250 GpioWrite( &SX126x.Spi.Nss, 0 );
251
252 SpiInOut( &SX126x.Spi, RADIO_READ_REGISTER );
253 SpiInOut( &SX126x.Spi, ( address & 0xFF00 ) >> 8 );
254 SpiInOut( &SX126x.Spi, address & 0x00FF );
255 SpiInOut( &SX126x.Spi, 0 );
256 for( uint16_t i = 0; i < size; i++ )
257 {
258 buffer[i] = SpiInOut( &SX126x.Spi, 0 );
259 }
260 GpioWrite( &SX126x.Spi.Nss, 1 );
261
262 SX126xWaitOnBusy( );
263 }
264
SX126xReadRegister(uint16_t address)265 uint8_t SX126xReadRegister( uint16_t address )
266 {
267 uint8_t data;
268 SX126xReadRegisters( address, &data, 1 );
269 return data;
270 }
271
SX126xWriteBuffer(uint8_t offset,uint8_t * buffer,uint8_t size)272 void SX126xWriteBuffer( uint8_t offset, uint8_t *buffer, uint8_t size )
273 {
274 SX126xCheckDeviceReady( );
275
276 GpioWrite( &SX126x.Spi.Nss, 0 );
277
278 SpiInOut( &SX126x.Spi, RADIO_WRITE_BUFFER );
279 SpiInOut( &SX126x.Spi, offset );
280 for( uint16_t i = 0; i < size; i++ )
281 {
282 SpiInOut( &SX126x.Spi, buffer[i] );
283 }
284 GpioWrite( &SX126x.Spi.Nss, 1 );
285
286 SX126xWaitOnBusy( );
287 }
288
SX126xReadBuffer(uint8_t offset,uint8_t * buffer,uint8_t size)289 void SX126xReadBuffer( uint8_t offset, uint8_t *buffer, uint8_t size )
290 {
291 SX126xCheckDeviceReady( );
292
293 GpioWrite( &SX126x.Spi.Nss, 0 );
294
295 SpiInOut( &SX126x.Spi, RADIO_READ_BUFFER );
296 SpiInOut( &SX126x.Spi, offset );
297 SpiInOut( &SX126x.Spi, 0 );
298 for( uint16_t i = 0; i < size; i++ )
299 {
300 buffer[i] = SpiInOut( &SX126x.Spi, 0 );
301 }
302 GpioWrite( &SX126x.Spi.Nss, 1 );
303
304 SX126xWaitOnBusy( );
305 }
306
SX126xSetRfTxPower(int8_t power)307 void SX126xSetRfTxPower( int8_t power )
308 {
309 SX126xSetTxParams( power, RADIO_RAMP_40_US );
310 }
311
SX126xGetDeviceId(void)312 uint8_t SX126xGetDeviceId( void )
313 {
314 if( GpioRead( &DeviceSel ) == 1 )
315 {
316 return SX1261;
317 }
318 else
319 {
320 return SX1262;
321 }
322 }
323
SX126xAntSwOn(void)324 void SX126xAntSwOn( void )
325 {
326 GpioInit( &AntPow, RADIO_ANT_SWITCH_POWER, PIN_OUTPUT, PIN_PUSH_PULL, PIN_PULL_UP, 1 );
327 }
328
SX126xAntSwOff(void)329 void SX126xAntSwOff( void )
330 {
331 GpioInit( &AntPow, RADIO_ANT_SWITCH_POWER, PIN_ANALOGIC, PIN_PUSH_PULL, PIN_NO_PULL, 0 );
332 }
333
SX126xCheckRfFrequency(uint32_t frequency)334 bool SX126xCheckRfFrequency( uint32_t frequency )
335 {
336 // Implement check. Currently all frequencies are supported
337 return true;
338 }
339
SX126xGetDio1PinState(void)340 uint32_t SX126xGetDio1PinState( void )
341 {
342 return GpioRead( &SX126x.DIO1 );
343 }
344
345 #if defined( USE_RADIO_DEBUG )
SX126xDbgPinTxWrite(uint8_t state)346 static void SX126xDbgPinTxWrite( uint8_t state )
347 {
348 GpioWrite( &DbgPinTx, state );
349 }
350
SX126xDbgPinRxWrite(uint8_t state)351 static void SX126xDbgPinRxWrite( uint8_t state )
352 {
353 GpioWrite( &DbgPinRx, state );
354 }
355 #endif
356