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 <string.h>
25 #include "board.h"
26 #include "radio.h"
27 #include "ulog/ulog.h"
28 #include "sx126x-board.h"
29 #include <drivers/u_ld.h>
30 #include <vfsdev/spi_dev.h>
31 #include <vfsdev/gpio_dev.h>
32 #include <devicevfs/devicevfs.h>
33 #include <drivers/char/u_device.h>
34 #include "aos/hal/gpio.h"
35 /*!
36  * \brief Holds the internal operating mode of the radio
37  */
38 static RadioOperatingModes_t OperatingMode;
39 
40 static int g_gpio_fd = 0;
41 
42 #define NSS_CRT(up) if (up == 1) {                                                      \
43                         SX126x.NSS.data = 1;                                            \
44                         ioctl(g_gpio_fd, IOC_GPIO_SET, (unsigned long)&SX126x.NSS);     \
45                     } else if (up == 0) {                                               \
46                         SX126x.NSS.data = 0;                                            \
47                         ioctl(g_gpio_fd, IOC_GPIO_SET, (unsigned long)&SX126x.NSS);     \
48                     } else {                                                            \
49                         LOG("invalid nss ctr\n");                                       \
50                     }
51 
52 #define SPI_SANITY_CHECK(ret) if(ret) {LOG("[%s][%d]spi err(%d)", __func__, __LINE__, ret); return;}
53 #define CRITICAL_SECTION_BEGIN()
54 #define CRITICAL_SECTION_END()
55 
SX126xIoInit(void)56 void SX126xIoInit( void )
57 {
58     memset(&SX126x, 0, sizeof(SX126x_t));
59 
60     SX126x.Spi = open("/dev/spi0", 0);
61     if (SX126x.Spi <= 0) {
62         LOG("[%s][%d]faild to open spi device!", __FUNCTION__, __LINE__);
63         return;
64     } else {
65         LOG("[%s][%d]succeed to open spi device(%d)!", __FUNCTION__, __LINE__, SX126x.Spi);
66     }
67 
68     int ret = ioctl(SX126x.Spi, IOC_SPI_SET_CFLAG, SPI_NO_CS | SPI_MODE_3 | SPI_MSB | SPI_TRANSFER_NORMAL_MODE | SPI_DATA_8BIT);
69     SPI_SANITY_CHECK(ret);
70 
71     ret = ioctl(SX126x.Spi, IOC_SPI_SET_FREQ, 2000000);
72     SPI_SANITY_CHECK(ret);
73 
74     g_gpio_fd = open("/dev/gpio", 0);
75 
76     SX126x.NSS.id = 22; //p2-6
77     SX126x.NSS.config = GPIO_IO_OUTPUT | GPIO_IO_OUTPUT_PP;
78 
79     SX126x.Reset.id = 33; //p4-1
80     SX126x.Reset.config=GPIO_IO_OUTPUT | GPIO_IO_OUTPUT_PP;
81 
82     SX126x.DIO1.id = 32; //p4-0
83 
84     SX126x.BUSY.id = 39; //p4-7
85     SX126x.BUSY.data = 0;
86     SX126x.BUSY.config=GPIO_IO_INPUT | GPIO_IO_INPUT_PD;
87 }
88 
SX126xIoIrqInit(DioIrqHandler dioIrq)89 void SX126xIoIrqInit( DioIrqHandler dioIrq )
90 {
91     SX126x.DIO1.config = GPIO_IRQ_CLEAR;
92 
93     int ret = ioctl(g_gpio_fd, IOC_GPIO_SET_IRQ, &SX126x.DIO1);
94     if (ret) {
95         LOG("clear gpio irq failed, ret %d", ret);
96         return;
97     }
98     SX126x.DIO1.config = GPIO_IRQ_DISABLE;
99     ret = ioctl(g_gpio_fd, IOC_GPIO_SET_IRQ, &SX126x.DIO1);
100     if (ret) {
101         LOG("clear gpio irq failed, ret %d", ret);
102         return;
103     }
104 
105     SX126x.DIO1.config = GPIO_IRQ_ENABLE | GPIO_IRQ_EDGE_RISING;
106     SX126x.DIO1.cb = dioIrq;
107     SX126x.DIO1.arg = NULL;
108 
109     ret = ioctl(g_gpio_fd, IOC_GPIO_SET_IRQ, &SX126x.DIO1);
110     if (ret) {
111         LOG("enable gpio irq failed, ret %d", ret);
112         return -1;
113     }
114 }
115 
SX126xIoDeInit(void)116 void SX126xIoDeInit( void )
117 {
118 }
119 
SX126xIoDbgInit(void)120 void SX126xIoDbgInit( void )
121 {
122 }
123 
SX126xIoTcxoInit(void)124 void SX126xIoTcxoInit( void )
125 {
126     // No TCXO component available on this board design.
127 }
128 
SX126xGetBoardTcxoWakeupTime(void)129 uint32_t SX126xGetBoardTcxoWakeupTime( void )
130 {
131     return 0;
132 }
133 
SX126xIoRfSwitchInit(void)134 void SX126xIoRfSwitchInit( void )
135 {
136     SX126xSetDio2AsRfSwitchCtrl( true );
137 }
138 
SX126xGetOperatingMode(void)139 RadioOperatingModes_t SX126xGetOperatingMode( void )
140 {
141     return OperatingMode;
142 }
143 
SX126xSetOperatingMode(RadioOperatingModes_t mode)144 void SX126xSetOperatingMode( RadioOperatingModes_t mode )
145 {
146     OperatingMode = mode;
147 }
148 
SX126xReset(void)149 void SX126xReset( void )
150 {
151     SX126x.Reset.data = 0;
152     ioctl(g_gpio_fd, IOC_GPIO_SET, (unsigned long)&SX126x.Reset);
153     usleep(500000);
154     SX126x.Reset.data = 1;
155     ioctl(g_gpio_fd, IOC_GPIO_SET, (unsigned long)&SX126x.Reset);
156 }
157 
SX126xWaitOnBusy(void)158 void SX126xWaitOnBusy( void )
159 {
160     int32_t ret = 0;
161     uint32_t busy = 1;
162     while(0 == ret) {
163         if (busy) {
164             usleep(5000);
165         } else {
166             break;
167         }
168         busy = ioctl(g_gpio_fd, IOC_GPIO_GET,  (unsigned long)&SX126x.BUSY);
169     }
170 }
171 
SpiInOut(uint8_t cmd)172 uint8_t SpiInOut(uint8_t cmd) {
173     uint8_t ack = 0;
174     ioc_spi_transfer_t t = {.rx_buf = &ack, .rx_size = 1, .tx_buf = &cmd, .tx_size = 1};
175     int ret = ioctl(SX126x.Spi, IOC_SPI_SEND_RECV, &t);
176     SPI_SANITY_CHECK(ret)
177     return ack;
178 }
179 
SpiOut(uint8_t cmd)180 void SpiOut(uint8_t cmd) {
181     write(SX126x.Spi, &cmd, 1);
182     usleep(10);
183 }
184 
SpiIn(uint8_t * ack)185 void SpiIn(uint8_t *ack) {
186     read(SX126x.Spi, ack, 1);
187 }
188 
SX126xWakeup(void)189 void SX126xWakeup( void )
190 {
191     CRITICAL_SECTION_BEGIN( );
192     int32_t ret = 0;
193 
194     NSS_CRT( 0 );
195     SpiOut( RADIO_GET_STATUS );
196     RadioStatus_t status = (RadioStatus_t)SpiInOut( 0x00 );
197     // LOG("[%s]chip mode:%d  command status:%d\n", __func__, status.Fields.ChipMode, status.Fields.CmdStatus);
198     NSS_CRT( 1 );
199     // Wait for chip to be ready.
200     SX126xWaitOnBusy( );
201     // Update operating mode context variable
202     SX126xSetOperatingMode( MODE_STDBY_RC );
203 
204     CRITICAL_SECTION_END( );
205 }
206 
SX126xWriteCommand(RadioCommands_t command,uint8_t * buffer,uint16_t size)207 void SX126xWriteCommand( RadioCommands_t command, uint8_t *buffer, uint16_t size )
208 {
209     int32_t ret = 0;
210 
211     SX126xCheckDeviceReady( );
212 
213     NSS_CRT( 0 );
214 
215     SpiOut( ( uint8_t )command );
216 
217     for( uint16_t i = 0; i < size; i++ )
218     {
219         SpiOut( buffer[i] );
220     }
221 
222     NSS_CRT( 1 );
223 
224     if( command != RADIO_SET_SLEEP )
225     {
226         SX126xWaitOnBusy( );
227     }
228 }
229 
SX126xReadCommand(RadioCommands_t command,uint8_t * buffer,uint16_t size)230 uint8_t SX126xReadCommand( RadioCommands_t command, uint8_t *buffer, uint16_t size )
231 {
232     int32_t ret = 0;
233     uint8_t status = 0;
234 
235     SX126xCheckDeviceReady( );
236 
237     NSS_CRT( 0 );
238 
239     SpiOut( ( uint8_t )command );
240     if (command == RADIO_GET_STATUS)
241     {
242         status = SpiInOut( 0x00 );
243     }
244     else
245     {
246         SpiOut( 0x00 );
247     }
248     for( uint16_t i = 0; i < size; i++ )
249     {
250         if (command == RADIO_GET_RXBUFFERSTATUS) {
251             SpiIn( buffer+i );
252         } else {
253             buffer[i] = SpiInOut( 0 );
254         }
255     }
256 
257     NSS_CRT( 1 );
258 
259     SX126xWaitOnBusy( );
260 
261     return status;
262 }
263 
SX126xWriteRegisters(uint16_t address,uint8_t * buffer,uint16_t size)264 void SX126xWriteRegisters( uint16_t address, uint8_t *buffer, uint16_t size )
265 {
266     int32_t ret = 0;
267     SX126xCheckDeviceReady( );
268 
269     NSS_CRT( 0 );
270 
271     SpiOut( RADIO_WRITE_REGISTER );
272     SpiOut( ( address & 0xFF00 ) >> 8 );
273     SpiOut( address & 0x00FF );
274 
275     for( uint16_t i = 0; i < size; i++ )
276     {
277         SpiOut( buffer[i] );
278     }
279 
280     NSS_CRT( 1 );
281 
282     SX126xWaitOnBusy( );
283 }
284 
SX126xWriteRegister(uint16_t address,uint8_t value)285 void SX126xWriteRegister( uint16_t address, uint8_t value )
286 {
287     SX126xWriteRegisters( address, &value, 1 );
288 }
289 
SX126xReadRegisters(uint16_t address,uint8_t * buffer,uint16_t size)290 void SX126xReadRegisters( uint16_t address, uint8_t *buffer, uint16_t size )
291 {
292     int32_t ret = 0;
293     SX126xCheckDeviceReady( );
294 
295     NSS_CRT( 0 );
296 
297     SpiOut( RADIO_READ_REGISTER );
298     SpiOut( ( address & 0xFF00 ) >> 8 );
299     SpiOut( address & 0x00FF );
300     SpiOut( 0 );
301     for( uint16_t i = 0; i < size; i++ )
302     {
303         //buffer[i] = SpiInOut( 0 );
304         SpiIn(buffer+i);
305     }
306 
307     NSS_CRT( 1 );
308 
309     SX126xWaitOnBusy( );
310 }
311 
SX126xReadRegister(uint16_t address)312 uint8_t SX126xReadRegister( uint16_t address )
313 {
314     uint8_t data;
315     SX126xReadRegisters( address, &data, 1 );
316     return data;
317 }
318 
SX126xWriteBuffer(uint8_t offset,uint8_t * buffer,uint8_t size)319 void SX126xWriteBuffer( uint8_t offset, uint8_t *buffer, uint8_t size )
320 {
321     int32_t ret = 0;
322     SX126xCheckDeviceReady( );
323 
324     NSS_CRT( 0 );
325 
326     SpiOut( RADIO_WRITE_BUFFER );
327     SpiOut( offset );
328     for( uint16_t i = 0; i < size; i++ )
329     {
330         SpiOut( buffer[i] );
331     }
332 
333     NSS_CRT( 1 );
334 
335     SX126xWaitOnBusy( );
336 }
337 
SX126xReadBuffer(uint8_t offset,uint8_t * buffer,uint8_t size)338 void SX126xReadBuffer( uint8_t offset, uint8_t *buffer, uint8_t size )
339 {
340     int32_t ret = 0;
341     SX126xCheckDeviceReady( );
342 
343     NSS_CRT( 0 );
344 
345     SpiOut( RADIO_READ_BUFFER );
346     SpiOut( offset );
347     SpiOut( 0 );
348     for( uint16_t i = 0; i < size; i++ )
349     {
350         SpiIn(buffer+i);
351     }
352 
353     NSS_CRT( 1 );
354 
355     SX126xWaitOnBusy( );
356 }
357 
SX126xSetRfTxPower(int8_t power)358 void SX126xSetRfTxPower( int8_t power )
359 {
360     SX126xSetTxParams( power, RADIO_RAMP_40_US );
361 }
362 
SX126xGetDeviceId(void)363 uint8_t SX126xGetDeviceId( void )
364 {
365     return SX1262;
366 }
367 
SX126xAntSwOn(void)368 void SX126xAntSwOn( void )
369 {
370 
371 }
372 
SX126xAntSwOff(void)373 void SX126xAntSwOff( void )
374 {
375 
376 }
377 
SX126xCheckRfFrequency(uint32_t frequency)378 bool SX126xCheckRfFrequency( uint32_t frequency )
379 {
380     // Implement check. Currently all frequencies are supported
381     return true;
382 }
383