1 /*!
2  * \file      sx1276mb1las-board.c
3  *
4  * \brief     Target board SX1276MB1LAS 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 "delay.h"
27 #include "radio.h"
28 #include "sx1276-board.h"
29 
30 /*!
31  * \brief Gets the board PA selection configuration
32  *
33  * \param [IN] channel Channel frequency in Hz
34  * \retval PaSelect RegPaConfig PaSelect value
35  */
36 static uint8_t SX1276GetPaSelect( uint32_t channel );
37 
38 /*!
39  * Flag used to set the RF switch control pins in low power mode when the radio is not active.
40  */
41 static bool RadioIsActive = false;
42 
43 /*!
44  * Radio driver structure initialization
45  */
46 const struct Radio_s Radio =
47 {
48     SX1276Init,
49     SX1276GetStatus,
50     SX1276SetModem,
51     SX1276SetChannel,
52     SX1276IsChannelFree,
53     SX1276Random,
54     SX1276SetRxConfig,
55     SX1276SetTxConfig,
56     SX1276CheckRfFrequency,
57     SX1276GetTimeOnAir,
58     SX1276Send,
59     SX1276SetSleep,
60     SX1276SetStby,
61     SX1276SetRx,
62     SX1276StartCad,
63     SX1276SetTxContinuousWave,
64     SX1276ReadRssi,
65     SX1276Write,
66     SX1276Read,
67     SX1276WriteBuffer,
68     SX1276ReadBuffer,
69     SX1276SetMaxPayloadLength,
70     SX1276SetPublicNetwork,
71     SX1276GetWakeupTime,
72     NULL, // void ( *IrqProcess )( void )
73     NULL, // void ( *RxBoosted )( uint32_t timeout ) - SX126x Only
74     NULL, // void ( *SetRxDutyCycle )( uint32_t rxTime, uint32_t sleepTime ) - SX126x Only
75 };
76 
77 /*!
78  * Antenna switch GPIO pins objects
79  */
80 Gpio_t AntSwitch;
81 
82 /*!
83  * Debug GPIO pins objects
84  */
85 #if defined( USE_RADIO_DEBUG )
86 Gpio_t DbgPinTx;
87 Gpio_t DbgPinRx;
88 #endif
89 
SX1276IoInit(void)90 void SX1276IoInit( void )
91 {
92     GpioInit( &SX1276.Spi.Nss, RADIO_NSS, PIN_OUTPUT, PIN_PUSH_PULL, PIN_NO_PULL, 1 );
93 
94     GpioInit( &SX1276.DIO0, RADIO_DIO_0, PIN_INPUT, PIN_PUSH_PULL, PIN_PULL_UP, 0 );
95     GpioInit( &SX1276.DIO1, RADIO_DIO_1, PIN_INPUT, PIN_PUSH_PULL, PIN_PULL_UP, 0 );
96     GpioInit( &SX1276.DIO2, RADIO_DIO_2, PIN_INPUT, PIN_PUSH_PULL, PIN_PULL_UP, 0 );
97     GpioInit( &SX1276.DIO3, RADIO_DIO_3, PIN_INPUT, PIN_PUSH_PULL, PIN_PULL_UP, 0 );
98     GpioInit( &SX1276.DIO4, RADIO_DIO_4, PIN_INPUT, PIN_PUSH_PULL, PIN_PULL_UP, 0 );
99     GpioInit( &SX1276.DIO5, RADIO_DIO_5, PIN_INPUT, PIN_PUSH_PULL, PIN_PULL_UP, 0 );
100 }
101 
SX1276IoIrqInit(DioIrqHandler ** irqHandlers)102 void SX1276IoIrqInit( DioIrqHandler **irqHandlers )
103 {
104     GpioSetInterrupt( &SX1276.DIO0, IRQ_RISING_EDGE, IRQ_HIGH_PRIORITY, irqHandlers[0] );
105     GpioSetInterrupt( &SX1276.DIO1, IRQ_RISING_FALLING_EDGE, IRQ_HIGH_PRIORITY, irqHandlers[1] );
106     GpioSetInterrupt( &SX1276.DIO2, IRQ_RISING_EDGE, IRQ_HIGH_PRIORITY, irqHandlers[2] );
107     GpioSetInterrupt( &SX1276.DIO3, IRQ_RISING_EDGE, IRQ_HIGH_PRIORITY, irqHandlers[3] );
108     GpioSetInterrupt( &SX1276.DIO4, IRQ_RISING_EDGE, IRQ_HIGH_PRIORITY, irqHandlers[4] );
109     GpioSetInterrupt( &SX1276.DIO5, IRQ_RISING_EDGE, IRQ_HIGH_PRIORITY, irqHandlers[5] );
110 }
111 
SX1276IoDeInit(void)112 void SX1276IoDeInit( void )
113 {
114     GpioInit( &SX1276.Spi.Nss, RADIO_NSS, PIN_OUTPUT, PIN_PUSH_PULL, PIN_NO_PULL, 1 );
115 
116     GpioInit( &SX1276.DIO0, RADIO_DIO_0, PIN_INPUT, PIN_PUSH_PULL, PIN_NO_PULL, 0 );
117     GpioInit( &SX1276.DIO1, RADIO_DIO_1, PIN_INPUT, PIN_PUSH_PULL, PIN_NO_PULL, 0 );
118     GpioInit( &SX1276.DIO2, RADIO_DIO_2, PIN_INPUT, PIN_PUSH_PULL, PIN_NO_PULL, 0 );
119     GpioInit( &SX1276.DIO3, RADIO_DIO_3, PIN_INPUT, PIN_PUSH_PULL, PIN_NO_PULL, 0 );
120     GpioInit( &SX1276.DIO4, RADIO_DIO_4, PIN_INPUT, PIN_PUSH_PULL, PIN_NO_PULL, 0 );
121     GpioInit( &SX1276.DIO5, RADIO_DIO_5, PIN_INPUT, PIN_PUSH_PULL, PIN_NO_PULL, 0 );
122 }
123 
SX1276IoDbgInit(void)124 void SX1276IoDbgInit( void )
125 {
126 #if defined( USE_RADIO_DEBUG )
127     GpioInit( &DbgPinTx, RADIO_DBG_PIN_TX, PIN_OUTPUT, PIN_PUSH_PULL, PIN_NO_PULL, 0 );
128     GpioInit( &DbgPinRx, RADIO_DBG_PIN_RX, PIN_OUTPUT, PIN_PUSH_PULL, PIN_NO_PULL, 0 );
129 #endif
130 }
131 
SX1276IoTcxoInit(void)132 void SX1276IoTcxoInit( void )
133 {
134     // No TCXO component available on this board design.
135 }
136 
SX1276SetBoardTcxo(uint8_t state)137 void SX1276SetBoardTcxo( uint8_t state )
138 {
139     // No TCXO component available on this board design.
140 #if 0
141     if( state == true )
142     {
143         TCXO_ON( );
144         DelayMs( BOARD_TCXO_WAKEUP_TIME );
145     }
146     else
147     {
148         TCXO_OFF( );
149     }
150 #endif
151 }
152 
SX1276GetBoardTcxoWakeupTime(void)153 uint32_t SX1276GetBoardTcxoWakeupTime( void )
154 {
155     return BOARD_TCXO_WAKEUP_TIME;
156 }
157 
SX1276Reset(void)158 void SX1276Reset( void )
159 {
160     // Enables the TCXO if available on the board design
161     SX1276SetBoardTcxo( true );
162 
163     // Set RESET pin to 0
164     GpioInit( &SX1276.Reset, RADIO_RESET, PIN_OUTPUT, PIN_PUSH_PULL, PIN_NO_PULL, 0 );
165 
166     // Wait 1 ms
167     DelayMs( 1 );
168 
169     // Configure RESET as input
170     GpioInit( &SX1276.Reset, RADIO_RESET, PIN_INPUT, PIN_PUSH_PULL, PIN_NO_PULL, 1 );
171 
172     // Wait 6 ms
173     DelayMs( 6 );
174 }
175 
SX1276SetRfTxPower(int8_t power)176 void SX1276SetRfTxPower( int8_t power )
177 {
178     uint8_t paConfig = 0;
179     uint8_t paDac = 0;
180 
181     paConfig = SX1276Read( REG_PACONFIG );
182     paDac = SX1276Read( REG_PADAC );
183 
184     paConfig = ( paConfig & RF_PACONFIG_PASELECT_MASK ) | SX1276GetPaSelect( SX1276.Settings.Channel );
185 
186     if( ( paConfig & RF_PACONFIG_PASELECT_PABOOST ) == RF_PACONFIG_PASELECT_PABOOST )
187     {
188         if( power > 17 )
189         {
190             paDac = ( paDac & RF_PADAC_20DBM_MASK ) | RF_PADAC_20DBM_ON;
191         }
192         else
193         {
194             paDac = ( paDac & RF_PADAC_20DBM_MASK ) | RF_PADAC_20DBM_OFF;
195         }
196         if( ( paDac & RF_PADAC_20DBM_ON ) == RF_PADAC_20DBM_ON )
197         {
198             if( power < 5 )
199             {
200                 power = 5;
201             }
202             if( power > 20 )
203             {
204                 power = 20;
205             }
206             paConfig = ( paConfig & RF_PACONFIG_OUTPUTPOWER_MASK ) | ( uint8_t )( ( uint16_t )( power - 5 ) & 0x0F );
207         }
208         else
209         {
210             if( power < 2 )
211             {
212                 power = 2;
213             }
214             if( power > 17 )
215             {
216                 power = 17;
217             }
218             paConfig = ( paConfig & RF_PACONFIG_OUTPUTPOWER_MASK ) | ( uint8_t )( ( uint16_t )( power - 2 ) & 0x0F );
219         }
220     }
221     else
222     {
223         if( power > 0 )
224         {
225             if( power > 15 )
226             {
227                 power = 15;
228             }
229             paConfig = ( paConfig & RF_PACONFIG_MAX_POWER_MASK & RF_PACONFIG_OUTPUTPOWER_MASK ) | ( 7 << 4 ) | ( power );
230         }
231         else
232         {
233             if( power < -4 )
234             {
235                 power = -4;
236             }
237             paConfig = ( paConfig & RF_PACONFIG_MAX_POWER_MASK & RF_PACONFIG_OUTPUTPOWER_MASK ) | ( 0 << 4 ) | ( power + 4 );
238         }
239     }
240     SX1276Write( REG_PACONFIG, paConfig );
241     SX1276Write( REG_PADAC, paDac );
242 }
243 
SX1276GetPaSelect(uint32_t channel)244 static uint8_t SX1276GetPaSelect( uint32_t channel )
245 {
246     if( channel > RF_MID_BAND_THRESH )
247     {
248         return RF_PACONFIG_PASELECT_PABOOST;
249     }
250     else
251     {
252         return RF_PACONFIG_PASELECT_RFO;
253     }
254 }
255 
SX1276SetAntSwLowPower(bool status)256 void SX1276SetAntSwLowPower( bool status )
257 {
258     if( RadioIsActive != status )
259     {
260         RadioIsActive = status;
261 
262         if( status == false )
263         {
264             SX1276AntSwInit( );
265         }
266         else
267         {
268             SX1276AntSwDeInit( );
269         }
270     }
271 }
272 
SX1276AntSwInit(void)273 void SX1276AntSwInit( void )
274 {
275     GpioInit( &AntSwitch, RADIO_ANT_SWITCH, PIN_OUTPUT, PIN_PUSH_PULL, PIN_PULL_UP, 0 );
276 }
277 
SX1276AntSwDeInit(void)278 void SX1276AntSwDeInit( void )
279 {
280     GpioInit( &AntSwitch, RADIO_ANT_SWITCH, PIN_OUTPUT, PIN_PUSH_PULL, PIN_NO_PULL, 0 );
281 }
282 
SX1276SetAntSw(uint8_t opMode)283 void SX1276SetAntSw( uint8_t opMode )
284 {
285     switch( opMode )
286     {
287     case RFLR_OPMODE_TRANSMITTER:
288         GpioWrite( &AntSwitch, 1 );
289         break;
290     case RFLR_OPMODE_RECEIVER:
291     case RFLR_OPMODE_RECEIVER_SINGLE:
292     case RFLR_OPMODE_CAD:
293     default:
294         GpioWrite( &AntSwitch, 0 );
295         break;
296     }
297 }
298 
SX1276CheckRfFrequency(uint32_t frequency)299 bool SX1276CheckRfFrequency( uint32_t frequency )
300 {
301     // Implement check. Currently all frequencies are supported
302     return true;
303 }
304 
SX1276GetDio1PinState(void)305 uint32_t SX1276GetDio1PinState( void )
306 {
307     return GpioRead( &SX1276.DIO1 );
308 }
309 
310 #if defined( USE_RADIO_DEBUG )
SX1276DbgPinTxWrite(uint8_t state)311 void SX1276DbgPinTxWrite( uint8_t state )
312 {
313     GpioWrite( &DbgPinTx, state );
314 }
315 
SX1276DbgPinRxWrite(uint8_t state)316 void SX1276DbgPinRxWrite( uint8_t state )
317 {
318     GpioWrite( &DbgPinRx, state );
319 }
320 #endif
321