From d94e8b266445313038be2a86b3ae671dae30e529 Mon Sep 17 00:00:00 2001 From: Vas Crabb Date: Tue, 12 Jun 2018 16:07:05 +1000 Subject: Revert "tms5220: fix the READYQ callback to poll the fifo state with a timer loop instead of always asserting the /ready via callback even if there is no more room in the FIFO, to match hardware. Fix the speak vsm mode to assume that the ADDR/DATA pin floats high if no VSM is attached, so that the speech chip doesn't get permanently stuck speaking silence if a spurious SPEAK VSM command is sent to it. Fix some race conditions with the INTQ callback and status flags not being updated before the callback is called. General cleanup and bool-ification of boolean variables. [Lord Nightmare]" This reverts commit 62fc2e8f068a67b84b324b1c2e9b55791850247e. See coments on https://github.com/mamedev/mame/commit/62fc2e8f068a67b84b324b1c2e9b55791850247e --- src/devices/sound/tms5220.cpp | 485 +++++++++++++++++++++--------------------- src/devices/sound/tms5220.h | 78 ++++--- 2 files changed, 275 insertions(+), 288 deletions(-) diff --git a/src/devices/sound/tms5220.cpp b/src/devices/sound/tms5220.cpp index d80d4a88f20..b0cf48a271a 100644 --- a/src/devices/sound/tms5220.cpp +++ b/src/devices/sound/tms5220.cpp @@ -198,10 +198,6 @@ Interpolation is inhibited (i.e. interpolation at IP frames will not happen ****Documentation of chip commands:*** - 76543210 (these are in logical 7 thru 0 order with MSB (7) first; TI calls - these bits by the opposite order, D0 thru D7, on the datasheet, - with D0 being the MSB) - x0x0xbcc: on 5200/5220: NOP (does nothing) on 5220C and CD2501ECD: Select frame length by cc, and b selects whether every frame is preceded by 2 bits to select the frame @@ -325,10 +321,9 @@ this), mostly on later pinballs with LPC speech) module (6511 based), IBM PS/2 Speech adapter (parallel port connection device), PES Speech adapter (serial port connection) -Street electronics had two later 1988-1990-era ECHO appleII cards which are -TSP50c0x/1x MCU based speech and not tms52xx based (though it is likely -emulating the tms5220 in MCU code). Look for a 16-pin chip at U6 labeled -"ECHO-2 SN" or "ECHO-3 SN". +Street electronics had a later 1989-era ECHO appleII card which is TSP50c0x/1x +MCU based speech and not tms5xxx based (though it is likely emulating the tms5220 +in MCU code). Look for a 16-pin chip at U6 labeled "ECHO-3 SN". ***********************************************************************************************/ @@ -387,8 +382,6 @@ static int16_t clip_analog(int16_t cliptemp); // above dumps info if a frame ran out of data #undef DEBUG_COMMAND_DUMP // above dumps all non-speech-data command writes -#undef DEBUG_COMMAND_VERBOSE -// above dumps decoded info about command writes #undef DEBUG_PIN_READS // above spams the errorlog with i/o ready messages whenever the ready or irq pin is read #undef DEBUG_GENERATION @@ -400,10 +393,9 @@ static int16_t clip_analog(int16_t cliptemp); #undef DEBUG_CLIP // above dumps info to stderr whenever the analog clip hardware is (or would be) clipping the signal. #undef DEBUG_IO_READY -// above debugs the io ready callback timer +// above debugs the io ready callback #undef DEBUG_RS_WS // above debugs the tms5220_data_r and data_w access methods which actually respect rs and ws -// TODO: switch the comments to be above the defines instead of below them #define MAX_SAMPLE_CHUNK 512 @@ -448,32 +440,12 @@ static const uint8_t reload_table[4] = { 0, 2, 4, 6 }; //sample count reload for void tms5220_device::register_for_save_states() { - // for sanity purposes these variables should be in the same order as in tms5220.h! - - // 5110 specific stuff - save_item(NAME(m_PDC)); - save_item(NAME(m_CTL_pins)); - save_item(NAME(m_state)); - - // new VSM stuff - save_item(NAME(m_address)); - save_item(NAME(m_next_is_address)); - save_item(NAME(m_schedule_dummy_read)); - save_item(NAME(m_addr_bit)); - save_item(NAME(m_CTL_buffer)); - - // old VSM stuff - save_item(NAME(m_read_byte_register)); - save_item(NAME(m_RDB_flag)); - - // FIFO save_item(NAME(m_fifo)); save_item(NAME(m_fifo_head)); save_item(NAME(m_fifo_tail)); save_item(NAME(m_fifo_count)); save_item(NAME(m_fifo_bits_taken)); - // global status bits (booleans) save_item(NAME(m_previous_TALK_STATUS)); save_item(NAME(m_SPEN)); save_item(NAME(m_DDIS)); @@ -484,7 +456,6 @@ void tms5220_device::register_for_save_states() save_item(NAME(m_irq_pin)); save_item(NAME(m_ready_pin)); - // current and previous frames save_item(NAME(m_OLDE)); save_item(NAME(m_OLDP)); @@ -521,59 +492,65 @@ void tms5220_device::register_for_save_states() save_item(NAME(m_RNG)); save_item(NAME(m_excitation_data)); + save_item(NAME(m_schedule_dummy_read)); + save_item(NAME(m_data_register)); + save_item(NAME(m_RDB_flag)); save_item(NAME(m_digital_select)); save_item(NAME(m_io_ready)); - // "proper" rs+ws emulation save_item(NAME(m_true_timing)); save_item(NAME(m_rs_ws)); save_item(NAME(m_read_latch)); save_item(NAME(m_write_latch)); + + // 5110 specific stuff + save_item(NAME(m_PDC)); + save_item(NAME(m_CTL_pins)); + save_item(NAME(m_state)); + save_item(NAME(m_address)); + save_item(NAME(m_next_is_address)); + save_item(NAME(m_addr_bit)); + save_item(NAME(m_CTL_buffer)); } /********************************************************************************************** - printbits helper function: takes an input and prints the resulting bits to a string buffer, passed to it using snprintf. + printbits helper function: takes a long int input and prints the resulting bits to stderr ***********************************************************************************************/ #ifdef DEBUG_PARSE_FRAME_DUMP_BIN -int tms5220_device::printbits(char *buffer, int count, unsigned int data, int num) +static void printbits(long data, int num) { - int retval = 0; int i; for (i=(num-1); i>=0; i--) - { - retval += snprintf(buffer+retval, count-retval, "%0d", (data>>i)&1); - } - retval += snprintf(buffer+retval, count-retval, " "); - return retval; + logerror("%0ld", (data>>i)&1); } #endif #ifdef DEBUG_PARSE_FRAME_DUMP_HEX -int tms5220_device::printbits(char *buffer, int count, unsigned int data, int num) +static void printbits(long data, int num) { - int retval = 0; switch((num-1)&0xFC) { case 0: - retval = snprintf(buffer, count, "%01x ", data); + logerror("%0lx", data); break; case 4: - retval = snprintf(buffer, count, "%02x ", data); + logerror("%02lx", data); break; case 8: - retval = snprintf(buffer, count, "%03x ", data); + logerror("%03lx", data); break; case 12: + logerror("%04lx", data); + break; default: - retval = snprintf(buffer, count, "%04x ", data); + logerror("%04lx", data); break; } - return retval; } #endif @@ -634,9 +611,10 @@ uint8_t tms5220_device::new_int_read() tms5220_device::data_write -- handle a write to the TMS5220 ***********************************************************************************************/ + void tms5220_device::data_write(int data) { - bool old_buffer_low = m_buffer_low; + int old_buffer_low = m_buffer_low; #ifdef DEBUG_DUMP_INPUT_DATA fprintf(stdout, "%c",data); #endif @@ -653,24 +631,24 @@ void tms5220_device::data_write(int data) #endif update_fifo_status_and_ints(); // if we just unset buffer low with that last write, and SPEN *was* zero (see circuit 251, sheet 12) - if ((!m_SPEN) && ((old_buffer_low) && (!m_buffer_low))) // MUST HAVE EDGE DETECT + if ((m_SPEN == 0) && ((old_buffer_low == 1) && (m_buffer_low == 0))) // MUST HAVE EDGE DETECT { int i; #ifdef DEBUG_FIFO logerror("data_write triggered SPEN to go active!\n"); #endif // ...then we now have enough bytes to start talking; set zpar and clear out the new frame parameters (it will become old frame just before the first call to parse_frame() ) - m_zpar = true; - m_uv_zpar = true; // zero k4-k10 as well - m_OLDE = true; // 'silence/zpar' frames are zero energy - m_OLDP = true; // 'silence/zpar' frames are zero pitch + m_zpar = 1; + m_uv_zpar = 1; // zero k4-k10 as well + m_OLDE = 1; // 'silence/zpar' frames are zero energy + m_OLDP = 1; // 'silence/zpar' frames are zero pitch #ifdef TMS5220_PERFECT_INTERPOLATION_HACK - m_old_zpar = true; // zero all the old parameters - m_old_uv_zpar = true; // zero old k4-k10 as well + m_old_zpar = 1; // zero all the old parameters + m_old_uv_zpar = 1; // zero old k4-k10 as well #endif - m_SPEN = true; + m_SPEN = 1; #ifdef FAST_START_HACK - m_TALK = true; + m_TALK = 1; #endif m_new_frame_energy_idx = 0; m_new_frame_pitch_idx = 0; @@ -720,6 +698,7 @@ void tms5220_device::data_write(int data) Speak External command execution is terminated. ***********************************************************************************************/ + void tms5220_device::update_fifo_status_and_ints() { /* update 52xx fifo flags and set ints if needed */ @@ -733,13 +712,11 @@ void tms5220_device::update_fifo_status_and_ints() { // generate an interrupt if necessary; if /BL was inactive and is now active, set int. if (!m_buffer_low) - { - m_buffer_low = true; set_interrupt_state(1); - } + m_buffer_low = 1; } else - m_buffer_low = false; + m_buffer_low = 0; /* BE is set if neither byte 15 nor 14 of the fifo are in use; this translates to having fifo_count equal to exactly 0 @@ -748,25 +725,23 @@ void tms5220_device::update_fifo_status_and_ints() { // generate an interrupt if necessary; if /BE was inactive and is now active, set int. if (!m_buffer_empty) - { - m_buffer_empty = true; set_interrupt_state(1); - } + m_buffer_empty = 1; if (m_DDIS) - m_TALK = m_SPEN = false; // /BE being active clears the TALK status via TCON, which in turn clears SPEN, but ONLY if m_DDIS is set! See patent page 16, gate 232b + m_TALK = m_SPEN = 0; // /BE being active clears the TALK status via TCON, which in turn clears SPEN, but ONLY if m_DDIS is set! See patent page 16, gate 232b } else - m_buffer_empty = false; + m_buffer_empty = 0; // generate an interrupt if /TS was active, and is now inactive. // also, in this case, regardless if DDIS was set, unset it. - if (m_previous_TALK_STATUS && (!TALK_STATUS())) + if ((m_previous_TALK_STATUS == 1) && (TALK_STATUS() == 0)) { #ifdef VERBOSE logerror("Talk status WAS 1, is now 0, unsetting DDIS and firing an interrupt!\n"); #endif set_interrupt_state(1); - m_DDIS = false; + m_DDIS = 0; } m_previous_TALK_STATUS = TALK_STATUS(); @@ -777,6 +752,7 @@ void tms5220_device::update_fifo_status_and_ints() extract_bits -- extract a specific number of bits from the current input stream (FIFO or VSM) ***********************************************************************************************/ + int tms5220_device::extract_bits(int count) { int val = 0; @@ -805,8 +781,6 @@ int tms5220_device::extract_bits(int count) // extract from VSM (speech ROM) if (m_speechrom) val = m_speechrom->read(count); - else - val = (1<> m_fifo_bits_taken) & 0xf; + if (val == 0) + /* 0 -> silence frame: we will only read 4 bits, and we will + * therefore need to read another frame before the FIFO is not + * full any more */ + answer += m_subc_reload?200:304; + /* 15 -> stop frame, we will only read 4 bits, but the FIFO will + * we cleared; otherwise, we need to parse the repeat flag (1 bit) + * and the pitch (6 bits), so everything will be OK. */ + } + } + + return answer; } + /********************************************************************************************** tms5220_int_read -- returns the interrupt state of the TMS5220 ***********************************************************************************************/ -bool tms5220_device::int_read() + +int tms5220_device::int_read() { #ifdef DEBUG_PIN_READS logerror("int_read: irq pin read, state is %d\n", m_irq_pin); @@ -889,14 +906,16 @@ bool tms5220_device::int_read() return m_irq_pin; } + /********************************************************************************************** tms5220_process -- fill the buffer with a specific number of samples ***********************************************************************************************/ + void tms5220_device::process(int16_t *buffer, unsigned int size) { - int buf_count = 0; + int buf_count=0; int i, bitout; int32_t this_sample; @@ -936,7 +955,7 @@ void tms5220_device::process(int16_t *buffer, unsigned int size) /* if the new frame is a stop frame, unset both TALK and SPEN (via TCON). TALKD remains active while the energy is ramping to 0. */ if (NEW_FRAME_STOP_FLAG()) { - m_TALK = m_SPEN = false; + m_TALK = m_SPEN = 0; update_fifo_status_and_ints(); // probably not necessary... } @@ -947,20 +966,20 @@ void tms5220_device::process(int16_t *buffer, unsigned int size) * Old frame was unvoiced, new is voiced * Old frame was unvoiced, new frame is silence/zero energy (non-existent on tms51xx rev D and F (present and working on tms52xx, present but buggy on tms51xx rev A and B)) */ - if ( (!OLD_FRAME_UNVOICED_FLAG() && NEW_FRAME_UNVOICED_FLAG()) - || (OLD_FRAME_UNVOICED_FLAG() && !NEW_FRAME_UNVOICED_FLAG()) - || (OLD_FRAME_SILENCE_FLAG() && !NEW_FRAME_SILENCE_FLAG()) - //|| ((m_inhibit == true) && OLD_FRAME_UNVOICED_FLAG() && NEW_FRAME_SILENCE_FLAG()) ) //TMS51xx INTERP BUG1 - || (OLD_FRAME_UNVOICED_FLAG() && NEW_FRAME_SILENCE_FLAG()) ) - m_inhibit = true; + if ( ((OLD_FRAME_UNVOICED_FLAG() == 0) && NEW_FRAME_UNVOICED_FLAG()) + || ((OLD_FRAME_UNVOICED_FLAG() == 1) && !NEW_FRAME_UNVOICED_FLAG()) + || ((OLD_FRAME_SILENCE_FLAG() == 1) && !NEW_FRAME_SILENCE_FLAG()) + //|| ((m_inhibit == 1) && (OLD_FRAME_UNVOICED_FLAG() == 1) && NEW_FRAME_SILENCE_FLAG()) ) //TMS51xx INTERP BUG1 + || ((OLD_FRAME_UNVOICED_FLAG() == 1) && NEW_FRAME_SILENCE_FLAG()) ) + m_inhibit = 1; else // normal frame, normal interpolation - m_inhibit = false; + m_inhibit = 0; #ifdef DEBUG_GENERATION /* Debug info for current parsed frame */ logerror( "OLDE: %d; NEWE: %d; OLDP: %d; NEWP: %d ", OLD_FRAME_SILENCE_FLAG(), NEW_FRAME_SILENCE_FLAG(), OLD_FRAME_UNVOICED_FLAG(), NEW_FRAME_UNVOICED_FLAG()); logerror("Processing new frame: "); - if (m_inhibit == false) + if (m_inhibit == 0) logerror( "Normal Frame\n"); else logerror("Interpolation Inhibited\n"); @@ -984,7 +1003,7 @@ void tms5220_device::process(int16_t *buffer, unsigned int size) } else // Not a new frame, just interpolate the existing frame. { - bool inhibit_state = ((m_inhibit == true) && (m_IP != 0)); // disable inhibit when reaching the last interp period, but don't overwrite the m_inhibit value + int inhibit_state = ((m_inhibit==1)&&(m_IP != 0)); // disable inhibit when reaching the last interp period, but don't overwrite the m_inhibit value #ifdef TMS5220_PERFECT_INTERPOLATION_HACK int samples_per_frame = m_subc_reload?175:266; // either (13 A cycles + 12 B cycles) * 7 interps for normal SPEAK/SPKEXT, or (13*2 A cycles + 12 B cycles) * 7 interps for SPKSLOW //int samples_per_frame = m_subc_reload?200:304; // either (13 A cycles + 12 B cycles) * 8 interps for normal SPEAK/SPKEXT, or (13*2 A cycles + 12 B cycles) * 8 interps for SPKSLOW @@ -1005,7 +1024,7 @@ void tms5220_device::process(int16_t *buffer, unsigned int size) } else // we're done, play this frame for 1/8 frame. { - if (m_subcycle == 2) m_pitch_zero = false; // this reset happens around the second subcycle during IP=0 + if (m_subcycle == 2) m_pitch_zero = 0; // this reset happens around the second subcycle during IP=0 m_current_energy = (m_coeff->energytable[m_new_frame_energy_idx] * (1-m_zpar)); m_current_pitch = (m_coeff->pitchtable[m_new_frame_pitch_idx] * (1-m_zpar)); for (i = 0; i < m_coeff->num_k; i++) @@ -1037,7 +1056,7 @@ void tms5220_device::process(int16_t *buffer, unsigned int size) } // calculate the output - if (OLD_FRAME_UNVOICED_FLAG() == true) + if (OLD_FRAME_UNVOICED_FLAG() == 1) { // generate unvoiced samples here if (m_RNG & 1) @@ -1119,13 +1138,13 @@ void tms5220_device::process(int16_t *buffer, unsigned int size) * According to testing the pitch zeroing lasts approximately 2 samples. * We set the zeroing latch here, and unset it on PC=1 in the generator. */ - if ((m_IP == 7)&&(m_inhibit == true)) m_pitch_zero = true; + if ((m_IP == 7)&&(m_inhibit==1)) m_pitch_zero = 1; if (m_IP == 7) // RESETL4 { // Latch OLDE and OLDP - //if (OLD_FRAME_SILENCE_FLAG()) m_uv_zpar = false; // TMS51xx INTERP BUG2 - OLD_FRAME_SILENCE_FLAG() = NEW_FRAME_SILENCE_FLAG() ? true : false; // m_OLDE - OLD_FRAME_UNVOICED_FLAG() = NEW_FRAME_UNVOICED_FLAG() ? true : false; // m_OLDP + //if (OLD_FRAME_SILENCE_FLAG()) m_uv_zpar = 0; // TMS51xx INTERP BUG2 + OLD_FRAME_SILENCE_FLAG() = NEW_FRAME_SILENCE_FLAG() ? 1 : 0; // m_OLDE + OLD_FRAME_UNVOICED_FLAG() = NEW_FRAME_UNVOICED_FLAG() ? 1 : 0; // m_OLDP /* if TALK was clear last frame, halt speech now, since TALKD (latched from TALK on new frame) just went inactive. */ #ifdef DEBUG_GENERATION logerror("RESETL4, about to update status: IP=%d, PC=%d, subcycle=%d, m_SPEN=%d, m_TALK=%d, m_TALKD=%d\n", m_IP, m_PC, m_subcycle, m_SPEN, m_TALK, m_TALKD); @@ -1136,7 +1155,7 @@ void tms5220_device::process(int16_t *buffer, unsigned int size) #endif m_TALKD = m_TALK; // TALKD is latched from TALK update_fifo_status_and_ints(); // to trigger an interrupt if TALK_STATUS has changed - if ((!m_TALK) && m_SPEN) m_TALK = true; // TALK is only activated if it wasn't already active, if m_SPEN is active, and if we're in RESETL4 (which we are). + if ((!m_TALK) && m_SPEN) m_TALK = 1; // TALK is only activated if it wasn't already active, if m_SPEN is active, and if we're in RESETL4 (which we are). #ifdef DEBUG_GENERATION logerror("RESETL4, status updated: IP=%d, PC=%d, subcycle=%d, m_SPEN=%d, m_TALK=%d, m_TALKD=%d\n", m_IP, m_PC, m_subcycle, m_SPEN, m_TALK, m_TALKD); #endif @@ -1152,7 +1171,7 @@ void tms5220_device::process(int16_t *buffer, unsigned int size) m_PC++; } m_pitch_count++; - if ((m_pitch_count >= m_current_pitch)||(m_pitch_zero == true)) m_pitch_count = 0; + if ((m_pitch_count >= m_current_pitch)||(m_pitch_zero == 1)) m_pitch_count = 0; m_pitch_count &= 0x1FF; } else // m_TALKD == 0 @@ -1164,7 +1183,7 @@ void tms5220_device::process(int16_t *buffer, unsigned int size) { m_TALKD = m_TALK; // TALKD is latched from TALK update_fifo_status_and_ints(); // probably not necessary - if ((!m_TALK) && m_SPEN) m_TALK = true; // TALK is only activated if it wasn't already active, if m_SPEN is active, and if we're in RESETL4 (which we are). + if ((!m_TALK) && m_SPEN) m_TALK = 1; // TALK is only activated if it wasn't already active, if m_SPEN is active, and if we're in RESETL4 (which we are). } m_subcycle = m_subc_reload; m_PC = 0; @@ -1188,6 +1207,7 @@ void tms5220_device::process(int16_t *buffer, unsigned int size) clip_analog -- clips the 14 bit return value from the lattice filter to its final 10 bit value (-512 to 511), and upshifts/range extends this to 16 bits ***********************************************************************************************/ + static int16_t clip_analog(int16_t cliptemp) { /* clipping, just like the patent shows: @@ -1219,6 +1239,7 @@ static int16_t clip_analog(int16_t cliptemp) #endif } + /********************************************************************************************** matrix_multiply -- does the proper multiply and shift @@ -1251,6 +1272,7 @@ static int32_t matrix_multiply(int32_t a, int32_t b) resulting sample. ***********************************************************************************************/ + int32_t tms5220_device::lattice_filter() { // Lattice filter here @@ -1317,11 +1339,13 @@ int32_t tms5220_device::lattice_filter() return m_u[0]; } + /********************************************************************************************** process_command -- extract a byte from the FIFO and interpret it as a command ***********************************************************************************************/ + void tms5220_device::process_command(unsigned char cmd) { int i; @@ -1332,9 +1356,6 @@ void tms5220_device::process_command(unsigned char cmd) switch (cmd & 0x70) { case 0x10 : /* read byte */ -#ifdef DEBUG_COMMAND_VERBOSE - logerror("Read Byte command received\n"); -#endif if (TALK_STATUS() == 0) /* TALKST must be clear for RDBY */ { if (m_schedule_dummy_read) @@ -1344,34 +1365,23 @@ void tms5220_device::process_command(unsigned char cmd) m_speechrom->read(1); } if (m_speechrom) - m_read_byte_register = m_speechrom->read(8); /* read one byte from speech ROM... */ + m_data_register = m_speechrom->read(8); /* read one byte from speech ROM... */ m_RDB_flag = true; } -#ifdef DEBUG_COMMAND_VERBOSE - else - logerror("Read Byte command received during TALK state, ignoring!\n"); -#endif break; case 0x00: case 0x20: /* set rate (tms5220c and cd2501ecd only), otherwise NOP */ if (TMS5220_HAS_RATE_CONTROL) -#ifdef DEBUG_COMMAND_VERBOSE { - logerror("Set Rate (or NOP) command received\n"); -#endif m_c_variant_rate = cmd&0x0F; -#ifdef DEBUG_COMMAND_VERBOSE } - else - logerror("NOP command received\n"); -#endif break; case 0x30 : /* read and branch */ if (TALK_STATUS() == 0) /* TALKST must be clear for RB */ { -#ifdef DEBUG_COMMAND_VERBOSE - logerror("Read and Branch command received\n"); +#ifdef VERBOSE + logerror("read and branch command received\n"); #endif m_RDB_flag = false; if (m_speechrom) @@ -1380,9 +1390,6 @@ void tms5220_device::process_command(unsigned char cmd) break; case 0x40 : /* load address */ -#ifdef DEBUG_COMMAND_VERBOSE - logerror("Load Address command received\n"); -#endif if (TALK_STATUS() == 0) /* TALKST must be clear for LA */ { /* tms5220 data sheet says that if we load only one 4-bit nibble, it won't work. @@ -1391,16 +1398,9 @@ void tms5220_device::process_command(unsigned char cmd) m_speechrom->load_address(cmd & 0x0f); m_schedule_dummy_read = true; } -#ifdef DEBUG_COMMAND_VERBOSE - else - logerror("Load Address command received during TALK state, ignoring!\n"); -#endif break; case 0x50 : /* speak */ -#ifdef DEBUG_COMMAND_VERBOSE - logerror("Speak (VSM) command received\n"); -#endif if (m_schedule_dummy_read) { m_schedule_dummy_read = false; @@ -1411,14 +1411,14 @@ void tms5220_device::process_command(unsigned char cmd) #ifdef FAST_START_HACK m_TALK = 1; #endif - m_DDIS = false; // speak using VSM - m_zpar = true; // zero all the parameters - m_uv_zpar = true; // zero k4-k10 as well - m_OLDE = true; // 'silence/zpar' frames are zero energy - m_OLDP = true; // 'silence/zpar' frames are zero pitch + m_DDIS = 0; + m_zpar = 1; // zero all the parameters + m_uv_zpar = 1; // zero k4-k10 as well + m_OLDE = 1; // 'silence/zpar' frames are zero energy + m_OLDP = 1; // 'silence/zpar' frames are zero pitch #ifdef TMS5220_PERFECT_INTERPOLATION_HACK - m_old_zpar = true; // zero all the old parameters - m_old_uv_zpar = true; // zero old k4-k10 as well + m_old_zpar = 1; // zero all the old parameters + m_old_uv_zpar = 1; // zero old k4-k10 as well #endif // following is semi-hack but matches idle state observed on chip m_new_frame_energy_idx = 0; @@ -1432,21 +1432,17 @@ void tms5220_device::process_command(unsigned char cmd) break; case 0x60 : /* speak external */ -#ifdef DEBUG_COMMAND_VERBOSE - logerror("Speak External command received\n"); -#endif - // SPKEXT going active asserts /SPKEE for 2 clocks, which clears the FIFO and its counters - memset(m_fifo, 0, sizeof(m_fifo[0])*FIFO_SIZE); + // SPKEXT going active activates SPKEE which clears the fifo m_fifo_head = m_fifo_tail = m_fifo_count = m_fifo_bits_taken = 0; - // SPEN is enabled when the FIFO passes half full (falling edge of BL signal) - m_DDIS = true; // speak using FIFO - m_zpar = true; // zero all the parameters - m_uv_zpar = true; // zero k4-k10 as well - m_OLDE = true; // 'silence/zpar' frames are zero energy - m_OLDP = true; // 'silence/zpar' frames are zero pitch + // SPEN is enabled when the fifo passes half full (falling edge of BL signal) + m_DDIS = 1; + m_zpar = 1; // zero all the parameters + m_uv_zpar = 1; // zero k4-k10 as well + m_OLDE = 1; // 'silence/zpar' frames are zero energy + m_OLDP = 1; // 'silence/zpar' frames are zero pitch #ifdef TMS5220_PERFECT_INTERPOLATION_HACK - m_old_zpar = true; // zero all the old parameters - m_old_uv_zpar = true; // zero old k4-k10 as well + m_old_zpar = 1; // zero all the old parameters + m_old_uv_zpar = 1; // zero old k4-k10 as well #endif // following is semi-hack but matches idle state observed on chip m_new_frame_energy_idx = 0; @@ -1461,9 +1457,6 @@ void tms5220_device::process_command(unsigned char cmd) break; case 0x70 : /* reset */ -#ifdef DEBUG_COMMAND_VERBOSE - logerror("Reset command received\n"); -#endif if (m_schedule_dummy_read) { m_schedule_dummy_read = false; @@ -1483,17 +1476,9 @@ void tms5220_device::process_command(unsigned char cmd) parse_frame -- parse a new frame's worth of data; returns 0 if not enough bits in buffer ******************************************************************************************/ + void tms5220_device::parse_frame() { -#ifdef DEBUG_PARSE_FRAME_DUMP - char p_buffer[64] = { - 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, - 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, - 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, - 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 - }; - uint8_t p_buffer_count = 0; -#endif int i, rep_flag; #ifdef TMS5220_PERFECT_INTERPOLATION_HACK m_old_uv_zpar = m_uv_zpar; @@ -1511,7 +1496,8 @@ void tms5220_device::parse_frame() { i = extract_bits(2); #ifdef DEBUG_PARSE_FRAME_DUMP - p_buffer_count += printbits(p_buffer+p_buffer_count, 64-p_buffer_count, i, 2); + printbits(i,2); + logerror(" "); #endif m_IP = reload_table[i]; } @@ -1524,7 +1510,8 @@ void tms5220_device::parse_frame() // attempt to extract the energy index m_new_frame_energy_idx = extract_bits(m_coeff->energy_bits); #ifdef DEBUG_PARSE_FRAME_DUMP - p_buffer_count += printbits(p_buffer+p_buffer_count, 64-p_buffer_count, m_new_frame_energy_idx, m_coeff->energy_bits); + printbits(m_new_frame_energy_idx,m_coeff->energy_bits); + logerror(" "); #endif update_fifo_status_and_ints(); if (m_DDIS && m_buffer_empty) goto ranout; @@ -1532,16 +1519,19 @@ void tms5220_device::parse_frame() if ((m_new_frame_energy_idx == 0) || (m_new_frame_energy_idx == 15)) return; + // attempt to extract the repeat flag rep_flag = extract_bits(1); #ifdef DEBUG_PARSE_FRAME_DUMP - p_buffer_count += printbits(p_buffer+p_buffer_count, 64-p_buffer_count, rep_flag, 1); + printbits(rep_flag, 1); + logerror(" "); #endif // attempt to extract the pitch m_new_frame_pitch_idx = extract_bits(m_coeff->pitch_bits); #ifdef DEBUG_PARSE_FRAME_DUMP - p_buffer_count += printbits(p_buffer+p_buffer_count, 64-p_buffer_count, m_new_frame_pitch_idx,m_coeff->pitch_bits); + printbits(m_new_frame_pitch_idx,m_coeff->pitch_bits); + logerror(" "); #endif // if the new frame is unvoiced, be sure to zero out the k5-k10 parameters m_uv_zpar = NEW_FRAME_UNVOICED_FLAG() ? 1 : 0; @@ -1556,7 +1546,8 @@ void tms5220_device::parse_frame() { m_new_frame_k_idx[i] = extract_bits(m_coeff->kbits[i]); #ifdef DEBUG_PARSE_FRAME_DUMP - p_buffer_count += printbits(p_buffer+p_buffer_count, 64-p_buffer_count, m_new_frame_k_idx[i],m_coeff->kbits[i]); + printbits(m_new_frame_k_idx[i],m_coeff->kbits[i]); + logerror(" "); #endif update_fifo_status_and_ints(); if (m_DDIS && m_buffer_empty) goto ranout; @@ -1574,13 +1565,14 @@ void tms5220_device::parse_frame() { m_new_frame_k_idx[i] = extract_bits(m_coeff->kbits[i]); #ifdef DEBUG_PARSE_FRAME_DUMP - p_buffer_count += printbits(p_buffer+p_buffer_count, 64-p_buffer_count, m_new_frame_k_idx[i],m_coeff->kbits[i]); + printbits(m_new_frame_k_idx[i],m_coeff->kbits[i]); + logerror(" "); #endif update_fifo_status_and_ints(); if (m_DDIS && m_buffer_empty) goto ranout; } #ifdef DEBUG_PARSE_FRAME_DUMP - logerror("%s\n", p_buffer); + logerror("\n"); #endif #ifdef VERBOSE if (m_DDIS) @@ -1602,6 +1594,7 @@ void tms5220_device::parse_frame() set_interrupt_state -- generate an interrupt ***********************************************************************************************/ + void tms5220_device::set_interrupt_state(int state) { if (!TMS5220_IS_52xx) return; // bail out if not a 52xx chip, since there's no int pin @@ -1618,18 +1611,16 @@ void tms5220_device::set_interrupt_state(int state) update_ready_state -- update the ready line ***********************************************************************************************/ + void tms5220_device::update_ready_state() { - bool state = ready_read(); - if (m_ready_pin != state) - { + int state = ready_read(); #ifdef DEBUG_PIN_READS - logerror("ready pin set to state %d\n", state); + logerror("ready pin set to state %d\n", state); #endif - if (!m_readyq_handler.isnull()) - m_readyq_handler(!state); - m_ready_pin = state; - } + if (!m_readyq_handler.isnull() && state != m_ready_pin) + m_readyq_handler(!state); + m_ready_pin = state; } @@ -1697,13 +1688,11 @@ void tms5220_device::device_start() m_stream = machine().sound().stream_alloc(*this, 0, 1, clock() / 80); m_timer_io_ready = timer_alloc(0); - //m_timer_rsq_wsq_check = timer_alloc(1); /* not during reset which is called from within a write! */ - m_io_ready = true; - m_true_timing = false; + m_io_ready = 1; + m_true_timing = 0; m_rs_ws = 0x03; // rs and ws are assumed to be inactive on device startup - m_write_latch = 0; // assume on start that nothing is driving the data bus register_for_save_states(); } @@ -1716,15 +1705,15 @@ void tms5220_device::device_reset() { m_digital_select = FORCE_DIGITAL; // assume analog output /* initialize the FIFO */ - memset(m_fifo, 0, sizeof(m_fifo[0])*FIFO_SIZE); + /*memset(m_fifo, 0, sizeof(m_fifo));*/ m_fifo_head = m_fifo_tail = m_fifo_count = m_fifo_bits_taken = 0; /* initialize the chip state */ /* Note that we do not actually clear IRQ on start-up : IRQ is even raised if m_buffer_empty or m_buffer_low are 0 */ - m_SPEN = m_DDIS = m_TALK = m_TALKD = m_previous_TALK_STATUS = m_irq_pin = m_ready_pin = false; + m_SPEN = m_DDIS = m_TALK = m_TALKD = m_previous_TALK_STATUS = m_irq_pin = m_ready_pin = 0; set_interrupt_state(0); update_ready_state(); - m_buffer_empty = m_buffer_low = true; + m_buffer_empty = m_buffer_low = 1; m_RDB_flag = false; @@ -1732,24 +1721,24 @@ void tms5220_device::device_reset() #ifdef TMS5220_PERFECT_INTERPOLATION_HACK m_old_frame_energy_idx = m_old_frame_pitch_idx = 0; memset(m_old_frame_k_idx, 0, sizeof(m_old_frame_k_idx)); - m_old_zpar = false; + m_old_zpar = 0; #endif m_new_frame_energy_idx = m_current_energy = m_previous_energy = 0; m_new_frame_pitch_idx = m_current_pitch = 0; - m_zpar = m_uv_zpar = false; + m_zpar = m_uv_zpar = 0; memset(m_new_frame_k_idx, 0, sizeof(m_new_frame_k_idx)); memset(m_current_k, 0, sizeof(m_current_k)); /* initialize the sample generators */ - m_inhibit = true; + m_inhibit = 1; m_subcycle = m_c_variant_rate = m_pitch_count = m_PC = 0; m_subc_reload = FORCE_SUBC_RELOAD; - m_OLDE = m_OLDP = true; + m_OLDE = m_OLDP = 1; m_IP = reload_table[m_c_variant_rate&0x3]; m_RNG = 0x1FFF; memset(m_u, 0, sizeof(m_u)); memset(m_x, 0, sizeof(m_x)); - m_schedule_dummy_read = false; + m_schedule_dummy_read = 0; if (m_speechrom) { @@ -1757,7 +1746,7 @@ void tms5220_device::device_reset() // MZ: Do the dummy read immediately. The previous line will cause a // shift in the address pointer in the VSM. When the next command is a // load_address, no dummy read will occur, hence the address will be - // incorrectly shifted. + // falsely shifted. m_speechrom->read(1); m_schedule_dummy_read = false; } @@ -1783,61 +1772,41 @@ void tms5220_device::device_timer(emu_timer &timer, device_timer_id id, int para { switch(id) { - case 0: // m_timer_io_ready - /* bring up to date first */ - m_stream->update(); -#ifdef DEBUG_IO_READY - logerror("m_timer_io_ready timer fired, param = %02x, m_rs_ws = %02x\n", param, m_rs_ws); -#endif - if (param) // low->high ready state + case 0: + if (param) { switch (m_rs_ws) { case 0x02: /* Write */ + /* bring up to date first */ #ifdef DEBUG_IO_READY - logerror("m_timer_io_ready: Attempting to service write...\n"); -#endif - if ((m_fifo_count >= FIFO_SIZE) && m_DDIS) // if fifo is full and we're in speak external mode - { -#ifdef DEBUG_IO_READY - logerror("m_timer_io_ready: in SPKEXT and FIFO was full! cannot service write now, delaying 16 cycles...\n"); -#endif - m_timer_io_ready->adjust(clocks_to_attotime(16), 1); - break; - } - else - { -#ifdef DEBUG_IO_READY - logerror("m_timer_io_ready: Serviced write: %02x\n", m_write_latch); + logerror("Serviced write: %02x\n", m_write_latch); + //logerror( "Processed write data: %02X\n", m_write_latch); #endif - data_write(m_write_latch); - m_io_ready = param; - break; - } + m_stream->update(); + data_write(m_write_latch); + break; case 0x01: /* Read */ - m_read_latch = status_read(true); + /* bring up to date first */ + m_stream->update(); + m_read_latch = status_read(); #ifdef DEBUG_IO_READY - logerror("m_timer_io_ready: Serviced read, returning %02x\n", m_read_latch); + logerror("Serviced read, returning %02x\n", m_read_latch); #endif - m_io_ready = param; break; case 0x03: /* High Impedance */ - m_io_ready = param; case 0x00: /* illegal */ - m_io_ready = param; break; } } + m_io_ready = param; update_ready_state(); break; - /*case 1: // m_timer_rsq_wsq_check - // TODO: write me, and get rid of the garbage in wsq_w, rsq_w, etc! - break; */ } } @@ -1848,7 +1817,7 @@ WRITE_LINE_MEMBER( tms5220_device::rsq_w ) { uint8_t new_val; - m_true_timing = true; + m_true_timing = 1; state &= 0x01; #ifdef DEBUG_RS_WS logerror("/RS written with data: %d\n", state); @@ -1859,7 +1828,7 @@ WRITE_LINE_MEMBER( tms5220_device::rsq_w ) m_rs_ws = new_val; if (new_val == 0) { - if (TMS5220_HAS_RATE_CONTROL) // correct for 5220c, probably also correct for cd2501ecd + if (TMS5220_HAS_RATE_CONTROL) // correct for 5220c, ? for cd2501ecd reset(); #ifdef DEBUG_RS_WS else @@ -1885,11 +1854,10 @@ WRITE_LINE_MEMBER( tms5220_device::rsq_w ) logerror("Scheduling ready cycle for /RS...\n"); #endif /* upon /RS being activated, /READY goes inactive after 100 nsec from data sheet, through 3 asynchronous gates on patent. This is effectively within one clock, so we immediately set io_ready to 0 and activate the callback. */ - m_io_ready = false; + m_io_ready = 0; update_ready_state(); - /* How long does /READY stay inactive, when /RS is pulled low? It might be always ~16 clocks (25 usec at 800khz as shown on the datasheet) - but the patent schematic implies it might be as short as 4 clock cycles. */ - m_timer_io_ready->adjust(clocks_to_attotime(16), 1); + /* How long does /READY stay inactive, when /RS is pulled low? I believe its almost always ~16 clocks (25 usec at 800khz as shown on the datasheet) */ + m_timer_io_ready->adjust(clocks_to_attotime(16), 1); // this should take around 10-16 (closer to ~11?) cycles to complete } } } @@ -1901,7 +1869,7 @@ WRITE_LINE_MEMBER( tms5220_device::wsq_w ) { uint8_t new_val; - m_true_timing = true; + m_true_timing = 1; state &= 0x01; #ifdef DEBUG_RS_WS logerror("/WS written with data: %d\n", state); @@ -1938,7 +1906,7 @@ WRITE_LINE_MEMBER( tms5220_device::wsq_w ) logerror("Scheduling ready cycle for /WS...\n"); #endif /* upon /WS being activated, /READY goes inactive after 100 nsec from data sheet, through 3 asynchronous gates on patent. This is effectively within one clock, so we immediately set io_ready to 0 and activate the callback. */ - m_io_ready = false; + m_io_ready = 0; update_ready_state(); /* Now comes the complicated part: how long does /READY stay inactive, when /WS is pulled low? This depends ENTIRELY on the command written, or whether the chip is in speak external mode or not... Speak external mode: ~16 cycles @@ -1965,7 +1933,7 @@ WRITE8_MEMBER( tms5220_device::combined_rsq_wsq_w ) { uint8_t new_val; uint8_t falling_edges; - m_true_timing = true; + m_true_timing = 1; #ifdef DEBUG_RS_WS logerror("/RS and /WS written with %d and %d respectively\n", (data&2)>>1, data&1); #endif @@ -1997,7 +1965,7 @@ WRITE8_MEMBER( tms5220_device::combined_rsq_wsq_w ) logerror("Scheduling ready cycle for /WS...\n"); #endif /* upon /WS being activated, /READY goes inactive after 100 nsec from data sheet, through 3 asynchronous gates on patent. This is effectively within one clock, so we immediately set io_ready to 0 and activate the callback. */ - m_io_ready = false; + m_io_ready = 0; update_ready_state(); /* Now comes the complicated part: how long does /READY stay inactive, when /WS is pulled low? This depends ENTIRELY on the command written, or whether the chip is in speak external mode or not... Speak external mode: ~16 cycles @@ -2020,7 +1988,7 @@ WRITE8_MEMBER( tms5220_device::combined_rsq_wsq_w ) logerror("Scheduling ready cycle for /RS...\n"); #endif /* upon /RS being activated, /READY goes inactive after 100 nsec from data sheet, through 3 asynchronous gates on patent. This is effectively within one clock, so we immediately set io_ready to 0 and activate the callback. */ - m_io_ready = false; + m_io_ready = 0; update_ready_state(); /* How long does /READY stay inactive, when /RS is pulled low? I believe its almost always ~16 clocks (25 usec at 800khz as shown on the datasheet) */ m_timer_io_ready->adjust(clocks_to_attotime(16), 1); // this should take around 10-16 (closer to ~11?) cycles to complete @@ -2038,14 +2006,18 @@ WRITE8_MEMBER( tms5220_device::combined_rsq_wsq_w ) void tms5220_device::write_data(uint8_t data) { + // prevent debugger from changing the internal state + if (machine().side_effects_disabled()) return; + #ifdef DEBUG_RS_WS logerror("tms5220_data_w: data %02x\n", data); #endif - /* bring up to date first */ - m_stream->update(); - m_write_latch = data; - if (!m_true_timing) // if we're in the default hacky mode where we don't bother with rsq_w and wsq_w... - data_write(m_write_latch); // ...force the write through instantly. + if (!m_true_timing) + { + /* bring up to date first */ + m_stream->update(); + data_write(data); + } else { /* actually in a write ? */ @@ -2053,9 +2025,12 @@ void tms5220_device::write_data(uint8_t data) if (!(m_rs_ws == 0x02)) logerror("tms5220_data_w: data written outside ws, status: %02x!\n", m_rs_ws); #endif + m_write_latch = data; } } + + /********************************************************************************************** tms5220_status_r -- read status or data from the sound chip @@ -2064,15 +2039,14 @@ void tms5220_device::write_data(uint8_t data) uint8_t tms5220_device::read_status() { - /* bring up to date first */ - m_stream->update(); + // prevent debugger from changing the internal state + if (machine().side_effects_disabled()) return 0; if (!m_true_timing) { - // prevent debugger from changing the internal state - if (machine().side_effects_disabled()) - return status_read(false); - return status_read(true); + /* bring up to date first */ + m_stream->update(); + return status_read(); } else { @@ -2083,7 +2057,7 @@ uint8_t tms5220_device::read_status() else logerror("tms5220_status_r: data read outside rs!\n"); #endif - return 0xff; // m_write_latch; // return open bus + return 0xff; } } @@ -2104,6 +2078,21 @@ READ_LINE_MEMBER( tms5220_device::readyq_r ) +/********************************************************************************************** + + tms5220_time_to_ready -- return the time until the ready line is asserted + +***********************************************************************************************/ + +attotime tms5220_device::time_to_ready() +{ + /* bring up to date first */ + m_stream->update(); + return clocks_to_attotime(cycles_to_ready() * 80); +} + + + /********************************************************************************************** tms5220_int_r -- return the int status from the sound chip diff --git a/src/devices/sound/tms5220.h b/src/devices/sound/tms5220.h index 0b7617be505..4cfab5491ef 100644 --- a/src/devices/sound/tms5220.h +++ b/src/devices/sound/tms5220.h @@ -90,6 +90,8 @@ public: READ_LINE_MEMBER( readyq_r ); READ_LINE_MEMBER( intq_r ); + attotime time_to_ready(); + protected: tms5220_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock, int variant); @@ -116,23 +118,20 @@ private: void data_write(int data); void update_fifo_status_and_ints(); int extract_bits(int count); - uint8_t status_read(bool clear_int); - bool ready_read(); - bool int_read(); + int status_read(); + int ready_read(); + int cycles_to_ready(); + int int_read(); void process(int16_t *buffer, unsigned int size); int32_t lattice_filter(); void process_command(unsigned char cmd); void parse_frame(); void set_interrupt_state(int state); void update_ready_state(); - //debug -#ifdef DEBUG_PARSE_FRAME_DUMP - printbits(char *buffer, int count, unsigned int data, int num); -#endif - bool TALK_STATUS() const { return m_SPEN || m_TALKD; } - bool &OLD_FRAME_SILENCE_FLAG() { return m_OLDE; } // 1 if E=0, 0 otherwise. - bool &OLD_FRAME_UNVOICED_FLAG() { return m_OLDP; } // 1 if P=0 (unvoiced), 0 if voiced + uint8_t TALK_STATUS() const { return m_SPEN | m_TALKD; } + uint8_t &OLD_FRAME_SILENCE_FLAG() { return m_OLDE; } // 1 if E=0, 0 otherwise. + uint8_t &OLD_FRAME_UNVOICED_FLAG() { return m_OLDP; } // 1 if P=0 (unvoiced), 0 if voiced bool NEW_FRAME_STOP_FLAG() const { return m_new_frame_energy_idx == 0x0F; } // 1 if this is a stop (Energy = 0xF) frame bool NEW_FRAME_SILENCE_FLAG() const { return m_new_frame_energy_idx == 0; } // ditto as above bool NEW_FRAME_UNVOICED_FLAG() const { return m_new_frame_pitch_idx == 0; } // ditto as above @@ -145,23 +144,23 @@ private: /* coefficient tables */ const struct tms5100_coeffs *m_coeff; - /* these contain global status bits for the 5100 */ + /* these contain global status bits */ uint8_t m_PDC; uint8_t m_CTL_pins; uint8_t m_state; /* New VSM interface */ uint32_t m_address; - bool m_next_is_address; - bool m_schedule_dummy_read; + uint8_t m_next_is_address; + uint8_t m_schedule_dummy_read; uint8_t m_addr_bit; /* read byte */ uint8_t m_CTL_buffer; /* Old VSM interface; R Nabet : These have been added to emulate speech Roms */ - //bool m_schedule_dummy_read; /* set after each load address, so that next read operation is preceded by a dummy read */ - uint8_t m_read_byte_register; /* a serial->parallel shifter, used by "read byte" command to store 8 bits from the VSM */ - bool m_RDB_flag; /* whether we should read data register or status register */ + //uint8_t m_schedule_dummy_read; /* set after each load address, so that next read operation is preceded by a dummy read */ + uint8_t m_data_register; /* data register, used by read command */ + uint8_t m_RDB_flag; /* whether we should read data register or status register */ /* these contain data that describes the 128-bit data FIFO */ uint8_t m_fifo[FIFO_SIZE]; @@ -171,20 +170,20 @@ private: uint8_t m_fifo_bits_taken; - /* these contain global status bits (booleans) */ - bool m_previous_TALK_STATUS;/* this is the OLD value of TALK_STATUS (i.e. previous value of m_SPEN|m_TALKD), needed for generating interrupts on a falling TALK_STATUS edge */ - bool m_SPEN; /* set on speak(or speak external and BL falling edge) command, cleared on stop command, reset command, or buffer out */ - bool m_DDIS; /* If 1, DDIS is 1, i.e. Speak External command in progress, writes go to FIFO. */ - bool m_TALK; /* set on SPEN & RESETL4(pc12->pc0 transition), cleared on stop command or reset command */ - bool m_TALKD; /* TALK(TCON) value, latched every RESETL4 */ - bool m_buffer_low; /* If 1, FIFO has less than 8 bytes in it */ - bool m_buffer_empty; /* If 1, FIFO is empty */ - bool m_irq_pin; /* state of the IRQ pin (output) */ - bool m_ready_pin; /* state of the READY pin (output) */ + /* these contain global status bits */ + uint8_t m_previous_TALK_STATUS; /* this is the OLD value of TALK_STATUS (i.e. previous value of m_SPEN|m_TALKD), needed for generating interrupts on a falling TALK_STATUS edge */ + uint8_t m_SPEN; /* set on speak(or speak external and BL falling edge) command, cleared on stop command, reset command, or buffer out */ + uint8_t m_DDIS; /* If 1, DDIS is 1, i.e. Speak External command in progress, writes go to FIFO. */ + uint8_t m_TALK; /* set on SPEN & RESETL4(pc12->pc0 transition), cleared on stop command or reset command */ + uint8_t m_TALKD; /* TALK(TCON) value, latched every RESETL4 */ + uint8_t m_buffer_low; /* If 1, FIFO has less than 8 bytes in it */ + uint8_t m_buffer_empty; /* If 1, FIFO is empty */ + uint8_t m_irq_pin; /* state of the IRQ pin (output) */ + uint8_t m_ready_pin; /* state of the READY pin (output) */ /* these contain data describing the current and previous voice frames */ - bool m_OLDE; - bool m_OLDP; + uint8_t m_OLDE; + uint8_t m_OLDP; uint8_t m_new_frame_energy_idx; uint8_t m_new_frame_pitch_idx; @@ -200,8 +199,8 @@ private: uint8_t m_old_frame_energy_idx; uint8_t m_old_frame_pitch_idx; uint8_t m_old_frame_k_idx[10]; - bool m_old_zpar; - bool m_old_uv_zpar; + uint8_t m_old_zpar; + uint8_t m_old_uv_zpar; int32_t m_current_energy; int32_t m_current_pitch; @@ -215,11 +214,11 @@ private: uint8_t m_PC; /* current parameter counter (what param is being interpolated), ranges from 0 to 12 */ /* NOTE: the interpolation period counts 1,2,3,4,5,6,7,0 for divide by 8,8,8,4,4,2,2,1 */ uint8_t m_IP; /* the current interpolation period */ - bool m_inhibit; /* If 1, interpolation is inhibited until the DIV1 period */ - bool m_uv_zpar; /* If 1, zero k5 thru k10 coefficients */ - bool m_zpar; /* If 1, zero ALL parameters. */ - bool m_pitch_zero; /* circuit 412; pitch is forced to zero under certain circumstances */ - uint8_t m_c_variant_rate; /* only relevant for tms5220C's multi frame rate feature; is the actual 4 bit value written on a 0x2* or 0x0* command */ + uint8_t m_inhibit; /* If 1, interpolation is inhibited until the DIV1 period */ + uint8_t m_uv_zpar; /* If 1, zero k5 thru k10 coefficients */ + uint8_t m_zpar; /* If 1, zero ALL parameters. */ + uint8_t m_pitch_zero; /* circuit 412; pitch is forced to zero under certain circumstances */ + uint8_t m_c_variant_rate; /* only relevant for tms5220C's multi frame rate feature; is the actual 4 bit value written on a 0x2* or 0x0* command */ uint16_t m_pitch_count; /* pitch counter; provides chirp rom address */ int32_t m_u[11]; @@ -233,17 +232,17 @@ private: The internal DAC used to feed the analog pin is only 8 bits, and has the funny clipping/clamping logic, while the digital pin gives full 10 bit resolution of the output data. - TODO: add an MCFG macro to set this other than the FORCE_DIGITAL define + TODO: add a way to set/reset this other than the FORCE_DIGITAL define */ - bool m_digital_select; + uint8_t m_digital_select; /* io_ready: page 3 of the datasheet specifies that READY will be asserted until * data is available or processed by the system. */ - bool m_io_ready; + uint8_t m_io_ready; /* flag for "true" timing involving rs/ws */ - bool m_true_timing; + uint8_t m_true_timing; /* rsws - state, rs bit 1, ws bit 0 */ uint8_t m_rs_ws; @@ -252,7 +251,6 @@ private: sound_stream *m_stream; emu_timer *m_timer_io_ready; - //emu_timer *m_timer_rsq_wsq_check; /* callbacks */ devcb_write_line m_irq_handler; -- cgit v1.2.3