# HG changeset patch # User Mychaela Falconia # Date 1477378167 0 # Node ID cefdc662332287a44b326874c9abd91686327363 # Parent ea061975c883ab3cdc7aa8deab1dc3bdc1e71497 fc-e1gen utility written, compiles diff -r ea061975c883 -r cefdc6623322 .hgignore --- a/.hgignore Sun Oct 23 21:52:29 2016 +0000 +++ b/.hgignore Tue Oct 25 06:49:27 2016 +0000 @@ -22,6 +22,8 @@ ^miscutil/fc-tch2fr$ ^miscutil/imei-luhn$ +^ringtools/fc-e1gen$ + ^rvinterf/asyncshell/fc-shell$ ^rvinterf/ctracedec/ctracedec$ ^rvinterf/etmsync/fc-dspapidump$ diff -r ea061975c883 -r cefdc6623322 ringtools/Makefile --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ringtools/Makefile Tue Oct 25 06:49:27 2016 +0000 @@ -0,0 +1,16 @@ +CC= gcc +CFLAGS= -O2 +PROGS= fc-e1gen +INSTBIN=/usr/local/bin + +all: ${PROGS} + +fc-e1gen: fc-e1gen.c + ${CC} ${CFLAGS} -o $@ $@.c + +install: + mkdir -p ${INSTBIN} + install -c ${PROGS} ${INSTBIN} + +clean: + rm -f ${PROGS} *.o *errs *.out diff -r ea061975c883 -r cefdc6623322 ringtools/examples/example.e1src --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ringtools/examples/example.e1src Tue Oct 25 06:49:27 2016 +0000 @@ -0,0 +1,13 @@ +time 1 +osc 0 df 8135 120 + +time 25 +osc 0 df 0 0 + +time 25 +osc 0 df 8135 120 + +time 25 +osc 0 df 0 0 + +end diff -r ea061975c883 -r cefdc6623322 ringtools/fc-e1gen.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ringtools/fc-e1gen.c Tue Oct 25 06:49:27 2016 +0000 @@ -0,0 +1,296 @@ +/* + * This program is an experimental compiler for TI's Melody E1 format + * based on the description given in the L1M_AS001_1.pdf document + * found in the Peek/FGW drop. + */ + +#include +#include +#include +#include +#include +#include + +#define MAX_FIELDS 16 + +char *infname, *outfname; +FILE *inf, *outf; +char linebuf[512], *fields[MAX_FIELDS+1]; +int lineno, nfields; + +int start_time, osc_mask; +u_short osc_words[8][4]; + +get_input_line() +{ + char *cp; + int n; + + if (!fgets(linebuf, sizeof linebuf, inf)) { + fprintf(stderr, "%s: unexpected EOF\n", infname); + exit(1); + } + cp = index(linebuf, '\n'); + if (!cp) { + fprintf(stderr, "%s line %d: too long or missing newline\n", + infname, lineno); + exit(1); + } + *cp = '\0'; + /* parse it into fields */ + cp = linebuf; + n = 0; + for (;;) { + while (isspace(*cp)) + cp++; + if (*cp == '\0' || *cp == '#') + break; + if (n >= MAX_FIELDS) { + fprintf(stderr, "%s line %d: too many fields\n", + infname, lineno); + exit(1); + } + fields[n++] = cp; + while (*cp && !isspace(*cp)) + cp++; + if (*cp) + *cp++ = '\0'; + } + fields[n] = 0; + nfields = n; +} + +input_number(str, min, max) + char *str; +{ + char *endp; + long val; + + val = strtol(str, &endp, 10); + if (*endp) { + fprintf(stderr, + "%s line %d: \"%s\" is not a valid decimal number\n", + infname, lineno, str); + exit(1); + } + if (val < min || val > max) { + fprintf(stderr, "%s line %d: number %ld is out of range\n", + infname, lineno, val); + exit(1); + } + return val; +} + +handle_time_line() +{ + if (nfields != 2) { + fprintf(stderr, "%s line %d: time header takes 1 argument\n", + infname, lineno); + exit(1); + } + start_time = input_number(fields[1], 1, 255); +} + +check_req_field(n) +{ + if (n >= nfields) { + fprintf(stderr, "%s line %d: too few fields\n", + infname, lineno); + exit(1); + } +} + +process_osc_line() +{ + int p = 1; + int oscn, osc_bit; + u_short word0, word1, word2, word3; + int amp, freq, length; + int tremT0, tremFreq; + int sustain, t1, t2, t3, t5; + + check_req_field(p); + oscn = input_number(fields[p], 0, 7); + p++; + osc_bit = 1 << oscn; + if (osc_mask & osc_bit) { + fprintf(stderr, "%s line %d: osc %d defined more than once\n", + infname, lineno, oscn); + exit(1); + } + osc_mask |= osc_bit; + + /* basic part */ + check_req_field(p); + if (!strcmp(fields[p], "df")) { + p++; + check_req_field(p); + freq = input_number(fields[p], -8192, 8191) & 0x3FFF; + p++; + check_req_field(p); + amp = input_number(fields[p], 0, 1023); + p++; + word0 = freq << 2 | 2; + word1 = amp << 6; + } else { + word0 = 0; + if (!strcmp(fields[p], "sq1")) { + p++; + word0 |= 4; + check_req_field(p); + } + if (!strcmp(fields[p], "sq2")) { + p++; + word0 |= 8; + check_req_field(p); + } + amp = input_number(fields[p], 0, 63); + p++; + check_req_field(p); + freq = input_number(fields[p], 0, 63); + p++; + word0 |= (freq << 10) | (amp << 4); + check_req_field(p); + length = input_number(fields[p], 0, 1023); + p++; + word1 = length << 6; + } + + /* optional 3rd word */ + if (p < nfields && !strcmp(fields[p], "trem")) { + p++; + word1 |= 0x10; + check_req_field(p); + tremT0 = input_number(fields[p], 0, 7); + p++; + check_req_field(p); + tremFreq = input_number(fields[p], -16, 15) & 31; + p++; + word2 = (tremFreq << 11) | (tremT0 << 8); + } + + /* optional 4th word */ + if (p < nfields && !strcmp(fields[p], "env")) { + p++; + word1 |= 0x20; + check_req_field(p); + sustain = input_number(fields[p], 0, 15); + p++; + check_req_field(p); + t1 = input_number(fields[p], 0, 7); + p++; + check_req_field(p); + t2 = input_number(fields[p], 0, 7); + p++; + check_req_field(p); + t3 = input_number(fields[p], 0, 7); + p++; + check_req_field(p); + t5 = input_number(fields[p], 0, 7); + p++; + word3 = (t1 << 13) | (t2 << 10) | (t3 << 7) | (t5 << 4) | + sustain; + } + + if (p != nfields) { + fprintf(stderr, "%s line %d: unexpected extra fields\n", + infname, lineno); + } + osc_words[oscn][0] = word0; + osc_words[oscn][1] = word1; + osc_words[oscn][2] = word2; + osc_words[oscn][3] = word3; +} + +read_osc_lines() +{ + osc_mask = 0; + for (;;) { + get_input_line(); + if (!nfields) + break; + if (!strcmp(fields[0], "osc")) { + process_osc_line(); + continue; + } + fprintf(stderr, "%s line %d: osc line expected\n", + infname, lineno); + exit(1); + } + if (!osc_mask) { + fprintf(stderr, "%s line %d: no oscillators defined\n", + infname, lineno); + exit(1); + } +} + +emit_16bit_word(word) + u_short word; +{ + putc(word & 0xFF, outf); + putc(word >> 8, outf); +} + +emit_record() +{ + int oscn, osc_bit; + + putc(start_time, outf); + putc(osc_mask, outf); + for (oscn = 0; oscn < 8; oscn++) { + osc_bit = 1 << oscn; + if (!(osc_mask & osc_bit)) + continue; + emit_16bit_word(osc_words[oscn][0]); + emit_16bit_word(osc_words[oscn][1]); + if (osc_words[oscn][1] & 0x10) + emit_16bit_word(osc_words[oscn][2]); + if (osc_words[oscn][1] & 0x20) + emit_16bit_word(osc_words[oscn][3]); + } +} + +main(argc, argv) + char **argv; +{ + if (argc != 3) { + fprintf(stderr, "usage: %s src-file e1-bin-file\n", argv[0]); + exit(1); + } + if (strcmp(argv[1], "-")) { + infname = argv[1]; + inf = fopen(infname, "r"); + if (!inf) { + perror(infname); + exit(1); + } + } else { + infname = "stdin"; + inf = stdin; + } + outfname = argv[2]; + outf = fopen(outfname, "w"); + if (!outf) { + perror(outfname); + exit(1); + } + + /* main loop */ + for (;;) { + do + get_input_line(); + while (!nfields); + if (!strcmp(fields[0], "time")) { + handle_time_line(); + read_osc_lines(); + emit_record(); + } else if (!strcmp(fields[0], "end")) { + emit_16bit_word(0); + exit(0); + } else { + fprintf(stderr, "%s line %d: expected time or end\n", + infname, lineno); + exit(1); + } + } +}