diff --git a/platform/drivers/GPS/GPS_ttwrplus.c b/platform/drivers/GPS/GPS_ttwrplus.c
new file mode 100644
index 00000000..66f7b95f
--- /dev/null
+++ b/platform/drivers/GPS/GPS_ttwrplus.c
@@ -0,0 +1,150 @@
+/***************************************************************************
+ * Copyright (C) 2023 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/targets/ttwrplus/CMakeLists.txt b/platform/targets/ttwrplus/CMakeLists.txt
index f0fc0ece..063bb2ab 100644
--- a/platform/targets/ttwrplus/CMakeLists.txt
+++ b/platform/targets/ttwrplus/CMakeLists.txt
@@ -16,6 +16,7 @@ target_sources(app
${OPENRTX_ROOT}/platform/drivers/keyboard/keyboard_ttwrplus.c
${OPENRTX_ROOT}/platform/drivers/baseband/radio_ttwrplus.cpp
${OPENRTX_ROOT}/platform/drivers/baseband/AT1846S_SA8x8.cpp
+ ${OPENRTX_ROOT}/platform/drivers/GPS/GPS_ttwrplus.c
${OPENRTX_ROOT}/platform/drivers/stubs/audio_stub.c
${OPENRTX_ROOT}/platform/drivers/stubs/cps_io_stub.c
diff --git a/platform/targets/ttwrplus/hwconfig.h b/platform/targets/ttwrplus/hwconfig.h
index d12e51b7..6b115c24 100644
--- a/platform/targets/ttwrplus/hwconfig.h
+++ b/platform/targets/ttwrplus/hwconfig.h
@@ -29,6 +29,7 @@
#define SCREEN_WIDTH DT_PROP(DISPLAY, width)
#define SCREEN_HEIGHT DT_PROP(DISPLAY, height)
#define PIX_FMT_BW
+#define GPS_PRESENT
#define BAT_LIPO_1S
diff --git a/platform/targets/ttwrplus/pmu.cpp b/platform/targets/ttwrplus/pmu.cpp
index 930599ff..b5e59414 100644
--- a/platform/targets/ttwrplus/pmu.cpp
+++ b/platform/targets/ttwrplus/pmu.cpp
@@ -146,7 +146,7 @@ void pmu_init()
PMU.enableALDO2();
//! ALDO4 GNSS VDD
- PMU.enableALDO4();
+ PMU.disableALDO4();
//! BLDO1 MIC VDD
PMU.enableBLDO1();
@@ -305,3 +305,11 @@ void pmu_setBasebandPower(bool enable)
else
PMU.disableDC3();
}
+
+void pmu_setGPSPower(bool enable)
+{
+ if (enable)
+ PMU.enableALDO4();
+ else
+ PMU.disableALDO4();
+}
diff --git a/platform/targets/ttwrplus/pmu.h b/platform/targets/ttwrplus/pmu.h
index fbe43ae1..2e1fda5a 100644
--- a/platform/targets/ttwrplus/pmu.h
+++ b/platform/targets/ttwrplus/pmu.h
@@ -27,6 +27,7 @@ extern "C" {
void pmu_init();
uint16_t pmu_getVbat();
void pmu_setBasebandPower(bool enable);
+void pmu_setGPSPower(bool enable);
#ifdef __cplusplus
}
diff --git a/platform/targets/ttwrplus/ttwrplus.dts b/platform/targets/ttwrplus/ttwrplus.dts
index 8628b05f..4975ebe2 100644
--- a/platform/targets/ttwrplus/ttwrplus.dts
+++ b/platform/targets/ttwrplus/ttwrplus.dts
@@ -18,6 +18,7 @@
i2c-0 = &i2c0;
watchdog0 = &wdt0;
radio = &uart0;
+ gps = &uart1;
radio-pwr = &radio_pwr;
radio-pdn = &radio_pdn;
radio-ptt = &radio_ptt;
@@ -94,6 +95,13 @@
pinctrl-names = "default";
};
+&uart1 {
+ status = "okay";
+ current-speed = <9600>;
+ pinctrl-0 = <&uart1_default>;
+ pinctrl-names = "default";
+};
+
&i2c0 {
status = "okay";
clock-frequency = ;
@@ -201,6 +209,17 @@
};
};
+ uart1_default: uart1_default {
+ group1 {
+ pinmux = ;
+ output-high;
+ };
+ group2 {
+ pinmux = ;
+ bias-pull-up;
+ };
+ };
+
i2c0_default: i2c0_default {
group1 {
pinmux = ,