view ubx.h @ 89:2d760d9d3435

ubx: add struct for UBX-SEC-UNIQID Signed-off-by: Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
author Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
date Mon, 22 Feb 2021 11:24:50 -0500
parents 2875fe2d8fd5
children 3c514e476693
line wrap: on
line source

/*
 * Copyright (c) 2019-2021 Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */

#ifndef __UBX_H
#define __UBX_H

#include <jeffpc/error.h>
#include <jeffpc/types.h>

#define UBX_SYNC_BYTE_1	0xb5
#define UBX_SYNC_BYTE_2	0x62

enum gnssid {
	GNSSID_GPS	= 0x00,
	GNSSID_SBAS	= 0x01,
	GNSSID_GALILEO	= 0x02,
	GNSSID_BEIDOU	= 0x03,
	GNSSID_IMES	= 0x04,
	GNSSID_QZSS	= 0x05,
	GNSSID_GLONASS	= 0x06,
};

enum ubx_class {
	UBX_CLASS_NAV = 0x01, /* navigation results */
	UBX_CLASS_RXM = 0x02, /* receiver manager */
	UBX_CLASS_INF = 0x04, /* information */
	UBX_CLASS_ACK = 0x05, /* ack/nak */
	UBX_CLASS_CFG = 0x06, /* configuration input */
	UBX_CLASS_UPD = 0x09, /* firmware update */
	UBX_CLASS_MON = 0x0a, /* monitoring */
	UBX_CLASS_AID = 0x0b, /* AssistNow aiding */
	UBX_CLASS_TIM = 0x0d, /* timing */
	UBX_CLASS_ESF = 0x10, /* external sensor fusion */
	UBX_CLASS_MGA = 0x13, /* multiple GNSS assistance */
	UBX_CLASS_LOG = 0x21, /* logging */
	UBX_CLASS_SEC = 0x27, /* security feature */
	UBX_CLASS_HNR = 0x28, /* high rate navigation results */
};

enum ubx_msg_id {
	UBX_ACK_ACK	= (UBX_CLASS_ACK << 8) | 0x01,
	UBX_ACK_NAK	= (UBX_CLASS_ACK << 8) | 0x00,
	UBX_CFG_GNSS	= (UBX_CLASS_CFG << 8) | 0x3e,
	UBX_CFG_PRT	= (UBX_CLASS_CFG << 8) | 0x00,
	UBX_CFG_MSG	= (UBX_CLASS_CFG << 8) | 0x01,
	UBX_CFG_NAV5	= (UBX_CLASS_CFG << 8) | 0x24,
	UBX_MON_HW	= (UBX_CLASS_MON << 8) | 0x09,
	UBX_MON_VER     = (UBX_CLASS_MON << 8) | 0x04,
	UBX_NAV_CLOCK	= (UBX_CLASS_NAV << 8) | 0x22,
	UBX_NAV_POSECEF = (UBX_CLASS_NAV << 8) | 0x01,
	UBX_NAV_PVT	= (UBX_CLASS_NAV << 8) | 0x07,
	UBX_NAV_SAT	= (UBX_CLASS_NAV << 8) | 0x35,
	UBX_RXM_MEASX   = (UBX_CLASS_RXM << 8) | 0x14,
	UBX_RXM_RAWX	= (UBX_CLASS_RXM << 8) | 0x15,
	UBX_RXM_RLM	= (UBX_CLASS_RXM << 8) | 0x59,
	UBX_RXM_SFRBX	= (UBX_CLASS_RXM << 8) | 0x13,
	UBX_SEC_UNIQID	= (UBX_CLASS_SEC << 8) | 0x03,
};

struct ubx_header {
	uint8_t sync[2];
	uint8_t class;
	uint8_t id;
	uint16_t len;
} __attribute__((packed,aligned(2)));

