changeset 38:6c53105716c0

capture: add simple framing to raw output This framing provides two major benefits: - it tags each ubx message with a pseudo-timestamp, allowing for more accurate analysis of the message stream - it allows more robust synchronization Signed-off-by: Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
author Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
date Tue, 14 Jan 2020 23:28:02 -0500
parents dd6139726f34
children d135288b7f53
files capture.c frame.h iothread.c iothread.h
diffstat 4 files changed, 71 insertions(+), 15 deletions(-) [+]
line wrap: on
line diff
--- a/capture.c	Wed Jan 15 09:40:43 2020 -0500
+++ b/capture.c	Tue Jan 14 23:28:02 2020 -0500
@@ -36,11 +36,11 @@
 
 static void usage(void)
 {
-	fprintf(stderr, "Usage: %s <device> <ubxport> <rawlog>\n", prog);
+	fprintf(stderr, "Usage: %s <device> <ubxport> <log>\n", prog);
 	fprintf(stderr, "\n");
 	fprintf(stderr, "  <device>       path or - for standard in\n");
 	fprintf(stderr, "  <ubxport>      port number (0=DCC, 1=UART, 3=USB, 4=SPI)\n");
-	fprintf(stderr, "  <rawlog>       path for raw UBX messages\n");
+	fprintf(stderr, "  <log>          path for framed UBX message log\n");
 	exit(1);
 }
 
@@ -267,7 +267,7 @@
 
 	rfile = fopen(argv[3], "wb");
 	if (rfile == NULL) {
-		fprintf(stderr, "Error: Failed to fopen raw: %s\n",
+		fprintf(stderr, "Error: Failed to fopen log: %s\n",
 			xstrerror(-errno));
 		return 9;
 	}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/frame.h	Tue Jan 14 23:28:02 2020 -0500
@@ -0,0 +1,38 @@
+/*
+ * 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 __FRAME_H
+#define __FRAME_H
+
+#include <jeffpc/types.h>
+
+#define FRAME_MAGIC	0x4a554630 /* JUF0 */
+
+struct frame {
+	uint32_t magic;
+	uint32_t session;
+	uint64_t tick;
+	uint32_t len;
+	uint32_t _pad;
+} __attribute__((packed,aligned(8)));
+
+#endif
--- a/iothread.c	Wed Jan 15 09:40:43 2020 -0500
+++ b/iothread.c	Tue Jan 14 23:28:02 2020 -0500
@@ -24,6 +24,8 @@
 #include <jeffpc/types.h>
 #include <jeffpc/io.h>
 #include <jeffpc/hexdump.h>
+#include <jeffpc/time.h>
+#include <jeffpc/rand.h>
 
 #include <unistd.h>
 
@@ -31,10 +33,11 @@
 #include "ubx.h"
 #include "xstdio.h"
 #include "rfc1145.h"
+#include "frame.h"
 
 static pthread_t io_thread;
 static FILE *input_file;
-static FILE *raw_file;
+static FILE *log_file;
 
 /* read until we get the beginning of a NMEA or UBX message */
 static int sync_reader(void)
@@ -73,31 +76,43 @@
 	return (exp == got) ? 0 : -ECKSUM;
 }
 
-static int log_raw_ubx(struct ubx_header *_hdr, uint8_t *raw)
+static int log_raw_ubx(struct ubx_header *_hdr, uint8_t *raw,
+		       uint64_t start_tick)
 {
 	struct ubx_header hdr = *_hdr;
+	struct frame frame;
 	int ret;
 
 	/* no log == no-op */
-	if (!raw_file)
+	if (!log_file)
 		return 0;
 
+	frame.magic   = cpu32_to_be(FRAME_MAGIC);
+	frame.session = cpu32_to_be(rand32());
+	frame.tick    = cpu64_to_be(start_tick);
+	frame.len     = cpu32_to_be(sizeof(hdr) + _hdr->len + 2);
+	frame._pad    = 0;
+
+	ret = xfwrite(log_file, &frame, sizeof(frame));
+	if (ret)
+		return ret;
+
 	hdr.len = cpu16_to_le(hdr.len);
 
-	ret = xfwrite(raw_file, &hdr, sizeof(hdr));
+	ret = xfwrite(log_file, &hdr, sizeof(hdr));
 	if (ret)
 		return ret;
 
-	ret = xfwrite(raw_file, raw, _hdr->len + 2);
+	ret = xfwrite(log_file, raw, _hdr->len + 2);
 	if (ret)
 		return ret;
 
-	fflush(raw_file);
+	fflush(log_file);
 
 	return 0;
 }
 
-static int read_ubx(void)
+static int read_ubx(uint64_t start_tick)
 {
 	struct ubx_header hdr;
 	int ret;
@@ -141,7 +156,7 @@
 			raw[hdr.len], raw[hdr.len + 1]);
 	}
 
-	ret = log_raw_ubx(&hdr, raw);
+	ret = log_raw_ubx(&hdr, raw, start_tick);
 	if (ret)
 		fprintf(stderr, "Failed to log raw UBX message: %s\n",
 			xstrerror(ret));
@@ -184,8 +199,11 @@
 
 	/* read a NMEA or UBX message & process it */
 	for (;;) {
+		uint64_t start_tick;
 		int byte;
 
+		start_tick = gettick();
+
 		byte = fgetc(input_file);
 		if (byte == EOF) {
 			fprintf(stderr, "Failed to read message sync byte\n");
@@ -199,7 +217,7 @@
 		}
 
 		if (byte == UBX_SYNC_BYTE_1) {
-			ret = read_ubx();
+			ret = read_ubx(start_tick);
 		} else if (byte == '$') {
 			ret = read_nmea();
 		} else {
@@ -218,10 +236,10 @@
 	return NULL;
 }
 
-int iothread_start(FILE *ifile, FILE *rfile)
+int iothread_start(FILE *ifile, FILE *lfile)
 {
 	input_file = ifile;
-	raw_file = rfile;
+	log_file = lfile;
 
 	return xthr_create(&io_thread, iothread_reader, NULL);
 }
--- a/iothread.h	Wed Jan 15 09:40:43 2020 -0500
+++ b/iothread.h	Tue Jan 14 23:28:02 2020 -0500
@@ -25,6 +25,6 @@
 
 #include <stdio.h>
 
-extern int iothread_start(FILE *ifile, FILE *rfile);
+extern int iothread_start(FILE *ifile, FILE *lfile);
 
 #endif