Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
92 changes: 80 additions & 12 deletions src/main/io/gps_ublox.c
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,9 @@ static const char * baudInitDataNMEA[GPS_BAUDRATE_COUNT] = {

static ubx_nav_sig_info satelites[UBLOX_MAX_SIGNALS] = {};

// Set from the MON-VER extensions, where a dual band receiver names itself, as in FWVER=SPGL1L5
static bool ubxDualBand = false;

// MON-RF noise value (noisePerMS) reported by UBX-MON-RF as U2 at payload offset 0x10
static uint16_t monRfNoisePerMs = 0;
static uint16_t monAgcCount = 0;
Expand Down Expand Up @@ -355,6 +358,49 @@ static int configureGNSS_SBAS(ubx_gnss_element_t * gnss_block)
return 1;
}

/*
* The major constellations to ask the receiver for: the ones selected, less any it
* does not have, cut down to as many as it says it can track at once. A receiver
* refuses a configuration it cannot run and carries on with the previous one, so a
* selection that does not fit would be lost whole. When it does not fit, the
* constellations INAV leaves off by default go first. The settings are left as they
* are, and apply in full on a receiver that can take them.
*/
static uint8_t ubloxGnssToEnable(void)
{
static const uint8_t leaveOutFirst[] = {
UBX_MON_GNSS_GLONASS_MASK, UBX_MON_GNSS_BEIDOU_MASK, UBX_MON_GNSS_GALILEO_MASK
};

uint8_t gnss = UBX_MON_GNSS_GPS_MASK;
if (gpsState.gpsConfig->ubloxUseGalileo) {
gnss |= UBX_MON_GNSS_GALILEO_MASK;
}
if (gpsState.gpsConfig->ubloxUseBeidou) {
gnss |= UBX_MON_GNSS_BEIDOU_MASK;
}
if (gpsState.gpsConfig->ubloxUseGlonass) {
gnss |= UBX_MON_GNSS_GLONASS_MASK;
}

// Until MON-GNSS answers nothing is known, and the selection goes out as it is. The
// count is only trusted next to a fresh mask: it is not cleared between attempts
if (!ubx_capabilities.supported) {
return gnss;
}

gnss &= ubx_capabilities.supported;

for (unsigned i = 0; i < ARRAYLEN(leaveOutFirst); i++) {
if (ubx_capabilities.capMaxGnss <= 0 || __builtin_popcount(gnss) <= ubx_capabilities.capMaxGnss) {
break;
}
gnss &= ~leaveOutFirst[i];
}

return gnss;
}

