changeset 70:919ca4da4660

gnss-galileo: estimate each satellites GST based on page numbers The pages are sent in a well defined sequence, so we can make educated guesses about how much time has passed since the last page we received. Signed-off-by: Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
author Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
date Wed, 22 Jan 2020 11:26:34 -0500
parents 9dd833ef57d3
children 5937a255131f
files gnss-galileo-state.c gnss-galileo.h
diffstat 2 files changed, 90 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- a/gnss-galileo-state.c	Mon Jan 20 12:58:48 2020 -0500
+++ b/gnss-galileo-state.c	Wed Jan 22 11:26:34 2020 -0500
@@ -191,6 +191,17 @@
 	__sync_time(&state->time, gst, wn, tow, true);
 
 	/*
+	 * We know the exact time, update the estimate with it.  We update
+	 * only the current sv's estimate otherwise it becomes confusing.
+	 * Specifically, if we were to set another sv's estimate to the
+	 * current time, when it tries to update its estimate in early page
+	 * 5 processing, it'll believe that it missed everything since the
+	 * previous page 5 - causing it to estimate 30 seconds in the
+	 * future.
+	 */
+	state->sv[sv].gst_estimate = gst;
+
+	/*
 	 * If this is *not* the first time message from the constellation,
 	 * we were able to tag all ephemeris pages received since then with
 	 * that GST timestamp.  This timestamp is required to sync the
@@ -204,6 +215,78 @@
 		state->ops->time(state, sv, &state->time, &prev_sv);
 }
 
+static void galileo_state_guess_time(struct galileo_state *state, int sv, int pg)
+{
+	/*
+	 * map page number to the second offset into the 30 second subframe
+	 *
+	 * The values are the offsets of the start of the second half of the
+	 * page - as listed in the ICD.
+	 */
+	static const uint32_t offsets[64] = {
+		[2] = 1,
+		[4] = 3,
+		[6] = 5,
+		[7] = 7,
+		[9] = 7,
+		[8] = 9,
+		[10] = 9,
+		[1] = 21,
+		[3] = 23,
+		[5] = 25,
+	};
+	uint32_t prevoff;
+	uint32_t curoff;
+	uint32_t adj;
+
+	ASSERT3U(pg, <, ARRAY_LEN(offsets));
+
+	curoff = offsets[pg];
+
+	if (curoff) {
+		/*
+		 * We know that it is currently (gst % 30) == curoff.  But
+		 * because we may have missed some messages, we cannot just
+		 * set our estimate to 'off' seconds past the last subframe
+		 * start as that could cause our estimate to go backwards.
+		 */
+
+		prevoff = state->sv[sv].gst_estimate % 30;
+
+		if (prevoff >= curoff) {
+			/*
+			 * We are certain that we are looking at a page from
+			 * a different subframe than we had before.  We do
+			 * not know if it is the immediately adjacent
+			 * subframe, or if we missed one or more.  We assume
+			 * that it is the adjacent one.
+			 */
+			adj = -prevoff + 30 + curoff;
+		} else {
+			/*
+			 * We cannot tell if this page is from the same
+			 * subframe as the one we had before.  Therefore, we
+			 * assume that it is the same one.
+			 */
+			adj = -prevoff + curoff;
+		}
+	} else {
+		/*
+		 * We have no idea where in the 30 second subframe we are,
+		 * but we know that we must be at least 2 seconds later than
+		 * before.
+		 *
+		 * Note that it is *two* seconds because we get whole pages
+		 * at a time.  If we were getting the page halves, we would
+		 * have to look at the even/odd bit to decide whether to
+		 * step by one or two seconds.
+		 */
+		adj = 2;
+	}
+
+	state->sv[sv].gst_estimate += adj;
+}
+
 bool galileo_state_apply_page(struct galileo_state *state,
 			      const unsigned int sv,
 			      const struct galileo_inav_page *pg)
@@ -216,6 +299,8 @@
 
 	state->sv[sv].pages[pg->nominal.type].count++;
 
+	galileo_state_guess_time(state, sv, pg->nominal.type);
+
 	if (pg->nominal.type == 63)
 		return true; /* nothing to do for dummy pages */
 
--- a/gnss-galileo.h	Mon Jan 20 12:58:48 2020 -0500
+++ b/gnss-galileo.h	Wed Jan 22 11:26:34 2020 -0500
@@ -233,8 +233,13 @@
 	/* 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 */