view gnss-galileo.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 5937a255131f
children
line wrap: on
line source

/*
 * Copyright (c) 2020 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 __GNSS_GALILEO_H
#define __GNSS_GALILEO_H

#include <jeffpc/types.h>

#include "gnss.h"

/* The highest sv number that we should ever see */
#define GALILEO_MAX_SV_ID	36

struct galileo_inav_page {
	bool page_nominal;

	union {
		struct {
			uint32_t sar; /* 22 bits */
			uint8_t type; /* 6 bits */
			struct {
				uint16_t iod; /* 10 bits */
				uint16_t t0e; /* 14 bits */
				int32_t m0; /* 32 bits */
				uint32_t e; /* 32 bits */
				uint32_t sqrt_a; /* 32 bits */
			} w1;
			struct {
				uint16_t iod; /* 10 bits */
				int32_t omega0; /* 32 bits */
				int32_t i0; /* 32 bits */
				int32_t omega; /* 32 bits */
				int16_t idot; /* 14 bits */
			} w2;
			struct {
				uint16_t iod; /* 10 bits */
				int32_t omegadot; /* 24 bits */
				int16_t delta_n; /* 16 bits */
				int16_t cuc; /* 16 bits */
				int16_t cus; /* 16 bits */
				int16_t crc; /* 16 bits */
				int16_t crs; /* 16 bits */
				uint8_t sisa; /* 8 bits */
			} w3;
			struct {
				uint16_t iod; /* 10 bits */
				uint8_t svid; /* 6 bits */
				int16_t cic; /* 16 bits */
				int16_t cis; /* 16 bits */
				uint16_t t0c; /* 14 bits */
				uint32_t af0; /* 31 bits */
				uint32_t af1; /* 21 bits */
				uint8_t af2; /* 6 bits */
			} w4;
			struct {
				uint16_t ai0; /* 11 bits */
				uint16_t ai1; /* 11 bits */
				uint16_t ai2; /* 14 bits */
				bool reg1;
				bool reg2;
				bool reg3;
				bool reg4;
				bool reg5;
				uint16_t bgda; /* 10 bits */
				uint16_t bgdb; /* 10 bits */
				uint8_t e5bhs; /* 2 bits */
				uint8_t e1bhs; /* 2 bits */
				bool e5bdvs;
				bool e1bdvs;
				uint16_t wn; /* 12 bits */
				uint32_t tow; /* 20 bits */
			} w5;
			struct {
				uint32_t a0; /* 32 bits */
				uint32_t a1; /* 24 bits */
				uint8_t delta_tls; /* 8 bits */
				uint8_t tot; /* 8 bits */
				uint8_t wn0t; /* 8 bits */
				uint8_t wnlsf; /* 8 bits */
				uint8_t dn; /* 3 bits */
				uint8_t delta_tlsf; /* 8 bits */
				uint32_t tow; /* 20 bits */
			} w6;
			struct {
				uint8_t iod; /* 4 bits */
				uint8_t wn; /* 2 bits */
				uint16_t t0a; /* 10 bits */
				uint8_t svid1; /* 6 bits */
				int16_t sv1_delta_sqrt_a; /* 13 bits */
				uint16_t sv1_e; /* 11 bits */
				int16_t sv1_omega; /* 16 bits */
				int16_t sv1_delta; /* 11 bits */
				int16_t sv1_omega0; /* 16 bits */
				int16_t sv1_omegadot; /* 11 bits */
				int16_t sv1_m0; /* 16 bits */
			} w7;
			struct {
				uint8_t iod; /* 4 bits */
				int16_t sv1_af0; /* 16 bits */
				int16_t sv1_af1; /* 13 bits */
				uint8_t sv1_e5bhs; /* 2 bits */
				uint8_t sv1_e1bhs; /* 2 bits */
				uint8_t svid2; /* 6 bits */
				int16_t sv2_delta_sqrt_a; /* 13 bits */
				uint16_t sv2_e; /* 11 bits */
				int16_t sv2_omega; /* 16 bits */
				int16_t sv2_delta; /* 11 bits */
				int16_t sv2_omega0; /* 16 bits */
				int16_t sv2_omegadot; /* 11 bits */
			} w8;
			struct {
				uint8_t iod; /* 4 bits */
				uint8_t wn; /* 2 bits */
				uint16_t t0a; /* 10 bits */
				int16_t sv2_m0; /* 16 bits */
				int16_t sv2_af0; /* 16 bits */
				int16_t sv2_af1; /* 13 bits */
				uint8_t sv2_e5bhs; /* 2 bits */
				uint8_t sv2_e1bhs; /* 2 bits */
				uint8_t svid3; /* 6 bits */
				int16_t sv3_delta_sqrt_a; /* 13 bits */
				uint16_t sv3_e; /* 11 bits */
				int16_t sv3_omega; /* 16 bits */
				int16_t sv3_delta; /* 11 bits */
			} w9;
			struct {
				uint8_t iod; /* 4 bits */
				int16_t sv3_omega0; /* 16 bits */
				int16_t sv3_omegadot; /* 11 bits */
				int16_t sv3_m0; /* 16 bits */
				int16_t sv3_af0; /* 16 bits */
				int16_t sv3_af1; /* 13 bits */
				uint8_t sv3_e5bhs; /* 2 */
				uint8_t sv3_e1bhs; /* 2 */
				uint16_t a0g; /* 16 bits */
				uint16_t a1g; /* 12 bits */
				uint8_t t0g; /* 8 bits */
				uint8_t wn; /* 6 bits */
			} w10;
			struct {
				uint16_t wn; /* 12 bits */
				uint32_t tow; /* 20 bits */
			} w0;
		} nominal;
		struct {
			/* TODO */
		} alert;
	};
};

