diff --git a/meson.build b/meson.build
index fa34fc6d..2dd00986 100644
--- a/meson.build
+++ b/meson.build
@@ -474,6 +474,7 @@ cs7000_src = ['platform/drivers/NVM/nvmem_CS7000.c',
'platform/drivers/GPIO/gpio_shiftReg.c',
'platform/drivers/SPI/spi_custom.c',
'platform/drivers/SPI/spi_bitbang.c',
+ 'platform/drivers/GPS/GPS_CS7000.cpp',
'platform/targets/CS7000/hwconfig.c',
'platform/targets/CS7000/platform.c']
diff --git a/platform/drivers/GPS/GPS_CS7000.cpp b/platform/drivers/GPS/GPS_CS7000.cpp
new file mode 100644
index 00000000..f6c9bb94
--- /dev/null
+++ b/platform/drivers/GPS/GPS_CS7000.cpp
@@ -0,0 +1,175 @@
+/***************************************************************************
+ * Copyright (C) 2024 by 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
+#include
+
+static size_t bufPos = 0;
+static size_t maxPos = 0;
+static char *dataBuf;
+static bool receiving = false;
+
+using namespace miosix;
+static Thread *gpsWaiting = 0;
+
+void __attribute__((used)) GpsUsartImpl()
+{
+ if(USART6->SR & USART_SR_RXNE)
+ {
+ char value = USART6->DR;
+
+ if((receiving == false) && (value == '$') && (bufPos == 0))
+ {
+ receiving = true;
+ }
+
+ if(receiving)
+ {
+ if(bufPos == maxPos)
+ {
+ receiving = false;
+ }
+
+ char prevChar = dataBuf[bufPos - 1];
+ dataBuf[bufPos] = value;
+ bufPos += 1;
+
+ if((prevChar == '\r') && (value == '\n'))
+ {
+ receiving = false;
+ bufPos -= 1;
+ }
+ }
+
+ if((receiving == false) && (bufPos != 0))
+ {
+ // NMEA sentence received, turn off serial port
+ USART6->CR1 &= ~USART_CR1_UE;
+
+ if(gpsWaiting)
+ {
+ gpsWaiting->IRQwakeup();
+ if(gpsWaiting->IRQgetPriority()>
+ Thread::IRQgetCurrentThread()->IRQgetPriority())
+ Scheduler::IRQfindNextThread();
+ gpsWaiting = 0;
+ }
+ }
+ }
+
+ USART6->SR = 0;
+}
+
+void __attribute__((naked)) USART6_IRQHandler()
+{
+ saveContext();
+ asm volatile("bl _Z12GpsUsartImplv");
+ restoreContext();
+}
+
+
+void gps_init(const uint16_t baud)
+{
+ gpio_setMode(GPS_RXD, ALTERNATE | ALTERNATE_FUNC(8));
+
+ RCC->APB2ENR |= RCC_APB2ENR_USART6EN;
+ __DSB();
+
+ uint32_t quot = rcc_getBusClock(PERIPH_BUS_APB2);
+ quot = (2 * quot) / baud;
+
+ USART6->BRR = (quot / 2) + (quot & 1);
+ USART6->CR3 |= USART_CR3_ONEBIT;
+ USART6->CR1 = USART_CR1_RE
+ | USART_CR1_RXNEIE;
+
+ NVIC_SetPriority(USART6_IRQn, 14);
+}
+
+void gps_terminate()
+{
+ gps_disable();
+
+ RCC->APB2ENR &= ~RCC_APB2ENR_USART6EN;
+}
+
+void gps_enable()
+{
+ // Enable IRQ
+ NVIC_ClearPendingIRQ(USART6_IRQn);
+ NVIC_EnableIRQ(USART6_IRQn);
+}
+
+void gps_disable()
+{
+ USART6->CR1 &= ~USART_CR1_UE;
+ NVIC_DisableIRQ(USART6_IRQn);
+
+ receiving = false;
+ bufPos = 0;
+}
+
+bool gps_detect(uint16_t timeout)
+{
+ (void) timeout;
+
+ return true;
+}
+
+int gps_getNmeaSentence(char *buf, const size_t maxLength)
+{
+ memset(buf, 0x00, maxLength);
+ bufPos = 0;
+ maxPos = maxLength;
+ dataBuf = buf;
+
+ // Enable serial port
+ USART6->CR1 |= USART_CR1_UE;
+
+ return 0;
+}
+
+bool gps_nmeaSentenceReady()
+{
+ return (receiving == false) && (bufPos > 0);
+}
+
+void gps_waitForNmeaSentence()
+{
+ /*
+ * Put the calling thread in waiting status until a complete sentence is ready.
+ */
+ {
+ FastInterruptDisableLock dLock;
+ gpsWaiting = Thread::IRQgetCurrentThread();
+ do
+ {
+ Thread::IRQwait();
+ {
+ FastInterruptEnableLock eLock(dLock);
+ Thread::yield();
+ }
+ }
+ while(gpsWaiting);
+ }
+}
diff --git a/platform/targets/CS7000/hwconfig.h b/platform/targets/CS7000/hwconfig.h
index d83e8fcb..14e2dd13 100644
--- a/platform/targets/CS7000/hwconfig.h
+++ b/platform/targets/CS7000/hwconfig.h
@@ -66,6 +66,9 @@ extern const struct sky73210 pll;
/* Device supports M17 mode */
#define CONFIG_M17
+/* Device has a GPS chip */
+#define CONFIG_GPS
+
#ifdef __cplusplus
}
#endif
diff --git a/platform/targets/CS7000/pinmap.h b/platform/targets/CS7000/pinmap.h
index ba44587c..7c49aafa 100644
--- a/platform/targets/CS7000/pinmap.h
+++ b/platform/targets/CS7000/pinmap.h
@@ -148,8 +148,8 @@
#define PHONE_DETECT GPIOA,13
/* GPS */
-#define GPS_RXD GPIOC,6
-#define GPS_TXD GPIOC,7
+#define GPS_TXD GPIOC,6
+#define GPS_RXD GPIOC,7
/* Accessory connector */
#define PHONE_TXD GPIOA,0