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