FreeCalypso > hg > gsm-net-reveng
comparison 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 | d4ee42801cdc |
comparison
equal
deleted
inserted
replaced
| 30:19039ffbe605 | 31:5f98c5cae4ea |
|---|---|
| 1 /* | |
| 2 * This program reads a 64 kbit/s timeslot recording file and looks for | |
| 3 * TFO frames of GSM 08.62, specifically the FR/EFR kind. | |
| 4 */ | |
| 5 | |
| 6 #include <stdio.h> | |
| 7 #include <stdint.h> | |
| 8 #include <stdlib.h> | |
| 9 #include <string.h> | |
| 10 #include <strings.h> | |
| 11 | |
| 12 static unsigned file_offset; | |
| 13 | |
| 14 static enum { | |
| 15 HUNT_FOR_0, | |
| 16 HUNT_FOUND_0, | |
| 17 GOT_8_ZEROS, | |
| 18 SYNCED | |
| 19 } state; | |
| 20 static unsigned hunt_for_0_count, frame_pos_count; | |
| 21 static uint8_t in_frame_2bit[160], frame_bits[320], d_bits[260]; | |
| 22 | |
| 23 static void | |
| 24 unpack_dibits() | |
| 25 { | |
| 26 int i, inb; | |
| 27 uint8_t *op; | |
| 28 | |
| 29 op = frame_bits; | |
| 30 for (i = 0; i < 160; i++) { | |
| 31 inb = in_frame_2bit[i]; | |
| 32 if (inb & 1) | |
| 33 *op++ = 1; | |
| 34 else | |
| 35 *op++ = 0; | |
| 36 if (inb & 2) | |
| 37 *op++ = 1; | |
| 38 else | |
| 39 *op++ = 0; | |
| 40 } | |
| 41 } | |
| 42 | |
| 43 static unsigned | |
| 44 bits_to_num(bits, nbits) | |
| 45 uint8_t *bits; | |
| 46 unsigned nbits; | |
| 47 { | |
| 48 unsigned accum; | |
| 49 unsigned n; | |
| 50 | |
| 51 accum = 0; | |
| 52 for (n = 0; n < nbits; n++) { | |
| 53 accum <<= 1; | |
| 54 if (*bits) | |
| 55 accum |= 1; | |
| 56 bits++; | |
| 57 } | |
| 58 return accum; | |
| 59 } | |
| 60 | |
| 61 static void | |
| 62 collect_d_bits() | |
| 63 { | |
| 64 bcopy(frame_bits + 33, d_bits, 15); | |
| 65 bcopy(frame_bits + 49, d_bits + 15, 15); | |
| 66 bcopy(frame_bits + 65, d_bits + 30, 15); | |
| 67 bcopy(frame_bits + 81, d_bits + 45, 15); | |
| 68 bcopy(frame_bits + 97, d_bits + 60, 15); | |
| 69 bcopy(frame_bits + 113, d_bits + 75, 15); | |
| 70 bcopy(frame_bits + 129, d_bits + 90, 15); | |
| 71 bcopy(frame_bits + 145, d_bits + 105, 15); | |
| 72 bcopy(frame_bits + 161, d_bits + 120, 15); | |
| 73 bcopy(frame_bits + 177, d_bits + 135, 15); | |
| 74 bcopy(frame_bits + 193, d_bits + 150, 15); | |
| 75 bcopy(frame_bits + 209, d_bits + 165, 15); | |
| 76 bcopy(frame_bits + 225, d_bits + 180, 15); | |
| 77 bcopy(frame_bits + 241, d_bits + 195, 15); | |
| 78 bcopy(frame_bits + 257, d_bits + 210, 15); | |
| 79 bcopy(frame_bits + 273, d_bits + 225, 15); | |
| 80 bcopy(frame_bits + 289, d_bits + 240, 15); | |
| 81 bcopy(frame_bits + 305, d_bits + 255, 5); | |
| 82 } | |
| 83 | |
| 84 static void | |
| 85 process_frame() | |
| 86 { | |
| 87 unsigned c1_5eq, c6_11; | |
| 88 | |
| 89 printf("Frame at 0x%x:\n", file_offset - 159); | |
| 90 printf(" C1-C5: %u%u%u%u%u", frame_bits[17], frame_bits[18], | |
| 91 frame_bits[19], frame_bits[20], frame_bits[21]); | |
| 92 c1_5eq = bits_to_num(frame_bits + 17, 4) << 1; | |
| 93 switch (c1_5eq) { | |
| 94 case 0x02: | |
| 95 fputs(" (FR UL)", stdout); | |
| 96 break; | |
| 97 case 0x1C: | |
| 98 fputs(" (FR DL)", stdout); | |
| 99 break; | |
| 100 case 0x1A: | |
| 101 fputs(" (EFR)", stdout); | |
| 102 break; | |
| 103 case 0x10: | |
| 104 fputs(" (idle UL)", stdout); | |
| 105 break; | |
| 106 case 0x0E: | |
| 107 fputs(" (idle DL)", stdout); | |
| 108 break; | |
| 109 } | |
| 110 putchar('\n'); | |
| 111 c6_11 = bits_to_num(frame_bits + 22, 6); | |
| 112 printf(" C6-C11: %u\n", c6_11); | |
| 113 printf(" C12=%u C13=%u C14=%u C15=%u\n", frame_bits[28], | |
| 114 frame_bits[29], frame_bits[30], frame_bits[31]); | |
| 115 switch (c1_5eq) { | |
| 116 case 0x02: | |
| 117 case 0x1C: | |
| 118 collect_d_bits(); | |
| 119 print_fr_frame(d_bits); | |
| 120 break; | |
| 121 case 0x1A: | |
| 122 collect_d_bits(); | |
| 123 check_efr_crc(d_bits); | |
| 124 print_efr_frame(d_bits); | |
| 125 break; | |
| 126 } | |
| 127 printf(" C16=%u C17=%u C18=%u C19=%u C20=%u C21=%u\n", | |
| 128 frame_bits[310], frame_bits[311], frame_bits[312], | |
| 129 frame_bits[313], frame_bits[314], frame_bits[315]); | |
| 130 printf(" T1=%u T2=%u T3=%u T4=%u\n", frame_bits[316], frame_bits[317], | |
| 131 frame_bits[318], frame_bits[319]); | |
| 132 } | |
| 133 | |
| 134 static int | |
| 135 check_sync_zeros() | |
| 136 { | |
| 137 int i; | |
| 138 | |
| 139 for (i = 0; i < 16; i++) { | |
| 140 if (frame_bits[i]) | |
| 141 return 0; | |
| 142 } | |
| 143 return 1; | |
| 144 } | |
| 145 | |
| 146 static int | |
| 147 check_sync_ones_full() | |
| 148 { | |
| 149 int i; | |
| 150 | |
| 151 for (i = 1; i < 20; i++) { | |
| 152 if (!frame_bits[i*16]) | |
| 153 return 0; | |
| 154 } | |
| 155 return 1; | |
| 156 } | |
| 157 | |
| 158 static int | |
| 159 check_sync_ones_partial() | |
| 160 { | |
| 161 int i; | |
| 162 | |
| 163 for (i = 1; i < 20; i++) { | |
| 164 if ((i & 1) == 0) | |
| 165 continue; | |
| 166 if (!frame_bits[i*16]) | |
| 167 return 0; | |
| 168 } | |
| 169 return 1; | |
| 170 } | |
| 171 | |
| 172 static void | |
| 173 check_sync() | |
| 174 { | |
| 175 if (check_sync_zeros() && check_sync_ones_partial()) { | |
| 176 if (!check_sync_ones_full()) | |
| 177 printf(" Sync pattern partially overwritten!\n"); | |
| 178 return; | |
| 179 } | |
| 180 printf("Bad frame sync, returning to hunt state\n"); | |
| 181 state = HUNT_FOR_0; | |
| 182 } | |
| 183 | |
| 184 static void | |
| 185 byte_input(inb) | |
| 186 { | |
| 187 switch (state) { | |
| 188 case HUNT_FOR_0: | |
| 189 if (inb != 0) | |
| 190 return; | |
| 191 state = HUNT_FOUND_0; | |
| 192 hunt_for_0_count = 1; | |
| 193 return; | |
| 194 case HUNT_FOUND_0: | |
| 195 if (inb != 0) { | |
| 196 state = HUNT_FOR_0; | |
| 197 return; | |
| 198 } | |
| 199 hunt_for_0_count++; | |
| 200 if (hunt_for_0_count >= 8) | |
| 201 state = GOT_8_ZEROS; | |
| 202 return; | |
| 203 case GOT_8_ZEROS: | |
| 204 if (inb & 1) { | |
| 205 printf("Found frame sync at file offset 0x%x\n", | |
| 206 file_offset - 8); | |
| 207 bzero(in_frame_2bit, 8); | |
| 208 in_frame_2bit[8] = inb; | |
| 209 frame_pos_count = 9; | |
| 210 state = SYNCED; | |
| 211 return; | |
| 212 } | |
| 213 if (inb != 0) | |
| 214 state = HUNT_FOR_0; | |
| 215 return; | |
| 216 case SYNCED: | |
| 217 in_frame_2bit[frame_pos_count++] = inb; | |
| 218 if (frame_pos_count < 160) | |
| 219 return; | |
| 220 frame_pos_count = 0; | |
| 221 unpack_dibits(); | |
| 222 process_frame(); | |
| 223 check_sync(); | |
| 224 return; | |
| 225 default: | |
| 226 fprintf(stderr, "BUG: bad sync state\n"); | |
| 227 abort(); | |
| 228 } | |
| 229 } | |
| 230 | |
| 231 main(argc, argv) | |
| 232 char **argv; | |
| 233 { | |
| 234 FILE *inf; | |
| 235 int inb; | |
| 236 | |
| 237 if (argc != 2) { | |
| 238 fprintf(stderr, "usage: %s binfile\n", argv[0]); | |
| 239 exit(1); | |
| 240 } | |
| 241 inf = fopen(argv[1], "r"); | |
| 242 if (!inf) { | |
| 243 perror(argv[1]); | |
| 244 exit(1); | |
| 245 } | |
| 246 state = HUNT_FOR_0; | |
| 247 for (file_offset = 0; ; file_offset++) { | |
| 248 inb = getc(inf); | |
| 249 if (inb < 0) | |
| 250 break; | |
| 251 inb &= 3; | |
| 252 byte_input(inb); | |
| 253 } | |
| 254 exit(0); | |
| 255 } |
