1 /*
2  * t6721.c - Toshiba 6721a Emulation
3  *
4  * Written by
5  *  groepaz <groepaz@gmx.net>
6  *
7  * This file is part of VICE, the Versatile Commodore Emulator.
8  * See README for copyright notice.
9  *
10  *  This program is free software; you can redistribute it and/or modify
11  *  it under the terms of the GNU General Public License as published by
12  *  the Free Software Foundation; either version 2 of the License, or
13  *  (at your option) any later version.
14  *
15  *  This program is distributed in the hope that it will be useful,
16  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
17  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  *  GNU General Public License for more details.
19  *
20  *  You should have received a copy of the GNU General Public License
21  *  along with this program; if not, write to the Free Software
22  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
23  *  02111-1307  USA.
24  *
25  */
26 
27 #include "vice.h"
28 
29 #include <stdio.h>
30 #include <stdlib.h>
31 #include <math.h>
32 #include <string.h>
33 
34 #include "lib.h"
35 #include "maincpu.h"
36 #include "monitor.h"
37 #include "snapshot.h"
38 #include "t6721.h"
39 
40 /*
41 
42     toshiba 6721a (voice output)
43 
44     based on code from alankila (parcor.py) and nojoopa (mvtool)
45 
46     - 8 kHz 9bit output (output is rendered in 16 bit)
47     - generates output for 20ms (or 10ms) out of 6 byte voice data!
48     - uses PARCOR voice synthesizing and analyzing method (Nippon Telegraph and Telephon Public Corporation)
49 
50 */
51 
52 #ifndef M_PI
53 #define M_PI 3.14159265358979323846
54 #endif
55 
56 /* #define T6721DEBUG */
57 
58 #define WRITEWAVFILE 0 /* write "test.wav" containing all generated output */
59 
60 #ifdef T6721DEBUG
61 #define DBG(x) DBG_STATUS(); printf x;
62 #define DBGADD(x) printf x
63 #define DBG_STATUS() \
64     printf("t6721: @:%04x apd: %d busy: %d eos: %d playing: %d ", reg_pc, t6721->apd, t6721->busy, t6721->eos, t6721->playing);
65 #else
66 #define DBG(x)
67 #define DBGADD(x)
68 #define DBG_STATUS()
69 #endif
70 
71 #define PARCOR_OUTPUT_HZ       (8000)
72 
73 #define PARCOR_BUFFER_LEN (0x400)
74 int16_t ringbuffer[PARCOR_BUFFER_LEN]; /* FIXME */
75 int ringbuffer_rptr = 0;
76 int ringbuffer_wptr = 0;
77 int phrase_sample_len = 0;
78 
79 #define RBSTATE_STOP 0
80 #define RBSTATE_PLAY 1
81 #define RBSTATE_DELAY_SAMPLES (PARCOR_OUTPUT_HZ / 200) /* 5 ms */
82 static int ringbuffer_state = 0;
83 
84 float upsmpcnt = 0;
85 float upsmp = 0;
86 
87 struct param_s {
88     uint8_t energy;
89     uint8_t pitch;
90     int16_t k[10];
91 };
92 typedef struct param_s param_t;
93 
94 static param_t p_from = { 0, 0x21, { 0 } };
95 static param_t p_to = { 0, 0x21, { 0 } };
96 static double p_z[11] = { 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 };
97 
98 /* FIXME: MOVE  parcor parameters: energy + pitch + k1..10 */
99 static uint16_t parcor_param[1 + 1 + 10];
100 
101 /*
102     words that use 48bits/frame:
103 
104     magicvoice rom:
105 
106      68 "ing"
107      78 "what"
108      80 "who"
109      105 "is"
110      129 "as"
111      130 "but"
112      148 "thuh"
113      151 "with"
114      158 "bad"
115      164 "because"
116      193 "orange"
117      209 "may"
118      225 "program"
119 
120      v364 and WoW do NOT use 48bit frames !
121 */
122 
123 /* parameter lengths (bits) */
124 /* [1] k0..k9 from speak and spell
125  * (48bit frames) 5, 5, 4, 4,  4, 4, 4, 3, 3, 3 (18bits + 21bits = 39bits, 9 free)
126  * [2] k0..k9 from "Handbook of Data Compression By David Salomon, Giovanni Motta, David (CON) Bryant
127  * (48bit frames) 3, 4, 4, 4,  4, 3, 3, 3, 3, 3 (15bits + 19bits = 34bits, 14 free)
128  */
129 static const int parcor_param_len[2][1 + 1 + 10] = {
130     /* FIXME: 48 bits/frame  (this is vaguely guessed and totally wrong)
131         12 ? bits for energy+pitch
132         21 ? bits for k1..4
133         15 ? bits for k5..10
134      */
135     {6, 6,   6,  5,  5,  5,   3, 3, 3, 2, 2, 2},
136 #if 0
137     { 4, 5,   5,  5,  4, 4,   4, 4, 4, 3, 3, 3 }, /* [1] vaguely recognizeable */
138     { 7, 7,   3,  4,  4, 4,   4, 3, 3, 3, 3, 3 }, /* [2] not working */
139 #endif
140     /* 96 bits/frame (these seem correct)
141         14 bits for energy+pitch
142         38 bits for k1..4
143         44 bits for k5..10
144      */
145     { 7, 7,  10, 10, 10, 8,   8, 8, 7, 7, 7, 7 }
146 };
147 static uint16_t chip_buf = 0;
148 static int chip_bit_i = 0;
149 static int param_i = 0;
150 
151 #define PARMVALUE(ctx, x) (parcor_param[x] >> (16 - parcor_param_len[(ctx)->cond2_framebits][x]))
152 
153 /* ------------------------------------------------------------------------- */
154 
155 static void set_dtrd(t6721_state *t6721, int dtrd);
156 static void set_apd(t6721_state *t6721, int apd);
157 static void set_eos(t6721_state *t6721, int eos);
158 static void set_playing(t6721_state *t6721, int playing);
159 
160 /*****************************************************************************
161     WAV Writer (for debugging)
162 *****************************************************************************/
163 
164 #if WRITEWAVFILE
165 static FILE *wav_fp = NULL;
166 static size_t wavsize = 0;
167 
168 static const uint8_t wav_header[] = {
169     'R', 'I', 'F', 'F',
170     0, 0, 0, 0, /* filesize - 8 */
171     'W', 'A', 'V', 'E',
172     'f', 'm', 't', ' ',
173     16, 0, 0, 0,
174     1, 0,
175     1, 0,
176     0x40, 0x1f, 0, 0, /* 8000 Hz */
177     0x80, 0x3e, 0, 0, /* 8000 Hz * 2B/sample */
178     2, 0,
179     16, 0,
180     'd', 'a', 't', 'a',
181     0, 0, 0, 0  /* bytes to follow (== wavsize)*/
182 };
183 
write_header(void)184 static int write_header(void)
185 {
186     if (fwrite(wav_header, 1, sizeof(wav_header), wav_fp) < sizeof(wav_header)) {
187         fclose(wav_fp);
188         wav_fp = NULL;
189         return 1;
190     }
191     return 0;
192 }
193 
fix_header(void)194 static int fix_header(void)
195 {
196     size_t temp;
197     uint8_t b[4] = { 0, 0, 0, 0 };
198 
199     fseek(wav_fp, 4, SEEK_SET);
200 
201     temp = wavsize + sizeof(wav_header) - 8;
202 
203     b[0] = (temp >> 0) & 0xff;
204     b[1] = (temp >> 8) & 0xff;
205     b[2] = (temp >> 16) & 0xff;
206     b[3] = (temp >> 24) & 0xff;
207 
208     if (fwrite(b, 1, 4, wav_fp) < 4) {
209         fclose(wav_fp);
210         wav_fp = NULL;
211         return 1;
212     }
213 
214     fseek(wav_fp, 40, SEEK_SET);
215 
216     temp = wavsize;
217 
218     b[0] = (temp >> 0) & 0xff;
219     b[1] = (temp >> 8) & 0xff;
220     b[2] = (temp >> 16) & 0xff;
221     b[3] = (temp >> 24) & 0xff;
222 
223     if (fwrite(b, 1, 4, wav_fp) < 4) {
224         fclose(wav_fp);
225         wav_fp = NULL;
226         return 1;
227     }
228 
229     return 0;
230 }
231 
wav_close_file(void)232 static void wav_close_file(void)
233 {
234     if (wav_fp) {
235         fix_header();
236         fclose(wav_fp);
237         wav_fp = NULL;
238     }
239 }
240 
wav_create_file(const char * filename)241 static int wav_create_file(const char *filename)
242 {
243     if ((wav_fp = fopen(filename, "wb")) == NULL) {
244         perror(filename);
245         return 1;
246     }
247 
248     archdep_vice_atexit(wav_close_file);
249     return write_header();
250 }
251 
wav_write_sample(int16_t data)252 static int wav_write_sample(int16_t data)
253 {
254     uint8_t d;
255 
256     if (wav_fp == NULL) {
257         wav_create_file("test.wav");
258     }
259 
260     d = (uint8_t)(data & 0xff);
261 
262     if (fwrite(&d, 1, 1, wav_fp) < 1) {
263         return 1;
264     }
265 
266     wavsize++;
267 
268     d = (uint8_t)((data >> 8) & 0xff);
269 
270     if (fwrite(&d, 1, 1, wav_fp) < 1) {
271         return 1;
272     }
273 
274     wavsize++;
275 
276     return 0;
277 }
278 #endif
279 
280 /*****************************************************************************
281     Output Ringbuffer
282 *****************************************************************************/
283 
ringbuffer_reset(void)284 static void ringbuffer_reset(void)
285 {
286     ringbuffer_rptr = 0;
287     ringbuffer_wptr = 0;
288     ringbuffer_state = RBSTATE_STOP;
289     phrase_sample_len = 0;
290 }
291 
292 /*
293     write one 8000khz sample to the output ringbuffer
294     returns 1 on error, 0 on success
295 */
parcor_output_sample(t6721_state * t6721,int16_t value)296 static int parcor_output_sample(t6721_state *t6721, int16_t value)
297 {
298     int next_wptr;
299 
300     ringbuffer[ringbuffer_wptr] = value;
301 #if WRITEWAVFILE
302     wav_write_sample(value);
303 #endif
304     next_wptr = ringbuffer_wptr + 1;
305     if (next_wptr == PARCOR_BUFFER_LEN) {
306         next_wptr = 0;
307     }
308     if (next_wptr != ringbuffer_rptr) {
309         ringbuffer_wptr = next_wptr;
310         phrase_sample_len++;
311         return 0;
312     }
313     /* DBG(("ringbuffer overflow\n")); */
314     return 1;
315 }
316 
317 /*
318     render one output sample
319 */
output_update_sample(t6721_state * t6721)320 static int16_t output_update_sample(t6721_state *t6721)
321 {
322     static float from, to;
323     int next_rptr;
324     int16_t this;
325 
326     this = (int16_t)((from * (1.0f - upsmpcnt)) + (to * upsmpcnt));
327 
328     upsmpcnt += (1.0f / upsmp);
329     if (upsmpcnt >= 1.0f) {
330         upsmpcnt -= 1.0f;
331         from = to;
332         if (ringbuffer_state == RBSTATE_STOP) {
333             if (phrase_sample_len > RBSTATE_DELAY_SAMPLES) {
334                 ringbuffer_state = RBSTATE_PLAY;
335             }
336         } else {
337             if (phrase_sample_len > 0) {
338                 next_rptr = ringbuffer_rptr + 1;
339                 if (next_rptr == PARCOR_BUFFER_LEN) {
340                     next_rptr = 0;
341                 }
342                 if (next_rptr != ringbuffer_wptr) {
343                     ringbuffer_rptr = next_rptr;
344                     phrase_sample_len--;
345                 }
346             } else {
347                 ringbuffer_state = RBSTATE_STOP;
348             }
349         }
350         to = (float) ringbuffer[ringbuffer_rptr];
351     }
352 
353     return this;
354 }
355 
356 static int framestretch[0x10] =
357 {
358     100, /* 0 : 1,0  */
359      70, /* 1 : 0,7  (1.4% faster) */
360      80, /* 2 : 0,8  */
361      90, /* 3 : 0,9  */
362     100, /* 4 : 1,0  (default) */
363     110, /* 5 : 1,1  */
364     120, /* 6 : 1,2  */
365     130, /* 7 : 1,3  */
366     140, /* 8 : 1,4  */
367     150, /* 9 : 1,5  */
368     155, /* a : 1,55 (0.65% slower) */
369     100, /* b : 1,0  */
370     100, /* c : 1,0  */
371     100, /* d : 1,0  */
372     100, /* e : 1,0  */
373     100  /* f : 1,0  */
374 };
375 
get_frame_samples(t6721_state * t6721)376 static int get_frame_samples(t6721_state *t6721)
377 {
378     return ((t6721->cycles_per_sec * t6721->cond2_framelen * framestretch[t6721->speed]) / (100 * 100));
379 }
380 
get_subframe_samples(t6721_state * t6721)381 static int get_subframe_samples(t6721_state *t6721)
382 {
383     return ((PARCOR_OUTPUT_HZ * t6721->cond2_framelen * framestretch[t6721->speed]) / (100 * 100 * 8));
384 }
385 
386 /*****************************************************************************
387     PARCOR Synthesis
388 *****************************************************************************/
389 
filter(int i,double ef,double k)390 static double filter(int i, double ef, double k)
391 {
392     double ef_prev = ef + k * p_z[1 + i - 1];
393     p_z[1 + i] = p_z[1 + i - 1] - k * ef_prev;
394     return ef_prev;
395 }
396 
397 /* -------------------------------------------------------------------------
398     render one PARCOR subframe
399     returns 1 on error, 0 on success
400    ------------------------------------------------------------------------- */
render_subframe(t6721_state * t6721,int sub_i,int voiced)401 static int render_subframe(t6721_state *t6721, int sub_i, int voiced)
402 {
403     int i, j;
404     static double phase = 0.0;
405 
406     double energy = ((p_from.energy * (8 - sub_i)) + (p_to.energy * sub_i)) / (8.0 * 127.0);
407     uint8_t pitch;
408     double phase_inc;
409 
410     double k[10];
411 
412     double sample, data;
413 
414     int16_t output;
415 
416     if (voiced) {
417         pitch = ((p_from.pitch * (8 - sub_i)) + (p_to.pitch * sub_i)) / 8;
418         phase_inc = 1.0 / (double)(pitch);
419     } else {
420         pitch = 0;
421         phase_inc = 0.0;
422     }
423 
424 /* DBG(("voiced %i, energy %f, pitch %02x, phase_inc %f, k: ", voiced, energy, pitch, phase_inc)); */
425 
426     for (i = 0; i < 10; ++i) {
427         k[i] = ((p_from.k[i] * (8 - sub_i)) + (p_to.k[i] * sub_i)) / (8.0 * 32768.0);
428 /* DBGADD(("%f, ", k[i])); */
429     }
430 /* DBGADD(("\n")); */
431 
432     for (i = 0; i < get_subframe_samples(t6721); ++i) {
433         /* sample */
434         if (voiced) {
435             phase += phase_inc;
436             if (phase >= 1.0) {
437                 phase -= 1.0;
438             }
439             sample = cos(M_PI * phase * phase);
440         } else {
441             /* FIXME: implement the actual pseudo random number generator used
442                       on the chip */
443             sample = lib_float_rand(-1.0, 1.0);
444         }
445         sample *= energy;
446 
447         /* filter */
448         data = sample;
449         for (j = t6721->cond2_stages - 1; j >= 0; --j) {
450             data = filter(j, data, k[j]);
451         }
452 
453         /* scale to 16bit */
454         output = (int16_t)(data * (8192.0f + 2048.0f));
455 
456         if (parcor_output_sample(t6721, output)) {
457             return 1;
458         }
459     }
460 
461     return 0;
462 }
463 
render_silence(t6721_state * t6721)464 static int render_silence(t6721_state *t6721)
465 {
466     int i;
467 
468     for (i = 0; i < (get_subframe_samples(t6721) * 8); ++i) {
469         if (parcor_output_sample(t6721, 0)) {
470             return 1;
471         }
472     }
473 
474     return 0;
475 }
476 
477 /* -------------------------------------------------------------------------
478     render one PARCOR frame
479     returns 1 on error, 0 on success
480    ------------------------------------------------------------------------- */
parcor_render_frame(t6721_state * t6721,uint16_t * new_param)481 static int parcor_render_frame(t6721_state *t6721, uint16_t *new_param)
482 {
483     int i, voiced, silent;
484     uint8_t new_pitch;
485 
486     new_pitch = (uint8_t)PARMVALUE(t6721, 1);
487     voiced = (new_pitch > 0);
488 
489     memcpy(&p_from, &p_to, sizeof(p_from));
490 
491     p_to.energy = (uint8_t)PARMVALUE(t6721, 0);
492     silent = ((new_pitch == 0x7e) && (p_to.energy == 1));
493 
494     if (!voiced && !silent) {
495         new_pitch = p_from.pitch;
496     }
497 
498     p_to.pitch = new_pitch;
499 
500     if (!silent) {
501         for (i = 0; i < (voiced ? (12 - 2) : (6 - 2)); ++i) {
502             p_to.k[i] = (int16_t)(new_param[i + 2]);
503         }
504 
505         for (i = 0; i < 8; ++i) {
506             if (render_subframe(t6721, i, voiced)) {
507                 return 1;
508             }
509         }
510     } else {
511         if (render_silence(t6721)) {
512             return 1;
513         }
514     }
515 
516     return 0;
517 }
518 
519 /*****************************************************************************
520     handle data input from the DI line
521 *****************************************************************************/
522 
523 static int parcor_framelen = 12;
524 static int parcor_frametype;
525 static int phrase_samples = 0;
526 
527 static int zero_frames = 0;
528 
529 /* read nibbles from FIFO and re-arrange into a parcor frame */
reset_di_fifo(void)530 static void reset_di_fifo(void)
531 {
532     chip_buf = 0;
533     chip_bit_i = 0;
534     param_i = 0;
535 }
536 
537 /*
538     read data (one bit) from the DI line
539 
540     returns:
541     -1 no data available
542      0 normal exit
543      1 got PARCOR frame
544 */
read_di_fifo(t6721_state * t6721)545 static int read_di_fifo(t6721_state *t6721)
546 {
547     unsigned int bit;
548 /*
549     if (t6721->dtrd) {
550         set_dtrd(t6721, 0);
551         return -1;
552     }
553 
554     set_dtrd(t6721, 1);
555 */
556     if (t6721->read_data(t6721, &bit) < 1) {
557         /* DBGADD(("<*>")); */
558         return -1;
559     }
560 
561     if ((param_i == 1) && (chip_bit_i == 0)) {
562         if (PARMVALUE(t6721, 0) == 0) {
563             if (bit) {
564                 reset_di_fifo();
565                 set_eos(t6721, 1);
566                 t6721->busy = 0;
567                 set_playing(t6721, 0);
568                 parcor_framelen = 1;
569                 parcor_frametype = T6721_FRAMETYPE_EOS;
570                 zero_frames = 0;
571                 return 1;
572             } else {
573                 reset_di_fifo();
574                 zero_frames++;
575                 parcor_framelen = 1;
576                 parcor_frametype = T6721_FRAMETYPE_ZERO;
577 
578                 if (zero_frames > 1) {
579                     set_eos(t6721, 1);
580                     t6721->busy = 0;
581                     set_playing(t6721, 0);
582                     zero_frames = 0;
583                 }
584                 return 1;
585             }
586         }
587         zero_frames = 0;
588     }
589 
590     chip_buf >>= 1;
591     chip_buf |= bit ? 0x8000 : 0;
592     chip_bit_i++;
593 
594 /* DBGADD(("(%x)", bit)); */
595 
596     if (chip_bit_i < parcor_param_len[t6721->cond2_framebits][param_i]) {
597         return 0;
598     }
599 
600 /* DBGADD(("<%03x>", chip_buf)); */
601 
602     /* next parm is ready */
603     parcor_param[param_i] = chip_buf;
604     chip_bit_i = 0;
605     chip_buf = 0;
606 
607     switch (param_i) {
608         case 0:
609             parcor_framelen = 12;
610             break;
611         case 1:
612             if (PARMVALUE(t6721, 1) == 0) {
613                 parcor_framelen = 6;
614                 parcor_frametype = T6721_FRAMETYPE_UNVOICED;
615             } else {
616                 if ((PARMVALUE(t6721, 0) == 1) && (PARMVALUE(t6721, 1) == 0x7e)) {
617                     parcor_frametype = T6721_FRAMETYPE_SILENT;
618                 } else {
619                     parcor_frametype = T6721_FRAMETYPE_VOICED;
620                 }
621             }
622             break;
623     }
624 
625     param_i++;
626 
627     if (param_i == parcor_framelen) {
628         /* complete frame was read */
629         reset_di_fifo();
630         return 1;
631     }
632 
633     return 0;
634 }
635 
636 /*****************************************************************************
637 *****************************************************************************/
638 
set_playing(t6721_state * t6721,int playing)639 static void set_playing(t6721_state *t6721, int playing)
640 {
641     if (t6721->playing != playing) {
642         if (playing) {
643             DBG(("start playing\n"));
644             t6721->playing_delay = 0x10000; /* FIXME: find out real value */
645         } else {
646             DBG(("stop playing\n"));
647             ringbuffer_reset();
648             reset_di_fifo(); /* ? */
649         }
650     }
651     t6721->playing = playing;
652 }
653 
set_dtrd(t6721_state * t6721,int dtrd)654 static void set_dtrd(t6721_state *t6721, int dtrd)
655 {
656     t6721->dtrd = dtrd;
657     if (t6721->set_dtrd) {
658         t6721->set_dtrd(t6721);
659     }
660 }
661 
set_apd(t6721_state * t6721,int apd)662 static void set_apd(t6721_state *t6721, int apd)
663 {
664     t6721->apd = apd;
665     if (t6721->set_apd) {
666         t6721->set_apd(t6721);
667     }
668 }
669 
set_eos(t6721_state * t6721,int eos)670 static void set_eos(t6721_state *t6721, int eos)
671 {
672     if (t6721->eos != eos) {
673         t6721->eos = eos;
674         if (eos) {
675             t6721->status |= T6721_STATUS_END_OF_SPEECH;
676         } else {
677             t6721->status &= ~T6721_STATUS_END_OF_SPEECH;
678         }
679         if (t6721->set_eos) {
680             t6721->set_eos(t6721);
681         }
682     }
683     if (eos) {
684         /* FIXME: confirm: is this correct ? */
685         /* 10ms or 20ms depending on current framelen */
686         t6721->eos_samples = get_frame_samples(t6721);
687     }
688 }
689 
690 /*****************************************************************************
691     "run" chip and update output_samples
692 
693     FIXME: this perhaps needs some other (per cycle) hook (?)
694 *****************************************************************************/
695 
696 /* run chip for exactly one CPU/System Cycle */
t6721_update_tick(t6721_state * t6721)697 void t6721_update_tick(t6721_state *t6721)
698 {
699     int res;
700 #ifdef T6721DEBUG
701     int i;
702 #endif
703 
704     /* once asserted, the EOS signal is generated for 20ms */
705     if (t6721->eos_samples == 0) {
706         set_eos(t6721, 0);
707     } else {
708         t6721->eos_samples--;
709     }
710 
711     if (t6721->playing_delay) {
712         t6721->playing_delay--;
713         return;
714     }
715 
716     if (phrase_samples) {
717         phrase_samples--;
718         return;
719     }
720 
721     if ((t6721->playing == 1) && (t6721->apd == 0) && (t6721->eos == 0)) {
722         set_dtrd(t6721, 1);
723         res = read_di_fifo(t6721);
724         if (res == -1) {
725             /* not enough data in FIFO */
726         } else if (res == 1) {
727             /* got PARCOR frame */
728             if ((parcor_frametype == T6721_FRAMETYPE_SILENT) ||
729                 (parcor_frametype == T6721_FRAMETYPE_VOICED) ||
730                 (parcor_frametype == T6721_FRAMETYPE_UNVOICED)) {
731                 parcor_render_frame(t6721, parcor_param);
732             }
733             /* FIXME: confirm: is this correct ? */
734             /* 10ms or 20ms depending on current framelen */
735             phrase_samples = get_frame_samples(t6721) - (((t6721->cond2_framebits ? 96 : 48) * 10 * framestretch[t6721->speed]) / 100);
736             set_dtrd(t6721, 0);
737 #ifdef T6721DEBUG
738             DBG(("got Frame: "));
739             switch (parcor_frametype) {
740                 case T6721_FRAMETYPE_VOICED:
741                     DBGADD(("[voiced]   "));
742                     break;
743                 case T6721_FRAMETYPE_UNVOICED:
744                     DBGADD(("[unvoiced] "));
745                     break;
746                 case T6721_FRAMETYPE_EOS:
747                     DBGADD(("[eos]      "));
748                     break;
749                 case T6721_FRAMETYPE_ZERO:
750                     DBGADD(("[zero]     "));
751                     break;
752                 case T6721_FRAMETYPE_SILENT:
753                     DBGADD(("[silent]   "));
754                     break;
755             }
756             for (i = 0; i < parcor_framelen; i++) {
757                 DBGADD(("%03x ", parcor_param[i] >> (16 - parcor_param_len[t6721->cond2_framebits][i])));
758             }
759             DBGADD(("\n"));
760 #endif
761         }
762     }
763 }
764 
765 /* run chip for N CPU/System Cycles */
t6721_update_ticks(t6721_state * t6721,int ticks)766 void t6721_update_ticks(t6721_state *t6721, int ticks)
767 {
768     while (ticks) {
769         t6721_update_tick(t6721);
770         t6721->cycles_done++;
771         ticks--;
772     }
773 }
774 
775 float up2smp = 0;
776 
777 /* render num samples into output buffer, run remaining cycles (if any) */
t6721_update_output(t6721_state * t6721,int16_t * buf,int num)778 void t6721_update_output(t6721_state *t6721, int16_t *buf, int num)
779 {
780     int i;
781     int cycles;
782 
783     cycles = (int)((num * up2smp) - t6721->cycles_done);
784     if (cycles > 0) {
785         /* run chip for remaining cycles */
786         t6721_update_ticks(t6721, cycles);
787         t6721->cycles_done = 0;
788     } else {
789         /* carry over remaining cycles to next sound frame */
790         t6721->cycles_done = 0 - cycles;
791     }
792 
793     /* render output samples */
794     for (i = 0; i < num; i++) {
795         *buf++ = output_update_sample(t6721);
796     }
797 }
798 
799 /*****************************************************************************
800     Chip Command Handling
801 *****************************************************************************/
802 
803 /*
804     when the WR pin goes high, d0..d3 from data are read by ("written to") the chip
805 */
t6721_store(t6721_state * t6721,uint8_t data)806 void t6721_store(t6721_state *t6721, uint8_t data)
807 {
808 /* DBG(("write %2x\n", data)); */
809     /* an actual store is performed on Lo->HI transition of WR */
810     if ((t6721->wr == 1) && (t6721->wr_last == 0)) {
811         if (t6721->cmd_nibbles) {
812             switch (t6721->cmd_current) {
813                 case 0x03: /* ADDRESS LOAD 1/6 */
814                     DBG(("arg %2x (ADDRESS LOAD %d/6)\n", data, 6 - t6721->cmd_nibbles));
815                     break;
816                 case 0x05: /* SPEED LOAD 1/2 */
817                     DBG(("arg %2x (SPEED LOAD %d/2)\n", data, 3 - t6721->cmd_nibbles));
818                     t6721->speed = data;
819                     break;
820                 case 0x06: /* CONDITION 1 1/2 */
821                     DBG(("arg %2x (CONDITION 1 %d/2) ", data, 3 - t6721->cmd_nibbles));
822                     t6721->condition1 = data;
823                     if (t6721->condition1 & T6721_COND1_LOSS) {
824                         t6721->cond1_loss = T6721_LOSS_ENABLED;
825                     } else {
826                         t6721->cond1_loss = T6721_LOSS_DISABLED;
827                     }
828                     if (t6721->condition1 & T6721_COND1_SHAPE) {
829                         t6721->cond1_shape = T6721_SHAPE_TRIANGLE;
830                     } else {
831                         t6721->cond1_shape = T6721_SHAPE_PITCH;
832                     }
833                     DBGADD(("loss effect calculation: %d Sound Source Shape: %s\n", t6721->cond1_loss, t6721->cond1_shape ? "Triangle" : "Pitch" ));
834                     break;
835                 case 0x07: /* CONDITION 2 1/2 */
836                     DBG(("arg %2x (CONDITION 2 %d/2) ", data, 3 - t6721->cmd_nibbles));
837                     t6721->condition2 = data;
838                     if (t6721->condition2 & T6721_COND2_STAGES) {
839                         t6721->cond2_stages = T6721_STAGES_8;
840                     } else {
841                         t6721->cond2_stages = T6721_STAGES_10;
842                     }
843                     if (t6721->condition2 & T6721_COND2_REPEAT) {
844                         t6721->cond2_repeat = T6721_REPEAT_DISABLED;
845                     } else {
846                         t6721->cond2_repeat = T6721_REPEAT_ENABLED;
847                     }
848                     if (t6721->condition2 & T6721_COND2_LENGTH) {
849                         t6721->cond2_framelen = T6721_FRAME_10MS;
850                     } else {
851                         t6721->cond2_framelen = T6721_FRAME_20MS;
852                     }
853                     if (t6721->condition2 & T6721_COND2_BPFRAME) {
854                         t6721->cond2_framebits = T6721_FRAME_96BIT;
855                     } else {
856                         t6721->cond2_framebits = T6721_FRAME_48BIT;
857                     }
858                     DBGADD(("stages: %d repeat: %d len: %d0ms bits: %d\n", t6721->cond2_stages, t6721->cond2_repeat, t6721->cond2_framelen, t6721->cond2_framebits ? 96 : 48 ));
859                     break;
860             }
861 
862             t6721->cmd_nibbles--;
863         } else {
864             t6721->cmd_current = data;
865 
866             switch (data) {
867                 case 0x00: /* NOP nop */
868                     DBG(("cmd %2x (nop)\n", data));
869                     t6721->readmode = T6721_READMODE_STATUS;
870                     break;
871                 case 0x01: /* STRT start */
872                     DBG(("cmd %2x (start)\n", data));
873                     set_playing(t6721, 1);
874                     set_eos(t6721, 0);
875                     t6721->status &= ~T6721_STATUS_ROM_DATA_ERROR; /* release rom data error status */
876                     t6721->readmode = T6721_READMODE_STATUS;
877                     break;
878                 case 0x02: /* STOP stop */
879                     DBG(("cmd %2x (stop)\n", data));
880                     set_playing(t6721, 0);
881                     t6721->readmode = T6721_READMODE_STATUS;
882                     break;
883                 case 0x03: /* ADDRESS LOAD 1/6 */
884                     DBG(("cmd %2x (ADDRESS LOAD 1/6)\n", data));
885                     t6721->cmd_nibbles = 5;
886                     t6721->readmode = T6721_READMODE_STATUS;
887                     break;
888                 case 0x04: /* AAGN AUDIO ASGIN */
889                     DBG(("cmd %2x (AUDIO ASGIN)\n", data));
890                     set_apd(t6721, 0); /* release audio power down signal */
891                     t6721->readmode = T6721_READMODE_STATUS;
892                     break;
893                 case 0x05: /* SPLD SPEED LOAD 1/2 */
894                     DBG(("cmd %2x (SPEED LOAD 1/2)\n", data));
895                     t6721->cmd_nibbles = 1;
896                     t6721->readmode = T6721_READMODE_STATUS;
897                     break;
898                 case 0x06: /* CNDT1 CONDITION 1 1/2 */
899                     DBG(("cmd %2x (CONDITION 1 1/2)\n", data));
900                     t6721->cmd_nibbles = 1;
901                     t6721->readmode = T6721_READMODE_STATUS;
902                     break;
903                 case 0x07: /* CNDT2 CONDITION 2 1/2 */
904                     DBG(("cmd %2x (CONDITION 2 1/2)\n", data));
905                     t6721->cmd_nibbles = 1;
906                     t6721->readmode = T6721_READMODE_STATUS;
907                     break;
908                 case 0x08: /* RRDM ROM READ MODE */
909                     DBG(("cmd %2x (ROM READ MODE)\n", data));
910                     t6721->readmode = T6721_READMODE_ROM;
911                     break;
912                 case 0x09: /* SPDN system power down */
913                     DBG(("cmd %2x (system power down)\n", data));
914                     set_playing(t6721, 0);
915                     t6721->readmode = T6721_READMODE_STATUS;
916                     break;
917                 case 0x0a: /* APDN AUDIO POWER DOWN */
918                     DBG(("cmd %2x (AUDIO POWER DOWN)\n", data));
919                     set_apd(t6721, 1); /* raise audio power down signal */
920                     t6721->readmode = T6721_READMODE_STATUS;
921                     break;
922                 case 0x0b: /* SAGN system assign */
923                     DBG(("cmd %2x (system assign)\n", data));
924                     set_playing(t6721, 0);
925                     t6721->status &= ~T6721_STATUS_SYSTEM_POWER_DOWN; /* release system power down status */
926                     t6721->readmode = T6721_READMODE_STATUS;
927                     break;
928                 /* c-f is "redundant" ? */
929                 case 0x0c:
930                 case 0x0d:
931                 case 0x0e:
932                 case 0x0f:
933                     DBG(("cmd %2x (redundant ?)\n", data));
934                     t6721->status |= T6721_STATUS_COMMAND_ERROR; /* raise command error status */
935                     break;
936             }
937         }
938     }
939 
940     t6721->wr_last = t6721->wr;
941 }
942 
t6721_read(t6721_state * t6721)943 uint8_t t6721_read(t6721_state *t6721)
944 {
945     int data;
946 
947     if (t6721->readmode == T6721_READMODE_STATUS) {
948         data = (t6721->status & 0x0f);
949     } else {
950         /* FIXME: read-through from speech ROM is missing */
951         data = 0;
952         DBG(("FIXME read-through from speech ROM\n"));
953     }
954 
955     return data;
956 }
957 
958 /*****************************************************************************/
959 
t6721_reset(t6721_state * t6721)960 void t6721_reset(t6721_state *t6721)
961 {
962     t6721->cmd_nibbles = 0;
963     t6721->cmd_current = 0;
964 
965     t6721->speed = 0; /* param for speed load cmd */
966     t6721->condition1 = 0;
967     t6721->condition2 = 0;
968 
969     t6721->busy = 0; /* BSY signal */
970     set_apd(t6721, 1);  /* APD signal */
971     set_eos(t6721, 0);  /* EOS signal */
972     set_dtrd(t6721, 0);  /* DTRD signal */
973     set_playing(t6721, 0);  /* stop playing */
974 
975     t6721->status = 0;
976     t6721->readmode = T6721_READMODE_STATUS;
977 }
978 
t6721_sound_machine_init(t6721_state * t6721,int speed,int cycles_per_sec)979 void t6721_sound_machine_init(t6721_state *t6721, int speed, int cycles_per_sec)
980 {
981     DBG(("sound machine init: speed %d cycles/sec: %d\n", speed, cycles_per_sec));
982     t6721->samples_per_sec = speed;
983     t6721->cycles_per_sec = cycles_per_sec;
984     /* ratio for converting ringbuffer -> output */
985     upsmp = (((float)speed) / ((float)PARCOR_OUTPUT_HZ));
986     /* ratio for converting samples in output buffer -> cpu/system cycles */
987     up2smp = (((float)cycles_per_sec) / ((float)speed));
988 }
989 
t6721_sound_machine_init_vbr(t6721_state * t6721,int speed,int cycles_per_sec,int factor)990 void t6721_sound_machine_init_vbr(t6721_state *t6721, int speed, int cycles_per_sec, int factor)
991 {
992     DBG(("sound machine init: speed %d cycles/sec: %d\n", speed, cycles_per_sec));
993     t6721->samples_per_sec = speed;
994     t6721->cycles_per_sec = (cycles_per_sec * 1000 / factor);
995     /* ratio for converting ringbuffer -> output */
996     upsmp = (((float)speed) / ((float)PARCOR_OUTPUT_HZ));
997     /* ratio for converting samples in output buffer -> cpu/system cycles */
998     up2smp = (((float)cycles_per_sec) / ((float)speed));
999 }
1000 
t6721_dump(t6721_state * t6721)1001 int t6721_dump(t6721_state *t6721)
1002 {
1003     mon_out("reference cycles per second: %d\n", t6721->cycles_per_sec);
1004     mon_out("output sample per second:    %d\n", t6721->samples_per_sec);
1005     mon_out("apd: %d busy: %d eos: %d playing: %d\n", t6721->apd, t6721->busy, t6721->eos, t6721->playing);
1006     return 0;
1007 }
1008 
1009 /* ---------------------------------------------------------------------*/
1010 /*    snapshot support functions                                             */
1011 
1012 #define CART_DUMP_VER_MAJOR   0
1013 #define CART_DUMP_VER_MINOR   0
1014 #define SNAP_MODULE_NAME  "T6721"
1015 
1016 /* FIXME: implement snapshot support */
t6721_snapshot_write_module(snapshot_t * s,t6721_state * t6721)1017 int t6721_snapshot_write_module(snapshot_t *s, t6721_state *t6721)
1018 {
1019     return -1;
1020 #if 0
1021     snapshot_module_t *m;
1022 
1023     m = snapshot_module_create(s, SNAP_MODULE_NAME,
1024                                CART_DUMP_VER_MAJOR, CART_DUMP_VER_MINOR);
1025     if (m == NULL) {
1026         return -1;
1027     }
1028 
1029     if (0) {
1030         snapshot_module_close(m);
1031         return -1;
1032     }
1033 
1034     snapshot_module_close(m);
1035     return 0;
1036 #endif
1037 }
1038 
t6721_snapshot_read_module(snapshot_t * s,t6721_state * t6721)1039 int t6721_snapshot_read_module(snapshot_t *s, t6721_state *t6721)
1040 {
1041     return -1;
1042 #if 0
1043     uint8_t vmajor, vminor;
1044     snapshot_module_t *m;
1045 
1046     m = snapshot_module_open(s, SNAP_MODULE_NAME, &vmajor, &vminor);
1047     if (m == NULL) {
1048         return -1;
1049     }
1050 
1051     if ((vmajor != CART_DUMP_VER_MAJOR) || (vminor != CART_DUMP_VER_MINOR)) {
1052         snapshot_module_close(m);
1053         return -1;
1054     }
1055 
1056     if (0) {
1057         snapshot_module_close(m);
1058         return -1;
1059     }
1060 
1061     snapshot_module_close(m);
1062     return 0;
1063 #endif
1064 }
1065