struct galileo_ephemeris {
	unsigned int sv;
	uint16_t iod;
	bool valid:1;

	/* All in radians, except as noted */
	double m0;
	double delta_n; /* rad/s */
	double e;
	double sqrt_a; /* sqrt(m) */
	double omega0;
	double i0;
	double omega;
	double omegadot; /* rad/s */
	double idot; /* rad/s */
	double cuc;
	double cus;
	double crc; /* m */
	double crs; /* m */
	double cic;
	double cis;
	struct {
		uint32_t raw; /* s */
		uint32_t gst;
	} t0;
};

struct galileo_state;

struct galileo_state_time {
	uint32_t gst; /* calculated from wn & tow */
	uint16_t wn;
	uint32_t tow;
	bool valid:1;
};

struct galileo_state_ops {
	/*
	 * We got an updated ephemeris from a satellite.  If @prev is NULL,
	 * this is the first update for this satellite.
	 */
	void (*eph_update)(struct galileo_state *state,
			   const struct galileo_ephemeris *prev,
			   const struct galileo_ephemeris *new);
	void (*time)(struct galileo_state *state,
		     const unsigned int tx_sv,
		     const struct galileo_state_time *now,
		     const struct galileo_state_time *prev_sv_time);
};

struct galileo_state {
	const struct galileo_state_ops *ops;

	/*
	 * global system time
	 *
	 * Updated by time received from svs (via page 5) as well as
	 * reasonably estimates based on page sequencing.
	 */
	struct galileo_state_time time;

	/*
	 * Note: SV numbers are currently 1..GALILEO_MAX_SV_ID.  To make it
	 * simpler, we use them as-is to index into the various structures.
	 * This means, that we need to make all of them have +1 entries, and
	 * the first entry is wasted.
	 */

	/* each SV's data */
	struct {
		struct galileo_ephemeris eph;

		/* last received GST update (page 5) */
		struct galileo_state_time last_time;

		/* guess at current time */
		uint32_t gst_estimate;

		/* per page-type info */
		struct {
			uint64_t count; /* number of pages received */
		} pages[64];
	} sv[GALILEO_MAX_SV_ID + 1];

	/* partially assembled data */
	struct {
		struct {
			/* The ephemeris is split across 4 pages */
			struct galileo_ephemeris eph;
			uint32_t gst[4]; /* global time when recv'd */
			uint16_t iod[4];
		} nav;
	} wip[GALILEO_MAX_SV_ID + 1];
};

extern void galileo_print_eph(const struct galileo_ephemeris *eph);
extern void galileo_eph_ecef(const struct galileo_ephemeris *eph,
			     const uint32_t gst, struct ecef *ecef);

extern bool galileo_parse_inav_page(struct galileo_inav_page *pg,
				    const uint32_t *words,
				    size_t nwords);

extern void galileo_state_init(struct galileo_state *state,
			       const struct galileo_state_ops *ops);
extern bool galileo_state_apply_page(struct galileo_state *state,
				     const unsigned int sv,
				     const struct galileo_inav_page *pg);

#endif