Loading files
This file is pinned to the selected release. Download the original to open it in your design tool.
66c1bda98This file is pinned to the selected release. Download the original to open it in your design tool.
#pragma once
#include <cstdint>
#include <cstddef>
#include <type_traits>
#include <algorithm>
namespace Gps {
enum DeviceVersion {
GPS_UNKNOWN,
GPS_M8,
GPS_M9,
GPS_F9,
};
constexpr uint8_t UBX_SYNC0 = 0xB5;
constexpr uint8_t UBX_SYNC1 = 0x62;
constexpr uint16_t UBX_SYNC = UBX_SYNC1 << 8 | UBX_SYNC0;
enum MsgClass: uint8_t
{
UBX_ACK = 0x05,
UBX_CFG = 0x06,
UBX_MON = 0x0A,
UBX_NAV = 0x01,
UBX_HNR = 0xB5,
NMEA_MSG = 0xF0,
};
enum MsgId: uint16_t
{
UBX_ACK_NAK = 0x00 << 8 | UBX_ACK, // Message not acknowledged
UBX_ACK_ACK = 0x01 << 8 | UBX_ACK, // Message acknowledged
UBX_MON_VER = 0x04 << 8 | UBX_MON, // Receiver and software version
UBX_CFG_CFG = 0x09 << 8 | UBX_CFG, // Clear, save and load configurations
UBX_CFG_DAT = 0x06 << 8 | UBX_CFG, // Set/Set datum
UBX_CFG_PRT = 0x00 << 8 | UBX_CFG, // Port configuration for UART ports
UBX_CFG_MSG = 0x01 << 8 | UBX_CFG, // Set message rate(s)
UBX_CFG_INF = 0x02 << 8 | UBX_CFG, // Information message configuration
UBX_CFG_RST = 0x04 << 8 | UBX_CFG, // Reset receiver / Clear backup data
UBX_CFG_RATE = 0x08 << 8 | UBX_CFG, // Navigation/measurement rate settings
UBX_CFG_SBAS = 0x16 << 8 | UBX_CFG, // SBAS configuration
UBX_CFG_NAV5 = 0x24 << 8 | UBX_CFG, // Navigation engine settings
UBX_CFG_GNSS = 0x3E << 8 | UBX_CFG, // GNSS system configuration (deprecated >PROTVER 23.01)
UBX_CFG_VALSET = 0x8A << 8 | UBX_CFG, // Configuration input (Generation 9+, replaces legacy CFG-* messages)
UBX_CFG_VALGET = 0x8B << 8 | UBX_CFG, // Configuration output (Generation 9+, replaces legacy CFG-* messages)
UBX_NAV_HPOSECEF = 0x13 << 8 | UBX_NAV, // High precision position solution in ECEF (28 Bytes)
UBX_NAV_HPOSLLH = 0x14 << 8 | UBX_NAV, // High precision geodetic position solution (36 Bytes)
UBX_NAV_POSECEF = 0x01 << 8 | UBX_NAV, // Position solution in ECEF (20 Bytes)
UBX_NAV_POSLLH = 0x02 << 8 | UBX_NAV, // Geodetic position solution (28 Bytes)
UBX_NAV_PVT = 0x07 << 8 | UBX_NAV, // Navigation position velocity time solution (92 Bytes)
UBX_NAV_SOL = 0x06 << 8 | UBX_NAV, // Navigation solution information (52 Bytes)
UBX_NAV_STATUS = 0x03 << 8 | UBX_NAV, // Receiver navigation status (16 Bytes)
UBX_NAV_SVINFO = 0x30 << 8 | UBX_NAV, // Space vehicle information (8 + 12xNumCh Bytes)
UBX_NAV_DOP = 0x04 << 8 | UBX_NAV, // Dilution of precision (18 Bytes)
UBX_NAV_SAT = 0x35 << 8 | UBX_NAV, // Satellite information (8 + 12xNumSats Bytes)
UBX_NAV_TIMEUTC = 0x21 << 8 | UBX_NAV, // UTC time solution (20 Bytes)
UBX_NAV_VELNED = 0x12 << 8 | UBX_NAV, // Velocity solution in NED frame (36 Bytes)
UBX_HNR_PVT = 0x00 << 8 | UBX_HNR, // High rate output of PVT solution (72 Bytes)
NMEA_MSG_GGA = 0x00 << 8 | NMEA_MSG, // Global positioning system fix data
NMEA_MSG_GLL = 0x01 << 8 | NMEA_MSG, // Latitude and longitude, with time of position fix and status
NMEA_MSG_GSA = 0x02 << 8 | NMEA_MSG, // GNSS DOP and active satellites
NMEA_MSG_GSV = 0x03 << 8 | NMEA_MSG, // GNSS satellites in view
NMEA_MSG_RMC = 0x04 << 8 | NMEA_MSG, // Recommended minimum data
NMEA_MSG_VTG = 0x05 << 8 | NMEA_MSG, // Course over ground and ground speed
};
inline uint16_t ubxChecksum(uint16_t init, uint8_t v)
{
uint8_t a = ((init & 0xff) + v) & 0xff;
uint8_t b = ((init >> 8) + a) & 0xff;
return b << 8 | a;
}
inline uint16_t ubxChecksum(uint16_t init, const uint8_t* it, size_t len)
{
while(len--)
{
init = ubxChecksum(init, *it++);
}
return init;
}
enum UbxState: uint8_t
{
UBX_STATE_IDLE,
UBX_STATE_SYNC,
UBX_STATE_CLASS,
UBX_STATE_ID,
UBX_STATE_LEN0,
UBX_STATE_LEN1,
UBX_STATE_PAYLOAD,
UBX_STATE_CRC0,
UBX_STATE_CRC1,
UBX_STATE_READY,
};
class UbxMessage
{
public:
UbxMessage() = default;
UbxMessage(const UbxMessage& m) = default;
UbxMessage& operator=(const UbxMessage& m) = default;
UbxMessage(uint8_t mId): msgId(mId), length(0), written(0) {}
uint16_t msgId = 0;
uint16_t length = 0;
uint8_t payload[512] = {0};
uint16_t crc = 0;
UbxState status{UBX_STATE_IDLE};
uint16_t written = 0;
uint16_t checksum() const
{
uint16_t c = 0;
c = ubxChecksum(c, msgId & 0xff);
c = ubxChecksum(c, msgId >> 8);
c = ubxChecksum(c, length & 0xff);
c = ubxChecksum(c, length >> 8);
for(size_t i = 0; i < length; i++) {
c = ubxChecksum(c, payload[i]);
}
return c;
}
template<typename Target>
const Target* getAs() const
{
return reinterpret_cast<const Target*>(payload);
}
bool isReady() const { return status == UBX_STATE_READY; }
bool isIdle() const { return status == UBX_STATE_IDLE; }
bool isResponse(MsgId id) const { return msgId == id; }
bool isAck() const { return msgId == UBX_ACK_ACK; }
bool isAck(MsgId id) const { return isAck() && id == (payload[1] << 8 | payload[0]); }
bool isNak() const { return msgId == UBX_ACK_NAK; }
bool isNak(MsgId id) const { return isNak() && id == (payload[1] << 8 | payload[0]); }
};
class UbxRequest
{
public:
UbxRequest(uint16_t msgId): msgId(msgId), length(0) {}
UbxRequest() = delete;
UbxRequest(const UbxRequest& m) = delete;
UbxRequest& operator=(const UbxRequest& m) = delete;
UbxRequest(UbxRequest&& m) = delete;
UbxRequest& operator=(UbxRequest&& m) = delete;
size_t write(const uint8_t * buff, size_t len)
{
if(length + len > sizeof(payload) - 2) return 0;
std::copy(buff, buff + len, payload + length);
length += len;
return len;
}
template<typename T>
size_t write(const T& data)
{
return write(reinterpret_cast<const uint8_t*>(&data), sizeof(T));
}
uint16_t msgId;
uint16_t length = 0;
uint8_t payload[72] = {0};
};
// -----------------------------------------------------------------
enum NmeaState: uint8_t
{
NMEA_STATE_IDLE,
NMEA_STATE_PAYLOAD,
NMEA_STATE_END,
NMEA_STATE_READY,
};
class NmeaMessage
{
public:
char payload[512] = {0};
size_t length = 0;
NmeaState status{NMEA_STATE_IDLE};
bool isReady() const { return status == NMEA_STATE_READY; }
bool isIdle() const { return status == NMEA_STATE_IDLE; }
};
// --------------------------------------------------------------
class UbxMonVer
{
public:
static constexpr MsgId ID = UBX_MON_VER;
} __attribute__((packed));
/**
* Used to get message rate
* @deprecated UBX-CFG-MSG is deprecated in favor of UBX-CFG-VALSET with CFG-MSGOUT-* keys
* kept for older firmware versions
*/
class UbxCfgMsg2
{
public:
static constexpr MsgId ID = UBX_CFG_MSG;
uint16_t msgId;
} __attribute__((packed));
/**
* Used to enable UBX and disable NMEA messages
* @deprecated UBX-CFG-MSG is deprecated in favor of UBX-CFG-VALSET with CFG-MSGOUT-* keys
* kept for older firmware versions
*/
class UbxCfgMsg3
{
public:
static constexpr MsgId ID = UBX_CFG_MSG;
uint16_t msgId;
uint8_t rate; // message output rate (0=disables, 1=every navigation solution, 2=every 2nd solution etc.)
} __attribute__((packed));
constexpr uint32_t CFG_MSGOUT_NMEA_GGA_UART1 = 0x209100bb; // NMEA GGA message output rate
constexpr uint32_t CFG_MSGOUT_NMEA_GLL_UART1 = 0x209100ca; // NMEA GLL message output rate
constexpr uint32_t CFG_MSGOUT_NMEA_GSA_UART1 = 0x209100c0; // NMEA GSA message output rate
constexpr uint32_t CFG_MSGOUT_NMEA_GSV_UART1 = 0x209100c5; // NMEA GSV message output rate
constexpr uint32_t CFG_MSGOUT_NMEA_RMC_UART1 = 0x209100e8; // NMEA RMC message output rate
constexpr uint32_t CFG_MSGOUT_NMEA_VTG_UART1 = 0x209100b1; // NMEA VTG message output rate
constexpr uint32_t CFG_MSGOUT_UBX_NAV_PVT_UART1 = 0x20910007; // UBX-NAV-PVT message output rate
constexpr uint32_t CFG_MSGOUT_UBX_NAV_SAT_UART1 = 0x20910016; // UBX-NAV-SAT message output rate
/**
* @deprecated UBX-CFG-MSG is deprecated in favor of UBX-CFG-VALSET with CFG-MSGOUT-* keys
* kept for older firmware versions
*/
class UbxCfgMsg8
{
public:
static constexpr MsgId ID = UBX_CFG_MSG;
uint16_t msgId;
uint8_t channels[6];
} __attribute__((packed));
/**
* Used to interface interface baud rate
* @deprecated UBX-CFG-PRT is deprecated in favor of UBX-CFG-VALSET with CFG-UART1-* keys
* kept for older firmware versions
*/
class UbxCfgPrt1
{
public:
static constexpr MsgId ID = UBX_CFG_PRT;
uint8_t portId;
} __attribute__((packed));
/**
* Used to set interface baud rate
* @deprecated UBX-CFG-PRT is deprecated in favor of UBX-CFG-VALSET with
* CFG-UART1-* keys
* kept for older firmware versions
*/
class UbxCfgPrt20
{
public:
static constexpr MsgId ID = UBX_CFG_PRT;
uint8_t portId;
uint8_t resered1;
uint16_t txReady;
uint32_t mode;
uint32_t baudRate;
uint16_t inProtoMask;
uint16_t outProtoMask;
uint16_t flags;
uint16_t resered2;
} __attribute__((packed));
constexpr uint32_t CFG_UART1_BAUDRATE = 0x40520001; // (?->target) UART1 baud rate (e.g. 9600, 115200)
constexpr uint32_t CFG_UART1_STOPBITS = 0x20520002; // (1) UART1 stop bits (0=half, 1=1, 2=1.5, 3=2)
constexpr uint32_t CFG_UART1_DATABITS = 0x20520003; // (8) UART1 data bits (0=8bits, 1=7bits)
constexpr uint32_t CFG_UART1_PARITY = 0x20520004; // (0) UART1 parity (0=none, 1=odd, 2=even)
constexpr uint32_t CFG_UART1_ENABLED = 0x10520005; // (1) UART1 enabled (0=disabled, 1=enabled)
constexpr uint32_t CFG_UART1_INPROT_UBX = 0x10730001; // (1) UART1 input protocol ubx
constexpr uint32_t CFG_UART1_INPROT_NMEA = 0x10730002; // (1) UART1 input protocol nmea
constexpr uint32_t CFG_UART1_OUTPROT_UBX = 0x10740001; // (1) UART1 output protocol ubx
constexpr uint32_t CFG_UART1_OUTPROT_NMEA = 0x10740002; // (1) UART1 output protocol nmea
/**
* Used to set measurement, navigation rate and time reference
* @deprecated UBX-CFG-RATE is deprecated in favor of UBX-CFG-VALSET with
* CFG_RATE-MEAS, CFG-RATE-NAV and CFG-RATE-TIMEREF keys
* kept for older firmware versions
*/
class UbxCfgRate6
{
public:
static constexpr MsgId ID = UBX_CFG_RATE;
uint16_t measRate; // in ms
uint16_t navRate; // ratio to measRate
uint16_t timeRef; // 0-utc, 1-gps, 2-glonass (18+), 3-BeiDou (18+), 4-Galileo (18+), 5-NavIC (29+)
} __attribute__((packed));
constexpr uint32_t CFG_RATE_MEAS = 0x30210001; // (1000->mRate) Measurement rate in ms
constexpr uint32_t CFG_RATE_NAV = 0x30210002; // (1) Navigation rate (number of measurement cycles)
constexpr uint32_t CFG_RATE_TIMEREF = 0x20210003; // (1->0) Time reference (0-utc, 1-gps, 2-glonass, 3-BeiDou (18+), 4-Galileo (18+), 5-NavIC (29+))
/**
* Used to set SBAS parameters
* @deprecated UBX-CFG-SBAS is deprecated in favor of UBX-CFG-VALSET with CFG-SBAS-* keys
* enablement should be done via CFG-SIGNAL-SBAS_ENA key
* kept for older firmware versions
*/
class UbxCfgSbas8
{
public:
static constexpr MsgId ID = UBX_CFG_SBAS;
uint8_t mode; // SBAS mode flags
uint8_t usage; // SBAS usage flags
uint8_t maxSbas; // Maximum number of SBAS prioritized tracking channels (valid range: 0 - 3) to use
uint8_t scanmode2; // Continuation of scanmode bitmask
uint32_t scanmode1; // Which SBAS PRN numbers to search for (bitmask). If all bits are set to zero, auto-scan (i.e. allvalid PRNs) are searched. Every bit corresponds to a PRN number
} __attribute__((packed));
constexpr uint32_t CFG_SBAS_TESTMODE = 0x10360002; // SBAS test mode
constexpr uint32_t CFG_SBAS_RANGING = 0x10360003; // SBAS ranging source
constexpr uint32_t CFG_SBAS_DIFFCORR = 0x10360004; // SBAS differential corrections
constexpr uint32_t CFG_SBAS_INTEGRITY = 0x10360005; // SBAS integrity information
constexpr uint32_t CFG_SBAS_PRNSCANMASK = 0x50360006; // (0x72bc8 -> 0) Which SBAS PRN numbers to search for (bitmask). If all bits are set to zero, auto-scan (i.e. allvalid PRNs) are searched. Every bit corresponds to a PRN number
struct UbxCfgGnssBlock
{
uint8_t gnssId;
uint8_t resTrkCh;
uint8_t maxTrkCh;
uint8_t reserved1;
uint8_t flagsEnable; // bit 0: enable GNSS system
uint8_t flagsReserved;
uint8_t sigCfgMask; // signal config: 0x01=L1, 0x20=L1+L5 (dual-band)
uint8_t flagsHigh;
} __attribute__((packed));
/**
* Used to set enabled GNSS systems and signals
* @deprecated UBX-CFG-GNSS is deprecated in favor of UBX-CFG-VALSET with CFG-SIGNAL-* keys
* kept for older firmware versions
*/
class UbxCfgGnss7
{
public:
static constexpr MsgId ID = UBX_CFG_GNSS;
uint8_t msgVer;
uint8_t numTrkChHw;
uint8_t numTrkChUse;
uint8_t numConfigBlocks;
UbxCfgGnssBlock blocks[7];
} __attribute__((packed));
class UbxCfgGnssHeader
{
public:
uint8_t msgVer;
uint8_t numTrkChHw;
uint8_t numTrkChUse;
uint8_t numConfigBlocks;
} __attribute__((packed));
// CFG-SIGNAL key IDs for UBX-CFG-VALSET (PROTVER > 27.00, u-blox Interface Description UBX-23001092)
constexpr uint32_t CFG_SIGNAL_GPS_ENA = 0x10310001; // GPS enable
constexpr uint32_t CFG_SIGNAL_GPS_L5 = 0x10310004; // GPS L5 signal enable (M10 dual-band)
constexpr uint32_t CFG_SIGNAL_SBAS_ENA = 0x10310020; // SBAS enable
constexpr uint32_t CFG_SIGNAL_GAL_ENA = 0x10310021; // Galileo enable
constexpr uint32_t CFG_SIGNAL_BDS_ENA = 0x10310022; // BeiDou enable
constexpr uint32_t CFG_SIGNAL_QZSS_ENA = 0x10310024; // QZSS enable
constexpr uint32_t CFG_SIGNAL_GLO_ENA = 0x10310025; // GLONASS enable
constexpr uint32_t CFG_SIGNAL_BDS_B2A = 0x10310028; // BeiDou B2a signal enable (M10 dual-band)
struct UbxCfgValsetKV
{
uint32_t key;
uint8_t value;
} __attribute__((packed));
template<size_t Size>
class UbxCfgValset
{
public:
static constexpr MsgId ID = UBX_CFG_VALSET;
uint8_t version; // 0
uint8_t layers; // 0x01 = RAM only
uint8_t reserved[2];
UbxCfgValsetKV kv[Size];
} __attribute__((packed));
template<uint32_t K, typename T>
struct UbxCfgValsetItem
{
explicit constexpr UbxCfgValsetItem(T v): key(K), value(v)
{
constexpr size_t size = (K >> 28) & 0x07u;
if constexpr (size == 1 || size == 2) {
static_assert((sizeof(T)) == 1, "Invalid value size for key, expected byte");
} else if constexpr (size == 3) {
static_assert((sizeof(T)) == 2, "Invalid value size for key, expected word");
} else if constexpr (size == 4) {
static_assert((sizeof(T)) == 4, "Invalid value size for key, expected dword");
} else if constexpr (size == 5) {
static_assert((sizeof(T)) == 8, "Invalid value size for key, expected qword");
}
}
uint32_t key;
T value;
} __attribute__((packed));
class UbxCfgValsetHeader
{
public:
uint8_t version = 0; // 0
uint8_t layers = 0x01; // 0x01 = RAM only
uint16_t position = 0; //
} __attribute__((packed));
/**
* Used to set enabled NAV5 parameters
* @deprecated UBX-CFG-NAV5 is deprecated in favor of UBX-CFG-VALSET with CFG-NAVSPG-* keys
* kept for older firmware versions
*/
class UbxCfgNav5
{
public:
static constexpr MsgId ID = UBX_CFG_NAV5;
union { // Parameters bitmask. Only the masked parameters will be applied.
uint16_t value;
struct {
uint8_t dyn: 1; // Apply dynamic model settings
uint8_t minEl: 1; // Apply minimum elevation settings
uint8_t posFixMode: 1; // Apply fix mode settings
uint8_t drLim: 1; // Reserved
uint8_t posMask: 1; // Apply position mask settings
uint8_t timeMask: 1; // Apply time mask settings
uint8_t staticHoldMask: 1; // Apply static hold settings
uint8_t dgpsMask: 1; // Apply DGPS settings
uint8_t cnoThreshold: 1; // Apply CNO threshold settings (cnoThresh, cnoThreshNumSVs)
uint8_t reserved: 1;
uint8_t utc: 1; // Apply UTC settings
};
} mask;
uint8_t dynModel; // Dynamic model, 0:portable, 2:stationary, 3:pedestrian, 4:automotive, 5:sea, 6:airbone<1g, 7:airbone<2g, 8: airbone<4g, 9:wrist watch, 10:motorbike, 11: lawnmower, 12: electric scooter
uint8_t fixMode; // Position fixing mode, 1: 2D only, 2: 3D only, 3: auto 2D/3D
int32_t fixedAlt; // Fixed altitude (mean sea level) for 2D fix mode, [m * 0.01]
uint32_t fixedAltVar; // Fixed altitude variance for 2D mode, [m^2 * 0.0001]
int8_t minElev; // Minimum elevation for a GNSS satellite to be used in NAV, [deg]
uint8_t drLimit; // reserved [s]
uint16_t pDOP; // Position DOP mask to use * 0.1
uint16_t tDOP; // Time DOP mask to use * 0.1
uint16_t pAcc; // Position accuracy mask [m]
uint16_t tAcc; // Time accuracy mask [m]
uint8_t staticHoldThresh; // Static hold threshold [cm/s]
uint8_t dgnssTimeout; // DGNSS timeout [s]
uint8_t cnoThreshNumSVs; // Number of satellites required to have C/N0 above cnoThresh for a fix to be attempted
uint8_t cnoThresh; // C/N0 threshold for deciding whether to attempt a fix
uint8_t reserved0[2];
uint16_t staticHoldMaxDist; // Static hold distance threshold
uint8_t utcStandard; // UTC standard to be used, 0:auto, 3:USNaval Obs, 5: EURLabs, 6:Soviet, 7: NTSC (China), 8: NTPL (India)
uint8_t reserved1[5];
} __attribute__((packed));
constexpr uint32_t CFG_NAVSPG_DYNMODEL = 0x20110021; // (0->8) Dynamic platform model, 0:portable, 2:stationary, 3:pedestrian, 4:automotive, 5:sea, 6:airbone<1g, 7:airbone<2g, 8: airbone<4g, 9:wrist watch, 10:motorbike, 11: lawnmower, 12: electric scooter
constexpr uint32_t CFG_NAVSPG_FIXMODE = 0x20110011; // (3) Position fixing mode, 1: 2D only, 2: 3D only, 3: auto 2D/3D
constexpr uint32_t CFG_NAVSPG_CONSTR_DGNSSTO = 0x201100c4; // (60) DGNSS timeout [s] 60
constexpr uint32_t CFG_NAVSPG_CONSTR_ALT = 0x401100c1; // (0) Fixed altitude (mean sea level) for 2D fix mode
constexpr uint32_t CFG_NAVSPG_CONSTR_ALTVAR = 0x401100c2; // (10000) Fixed altitude variance for 2D mode
constexpr uint32_t CFG_NAVSPG_INFIL_CNOTHRS = 0x201100ab; // (0) C/N0 threshold for deciding whether to attempt a fix
constexpr uint32_t CFG_NAVSPG_INFIL_NCNOTHRS = 0x201100aa; // (0) Number of satellites required to have C/N0 above CFG-NAVSPG-INFIL_CNOTHRS for a fix to be attempted
constexpr uint32_t CFG_NAVSPG_INFIL_MINELEV = 0x201100a4; // (5) Minimum elevation for a GNSS satellite to be used in navigation
constexpr uint32_t CFG_NAVSPG_OUTFIL_PDOP = 0x301100b1; // (250) Output filter position DOP mask (threshold)
constexpr uint32_t CFG_NAVSPG_OUTFIL_TDOP = 0x301100b2; // (250) Output filter time DOP mask (threshold)
constexpr uint32_t CFG_NAVSPG_OUTFIL_PACC = 0x301100b3; // (100) Output filter position accuracy mask (threshold)
constexpr uint32_t CFG_NAVSPG_OUTFIL_TACC = 0x301100b4; // (350 -> 300?) Output filter time accuracy mask (threshold)
constexpr uint32_t CFG_NAVSPG_OUTFIL_FACC = 0x301100b5; // (150) Output filter frequency accuracy mask (threshold)
constexpr uint32_t CFG_NAVSPG_UTCSTANDARD = 0x2011001c; // (0) UTC standard 0:auto, 3:USNaval Obs, 5: EURLabs, 6:Soviet, 7: NTSC (China), 8: NTPL (India)
constexpr uint32_t CFG_MOT_GNSSSPEED_THRS = 0x20250038; // (0) GNSS speed threshold below which platform is considered as stationary (a.k.a. static hold threshold)
constexpr uint32_t CFG_MOT_GNSSDIST_THRS = 0x3025003b; // (0) Distance above which GNSS-based stationary motion is exit (a.k.a. static hold distance threshold)
/**
* Used to receive high rate PVT solution
*/
class UbxNavPvt92
{
public:
static constexpr MsgId ID = UBX_NAV_PVT;
uint32_t iTow; // ms
uint16_t year; // UTC year
uint8_t month; // 1..12
uint8_t day; // 1..31
uint8_t hour; // 0..23
uint8_t min; // 0..59
uint8_t sec; // 0..60
union {
uint8_t value;
struct {
uint8_t validDate: 1; // 1 = valid UTC Date
uint8_t validTime: 1; // 1 = valid UTC time of day
uint8_t fullyResolved: 1; // 1 = UTC time of day has been fully resolved (no seconds uncertainty). Cannot be used to check if time is completely solved.
uint8_t validMag: 1; // 1 = valid magnetic declination
};
} valid;
uint32_t tAcc; // time accuracy (ns)
int32_t nano; // Fraction of seconds (ns x -1e9..1e9)
uint8_t fixType; // 0: no-fix, 1: dead-recon, 2: 2D, 3: 3D, 4: GNSS+DR, 5: time fix only
union {
uint8_t value;
struct {
uint8_t gnssFixOk: 1; // 1 = valid fix (i.e within DOP & accuracy masks)
uint8_t diffSoln: 1; // 1 = differential corrections were applied
uint8_t psmState: 3; // Power save mode state
uint8_t headVehValid: 1; // 1 = heading of vehicle is valid, only set if the receiver is in sensor fusion mode
uint8_t carrSoln: 2; // Carrier phase range solution status: 0: no carrier, 1: carrier with floating ambiguities, 2: with fixed ambiguities
};
} flags; // fix status flags
union {
uint8_t value;
struct {
uint8_t reserved : 5;
uint8_t confirmedAvai: 1; // 1 = information about UTC Date and Time of Day validity confirmation is available
uint8_t confirmedDate: 1; // 1 = UTC Date validity could be confirmed
uint8_t confirmedTime: 1; // 1 = UTC Time of Day could be confirmed
};
} flags2; // additional flags
uint8_t numSV; // Number of satelites in Nav Sol
int32_t lon; // Longnitude, deg x 1e-7
int32_t lat; // Latitude, deg x 1e-7
int32_t height; // Height above allipsoid (mm)
int32_t hSML; // Height above mean sea level (mm)
uint32_t hAcc; // horizontal accuracy (mm)
uint32_t vAcc; // vertical accuracy (mm)
int32_t velN; // notrh velocity (mm/s)
int32_t velE; // east velocity (mm/s)
int32_t velD; // down velocity (mm/s)
int32_t gSpeed; // ground speed (mm/s, 2D)
int32_t headMot; // heading of motion (deg x 1e-5)
uint32_t sAcc; // speed accuracy (mm/s)
uint32_t headAcc; // heading accuracy (deg x 1e-5)
uint16_t pDOP; // position Dillution DOP (x 0.01)
union {
uint16_t value;
struct {
uint8_t invalidLlh: 1; // 1 = Invalid lon, lat, height and hMSL
uint8_t lastCorrectionAge: 4; // Age of the most recently received differential correction: 0: ?, 1: 0-1, 2: 1-2, 3: 2-5, 4: 5-10, 5: 10-15...
};
} flags3; // additional flags
uint32_t reserved1; // reserved
int32_t headVeh; // heading of vehicle (deg x 1e-5), only if headVehValid flag is set
int16_t magDec; // Magnetic declination (deg x 1e-2), only in ADR4.10+
uint16_t magAcc; // Magnetic declination accuracy (deg x 1e-2), only in ADR4.10+
} __attribute__((packed));
/**
* Used to receive satellite information
*/
class UbxNavSat
{
public:
static constexpr MsgId ID = UBX_NAV_SAT;
uint32_t iTow; // time of week
uint8_t version; // message version (0x01)
uint8_t numSvs; // number of satelites
uint16_t reserved1;
struct {
uint8_t gnssId; // GNSS ID
uint8_t svId; // Satelite ID
uint8_t cno; // dBHz
int8_t elev; // deg +/-90
int16_t azim; // deg 0-360
int16_t prRes; // Pseudorange residual
union {
uint32_t value;
struct {
uint8_t qualityInd: 3; // quality indicatopr: 0-no signal, 1-searching, 2-aquired, 3-unstable, 4-code locked, 5,6,7-code and carrier locked
uint8_t svUsed: 1; // used for navigation
uint8_t health: 2; // signal health 0-unknown, 1-healthy, 2-unhealty
uint8_t difCorr: 1; // differential correction available for this SV
uint8_t smoothed: 1; // carrier smotthed pseudorange used
uint8_t orbitSource: 3; // orbit source: 0-no inform, 1-ephemeris, 2-almanac, 3-assistnow offline, 4-assistnow autonomous, 5,6,7-other
uint8_t ephAvail: 1; // ephemeris available
uint8_t elmAvail: 1; // almanac available
uint8_t enoAvail: 1; // assistnow offline available
uint8_t eopAvail: 1; // assistnow autonomous available
uint8_t reserved: 1;
uint8_t sbasCorrUsed: 1; // SBAS corrections used
uint8_t rtcmCorrUsed: 1; // RTCM corrections used
uint8_t slasCorrUsed: 1; // SLAS corrections used
uint8_t spartnCorrUsed: 1; // SPARTN corrections used
uint8_t prCorrUsed: 1; // Pseudorange corrections used
uint8_t crCorrUsed: 1; // Carrier range corrections used
uint8_t doCorrUsed: 1; // Range rate (Doppler) corrections used
uint8_t clasCorrUsed: 1; // CLAS corrections used
};
} flags;
} sats[];
} __attribute__((packed));
// ----------------------------------------------------------------------------------------
template<typename MsgType, typename Enable = void>
class UbxFrame
{
static_assert(sizeof(MsgType) != 0, "MsgType cannot be empty!");
public:
UbxFrame(const MsgType& m): msg(m)
{
const uint8_t* it = reinterpret_cast<const uint8_t*>(this) + 2; // start after sync headers
crc = ubxChecksum(0, it, sizeof(MsgType) + 4); // plus msgClass + msgId + length
}
const uint16_t hdr = UBX_SYNC;
const MsgId id = MsgType::ID;
const uint16_t length = sizeof(MsgType);
const MsgType msg;
uint16_t crc;
} __attribute__((packed));
// specialization for zero-size messages
template<typename MsgType>
class UbxFrame<MsgType, typename std::enable_if<std::is_empty<MsgType>::value>::type>
{
public:
UbxFrame(const MsgType& m)
{
const uint8_t* it = reinterpret_cast<const uint8_t*>(this) + 2; // start after sync headers
crc = ubxChecksum(0, it, 4); // only msgClass + msgId + length
}
const uint16_t hdr = UBX_SYNC;
const MsgId id = MsgType::ID;
const uint16_t length = 0;
uint16_t crc;
} __attribute__((packed));
// specialization for UbxRequest, which has variable length payload
template<>
class UbxFrame<UbxRequest>
{
public:
UbxFrame(const UbxRequest& m)
{
auto ptr = std::copy_n(reinterpret_cast<const uint8_t*>(&m.msgId), 2, data); // msgId
ptr = std::copy_n(reinterpret_cast<const uint8_t*>(&m.length), 2, ptr); // length
ptr = std::copy_n(m.payload, m.length, ptr); // payload
const uint8_t* it = reinterpret_cast<const uint8_t*>(this) + 2; // start after sync headers
uint16_t crc = ubxChecksum(0, it, m.length + 4); // plus msgClass + msgId + length + payload
data[m.length + 4] = crc & 0xff; // crc low byte
data[m.length + 5] = crc >> 8; // crc high byte
}
uint16_t size() const
{
return ((uint16_t)data[2] | ((uint16_t)data[3] << 8)) + 8; // header(2) + msgId(2) + length(2) + payload + crc(2)
}
const uint16_t hdr = UBX_SYNC;
uint8_t data[80] = {0};
};
}