FreeCalypso > hg > gsm-net-reveng
view trau-decode/parse-tfo16.c @ 36:d9553c7ac6ea
doc/TFO-xform/EFR: beginning of article
author | Mychaela Falconia <falcon@freecalypso.org> |
---|---|
date | Tue, 03 Sep 2024 07:08:24 +0000 |
parents | 5f98c5cae4ea |
children |
line wrap: on
line source
/* * 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); }