view ubx.h @ 88:2875fe2d8fd5

ubx: switch from stdio to read/write syscalls Occasionally, we'd run into deadlocks between iothread calling fgetc and the main thread calling fwrite. Instead of trying to diagnose the reason, it is simpler to just switch to xread/xwrite. Signed-off-by: Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
author Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
date Mon, 22 Feb 2021 09:14:24 -0500
parents 0e4ab6c2a99c
children 2d760d9d3435
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);

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