1 /*
2  * Copyright (c) 2019 Manivannan Sadhasivam
3  * Copyright (c) 2020 Andreas Sandberg
4  *
5  * SPDX-License-Identifier: Apache-2.0
6  */
7 
8 #include <drivers/gpio.h>
9 #include <drivers/lora.h>
10 #include <drivers/spi.h>
11 #include <zephyr.h>
12 
13 #include <sx126x/sx126x.h>
14 
15 #include "sx12xx_common.h"
16 #include "sx126x_common.h"
17 
18 #include <logging/log.h>
19 LOG_MODULE_REGISTER(sx126x, CONFIG_LORA_LOG_LEVEL);
20 
21 BUILD_ASSERT(DT_NUM_INST_STATUS_OKAY(semtech_sx1261) +
22 	     DT_NUM_INST_STATUS_OKAY(semtech_sx1262) +
23 	     DT_NUM_INST_STATUS_OKAY(st_stm32wl_subghz_radio) <= 1,
24 	     "Multiple SX126x instances in DT");
25 
26 #define DIO2_TX_ENABLE DT_INST_PROP(0, dio2_tx_enable)
27 
28 #define HAVE_DIO3_TCXO		DT_INST_NODE_HAS_PROP(0, dio3_tcxo_voltage)
29 #if HAVE_DIO3_TCXO
30 #define TCXO_DIO3_VOLTAGE	DT_INST_PROP(0, dio3_tcxo_voltage)
31 #endif
32 
33 #if DT_INST_NODE_HAS_PROP(0, tcxo_power_startup_delay_ms)
34 #define TCXO_POWER_STARTUP_DELAY_MS			\
35 	DT_INST_PROP(0, tcxo_power_startup_delay_ms)
36 #else
37 #define TCXO_POWER_STARTUP_DELAY_MS	0
38 #endif
39 
40 #define SX126X_CALIBRATION_ALL 0x7f
41 
42 static struct sx126x_data dev_data;
43 
44 void SX126xWaitOnBusy(void);
45 
46 #define MODE(m) [MODE_##m] = #m
47 static const char *const mode_names[] = {
48 	MODE(SLEEP),
49 	MODE(STDBY_RC),
50 	MODE(STDBY_XOSC),
51 	MODE(FS),
52 	MODE(TX),
53 	MODE(RX),
54 	MODE(RX_DC),
55 	MODE(CAD),
56 };
57 #undef MODE
58 
sx126x_mode_name(RadioOperatingModes_t m)59 static const char *sx126x_mode_name(RadioOperatingModes_t m)
60 {
61 	static const char *unknown_mode = "unknown";
62 
63 	if (m < ARRAY_SIZE(mode_names) && mode_names[m]) {
64 		return mode_names[m];
65 	} else {
66 		return unknown_mode;
67 	}
68 }
69 
sx126x_spi_transceive(uint8_t * req_tx,uint8_t * req_rx,size_t req_len,void * data_tx,void * data_rx,size_t data_len)70 static int sx126x_spi_transceive(uint8_t *req_tx, uint8_t *req_rx,
71 				 size_t req_len, void *data_tx, void *data_rx,
72 				 size_t data_len)
73 {
74 	int ret;
75 
76 	const struct spi_buf tx_buf[] = {
77 		{
78 			.buf = req_tx,
79 			.len = req_len,
80 		},
81 		{
82 			.buf = data_tx,
83 			.len = data_len
84 		}
85 	};
86 
87 	const struct spi_buf rx_buf[] = {
88 		{
89 			.buf = req_rx,
90 			.len = req_len,
91 		},
92 		{
93 			.buf = data_rx,
94 			.len = data_len
95 		}
96 	};
97 
98 	const struct spi_buf_set tx = {
99 		.buffers = tx_buf,
100 		.count = ARRAY_SIZE(tx_buf),
101 	};
102 
103 	const struct spi_buf_set rx = {
104 		.buffers = rx_buf,
105 		.count = ARRAY_SIZE(rx_buf)
106 	};
107 
108 	/* Wake the device if necessary */
109 	SX126xCheckDeviceReady();
110 
111 	if (!req_rx && !data_rx) {
112 		ret = spi_write(dev_data.spi, &dev_data.spi_cfg, &tx);
113 	} else {
114 		ret = spi_transceive(dev_data.spi, &dev_data.spi_cfg,
115 				     &tx, &rx);
116 	}
117 
118 	if (ret < 0) {
119 		LOG_ERR("SPI transaction failed: %i", ret);
120 	}
121 
122 	if (req_len >= 1 && req_tx[0] != RADIO_SET_SLEEP) {
123 		SX126xWaitOnBusy();
124 	}
125 	return ret;
126 }
127 
SX126xReadRegister(uint16_t address)128 uint8_t SX126xReadRegister(uint16_t address)
129 {
130 	uint8_t data;
131 
132 	SX126xReadRegisters(address, &data, 1);
133 
134 	return data;
135 }
136 
SX126xReadRegisters(uint16_t address,uint8_t * buffer,uint16_t size)137 void SX126xReadRegisters(uint16_t address, uint8_t *buffer, uint16_t size)
138 {
139 	uint8_t req[] = {
140 		RADIO_READ_REGISTER,
141 		(address >> 8) & 0xff,
142 		address & 0xff,
143 		0,
144 	};
145 
146 	LOG_DBG("Reading %" PRIu16 " registers @ 0x%" PRIx16, size, address);
147 	sx126x_spi_transceive(req, NULL, sizeof(req), NULL, buffer, size);
148 	LOG_HEXDUMP_DBG(buffer, size, "register_value");
149 }
150 
SX126xWriteRegister(uint16_t address,uint8_t value)151 void SX126xWriteRegister(uint16_t address, uint8_t value)
152 {
153 	SX126xWriteRegisters(address, &value, 1);
154 }
155 
SX126xWriteRegisters(uint16_t address,uint8_t * buffer,uint16_t size)156 void SX126xWriteRegisters(uint16_t address, uint8_t *buffer, uint16_t size)
157 {
158 	uint8_t req[] = {
159 		RADIO_WRITE_REGISTER,
160 		(address >> 8) & 0xff,
161 		address & 0xff,
162 	};
163 
164 	LOG_DBG("Writing %" PRIu16 " registers @ 0x%" PRIx16
165 		": 0x%" PRIx8 " , ...",
166 		size, address, buffer[0]);
167 	sx126x_spi_transceive(req, NULL, sizeof(req), buffer, NULL, size);
168 }
169 
SX126xReadCommand(RadioCommands_t opcode,uint8_t * buffer,uint16_t size)170 uint8_t SX126xReadCommand(RadioCommands_t opcode,
171 			  uint8_t *buffer, uint16_t size)
172 {
173 	uint8_t tx_req[] = {
174 		opcode,
175 		0x00,
176 	};
177 
178 	uint8_t rx_req[sizeof(tx_req)];
179 
180 	LOG_DBG("Issuing opcode 0x%x (data size: %" PRIx16 ")",
181 		opcode, size);
182 	sx126x_spi_transceive(tx_req, rx_req, sizeof(rx_req),
183 			      NULL, buffer, size);
184 	LOG_DBG("-> status: 0x%" PRIx8, rx_req[1]);
185 	return rx_req[1];
186 }
187 
SX126xWriteCommand(RadioCommands_t opcode,uint8_t * buffer,uint16_t size)188 void SX126xWriteCommand(RadioCommands_t opcode, uint8_t *buffer, uint16_t size)
189 {
190 	uint8_t req[] = {
191 		opcode,
192 	};
193 
194 	LOG_DBG("Issuing opcode 0x%x w. %" PRIu16 " bytes of data",
195 		opcode, size);
196 	sx126x_spi_transceive(req, NULL, sizeof(req), buffer, NULL, size);
197 }
198 
SX126xReadBuffer(uint8_t offset,uint8_t * buffer,uint8_t size)199 void SX126xReadBuffer(uint8_t offset, uint8_t *buffer, uint8_t size)
200 {
201 	uint8_t req[] = {
202 		RADIO_READ_BUFFER,
203 		offset,
204 		0x00,
205 	};
206 
207 	LOG_DBG("Reading buffers @ 0x%" PRIx8 " (%" PRIu8 " bytes)",
208 		offset, size);
209 	sx126x_spi_transceive(req, NULL, sizeof(req), NULL, buffer, size);
210 }
211 
SX126xWriteBuffer(uint8_t offset,uint8_t * buffer,uint8_t size)212 void SX126xWriteBuffer(uint8_t offset, uint8_t *buffer, uint8_t size)
213 {
214 	uint8_t req[] = {
215 		RADIO_WRITE_BUFFER,
216 		offset,
217 	};
218 
219 	LOG_DBG("Writing buffers @ 0x%" PRIx8 " (%" PRIu8 " bytes)",
220 		offset, size);
221 	sx126x_spi_transceive(req, NULL, sizeof(req), buffer, NULL, size);
222 }
223 
SX126xAntSwOn(void)224 void SX126xAntSwOn(void)
225 {
226 #if HAVE_GPIO_ANTENNA_ENABLE
227 	LOG_DBG("Enabling antenna switch");
228 	gpio_pin_set(dev_data.antenna_enable, GPIO_ANTENNA_ENABLE_PIN, 1);
229 #else
230 	LOG_DBG("No antenna switch configured");
231 #endif
232 }
233 
SX126xAntSwOff(void)234 void SX126xAntSwOff(void)
235 {
236 #if HAVE_GPIO_ANTENNA_ENABLE
237 	LOG_DBG("Disabling antenna switch");
238 	gpio_pin_set(dev_data.antenna_enable, GPIO_ANTENNA_ENABLE_PIN, 0);
239 #else
240 	LOG_DBG("No antenna switch configured");
241 #endif
242 }
243 
sx126x_set_tx_enable(int value)244 static void sx126x_set_tx_enable(int value)
245 {
246 #if HAVE_GPIO_TX_ENABLE
247 	gpio_pin_set(dev_data.tx_enable, GPIO_TX_ENABLE_PIN, value);
248 #endif
249 }
250 
sx126x_set_rx_enable(int value)251 static void sx126x_set_rx_enable(int value)
252 {
253 #if HAVE_GPIO_RX_ENABLE
254 	gpio_pin_set(dev_data.rx_enable, GPIO_RX_ENABLE_PIN, value);
255 #endif
256 }
257 
SX126xGetOperatingMode(void)258 RadioOperatingModes_t SX126xGetOperatingMode(void)
259 {
260 	return dev_data.mode;
261 }
262 
SX126xSetOperatingMode(RadioOperatingModes_t mode)263 void SX126xSetOperatingMode(RadioOperatingModes_t mode)
264 {
265 	LOG_DBG("SetOperatingMode: %s (%i)", sx126x_mode_name(mode), mode);
266 
267 	dev_data.mode = mode;
268 
269 	/* To avoid inadvertently putting the RF switch in an
270 	 * undefined state, first disable the port we don't want to
271 	 * use and then enable the other one.
272 	 */
273 	switch (mode) {
274 	case MODE_TX:
275 		sx126x_set_rx_enable(0);
276 		sx126x_set_tx_enable(1);
277 		break;
278 
279 	case MODE_RX:
280 	case MODE_RX_DC:
281 	case MODE_CAD:
282 		sx126x_set_tx_enable(0);
283 		sx126x_set_rx_enable(1);
284 		break;
285 
286 	case MODE_SLEEP:
287 		/* Additionally disable the DIO1 interrupt to save power */
288 		sx126x_dio1_irq_disable(&dev_data);
289 		__fallthrough;
290 	default:
291 		sx126x_set_rx_enable(0);
292 		sx126x_set_tx_enable(0);
293 		break;
294 	}
295 }
296 
SX126xGetBoardTcxoWakeupTime(void)297 uint32_t SX126xGetBoardTcxoWakeupTime(void)
298 {
299 	return TCXO_POWER_STARTUP_DELAY_MS;
300 }
301 
SX126xGetDeviceId(void)302 uint8_t SX126xGetDeviceId(void)
303 {
304 	return SX126X_DEVICE_ID;
305 }
306 
SX126xIoIrqInit(DioIrqHandler dioIrq)307 void SX126xIoIrqInit(DioIrqHandler dioIrq)
308 {
309 	LOG_DBG("Configuring DIO IRQ callback");
310 	dev_data.radio_dio_irq = dioIrq;
311 }
312 
SX126xIoTcxoInit(void)313 void SX126xIoTcxoInit(void)
314 {
315 #if HAVE_DIO3_TCXO
316 	CalibrationParams_t cal = {
317 		.Value = SX126X_CALIBRATION_ALL,
318 	};
319 
320 	LOG_DBG("TCXO on DIO3");
321 
322 	/* Delay in units of 15.625 us (1/64 ms) */
323 	SX126xSetDio3AsTcxoCtrl(TCXO_DIO3_VOLTAGE,
324 				TCXO_POWER_STARTUP_DELAY_MS << 6);
325 	SX126xCalibrate(cal);
326 #else
327 	LOG_DBG("No TCXO configured");
328 #endif
329 }
330 
SX126xIoRfSwitchInit(void)331 void SX126xIoRfSwitchInit(void)
332 {
333 	LOG_DBG("Configuring DIO2");
334 	SX126xSetDio2AsRfSwitchCtrl(DIO2_TX_ENABLE);
335 }
336 
SX126xReset(void)337 void SX126xReset(void)
338 {
339 	LOG_DBG("Resetting radio");
340 
341 	sx126x_reset(&dev_data);
342 
343 	/* Device transitions to standby on reset */
344 	dev_data.mode = MODE_STDBY_RC;
345 }
346 
SX126xSetRfTxPower(int8_t power)347 void SX126xSetRfTxPower(int8_t power)
348 {
349 	LOG_DBG("power: %" PRIi8, power);
350 	SX126xSetTxParams(power, RADIO_RAMP_40_US);
351 }
352 
SX126xWaitOnBusy(void)353 void SX126xWaitOnBusy(void)
354 {
355 	while (sx126x_is_busy(&dev_data)) {
356 		k_sleep(K_MSEC(1));
357 	}
358 }
359 
SX126xWakeup(void)360 void SX126xWakeup(void)
361 {
362 	int ret;
363 
364 	/* Reenable DIO1 when waking up */
365 	sx126x_dio1_irq_enable(&dev_data);
366 
367 	uint8_t req[] = { RADIO_GET_STATUS, 0 };
368 	const struct spi_buf tx_buf = {
369 		.buf = req,
370 		.len = sizeof(req),
371 	};
372 
373 	const struct spi_buf_set tx = {
374 		.buffers = &tx_buf,
375 		.count = 1,
376 	};
377 
378 	LOG_DBG("Sending GET_STATUS");
379 	ret = spi_write(dev_data.spi, &dev_data.spi_cfg, &tx);
380 	if (ret < 0) {
381 		LOG_ERR("SPI transaction failed: %i", ret);
382 		return;
383 	}
384 
385 	LOG_DBG("Waiting for device...");
386 	SX126xWaitOnBusy();
387 	LOG_DBG("Device ready");
388 	/* This function is only called from sleep mode
389 	 * All edges on the SS SPI pin will transition the modem to
390 	 * standby mode (via startup)
391 	 */
392 	dev_data.mode = MODE_STDBY_RC;
393 }
394 
SX126xGetDio1PinState(void)395 uint32_t SX126xGetDio1PinState(void)
396 {
397 	return sx126x_get_dio1_pin_state(&dev_data);
398 }
399 
sx126x_dio1_irq_work_handler(struct k_work * work)400 static void sx126x_dio1_irq_work_handler(struct k_work *work)
401 {
402 	LOG_DBG("Processing DIO1 interrupt");
403 	if (!dev_data.radio_dio_irq) {
404 		LOG_WRN("DIO1 interrupt without valid HAL IRQ callback.");
405 		return;
406 	}
407 
408 	dev_data.radio_dio_irq(NULL);
409 	if (Radio.IrqProcess) {
410 		Radio.IrqProcess();
411 	}
412 
413 	/* Re-enable the interrupt if we are not in sleep mode */
414 	if (dev_data.mode != MODE_SLEEP) {
415 		sx126x_dio1_irq_enable(&dev_data);
416 	}
417 }
418 
sx126x_lora_init(const struct device * dev)419 static int sx126x_lora_init(const struct device *dev)
420 {
421 	int ret;
422 
423 	LOG_DBG("Initializing %s", DT_INST_LABEL(0));
424 
425 	if (sx12xx_configure_pin(antenna_enable, GPIO_OUTPUT_INACTIVE) ||
426 	    sx12xx_configure_pin(rx_enable, GPIO_OUTPUT_INACTIVE) ||
427 	    sx12xx_configure_pin(tx_enable, GPIO_OUTPUT_INACTIVE)) {
428 		return -EIO;
429 	}
430 
431 	k_work_init(&dev_data.dio1_irq_work, sx126x_dio1_irq_work_handler);
432 
433 	ret = sx126x_variant_init(dev);
434 	if (ret) {
435 		LOG_ERR("Variant initialization failed");
436 		return ret;
437 	}
438 
439 	dev_data.spi = device_get_binding(DT_INST_BUS_LABEL(0));
440 	if (!dev_data.spi) {
441 		LOG_ERR("Cannot get pointer to %s device",
442 			DT_INST_BUS_LABEL(0));
443 		return -EINVAL;
444 	}
445 
446 #if HAVE_GPIO_CS
447 	dev_data.spi_cs.gpio_dev = device_get_binding(GPIO_CS_LABEL);
448 	if (!dev_data.spi_cs.gpio_dev) {
449 		LOG_ERR("Cannot get pointer to %s device", GPIO_CS_LABEL);
450 		return -EIO;
451 	}
452 
453 	dev_data.spi_cs.gpio_pin = GPIO_CS_PIN;
454 	dev_data.spi_cs.gpio_dt_flags = GPIO_CS_FLAGS;
455 	dev_data.spi_cs.delay = 0U;
456 
457 	dev_data.spi_cfg.cs = &dev_data.spi_cs;
458 #endif
459 	dev_data.spi_cfg.operation = SPI_WORD_SET(8) | SPI_TRANSFER_MSB;
460 	dev_data.spi_cfg.frequency = DT_INST_PROP(0, spi_max_frequency);
461 	dev_data.spi_cfg.slave = DT_INST_REG_ADDR(0);
462 
463 
464 	ret = sx12xx_init(dev);
465 	if (ret < 0) {
466 		LOG_ERR("Failed to initialize SX12xx common");
467 		return ret;
468 	}
469 
470 	return 0;
471 }
472 
473 static const struct lora_driver_api sx126x_lora_api = {
474 	.config = sx12xx_lora_config,
475 	.send = sx12xx_lora_send,
476 	.send_async = sx12xx_lora_send_async,
477 	.recv = sx12xx_lora_recv,
478 	.test_cw = sx12xx_lora_test_cw,
479 };
480 
481 DEVICE_DT_INST_DEFINE(0, &sx126x_lora_init, NULL, &dev_data,
482 		      NULL, POST_KERNEL, CONFIG_LORA_INIT_PRIORITY,
483 		      &sx126x_lora_api);
484