diff hr-bits/sid-count.c @ 407:183e81c8f6c0

hr-bits: sid-count program written
author Mychaela Falconia <falcon@freecalypso.org>
date Mon, 22 Jul 2024 10:00:58 +0000
parents
children 14302e075f37
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hr-bits/sid-count.c	Mon Jul 22 10:00:58 2024 +0000
@@ -0,0 +1,181 @@
+/*
+ * This program reads a TCH/HS DL capture file made with FC tools
+ * and analyzes the hex string of payload bits in every frame.
+ * For each frame, this program counts how many bits in the SID field
+ * are set (both class 1 and class 2.  All input lines are passed
+ * through to the output, but at the end of each line this program
+ * appends bit counts that match the conventions used in GSM 06.06
+ * swSidDetection() function.
+ */
+
+#include <ctype.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#include <strings.h>
+
+static const uint8_t class1_mask[12] = {0x07, 0xFF, 0xFF, 0xFF, 0xFF, 0xF9,
+					0x3F, 0xC0, 0x0F, 0x78, 0x0E, 0x06};
+static const uint8_t class2_mask[3]  = {0x1F, 0xFF, 0xF0};
+
+static char *infname, *outfname;
+static FILE *inf, *outf;
+static int lineno;
+static char linebuf[80];
+static uint8_t frame[15];
+
+static int
+is_hex_string_spc(str, expect_len)
+	char *str;
+	unsigned expect_len;
+{
+	char *cp, *endp;
+
+	endp = str + expect_len;
+	for (cp = str; cp < endp; cp++) {
+		if (!isxdigit(*cp))
+			return 0;
+	}
+	if (*cp == ' ')
+		return 1;
+	else
+		return 0;
+}
+
+static int
+decode_hex_digit(c)
+{
+	int d;
+
+	if (isdigit(c))
+		d = c - '0';
+	else if (isupper(c))
+		d = c - 'A' + 10;
+	else
+		d = c - 'a' + 10;
+	return d;
+}
+
+static void
+frame_from_hex()
+{
+	char *cp;
+	uint8_t *dp;
+	unsigned n, u, l;
+
+	cp = linebuf + 18;
+	dp = frame;
+	for (n = 0; n < 15; n++) {
+		u = decode_hex_digit(*cp++);
+		l = decode_hex_digit(*cp++);
+		*dp++ = (u << 4) | l;
+	}
+}
+
+static unsigned
+ones_in_byte(byte)
+	unsigned byte;
+{
+	unsigned count;
+
+	count = 0;
+	for (; byte; byte >>= 1) {
+		if (byte & 1)
+			count++;
+	}
+	return count;
+}
+
+static unsigned
+count_1_bits(data, mask, nbytes)
+	uint8_t *data, *mask;
+	unsigned nbytes;
+{
+	unsigned n, and, accum;
+
+	accum = 0;
+	for (n = 0; n < nbytes; n++) {
+		and = *data++ & *mask++;
+		accum += ones_in_byte(and);
+	}
+	return accum;
+}
+
+static void
+process_line()
+{
+	char *cp;
+	unsigned class1_ones, class1_zeros;
+	unsigned class2_ones, class2_zeros;
+	unsigned n1n2;
+
+	cp = index(linebuf, '\n');
+	if (!cp) {
+		fprintf(stderr, "%s line %d: too long or missing newline\n",
+			infname, lineno);
+		exit(1);
+	}
+	*cp = '\0';
+	if (strncmp(linebuf, "HR ", 3)) {
+inv:		fprintf(stderr,
+			"%s line %d: format does not match HR DL capture\n",
+			infname, lineno);
+		exit(1);
+	}
+	if (!is_hex_string_spc(linebuf + 3, 4))
+		goto inv;
+	if (!is_hex_string_spc(linebuf + 8, 4))
+		goto inv;
+	if (!is_hex_string_spc(linebuf + 13, 4))
+		goto inv;
+	if (!is_hex_string_spc(linebuf + 18, 30))
+		goto inv;
+	frame_from_hex();
+
+	class1_ones = count_1_bits(frame, class1_mask, 12);
+	class1_zeros = 62 - class1_ones;
+	class2_ones = count_1_bits(frame + 12, class2_mask, 3);
+	class2_zeros = 17 - class2_ones;
+	n1n2 = class1_zeros + class2_zeros;
+
+	fprintf(outf, "%s %u %u", linebuf, class1_zeros, n1n2);
+	if (n1n2 >= 11 && n1n2 < 16)
+		fputs(" SID-1-diff", outf);
+	if (n1n2 >= 16 && n1n2 <= 25)
+		fputs(" BCI-to-BFI", outf);
+	putc('\n', outf);
+}
+
+main(argc, argv)
+	char **argv;
+{
+	if (argc >= 2) {
+		infname = argv[1];
+		inf = fopen(infname, "r");
+		if (!inf) {
+			perror(infname);
+			exit(1);
+		}
+	} else {
+		inf = stdin;
+		infname = "stdin";
+	}
+
+	if (argc >= 3) {
+		outfname = argv[2];
+		outf = fopen(outfname, "w");
+		if (!outf) {
+			perror(outfname);
+			exit(1);
+		}
+	} else {
+		outf = stdout;
+		outfname = "stdout";
+	}
+
+	for (lineno = 1; fgets(linebuf, sizeof linebuf, inf); lineno++)
+		process_line();
+
+	exit(0);
+}