FreeCalypso > hg > gsm-net-reveng
comparison trau-decode/trau-hr-dump.c @ 28:9bcdb091c24d
trau-decode: new program trau-hr-dump
| author | Mychaela Falconia <falcon@freecalypso.org> |
|---|---|
| date | Sun, 18 Aug 2024 08:37:02 +0000 |
| parents | trau-decode/trau-sync8.c@f508dacf2cf9 |
| children | 61181373875d |
comparison
equal
deleted
inserted
replaced
| 27:f508dacf2cf9 | 28:9bcdb091c24d |
|---|---|
| 1 /* | |
| 2 * This program reads a 64 kbit/s timeslot recording file, examines one | |
| 3 * of the eight 8 kbit/s subslots (selected), looks for the sync pattern of | |
| 4 * GSM 08.61, decodes each frame as HRv1 speech and dumps everything it | |
| 5 * decodes. | |
| 6 */ | |
| 7 | |
| 8 #include <sys/types.h> | |
| 9 #include <sys/file.h> | |
| 10 #include <sys/stat.h> | |
| 11 #include <stdio.h> | |
| 12 #include <stdint.h> | |
| 13 #include <stdlib.h> | |
| 14 #include <string.h> | |
| 15 #include <strings.h> | |
| 16 #include <unistd.h> | |
| 17 #include "gsmhr_unpack.h" | |
| 18 #include "osmo_bits.h" | |
| 19 | |
| 20 /* | |
| 21 * EFR TRAU parity (also used for HR) | |
| 22 * | |
| 23 * g(x) = x^3 + x^1 + 1 | |
| 24 */ | |
| 25 static const struct osmo_crc8gen_code gsm0860_efr_crc3 = { | |
| 26 .bits = 3, | |
| 27 .poly = 0x3, | |
| 28 .init = 0x0, | |
| 29 .remainder = 0x7, | |
| 30 }; | |
| 31 | |
| 32 static uint8_t *filebuf; | |
| 33 static unsigned total_size; | |
| 34 | |
| 35 static void | |
| 36 read_ts_file(filename, subslot_arg) | |
| 37 char *filename, *subslot_arg; | |
| 38 { | |
| 39 FILE *inf; | |
| 40 struct stat st; | |
| 41 int subslot, right_shift; | |
| 42 unsigned n; | |
| 43 uint8_t *dp; | |
| 44 int b; | |
| 45 | |
| 46 inf = fopen(filename, "r"); | |
| 47 if (!inf) { | |
| 48 perror(filename); | |
| 49 exit(1); | |
| 50 } | |
| 51 fstat(fileno(inf), &st); | |
| 52 if (!S_ISREG(st.st_mode)) { | |
| 53 fprintf(stderr, "error: %s is not a regular file\n", filename); | |
| 54 exit(1); | |
| 55 } | |
| 56 total_size = st.st_size; | |
| 57 if (total_size < 160) { | |
| 58 fprintf(stderr, "error: %s is too short\n", filename); | |
| 59 exit(1); | |
| 60 } | |
| 61 filebuf = malloc(total_size); | |
| 62 if (!filebuf) { | |
| 63 perror("malloc of file size"); | |
| 64 exit(1); | |
| 65 } | |
| 66 subslot = atoi(subslot_arg); | |
| 67 if (subslot < 0 || subslot > 7) { | |
| 68 fprintf(stderr, "error: invalid subslot argument\n"); | |
| 69 exit(1); | |
| 70 } | |
| 71 right_shift = 7 - subslot; | |
| 72 dp = filebuf; | |
| 73 for (n = 0; n < total_size; n++) { | |
| 74 b = getc(inf); | |
| 75 if (b < 0) { | |
| 76 fprintf(stderr, | |
| 77 "error: getc() returned EOF contrary to st_size\n"); | |
| 78 exit(1); | |
| 79 } | |
| 80 *dp++ = (b >> right_shift) & 1; | |
| 81 } | |
| 82 fclose(inf); | |
| 83 } | |
| 84 | |
| 85 static int | |
| 86 check_sync(pos) | |
| 87 unsigned pos; | |
| 88 { | |
| 89 uint8_t *cand = filebuf + pos; | |
| 90 unsigned n; | |
| 91 | |
| 92 for (n = 0; n < 8; n++) { | |
| 93 if (cand[n]) | |
| 94 return 0; | |
| 95 } | |
| 96 if (!cand[8]) | |
| 97 return 0; | |
| 98 if (cand[16]) | |
| 99 return 0; | |
| 100 if (!cand[17]) | |
| 101 return 0; | |
| 102 for (n = 3; n < 20; n++) { | |
| 103 if (!cand[n * 8]) | |
| 104 return 0; | |
| 105 } | |
| 106 return 1; | |
| 107 } | |
| 108 | |
| 109 static int | |
| 110 bit_parity(bits, nbits) | |
| 111 ubit_t *bits; | |
| 112 unsigned nbits; | |
| 113 { | |
| 114 unsigned n, sum; | |
| 115 | |
| 116 sum = 0; | |
| 117 for (n = 0; n < nbits; n++) | |
| 118 sum += bits[n]; | |
| 119 return sum & 1; | |
| 120 } | |
| 121 | |
| 122 static void | |
| 123 bits2bytes(bits, bytes, nbytes) | |
| 124 ubit_t *bits; | |
| 125 uint8_t *bytes; | |
| 126 unsigned nbytes; | |
| 127 { | |
| 128 unsigned n, m, acc; | |
| 129 | |
| 130 for (n = 0; n < nbytes; n++) { | |
| 131 acc = 0; | |
| 132 for (m = 0; m < 8; m++) { | |
| 133 acc <<= 1; | |
| 134 acc |= *bits++; | |
| 135 } | |
| 136 *bytes++ = acc; | |
| 137 } | |
| 138 } | |
| 139 | |
| 140 static void | |
| 141 process_frame(pos) | |
| 142 unsigned pos; | |
| 143 { | |
| 144 ubit_t *frame = filebuf + pos; | |
| 145 ubit_t xc_bits[6], dbits[112]; | |
| 146 uint8_t hr_bytes[14]; | |
| 147 int16_t params[18]; | |
| 148 int crc_stat; | |
| 149 | |
| 150 printf("Frame at 0x%x:\n", pos); | |
| 151 printf(" C1-C4: %u%u%u%u OP %s\n", frame[9], frame[10], frame[11], | |
| 152 frame[12], bit_parity(frame + 9, 5) ? "good" : "bad"); | |
| 153 bcopy(frame + 14, xc_bits, 2); | |
| 154 bcopy(frame + 18, xc_bits + 2, 4); | |
| 155 printf(" XC1-XC5: %u%u%u%u%u OP %s\n", xc_bits[0], xc_bits[1], | |
| 156 xc_bits[2], xc_bits[3], xc_bits[4], | |
| 157 bit_parity(xc_bits, 6) ? "good" : "bad"); | |
| 158 bcopy(frame + 22, dbits, 2); | |
| 159 bcopy(frame + 25, dbits + 2, 7); | |
| 160 bcopy(frame + 33, dbits + 9, 7); | |
| 161 bcopy(frame + 41, dbits + 16, 7); | |
| 162 bcopy(frame + 49, dbits + 23, 7); | |
| 163 bcopy(frame + 57, dbits + 30, 7); | |
| 164 bcopy(frame + 65, dbits + 37, 7); | |
| 165 bcopy(frame + 76, dbits + 44, 4); | |
| 166 bcopy(frame + 81, dbits + 48, 7); | |
| 167 bcopy(frame + 89, dbits + 55, 7); | |
| 168 bcopy(frame + 97, dbits + 62, 7); | |
| 169 bcopy(frame + 105, dbits + 69, 7); | |
| 170 bcopy(frame + 113, dbits + 76, 7); | |
| 171 bcopy(frame + 121, dbits + 83, 7); | |
| 172 bcopy(frame + 129, dbits + 90, 7); | |
| 173 bcopy(frame + 137, dbits + 97, 7); | |
| 174 bcopy(frame + 145, dbits + 104, 7); | |
| 175 dbits[111] = frame[153]; | |
| 176 crc_stat = osmo_crc8gen_check_bits(&gsm0860_efr_crc3, dbits, 44, | |
| 177 frame + 73); | |
| 178 printf(" CRC %s\n", crc_stat ? "bad" : "good"); | |
| 179 bits2bytes(dbits, hr_bytes, 14); | |
| 180 gsmhr_unpack_ts101318(hr_bytes, params); | |
| 181 printf(" R0=%02x LPC=%03x,%03x,%02x Int=%x Mode=%x\n", params[0], | |
| 182 params[1], params[2], params[3], params[4], params[5]); | |
| 183 printf(params[5] ? " s1=%02x,%03x,%02x" : " s1=%02x,%02x,%02x", | |
| 184 params[6], params[7], params[8]); | |
| 185 printf(params[5] ? " s2=%x,%03x,%02x" : " s2=%02x,%02x,%02x", | |
| 186 params[9], params[10], params[11]); | |
| 187 printf(params[5] ? " s3=%x,%03x,%02x" : " s3=%02x,%02x,%02x", | |
| 188 params[12], params[13], params[14]); | |
| 189 printf(params[5] ? " s4=%x,%03x,%02x\n" : " s4=%02x,%02x,%02x\n", | |
| 190 params[15], params[16], params[17]); | |
| 191 printf(" C6-C9: %u%u%u%u\n", frame[154], frame[155], frame[156], | |
| 192 frame[157]); | |
| 193 printf(" T1=%u T2=%u\n", frame[158], frame[159]); | |
| 194 } | |
| 195 | |
| 196 static void | |
| 197 process_filebuf() | |
| 198 { | |
| 199 unsigned p, endp; | |
| 200 int sync = 0, match; | |
| 201 | |
| 202 endp = total_size - 160; | |
| 203 for (p = 0; p < endp; ) { | |
| 204 match = check_sync(p); | |
| 205 if (match != sync) { | |
| 206 printf("# %s frame sync at file offset 0x%x\n", | |
| 207 match ? "Acquired" : "Lost", p); | |
| 208 } | |
| 209 if (match) { | |
| 210 process_frame(p); | |
| 211 if (!filebuf[p+158] && !filebuf[p+159]) { | |
| 212 printf( | |
| 213 "# both T bits equal 0, shifting frame alignment\n"); | |
| 214 p += 158; | |
| 215 } else | |
| 216 p += 160; | |
| 217 } else | |
| 218 p++; | |
| 219 sync = match; | |
| 220 } | |
| 221 } | |
| 222 | |
| 223 main(argc, argv) | |
| 224 char **argv; | |
| 225 { | |
| 226 if (argc != 3) { | |
| 227 fprintf(stderr, "usage: %s binfile subslot\n", argv[0]); | |
| 228 exit(1); | |
| 229 } | |
| 230 read_ts_file(argv[1], argv[2]); | |
| 231 process_filebuf(); | |
| 232 exit(0); | |
| 233 } |