static int configureGNSS_GALILEO(ubx_gnss_element_t * gnss_block)
{
if (!gpsUbloxHasGalileo()) {
Expand All @@ -368,7 +414,7 @@ static int configureGNSS_GALILEO(ubx_gnss_element_t * gnss_block)
// 0x10 = Galileo E5a // off by default
// 0x20 = Galileo E5b // off by default
gnss_block->sigCfgMask = 0x01;
if (gpsState.gpsConfig->ubloxUseGalileo) {
if (ubloxGnssToEnable() & UBX_MON_GNSS_GALILEO_MASK) {
gnss_block->enabled = 1;
gnss_block->resTrkCh = 4;
} else {
Expand All @@ -392,7 +438,7 @@ static int configureGNSS_BEIDOU(ubx_gnss_element_t * gnss_block)
// 0x10 = BeiDou B2I // off by default
// 0x80 = BeiDou B2A // off by default
gnss_block->sigCfgMask = 0x01;
if (gpsState.gpsConfig->ubloxUseBeidou) {
if (ubloxGnssToEnable() & UBX_MON_GNSS_BEIDOU_MASK) {
gnss_block->enabled = 1;
gnss_block->resTrkCh = 4;
} else {
Expand Down Expand Up @@ -434,7 +480,7 @@ static int configureGNSS_GLONASS(ubx_gnss_element_t * gnss_block)
// 0x01 = GLONASS L1
// 0x10 = GLONASS L2 // off by default
gnss_block->sigCfgMask = 0x01;
if (gpsState.gpsConfig->ubloxUseGlonass) {
if (ubloxGnssToEnable() & UBX_MON_GNSS_GLONASS_MASK) {
gnss_block->enabled = 1;
gnss_block->resTrkCh = 4;
} else {
Expand All @@ -447,32 +493,46 @@ static int configureGNSS_GLONASS(ubx_gnss_element_t * gnss_block)

static void configureGNSS10(void)
{
const uint8_t gnss = ubloxGnssToEnable();
const bool useGalileo = gnss & UBX_MON_GNSS_GALILEO_MASK;
const bool useBeidou = gnss & UBX_MON_GNSS_BEIDOU_MASK;
const bool useGlonass = gnss & UBX_MON_GNSS_GLONASS_MASK;

// A dual band receiver has no B1I: its Beidou L1 signal is B1C, and it rejects a
// configuration that would leave one of the two bands enabled without the other
const bool useB1C = ubxDualBand || useGlonass;

ubx_config_data8_payload_t gnssConfigValues[] = {
// SBAS
{UBLOX_CFG_SIGNAL_SBAS_ENA, gpsState.gpsConfig->sbasMode == SBAS_NONE ? 0 : 1},
{UBLOX_CFG_SIGNAL_SBAS_L1CA_ENA, gpsState.gpsConfig->sbasMode == SBAS_NONE ? 0 : 1},

// Galileo
{UBLOX_CFG_SIGNAL_GAL_ENA, gpsState.gpsConfig->ubloxUseGalileo},
{UBLOX_CFG_SIGNAL_GAL_E1_ENA, gpsState.gpsConfig->ubloxUseGalileo},
{UBLOX_CFG_SIGNAL_GAL_ENA, useGalileo},
{UBLOX_CFG_SIGNAL_GAL_E1_ENA, useGalileo},

// Beidou
// M10 can't use BDS_B1I and Glonass together. Instead, use BDS_B1C
{UBLOX_CFG_SIGNAL_BDS_ENA, gpsState.gpsConfig->ubloxUseBeidou},
{UBLOX_CFG_SIGNAL_BDS_B1_ENA, gpsState.gpsConfig->ubloxUseBeidou && ! gpsState.gpsConfig->ubloxUseGlonass},
{UBLOX_CFG_SIGNAL_BDS_B1C_ENA, gpsState.gpsConfig->ubloxUseBeidou && gpsState.gpsConfig->ubloxUseGlonass},
{UBLOX_CFG_SIGNAL_BDS_ENA, useBeidou},
{UBLOX_CFG_SIGNAL_BDS_B1_ENA, useBeidou && !useB1C},
{UBLOX_CFG_SIGNAL_BDS_B1C_ENA, useBeidou && useB1C},

// Should be enabled with GPS
{UBLOX_CFG_QZSS_ENA, 1},
{UBLOX_CFG_QZSS_L1CA_ENA, 1},
{UBLOX_CFG_QZSS_L1S_ENA, 1},

// Glonass
{UBLOX_CFG_GLO_ENA, gpsState.gpsConfig->ubloxUseGlonass},
{UBLOX_CFG_GLO_L1_ENA, gpsState.gpsConfig->ubloxUseGlonass}
// Glonass, must stay last so it can be left out
{UBLOX_CFG_GLO_ENA, useGlonass},
{UBLOX_CFG_GLO_L1_ENA, useGlonass}
};

ubloxSendSetCfgBytes(gnssConfigValues, 12);
// A receiver without Glonass has no Glonass keys either, and one unknown key makes it
// reject the whole message, taking SBAS, Galileo, BeiDou and QZSS down with it. An
// empty mask means MON-GNSS never answered and nothing is known, so send them all.
const bool noGlonass = ubx_capabilities.supported && !gpsUbloxHasGlonass();

ubloxSendSetCfgBytes(gnssConfigValues, noGlonass ? 10 : 12);
}

static void configureGNSS(void)
Expand Down Expand Up @@ -765,6 +825,13 @@ static bool gpsParseFrameUBLOX(void)
break;
}
}

for (int j = 40; j < _payload_length; j += 30) {
if (strnstr((const char *)(_buffer.bytes + j), "L1L5", 30)) {
ubxDualBand = true;
break;
}
}
}
}
break;
Expand Down Expand Up @@ -1250,6 +1317,7 @@ STATIC_PROTOTHREAD(gpsProtocolStateThread)

// Attempt to detect GPS hw version
gpsState.hwVersion = UBX_HW_VERSION_UNKNOWN;
ubxDualBand = false;
gpsState.autoConfigStep = 0;

// Configure GPS module if enabled
Expand Down
Loading