1 /*
2  * Copyright (c) 2025 Croxel Inc.
3  * Copyright (c) 2025 CogniPilot Foundation
4  *
5  * SPDX-License-Identifier: Apache-2.0
6  */
7 
8 #include <zephyr/kernel.h>
9 #include <zephyr/init.h>
10 #include <zephyr/sys/check.h>
11 #include <zephyr/sys/ring_buffer.h>
12 #include <zephyr/drivers/uart.h>
13 #include <zephyr/gnss/rtk/decoder.h>
14 #include <zephyr/gnss/rtk/rtk_publish.h>
15 #include <zephyr/gnss/rtk/rtk.h>
16 
17 #include <zephyr/logging/log.h>
18 LOG_MODULE_REGISTER(rtk_serial, CONFIG_GNSS_RTK_LOG_LEVEL);
19 
20 static const struct device *rtk_serial_dev = DEVICE_DT_GET(DT_CHOSEN(zephyr_rtk_serial));
21 static struct ring_buf process_ringbuf;
22 static uint8_t process_buf[2048];
23 
gnss_rtk_process_work_handler(struct k_work * work)24 static void gnss_rtk_process_work_handler(struct k_work *work)
25 {
26 	static uint8_t work_buf[2048];
27 	uint32_t len = ring_buf_get(&process_ringbuf, work_buf, sizeof(work_buf));
28 	uint32_t offset = 0;
29 
30 	ARG_UNUSED(work);
31 
32 	do {
33 		uint8_t *frame;
34 		size_t frame_len;
35 		int err;
36 
37 		err = gnss_rtk_decoder_frame_get(work_buf + offset, len - offset,
38 						 &frame, &frame_len);
39 		if (err != 0) {
40 			return;
41 		}
42 
43 		LOG_HEXDUMP_DBG(frame, frame_len, "Frame received");
44 
45 		/* Publish results */
46 		struct gnss_rtk_data rtk_data = {
47 			.data = frame,
48 			.len = frame_len,
49 		};
50 
51 		gnss_rtk_publish_data(&rtk_data);
52 		offset += frame_len;
53 
54 	} while (len > offset);
55 }
56 
57 static K_WORK_DELAYABLE_DEFINE(gnss_rtk_process_work, gnss_rtk_process_work_handler);
58 
rtk_uart_isr_callback(const struct device * dev,void * user_data)59 static void rtk_uart_isr_callback(const struct device *dev, void *user_data)
60 {
61 	ARG_UNUSED(user_data);
62 
63 	(void)uart_irq_update(dev);
64 
65 	if (uart_irq_rx_ready(dev)) {
66 		int ret;
67 
68 		do {
69 			char c;
70 
71 			ret = uart_fifo_read(dev, &c, 1);
72 			if (ret > 0) {
73 				ret = ring_buf_put(&process_ringbuf, &c, 1);
74 			}
75 		} while (ret > 0);
76 
77 		/** Since messages come through in a burst at a period
78 		 * (e.g: 1 Hz), wait until all messages are received before
79 		 * processing.
80 		 */
81 		(void)k_work_reschedule(&gnss_rtk_process_work, K_MSEC(10));
82 	}
83 }
84 
rtk_serial_client_init(void)85 static int rtk_serial_client_init(void)
86 {
87 	int err;
88 
89 	ring_buf_init(&process_ringbuf, ARRAY_SIZE(process_buf), process_buf);
90 
91 	err = uart_irq_callback_user_data_set(rtk_serial_dev, rtk_uart_isr_callback, NULL);
92 	if (err < 0) {
93 		return err;
94 	}
95 
96 	uart_irq_rx_enable(rtk_serial_dev);
97 
98 	return 0;
99 }
100 
101 SYS_INIT(rtk_serial_client_init, APPLICATION, CONFIG_APPLICATION_INIT_PRIORITY);
102