From e1839e33f2cf308186a68fb55828c2826a002fc5 Mon Sep 17 00:00:00 2001 From: Jonathan Bennett Date: Sun, 10 Sep 2023 22:21:14 -0500 Subject: [PATCH] Lazy probe of GPS (#2781) * First attempt at lazy config of GPS * More GPS rework Break GPS init into smaller, interruptable steps Move more GPS commands into ubx.h Combine Setup functions * Move the rest of UBX messages to ubs.h --- src/gps/GPS.cpp | 717 +++++++++++++++----------------------------- src/gps/GPS.h | 39 ++- src/gps/NMEAGPS.cpp | 24 -- src/gps/NMEAGPS.h | 2 - src/gps/ubx.h | 161 ++++++++++ src/main.cpp | 22 +- src/sleep.cpp | 4 +- 7 files changed, 431 insertions(+), 538 deletions(-) diff --git a/src/gps/GPS.cpp b/src/gps/GPS.cpp index 91efbdf0d..1ee61d592 100644 --- a/src/gps/GPS.cpp +++ b/src/gps/GPS.cpp @@ -251,462 +251,23 @@ int GPS::getACK(uint8_t *buffer, uint16_t size, uint8_t requestedClass, uint8_t return 0; } -bool GPS::setupGPS() -{ - if (_serial_gps && !didSerialInit) { - didSerialInit = true; - -#ifdef ARCH_ESP32 - // In esp32 framework, setRxBufferSize needs to be initialized before Serial - _serial_gps->setRxBufferSize(SERIAL_BUFFER_SIZE); // the default is 256 -#endif - - // if the overrides are not dialled in, set them from the board definitions, if they exist - -#if defined(GPS_RX_PIN) - if (!config.position.rx_gpio) - config.position.rx_gpio = GPS_RX_PIN; -#endif -#if defined(GPS_TX_PIN) - if (!config.position.tx_gpio) - config.position.tx_gpio = GPS_TX_PIN; -#endif - -// #define BAUD_RATE 115200 -// ESP32 has a special set of parameters vs other arduino ports -#if defined(ARCH_ESP32) - if (config.position.rx_gpio) { - LOG_DEBUG("Using GPIO%d for GPS RX\n", config.position.rx_gpio); - LOG_DEBUG("Using GPIO%d for GPS TX\n", config.position.tx_gpio); - _serial_gps->begin(GPS_BAUDRATE, SERIAL_8N1, config.position.rx_gpio, config.position.tx_gpio); - } -#else - _serial_gps->begin(GPS_BAUDRATE); -#endif - - /* - * T-Beam-S3-Core will be preset to use gps Probe here, and other boards will not be changed first - */ -#if defined(GPS_UC6580) - _serial_gps->updateBaudRate(115200); - gnssModel = GNSS_MODEL_UC6850; -#else - for (int serialSpeed : {9600, 4800, 38400, 57600, 115200}) { - LOG_DEBUG("Probing for GPS at %d \n", serialSpeed); - gnssModel = probe(serialSpeed); - if (gnssModel != GNSS_MODEL_UNKNOWN) - break; - } - if (gnssModel == GNSS_MODEL_UNKNOWN) { - LOG_DEBUG("No GPS found, retrying at 9600 baud.\n"); - gnssModel = probe(9600); - } -#endif - - if (gnssModel == GNSS_MODEL_MTK) { - /* - * t-beam-s3-core uses the same L76K GNSS module as t-echo. - * Unlike t-echo, L76K uses 9600 baud rate for communication by default. - * */ - // _serial_gps->begin(9600); //The baud rate of 9600 has been initialized at the beginning of setupGPS, this line - // is the redundant part delay(250); - - // Initialize the L76K Chip, use GPS + GLONASS + BEIDOU - _serial_gps->write("$PCAS04,7*1E\r\n"); - delay(250); - // only ask for RMC and GGA - _serial_gps->write("$PCAS03,1,0,0,0,1,0,0,0,0,0,,,0,0*02\r\n"); - delay(250); - // Switch to Vehicle Mode, since SoftRF enables Aviation < 2g - _serial_gps->write("$PCAS11,3*1E\r\n"); - delay(250); - } else if (gnssModel == GNSS_MODEL_UC6850) { - - // use GPS + GLONASS - _serial_gps->write("$CFGSYS,h15\r\n"); - delay(250); - } else if (gnssModel == GNSS_MODEL_UBLOX) { - /* - uint8_t buffer[768] = {0}; - uint8_t _message_GNSS[8] = {0xb5, 0x62, // Sync message for UBX protocol - 0x06, 0x3e, // Message class and ID (UBX-CFG-GNSS) - 0x00, 0x00, // Length of payload (28 bytes) - 0x00, 0x00}; - UBXChecksum(_message_GNSS, sizeof(_message_GNSS)); - // Send the message to the module - _serial_gps->write(_message_GNSS, sizeof(_message_GNSS)); - int ackLen = getACK(buffer, sizeof(buffer), 0x06, 0x3e, 2000); - LOG_DEBUG("monver reply size = %d\n", ackLen); - LOG_DEBUG("Ack: "); - for (int i = 0; i < ackLen; i++) { - LOG_DEBUG("%02X", buffer[i]); - } - LOG_DEBUG("\n"); */ - - // Configure GNSS system to GPS+SBAS+GLONASS (Module may restart after this command) - // We need set it because by default it is GPS only, and we want to use GLONASS too - // Also we need SBAS for better accuracy and extra features - // ToDo: Dynamic configure GNSS systems depending of LoRa region - - if (strncmp(info.hwVersion, "00040007", 8) != - 0) { // The original ublox 6 is GPS only and doesn't support the UBX-CFG-GNSS message - if (strncmp(info.hwVersion, "00070000", 8) == 0) { // Max7 seems to only support GPS *or* GLONASS - LOG_DEBUG("Setting GPS+SBAS\n"); - uint8_t _message_GNSS[28] = { - 0xb5, 0x62, // Sync message for UBX protocol - 0x06, 0x3e, // Message class and ID (UBX-CFG-GNSS) - 0x14, 0x00, // Length of payload (28 bytes) - 0x00, // msgVer (0 for this version) - 0x00, // numTrkChHw (max number of hardware channels, read only, so it's always 0) - 0xff, // numTrkChUse (max number of channels to use, 0xff = max available) - 0x02, // numConfigBlocks (number of GNSS systems), most modules support maximum 3 GNSS systems - // GNSS config format: gnssId, resTrkCh, maxTrkCh, reserved1, flags - 0x00, 0x08, 0x10, 0x00, 0x01, 0x00, 0x00, 0x01, // GPS - 0x01, 0x01, 0x03, 0x00, 0x01, 0x00, 0x00, 0x01, // SBAS - 0x00, 0x00 // Checksum (to be calculated below) - }; - // Calculate the checksum and update the message. - UBXChecksum(_message_GNSS, sizeof(_message_GNSS)); - // Send the message to the module - _serial_gps->write(_message_GNSS, sizeof(_message_GNSS)); - } else { - uint8_t _message_GNSS[36] = { - 0xb5, 0x62, // Sync message for UBX protocol - 0x06, 0x3e, // Message class and ID (UBX-CFG-GNSS) - 0x1c, 0x00, // Length of payload (28 bytes) - 0x00, // msgVer (0 for this version) - 0x00, // numTrkChHw (max number of hardware channels, read only, so it's always 0) - 0xff, // numTrkChUse (max number of channels to use, 0xff = max available) - 0x03, // numConfigBlocks (number of GNSS systems), most modules support maximum 3 GNSS systems - // GNSS config format: gnssId, resTrkCh, maxTrkCh, reserved1, flags - 0x00, 0x08, 0x10, 0x00, 0x01, 0x00, 0x01, 0x01, // GPS - 0x01, 0x01, 0x03, 0x00, 0x01, 0x00, 0x01, 0x01, // SBAS - 0x06, 0x08, 0x0e, 0x00, 0x01, 0x00, 0x01, 0x01, // GLONASS - 0x00, 0x00 // Checksum (to be calculated below) - }; - // Calculate the checksum and update the message. - UBXChecksum(_message_GNSS, sizeof(_message_GNSS)); - // Send the message to the module - _serial_gps->write(_message_GNSS, sizeof(_message_GNSS)); - } - - if (getACK(0x06, 0x3e, 800) == GNSS_RESPONSE_NAK) { - // It's not critical if the module doesn't acknowledge this configuration. - // The module should operate adequately with its factory or previously saved settings. - // It appears that there is a firmware bug in some GPS modules: When an attempt is made - // to overwrite a saved state with identical values, no ACK/NAK is received, contrary to - // what is specified in the Ublox documentation. - // There is also a possibility that the module may be GPS-only. - LOG_INFO("Unable to reconfigure GNSS - defaults maintained. Is this module GPS-only?\n"); - } else { - if (strncmp(info.hwVersion, "00070000", 8) == 0) { - LOG_INFO("GNSS configured for GPS+SBAS. Pause for 0.75s before sending next command.\n"); - } else { - LOG_INFO("GNSS configured for GPS+SBAS+GLONASS. Pause for 0.75s before sending next command.\n"); - } - // Documentation say, we need wait atleast 0.5s after reconfiguration of GNSS module, before sending next - // commands - delay(750); - } - } - - // Enable interference resistance, because we are using LoRa, WiFi and Bluetooth on same board, - // and we need to reduce interference from them - uint8_t _message_JAM[16] = { - 0xB5, 0x62, // UBX protocol sync characters - 0x06, 0x39, // Message class and ID (UBX-CFG-ITFM) - 0x08, 0x00, // Length of payload (8 bytes) - // bbThreshold (Broadband jamming detection threshold) is set to 0x3F (63 in decimal) - // cwThreshold (CW jamming detection threshold) is set to 0x10 (16 in decimal) - // algorithmBits (Reserved algorithm settings) is set to 0x16B156 as recommended - // enable (Enable interference detection) is set to 1 (enabled) - 0x3F, 0x10, 0xB1, 0x56, // config: Interference config word - // generalBits (General settings) is set to 0x31E as recommended - // antSetting (Antenna setting, 0=unknown, 1=passive, 2=active) is set to 0 (unknown) - // ToDo: Set to 1 (passive) or 2 (active) if known, for example from UBX-MON-HW, or from board info - // enable2 (Set to 1 to scan auxiliary bands, u-blox 8 / u-blox M8 only, otherwise ignored) is set to 1 - // (enabled) - 0x1E, 0x03, 0x00, 0x01, // config2: Extra settings for jamming/interference monitor - 0x00, 0x00 // Checksum (calculated below) - }; - - // Calculate the checksum and update the message. - UBXChecksum(_message_JAM, sizeof(_message_JAM)); - - // Send the message to the module - _serial_gps->write(_message_JAM, sizeof(_message_JAM)); - - if (getACK(0x06, 0x39, 300) != GNSS_RESPONSE_OK) { - LOG_WARN("Unable to enable interference resistance.\n"); - } - - // Configure navigation engine expert settings: - uint8_t _message_NAVX5[48] = { - 0xb5, 0x62, // UBX protocol sync characters - 0x06, 0x23, // Message class and ID (UBX-CFG-NAVX5) - 0x28, 0x00, // Length of payload (40 bytes) - 0x00, 0x00, // msgVer (0 for this version) - // minMax flag = 1: apply min/max SVs settings - // minCno flag = 1: apply minimum C/N0 setting - // initial3dfix flag = 0: apply initial 3D fix settings - // aop flag = 1: apply aopCfg (useAOP flag) settings (AssistNow Autonomous) - 0x1B, 0x00, // mask1 (First parameters bitmask) - // adr flag = 0: apply ADR sensor fusion on/off setting (useAdr flag) - // If firmware is not ADR/UDR, enabling this flag will fail configuration - // ToDo: check this with UBX-MON-VER - 0x00, 0x00, 0x00, 0x00, // mask2 (Second parameters bitmask) - 0x00, 0x00, // Reserved - 0x03, // minSVs (Minimum number of satellites for navigation) = 3 - 0x10, // maxSVs (Maximum number of satellites for navigation) = 16 - 0x06, // minCNO (Minimum satellite signal level for navigation) = 6 dBHz - 0x00, // Reserved - 0x00, // iniFix3D (Initial fix must be 3D) = 0 (disabled) - 0x00, 0x00, // Reserved - 0x00, // ackAiding (Issue acknowledgements for assistance message input) = 0 (disabled) - 0x00, 0x00, // Reserved - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Reserved - 0x00, // Reserved - 0x01, // aopCfg (AssistNow Autonomous configuration) = 1 (enabled) - 0x00, 0x00, // Reserved - 0x00, 0x00, // Reserved - 0x00, 0x00, 0x00, 0x00, // Reserved - 0x00, 0x00, 0x00, // Reserved - 0x01, // useAdr (Enable/disable ADR sensor fusion) = 1 (enabled) - 0x00, 0x00 // Checksum (calculated below) - }; - - // Calculate the checksum and update the message. - UBXChecksum(_message_NAVX5, sizeof(_message_NAVX5)); - - // Send the message to the module - _serial_gps->write(_message_NAVX5, sizeof(_message_NAVX5)); - - if (getACK(0x06, 0x23, 300) != GNSS_RESPONSE_OK) { - LOG_WARN("Unable to configure extra settings.\n"); - } - - // ublox-M10S can be compatible with UBLOX traditional protocol, so the following sentence settings are also valid - - // Set GPS update rate to 1Hz - // Lowering the update rate helps to save power. - // Additionally, for some new modules like the M9/M10, an update rate lower than 5Hz - // is recommended to avoid a known issue with satellites disappearing. - uint8_t _message_1Hz[] = { - 0xB5, 0x62, // UBX protocol sync characters - 0x06, 0x08, // Message class and ID (UBX-CFG-RATE) - 0x06, 0x00, // Length of payload (6 bytes) - 0xE8, 0x03, // Measurement Rate (1000ms for 1Hz) - 0x01, 0x00, // Navigation rate, always 1 in GPS mode - 0x01, 0x00, // Time reference - 0x00, 0x00 // Placeholder for checksum, will be calculated next - }; - - // Calculate the checksum and update the message. - UBXChecksum(_message_1Hz, sizeof(_message_1Hz)); - - // Send the message to the module - _serial_gps->write(_message_1Hz, sizeof(_message_1Hz)); - - if (getACK(0x06, 0x08, 300) != GNSS_RESPONSE_OK) { - LOG_WARN("Unable to set GPS update rate.\n"); - } - - // Disable GGL. GGL - Geographic position (latitude and longitude), which provides the current geographical - // coordinates. - uint8_t _message_GGL[] = { - 0xB5, 0x62, // UBX sync characters - 0x06, 0x01, // Message class and ID (UBX-CFG-MSG) - 0x08, 0x00, // Length of payload (8 bytes) - 0xF0, 0x01, // NMEA ID for GLL - 0x01, // I/O Target 0=I/O, 1=UART1, 2=UART2, 3=USB, 4=SPI - 0x00, // Disable - 0x01, 0x01, 0x01, 0x01, // Reserved - 0x00, 0x00 // CK_A and CK_B (Checksum) - }; - - // Calculate the checksum and update the message. - UBXChecksum(_message_GGL, sizeof(_message_GGL)); - - // Send the message to the module - _serial_gps->write(_message_GGL, sizeof(_message_GGL)); - - if (getACK(0x06, 0x01, 300) != GNSS_RESPONSE_OK) { - LOG_WARN("Unable to disable NMEA GGL.\n"); - } - - // Enable GSA. GSA - GPS DOP and active satellites, used for detailing the satellites used in the positioning and - // the DOP (Dilution of Precision) - uint8_t _message_GSA[] = { - 0xB5, 0x62, // UBX sync characters - 0x06, 0x01, // Message class and ID (UBX-CFG-MSG) - 0x08, 0x00, // Length of payload (8 bytes) - 0xF0, 0x02, // NMEA ID for GSA - 0x01, // I/O Target 0=I/O, 1=UART1, 2=UART2, 3=USB, 4=SPI - 0x01, // Enable - 0x01, 0x01, 0x01, 0x01, // Reserved - 0x00, 0x00 // CK_A and CK_B (Checksum) - }; - UBXChecksum(_message_GSA, sizeof(_message_GSA)); - _serial_gps->write(_message_GSA, sizeof(_message_GSA)); - if (getACK(0x06, 0x01, 300) != GNSS_RESPONSE_OK) { - LOG_WARN("Unable to Enable NMEA GSA.\n"); - } - - // Disable GSV. GSV - Satellites in view, details the number and location of satellites in view. - uint8_t _message_GSV[] = { - 0xB5, 0x62, // UBX sync characters - 0x06, 0x01, // Message class and ID (UBX-CFG-MSG) - 0x08, 0x00, // Length of payload (8 bytes) - 0xF0, 0x03, // NMEA ID for GSV - 0x01, // I/O Target 0=I/O, 1=UART1, 2=UART2, 3=USB, 4=SPI - 0x00, // Disable - 0x01, 0x01, 0x01, 0x01, // Reserved - 0x00, 0x00 // CK_A and CK_B (Checksum) - }; - UBXChecksum(_message_GSV, sizeof(_message_GSV)); - _serial_gps->write(_message_GSV, sizeof(_message_GSV)); - if (getACK(0x06, 0x01, 300) != GNSS_RESPONSE_OK) { - LOG_WARN("Unable to disable NMEA GSV.\n"); - } - - // Disable VTG. VTG - Track made good and ground speed, which provides course and speed information relative to - // the ground. - uint8_t _message_VTG[] = { - 0xB5, 0x62, // UBX sync characters - 0x06, 0x01, // Message class and ID (UBX-CFG-MSG) - 0x08, 0x00, // Length of payload (8 bytes) - 0xF0, 0x05, // NMEA ID for VTG - 0x01, // I/O Target 0=I/O, 1=UART1, 2=UART2, 3=USB, 4=SPI - 0x00, // Disable - 0x01, 0x01, 0x01, 0x01, // Reserved - 0x00, 0x00 // CK_A and CK_B (Checksum) - }; - UBXChecksum(_message_VTG, sizeof(_message_VTG)); - _serial_gps->write(_message_VTG, sizeof(_message_VTG)); - if (getACK(0x06, 0x01, 300) != GNSS_RESPONSE_OK) { - LOG_WARN("Unable to disable NMEA VTG.\n"); - } - - // Enable RMC. RMC - Recommended Minimum data, the essential gps pvt (position, velocity, time) data. - uint8_t _message_RMC[] = { - 0xB5, 0x62, // UBX sync characters - 0x06, 0x01, // Message class and ID (UBX-CFG-MSG) - 0x08, 0x00, // Length of payload (8 bytes) - 0xF0, 0x04, // NMEA ID for RMC - 0x01, // I/O Target 0=I/O, 1=UART1, 2=UART2, 3=USB, 4=SPI - 0x01, // Enable - 0x01, 0x01, 0x01, 0x01, // Reserved - 0x00, 0x00 // CK_A and CK_B (Checksum) - }; - UBXChecksum(_message_RMC, sizeof(_message_RMC)); - _serial_gps->write(_message_RMC, sizeof(_message_RMC)); - if (getACK(0x06, 0x01, 300) != GNSS_RESPONSE_OK) { - LOG_WARN("Unable to enable NMEA RMC.\n"); - } - - // Enable GGA. GGA - Global Positioning System Fix Data, which provides 3D location and accuracy data. - uint8_t _message_GGA[] = { - 0xB5, 0x62, // UBX sync characters - 0x06, 0x01, // Message class and ID (UBX-CFG-MSG) - 0x08, 0x00, // Length of payload (8 bytes) - 0xF0, 0x00, // NMEA ID for GGA - 0x01, // I/O Target 0=I/O, 1=UART1, 2=UART2, 3=USB, 4=SPI - 0x01, // Enable - 0x01, 0x01, 0x01, 0x01, // Reserved - 0x00, 0x00 // CK_A and CK_B (Checksum) - }; - UBXChecksum(_message_GGA, sizeof(_message_GGA)); - _serial_gps->write(_message_GGA, sizeof(_message_GGA)); - if (getACK(0x06, 0x01, 300) != GNSS_RESPONSE_OK) { - LOG_WARN("Unable to enable NMEA GGA.\n"); - } - - // The Power Management configuration allows the GPS module to operate in different power modes for optimized power - // consumption. - // The modes supported are: - // 0x00 = Full power: The module operates at full power with no power saving. - // 0x01 = Balanced: The module dynamically adjusts the tracking behavior to balance power consumption. - // 0x02 = Interval: The module operates in a periodic mode, cycling between tracking and power saving states. - // 0x03 = Aggressive with 1 Hz: The module operates in a power saving mode with a 1 Hz update rate. - // 0x04 = Aggressive with 2 Hz: The module operates in a power saving mode with a 2 Hz update rate. - // 0x05 = Aggressive with 4 Hz: The module operates in a power saving mode with a 4 Hz update rate. - // The 'period' field specifies the position update and search period. It is only valid when the powerSetupValue is - // set to Interval; otherwise, it must be set to '0'. The 'onTime' field specifies the duration of the ON phase and - // must be smaller than the period. It is only valid when the powerSetupValue is set to Interval; otherwise, it must - // be set to '0'. - if (uBloxProtocolVersion >= 18) { - byte UBX_CFG_PMS[16] = { - 0xB5, 0x62, // UBX sync characters - 0x06, 0x86, // Message class and ID (UBX-CFG-PMS) - 0x08, 0x00, // Length of payload (6 bytes) - 0x00, // Version (0) - 0x03, // Power setup value - 0x00, 0x00, // period: not applicable, set to 0 - 0x00, 0x00, // onTime: not applicable, set to 0 - 0x97, 0x6F, // reserved, generated by u-center - 0x00, 0x00 // Placeholder for checksum, will be calculated next - }; - - // Calculate the checksum and update the message - UBXChecksum(UBX_CFG_PMS, sizeof(UBX_CFG_PMS)); - - // Send the message to the module - _serial_gps->write(UBX_CFG_PMS, sizeof(UBX_CFG_PMS)); - if (getACK(0x06, 0x86, 300) != GNSS_RESPONSE_OK) { - LOG_WARN("Unable to enable powersaving for GPS.\n"); - } - } else { - if (strncmp(info.hwVersion, "00040007", 8) == 0) { // This PSM mode has only been tested on this hardware - int msglen = makeUBXPacket(0x06, 0x11, 0x2, _message_CFG_RXM_PSM); - _serial_gps->write(UBXscratch, msglen); - if (getACK(0x06, 0x11, 300) != GNSS_RESPONSE_OK) { - LOG_WARN("Unable to enable powersaving mode for GPS.\n"); - } - msglen = makeUBXPacket(0x06, 0x3B, 44, _message_CFG_PM2); - _serial_gps->write(UBXscratch, msglen); - if (getACK(0x06, 0x3B, 300) != GNSS_RESPONSE_OK) { - LOG_WARN("Unable to enable powersaving details for GPS.\n"); - } - } else { - int msglen = makeUBXPacket(0x06, 0x11, 0x2, _message_CFG_RXM_ECO); - _serial_gps->write(UBXscratch, msglen); - if (getACK(0x06, 0x11, 300) != GNSS_RESPONSE_OK) { - LOG_WARN("Unable to enable powersaving ECO mode for GPS.\n"); - } - } - } - // We need save configuration to flash to make our config changes persistent - uint8_t _message_SAVE[21] = { - 0xB5, 0x62, // UBX protocol header - 0x06, 0x09, // UBX class ID (Configuration Input Messages), message ID (UBX-CFG-CFG) - 0x0D, 0x00, // Length of payload (13 bytes) - 0x00, 0x00, 0x00, 0x00, // clearMask: no sections cleared - 0xFF, 0xFF, 0x00, 0x00, // saveMask: save all sections - 0x00, 0x00, 0x00, 0x00, // loadMask: no sections loaded - 0x0F, // deviceMask: BBR, Flash, EEPROM, and SPI Flash - 0x00, 0x00 // Checksum (calculated below) - }; - - // Calculate the checksum and update the message. - UBXChecksum(_message_SAVE, sizeof(_message_SAVE)); - - // Send the message to the module - _serial_gps->write(_message_SAVE, sizeof(_message_SAVE)); - - if (getACK(0x06, 0x09, 300) != GNSS_RESPONSE_OK) { - LOG_WARN("Unable to save GNSS module configuration.\n"); - } else { - LOG_INFO("GNSS module configuration saved!\n"); - } - } - } - - return true; -} - bool GPS::setup() { + int msglen = 0; // Master power for the GPS +#ifdef PIN_GPS_PPS + // pulse per second + pinMode(PIN_GPS_PPS, INPUT); +#endif + +// Currently disabled per issue #525 (TinyGPS++ crash bug) +// when fixed upstream, can be un-disabled to enable 3D FixType and PDOP +#ifndef TINYGPS_OPTION_NO_CUSTOM_FIELDS + // see NMEAGPS.h + gsafixtype.begin(reader, NMEA_MSG_GXGSA, 2); + gsapdop.begin(reader, NMEA_MSG_GXGSA, 15); + LOG_DEBUG("Using " NMEA_MSG_GXGSA " for 3DFIX and PDOP\n"); +#endif #if defined(HAS_PMU) || defined(PIN_GPS_EN) if (config.position.gps_enabled) { @@ -724,18 +285,214 @@ bool GPS::setup() digitalWrite(PIN_GPS_RESET, !GPS_RESET_MODE); #endif setAwake(true); // Wake GPS power before doing any init - bool ok = setupGPS(); - if (ok) { - notifySleepObserver.observe(¬ifySleep); - notifyDeepSleepObserver.observe(¬ifyDeepSleep); - notifyGPSSleepObserver.observe(¬ifyGPSSleep); + if (_serial_gps && !didSerialInit) { + if (!GPSInitStarted) { + GPSInitStarted = true; +#ifdef ARCH_ESP32 + // In esp32 framework, setRxBufferSize needs to be initialized before Serial + _serial_gps->setRxBufferSize(SERIAL_BUFFER_SIZE); // the default is 256 +#endif + + // if the overrides are not dialled in, set them from the board definitions, if they exist + +#if defined(GPS_RX_PIN) + if (!config.position.rx_gpio) + config.position.rx_gpio = GPS_RX_PIN; +#endif +#if defined(GPS_TX_PIN) + if (!config.position.tx_gpio) + config.position.tx_gpio = GPS_TX_PIN; +#endif + +// #define BAUD_RATE 115200 +// ESP32 has a special set of parameters vs other arduino ports +#if defined(ARCH_ESP32) + if (config.position.rx_gpio) { + LOG_DEBUG("Using GPIO%d for GPS RX\n", config.position.rx_gpio); + LOG_DEBUG("Using GPIO%d for GPS TX\n", config.position.tx_gpio); + _serial_gps->begin(GPS_BAUDRATE, SERIAL_8N1, config.position.rx_gpio, config.position.tx_gpio); + } +#else + _serial_gps->begin(GPS_BAUDRATE); +#endif + + /* + * T-Beam-S3-Core will be preset to use gps Probe here, and other boards will not be changed first + */ +#if defined(GPS_UC6580) + _serial_gps->updateBaudRate(115200); + gnssModel = GNSS_MODEL_UC6850; +#else + } + LOG_DEBUG("Probing for GPS at %d \n", serialSpeeds[speedSelect]); + gnssModel = probe(serialSpeeds[speedSelect]); + if (gnssModel == GNSS_MODEL_UNKNOWN) { + if (++speedSelect == sizeof(serialSpeeds) / sizeof(int)) { + speedSelect = 0; + if (--probeTries == 0) { + LOG_WARN("Giving up on GPS probe and setting to 9600.\n"); + return true; + } + } + return false; +#endif + } + + if (gnssModel == GNSS_MODEL_MTK) { + /* + * t-beam-s3-core uses the same L76K GNSS module as t-echo. + * Unlike t-echo, L76K uses 9600 baud rate for communication by default. + * */ + + // Initialize the L76K Chip, use GPS + GLONASS + BEIDOU + _serial_gps->write("$PCAS04,7*1E\r\n"); + delay(250); + // only ask for RMC and GGA + _serial_gps->write("$PCAS03,1,0,0,0,1,0,0,0,0,0,,,0,0*02\r\n"); + delay(250); + // Switch to Vehicle Mode, since SoftRF enables Aviation < 2g + _serial_gps->write("$PCAS11,3*1E\r\n"); + delay(250); + } else if (gnssModel == GNSS_MODEL_UC6850) { + + // use GPS + GLONASS + _serial_gps->write("$CFGSYS,h15\r\n"); + delay(250); + } else if (gnssModel == GNSS_MODEL_UBLOX) { + // Configure GNSS system to GPS+SBAS+GLONASS (Module may restart after this command) + // We need set it because by default it is GPS only, and we want to use GLONASS too + // Also we need SBAS for better accuracy and extra features + // ToDo: Dynamic configure GNSS systems depending of LoRa region + + if (strncmp(info.hwVersion, "00040007", 8) != + 0) { // The original ublox 6 is GPS only and doesn't support the UBX-CFG-GNSS message + if (strncmp(info.hwVersion, "00070000", 8) == 0) { // Max7 seems to only support GPS *or* GLONASS + LOG_DEBUG("Setting GPS+SBAS\n"); + msglen = makeUBXPacket(0x06, 0x3e, sizeof(_message_GNSS_7), _message_GNSS_7); + _serial_gps->write(UBXscratch, msglen); + } else { + msglen = makeUBXPacket(0x06, 0x3e, sizeof(_message_GNSS), _message_GNSS); + _serial_gps->write(UBXscratch, msglen); + } + + if (getACK(0x06, 0x3e, 800) == GNSS_RESPONSE_NAK) { + // It's not critical if the module doesn't acknowledge this configuration. + LOG_INFO("Unable to reconfigure GNSS - defaults maintained. Is this module GPS-only?\n"); + } else { + if (strncmp(info.hwVersion, "00070000", 8) == 0) { + LOG_INFO("GNSS configured for GPS+SBAS. Pause for 0.75s before sending next command.\n"); + } else { + LOG_INFO("GNSS configured for GPS+SBAS+GLONASS. Pause for 0.75s before sending next command.\n"); + } + // Documentation say, we need wait atleast 0.5s after reconfiguration of GNSS module, before sending next + // commands + delay(750); + } + } + + msglen = makeUBXPacket(0x06, 0x39, sizeof(_message_JAM), _message_JAM); + _serial_gps->write(UBXscratch, msglen); + if (getACK(0x06, 0x39, 300) != GNSS_RESPONSE_OK) { + LOG_WARN("Unable to enable interference resistance.\n"); + } + + msglen = makeUBXPacket(0x06, 0x23, sizeof(_message_NAVX5), _message_NAVX5); + _serial_gps->write(UBXscratch, msglen); + if (getACK(0x06, 0x23, 300) != GNSS_RESPONSE_OK) { + LOG_WARN("Unable to configure extra settings.\n"); + } + + // ublox-M10S can be compatible with UBLOX traditional protocol, so the following sentence settings are also valid + + msglen = makeUBXPacket(0x06, 0x08, sizeof(_message_1HZ), _message_1HZ); + _serial_gps->write(UBXscratch, msglen); + if (getACK(0x06, 0x08, 300) != GNSS_RESPONSE_OK) { + LOG_WARN("Unable to set GPS update rate.\n"); + } + + msglen = makeUBXPacket(0x06, 0x01, sizeof(_message_GGL), _message_GGL); + _serial_gps->write(UBXscratch, msglen); + if (getACK(0x06, 0x01, 300) != GNSS_RESPONSE_OK) { + LOG_WARN("Unable to disable NMEA GGL.\n"); + } + + msglen = makeUBXPacket(0x06, 0x01, sizeof(_message_GSA), _message_GSA); + _serial_gps->write(UBXscratch, msglen); + if (getACK(0x06, 0x01, 300) != GNSS_RESPONSE_OK) { + LOG_WARN("Unable to Enable NMEA GSA.\n"); + } + + msglen = makeUBXPacket(0x06, 0x01, sizeof(_message_GSV), _message_GSV); + _serial_gps->write(UBXscratch, msglen); + if (getACK(0x06, 0x01, 300) != GNSS_RESPONSE_OK) { + LOG_WARN("Unable to disable NMEA GSV.\n"); + } + + msglen = makeUBXPacket(0x06, 0x01, sizeof(_message_VTG), _message_VTG); + _serial_gps->write(UBXscratch, msglen); + if (getACK(0x06, 0x01, 300) != GNSS_RESPONSE_OK) { + LOG_WARN("Unable to disable NMEA VTG.\n"); + } + + msglen = makeUBXPacket(0x06, 0x01, sizeof(_message_RMC), _message_RMC); + _serial_gps->write(UBXscratch, msglen); + if (getACK(0x06, 0x01, 300) != GNSS_RESPONSE_OK) { + LOG_WARN("Unable to enable NMEA RMC.\n"); + } + + msglen = makeUBXPacket(0x06, 0x01, sizeof(_message_GGA), _message_GGA); + _serial_gps->write(UBXscratch, msglen); + if (getACK(0x06, 0x01, 300) != GNSS_RESPONSE_OK) { + LOG_WARN("Unable to enable NMEA GGA.\n"); + } + + if (uBloxProtocolVersion >= 18) { + msglen = makeUBXPacket(0x06, 0x86, sizeof(_message_PMS), _message_PMS); + _serial_gps->write(UBXscratch, msglen); + if (getACK(0x06, 0x86, 300) != GNSS_RESPONSE_OK) { + LOG_WARN("Unable to enable powersaving for GPS.\n"); + } + } else { + if (strncmp(info.hwVersion, "00040007", 8) == 0) { // This PSM mode has only been tested on this hardware + msglen = makeUBXPacket(0x06, 0x11, 0x2, _message_CFG_RXM_PSM); + _serial_gps->write(UBXscratch, msglen); + if (getACK(0x06, 0x11, 300) != GNSS_RESPONSE_OK) { + LOG_WARN("Unable to enable powersaving mode for GPS.\n"); + } + msglen = makeUBXPacket(0x06, 0x3B, 44, _message_CFG_PM2); + _serial_gps->write(UBXscratch, msglen); + if (getACK(0x06, 0x3B, 300) != GNSS_RESPONSE_OK) { + LOG_WARN("Unable to enable powersaving details for GPS.\n"); + } + } else { + msglen = makeUBXPacket(0x06, 0x11, 0x2, _message_CFG_RXM_ECO); + _serial_gps->write(UBXscratch, msglen); + if (getACK(0x06, 0x11, 300) != GNSS_RESPONSE_OK) { + LOG_WARN("Unable to enable powersaving ECO mode for GPS.\n"); + } + } + } + + msglen = makeUBXPacket(0x06, 0x09, sizeof(_message_SAVE), _message_SAVE); + _serial_gps->write(UBXscratch, msglen); + if (getACK(0x06, 0x09, 300) != GNSS_RESPONSE_OK) { + LOG_WARN("Unable to save GNSS module configuration.\n"); + } else { + LOG_INFO("GNSS module configuration saved!\n"); + } + } + didSerialInit = true; } + notifySleepObserver.observe(¬ifySleep); + notifyDeepSleepObserver.observe(¬ifyDeepSleep); + notifyGPSSleepObserver.observe(¬ifyGPSSleep); + if (config.position.gps_enabled == false && config.position.fixed_position == false) { setAwake(false); } - return ok; + return true; } GPS::~GPS() @@ -865,6 +622,28 @@ void GPS::publishUpdate() int32_t GPS::runOnce() { + if (!GPSInitFinished) { + if (!setup()) + return 2000; // Setup failed, re-run in two seconds + gpsStatus->observe(&gps->newStatus); + + // We have now loaded our saved preferences from flash + + // ONCE we will factory reset the GPS for bug #327 + if (gps && !devicestate.did_gps_reset) { + LOG_WARN("GPS FactoryReset requested\n"); + if (gps->factoryReset()) { // If we don't succeed try again next time + devicestate.did_gps_reset = true; + nodeDB.saveToDisk(SEGMENT_DEVICESTATE); + } + } + GPSInitFinished = true; + if (config.position.gps_enabled == false) { + doGPSpowersave(false); + return 0; + } + } + // Repeaters have no need for GPS if (config.device.role == meshtastic_Config_DeviceConfig_Role_REPEATER) disable(); @@ -1138,24 +917,6 @@ GPS *createGps() #if !HAS_GPS return nullptr; #else - if (config.position.gps_enabled) { -#ifdef GPS_ALTITUDE_HAE - LOG_DEBUG("Using HAE altitude model\n"); -#else - LOG_DEBUG("Using MSL altitude model\n"); -#endif - if (GPS::_serial_gps) { - // Some boards might have only the TX line from the GPS connected, in that case, we can't configure it at all. - // Just assume NMEA at 9600 baud. - GPS *new_gps = new NMEAGPS(); - new_gps->setup(); - return new_gps; - } - } else { - GPS *new_gps = new NMEAGPS(); - new_gps->setup(); - return new_gps; - } - return nullptr; + return new NMEAGPS(); #endif } \ No newline at end of file diff --git a/src/gps/GPS.h b/src/gps/GPS.h index f5254890d..67ff69068 100644 --- a/src/gps/GPS.h +++ b/src/gps/GPS.h @@ -37,6 +37,10 @@ class GPS : private concurrency::OSThread { private: uint32_t lastWakeStartMsec = 0, lastSleepStartMsec = 0, lastWhileActiveMsec = 0; + const int serialSpeeds[6] = {9600, 4800, 38400, 57600, 115200, 9600}; + + int speedSelect = 0; + int probeTries = 2; /** * hasValidLocation - indicates that the position variables contain a complete @@ -52,6 +56,9 @@ class GPS : private concurrency::OSThread bool hasGPS = false; // Do we have a GPS we are talking to + bool GPSInitFinished = false; // Init thread finished? + bool GPSInitStarted = false; // Init thread finished? + uint8_t numSatellites = 0; CallbackObserver notifySleepObserver = CallbackObserver(this, &GPS::prepareSleep); @@ -62,10 +69,24 @@ class GPS : private concurrency::OSThread /** If !NULL we will use this serial port to construct our GPS */ static HardwareSerial *_serial_gps; - static const uint8_t _message_PMREQ[8]; - static const uint8_t _message_CFG_RXM_PSM[2]; - static const uint8_t _message_CFG_RXM_ECO[2]; - static const uint8_t _message_CFG_PM2[44]; + static const uint8_t _message_PMREQ[]; + static const uint8_t _message_CFG_RXM_PSM[]; + static const uint8_t _message_CFG_RXM_ECO[]; + static const uint8_t _message_CFG_PM2[]; + static const uint8_t _message_GNSS_7[]; + static const uint8_t _message_GNSS[]; + static const uint8_t _message_JAM[]; + static const uint8_t _message_NAVX5[]; + static const uint8_t _message_1HZ[]; + static const uint8_t _message_GGL[]; + static const uint8_t _message_GSA[]; + static const uint8_t _message_GSV[]; + static const uint8_t _message_VTG[]; + static const uint8_t _message_RMC[]; + static const uint8_t _message_GGA[]; + static const uint8_t _message_PMS[]; + static const uint8_t _message_SAVE[]; + meshtastic_Position p = meshtastic_Position_init_default; GPS() : concurrency::OSThread("GPS") {} @@ -111,10 +132,11 @@ class GPS : private concurrency::OSThread // scratch space for creating ublox packets uint8_t UBXscratch[250] = {0}; - protected: - /// Do gps chipset specific init, return true for success - virtual bool setupGPS(); + int getACK(uint8_t *buffer, uint16_t size, uint8_t requestedClass, uint8_t requestedID, uint32_t waitMillis); + GPS_RESPONSE getACK(uint8_t c, uint8_t i, uint32_t waitMillis); + GPS_RESPONSE getACK(const char *message, uint32_t waitMillis); + protected: /// If possible force the GPS into sleep/low power mode virtual void sleep(); @@ -189,9 +211,6 @@ class GPS : private concurrency::OSThread String getNMEA(); GnssModel_t probe(int serialSpeed); - int getACK(uint8_t *buffer, uint16_t size, uint8_t requestedClass, uint8_t requestedID, uint32_t waitMillis); - GPS_RESPONSE getACK(uint8_t c, uint8_t i, uint32_t waitMillis); - GPS_RESPONSE getACK(const char *message, uint32_t waitMillis); // delay counter to allow more sats before fixed position stops GPS thread uint8_t fixeddelayCtr = 0; diff --git a/src/gps/NMEAGPS.cpp b/src/gps/NMEAGPS.cpp index 202185a3b..f62a1aee8 100644 --- a/src/gps/NMEAGPS.cpp +++ b/src/gps/NMEAGPS.cpp @@ -36,30 +36,6 @@ bool NMEAGPS::factoryReset() return true; } -bool NMEAGPS::setupGPS() -{ - GPS::setupGPS(); - -#ifdef PIN_GPS_PPS - // pulse per second - // FIXME - move into shared GPS code - pinMode(PIN_GPS_PPS, INPUT); -#endif - -// Currently disabled per issue #525 (TinyGPS++ crash bug) -// when fixed upstream, can be un-disabled to enable 3D FixType and PDOP -#ifndef TINYGPS_OPTION_NO_CUSTOM_FIELDS - // see NMEAGPS.h - gsafixtype.begin(reader, NMEA_MSG_GXGSA, 2); - gsapdop.begin(reader, NMEA_MSG_GXGSA, 15); - LOG_DEBUG("Using " NMEA_MSG_GXGSA " for 3DFIX and PDOP\n"); -#else - LOG_DEBUG("GxGSA NOT available\n"); -#endif - - return true; -} - /** * Perform any processing that should be done only while the GPS is awake and looking for a fix. * Override this method to check for new locations diff --git a/src/gps/NMEAGPS.h b/src/gps/NMEAGPS.h index 85521077a..ea918de66 100644 --- a/src/gps/NMEAGPS.h +++ b/src/gps/NMEAGPS.h @@ -24,8 +24,6 @@ class NMEAGPS : public GPS #endif public: - virtual bool setupGPS() override; - virtual bool factoryReset() override; protected: diff --git a/src/gps/ubx.h b/src/gps/ubx.h index a81b52e80..6493b2ce7 100644 --- a/src/gps/ubx.h +++ b/src/gps/ubx.h @@ -28,4 +28,165 @@ const uint8_t GPS::_message_CFG_PM2[] PROGMEM = { 0x03, 0x00, 0x87, 0x02, // reserved 0x00, 0x00, 0xFF, 0x00, // reserved 0x01, 0x00, 0xD6, 0x4D // reserved +}; + +const uint8_t GPS::_message_GNSS_7[] = { + 0x00, // msgVer (0 for this version) + 0x00, // numTrkChHw (max number of hardware channels, read only, so it's always 0) + 0xff, // numTrkChUse (max number of channels to use, 0xff = max available) + 0x02, // numConfigBlocks (number of GNSS systems), most modules support maximum 3 GNSS systems + // GNSS config format: gnssId, resTrkCh, maxTrkCh, reserved1, flags + 0x00, 0x08, 0x10, 0x00, 0x01, 0x00, 0x00, 0x01, // GPS + 0x01, 0x01, 0x03, 0x00, 0x01, 0x00, 0x00, 0x01 // SBAS +}; + +// It's not critical if the module doesn't acknowledge this configuration. +// The module should operate adequately with its factory or previously saved settings. +// It appears that there is a firmware bug in some GPS modules: When an attempt is made +// to overwrite a saved state with identical values, no ACK/NAK is received, contrary to +// what is specified in the Ublox documentation. +// There is also a possibility that the module may be GPS-only. +const uint8_t GPS::_message_GNSS[] = { + 0x00, // msgVer (0 for this version) + 0x00, // numTrkChHw (max number of hardware channels, read only, so it's always 0) + 0xff, // numTrkChUse (max number of channels to use, 0xff = max available) + 0x03, // numConfigBlocks (number of GNSS systems), most modules support maximum 3 GNSS systems + // GNSS config format: gnssId, resTrkCh, maxTrkCh, reserved1, flags + 0x00, 0x08, 0x10, 0x00, 0x01, 0x00, 0x01, 0x01, // GPS + 0x01, 0x01, 0x03, 0x00, 0x01, 0x00, 0x01, 0x01, // SBAS + 0x06, 0x08, 0x0e, 0x00, 0x01, 0x00, 0x01, 0x01 // GLONASS +}; + +// Enable interference resistance, because we are using LoRa, WiFi and Bluetooth on same board, +// and we need to reduce interference from them +const uint8_t GPS::_message_JAM[] = { + // bbThreshold (Broadband jamming detection threshold) is set to 0x3F (63 in decimal) + // cwThreshold (CW jamming detection threshold) is set to 0x10 (16 in decimal) + // algorithmBits (Reserved algorithm settings) is set to 0x16B156 as recommended + // enable (Enable interference detection) is set to 1 (enabled) + 0x3F, 0x10, 0xB1, 0x56, // config: Interference config word + // generalBits (General settings) is set to 0x31E as recommended + // antSetting (Antenna setting, 0=unknown, 1=passive, 2=active) is set to 0 (unknown) + // ToDo: Set to 1 (passive) or 2 (active) if known, for example from UBX-MON-HW, or from board info + // enable2 (Set to 1 to scan auxiliary bands, u-blox 8 / u-blox M8 only, otherwise ignored) is set to 1 + // (enabled) + 0x1E, 0x03, 0x00, 0x01 // config2: Extra settings for jamming/interference monitor +}; + +// Configure navigation engine expert settings: +const uint8_t GPS::_message_NAVX5[] = { + 0x00, 0x00, // msgVer (0 for this version) + // minMax flag = 1: apply min/max SVs settings + // minCno flag = 1: apply minimum C/N0 setting + // initial3dfix flag = 0: apply initial 3D fix settings + // aop flag = 1: apply aopCfg (useAOP flag) settings (AssistNow Autonomous) + 0x1B, 0x00, // mask1 (First parameters bitmask) + // adr flag = 0: apply ADR sensor fusion on/off setting (useAdr flag) + // If firmware is not ADR/UDR, enabling this flag will fail configuration + // ToDo: check this with UBX-MON-VER + 0x00, 0x00, 0x00, 0x00, // mask2 (Second parameters bitmask) + 0x00, 0x00, // Reserved + 0x03, // minSVs (Minimum number of satellites for navigation) = 3 + 0x10, // maxSVs (Maximum number of satellites for navigation) = 16 + 0x06, // minCNO (Minimum satellite signal level for navigation) = 6 dBHz + 0x00, // Reserved + 0x00, // iniFix3D (Initial fix must be 3D) = 0 (disabled) + 0x00, 0x00, // Reserved + 0x00, // ackAiding (Issue acknowledgements for assistance message input) = 0 (disabled) + 0x00, 0x00, // Reserved + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Reserved + 0x00, // Reserved + 0x01, // aopCfg (AssistNow Autonomous configuration) = 1 (enabled) + 0x00, 0x00, // Reserved + 0x00, 0x00, // Reserved + 0x00, 0x00, 0x00, 0x00, // Reserved + 0x00, 0x00, 0x00, // Reserved + 0x01, // useAdr (Enable/disable ADR sensor fusion) = 1 (enabled) +}; + +// Set GPS update rate to 1Hz +// Lowering the update rate helps to save power. +// Additionally, for some new modules like the M9/M10, an update rate lower than 5Hz +// is recommended to avoid a known issue with satellites disappearing. +const uint8_t GPS::_message_1HZ[] = { + 0xE8, 0x03, // Measurement Rate (1000ms for 1Hz) + 0x01, 0x00, // Navigation rate, always 1 in GPS mode + 0x01, 0x00, // Time reference +}; + +// Disable GGL. GGL - Geographic position (latitude and longitude), which provides the current geographical +// coordinates. +const uint8_t GPS::_message_GGL[] = { + 0xF0, 0x01, // NMEA ID for GLL + 0x01, // I/O Target 0=I/O, 1=UART1, 2=UART2, 3=USB, 4=SPI + 0x00, // Disable + 0x01, 0x01, 0x01, 0x01 // Reserved +}; + +// Enable GSA. GSA - GPS DOP and active satellites, used for detailing the satellites used in the positioning and +// the DOP (Dilution of Precision) +const uint8_t GPS::_message_GSA[] = { + 0xF0, 0x02, // NMEA ID for GSA + 0x01, // I/O Target 0=I/O, 1=UART1, 2=UART2, 3=USB, 4=SPI + 0x01, // Enable + 0x01, 0x01, 0x01, 0x01 // Reserved +}; + +// Disable GSV. GSV - Satellites in view, details the number and location of satellites in view. +const uint8_t GPS::_message_GSV[] = { + 0xF0, 0x03, // NMEA ID for GSV + 0x01, // I/O Target 0=I/O, 1=UART1, 2=UART2, 3=USB, 4=SPI + 0x00, // Disable + 0x01, 0x01, 0x01, 0x01 // Reserved +}; + +// Disable VTG. VTG - Track made good and ground speed, which provides course and speed information relative to +// the ground. +const uint8_t GPS::_message_VTG[] = { + 0xF0, 0x05, // NMEA ID for VTG + 0x01, // I/O Target 0=I/O, 1=UART1, 2=UART2, 3=USB, 4=SPI + 0x00, // Disable + 0x01, 0x01, 0x01, 0x01 // Reserved +}; + +// Enable RMC. RMC - Recommended Minimum data, the essential gps pvt (position, velocity, time) data. +const uint8_t GPS::_message_RMC[] = { + 0xF0, 0x04, // NMEA ID for RMC + 0x01, // I/O Target 0=I/O, 1=UART1, 2=UART2, 3=USB, 4=SPI + 0x01, // Enable + 0x01, 0x01, 0x01, 0x01 // Reserved +}; + +// Enable GGA. GGA - Global Positioning System Fix Data, which provides 3D location and accuracy data. +const uint8_t GPS::_message_GGA[] = { + 0xF0, 0x00, // NMEA ID for GGA + 0x01, // I/O Target 0=I/O, 1=UART1, 2=UART2, 3=USB, 4=SPI + 0x01, // Enable + 0x01, 0x01, 0x01, 0x01 // Reserved +}; + +// The Power Management configuration allows the GPS module to operate in different power modes for optimized +// power consumption. The modes supported are: 0x00 = Full power: The module operates at full power with no power +// saving. 0x01 = Balanced: The module dynamically adjusts the tracking behavior to balance power consumption. +// 0x02 = Interval: The module operates in a periodic mode, cycling between tracking and power saving states. +// 0x03 = Aggressive with 1 Hz: The module operates in a power saving mode with a 1 Hz update rate. +// 0x04 = Aggressive with 2 Hz: The module operates in a power saving mode with a 2 Hz update rate. +// 0x05 = Aggressive with 4 Hz: The module operates in a power saving mode with a 4 Hz update rate. +// The 'period' field specifies the position update and search period. It is only valid when the powerSetupValue +// is set to Interval; otherwise, it must be set to '0'. The 'onTime' field specifies the duration of the ON phase +// and must be smaller than the period. It is only valid when the powerSetupValue is set to Interval; otherwise, +// it must be set to '0'. +const uint8_t GPS::_message_PMS[] = { + 0x00, // Version (0) + 0x03, // Power setup value + 0x00, 0x00, // period: not applicable, set to 0 + 0x00, 0x00, // onTime: not applicable, set to 0 + 0x97, 0x6F // reserved, generated by u-center +}; + +const uint8_t GPS::_message_SAVE[] = { + 0x00, 0x00, 0x00, 0x00, // clearMask: no sections cleared + 0xFF, 0xFF, 0x00, 0x00, // saveMask: save all sections + 0x00, 0x00, 0x00, 0x00, // loadMask: no sections loaded + 0x0F // deviceMask: BBR, Flash, EEPROM, and SPI Flash }; \ No newline at end of file diff --git a/src/main.cpp b/src/main.cpp index e67603c64..d31ec3dba 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -559,6 +559,7 @@ void setup() readFromRTC(); // read the main CPU RTC at first (in case we can't get GPS time) nodeStatus->observe(&nodeDB.newStatus); + gps = createGps(); service.init(); @@ -736,27 +737,6 @@ void setup() PowerFSM_setup(); // we will transition to ON in a couple of seconds, FIXME, only do this for cold boots, not waking from SDS powerFSMthread = new PowerFSMThread(); - gps = createGps(); - - if (gps) { - gpsStatus->observe(&gps->newStatus); - if (config.position.gps_enabled == false && config.position.fixed_position == false) { - doGPSpowersave(false); - } - } else { - LOG_WARN("No GPS found - running without GPS\n"); - } - // We have now loaded our saved preferences from flash - - // ONCE we will factory reset the GPS for bug #327 - if (gps && !devicestate.did_gps_reset) { - LOG_WARN("GPS FactoryReset requested\n"); - if (gps->factoryReset()) { // If we don't succeed try again next time - devicestate.did_gps_reset = true; - nodeDB.saveToDisk(SEGMENT_DEVICESTATE); - } - } - // setBluetoothEnable(false); we now don't start bluetooth until we enter the proper state setCPUFast(false); // 80MHz is fine for our slow peripherals } diff --git a/src/sleep.cpp b/src/sleep.cpp index 891cce228..9df5da686 100644 --- a/src/sleep.cpp +++ b/src/sleep.cpp @@ -209,9 +209,7 @@ void doGPSpowersave(bool on) uint8_t msglen; notifyGPSSleep.notifyObservers(NULL); msglen = gps->makeUBXPacket(0x02, 0x41, 0x08, gps->_message_PMREQ); - for (int i = 0; i < msglen; i++) { - gps->_serial_gps->write(gps->UBXscratch, msglen); - } + gps->_serial_gps->write(gps->UBXscratch, msglen); } else { gps->forceWake(1); gps->_serial_gps->write(0xFF);