1 /*!
2  * \file      sx1272-board.c
3  *
4  * \brief     Target board SX1272 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 "sx1272-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 SX1272GetPaSelect( 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     SX1272Init,
49     SX1272GetStatus,
50     SX1272SetModem,
51     SX1272SetChannel,
52     SX1272IsChannelFree,
53     SX1272Random,
54     SX1272SetRxConfig,
55     SX1272SetTxConfig,
56     SX1272CheckRfFrequency,
57     SX1272GetTimeOnAir,
58     SX1272Send,
59     SX1272SetSleep,
60     SX1272SetStby,
61     SX1272SetRx,
62     SX1272StartCad,
63     SX1272SetTxContinuousWave,
64     SX1272ReadRssi,
65     SX1272Write,
66     SX1272Read,
67     SX1272WriteBuffer,
68     SX1272ReadBuffer,
69     SX1272SetMaxPayloadLength,
70     SX1272SetPublicNetwork,
71     SX1272GetWakeupTime,
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 AntTx;
81 Gpio_t AntRx;
82 
83 /*!
84  * Debug GPIO pins objects
85  */
86 #if defined( USE_RADIO_DEBUG )
87 Gpio_t DbgPinTx;
88 Gpio_t DbgPinRx;
89 #endif
90 
SX1272IoInit(void)91 void SX1272IoInit( void )
92 {
93     GpioInit( &SX1272.Spi.Nss, RADIO_NSS, PIN_OUTPUT, PIN_PUSH_PULL, PIN_NO_PULL, 1 );
94 
95     GpioInit( &SX1272.DIO0, RADIO_DIO_0, PIN_INPUT, PIN_PUSH_PULL, PIN_PULL_UP, 0 );
96     GpioInit( &SX1272.DIO1, RADIO_DIO_1, PIN_INPUT, PIN_PUSH_PULL, PIN_PULL_UP, 0 );
97     GpioInit( &SX1272.DIO2, RADIO_DIO_2, PIN_INPUT, PIN_PUSH_PULL, PIN_PULL_UP, 0 );
98     GpioInit( &SX1272.DIO3, RADIO_DIO_3, PIN_INPUT, PIN_PUSH_PULL, PIN_PULL_UP, 0 );
99     // DIO4 and DIO5 aren't connected.
100     // Initialize Gpio_t port to NULL.
101     SX1272.DIO4.port = NULL;
102     SX1272.DIO5.port = NULL;
103 }
104 
SX1272IoIrqInit(DioIrqHandler ** irqHandlers)105 void SX1272IoIrqInit( DioIrqHandler **irqHandlers )
106 {
107     GpioSetInterrupt( &SX1272.DIO0, IRQ_RISING_EDGE, IRQ_HIGH_PRIORITY, irqHandlers[0] );
108     GpioSetInterrupt( &SX1272.DIO1, IRQ_RISING_FALLING_EDGE, IRQ_HIGH_PRIORITY, irqHandlers[1] );
109     GpioSetInterrupt( &SX1272.DIO2, IRQ_RISING_EDGE, IRQ_HIGH_PRIORITY, irqHandlers[2] );
110     GpioSetInterrupt( &SX1272.DIO3, IRQ_RISING_EDGE, IRQ_HIGH_PRIORITY, irqHandlers[3] );
111 }
112 
SX1272IoDeInit(void)113 void SX1272IoDeInit( void )
114 {
115     GpioInit( &SX1272.Spi.Nss, RADIO_NSS, PIN_OUTPUT, PIN_PUSH_PULL, PIN_NO_PULL, 1 );
116 
117     GpioInit( &SX1272.DIO0, RADIO_DIO_0, PIN_INPUT, PIN_PUSH_PULL, PIN_NO_PULL, 0 );
118     GpioInit( &SX1272.DIO1, RADIO_DIO_1, PIN_INPUT, PIN_PUSH_PULL, PIN_NO_PULL, 0 );
119     GpioInit( &SX1272.DIO2, RADIO_DIO_2, PIN_INPUT, PIN_PUSH_PULL, PIN_NO_PULL, 0 );
120     GpioInit( &SX1272.DIO3, RADIO_DIO_3, PIN_INPUT, PIN_PUSH_PULL, PIN_NO_PULL, 0 );
121 }
122 
SX1272IoDbgInit(void)123 void SX1272IoDbgInit( void )
124 {
125 #if defined( USE_RADIO_DEBUG )
126     GpioInit( &DbgPinTx, RADIO_DBG_PIN_TX, PIN_OUTPUT, PIN_PUSH_PULL, PIN_NO_PULL, 0 );
127     GpioInit( &DbgPinRx, RADIO_DBG_PIN_RX, PIN_OUTPUT, PIN_PUSH_PULL, PIN_NO_PULL, 0 );
128 #endif
129 }
130 
SX1272IoTcxoInit(void)131 void SX1272IoTcxoInit( void )
132 {
133     // No TCXO component available on this board design.
134 }
135 
SX1272SetBoardTcxo(uint8_t state)136 void SX1272SetBoardTcxo( uint8_t state )
137 {
138     // No TCXO component available on this board design.
139 #if 0
140     if( state == true )
141     {
142         TCXO_ON( );
143         DelayMs( BOARD_TCXO_WAKEUP_TIME );
144     }
145     else
146     {
147         TCXO_OFF( );
148     }
149 #endif
150 }
151 
SX1272GetBoardTcxoWakeupTime(void)152 uint32_t SX1272GetBoardTcxoWakeupTime( void )
153 {
154     return BOARD_TCXO_WAKEUP_TIME;
155 }
156 
SX1272Reset(void)157 void SX1272Reset( void )
158 {
159     // Enables the TCXO if available on the board design
160     SX1272SetBoardTcxo( true );
161 
162     // Set RESET pin to 1
163     GpioInit( &SX1272.Reset, RADIO_RESET, PIN_OUTPUT, PIN_PUSH_PULL, PIN_NO_PULL, 1 );
164 
165     // Wait 1 ms
166     DelayMs( 1 );
167 
168     // Configure RESET as input
169     GpioInit( &SX1272.Reset, RADIO_RESET, PIN_INPUT, PIN_PUSH_PULL, PIN_NO_PULL, 1 );
170 
171     // Wait 6 ms
172     DelayMs( 6 );
173 }
174 
SX1272SetRfTxPower(int8_t power)175 void SX1272SetRfTxPower( int8_t power )
176 {
177     uint8_t paConfig = 0;
178     uint8_t paDac = 0;
179 
180     paConfig = SX1272Read( REG_PACONFIG );
181     paDac = SX1272Read( REG_PADAC );
182 
183     paConfig = ( paConfig & RF_PACONFIG_PASELECT_MASK ) | SX1272GetPaSelect( SX1272.Settings.Channel );
184 
185     if( ( paConfig & RF_PACONFIG_PASELECT_PABOOST ) == RF_PACONFIG_PASELECT_PABOOST )
186     {
187         if( power > 17 )
188         {
189             paDac = ( paDac & RF_PADAC_20DBM_MASK ) | RF_PADAC_20DBM_ON;
190         }
191         else
192         {
193             paDac = ( paDac & RF_PADAC_20DBM_MASK ) | RF_PADAC_20DBM_OFF;
194         }
195         if( ( paDac & RF_PADAC_20DBM_ON ) == RF_PADAC_20DBM_ON )
196         {
197             if( power < 5 )
198             {
199                 power = 5;
200             }
201             if( power > 20 )
202             {
203                 power = 20;
204             }
205             paConfig = ( paConfig & RFLR_PACONFIG_OUTPUTPOWER_MASK ) | ( uint8_t )( ( uint16_t )( power - 5 ) & 0x0F );
206         }
207         else
208         {
209             if( power < 2 )
210             {
211                 power = 2;
212             }
213             if( power > 17 )
214             {
215                 power = 17;
216             }
217             paConfig = ( paConfig & RFLR_PACONFIG_OUTPUTPOWER_MASK ) | ( uint8_t )( ( uint16_t )( power - 2 ) & 0x0F );
218         }
219     }
220     else
221     {
222         if( power < -1 )
223         {
224             power = -1;
225         }
226         if( power > 14 )
227         {
228             power = 14;
229         }
230         paConfig = ( paConfig & RFLR_PACONFIG_OUTPUTPOWER_MASK ) | ( uint8_t )( ( uint16_t )( power + 1 ) & 0x0F );
231     }
232     SX1272Write( REG_PACONFIG, paConfig );
233     SX1272Write( REG_PADAC, paDac );
234 }
235 
SX1272GetPaSelect(uint32_t channel)236 static uint8_t SX1272GetPaSelect( uint32_t channel )
237 {
238     return RF_PACONFIG_PASELECT_RFO;
239 }
240 
SX1272SetAntSwLowPower(bool status)241 void SX1272SetAntSwLowPower( bool status )
242 {
243     if( RadioIsActive != status )
244     {
245         RadioIsActive = status;
246 
247         if( status == false )
248         {
249             SX1272AntSwInit( );
250         }
251         else
252         {
253             SX1272AntSwDeInit( );
254         }
255     }
256 }
257 
SX1272AntSwInit(void)258 void SX1272AntSwInit( void )
259 {
260     GpioInit( &AntTx, RADIO_ANT_SWITCH_TX, PIN_OUTPUT, PIN_PUSH_PULL, PIN_PULL_UP, 0 );
261     GpioInit( &AntRx, RADIO_ANT_SWITCH_RX, PIN_OUTPUT, PIN_PUSH_PULL, PIN_PULL_UP, 1 );
262 }
263 
SX1272AntSwDeInit(void)264 void SX1272AntSwDeInit( void )
265 {
266     GpioInit( &AntTx, RADIO_ANT_SWITCH_TX, PIN_ANALOGIC, PIN_PUSH_PULL, PIN_NO_PULL, 0 );
267     GpioInit( &AntRx, RADIO_ANT_SWITCH_RX, PIN_ANALOGIC, PIN_PUSH_PULL, PIN_NO_PULL, 0 );
268 }
269 
SX1272SetAntSw(uint8_t opMode)270 void SX1272SetAntSw( uint8_t opMode )
271 {
272     switch( opMode )
273     {
274     case RFLR_OPMODE_TRANSMITTER:
275         GpioWrite( &AntTx, 1 );
276         GpioWrite( &AntRx, 0 );
277         break;
278     case RFLR_OPMODE_RECEIVER:
279     case RFLR_OPMODE_RECEIVER_SINGLE:
280     case RFLR_OPMODE_CAD:
281     default:
282         GpioWrite( &AntTx, 0 );
283         GpioWrite( &AntRx, 1 );
284         break;
285     }
286 }
287 
SX1272CheckRfFrequency(uint32_t frequency)288 bool SX1272CheckRfFrequency( uint32_t frequency )
289 {
290     // Implement check. Currently all frequencies are supported
291     return true;
292 }
293 
SX1272GetDio1PinState(void)294 uint32_t SX1272GetDio1PinState( void )
295 {
296     return GpioRead( &SX1272.DIO1 );
297 }
298 
299 #if defined( USE_RADIO_DEBUG )
SX1272DbgPinTxWrite(uint8_t state)300 void SX1272DbgPinTxWrite( uint8_t state )
301 {
302     GpioWrite( &DbgPinTx, state );
303 }
304 
SX1272DbgPinRxWrite(uint8_t state)305 void SX1272DbgPinRxWrite( uint8_t state )
306 {
307     GpioWrite( &DbgPinRx, state );
308 }
309 #endif
310