FreeCalypso > hg > gsm-net-reveng
changeset 28:9bcdb091c24d default tip
trau-decode: new program trau-hr-dump
author | Mychaela Falconia <falcon@freecalypso.org> |
---|---|
date | Sun, 18 Aug 2024 08:37:02 +0000 |
parents | f508dacf2cf9 |
children | |
files | .hgignore trau-decode/Makefile trau-decode/gsmhr_unpack.c trau-decode/gsmhr_unpack.h trau-decode/trau-hr-dump.c |
diffstat | 5 files changed, 312 insertions(+), 1 deletions(-) [+] |
line wrap: on
line diff
--- a/.hgignore Sun Aug 18 06:26:23 2024 +0000 +++ b/.hgignore Sun Aug 18 08:37:02 2024 +0000 @@ -6,6 +6,7 @@ ^trau-decode/dump-1bit$ ^trau-decode/trau-extr$ +^trau-decode/trau-hr-dump$ ^trau-decode/trau-parse$ ^trau-decode/trau-sync8$
--- a/trau-decode/Makefile Sun Aug 18 06:26:23 2024 +0000 +++ b/trau-decode/Makefile Sun Aug 18 08:37:02 2024 +0000 @@ -1,6 +1,6 @@ CC= gcc CFLAGS= -O2 -PROGS= dump-1bit trau-extr trau-parse trau-sync8 +PROGS= dump-1bit trau-extr trau-hr-dump trau-parse trau-sync8 all: ${PROGS} @@ -10,6 +10,9 @@ trau-extr: extr-fr.o extr-efr.o extr-main.o ${CC} ${CFLAGS} -o $@ $^ -lgsmfr2 +trau-hr-dump: crc8gen.o gsmhr_unpack.o trau-hr-dump.o + ${CC} ${CFLAGS} -o $@ $^ + trau-parse: crc8gen.o parse-fr.o parse-efr.o parse-main.o ${CC} ${CFLAGS} -o $@ $^ -lgsmfr2 -lgsmefr
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/trau-decode/gsmhr_unpack.c Sun Aug 18 08:37:02 2024 +0000 @@ -0,0 +1,68 @@ +/* + * This module has been copied from WIP libgsmhr1: it holds the function that + * unpacks a single GSM-HR codec frame from TS 101 318 packed format into + * the codec's native array of parameters. + */ + +#include <stdint.h> +#include "gsmhr_unpack.h" + +void gsmhr_unpack_ts101318(const uint8_t *payload, int16_t *params) +{ + const uint8_t *c = payload; + + params[0] = (*c >> 3) & 0x1F; + params[1] = (*c++ & 0x7) << 8; + params[1] |= *c++; + params[2] = (*c++ & 0xFF) << 1; + params[2] |= (*c >> 7) & 0x1; + params[3] = (*c++ & 0x7F) << 1; + params[3] |= (*c >> 7) & 0x1; + params[4] = (*c >> 6) & 0x1; + params[5] = (*c >> 4) & 0x3; + if (params[5]) { + /* voiced modes */ + params[6] = (*c++ & 0xF) << 4; + params[6] |= (*c >> 4) & 0xF; + params[7] = (*c++ & 0xF) << 5; + params[7] |= (*c >> 3) & 0x1F; + params[8] = (*c++ & 0x7) << 2; + params[8] |= (*c >> 6) & 0x3; + params[9] = (*c >> 2) & 0xF; + params[10] = (*c++ & 0x3) << 7; + params[10] |= (*c >> 1) & 0x7F; + params[11] = (*c++ & 0x1) << 4; + params[11] |= (*c >> 4) & 0xF; + params[12] = *c++ & 0xF; + params[13] = (*c++ & 0xFF) << 1; + params[13] |= (*c >> 7) & 0x1; + params[14] = (*c >> 2) & 0x1F; + params[15] = (*c++ & 0x3) << 2; + params[15] |= (*c >> 6) & 0x3; + params[16] = (*c++ & 0x3F) << 3; + params[16] |= (*c >> 5) & 0x7; + params[17] = *c++ & 0x1F; + } else { + /* unvoiced mode */ + params[6] = (*c++ & 0xF) << 3; + params[6] |= (*c >> 5) & 0x7; + params[7] = (*c++ & 0x1F) << 2; + params[7] |= (*c >> 6) & 0x3; + params[8] = (*c >> 1) & 0x1F; + params[9] = (*c++ & 0x1) << 6; + params[9] |= (*c >> 2) & 0x3F; + params[10] = (*c++ & 0x3) << 5; + params[10] |= (*c >> 3) & 0x1F; + params[11] = (*c++ & 0x7) << 2; + params[11] |= (*c >> 6) & 0x3; + params[12] = (*c++ & 0x3F) << 1; + params[12] |= (*c >> 7) & 0x1; + params[13] = *c++ & 0x7F; + params[14] = (*c >> 3) & 0x1F; + params[15] = (*c++ & 0x7) << 4; + params[15] |= (*c >> 4) & 0xF; + params[16] = (*c++ & 0xF) << 3; + params[16] |= (*c >> 5) & 0x7; + params[17] = *c++ & 0x1F; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/trau-decode/gsmhr_unpack.h Sun Aug 18 08:37:02 2024 +0000 @@ -0,0 +1,6 @@ +/* + * Function prototype for our local copy (outside of libgsmhr1) + * of gsmhr_unpack_ts101318() function. + */ + +void gsmhr_unpack_ts101318(const uint8_t *payload, int16_t *params);
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/trau-decode/trau-hr-dump.c Sun Aug 18 08:37:02 2024 +0000 @@ -0,0 +1,233 @@ +/* + * This program reads a 64 kbit/s timeslot recording file, examines one + * of the eight 8 kbit/s subslots (selected), looks for the sync pattern of + * GSM 08.61, decodes each frame as HRv1 speech and dumps everything it + * decodes. + */ + +#include <sys/types.h> +#include <sys/file.h> +#include <sys/stat.h> +#include <stdio.h> +#include <stdint.h> +#include <stdlib.h> +#include <string.h> +#include <strings.h> +#include <unistd.h> +#include "gsmhr_unpack.h" +#include "osmo_bits.h" + +/* + * EFR TRAU parity (also used for HR) + * + * g(x) = x^3 + x^1 + 1 + */ +static const struct osmo_crc8gen_code gsm0860_efr_crc3 = { + .bits = 3, + .poly = 0x3, + .init = 0x0, + .remainder = 0x7, +}; + +static uint8_t *filebuf; +static unsigned total_size; + +static void +read_ts_file(filename, subslot_arg) + char *filename, *subslot_arg; +{ + FILE *inf; + struct stat st; + int subslot, right_shift; + unsigned n; + uint8_t *dp; + int b; + + inf = fopen(filename, "r"); + if (!inf) { + perror(filename); + exit(1); + } + fstat(fileno(inf), &st); + if (!S_ISREG(st.st_mode)) { + fprintf(stderr, "error: %s is not a regular file\n", filename); + exit(1); + } + total_size = st.st_size; + if (total_size < 160) { + fprintf(stderr, "error: %s is too short\n", filename); + exit(1); + } + filebuf = malloc(total_size); + if (!filebuf) { + perror("malloc of file size"); + exit(1); + } + subslot = atoi(subslot_arg); + if (subslot < 0 || subslot > 7) { + fprintf(stderr, "error: invalid subslot argument\n"); + exit(1); + } + right_shift = 7 - subslot; + dp = filebuf; + for (n = 0; n < total_size; n++) { + b = getc(inf); + if (b < 0) { + fprintf(stderr, + "error: getc() returned EOF contrary to st_size\n"); + exit(1); + } + *dp++ = (b >> right_shift) & 1; + } + fclose(inf); +} + +static int +check_sync(pos) + unsigned pos; +{ + uint8_t *cand = filebuf + pos; + unsigned n; + + for (n = 0; n < 8; n++) { + if (cand[n]) + return 0; + } + if (!cand[8]) + return 0; + if (cand[16]) + return 0; + if (!cand[17]) + return 0; + for (n = 3; n < 20; n++) { + if (!cand[n * 8]) + return 0; + } + return 1; +} + +static int +bit_parity(bits, nbits) + ubit_t *bits; + unsigned nbits; +{ + unsigned n, sum; + + sum = 0; + for (n = 0; n < nbits; n++) + sum += bits[n]; + return sum & 1; +} + +static void +bits2bytes(bits, bytes, nbytes) + ubit_t *bits; + uint8_t *bytes; + unsigned nbytes; +{ + unsigned n, m, acc; + + for (n = 0; n < nbytes; n++) { + acc = 0; + for (m = 0; m < 8; m++) { + acc <<= 1; + acc |= *bits++; + } + *bytes++ = acc; + } +} + +static void +process_frame(pos) + unsigned pos; +{ + ubit_t *frame = filebuf + pos; + ubit_t xc_bits[6], dbits[112]; + uint8_t hr_bytes[14]; + int16_t params[18]; + int crc_stat; + + printf("Frame at 0x%x:\n", pos); + printf(" C1-C4: %u%u%u%u OP %s\n", frame[9], frame[10], frame[11], + frame[12], bit_parity(frame + 9, 5) ? "good" : "bad"); + bcopy(frame + 14, xc_bits, 2); + bcopy(frame + 18, xc_bits + 2, 4); + printf(" XC1-XC5: %u%u%u%u%u OP %s\n", xc_bits[0], xc_bits[1], + xc_bits[2], xc_bits[3], xc_bits[4], + bit_parity(xc_bits, 6) ? "good" : "bad"); + bcopy(frame + 22, dbits, 2); + bcopy(frame + 25, dbits + 2, 7); + bcopy(frame + 33, dbits + 9, 7); + bcopy(frame + 41, dbits + 16, 7); + bcopy(frame + 49, dbits + 23, 7); + bcopy(frame + 57, dbits + 30, 7); + bcopy(frame + 65, dbits + 37, 7); + bcopy(frame + 76, dbits + 44, 4); + bcopy(frame + 81, dbits + 48, 7); + bcopy(frame + 89, dbits + 55, 7); + bcopy(frame + 97, dbits + 62, 7); + bcopy(frame + 105, dbits + 69, 7); + bcopy(frame + 113, dbits + 76, 7); + bcopy(frame + 121, dbits + 83, 7); + bcopy(frame + 129, dbits + 90, 7); + bcopy(frame + 137, dbits + 97, 7); + bcopy(frame + 145, dbits + 104, 7); + dbits[111] = frame[153]; + crc_stat = osmo_crc8gen_check_bits(&gsm0860_efr_crc3, dbits, 44, + frame + 73); + printf(" CRC %s\n", crc_stat ? "bad" : "good"); + bits2bytes(dbits, hr_bytes, 14); + gsmhr_unpack_ts101318(hr_bytes, params); + printf(" R0=%02x LPC=%03x,%03x,%02x Int=%x Mode=%x\n", params[0], + params[1], params[2], params[3], params[4], params[5]); + printf(params[5] ? " s1=%02x,%03x,%02x" : " s1=%02x,%02x,%02x", + params[6], params[7], params[8]); + printf(params[5] ? " s2=%x,%03x,%02x" : " s2=%02x,%02x,%02x", + params[9], params[10], params[11]); + printf(params[5] ? " s3=%x,%03x,%02x" : " s3=%02x,%02x,%02x", + params[12], params[13], params[14]); + printf(params[5] ? " s4=%x,%03x,%02x\n" : " s4=%02x,%02x,%02x\n", + params[15], params[16], params[17]); + printf(" C6-C9: %u%u%u%u\n", frame[154], frame[155], frame[156], + frame[157]); + printf(" T1=%u T2=%u\n", frame[158], frame[159]); +} + +static void +process_filebuf() +{ + unsigned p, endp; + int sync = 0, match; + + endp = total_size - 160; + for (p = 0; p < endp; ) { + match = check_sync(p); + if (match != sync) { + printf("# %s frame sync at file offset 0x%x\n", + match ? "Acquired" : "Lost", p); + } + if (match) { + process_frame(p); + if (!filebuf[p+158] && !filebuf[p+159]) { + printf( + "# both T bits equal 0, shifting frame alignment\n"); + p += 158; + } else + p += 160; + } else + p++; + sync = match; + } +} + +main(argc, argv) + char **argv; +{ + if (argc != 3) { + fprintf(stderr, "usage: %s binfile subslot\n", argv[0]); + exit(1); + } + read_ts_file(argv[1], argv[2]); + process_filebuf(); + exit(0); +}