diff --git a/platform/drivers/GPS/GPS_ttwrplus.c b/platform/drivers/GPS/GPS_ttwrplus.c
deleted file mode 100644
index 92d55893..00000000
--- a/platform/drivers/GPS/GPS_ttwrplus.c
+++ /dev/null
@@ -1,150 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2023 - 2025 by Federico Amedeo Izzo IU2NUO, *
- * Niccolò Izzo IU2KIN *
- * Frederik Saraci IU2NRO *
- * Silvano Seva IU2KWO *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 3 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program; if not, see *
- ***************************************************************************/
-
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-
-
-#if DT_NODE_HAS_STATUS(DT_ALIAS(gps), okay)
-#define UART_GPS_DEV_NODE DT_ALIAS(gps)
-#else
-#error "Please select the correct gps UART device"
-#endif
-
-#define NMEA_MSG_SIZE 82
-
-K_MSGQ_DEFINE(gps_uart_msgq, NMEA_MSG_SIZE, 10, 4);
-
-static const struct device *const gps_dev = DEVICE_DT_GET(UART_GPS_DEV_NODE);
-
-// receive buffer used in UART ISR callback
-static char rx_buf[NMEA_MSG_SIZE];
-static uint16_t rx_buf_pos;
-
-
-static void gps_serialCb(const struct device *dev, void *user_data)
-{
- uint8_t c;
-
- if (uart_irq_update(gps_dev) == false)
- return;
-
- if (uart_irq_rx_ready(gps_dev) == false)
- return;
-
- // read until FIFO empty
- while (uart_fifo_read(gps_dev, &c, 1) == 1)
- {
- if (c == '$' && rx_buf_pos > 0)
- {
- // terminate string
- rx_buf[rx_buf_pos] = '\0';
-
- // if queue is full, message is silently dropped
- k_msgq_put(&gps_uart_msgq, &rx_buf, K_NO_WAIT);
-
- // reset the buffer (it was copied to the msgq)
- rx_buf_pos = 0;
- rx_buf[rx_buf_pos++] = '$';
- }
- else if (rx_buf_pos < (sizeof(rx_buf) - 1))
- {
- rx_buf[rx_buf_pos++] = c;
- }
- }
-}
-
-
-void gps_init(const uint16_t baud)
-{
- int ret = 0;
-
- // Check if GPS UART is ready
- if (device_is_ready(gps_dev) == false)
- {
- printk("UART device not found!\n");
- return;
- }
-
- ret = uart_irq_callback_user_data_set(gps_dev, gps_serialCb, NULL);
- if (ret < 0)
- {
- if (ret == -ENOTSUP)
- {
- printk("Interrupt-driven UART support not enabled\n");
- }
- else if (ret == -ENOSYS)
- {
- printk("UART device does not support interrupt-driven API\n");
- }
- else
- {
- printk("Error setting UART callback: %d\n", ret);
- }
-
- return;
- }
-
- uart_irq_rx_enable(gps_dev);
-}
-
-void gps_terminate()
-{
- gps_disable();
-}
-
-void gps_enable()
-{
- pmu_setGPSPower(true);
-}
-
-void gps_disable()
-{
- pmu_setGPSPower(false);
-}
-
-bool gps_detect(uint16_t timeout)
-{
- return true;
-}
-
-int gps_getNmeaSentence(char *buf, const size_t maxLength)
-{
- k_msgq_get(&gps_uart_msgq, buf, K_FOREVER);
- return 0;
-}
-
-bool gps_nmeaSentenceReady()
-{
- return k_msgq_num_used_get(&gps_uart_msgq) != 0;
-}
-
-void gps_waitForNmeaSentence()
-{
- while (k_msgq_num_used_get(&gps_uart_msgq) != 0)
- {
- sleepFor(0, 100);
- }
-}
diff --git a/platform/drivers/GPS/gps_zephyr.c b/platform/drivers/GPS/gps_zephyr.c
new file mode 100644
index 00000000..a0a2b7eb
--- /dev/null
+++ b/platform/drivers/GPS/gps_zephyr.c
@@ -0,0 +1,89 @@
+/***************************************************************************
+ * Copyright (C) 2023 - 2025 by Federico Amedeo Izzo IU2NUO, *
+ * Niccolò Izzo IU2KIN *
+ * Frederik Saraci IU2NRO *
+ * Silvano Seva IU2KWO *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 3 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program; if not, see *
+ ***************************************************************************/
+
+#include
+#include
+#include
+#include
+
+#if !DT_NODE_HAS_STATUS(DT_ALIAS(gps), okay)
+#error "Please select the correct gps UART device"
+#endif
+
+static const struct device *const gpsDev = DEVICE_DT_GET(DT_ALIAS(gps));
+static struct nmeaRbuf ringBuf;
+
+static void uartRxCallback(const struct device *dev, void *user_data)
+{
+ uint8_t c;
+
+ if(uart_irq_update(dev) == false)
+ return;
+
+ if(uart_irq_rx_ready(dev) == false)
+ return;
+
+ // read until FIFO empty
+ while(uart_fifo_read(dev, &c, 1) == 1)
+ nmeaRbuf_putChar(&ringBuf, c);
+}
+
+void gpsZephyr_init()
+{
+ int ret = 0;
+
+ // Check if GPS UART is ready
+ if(device_is_ready(gpsDev) == false) {
+ printk("UART device not found!\n");
+ return;
+ }
+
+ ret = uart_irq_callback_user_data_set(gpsDev, uartRxCallback, NULL);
+ if(ret < 0) {
+ switch(ret) {
+ case -ENOTSUP:
+ printk("Interrupt-driven UART support not enabled\n");
+ break;
+
+ case -ENOSYS:
+ printk("UART device does not support interrupt-driven API\n");
+ break;
+
+ default:
+ printk("Error setting UART callback: %d\n", ret);
+ break;
+ }
+ }
+
+ nmeaRbuf_reset(&ringBuf);
+ uart_irq_rx_enable(gpsDev);
+}
+
+void gpsZephyr_terminate()
+{
+ uart_irq_rx_disable(gpsDev);
+}
+
+int gpsZephyr_getNmeaSentence(void *priv, char *buf, const size_t maxLength)
+{
+ (void) priv;
+
+ return nmeaRbuf_getSentence(&ringBuf, buf, maxLength);
+}
diff --git a/platform/drivers/GPS/gps_zephyr.h b/platform/drivers/GPS/gps_zephyr.h
new file mode 100644
index 00000000..ffa6ebeb
--- /dev/null
+++ b/platform/drivers/GPS/gps_zephyr.h
@@ -0,0 +1,59 @@
+/***************************************************************************
+ * Copyright (C) 2021 - 2025 by Federico Amedeo Izzo IU2NUO, *
+ * Niccolò Izzo IU2KIN *
+ * Frederik Saraci IU2NRO *
+ * Silvano Seva IU2KWO *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 3 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program; if not, see *
+ ***************************************************************************/
+
+#ifndef GPS_ZEPHYR_H
+#define GPS_ZEPHYR_H
+
+#include
+#include
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * Initialise the GPS driver.
+ * This function does not turn on the GPS module.
+ */
+void gpsZephyr_init();
+
+/**
+ * Terminate the GPS driver.
+ */
+void gpsZephyr_terminate();
+
+/**
+ * Retrieve a NMEA sentence from the GPS.
+ * If the sentence is longer than the maximum size of the destination buffer,
+ * the characters not written in the destination are lost.
+ *
+ * @param priv: unused parameter, for function signature compatibility.
+ * @param buf: pointer to NMEA sentence destination buffer.
+ * @param maxLen: maximum acceptable size for the destination buffer.
+ * @return the length of the extracted sentence or -1 if the sentence is longer
+ * than the maximum allowed size. If the ring buffer is empty, zero is returned.
+ */
+int gpsZephyr_getNmeaSentence(void *priv, char *buf, const size_t maxLength);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* GPS_STM32_H */
diff --git a/platform/targets/ttwrplus/CMakeLists.txt b/platform/targets/ttwrplus/CMakeLists.txt
index 845cd7e5..125259f9 100644
--- a/platform/targets/ttwrplus/CMakeLists.txt
+++ b/platform/targets/ttwrplus/CMakeLists.txt
@@ -17,7 +17,8 @@ target_sources(app
${OPENRTX_ROOT}/platform/drivers/baseband/radio_ttwrplus.cpp
${OPENRTX_ROOT}/platform/drivers/baseband/AT1846S_SA8x8.cpp
${OPENRTX_ROOT}/platform/drivers/baseband/SA8x8.c
- ${OPENRTX_ROOT}/platform/drivers/GPS/GPS_ttwrplus.c
+ ${OPENRTX_ROOT}/platform/drivers/GPS/gps_zephyr.c
+ ${OPENRTX_ROOT}/platform/drivers/GPS/nmea_rbuf.c
${OPENRTX_ROOT}/platform/drivers/audio/audio_ttwrplus.c
${OPENRTX_ROOT}/platform/drivers/NVM/flash_zephyr.c
${OPENRTX_ROOT}/platform/drivers/NVM/nvmem_ttwrplus.c
diff --git a/platform/targets/ttwrplus/hwconfig.h b/platform/targets/ttwrplus/hwconfig.h
index 3a678b63..40f52f56 100644
--- a/platform/targets/ttwrplus/hwconfig.h
+++ b/platform/targets/ttwrplus/hwconfig.h
@@ -29,7 +29,9 @@
#define CONFIG_SCREEN_WIDTH DT_PROP(DISPLAY, width)
#define CONFIG_SCREEN_HEIGHT DT_PROP(DISPLAY, height)
#define CONFIG_PIX_FMT_BW
+
#define CONFIG_GPS
+#define CONFIG_NMEA_RBUF_SIZE 128
#define CONFIG_BAT_LIPO
#define CONFIG_BAT_NCELLS 1
diff --git a/platform/targets/ttwrplus/platform.c b/platform/targets/ttwrplus/platform.c
index ff930fdf..c1901eee 100644
--- a/platform/targets/ttwrplus/platform.c
+++ b/platform/targets/ttwrplus/platform.c
@@ -19,7 +19,9 @@
#include
#include
+#include
#include
+#include
#include
#include
@@ -52,6 +54,24 @@ static hwInfo_t hwInfo =
// RGB led color data
static struct led_rgb led_color = {0};
+static void gpsEnable(void *priv)
+{
+ (void) priv;
+ pmu_setGPSPower(true);
+}
+
+static void gpsDisable(void *priv)
+{
+ (void) priv;
+ pmu_setGPSPower(false);
+}
+
+static const struct gpsDevice gps =
+{
+ .enable = gpsEnable,
+ .disable = gpsDisable,
+ .getSentence = gpsZephyr_getNmeaSentence
+};
void platform_init()
{
@@ -107,6 +127,7 @@ void platform_init()
void platform_terminate()
{
+ gpsZephyr_terminate();
pmu_terminate();
}
@@ -219,3 +240,9 @@ const hwInfo_t *platform_getHwInfo()
return &hwInfo;
}
+const struct gpsDevice *platform_initGps()
+{
+ gpsZephyr_init();
+
+ return &gps;
+}