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