view tchtools/fc-tch2fr.c @ 982:1c5b485f10ba

fc-loadtool flash: do AMD reset after PL-J PPB write operations
author Mychaela Falconia <falcon@freecalypso.org>
date Sat, 02 Dec 2023 06:04:37 +0000
parents a7ad6b39e01b
children
line wrap: on
line source

/*
 * This program reads TCH downlink capture files in the old format from 2016
 * (the format which fc-shell tch record will write if the firmware running
 * on the Calypso GSM device is an old version that emits TCH DL bits in
 * the old format from 2016), completely *disregards* all 3 status words
 * including the essential word of control flags, converts the 260-bit
 * payload portion of each frame into standard libgsm/RTP format, and
 * writes the result into a .gsm binary file.
 *
 * This program was written in 2016, at that time we (FreeCalypso team)
 * did not have a proper understanding of how the complete TCH DL processing
 * chain works - we particularly missed the Rx DTX handler block that MUST
 * be present between the output of the GSM 05.03 channel decoder and the
 * input to the GSM 06.10 speech decoder - and therefore the function
 * performed by this program is a bogo-transform.
 *
 * This bogo-transform program is kept as part of FC host tools package
 * only for backward compatibility - for actual decoding of TCH DL captures,
 * please use our new gsmfr-dlcap-* and gsmefr-dlcap-* utilities that are
 * maintained as part of Themyscira Wireless GSM codec libraries & utilities
 * package.
 */

#include <sys/types.h>
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>

static
decode_hex_digit(ch)
{
	if (isdigit(ch))
		return(ch - '0');
	else if (isupper(ch))
		return(ch - 'A' + 10);
	else
		return(ch - 'a' + 10);
}

main(argc, argv)
	char **argv;
{
	FILE *inf, *outf;
	char linebuf[128];
	int lineno;
	char *cp;
	int i, j;
	u_char tidsp_bytes[33], libgsm_bytes[33];

	if (argc != 3) {
		fprintf(stderr, "usage: %s infile outfile\n", argv[0]);
		exit(1);
	}
	inf = fopen(argv[1], "r");
	if (!inf) {
		perror(argv[1]);
		exit(1);
	}
	outf = fopen(argv[2], "w");
	if (!outf) {
		perror(argv[2]);
		exit(1);
	}
	for (lineno = 1; fgets(linebuf, sizeof linebuf, inf); lineno++) {
		/* skip DSP status words */
		cp = linebuf;
		for (i = 0; i < 3; i++) {
			for (j = 0; j < 4; j++) {
				if (!isxdigit(*cp++)) {
invalid:				fprintf(stderr,
				    "error: %s is not in the expected format\n",
						argv[1]);
					exit(1);
				}
			}
			if (*cp++ != ' ')
				goto invalid;
		}
		/* read the frame bits */
		for (i = 0; i < 33; i++) {
			if (!isxdigit(cp[0]) || !isxdigit(cp[1]))
				goto invalid;
			tidsp_bytes[i] = (decode_hex_digit(cp[0]) << 4) |
					  decode_hex_digit(cp[1]);
			cp += 2;
		}
		gsm0610_tidsp_to_libgsm(tidsp_bytes, libgsm_bytes);
		fwrite(libgsm_bytes, 1, 33, outf);
	}
	exit(0);
}