#define UBX_CFG_GNSS_NUM_BLOCKS		6
struct ubx_cfg_gnss {
	uint8_t msgver; /* 0 */
	uint8_t num_trk_ch_hw;
	uint8_t num_trk_ch_use;
	uint8_t num_cfg_blocks; /* UBX_CFG_GNSS_NUM_BLOCKS */
	struct {
		uint8_t gnssid;
		uint8_t res_trk_ch;
		uint8_t max_trk_ch;
		uint8_t _reserved0;
		uint32_t flags;
			/* 0x00000001 = enable */
			/* 0x00010000 = GPS L1C/A */
			/* 0x00100000 = GPS L2C */
			/* 0x00010000 = SBAS L1C/A */
			/* 0x00010000 = Galileo E1 */
			/* 0x00200000 = Galileo E5b  */
			/* 0x00010000 = BeiDou B1I */
			/* 0x00100000 = BeiDou B2I */
			/* 0x00010000 = IMES L1 */
			/* 0x00010000 = QZSS L1C/A */
			/* 0x00040000 = QZSS L1S */
			/* 0x00100000 = QZSS L2C */
			/* 0x00010000 = GLONASS L1 */
			/* 0x00100000 = GLONASS L2 */
			/* 0x00010000 = IRNSS L5A */
	} cfg[UBX_CFG_GNSS_NUM_BLOCKS];
} __attribute__((packed,aligned(4)));
STATIC_ASSERT(sizeof(struct ubx_cfg_gnss) == 4 + 8 * UBX_CFG_GNSS_NUM_BLOCKS);

struct ubx_cfg_nav5 {
	uint16_t mask; /* fields to apply: */
		/* 0x0001 = apply dynamic model settings */
		/* 0x0002 = apply minimum elevation settings */
		/* 0x0004 = apply fix mode settings */
		/* 0x0008 = reserved */
		/* 0x0010 = apply position mask settings */
		/* 0x0020 = apply time mask settings */
		/* 0x0040 = apply static hold settings */
		/* 0x0080 = apply DGPS settings */
		/* 0x0100 = apply CNO threshold settings */
		/* 0x0400 = apply UTC settings */
	uint8_t dyn_model;
		/* 0 = portable */
		/* 2 = stationary */
		/* 3 = pedestrian */
		/* 4 = automotive */
		/* 5 = sea */
		/* 6 = airborne <1g accel */
		/* 7 = airborne <2g accel */
		/* 8 = airborne <4g accel */
		/* 9 = wrist */
		/* 10 = bike */
	uint8_t fix_mode; /* 1=2D only, 2=3D only, 3=auto 2D/3D */
	uint32_t fixed_alt; /* m * 0.01, signed */
	uint32_t fixed_alt_var; /* m^2 * 1e-4 */
	uint8_t min_elev; /* deg, signed */
	uint8_t dr_limit; /* s, reserved */
	uint16_t pdop; /* 0.1 */
	uint16_t tdop; /* 0.1 */
	uint16_t pacc; /* m */
	uint16_t tacc; /* m */
	uint8_t static_hold_thresh; /* cm/s */
	uint8_t dgnss_timeout; /* s */
	uint8_t cno_threshold_num_svs;
	uint8_t cno_thresh; /* dBHz */
	uint8_t _reserved0[2];
	uint16_t static_hold_max_dist; /* m */
	uint8_t utc_standard;
	uint8_t _reserved1[5];
} __attribute__((packed,aligned(4)));
STATIC_ASSERT(sizeof(struct ubx_cfg_nav5) == 36);

struct ubx_cfg_prt_uart {
	uint8_t port;
	uint8_t _reserved0;
	uint16_t tx_ready;
	uint32_t mode;
	uint32_t baud_rate;
	uint16_t in_proto_mask;
	uint16_t out_proto_mask;
	uint16_t flags;
	uint8_t _reserved1[2];
} __attribute__((packed,aligned(4)));

struct ubx_cfg_prt_usb {
	uint8_t port;
	uint8_t _reserved0;
	uint16_t tx_ready;
	uint8_t _reserved1[8];
	uint16_t in_proto_mask;
	uint16_t out_proto_mask;
	uint8_t _reserved2[2];
	uint8_t _reserved3[2];
} __attribute__((packed,aligned(4)));

struct ubx_nav_posecef {
	uint32_t itow; /* ms */
	uint32_t ecefx; /* cm, signed */
	uint32_t ecefy; /* cm, signed */
	uint32_t ecefz; /* cm, signed */
	uint32_t acc; /* cm */
} __attribute__((packed,aligned(4)));

