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