FreeCalypso > hg > freecalypso-tools
comparison 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 |
comparison
equal
deleted
inserted
replaced
239:d55368e45bfe | 240:2568a2a8a453 |
---|---|
1 /* | |
2 * This utility compiles a TI audio mode config file from our ASCII source | |
3 * format into the binary for uploading into Calypso device FFS. | |
4 */ | |
5 | |
6 #include <sys/types.h> | |
7 #include <sys/file.h> | |
8 #include <ctype.h> | |
9 #include <string.h> | |
10 #include <strings.h> | |
11 #include <stdio.h> | |
12 #include <stdint.h> | |
13 #include <endian.h> | |
14 #include <stdlib.h> | |
15 #include <unistd.h> | |
16 #include "binstruct.h" | |
17 | |
18 struct audio_cfg_bin bin; | |
19 | |
20 char *infname; | |
21 FILE *inf; | |
22 int lineno; | |
23 | |
24 init_nonzero_defaults() | |
25 { | |
26 bin.mic_bytes[0] = 3; | |
27 bin.mic_fir[0] = 0x4000; | |
28 bin.speaker_fir[0] = 0x4000; | |
29 bin.sidetone_gain = -5; | |
30 } | |
31 | |
32 static long | |
33 strtol_wrap(arg) | |
34 char *arg; | |
35 { | |
36 char *endptr; | |
37 long ret; | |
38 | |
39 ret = strtol(arg, &endptr, 0); | |
40 if (*endptr) { | |
41 fprintf(stderr, "%s line %d: \"%s\" is not a valid number\n", | |
42 infname, lineno, arg); | |
43 exit(1); | |
44 } | |
45 return(ret); | |
46 } | |
47 | |
48 static void | |
49 mic_gain_setting(args) | |
50 char *args; | |
51 { | |
52 char *cp, *np; | |
53 | |
54 for (cp = args; isspace(*cp); cp++) | |
55 ; | |
56 if (*cp == '\0' || *cp == '#') { | |
57 fprintf(stderr, | |
58 "%s line %d: mic gain setting requires an argument\n", | |
59 infname, lineno); | |
60 exit(1); | |
61 } | |
62 for (np = cp; *cp && !isspace(*cp); cp++) | |
63 ; | |
64 if (*cp) | |
65 *cp++ = '\0'; | |
66 while (isspace(*cp)) | |
67 cp++; | |
68 if (*cp != '\0' && *cp != '#') { | |
69 fprintf(stderr, | |
70 "%s line %d: mic gain setting takes only one argument\n", | |
71 infname, lineno); | |
72 exit(1); | |
73 } | |
74 bin.mic_bytes[0] = strtol_wrap(np); | |
75 } | |
76 | |
77 static void | |
78 mic_extra_gain_setting(args) | |
79 char *args; | |
80 { | |
81 char *cp, *np; | |
82 | |
83 if (bin.mic_mode != AUDIO_MICROPHONE_HANDFREE) { | |
84 fprintf(stderr, | |
85 "%s line %d: mic extra-gain setting is only valid in aux mode\n", | |
86 infname, lineno); | |
87 exit(1); | |
88 } | |
89 for (cp = args; isspace(*cp); cp++) | |
90 ; | |
91 if (*cp == '\0' || *cp == '#') { | |
92 fprintf(stderr, | |
93 "%s line %d: mic extra-gain setting requires an argument\n", | |
94 infname, lineno); | |
95 exit(1); | |
96 } | |
97 for (np = cp; *cp && !isspace(*cp); cp++) | |
98 ; | |
99 if (*cp) | |
100 *cp++ = '\0'; | |
101 while (isspace(*cp)) | |
102 cp++; | |
103 if (*cp != '\0' && *cp != '#') { | |
104 fprintf(stderr, | |
105 "%s line %d: mic extra-gain setting takes only one argument\n", | |
106 infname, lineno); | |
107 exit(1); | |
108 } | |
109 bin.mic_bytes[1] = strtol_wrap(np); | |
110 } | |
111 | |
112 static void | |
113 mic_output_bias_setting(args) | |
114 char *args; | |
115 { | |
116 char *cp, *np; | |
117 int idx; | |
118 | |
119 for (cp = args; isspace(*cp); cp++) | |
120 ; | |
121 if (*cp == '\0' || *cp == '#') { | |
122 fprintf(stderr, | |
123 "%s line %d: mic output-bias setting requires an argument\n", | |
124 infname, lineno); | |
125 exit(1); | |
126 } | |
127 for (np = cp; *cp && !isspace(*cp); cp++) | |
128 ; | |
129 if (*cp) | |
130 *cp++ = '\0'; | |
131 while (isspace(*cp)) | |
132 cp++; | |
133 if (*cp != '\0' && *cp != '#') { | |
134 fprintf(stderr, | |
135 "%s line %d: mic output-bias setting takes only one argument\n", | |
136 infname, lineno); | |
137 exit(1); | |
138 } | |
139 if (bin.mic_mode != AUDIO_MICROPHONE_HANDFREE) | |
140 idx = 1; | |
141 else | |
142 idx = 2; | |
143 bin.mic_bytes[idx] = strtol_wrap(np); | |
144 } | |
145 | |
146 static void | |
147 mic_fir_setting(args) | |
148 char *args; | |
149 { | |
150 char *cp, *np; | |
151 int idx, start_idx; | |
152 | |
153 for (cp = args; isspace(*cp); cp++) | |
154 ; | |
155 if (*cp == '\0' || *cp == '#') { | |
156 missing_arg: fprintf(stderr, | |
157 "%s line %d: mic fir setting requires two or more arguments\n", | |
158 infname, lineno); | |
159 exit(1); | |
160 } | |
161 for (np = cp; *cp && !isspace(*cp); cp++) | |
162 ; | |
163 if (*cp) | |
164 *cp++ = '\0'; | |
165 start_idx = strtol_wrap(np); | |
166 if (start_idx < 0 || start_idx > 31) { | |
167 fprintf(stderr, | |
168 "%s line %d: FIR coefficient number must be between 0 and 31\n", | |
169 infname, lineno); | |
170 exit(1); | |
171 } | |
172 for (idx = start_idx; ; idx++) { | |
173 while (isspace(*cp)) | |
174 cp++; | |
175 if (*cp == '\0' || *cp == '#') { | |
176 if (idx == start_idx) | |
177 goto missing_arg; | |
178 break; | |
179 } | |
180 if (idx > 31) { | |
181 fprintf(stderr, | |
182 "%s line %d: spill past FIR coefficient 31\n", | |
183 infname, lineno); | |
184 exit(1); | |
185 } | |
186 for (np = cp; *cp && !isspace(*cp); cp++) | |
187 ; | |
188 if (*cp) | |
189 *cp++ = '\0'; | |
190 bin.mic_fir[idx] = htole16(strtol_wrap(np)); | |
191 } | |
192 } | |
193 | |
194 static void | |
195 mic_head_line(args) | |
196 char *args; | |
197 { | |
198 char linebuf[512]; | |
199 char *cp, *np; | |
200 | |
201 for (cp = args; isspace(*cp); cp++) | |
202 ; | |
203 if (*cp == '\0' || *cp == '#') { | |
204 fprintf(stderr, | |
205 "%s line %d: mic setting requires a mode argument\n", | |
206 infname, lineno); | |
207 exit(1); | |
208 } | |
209 for (np = cp; *cp && !isspace(*cp); cp++) | |
210 ; | |
211 if (*cp) | |
212 *cp++ = '\0'; | |
213 if (!strcmp(np, "default")) | |
214 bin.mic_mode = AUDIO_MICROPHONE_HANDHELD; | |
215 else if (!strcmp(np, "aux")) | |
216 bin.mic_mode = AUDIO_MICROPHONE_HANDFREE; | |
217 else if (!strcmp(np, "headset")) | |
218 bin.mic_mode = AUDIO_MICROPHONE_HEADSET; | |
219 else { | |
220 fprintf(stderr, "%s line %d: unknown mic mode \"%s\"\n", | |
221 infname, lineno, np); | |
222 exit(1); | |
223 } | |
224 while (isspace(*cp)) | |
225 cp++; | |
226 if (*cp == '\0' || *cp == '#') | |
227 return; | |
228 if (*cp != '{') { | |
229 fprintf(stderr, | |
230 "%s line %d: invalid syntax on the mic head line\n", | |
231 infname, lineno); | |
232 exit(1); | |
233 } | |
234 for (;;) { | |
235 if (!fgets(linebuf, sizeof linebuf, inf)) { | |
236 fprintf(stderr, "%s: unexpected EOF in mic section\n", | |
237 infname); | |
238 exit(1); | |
239 } | |
240 lineno++; | |
241 for (cp = linebuf; isspace(*cp); cp++) | |
242 ; | |
243 if (*cp == '\0' || *cp == '#') | |
244 continue; | |
245 for (np = cp; *cp && !isspace(*cp); cp++) | |
246 ; | |
247 if (*cp) | |
248 *cp++ = '\0'; | |
249 if (!strcmp(np, "gain")) | |
250 mic_gain_setting(cp); | |
251 else if (!strcmp(np, "extra-gain")) | |
252 mic_extra_gain_setting(cp); | |
253 else if (!strcmp(np, "output-bias")) | |
254 mic_output_bias_setting(cp); | |
255 else if (!strcmp(np, "fir")) | |
256 mic_fir_setting(cp); | |
257 else if (!strcmp(np, "}")) | |
258 break; | |
259 else { | |
260 fprintf(stderr, | |
261 "%s line %d: unknown mic setting \"%s\"\n", | |
262 infname, lineno, np); | |
263 exit(1); | |
264 } | |
265 } | |
266 } | |
267 | |
268 static void | |
269 speaker_gain_setting(args) | |
270 char *args; | |
271 { | |
272 char *cp, *np; | |
273 | |
274 if (bin.speaker_mode == AUDIO_SPEAKER_BUZZER) { | |
275 fprintf(stderr, | |
276 "%s line %d: speaker gain setting is not valid in buzzer mode\n", | |
277 infname, lineno); | |
278 exit(1); | |
279 } | |
280 for (cp = args; isspace(*cp); cp++) | |
281 ; | |
282 if (*cp == '\0' || *cp == '#') { | |
283 fprintf(stderr, | |
284 "%s line %d: speaker gain setting requires an argument\n", | |
285 infname, lineno); | |
286 exit(1); | |
287 } | |
288 for (np = cp; *cp && !isspace(*cp); cp++) | |
289 ; | |
290 if (*cp) | |
291 *cp++ = '\0'; | |
292 while (isspace(*cp)) | |
293 cp++; | |
294 if (*cp != '\0' && *cp != '#') { | |
295 fprintf(stderr, | |
296 "%s line %d: speaker gain setting takes only one argument\n", | |
297 infname, lineno); | |
298 exit(1); | |
299 } | |
300 bin.speaker_bytes[0] = strtol_wrap(np); | |
301 } | |
302 | |
303 static void | |
304 speaker_audio_filter_setting(args) | |
305 char *args; | |
306 { | |
307 char *cp, *np; | |
308 | |
309 if (bin.speaker_mode == AUDIO_SPEAKER_BUZZER) { | |
310 fprintf(stderr, | |
311 "%s line %d: speaker audio-filter setting is not valid in buzzer mode\n", | |
312 infname, lineno); | |
313 exit(1); | |
314 } | |
315 for (cp = args; isspace(*cp); cp++) | |
316 ; | |
317 if (*cp == '\0' || *cp == '#') { | |
318 fprintf(stderr, | |
319 "%s line %d: speaker audio-filter setting requires an argument\n", | |
320 infname, lineno); | |
321 exit(1); | |
322 } | |
323 for (np = cp; *cp && !isspace(*cp); cp++) | |
324 ; | |
325 if (*cp) | |
326 *cp++ = '\0'; | |
327 while (isspace(*cp)) | |
328 cp++; | |
329 if (*cp != '\0' && *cp != '#') { | |
330 fprintf(stderr, | |
331 "%s line %d: speaker audio-filter setting takes only one argument\n", | |
332 infname, lineno); | |
333 exit(1); | |
334 } | |
335 bin.speaker_bytes[1] = strtol_wrap(np); | |
336 } | |
337 | |
338 static void | |
339 speaker_fir_setting(args) | |
340 char *args; | |
341 { | |
342 char *cp, *np; | |
343 int idx, start_idx; | |
344 | |
345 if (bin.speaker_mode == AUDIO_SPEAKER_BUZZER) { | |
346 fprintf(stderr, | |
347 "%s line %d: speaker fir setting is not valid in buzzer mode\n", | |
348 infname, lineno); | |
349 exit(1); | |
350 } | |
351 for (cp = args; isspace(*cp); cp++) | |
352 ; | |
353 if (*cp == '\0' || *cp == '#') { | |
354 missing_arg: fprintf(stderr, | |
355 "%s line %d: speaker fir setting requires two or more arguments\n", | |
356 infname, lineno); | |
357 exit(1); | |
358 } | |
359 for (np = cp; *cp && !isspace(*cp); cp++) | |
360 ; | |
361 if (*cp) | |
362 *cp++ = '\0'; | |
363 start_idx = strtol_wrap(np); | |
364 if (start_idx < 0 || start_idx > 31) { | |
365 fprintf(stderr, | |
366 "%s line %d: FIR coefficient number must be between 0 and 31\n", | |
367 infname, lineno); | |
368 exit(1); | |
369 } | |
370 for (idx = start_idx; ; idx++) { | |
371 while (isspace(*cp)) | |
372 cp++; | |
373 if (*cp == '\0' || *cp == '#') { | |
374 if (idx == start_idx) | |
375 goto missing_arg; | |
376 break; | |
377 } | |
378 if (idx > 31) { | |
379 fprintf(stderr, | |
380 "%s line %d: spill past FIR coefficient 31\n", | |
381 infname, lineno); | |
382 exit(1); | |
383 } | |
384 for (np = cp; *cp && !isspace(*cp); cp++) | |
385 ; | |
386 if (*cp) | |
387 *cp++ = '\0'; | |
388 bin.speaker_fir[idx] = htole16(strtol_wrap(np)); | |
389 } | |
390 } | |
391 | |
392 static void | |
393 speaker_activate_setting(args) | |
394 char *args; | |
395 { | |
396 char *cp, *np; | |
397 | |
398 if (bin.speaker_mode != AUDIO_SPEAKER_BUZZER) { | |
399 fprintf(stderr, | |
400 "%s line %d: speaker activate setting is only valid in buzzer mode\n", | |
401 infname, lineno); | |
402 exit(1); | |
403 } | |
404 for (cp = args; isspace(*cp); cp++) | |
405 ; | |
406 if (*cp == '\0' || *cp == '#') { | |
407 fprintf(stderr, | |
408 "%s line %d: speaker activate setting requires an argument\n", | |
409 infname, lineno); | |
410 exit(1); | |
411 } | |
412 for (np = cp; *cp && !isspace(*cp); cp++) | |
413 ; | |
414 if (*cp) | |
415 *cp++ = '\0'; | |
416 while (isspace(*cp)) | |
417 cp++; | |
418 if (*cp != '\0' && *cp != '#') { | |
419 fprintf(stderr, | |
420 "%s line %d: speaker activate setting takes only one argument\n", | |
421 infname, lineno); | |
422 exit(1); | |
423 } | |
424 bin.speaker_bytes[0] = strtol_wrap(np); | |
425 } | |
426 | |
427 static void | |
428 speaker_head_line(args) | |
429 char *args; | |
430 { | |
431 char linebuf[512]; | |
432 char *cp, *np; | |
433 | |
434 for (cp = args; isspace(*cp); cp++) | |
435 ; | |
436 if (*cp == '\0' || *cp == '#') { | |
437 fprintf(stderr, | |
438 "%s line %d: speaker setting requires a mode argument\n", | |
439 infname, lineno); | |
440 exit(1); | |
441 } | |
442 for (np = cp; *cp && !isspace(*cp); cp++) | |
443 ; | |
444 if (*cp) | |
445 *cp++ = '\0'; | |
446 if (!strcmp(np, "ear")) | |
447 bin.speaker_mode = AUDIO_SPEAKER_HANDHELD; | |
448 else if (!strcmp(np, "aux")) | |
449 bin.speaker_mode = AUDIO_SPEAKER_HANDFREE; | |
450 else if (!strcmp(np, "headset")) | |
451 bin.speaker_mode = AUDIO_SPEAKER_HEADSET; | |
452 else if (!strcmp(np, "buzzer")) | |
453 bin.speaker_mode = AUDIO_SPEAKER_BUZZER; | |
454 else if (!strcmp(np, "ear+aux")) | |
455 bin.speaker_mode = AUDIO_SPEAKER_HANDHELD_HANDFREE; | |
456 else { | |
457 fprintf(stderr, "%s line %d: unknown speaker mode \"%s\"\n", | |
458 infname, lineno, np); | |
459 exit(1); | |
460 } | |
461 while (isspace(*cp)) | |
462 cp++; | |
463 if (*cp == '\0' || *cp == '#') | |
464 return; | |
465 if (*cp != '{') { | |
466 fprintf(stderr, | |
467 "%s line %d: invalid syntax on the speaker head line\n", | |
468 infname, lineno); | |
469 exit(1); | |
470 } | |
471 for (;;) { | |
472 if (!fgets(linebuf, sizeof linebuf, inf)) { | |
473 fprintf(stderr, | |
474 "%s: unexpected EOF in speaker section\n", | |
475 infname); | |
476 exit(1); | |
477 } | |
478 lineno++; | |
479 for (cp = linebuf; isspace(*cp); cp++) | |
480 ; | |
481 if (*cp == '\0' || *cp == '#') | |
482 continue; | |
483 for (np = cp; *cp && !isspace(*cp); cp++) | |
484 ; | |
485 if (*cp) | |
486 *cp++ = '\0'; | |
487 if (!strcmp(np, "gain")) | |
488 speaker_gain_setting(cp); | |
489 else if (!strcmp(np, "audio-filter")) | |
490 speaker_audio_filter_setting(cp); | |
491 else if (!strcmp(np, "fir")) | |
492 speaker_fir_setting(cp); | |
493 else if (!strcmp(np, "activate")) | |
494 speaker_activate_setting(cp); | |
495 else if (!strcmp(np, "}")) | |
496 break; | |
497 else { | |
498 fprintf(stderr, | |
499 "%s line %d: unknown speaker setting \"%s\"\n", | |
500 infname, lineno, np); | |
501 exit(1); | |
502 } | |
503 } | |
504 } | |
505 | |
506 static void | |
507 voice_path_setting(args) | |
508 char *args; | |
509 { | |
510 char *cp, *np; | |
511 | |
512 for (cp = args; isspace(*cp); cp++) | |
513 ; | |
514 if (*cp == '\0' || *cp == '#') { | |
515 fprintf(stderr, | |
516 "%s line %d: voice-path setting requires an argument\n", | |
517 infname, lineno); | |
518 exit(1); | |
519 } | |
520 for (np = cp; *cp && !isspace(*cp); cp++) | |
521 ; | |
522 if (*cp) | |
523 *cp++ = '\0'; | |
524 while (isspace(*cp)) | |
525 cp++; | |
526 if (*cp != '\0' && *cp != '#') { | |
527 fprintf(stderr, | |
528 "%s line %d: voice-path setting takes only one argument\n", | |
529 infname, lineno); | |
530 exit(1); | |
531 } | |
532 bin.voice_path = strtol_wrap(np); | |
533 } | |
534 | |
535 static void | |
536 sidetone_setting(args) | |
537 char *args; | |
538 { | |
539 char *cp, *np; | |
540 | |
541 for (cp = args; isspace(*cp); cp++) | |
542 ; | |
543 if (*cp == '\0' || *cp == '#') { | |
544 fprintf(stderr, | |
545 "%s line %d: sidetone setting requires an argument\n", | |
546 infname, lineno); | |
547 exit(1); | |
548 } | |
549 for (np = cp; *cp && !isspace(*cp); cp++) | |
550 ; | |
551 if (*cp) | |
552 *cp++ = '\0'; | |
553 while (isspace(*cp)) | |
554 cp++; | |
555 if (*cp != '\0' && *cp != '#') { | |
556 fprintf(stderr, | |
557 "%s line %d: sidetone setting takes only one argument\n", | |
558 infname, lineno); | |
559 exit(1); | |
560 } | |
561 bin.sidetone_gain = strtol_wrap(np); | |
562 } | |
563 | |
564 static void | |
565 aec_setting(args) | |
566 char *args; | |
567 { | |
568 char *cp, *np; | |
569 int n; | |
570 | |
571 cp = args; | |
572 for (n = 0; n < 5; n++) { | |
573 while (isspace(*cp)) | |
574 cp++; | |
575 if (*cp == '\0' || *cp == '#') { | |
576 argcount_err: fprintf(stderr, | |
577 "%s line %d: aec setting takes 5 arguments\n", | |
578 infname, lineno); | |
579 exit(1); | |
580 } | |
581 for (np = cp; *cp && !isspace(*cp); cp++) | |
582 ; | |
583 if (*cp) | |
584 *cp++ = '\0'; | |
585 bin.aec_words[n] = htole16(strtol_wrap(np)); | |
586 } | |
587 while (isspace(*cp)) | |
588 cp++; | |
589 if (*cp != '\0' && *cp != '#') | |
590 goto argcount_err; | |
591 } | |
592 | |
593 read_input_main() | |
594 { | |
595 char linebuf[512]; | |
596 char *cp, *np; | |
597 | |
598 for (lineno = 1; fgets(linebuf, sizeof linebuf, inf); lineno++) { | |
599 for (cp = linebuf; isspace(*cp); cp++) | |
600 ; | |
601 if (*cp == '\0' || *cp == '#') | |
602 continue; | |
603 for (np = cp; *cp && !isspace(*cp); cp++) | |
604 ; | |
605 if (*cp) | |
606 *cp++ = '\0'; | |
607 if (!strcmp(np, "voice-path")) | |
608 voice_path_setting(cp); | |
609 else if (!strcmp(np, "mic")) | |
610 mic_head_line(cp); | |
611 else if (!strcmp(np, "speaker")) | |
612 speaker_head_line(cp); | |
613 else if (!strcmp(np, "sidetone")) | |
614 sidetone_setting(cp); | |
615 else if (!strcmp(np, "aec")) | |
616 aec_setting(cp); | |
617 else { | |
618 fprintf(stderr, | |
619 "%s line %d: unknown top-level setting \"%s\"\n", | |
620 infname, lineno, np); | |
621 exit(1); | |
622 } | |
623 } | |
624 } | |
625 | |
626 write_bin_output(filename) | |
627 char *filename; | |
628 { | |
629 int fd; | |
630 | |
631 fd = open(filename, O_WRONLY|O_CREAT|O_TRUNC, 0666); | |
632 if (fd < 0) { | |
633 perror(filename); | |
634 exit(1); | |
635 } | |
636 write(fd, &bin, sizeof bin); | |
637 close(fd); | |
638 } | |
639 | |
640 main(argc, argv) | |
641 char **argv; | |
642 { | |
643 if (argc != 3) { | |
644 fprintf(stderr, "usage: %s infile outfile\n", argv[0]); | |
645 exit(1); | |
646 } | |
647 if (strcmp(argv[1], "-")) { | |
648 infname = argv[1]; | |
649 inf = fopen(infname, "r"); | |
650 if (!inf) { | |
651 perror(infname); | |
652 exit(1); | |
653 } | |
654 } else { | |
655 inf = stdin; | |
656 infname = "stdin"; | |
657 } | |
658 init_nonzero_defaults(); | |
659 read_input_main(); | |
660 write_bin_output(argv[2]); | |
661 exit(0); | |
662 } |