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