view gnss-galileo.h @ 64:8e85919405df

gnss-galileo: add a valid bit to each ephemeris This is easier than trying to guess whether the ephemeris contains any meaningful values. Signed-off-by: Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
author Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
date Wed, 22 Jan 2020 10:10:26 -0500
parents c8c848632471
children 123cac19d9bd
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 */
	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;
		struct galileo_state_time last_time;
		bool valid_eph:1;
	} 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