FreeCalypso > hg > gsm-net-reveng
diff trau-decode/parse-tfo16.c @ 31:5f98c5cae4ea
new program tfo-parse-fr16
author | Mychaela Falconia <falcon@freecalypso.org> |
---|---|
date | Wed, 28 Aug 2024 06:23:21 +0000 |
parents | trau-decode/parse-main.c@4d1732e4a143 |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/trau-decode/parse-tfo16.c Wed Aug 28 06:23:21 2024 +0000 @@ -0,0 +1,255 @@ +/* + * This program reads a 64 kbit/s timeslot recording file and looks for + * TFO frames of GSM 08.62, specifically the FR/EFR kind. + */ + +#include <stdio.h> +#include <stdint.h> +#include <stdlib.h> +#include <string.h> +#include <strings.h> + +static unsigned file_offset; + +static enum { + HUNT_FOR_0, + HUNT_FOUND_0, + GOT_8_ZEROS, + SYNCED +} state; +static unsigned hunt_for_0_count, frame_pos_count; +static uint8_t in_frame_2bit[160], frame_bits[320], d_bits[260]; + +static void +unpack_dibits() +{ + int i, inb; + uint8_t *op; + + op = frame_bits; + for (i = 0; i < 160; i++) { + inb = in_frame_2bit[i]; + if (inb & 1) + *op++ = 1; + else + *op++ = 0; + if (inb & 2) + *op++ = 1; + else + *op++ = 0; + } +} + +static unsigned +bits_to_num(bits, nbits) + uint8_t *bits; + unsigned nbits; +{ + unsigned accum; + unsigned n; + + accum = 0; + for (n = 0; n < nbits; n++) { + accum <<= 1; + if (*bits) + accum |= 1; + bits++; + } + return accum; +} + +static void +collect_d_bits() +{ + bcopy(frame_bits + 33, d_bits, 15); + bcopy(frame_bits + 49, d_bits + 15, 15); + bcopy(frame_bits + 65, d_bits + 30, 15); + bcopy(frame_bits + 81, d_bits + 45, 15); + bcopy(frame_bits + 97, d_bits + 60, 15); + bcopy(frame_bits + 113, d_bits + 75, 15); + bcopy(frame_bits + 129, d_bits + 90, 15); + bcopy(frame_bits + 145, d_bits + 105, 15); + bcopy(frame_bits + 161, d_bits + 120, 15); + bcopy(frame_bits + 177, d_bits + 135, 15); + bcopy(frame_bits + 193, d_bits + 150, 15); + bcopy(frame_bits + 209, d_bits + 165, 15); + bcopy(frame_bits + 225, d_bits + 180, 15); + bcopy(frame_bits + 241, d_bits + 195, 15); + bcopy(frame_bits + 257, d_bits + 210, 15); + bcopy(frame_bits + 273, d_bits + 225, 15); + bcopy(frame_bits + 289, d_bits + 240, 15); + bcopy(frame_bits + 305, d_bits + 255, 5); +} + +static void +process_frame() +{ + unsigned c1_5eq, c6_11; + + printf("Frame at 0x%x:\n", file_offset - 159); + printf(" C1-C5: %u%u%u%u%u", frame_bits[17], frame_bits[18], + frame_bits[19], frame_bits[20], frame_bits[21]); + c1_5eq = bits_to_num(frame_bits + 17, 4) << 1; + switch (c1_5eq) { + case 0x02: + fputs(" (FR UL)", stdout); + break; + case 0x1C: + fputs(" (FR DL)", stdout); + break; + case 0x1A: + fputs(" (EFR)", stdout); + break; + case 0x10: + fputs(" (idle UL)", stdout); + break; + case 0x0E: + fputs(" (idle DL)", stdout); + break; + } + putchar('\n'); + c6_11 = bits_to_num(frame_bits + 22, 6); + printf(" C6-C11: %u\n", c6_11); + printf(" C12=%u C13=%u C14=%u C15=%u\n", frame_bits[28], + frame_bits[29], frame_bits[30], frame_bits[31]); + switch (c1_5eq) { + case 0x02: + case 0x1C: + collect_d_bits(); + print_fr_frame(d_bits); + break; + case 0x1A: + collect_d_bits(); + check_efr_crc(d_bits); + print_efr_frame(d_bits); + break; + } + printf(" C16=%u C17=%u C18=%u C19=%u C20=%u C21=%u\n", + frame_bits[310], frame_bits[311], frame_bits[312], + frame_bits[313], frame_bits[314], frame_bits[315]); + printf(" T1=%u T2=%u T3=%u T4=%u\n", frame_bits[316], frame_bits[317], + frame_bits[318], frame_bits[319]); +} + +static int +check_sync_zeros() +{ + int i; + + for (i = 0; i < 16; i++) { + if (frame_bits[i]) + return 0; + } + return 1; +} + +static int +check_sync_ones_full() +{ + int i; + + for (i = 1; i < 20; i++) { + if (!frame_bits[i*16]) + return 0; + } + return 1; +} + +static int +check_sync_ones_partial() +{ + int i; + + for (i = 1; i < 20; i++) { + if ((i & 1) == 0) + continue; + if (!frame_bits[i*16]) + return 0; + } + return 1; +} + +static void +check_sync() +{ + if (check_sync_zeros() && check_sync_ones_partial()) { + if (!check_sync_ones_full()) + printf(" Sync pattern partially overwritten!\n"); + return; + } + printf("Bad frame sync, returning to hunt state\n"); + state = HUNT_FOR_0; +} + +static void +byte_input(inb) +{ + switch (state) { + case HUNT_FOR_0: + if (inb != 0) + return; + state = HUNT_FOUND_0; + hunt_for_0_count = 1; + return; + case HUNT_FOUND_0: + if (inb != 0) { + state = HUNT_FOR_0; + return; + } + hunt_for_0_count++; + if (hunt_for_0_count >= 8) + state = GOT_8_ZEROS; + return; + case GOT_8_ZEROS: + if (inb & 1) { + printf("Found frame sync at file offset 0x%x\n", + file_offset - 8); + bzero(in_frame_2bit, 8); + in_frame_2bit[8] = inb; + frame_pos_count = 9; + state = SYNCED; + return; + } + if (inb != 0) + state = HUNT_FOR_0; + return; + case SYNCED: + in_frame_2bit[frame_pos_count++] = inb; + if (frame_pos_count < 160) + return; + frame_pos_count = 0; + unpack_dibits(); + process_frame(); + check_sync(); + return; + default: + fprintf(stderr, "BUG: bad sync state\n"); + abort(); + } +} + +main(argc, argv) + char **argv; +{ + FILE *inf; + int inb; + + if (argc != 2) { + fprintf(stderr, "usage: %s binfile\n", argv[0]); + exit(1); + } + inf = fopen(argv[1], "r"); + if (!inf) { + perror(argv[1]); + exit(1); + } + state = HUNT_FOR_0; + for (file_offset = 0; ; file_offset++) { + inb = getc(inf); + if (inb < 0) + break; + inb &= 3; + byte_input(inb); + } + exit(0); +}