diff --git a/radio/src/cli.cpp b/radio/src/cli.cpp index 873cd8d2d..7f8972756 100644 --- a/radio/src/cli.cpp +++ b/radio/src/cli.cpp @@ -708,6 +708,28 @@ int cliShowJitter(const char ** argv) } #endif +#if defined(INTERNAL_GPS) +int cliGps(const char ** argv) +{ + int 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); + } + else { + serialPrint("%s: Invalid arguments", argv[0]); + } + return 0; +} +#endif const CliCommand cliCommands[] = { { "beep", cliBeep, "[] []" }, @@ -731,6 +753,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..372427b03 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: @@ -255,3 +278,27 @@ void gpsWakeup() 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/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/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/main_arm.cpp b/radio/src/main_arm.cpp index ee32fcf9c..b05bd10ac 100644 --- a/radio/src/main_arm.cpp +++ b/radio/src/main_arm.cpp @@ -467,7 +467,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 e4c840d8f..97a92866e 100644 --- a/radio/src/targets/horus/CMakeLists.txt +++ b/radio/src/targets/horus/CMakeLists.txt @@ -1,5 +1,14 @@ set(PCBREV "13" CACHE STRING "PCB Revision") +set(INTERNAL_GPS_BAUDRATE "9600" CACHE STRING "Baud rate for internal GPS") 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) @@ -16,6 +25,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) @@ -44,11 +54,15 @@ 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() 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 ead735316..c49e33ed8 100644 --- a/radio/src/targets/horus/board.cpp +++ b/radio/src/targets/horus/board.cpp @@ -162,7 +162,7 @@ void boardInit() lcdInit(); backlightInit(); // TODO ? backlightEnable(100); - + audioInit(); init2MhzTimer(); init1msTimer(); @@ -171,8 +171,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 deaf67318..4299872e8 100644 --- a/radio/src/targets/horus/board.h +++ b/radio/src/targets/horus/board.h @@ -399,13 +399,12 @@ void hapticOff(void); void hapticOn(uint32_t pwmPercent); // GPS driver -#if PCBREV >= 13 -#define INTERNAL_GPS 1 -#else -#define INTERNAL_GPS 0 -#endif -void gpsInit(void); +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 2f2725d42..c9805ee42 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; @@ -56,9 +60,23 @@ void gpsInit() 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; @@ -85,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 diff --git a/radio/src/targets/horus/hal.h b/radio/src/targets/horus/hal.h index a8d2b49b9..3051a6fee 100644 --- a/radio/src/targets/horus/hal.h +++ b/radio/src/targets/horus/hal.h @@ -443,6 +443,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_