struct ubx_nav_pvt {
	uint32_t itow; /* ms */
	uint16_t year; /* UTC */
	uint8_t month; /* UTC (1..12) */
	uint8_t day; /* UTC (1..31) */
	uint8_t hour; /* UTC (0..23) */
	uint8_t min; /* UTC (0..59) */
	uint8_t sec; /* UTC (0..60) */
	uint8_t valid; /* flags: */
		/* 0x01 - valid date */
		/* 0x02 - valid time */
		/* 0x04 - fully resolved */
		/* 0x08 - valid mag */
	uint32_t time_acc; /* ns UTC estimate */
	uint32_t nsec; /* ns UTC (-1e9..+1e9), signed */
	uint8_t fix_type; /* 0..5 */
	uint8_t flags;
		/* 0x01 - valid fix (i.e., within DOP & accuracy masks */
		/* 0x02 - differential corrections applied */
		/* 0x20 - vehicle heading valid */
	uint8_t flags2;
		/* 0x20 - UTC Date & Time validity confirmation available */
		/* 0x40 - UTC Date validity could be confirmed */
		/* 0x80 - UTC Time validity could be confirmed */
	uint8_t num_sv;
	uint32_t lon; /* deg * 1e-7, signed */
	uint32_t lat; /* deg * 1e-7, signed */
	uint32_t height_ell; /* mm above elipsoid, signed */
	uint32_t height_msl; /* mm MSL, signed */
	uint32_t horiz_acc; /* mm */
	uint32_t vert_acc; /* mm */
	uint32_t vel_n; /* mm/s, signed */
	uint32_t vel_e; /* mm/s, signed */
	uint32_t vel_d; /* mm/s, signed */
	uint32_t gspeed; /* mm/s, signed */
	uint32_t motion_heading; /* deg * 1e-5, signed */
	uint32_t speed_acc; /* mm/s */
	uint32_t head_acc; /* deg * 1e-5 */
	uint16_t pdop; /* 0.01 */
	uint8_t _reserved[6];
	uint32_t vehicle_heading; /* deg * 1e-5, signed */
	uint16_t mag_dec; /* deg * 1e-2, signed */
	uint16_t mag_dec_acc; /* deg * 1e-2 */
} __attribute__((packed,aligned(4)));

struct ubx_nav_sat {
	uint32_t itow; /* ms */
	uint8_t version;
	uint8_t num_svs;
	uint8_t _reserved[2];
	struct {
		uint8_t gnssid;
		uint8_t svid;
		uint8_t cno; /* dBHz */
		uint8_t elev; /* deg, signed */
		uint16_t azim; /* deg, signed */
		uint16_t prres; /* m * 0.1, signed */
		uint32_t flags;
			/* 0x000007 = quality indicator */
			/* 0x000008 = signal used for nav */
			/* 0x000030 = signal health */
			/* 0x000040 = differential corr avail */
			/* 0x000080 = carrier smoothed PR used */
			/* 0x000700 = orbit source */
			/* 0x000800 = ephemeris avail for sv */
			/* 0x001000 = almanac avail for sv */
			/* 0x002000 = AssistNow Offline avail for sv */
			/* 0x004000 = AssistNow Auto avail for sv */
			/* 0x010000 = SBAS corr used for this sv */
			/* 0x020000 = RTCM corr used for this sv */
			/* 0x040000 = QZSS SLAS corr used for this sv */
			/* 0x100000 = pseudorange corr used for this sv */
			/* 0x200000 = carrier corr used for this sv */
			/* 0x400000 = doppler corr used for this sv */
	} sv[];
} __attribute__((packed,aligned(4)));

struct ubx_rxm_sfrbx {
	uint8_t gnssid;
	uint8_t svid;
	uint8_t _reserved0;
	uint8_t freqid;
	uint8_t num_words;
	uint8_t channel;
	uint8_t version;
	uint8_t reserved1;
	uint32_t words[];
} __attribute__((packed,aligned(4)));
STATIC_ASSERT(sizeof(struct ubx_rxm_sfrbx) == 8);

struct ubx_sec_uniqid {
	uint8_t version; /* 1 */
	uint8_t _reserved[3];
	uint8_t unique[5];
} __attribute__((packed,aligned(4)));

extern void ubx_init_queue(void);
extern const char *ubx_msg_name(enum ubx_msg_id id);
extern int send_ubx(int fd, enum ubx_msg_id id, const void *data,
		    size_t len);
extern int send_ubx_with_ack(int fd, enum ubx_msg_id id, const void *data,
			     size_t len);
extern int enable_ubx_msg(int fd, enum ubx_msg_id id, int port, int rate);
extern void notify_ubx_ack(const uint8_t *data, size_t len, bool success);

extern bool parse_and_process_ubx_message(const uint8_t *buf, size_t len,
					  const uint64_t tick,
					  void(*f)(const struct ubx_header *,
						   const uint8_t *, size_t,
						   enum ubx_msg_id,
						   uint64_t));

static inline enum ubx_msg_id mkmsgid(uint8_t class, uint8_t msg)
{
	enum ubx_msg_id id = (((uint16_t) class) << 8) | ((uint16_t) msg);

	return id;
}

#endif