From 1ef91597ca7c0d7cc5d2e006821373eb07c01f3e Mon Sep 17 00:00:00 2001 From: Damjan Adamic Date: Mon, 29 Aug 2016 23:18:20 +0200 Subject: [PATCH 1/3] Horus internal GPS: settable baudrate, misc fixes, new cmake options, cosmetics, cli --- radio/src/cli.cpp | 17 +++++++++ radio/src/gps.cpp | 48 +++++++++++++++++++------- radio/src/gui/common/arm/widgets.cpp | 4 +++ radio/src/targets/horus/CMakeLists.txt | 6 ++++ radio/src/targets/horus/board.cpp | 6 ++-- radio/src/targets/horus/board.h | 4 +-- radio/src/targets/horus/gps_driver.cpp | 10 ++++-- radio/src/targets/horus/hal.h | 1 - 8 files changed, 75 insertions(+), 21 deletions(-) diff --git a/radio/src/cli.cpp b/radio/src/cli.cpp index 873cd8d2d..eb238df5f 100644 --- a/radio/src/cli.cpp +++ b/radio/src/cli.cpp @@ -708,6 +708,20 @@ int cliShowJitter(const char ** argv) } #endif +#if defined(INTERNAL_GPS) +int cliGps(const char ** argv) +{ + int baudrate = 0; + if (toInt(argv, 1, &baudrate) > 0 && baudrate > 0) { + gpsInit(baudrate); + serialPrint("GPS baudrate set to %d", baudrate); + } + else { + serialPrint("%s: Invalid arguments", argv[0]); + } + return 0; +} +#endif const CliCommand cliCommands[] = { { "beep", cliBeep, "[] []" }, @@ -731,6 +745,9 @@ const CliCommand cliCommands[] = { { "repeat", cliRepeat, " " }, #if defined(JITTER_MEASURE) { "jitter", cliShowJitter, "" }, +#endif +#if defined(INTERNAL_GPS) + { "gps", cliGps, "" }, #endif { NULL, NULL, NULL } /* sentinel */ }; diff --git a/radio/src/gps.cpp b/radio/src/gps.cpp index 14669160e..81221604c 100644 --- a/radio/src/gps.cpp +++ b/radio/src/gps.cpp @@ -1,5 +1,26 @@ /* - * This file is part of Cleanflight. + * Copyright (C) OpenTX + * + * Based on code named + * th9x - http://code.google.com/p/th9x + * er9x - http://code.google.com/p/er9x + * gruvin9x - http://code.google.com/p/gruvin9x + * + * License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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. + */ + +/* + * This file is based on code from Cleanflight project + * https://github.com/cleanflight/cleanflight * * Cleanflight is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -47,14 +68,14 @@ uint32_t GPS_coord_to_degrees(const char * coordinateString) uint8_t degrees = 0, minutes = 0; uint16_t fractionalMinutes = 0; uint8_t digitIndex; - + // scan for decimal point or end of field for (fieldSeparator = coordinateString; isdigit((unsigned char) *fieldSeparator); fieldSeparator++) { if (fieldSeparator >= coordinateString + 15) return 0; // stop potential fail } remainingString = coordinateString; - + // convert degrees while ((fieldSeparator - remainingString) > 2) { if (degrees) @@ -118,12 +139,12 @@ typedef struct gpsDataNmea_s bool gpsNewFrameNMEA(char c) { static gpsDataNmea_t gps_Msg; - + uint8_t frameOK = 0; static uint8_t param = 0, offset = 0, parity = 0; static char string[15]; static uint8_t checksum_param, gps_frame = NO_FRAME; - + switch (c) { case '$': param = 0; @@ -134,14 +155,14 @@ bool gpsNewFrameNMEA(char c) case '*': string[offset] = 0; if (param == 0) { - // Frame identification + // Frame identification (accept all GPS talkers (GP: GPS, GL:Glonass, GN:combination, etc...)) gps_frame = NO_FRAME; - if (string[0] == 'G' && string[1] == 'P' && string[2] == 'G' && string[3] == 'G' && string[4] == 'A') + if (string[0] == 'G' && string[2] == 'G' && string[3] == 'G' && string[4] == 'A') gps_frame = FRAME_GGA; - if (string[0] == 'G' && string[1] == 'P' && string[2] == 'R' && string[3] == 'M' && string[4] == 'C') + if (string[0] == 'G' && string[2] == 'R' && string[3] == 'M' && string[4] == 'C') gps_frame = FRAME_RMC; } - + switch (gps_frame) { case FRAME_GGA: //************* GPGGA FRAME parsing switch (param) { @@ -189,7 +210,7 @@ bool gpsNewFrameNMEA(char c) break; } - + param++; offset = 0; if (c == '*') @@ -207,12 +228,14 @@ bool gpsNewFrameNMEA(char c) switch (gps_frame) { case FRAME_GGA: frameOK = 1; + gpsData.fix = gps_Msg.fix; + gpsData.numSat = gps_Msg.numSat; if (gps_Msg.fix) { - gpsData.fix = 1; + __disable_irq(); // do the atomic update of lat/lon gpsData.latitude = gps_Msg.latitude; gpsData.longitude = gps_Msg.longitude; - gpsData.numSat = gps_Msg.numSat; gpsData.altitude = gps_Msg.altitude; + __enable_irq(); } break; case FRAME_RMC: @@ -252,6 +275,7 @@ void gpsWakeup() { uint8_t byte; while (gpsGetByte(&byte)) { + TRACE_PING("%c", (char)byte); gpsNewData(byte); } } diff --git a/radio/src/gui/common/arm/widgets.cpp b/radio/src/gui/common/arm/widgets.cpp index 941242b3d..94f5eb017 100644 --- a/radio/src/gui/common/arm/widgets.cpp +++ b/radio/src/gui/common/arm/widgets.cpp @@ -136,6 +136,10 @@ void drawSourceCustomValue(coord_t x, coord_t y, source_t source, int32_t value, if (gpsData.fix) { drawGPSPosition(x, y, gpsData.longitude, gpsData.latitude, flags); } + else { + lcdDrawText(x, y, "sats: ", flags); + lcdDrawNumber(lcdNextPos, y, gpsData.numSat, flags); + } } #endif else if (source < MIXSRC_FIRST_CH) { diff --git a/radio/src/targets/horus/CMakeLists.txt b/radio/src/targets/horus/CMakeLists.txt index 54158bcd2..63f95c013 100644 --- a/radio/src/targets/horus/CMakeLists.txt +++ b/radio/src/targets/horus/CMakeLists.txt @@ -1,4 +1,6 @@ set(PCBREV "13" CACHE STRING "PCB Revision") +set(INTERNAL_GPS_BAUDRATE "9600" CACHE STRING "Baud rate for internal GPS") +option(INTERNAL_GPS_INSTALLED "Internal GPS installed in beta hardware version" NO) option(DISK_CACHE "Enable SD card disk cache" YES) set(CPU_TYPE STM32F4) @@ -16,6 +18,7 @@ set(RAMBACKUP YES) add_definitions(-DPCBHORUS -DPCBREV=${PCBREV} -DSTM32F429_439xx -DSDRAM -DCOLORLCD -DPPM_PIN_UART -DPPM_PIN_TIMER) add_definitions(-DEEPROM_VARIANT=0 -DAUDIO -DVOICE -DRTCLOCK) +add_definitions(-DGPS_USART_BAUDRATE=${INTERNAL_GPS_BAUDRATE}) include_directories(${RADIO_SRC_DIRECTORY}/fonts/480x272 gui/${GUI_DIR} gui/${GUI_DIR}/layouts) @@ -49,6 +52,9 @@ if(DISK_CACHE) set(SRC ${SRC} disk_cache.cpp) add_definitions(-DDISK_CACHE) endif() +if(INTERNAL_GPS_INSTALLED) + add_definitions(-DINTERNAL_GPS_INSTALLED) +endif() set(SERIAL2_DRIVER serial2_driver.cpp) set(TARGET_SRC ${TARGET_SRC} diff --git a/radio/src/targets/horus/board.cpp b/radio/src/targets/horus/board.cpp index 9c8b4971f..97199c5f5 100644 --- a/radio/src/targets/horus/board.cpp +++ b/radio/src/targets/horus/board.cpp @@ -168,7 +168,7 @@ void boardInit() lcdInit(); backlightInit(); // TODO ? backlightEnable(100); - + audioInit(); init2MhzTimer(); init1msTimer(); @@ -177,8 +177,8 @@ void boardInit() // bt_open(); - gpsInit(); - + gpsInit(GPS_USART_BAUDRATE); + #if defined(DEBUG) DBGMCU_APB1PeriphConfig(DBGMCU_IWDG_STOP|DBGMCU_TIM1_STOP|DBGMCU_TIM2_STOP|DBGMCU_TIM3_STOP|DBGMCU_TIM4_STOP|DBGMCU_TIM5_STOP|DBGMCU_TIM6_STOP|DBGMCU_TIM7_STOP|DBGMCU_TIM8_STOP|DBGMCU_TIM9_STOP|DBGMCU_TIM10_STOP|DBGMCU_TIM11_STOP|DBGMCU_TIM12_STOP|DBGMCU_TIM13_STOP|DBGMCU_TIM14_STOP, ENABLE); #endif diff --git a/radio/src/targets/horus/board.h b/radio/src/targets/horus/board.h index 500a7e3e3..6adbec507 100644 --- a/radio/src/targets/horus/board.h +++ b/radio/src/targets/horus/board.h @@ -389,12 +389,12 @@ void hapticOff(void); void hapticOn(uint32_t pwmPercent); // GPS driver -#if PCBREV >= 13 +#if PCBREV >= 13 || defined(INTERNAL_GPS_INSTALLED) #define INTERNAL_GPS 1 #else #define INTERNAL_GPS 0 #endif -void gpsInit(void); +void gpsInit(uint32_t baudrate); uint8_t gpsGetByte(uint8_t * byte); // Second serial port driver diff --git a/radio/src/targets/horus/gps_driver.cpp b/radio/src/targets/horus/gps_driver.cpp index 2f2725d42..65ec3cfe0 100644 --- a/radio/src/targets/horus/gps_driver.cpp +++ b/radio/src/targets/horus/gps_driver.cpp @@ -20,9 +20,13 @@ #include "opentx.h" -Fifo gpsRxFifo; +#if GPS_USART_BAUDRATE > 9600 + Fifo gpsRxFifo; +#else + Fifo gpsRxFifo; +#endif -void gpsInit() +void gpsInit(uint32_t baudrate) { GPIO_InitTypeDef GPIO_InitStructure; USART_InitTypeDef USART_InitStructure; @@ -39,7 +43,7 @@ void gpsInit() GPIO_Init(GPS_UART_GPIO, &GPIO_InitStructure); // UART config - USART_InitStructure.USART_BaudRate = GPS_USART_BAUDRATE; + USART_InitStructure.USART_BaudRate = baudrate; USART_InitStructure.USART_Parity = USART_Parity_No; USART_InitStructure.USART_StopBits = USART_StopBits_1; USART_InitStructure.USART_WordLength = USART_WordLength_8b; diff --git a/radio/src/targets/horus/hal.h b/radio/src/targets/horus/hal.h index d4119c4c1..8143f4554 100644 --- a/radio/src/targets/horus/hal.h +++ b/radio/src/targets/horus/hal.h @@ -439,6 +439,5 @@ #define GPS_RX_GPIO_PIN GPIO_Pin_1 // PA.01 #define GPS_TX_GPIO_PinSource GPIO_PinSource0 #define GPS_RX_GPIO_PinSource GPIO_PinSource1 -#define GPS_USART_BAUDRATE 9600 #endif // _HAL_H_ From ff37274e64e0413c2282bf8b1e9ef09a8cac1423 Mon Sep 17 00:00:00 2001 From: Damjan Adamic Date: Tue, 30 Aug 2016 21:23:20 +0200 Subject: [PATCH 2/3] Horus internal GPS: cmake changes, more CLI options, ability to send commands to the module --- radio/src/cli.cpp | 10 +++++++++- radio/src/gps.cpp | 25 ++++++++++++++++++++++++- radio/src/gps.h | 4 ++++ radio/src/main_arm.cpp | 2 +- radio/src/targets/horus/CMakeLists.txt | 14 +++++++++++--- radio/src/targets/horus/board.h | 9 ++++----- radio/src/targets/horus/gps_driver.cpp | 24 ++++++++++++++++++++++-- 7 files changed, 75 insertions(+), 13 deletions(-) diff --git a/radio/src/cli.cpp b/radio/src/cli.cpp index eb238df5f..7f8972756 100644 --- a/radio/src/cli.cpp +++ b/radio/src/cli.cpp @@ -712,7 +712,15 @@ int cliShowJitter(const char ** argv) int cliGps(const char ** argv) { int baudrate = 0; - if (toInt(argv, 1, &baudrate) > 0 && baudrate > 0) { + if (argv[1][0] == '$') { + // send command to GPS + gpsSendFrame(argv[1]); + } + else if (!strcmp(argv[1], "trace")) { + gpsTraceEnabled = !gpsTraceEnabled; + } + + else if (toInt(argv, 1, &baudrate) > 0 && baudrate > 0) { gpsInit(baudrate); serialPrint("GPS baudrate set to %d", baudrate); } diff --git a/radio/src/gps.cpp b/radio/src/gps.cpp index 81221604c..372427b03 100644 --- a/radio/src/gps.cpp +++ b/radio/src/gps.cpp @@ -275,7 +275,30 @@ void gpsWakeup() { uint8_t byte; while (gpsGetByte(&byte)) { - TRACE_PING("%c", (char)byte); gpsNewData(byte); } } + +#if defined(DEBUG) +char hex(uint8_t b) { + return b > 9 ? b + 'A' - 10 : b + '0'; +} + +void gpsSendFrame(const char * frame) +{ + // send given frame, add checksum and CRLF + uint8_t parity = 0; + while (*frame) { + if (*frame != '$') parity ^= *frame; + gpsSendByte(*frame); + ++frame; + } + gpsSendByte('*'); + gpsSendByte(hex(parity >> 4)); + gpsSendByte(hex(parity & 0x0F)); + gpsSendByte('\r'); + gpsSendByte('\n'); + TRACE("parity %02x", parity); +} + +#endif // #if defined(DEBUG) diff --git a/radio/src/gps.h b/radio/src/gps.h index 6b6919778..0c1b9d3ab 100644 --- a/radio/src/gps.h +++ b/radio/src/gps.h @@ -40,4 +40,8 @@ struct gpsdata_t extern gpsdata_t gpsData; void gpsWakeup(); +#if defined(DEBUG) +void gpsSendFrame(const char * frame); +#endif + #endif // _GPS_H_ diff --git a/radio/src/main_arm.cpp b/radio/src/main_arm.cpp index 28807575e..1c68c078b 100644 --- a/radio/src/main_arm.cpp +++ b/radio/src/main_arm.cpp @@ -464,7 +464,7 @@ void perMain() bluetoothWakeup(); #endif -#if INTERNAL_GPS > 0 +#if defined(INTERNAL_GPS) gpsWakeup(); #endif } diff --git a/radio/src/targets/horus/CMakeLists.txt b/radio/src/targets/horus/CMakeLists.txt index 63f95c013..19cb18ac2 100644 --- a/radio/src/targets/horus/CMakeLists.txt +++ b/radio/src/targets/horus/CMakeLists.txt @@ -1,7 +1,14 @@ set(PCBREV "13" CACHE STRING "PCB Revision") set(INTERNAL_GPS_BAUDRATE "9600" CACHE STRING "Baud rate for internal GPS") -option(INTERNAL_GPS_INSTALLED "Internal GPS installed in beta hardware version" NO) option(DISK_CACHE "Enable SD card disk cache" YES) +if(${PCBREV} GREATER 10) + option(INTERNAL_GPS "Internal GPS installed" YES) +else() + option(INTERNAL_GPS "Internal GPS installed" NO) + if(NOT INTERNAL_GPS) + message("Internal GPS is optional, use INTERNAL_GPS=YES option to enable it") + endif() +endif() set(CPU_TYPE STM32F4) set(HSE_VALUE 12000000) @@ -52,8 +59,9 @@ if(DISK_CACHE) set(SRC ${SRC} disk_cache.cpp) add_definitions(-DDISK_CACHE) endif() -if(INTERNAL_GPS_INSTALLED) - add_definitions(-DINTERNAL_GPS_INSTALLED) +if(INTERNAL_GPS) + add_definitions(-DINTERNAL_GPS) + message("Internal GPS enabled") endif() set(SERIAL2_DRIVER serial2_driver.cpp) set(TARGET_SRC diff --git a/radio/src/targets/horus/board.h b/radio/src/targets/horus/board.h index 6adbec507..66b8ed5fe 100644 --- a/radio/src/targets/horus/board.h +++ b/radio/src/targets/horus/board.h @@ -389,13 +389,12 @@ void hapticOff(void); void hapticOn(uint32_t pwmPercent); // GPS driver -#if PCBREV >= 13 || defined(INTERNAL_GPS_INSTALLED) -#define INTERNAL_GPS 1 -#else -#define INTERNAL_GPS 0 -#endif void gpsInit(uint32_t baudrate); uint8_t gpsGetByte(uint8_t * byte); +#if defined(DEBUG) + extern uint8_t gpsTraceEnabled; + void gpsSendByte(uint8_t byte); +#endif // Second serial port driver #define SERIAL2 diff --git a/radio/src/targets/horus/gps_driver.cpp b/radio/src/targets/horus/gps_driver.cpp index 65ec3cfe0..c9805ee42 100644 --- a/radio/src/targets/horus/gps_driver.cpp +++ b/radio/src/targets/horus/gps_driver.cpp @@ -60,9 +60,23 @@ void gpsInit(uint32_t baudrate) NVIC_Init(&NVIC_InitStructure); } +#if defined(DEBUG) +uint8_t gpsTraceEnabled = false; +Fifo gpsTxFifo; + +void gpsSendByte(uint8_t byte) +{ + while (gpsTxFifo.isFull()); + gpsTxFifo.push(byte); + USART_ITConfig(GPS_USART, USART_IT_TXE, ENABLE); +} + +#endif // #if defined(DEBUG) + + extern "C" void GPS_USART_IRQHandler(void) { -#if 0 +#if defined(DEBUG) // Send if (USART_GetITStatus(GPS_USART, USART_IT_TXE) != RESET) { uint8_t txchar; @@ -89,5 +103,11 @@ extern "C" void GPS_USART_IRQHandler(void) uint8_t gpsGetByte(uint8_t * byte) { - return gpsRxFifo.pop(*byte); + uint8_t result = gpsRxFifo.pop(*byte); +#if defined(DEBUG) + if (gpsTraceEnabled) { + serialPutc(*byte); + } +#endif + return result; } \ No newline at end of file From 590b0eaab77303f1704430aae5642bc66978d39a Mon Sep 17 00:00:00 2001 From: Damjan Adamic Date: Tue, 30 Aug 2016 21:55:09 +0200 Subject: [PATCH 3/3] Compilation fixes --- radio/src/gui/480x272/widgets/value.cpp | 9 +++++++-- radio/src/targets/horus/CMakeLists.txt | 2 +- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/radio/src/gui/480x272/widgets/value.cpp b/radio/src/gui/480x272/widgets/value.cpp index 093b26eaa..5ce08a87f 100644 --- a/radio/src/gui/480x272/widgets/value.cpp +++ b/radio/src/gui/480x272/widgets/value.cpp @@ -75,10 +75,15 @@ void ValueWidget::refresh() yValue = y+18; xLabel = x+NUMBERS_PADDING; yLabel = y+2; - if (field == MIXSRC_TX_GPS) +#if defined(INTERNAL_GPS) + if (field == MIXSRC_TX_GPS) { attrValue = LEFT | MIDSIZE; - else + } + else +#endif + { attrValue = LEFT | DBLSIZE; + } } if (field >= MIXSRC_FIRST_TIMER && field <= MIXSRC_LAST_TIMER) { diff --git a/radio/src/targets/horus/CMakeLists.txt b/radio/src/targets/horus/CMakeLists.txt index 19cb18ac2..c859dba60 100644 --- a/radio/src/targets/horus/CMakeLists.txt +++ b/radio/src/targets/horus/CMakeLists.txt @@ -54,12 +54,12 @@ set(GUI_SRC ${LAYOUTS_SRC} ${WIDGETS_SRC} ) -set(SRC ${SRC} gps.cpp) if(DISK_CACHE) set(SRC ${SRC} disk_cache.cpp) add_definitions(-DDISK_CACHE) endif() if(INTERNAL_GPS) + set(SRC ${SRC} gps.cpp) add_definitions(-DINTERNAL_GPS) message("Internal GPS enabled") endif()