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  * Flag used to set the RF switch control pins in low power mode when the radio is not active.
32  */
33 static bool RadioIsActive = false;
34 
35 /*!
36  * Radio driver structure initialization
37  */
38 const struct Radio_s Radio =
39 {
40     SX1272Init,
41     SX1272GetStatus,
42     SX1272SetModem,
43     SX1272SetChannel,
44     SX1272IsChannelFree,
45     SX1272Random,
46     SX1272SetRxConfig,
47     SX1272SetTxConfig,
48     SX1272CheckRfFrequency,
49     SX1272GetTimeOnAir,
50     SX1272Send,
51     SX1272SetSleep,
52     SX1272SetStby,
53     SX1272SetRx,
54     SX1272StartCad,
55     SX1272SetTxContinuousWave,
56     SX1272ReadRssi,
57     SX1272Write,
58     SX1272Read,
59     SX1272WriteBuffer,
60     SX1272ReadBuffer,
61     SX1272SetMaxPayloadLength,
62     SX1272SetPublicNetwork,
63     SX1272GetWakeupTime,
64     NULL, // void ( *IrqProcess )( void )
65     NULL, // void ( *RxBoosted )( uint32_t timeout ) - SX126x Only
66     NULL, // void ( *SetRxDutyCycle )( uint32_t rxTime, uint32_t sleepTime ) - SX126x Only
67 };
68 
69 /*!
70  * Antenna switch GPIO pins objects
71  */
72 Gpio_t RadioSwitchCtrl1;
73 Gpio_t RadioSwitchCtrl2;
74 Gpio_t RadioPwrAmpCtrl;
75 
76 /*!
77  * Debug GPIO pins objects
78  */
79 #if defined( USE_RADIO_DEBUG )
80 Gpio_t DbgPinTx;
81 Gpio_t DbgPinRx;
82 #endif
83 
84 /*
85        PD_2=0  PD_2=1
86 op PaB  rfo     rfo
87 0  4.6  18.5    27.0
88 1  5.6  21.1    28.1
89 2  6.7  23.3    29.1
90 3  7.7  25.3    30.1
91 4  8.8  26.2    30.7
92 5  9.8  27.3    31.2
93 6  10.7 28.1    31.6
94 7  11.7 28.6    32.2
95 8  12.8 29.2    32.4
96 9  13.7 29.9    32.9
97 10 14.7 30.5    33.1
98 11 15.6 30.8    33.4
99 12 16.4 30.9    33.6
100 13 17.1 31.0    33.7
101 14 17.8 31.1    33.7
102 15 18.4 31.1    33.7
103 */
104 //                           txpow:   0  1  2  3  4  5  6  7  8  9 10 11 12 13 14  15  16  17  18  19
105 static const uint8_t PaBTable[20] = { 0, 0, 0, 0, 0, 1, 2, 3, 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 14, 15 };
106 
107 //                           txpow:  20 21 22 23 24 25 26 27 28 29 30
108 static const uint8_t RfoTable[11] = { 1, 1, 1, 2, 2, 3, 4, 5, 6, 8, 9 };
109 
SX1272IoInit(void)110 void SX1272IoInit( void )
111 {
112     GpioInit( &SX1272.Spi.Nss, RADIO_NSS, PIN_OUTPUT, PIN_PUSH_PULL, PIN_NO_PULL, 1 );
113 
114     GpioInit( &SX1272.DIO0, RADIO_DIO_0, PIN_INPUT, PIN_PUSH_PULL, PIN_PULL_UP, 0 );
115     GpioInit( &SX1272.DIO1, RADIO_DIO_1, PIN_INPUT, PIN_PUSH_PULL, PIN_PULL_UP, 0 );
116     GpioInit( &SX1272.DIO2, RADIO_DIO_2, PIN_INPUT, PIN_PUSH_PULL, PIN_PULL_UP, 0 );
117     GpioInit( &SX1272.DIO3, RADIO_DIO_3, PIN_INPUT, PIN_PUSH_PULL, PIN_PULL_UP, 0 );
118     GpioInit( &SX1272.DIO4, RADIO_DIO_4, PIN_INPUT, PIN_PUSH_PULL, PIN_PULL_UP, 0 );
119     GpioInit( &SX1272.DIO5, RADIO_DIO_5, PIN_INPUT, PIN_PUSH_PULL, PIN_PULL_UP, 0 );
120 }
121 
SX1272IoIrqInit(DioIrqHandler ** irqHandlers)122 void SX1272IoIrqInit( DioIrqHandler **irqHandlers )
123 {
124     GpioSetInterrupt( &SX1272.DIO0, IRQ_RISING_EDGE, IRQ_HIGH_PRIORITY, irqHandlers[0] );
125     GpioSetInterrupt( &SX1272.DIO1, IRQ_RISING_FALLING_EDGE, IRQ_HIGH_PRIORITY, irqHandlers[1] );
126     GpioSetInterrupt( &SX1272.DIO2, IRQ_RISING_EDGE, IRQ_HIGH_PRIORITY, irqHandlers[2] );
127     GpioSetInterrupt( &SX1272.DIO3, IRQ_RISING_EDGE, IRQ_HIGH_PRIORITY, irqHandlers[3] );
128     GpioSetInterrupt( &SX1272.DIO4, IRQ_RISING_EDGE, IRQ_HIGH_PRIORITY, irqHandlers[4] );
129     GpioSetInterrupt( &SX1272.DIO5, IRQ_RISING_EDGE, IRQ_HIGH_PRIORITY, irqHandlers[5] );
130 }
131 
SX1272IoDeInit(void)132 void SX1272IoDeInit( void )
133 {
134     GpioInit( &SX1272.Spi.Nss, RADIO_NSS, PIN_OUTPUT, PIN_PUSH_PULL, PIN_NO_PULL, 1 );
135 
136     GpioInit( &SX1272.DIO0, RADIO_DIO_0, PIN_INPUT, PIN_PUSH_PULL, PIN_NO_PULL, 0 );
137     GpioInit( &SX1272.DIO1, RADIO_DIO_1, PIN_INPUT, PIN_PUSH_PULL, PIN_NO_PULL, 0 );
138     GpioInit( &SX1272.DIO2, RADIO_DIO_2, PIN_INPUT, PIN_PUSH_PULL, PIN_NO_PULL, 0 );
139     GpioInit( &SX1272.DIO3, RADIO_DIO_3, PIN_INPUT, PIN_PUSH_PULL, PIN_NO_PULL, 0 );
140     GpioInit( &SX1272.DIO4, RADIO_DIO_4, PIN_INPUT, PIN_PUSH_PULL, PIN_NO_PULL, 0 );
141     GpioInit( &SX1272.DIO5, RADIO_DIO_5, PIN_INPUT, PIN_PUSH_PULL, PIN_NO_PULL, 0 );
142 }
143 
SX1272IoDbgInit(void)144 void SX1272IoDbgInit( void )
145 {
146 #if defined( USE_RADIO_DEBUG )
147     GpioInit( &DbgPinTx, RADIO_DBG_PIN_TX, PIN_OUTPUT, PIN_PUSH_PULL, PIN_NO_PULL, 0 );
148     GpioInit( &DbgPinRx, RADIO_DBG_PIN_RX, PIN_OUTPUT, PIN_PUSH_PULL, PIN_NO_PULL, 0 );
149 #endif
150 }
151 
SX1272IoTcxoInit(void)152 void SX1272IoTcxoInit( void )
153 {
154     // No TCXO component available on this board design.
155 }
156 
SX1272SetBoardTcxo(uint8_t state)157 void SX1272SetBoardTcxo( uint8_t state )
158 {
159     // No TCXO component available on this board design.
160 #if 0
161     if( state == true )
162     {
163         TCXO_ON( );
164         DelayMs( BOARD_TCXO_WAKEUP_TIME );
165     }
166     else
167     {
168         TCXO_OFF( );
169     }
170 #endif
171 }
172 
SX1272GetBoardTcxoWakeupTime(void)173 uint32_t SX1272GetBoardTcxoWakeupTime( void )
174 {
175     return BOARD_TCXO_WAKEUP_TIME;
176 }
177 
SX1272Reset(void)178 void SX1272Reset( void )
179 {
180     // Enables the TCXO if available on the board design
181     SX1272SetBoardTcxo( true );
182 
183     // Set RESET pin to 1
184     GpioInit( &SX1272.Reset, RADIO_RESET, PIN_OUTPUT, PIN_PUSH_PULL, PIN_NO_PULL, 1 );
185 
186     // Wait 1 ms
187     DelayMs( 1 );
188 
189     // Configure RESET as input
190     GpioInit( &SX1272.Reset, RADIO_RESET, PIN_INPUT, PIN_PUSH_PULL, PIN_NO_PULL, 1 );
191 
192     // Wait 6 ms
193     DelayMs( 6 );
194 }
195 
SX1272SetRfTxPower(int8_t power)196 void SX1272SetRfTxPower( int8_t power )
197 {
198     uint8_t paConfig = 0;
199     uint8_t paDac = 0;
200 
201     paConfig = Radio.Read( REG_PACONFIG );
202     paDac = Radio.Read( REG_PADAC );
203 
204     if( power > 19 )
205     {
206         paConfig = ( paConfig & RF_PACONFIG_PASELECT_MASK ) | RF_PACONFIG_PASELECT_RFO;
207         paConfig = ( paConfig & RFLR_PACONFIG_OUTPUTPOWER_MASK ) | RfoTable[power - 20];
208     }
209     else
210     {
211         paConfig = ( paConfig & RF_PACONFIG_PASELECT_MASK ) | RF_PACONFIG_PASELECT_PABOOST;
212         paConfig = ( paConfig & RFLR_PACONFIG_OUTPUTPOWER_MASK ) | PaBTable[MAX( power, 0 )];
213     }
214     Radio.Write( REG_PACONFIG, paConfig );
215     Radio.Write( REG_PADAC, paDac );
216 }
217 
SX1272SetAntSwLowPower(bool status)218 void SX1272SetAntSwLowPower( bool status )
219 {
220     if( RadioIsActive != status )
221     {
222         RadioIsActive = status;
223 
224         if( status == false )
225         {
226             SX1272AntSwInit( );
227         }
228         else
229         {
230             SX1272AntSwDeInit( );
231         }
232     }
233 }
234 
SX1272AntSwInit(void)235 void SX1272AntSwInit( void )
236 {
237     GpioInit( &RadioSwitchCtrl1, RADIO_SWITCH_CTRL1, PIN_OUTPUT, PIN_PUSH_PULL, PIN_PULL_UP, 0 );
238     GpioInit( &RadioSwitchCtrl2, RADIO_SWITCH_CTRL2, PIN_OUTPUT, PIN_PUSH_PULL, PIN_PULL_UP, 0 );
239     GpioInit( &RadioPwrAmpCtrl , RADIO_PWRAMP_CTRL , PIN_OUTPUT, PIN_PUSH_PULL, PIN_PULL_UP, 0 );
240 }
241 
SX1272AntSwDeInit(void)242 void SX1272AntSwDeInit( void )
243 {
244     GpioInit( &RadioSwitchCtrl1, RADIO_SWITCH_CTRL1, PIN_OUTPUT, PIN_PUSH_PULL, PIN_PULL_UP, 0 );
245     GpioInit( &RadioSwitchCtrl2, RADIO_SWITCH_CTRL2, PIN_OUTPUT, PIN_PUSH_PULL, PIN_PULL_UP, 0 );
246     GpioInit( &RadioPwrAmpCtrl , RADIO_PWRAMP_CTRL , PIN_OUTPUT, PIN_PUSH_PULL, PIN_PULL_UP, 0 );
247 }
248 
SX1272SetAntSw(uint8_t opMode)249 void SX1272SetAntSw( uint8_t opMode )
250 {
251     switch( opMode )
252     {
253     case RFLR_OPMODE_TRANSMITTER:
254         if( ( Radio.Read( REG_PACONFIG ) & RF_PACONFIG_PASELECT_PABOOST ) == RF_PACONFIG_PASELECT_PABOOST )
255         {
256             GpioWrite( &RadioSwitchCtrl1, 1 );
257             GpioWrite( &RadioSwitchCtrl2, 0 );
258         }
259         else
260         {
261             GpioWrite( &RadioSwitchCtrl1, 0 );
262             GpioWrite( &RadioSwitchCtrl2, 1 );
263         }
264         break;
265     case RFLR_OPMODE_RECEIVER:
266     case RFLR_OPMODE_RECEIVER_SINGLE:
267     case RFLR_OPMODE_CAD:
268         GpioWrite( &RadioSwitchCtrl1, 1 );
269         GpioWrite( &RadioSwitchCtrl2, 1 );
270         break;
271     default:
272         GpioWrite( &RadioSwitchCtrl1, 0 );
273         GpioWrite( &RadioSwitchCtrl2, 0 );
274         GpioWrite( &RadioPwrAmpCtrl, 0 );
275         break;
276     }
277 }
278 
SX1272CheckRfFrequency(uint32_t frequency)279 bool SX1272CheckRfFrequency( uint32_t frequency )
280 {
281     // Implement check. Currently all frequencies are supported
282     return true;
283 }
284 
SX1272GetDio1PinState(void)285 uint32_t SX1272GetDio1PinState( void )
286 {
287     return GpioRead( &SX1272.DIO1 );
288 }
289 
290 #if defined( USE_RADIO_DEBUG )
SX1272DbgPinTxWrite(uint8_t state)291 void SX1272DbgPinTxWrite( uint8_t state )
292 {
293     GpioWrite( &DbgPinTx, state );
294 }
295 
SX1272DbgPinRxWrite(uint8_t state)296 void SX1272DbgPinRxWrite( uint8_t state )
297 {
298     GpioWrite( &DbgPinRx, state );
299 }
300 #endif
301