FreeCalypso > hg > freecalypso-tools
diff ffstools/tiaud/compile.c @ 240:2568a2a8a453
tiaud-compile program written
author | Mychaela Falconia <falcon@freecalypso.org> |
---|---|
date | Fri, 25 Aug 2017 23:36:07 +0000 |
parents | |
children | 2abc086b13ed |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ffstools/tiaud/compile.c Fri Aug 25 23:36:07 2017 +0000 @@ -0,0 +1,662 @@ +/* + * This utility compiles a TI audio mode config file from our ASCII source + * format into the binary for uploading into Calypso device FFS. + */ + +#include <sys/types.h> +#include <sys/file.h> +#include <ctype.h> +#include <string.h> +#include <strings.h> +#include <stdio.h> +#include <stdint.h> +#include <endian.h> +#include <stdlib.h> +#include <unistd.h> +#include "binstruct.h" + +struct audio_cfg_bin bin; + +char *infname; +FILE *inf; +int lineno; + +init_nonzero_defaults() +{ + bin.mic_bytes[0] = 3; + bin.mic_fir[0] = 0x4000; + bin.speaker_fir[0] = 0x4000; + bin.sidetone_gain = -5; +} + +static long +strtol_wrap(arg) + char *arg; +{ + char *endptr; + long ret; + + ret = strtol(arg, &endptr, 0); + if (*endptr) { + fprintf(stderr, "%s line %d: \"%s\" is not a valid number\n", + infname, lineno, arg); + exit(1); + } + return(ret); +} + +static void +mic_gain_setting(args) + char *args; +{ + char *cp, *np; + + for (cp = args; isspace(*cp); cp++) + ; + if (*cp == '\0' || *cp == '#') { + fprintf(stderr, + "%s line %d: mic gain setting requires an argument\n", + infname, lineno); + exit(1); + } + for (np = cp; *cp && !isspace(*cp); cp++) + ; + if (*cp) + *cp++ = '\0'; + while (isspace(*cp)) + cp++; + if (*cp != '\0' && *cp != '#') { + fprintf(stderr, + "%s line %d: mic gain setting takes only one argument\n", + infname, lineno); + exit(1); + } + bin.mic_bytes[0] = strtol_wrap(np); +} + +static void +mic_extra_gain_setting(args) + char *args; +{ + char *cp, *np; + + if (bin.mic_mode != AUDIO_MICROPHONE_HANDFREE) { + fprintf(stderr, + "%s line %d: mic extra-gain setting is only valid in aux mode\n", + infname, lineno); + exit(1); + } + for (cp = args; isspace(*cp); cp++) + ; + if (*cp == '\0' || *cp == '#') { + fprintf(stderr, + "%s line %d: mic extra-gain setting requires an argument\n", + infname, lineno); + exit(1); + } + for (np = cp; *cp && !isspace(*cp); cp++) + ; + if (*cp) + *cp++ = '\0'; + while (isspace(*cp)) + cp++; + if (*cp != '\0' && *cp != '#') { + fprintf(stderr, + "%s line %d: mic extra-gain setting takes only one argument\n", + infname, lineno); + exit(1); + } + bin.mic_bytes[1] = strtol_wrap(np); +} + +static void +mic_output_bias_setting(args) + char *args; +{ + char *cp, *np; + int idx; + + for (cp = args; isspace(*cp); cp++) + ; + if (*cp == '\0' || *cp == '#') { + fprintf(stderr, + "%s line %d: mic output-bias setting requires an argument\n", + infname, lineno); + exit(1); + } + for (np = cp; *cp && !isspace(*cp); cp++) + ; + if (*cp) + *cp++ = '\0'; + while (isspace(*cp)) + cp++; + if (*cp != '\0' && *cp != '#') { + fprintf(stderr, + "%s line %d: mic output-bias setting takes only one argument\n", + infname, lineno); + exit(1); + } + if (bin.mic_mode != AUDIO_MICROPHONE_HANDFREE) + idx = 1; + else + idx = 2; + bin.mic_bytes[idx] = strtol_wrap(np); +} + +static void +mic_fir_setting(args) + char *args; +{ + char *cp, *np; + int idx, start_idx; + + for (cp = args; isspace(*cp); cp++) + ; + if (*cp == '\0' || *cp == '#') { +missing_arg: fprintf(stderr, + "%s line %d: mic fir setting requires two or more arguments\n", + infname, lineno); + exit(1); + } + for (np = cp; *cp && !isspace(*cp); cp++) + ; + if (*cp) + *cp++ = '\0'; + start_idx = strtol_wrap(np); + if (start_idx < 0 || start_idx > 31) { + fprintf(stderr, + "%s line %d: FIR coefficient number must be between 0 and 31\n", + infname, lineno); + exit(1); + } + for (idx = start_idx; ; idx++) { + while (isspace(*cp)) + cp++; + if (*cp == '\0' || *cp == '#') { + if (idx == start_idx) + goto missing_arg; + break; + } + if (idx > 31) { + fprintf(stderr, + "%s line %d: spill past FIR coefficient 31\n", + infname, lineno); + exit(1); + } + for (np = cp; *cp && !isspace(*cp); cp++) + ; + if (*cp) + *cp++ = '\0'; + bin.mic_fir[idx] = htole16(strtol_wrap(np)); + } +} + +static void +mic_head_line(args) + char *args; +{ + char linebuf[512]; + char *cp, *np; + + for (cp = args; isspace(*cp); cp++) + ; + if (*cp == '\0' || *cp == '#') { + fprintf(stderr, + "%s line %d: mic setting requires a mode argument\n", + infname, lineno); + exit(1); + } + for (np = cp; *cp && !isspace(*cp); cp++) + ; + if (*cp) + *cp++ = '\0'; + if (!strcmp(np, "default")) + bin.mic_mode = AUDIO_MICROPHONE_HANDHELD; + else if (!strcmp(np, "aux")) + bin.mic_mode = AUDIO_MICROPHONE_HANDFREE; + else if (!strcmp(np, "headset")) + bin.mic_mode = AUDIO_MICROPHONE_HEADSET; + else { + fprintf(stderr, "%s line %d: unknown mic mode \"%s\"\n", + infname, lineno, np); + exit(1); + } + while (isspace(*cp)) + cp++; + if (*cp == '\0' || *cp == '#') + return; + if (*cp != '{') { + fprintf(stderr, + "%s line %d: invalid syntax on the mic head line\n", + infname, lineno); + exit(1); + } + for (;;) { + if (!fgets(linebuf, sizeof linebuf, inf)) { + fprintf(stderr, "%s: unexpected EOF in mic section\n", + infname); + exit(1); + } + lineno++; + for (cp = linebuf; isspace(*cp); cp++) + ; + if (*cp == '\0' || *cp == '#') + continue; + for (np = cp; *cp && !isspace(*cp); cp++) + ; + if (*cp) + *cp++ = '\0'; + if (!strcmp(np, "gain")) + mic_gain_setting(cp); + else if (!strcmp(np, "extra-gain")) + mic_extra_gain_setting(cp); + else if (!strcmp(np, "output-bias")) + mic_output_bias_setting(cp); + else if (!strcmp(np, "fir")) + mic_fir_setting(cp); + else if (!strcmp(np, "}")) + break; + else { + fprintf(stderr, + "%s line %d: unknown mic setting \"%s\"\n", + infname, lineno, np); + exit(1); + } + } +} + +static void +speaker_gain_setting(args) + char *args; +{ + char *cp, *np; + + if (bin.speaker_mode == AUDIO_SPEAKER_BUZZER) { + fprintf(stderr, + "%s line %d: speaker gain setting is not valid in buzzer mode\n", + infname, lineno); + exit(1); + } + for (cp = args; isspace(*cp); cp++) + ; + if (*cp == '\0' || *cp == '#') { + fprintf(stderr, + "%s line %d: speaker gain setting requires an argument\n", + infname, lineno); + exit(1); + } + for (np = cp; *cp && !isspace(*cp); cp++) + ; + if (*cp) + *cp++ = '\0'; + while (isspace(*cp)) + cp++; + if (*cp != '\0' && *cp != '#') { + fprintf(stderr, + "%s line %d: speaker gain setting takes only one argument\n", + infname, lineno); + exit(1); + } + bin.speaker_bytes[0] = strtol_wrap(np); +} + +static void +speaker_audio_filter_setting(args) + char *args; +{ + char *cp, *np; + + if (bin.speaker_mode == AUDIO_SPEAKER_BUZZER) { + fprintf(stderr, + "%s line %d: speaker audio-filter setting is not valid in buzzer mode\n", + infname, lineno); + exit(1); + } + for (cp = args; isspace(*cp); cp++) + ; + if (*cp == '\0' || *cp == '#') { + fprintf(stderr, + "%s line %d: speaker audio-filter setting requires an argument\n", + infname, lineno); + exit(1); + } + for (np = cp; *cp && !isspace(*cp); cp++) + ; + if (*cp) + *cp++ = '\0'; + while (isspace(*cp)) + cp++; + if (*cp != '\0' && *cp != '#') { + fprintf(stderr, + "%s line %d: speaker audio-filter setting takes only one argument\n", + infname, lineno); + exit(1); + } + bin.speaker_bytes[1] = strtol_wrap(np); +} + +static void +speaker_fir_setting(args) + char *args; +{ + char *cp, *np; + int idx, start_idx; + + if (bin.speaker_mode == AUDIO_SPEAKER_BUZZER) { + fprintf(stderr, + "%s line %d: speaker fir setting is not valid in buzzer mode\n", + infname, lineno); + exit(1); + } + for (cp = args; isspace(*cp); cp++) + ; + if (*cp == '\0' || *cp == '#') { +missing_arg: fprintf(stderr, + "%s line %d: speaker fir setting requires two or more arguments\n", + infname, lineno); + exit(1); + } + for (np = cp; *cp && !isspace(*cp); cp++) + ; + if (*cp) + *cp++ = '\0'; + start_idx = strtol_wrap(np); + if (start_idx < 0 || start_idx > 31) { + fprintf(stderr, + "%s line %d: FIR coefficient number must be between 0 and 31\n", + infname, lineno); + exit(1); + } + for (idx = start_idx; ; idx++) { + while (isspace(*cp)) + cp++; + if (*cp == '\0' || *cp == '#') { + if (idx == start_idx) + goto missing_arg; + break; + } + if (idx > 31) { + fprintf(stderr, + "%s line %d: spill past FIR coefficient 31\n", + infname, lineno); + exit(1); + } + for (np = cp; *cp && !isspace(*cp); cp++) + ; + if (*cp) + *cp++ = '\0'; + bin.speaker_fir[idx] = htole16(strtol_wrap(np)); + } +} + +static void +speaker_activate_setting(args) + char *args; +{ + char *cp, *np; + + if (bin.speaker_mode != AUDIO_SPEAKER_BUZZER) { + fprintf(stderr, + "%s line %d: speaker activate setting is only valid in buzzer mode\n", + infname, lineno); + exit(1); + } + for (cp = args; isspace(*cp); cp++) + ; + if (*cp == '\0' || *cp == '#') { + fprintf(stderr, + "%s line %d: speaker activate setting requires an argument\n", + infname, lineno); + exit(1); + } + for (np = cp; *cp && !isspace(*cp); cp++) + ; + if (*cp) + *cp++ = '\0'; + while (isspace(*cp)) + cp++; + if (*cp != '\0' && *cp != '#') { + fprintf(stderr, + "%s line %d: speaker activate setting takes only one argument\n", + infname, lineno); + exit(1); + } + bin.speaker_bytes[0] = strtol_wrap(np); +} + +static void +speaker_head_line(args) + char *args; +{ + char linebuf[512]; + char *cp, *np; + + for (cp = args; isspace(*cp); cp++) + ; + if (*cp == '\0' || *cp == '#') { + fprintf(stderr, + "%s line %d: speaker setting requires a mode argument\n", + infname, lineno); + exit(1); + } + for (np = cp; *cp && !isspace(*cp); cp++) + ; + if (*cp) + *cp++ = '\0'; + if (!strcmp(np, "ear")) + bin.speaker_mode = AUDIO_SPEAKER_HANDHELD; + else if (!strcmp(np, "aux")) + bin.speaker_mode = AUDIO_SPEAKER_HANDFREE; + else if (!strcmp(np, "headset")) + bin.speaker_mode = AUDIO_SPEAKER_HEADSET; + else if (!strcmp(np, "buzzer")) + bin.speaker_mode = AUDIO_SPEAKER_BUZZER; + else if (!strcmp(np, "ear+aux")) + bin.speaker_mode = AUDIO_SPEAKER_HANDHELD_HANDFREE; + else { + fprintf(stderr, "%s line %d: unknown speaker mode \"%s\"\n", + infname, lineno, np); + exit(1); + } + while (isspace(*cp)) + cp++; + if (*cp == '\0' || *cp == '#') + return; + if (*cp != '{') { + fprintf(stderr, + "%s line %d: invalid syntax on the speaker head line\n", + infname, lineno); + exit(1); + } + for (;;) { + if (!fgets(linebuf, sizeof linebuf, inf)) { + fprintf(stderr, + "%s: unexpected EOF in speaker section\n", + infname); + exit(1); + } + lineno++; + for (cp = linebuf; isspace(*cp); cp++) + ; + if (*cp == '\0' || *cp == '#') + continue; + for (np = cp; *cp && !isspace(*cp); cp++) + ; + if (*cp) + *cp++ = '\0'; + if (!strcmp(np, "gain")) + speaker_gain_setting(cp); + else if (!strcmp(np, "audio-filter")) + speaker_audio_filter_setting(cp); + else if (!strcmp(np, "fir")) + speaker_fir_setting(cp); + else if (!strcmp(np, "activate")) + speaker_activate_setting(cp); + else if (!strcmp(np, "}")) + break; + else { + fprintf(stderr, + "%s line %d: unknown speaker setting \"%s\"\n", + infname, lineno, np); + exit(1); + } + } +} + +static void +voice_path_setting(args) + char *args; +{ + char *cp, *np; + + for (cp = args; isspace(*cp); cp++) + ; + if (*cp == '\0' || *cp == '#') { + fprintf(stderr, + "%s line %d: voice-path setting requires an argument\n", + infname, lineno); + exit(1); + } + for (np = cp; *cp && !isspace(*cp); cp++) + ; + if (*cp) + *cp++ = '\0'; + while (isspace(*cp)) + cp++; + if (*cp != '\0' && *cp != '#') { + fprintf(stderr, + "%s line %d: voice-path setting takes only one argument\n", + infname, lineno); + exit(1); + } + bin.voice_path = strtol_wrap(np); +} + +static void +sidetone_setting(args) + char *args; +{ + char *cp, *np; + + for (cp = args; isspace(*cp); cp++) + ; + if (*cp == '\0' || *cp == '#') { + fprintf(stderr, + "%s line %d: sidetone setting requires an argument\n", + infname, lineno); + exit(1); + } + for (np = cp; *cp && !isspace(*cp); cp++) + ; + if (*cp) + *cp++ = '\0'; + while (isspace(*cp)) + cp++; + if (*cp != '\0' && *cp != '#') { + fprintf(stderr, + "%s line %d: sidetone setting takes only one argument\n", + infname, lineno); + exit(1); + } + bin.sidetone_gain = strtol_wrap(np); +} + +static void +aec_setting(args) + char *args; +{ + char *cp, *np; + int n; + + cp = args; + for (n = 0; n < 5; n++) { + while (isspace(*cp)) + cp++; + if (*cp == '\0' || *cp == '#') { +argcount_err: fprintf(stderr, + "%s line %d: aec setting takes 5 arguments\n", + infname, lineno); + exit(1); + } + for (np = cp; *cp && !isspace(*cp); cp++) + ; + if (*cp) + *cp++ = '\0'; + bin.aec_words[n] = htole16(strtol_wrap(np)); + } + while (isspace(*cp)) + cp++; + if (*cp != '\0' && *cp != '#') + goto argcount_err; +} + +read_input_main() +{ + char linebuf[512]; + char *cp, *np; + + for (lineno = 1; fgets(linebuf, sizeof linebuf, inf); lineno++) { + for (cp = linebuf; isspace(*cp); cp++) + ; + if (*cp == '\0' || *cp == '#') + continue; + for (np = cp; *cp && !isspace(*cp); cp++) + ; + if (*cp) + *cp++ = '\0'; + if (!strcmp(np, "voice-path")) + voice_path_setting(cp); + else if (!strcmp(np, "mic")) + mic_head_line(cp); + else if (!strcmp(np, "speaker")) + speaker_head_line(cp); + else if (!strcmp(np, "sidetone")) + sidetone_setting(cp); + else if (!strcmp(np, "aec")) + aec_setting(cp); + else { + fprintf(stderr, + "%s line %d: unknown top-level setting \"%s\"\n", + infname, lineno, np); + exit(1); + } + } +} + +write_bin_output(filename) + char *filename; +{ + int fd; + + fd = open(filename, O_WRONLY|O_CREAT|O_TRUNC, 0666); + if (fd < 0) { + perror(filename); + exit(1); + } + write(fd, &bin, sizeof bin); + close(fd); +} + +main(argc, argv) + char **argv; +{ + if (argc != 3) { + fprintf(stderr, "usage: %s infile outfile\n", argv[0]); + exit(1); + } + if (strcmp(argv[1], "-")) { + infname = argv[1]; + inf = fopen(infname, "r"); + if (!inf) { + perror(infname); + exit(1); + } + } else { + inf = stdin; + infname = "stdin"; + } + init_nonzero_defaults(); + read_input_main(); + write_bin_output(argv[2]); + exit(0); +}