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