From cb338ceb3d99b0ab84dc674027e9b20c07dd59bb Mon Sep 17 00:00:00 2001 From: Silvano Seva Date: Tue, 15 Oct 2024 18:15:55 +0200 Subject: [PATCH] CS7000: added GPS support --- meson.build | 1 + platform/drivers/GPS/GPS_CS7000.cpp | 175 ++++++++++++++++++++++++++++ platform/targets/CS7000/hwconfig.h | 3 + platform/targets/CS7000/pinmap.h | 4 +- 4 files changed, 181 insertions(+), 2 deletions(-) create mode 100644 platform/drivers/GPS/GPS_CS7000.cpp 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