tms5220: Convert logging calls to logmacro.h standard (nw)

This also reinstates the command logging improvements from 62fc2e8f06.
This commit is contained in:
AJR 2018-06-12 10:20:47 -04:00
parent d94e8b2664
commit 4c62c8a48f
2 changed files with 273 additions and 338 deletions

View File

@ -330,8 +330,6 @@ in MCU code). Look for a 16-pin chip at U6 labeled "ECHO-3 SN".
#include "emu.h" #include "emu.h"
#include "tms5220.h" #include "tms5220.h"
static int16_t clip_analog(int16_t cliptemp);
/* *****optional defines***** */ /* *****optional defines***** */
/* Hacky improvements which don't match patent: */ /* Hacky improvements which don't match patent: */
@ -365,38 +363,41 @@ static int16_t clip_analog(int16_t cliptemp);
/* *****debugging defines***** */ /* *****debugging defines***** */
#undef VERBOSE #define LOG_GENERAL (1 << 0)
// above is general, somewhat obsolete, catch all for debugs which don't fit elsewhere // above is general, somewhat obsolete, catch all for debugs which don't fit elsewhere
#undef DEBUG_DUMP_INPUT_DATA #define LOG_DUMP_INPUT_DATA (1 << 1)
/* 5220 only; above dumps the data written to the tms52xx to stdout, useful /* 5220 only; above dumps the data written to the tms52xx to stdout, useful
for making logged data dumps for real hardware tests */ for making logged data dumps for real hardware tests */
#undef DEBUG_FIFO #define LOG_FIFO (1 << 2)
// 5220 only; above debugs fifo stuff: writes, reads and flag updates // 5220 only; above debugs fifo stuff: writes, reads and flag updates
#undef DEBUG_PARSE_FRAME_DUMP #define LOG_PARSE_FRAME_DUMP_BIN (1 << 3)
// above dumps each frame to stderr: be sure to select one of the options below if you define it!
#undef DEBUG_PARSE_FRAME_DUMP_BIN
// dumps each speech frame as binary // dumps each speech frame as binary
#undef DEBUG_PARSE_FRAME_DUMP_HEX #define LOG_PARSE_FRAME_DUMP_HEX (1 << 4)
// dumps each speech frame as hex // dumps each speech frame as hex
#undef DEBUG_FRAME_ERRORS #define LOG_FRAME_ERRORS (1 << 6)
// above dumps info if a frame ran out of data // above dumps info if a frame ran out of data
#undef DEBUG_COMMAND_DUMP #define LOG_COMMAND_DUMP (1 << 7)
// above dumps all non-speech-data command writes // above dumps all non-speech-data command writes
#undef DEBUG_PIN_READS #define LOG_COMMAND_VERBOSE (1 << 8)
// above dumps decoded info about command writes
#define LOG_PIN_READS (1 << 9)
// above spams the errorlog with i/o ready messages whenever the ready or irq pin is read // above spams the errorlog with i/o ready messages whenever the ready or irq pin is read
#undef DEBUG_GENERATION #define LOG_GENERATION (1 << 10)
// above dumps debug information related to the sample generation loop, i.e. whether interpolation is inhibited or not, and what the current and target values for each frame are. // above dumps debug information related to the sample generation loop, i.e. whether interpolation is inhibited or not, and what the current and target values for each frame are.
#undef DEBUG_GENERATION_VERBOSE #define LOG_GENERATION_VERBOSE (1 << 11)
// above dumps MUCH MORE debug information related to the sample generation loop, namely the excitation, energy, pitch, k*, and output values for EVERY SINGLE SAMPLE during a frame. // above dumps MUCH MORE debug information related to the sample generation loop, namely the excitation, energy, pitch, k*, and output values for EVERY SINGLE SAMPLE during a frame.
#undef DEBUG_LATTICE #define LOG_LATTICE (1 << 12)
// above dumps the lattice filter state data each sample. // above dumps the lattice filter state data each sample.
#undef DEBUG_CLIP #define LOG_CLIP (1 << 13)
// above dumps info to stderr whenever the analog clip hardware is (or would be) clipping the signal. // above dumps info to stderr whenever the analog clip hardware is (or would be) clipping the signal.
#undef DEBUG_IO_READY #define LOG_IO_READY (1 << 14)
// above debugs the io ready callback // above debugs the io ready callback timer
#undef DEBUG_RS_WS #define LOG_RS_WS (1 << 15)
// above debugs the tms5220_data_r and data_w access methods which actually respect rs and ws // above debugs the tms5220_data_r and data_w access methods which actually respect rs and ws
//#define VERBOSE (LOG_GENERAL | LOG_DUMP_INPUT_DATA | LOG_FIFO | LOG_PARSE_FRAME_DUMP_HEX | LOG_FRAME_ERRORS | LOG_COMMAND_DUMP | LOG_COMMAND_VERBOSE | LOG_PIN_READS | LOG_GENERATION | LOG_GENERATION_VERBOSE | LOG_LATTICE | LOG_CLIP | LOG_IO_READY | LOG_RS_WS)
#include "logmacro.h"
#define MAX_SAMPLE_CHUNK 512 #define MAX_SAMPLE_CHUNK 512
/* 6+4 Variants, from tms5110r.inc */ /* 6+4 Variants, from tms5110r.inc */
@ -522,37 +523,30 @@ void tms5220_device::register_for_save_states()
***********************************************************************************************/ ***********************************************************************************************/
#ifdef DEBUG_PARSE_FRAME_DUMP_BIN void tms5220_device::printbits(long data, int num)
static void printbits(long data, int num)
{ {
int i; for (int i = num - 1; i >= 0; i--)
for (i=(num-1); i>=0; i--) LOGMASKED(LOG_PARSE_FRAME_DUMP_BIN, "%0ld", (data>>i)&1);
logerror("%0ld", (data>>i)&1);
} switch ((num - 1) & 0xfc)
#endif
#ifdef DEBUG_PARSE_FRAME_DUMP_HEX
static void printbits(long data, int num)
{
switch((num-1)&0xFC)
{ {
case 0: case 0:
logerror("%0lx", data); LOGMASKED(LOG_PARSE_FRAME_DUMP_HEX, "%0lx", data);
break; break;
case 4: case 4:
logerror("%02lx", data); LOGMASKED(LOG_PARSE_FRAME_DUMP_HEX, "%02lx", data);
break; break;
case 8: case 8:
logerror("%03lx", data); LOGMASKED(LOG_PARSE_FRAME_DUMP_HEX, "%03lx", data);
break; break;
case 12: case 12:
logerror("%04lx", data); LOGMASKED(LOG_PARSE_FRAME_DUMP_HEX, "%04lx", data);
break; break;
default: default:
logerror("%04lx", data); LOGMASKED(LOG_PARSE_FRAME_DUMP_HEX, "%04lx", data);
break; break;
} }
} }
#endif
/********************************************************************************************** /**********************************************************************************************
@ -600,9 +594,7 @@ uint8_t tms5220_device::new_int_read()
new_int_write(0, 0, 0, 0); // romclk 0, m0 0, m1 0, addr bus nybble = 0/open bus new_int_write(0, 0, 0, 0); // romclk 0, m0 0, m1 0, addr bus nybble = 0/open bus
if (!m_data_cb.isnull()) if (!m_data_cb.isnull())
return m_data_cb(); return m_data_cb();
#ifdef VERBOSE LOGMASKED(LOG_GENERAL, "WARNING: CALLBACK MISSING, RETURNING 0!\n");
logerror("WARNING: CALLBACK MISSING, RETURNING 0!\n");
#endif
return 0; return 0;
} }
@ -615,9 +607,8 @@ uint8_t tms5220_device::new_int_read()
void tms5220_device::data_write(int data) void tms5220_device::data_write(int data)
{ {
int old_buffer_low = m_buffer_low; int old_buffer_low = m_buffer_low;
#ifdef DEBUG_DUMP_INPUT_DATA LOGMASKED(LOG_DUMP_INPUT_DATA, "%c", data);
fprintf(stdout, "%c",data);
#endif
if (m_DDIS) // If we're in speak external mode if (m_DDIS) // If we're in speak external mode
{ {
// add this byte to the FIFO // add this byte to the FIFO
@ -626,17 +617,13 @@ void tms5220_device::data_write(int data)
m_fifo[m_fifo_tail] = data; m_fifo[m_fifo_tail] = data;
m_fifo_tail = (m_fifo_tail + 1) % FIFO_SIZE; m_fifo_tail = (m_fifo_tail + 1) % FIFO_SIZE;
m_fifo_count++; m_fifo_count++;
#ifdef DEBUG_FIFO LOGMASKED(LOG_FIFO, "data_write: Added byte to FIFO (current count=%2d)\n", m_fifo_count);
logerror("data_write: Added byte to FIFO (current count=%2d)\n", m_fifo_count);
#endif
update_fifo_status_and_ints(); 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 we just unset buffer low with that last write, and SPEN *was* zero (see circuit 251, sheet 12)
if ((m_SPEN == 0) && ((old_buffer_low == 1) && (m_buffer_low == 0))) // MUST HAVE EDGE DETECT if ((m_SPEN == 0) && ((old_buffer_low == 1) && (m_buffer_low == 0))) // MUST HAVE EDGE DETECT
{ {
int i; LOGMASKED(LOG_FIFO, "data_write triggered SPEN to go active!\n");
#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() ) // ...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 = 1; m_zpar = 1;
m_uv_zpar = 1; // zero k4-k10 as well m_uv_zpar = 1; // zero k4-k10 as well
@ -652,21 +639,19 @@ void tms5220_device::data_write(int data)
#endif #endif
m_new_frame_energy_idx = 0; m_new_frame_energy_idx = 0;
m_new_frame_pitch_idx = 0; m_new_frame_pitch_idx = 0;
for (i = 0; i < 4; i++) for (int i = 0; i < 4; i++)
m_new_frame_k_idx[i] = 0; m_new_frame_k_idx[i] = 0;
for (i = 4; i < 7; i++) for (int i = 4; i < 7; i++)
m_new_frame_k_idx[i] = 0xF; m_new_frame_k_idx[i] = 0xF;
for (i = 7; i < m_coeff->num_k; i++) for (int i = 7; i < m_coeff->num_k; i++)
m_new_frame_k_idx[i] = 0x7; m_new_frame_k_idx[i] = 0x7;
} }
} }
else else
{ {
#ifdef DEBUG_FIFO LOGMASKED(LOG_FIFO, "data_write: Ran out of room in the tms52xx FIFO! this should never happen!\n");
logerror("data_write: Ran out of room in the tms52xx FIFO! this should never happen!\n");
// at this point, /READY should remain HIGH/inactive until the fifo has at least one byte open in it. // at this point, /READY should remain HIGH/inactive until the fifo has at least one byte open in it.
#endif
} }
@ -737,9 +722,7 @@ void tms5220_device::update_fifo_status_and_ints()
// also, in this case, regardless if DDIS was set, unset it. // also, in this case, regardless if DDIS was set, unset it.
if ((m_previous_TALK_STATUS == 1) && (TALK_STATUS() == 0)) if ((m_previous_TALK_STATUS == 1) && (TALK_STATUS() == 0))
{ {
#ifdef VERBOSE LOGMASKED(LOG_GENERAL, "Talk status WAS 1, is now 0, unsetting DDIS and firing an interrupt!\n");
logerror("Talk status WAS 1, is now 0, unsetting DDIS and firing an interrupt!\n");
#endif
set_interrupt_state(1); set_interrupt_state(1);
m_DDIS = 0; m_DDIS = 0;
} }
@ -785,9 +768,7 @@ int tms5220_device::extract_bits(int count)
while (count--) while (count--)
{ {
val = (val << 1) | new_int_read(); val = (val << 1) | new_int_read();
#ifdef VERBOSE LOGMASKED(LOG_GENERAL, "bit read: %d\n", val&1);
logerror("bit read: %d\n", val&1);
#endif
} }
#endif #endif
} }
@ -799,12 +780,8 @@ void tms5220_device::perform_dummy_read()
{ {
if (m_schedule_dummy_read) if (m_schedule_dummy_read)
{ {
#ifdef VERBOSE
int data = new_int_read(); int data = new_int_read();
logerror("TMS5110 performing dummy read; value read = %1i\n", data & 1); LOGMASKED(LOG_GENERAL, "TMS5110 performing dummy read; value read = %1i\n", data & 1);
#else
new_int_read();
#endif
m_schedule_dummy_read = false; m_schedule_dummy_read = false;
} }
} }
@ -826,9 +803,7 @@ int tms5220_device::status_read()
{ /* read status */ { /* read status */
/* clear the interrupt pin on status read */ /* clear the interrupt pin on status read */
set_interrupt_state(0); set_interrupt_state(0);
#ifdef DEBUG_PIN_READS LOGMASKED(LOG_PIN_READS, "Status read: TS=%d BL=%d BE=%d\n", TALK_STATUS(), m_buffer_low, m_buffer_empty);
logerror("Status read: TS=%d BL=%d BE=%d\n", TALK_STATUS(), m_buffer_low, m_buffer_empty);
#endif
return (TALK_STATUS() << 7) | (m_buffer_low << 6) | (m_buffer_empty << 5); return (TALK_STATUS() << 7) | (m_buffer_low << 6) | (m_buffer_empty << 5);
} }
} }
@ -842,9 +817,8 @@ int tms5220_device::status_read()
int tms5220_device::ready_read() int tms5220_device::ready_read()
{ {
#ifdef DEBUG_PIN_READS LOGMASKED(LOG_PIN_READS, "ready_read: ready pin read, io_ready is %d, fifo count is %d, DDIS(speak external) is %d\n", m_io_ready, m_fifo_count, m_DDIS);
logerror("ready_read: ready pin read, io_ready is %d, fifo count is %d, DDIS(speak external) is %d\n", m_io_ready, m_fifo_count, m_DDIS);
#endif
return ((m_fifo_count < FIFO_SIZE)||(!m_DDIS)) && m_io_ready; return ((m_fifo_count < FIFO_SIZE)||(!m_DDIS)) && m_io_ready;
} }
@ -900,9 +874,8 @@ int tms5220_device::cycles_to_ready()
int tms5220_device::int_read() int tms5220_device::int_read()
{ {
#ifdef DEBUG_PIN_READS LOGMASKED(LOG_PIN_READS, "int_read: irq pin read, state is %d\n", m_irq_pin);
logerror("int_read: irq pin read, state is %d\n", m_irq_pin);
#endif
return m_irq_pin; return m_irq_pin;
} }
@ -919,9 +892,7 @@ void tms5220_device::process(int16_t *buffer, unsigned int size)
int i, bitout; int i, bitout;
int32_t this_sample; int32_t this_sample;
#ifdef VERBOSE LOGMASKED(LOG_GENERAL, "process called with size of %d; IP=%d, PC=%d, subcycle=%d, m_SPEN=%d, m_TALK=%d, m_TALKD=%d\n", size, m_IP, m_PC, m_subcycle, m_SPEN, m_TALK, m_TALKD);
logerror("process called with size of %d; IP=%d, PC=%d, subcycle=%d, m_SPEN=%d, m_TALK=%d, m_TALKD=%d\n", size, m_IP, m_PC, m_subcycle, m_SPEN, m_TALK, m_TALKD);
#endif
/* loop until the buffer is full or we've stopped speaking */ /* loop until the buffer is full or we've stopped speaking */
while (size > 0) while (size > 0)
@ -975,16 +946,15 @@ void tms5220_device::process(int16_t *buffer, unsigned int size)
else // normal frame, normal interpolation else // normal frame, normal interpolation
m_inhibit = 0; m_inhibit = 0;
#ifdef DEBUG_GENERATION
/* Debug info for current parsed frame */ /* 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()); LOGMASKED(LOG_GENERATION, "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: "); LOGMASKED(LOG_GENERATION, "Processing new frame: ");
if (m_inhibit == 0) if (m_inhibit == 0)
logerror( "Normal Frame\n"); LOGMASKED(LOG_GENERATION, "Normal Frame\n");
else else
logerror("Interpolation Inhibited\n"); LOGMASKED(LOG_GENERATION, "Interpolation Inhibited\n");
logerror("*** current Energy, Pitch and Ks = %04d, %04d, %04d, %04d, %04d, %04d, %04d, %04d, %04d, %04d, %04d, %04d\n",m_current_energy, m_current_pitch, m_current_k[0], m_current_k[1], m_current_k[2], m_current_k[3], m_current_k[4], m_current_k[5], m_current_k[6], m_current_k[7], m_current_k[8], m_current_k[9]); LOGMASKED(LOG_GENERATION, "*** current Energy, Pitch and Ks = %04d, %04d, %04d, %04d, %04d, %04d, %04d, %04d, %04d, %04d, %04d, %04d\n",m_current_energy, m_current_pitch, m_current_k[0], m_current_k[1], m_current_k[2], m_current_k[3], m_current_k[4], m_current_k[5], m_current_k[6], m_current_k[7], m_current_k[8], m_current_k[9]);
logerror("*** target Energy(idx), Pitch, and Ks = %04d(%x),%04d, %04d, %04d, %04d, %04d, %04d, %04d, %04d, %04d, %04d, %04d\n", LOGMASKED(LOG_GENERATION, "*** target Energy(idx), Pitch, and Ks = %04d(%x),%04d, %04d, %04d, %04d, %04d, %04d, %04d, %04d, %04d, %04d, %04d\n",
(m_coeff->energytable[m_new_frame_energy_idx] * (1-m_zpar)), (m_coeff->energytable[m_new_frame_energy_idx] * (1-m_zpar)),
m_new_frame_energy_idx, m_new_frame_energy_idx,
(m_coeff->pitchtable[m_new_frame_pitch_idx] * (1-m_zpar)), (m_coeff->pitchtable[m_new_frame_pitch_idx] * (1-m_zpar)),
@ -998,8 +968,6 @@ void tms5220_device::process(int16_t *buffer, unsigned int size)
(m_coeff->ktable[7][m_new_frame_k_idx[7]] * (1-m_uv_zpar)), (m_coeff->ktable[7][m_new_frame_k_idx[7]] * (1-m_uv_zpar)),
(m_coeff->ktable[8][m_new_frame_k_idx[8]] * (1-m_uv_zpar)), (m_coeff->ktable[8][m_new_frame_k_idx[8]] * (1-m_uv_zpar)),
(m_coeff->ktable[9][m_new_frame_k_idx[9]] * (1-m_uv_zpar)) ); (m_coeff->ktable[9][m_new_frame_k_idx[9]] * (1-m_uv_zpar)) );
#endif
} }
else // Not a new frame, just interpolate the existing frame. else // Not a new frame, just interpolate the existing frame.
{ {
@ -1090,20 +1058,20 @@ void tms5220_device::process(int16_t *buffer, unsigned int size)
m_RNG |= bitout; m_RNG |= bitout;
} }
this_sample = lattice_filter(); /* execute lattice filter */ this_sample = lattice_filter(); /* execute lattice filter */
#ifdef DEBUG_GENERATION_VERBOSE
//logerror("C:%01d; ",m_subcycle); //LOGMASKED(LOG_GENERATION_VERBOSE, "C:%01d; ",m_subcycle);
logerror("IP:%01d PC:%02d X:%04d E:%03d P:%03d Pc:%03d ",m_IP, m_PC, m_excitation_data, m_current_energy, m_current_pitch, m_pitch_count); LOGMASKED(LOG_GENERATION_VERBOSE, "IP:%01d PC:%02d X:%04d E:%03d P:%03d Pc:%03d ",m_IP, m_PC, m_excitation_data, m_current_energy, m_current_pitch, m_pitch_count);
//logerror("X:%04d E:%03d P:%03d Pc:%03d ", m_excitation_data, m_current_energy, m_current_pitch, m_pitch_count); //LOGMASKED(LOG_GENERATION_VERBOSE, "X:%04d E:%03d P:%03d Pc:%03d ", m_excitation_data, m_current_energy, m_current_pitch, m_pitch_count);
for (i=0; i<10; i++) for (i=0; i<10; i++)
logerror("K%d:%04d ", i+1, m_current_k[i]); LOGMASKED(LOG_GENERATION_VERBOSE, "K%d:%04d ", i+1, m_current_k[i]);
logerror("Out:%06d ", this_sample); LOGMASKED(LOG_GENERATION_VERBOSE, "Out:%06d ", this_sample);
//#ifdef TMS5220_PERFECT_INTERPOLATION_HACK //#ifdef TMS5220_PERFECT_INTERPOLATION_HACK
// logerror("%d%d%d%d",m_old_zpar,m_zpar,m_old_uv_zpar,m_uv_zpar); // LOGMASKED(LOG_GENERATION_VERBOSE, "%d%d%d%d",m_old_zpar,m_zpar,m_old_uv_zpar,m_uv_zpar);
//#else //#else
// logerror("x%dx%d",m_zpar,m_uv_zpar); // LOGMASKED(LOG_GENERATION_VERBOSE, "x%dx%d",m_zpar,m_uv_zpar);
//#endif //#endif
logerror("\n"); LOGMASKED(LOG_GENERATION_VERBOSE, "\n");
#endif
/* next, force result to 14 bits (since its possible that the addition at the final (k1) stage of the lattice overflowed) */ /* next, force result to 14 bits (since its possible that the addition at the final (k1) stage of the lattice overflowed) */
while (this_sample > 16383) this_sample -= 32768; while (this_sample > 16383) this_sample -= 32768;
while (this_sample < -16384) this_sample += 32768; while (this_sample < -16384) this_sample += 32768;
@ -1146,19 +1114,16 @@ void tms5220_device::process(int16_t *buffer, unsigned int size)
OLD_FRAME_SILENCE_FLAG() = NEW_FRAME_SILENCE_FLAG() ? 1 : 0; // m_OLDE OLD_FRAME_SILENCE_FLAG() = NEW_FRAME_SILENCE_FLAG() ? 1 : 0; // m_OLDE
OLD_FRAME_UNVOICED_FLAG() = NEW_FRAME_UNVOICED_FLAG() ? 1 : 0; // m_OLDP 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. */ /* 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); LOGMASKED(LOG_GENERATION, "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);
#endif
#ifdef DEBUG_GENERATION
if ((!m_TALK) && (!m_SPEN)) if ((!m_TALK) && (!m_SPEN))
logerror("tms5220_process: processing frame: TALKD = 0 caused by stop frame or buffer empty, halting speech.\n"); LOGMASKED(LOG_GENERATION, "tms5220_process: processing frame: TALKD = 0 caused by stop frame or buffer empty, halting speech.\n");
#endif
m_TALKD = m_TALK; // TALKD is latched from TALK m_TALKD = m_TALK; // TALKD is latched from TALK
update_fifo_status_and_ints(); // to trigger an interrupt if TALK_STATUS has changed update_fifo_status_and_ints(); // to trigger an interrupt if TALK_STATUS has changed
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). 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); LOGMASKED(LOG_GENERATION, "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
} }
m_subcycle = m_subc_reload; m_subcycle = m_subc_reload;
m_PC = 0; m_PC = 0;
@ -1208,7 +1173,7 @@ void tms5220_device::process(int16_t *buffer, unsigned int size)
***********************************************************************************************/ ***********************************************************************************************/
static int16_t clip_analog(int16_t cliptemp) int16_t tms5220_device::clip_analog(int16_t cliptemp) const
{ {
/* clipping, just like the patent shows: /* clipping, just like the patent shows:
* the top 10 bits of this result are visible on the digital output IO pin. * the top 10 bits of this result are visible on the digital output IO pin.
@ -1218,9 +1183,8 @@ static int16_t clip_analog(int16_t cliptemp)
* 00 0bcd efgh xxxx -> 0b0bcdefgh * 00 0bcd efgh xxxx -> 0b0bcdefgh
* 0x xxxx xxxx xxxx -> 0b01111111 * 0x xxxx xxxx xxxx -> 0b01111111
*/ */
#ifdef DEBUG_CLIP if ((cliptemp > 2047) || (cliptemp < -2048))
if ((cliptemp > 2047) || (cliptemp < -2048)) logerror("clipping cliptemp to range; was %d\n", cliptemp); LOGMASKED(LOG_CLIP, "clipping cliptemp to range; was %d\n", cliptemp);
#endif
if (cliptemp > 2047) cliptemp = 2047; if (cliptemp > 2047) cliptemp = 2047;
else if (cliptemp < -2048) cliptemp = -2048; else if (cliptemp < -2048) cliptemp = -2048;
/* at this point the analog output is tapped */ /* at this point the analog output is tapped */
@ -1250,7 +1214,7 @@ static int16_t clip_analog(int16_t cliptemp)
output, this makes almost no difference in the computation. output, this makes almost no difference in the computation.
**********************************************************************************************/ **********************************************************************************************/
static int32_t matrix_multiply(int32_t a, int32_t b) int32_t tms5220_device::matrix_multiply(int32_t a, int32_t b) const
{ {
int32_t result; int32_t result;
while (a>511) { a-=1024; } while (a>511) { a-=1024; }
@ -1258,10 +1222,8 @@ static int32_t matrix_multiply(int32_t a, int32_t b)
while (b>16383) { b-=32768; } while (b>16383) { b-=32768; }
while (b<-16384) { b+=32768; } while (b<-16384) { b+=32768; }
result = ((a*b)>>9); /** TODO: this isn't technically right to the chip, which truncates the lowest result bit, but it causes glitches otherwise. **/ result = ((a*b)>>9); /** TODO: this isn't technically right to the chip, which truncates the lowest result bit, but it causes glitches otherwise. **/
#ifdef VERBOSE if (result>16383) LOGMASKED(LOG_GENERAL, "matrix multiplier overflowed! a: %x, b: %x, result: %x", a, b, result);
if (result>16383) logerror("matrix multiplier overflowed! a: %x, b: %x, result: %x", a, b, result); if (result<-16384) LOGMASKED(LOG_GENERAL, "matrix multiplier underflowed! a: %x, b: %x, result: %x", a, b, result);
if (result<-16384) logerror("matrix multiplier underflowed! a: %x, b: %x, result: %x", a, b, result);
#endif
return result; return result;
} }
@ -1307,9 +1269,7 @@ int32_t tms5220_device::lattice_filter()
m_u[2] = m_u[3] - matrix_multiply(m_current_k[2], m_x[2]); m_u[2] = m_u[3] - matrix_multiply(m_current_k[2], m_x[2]);
m_u[1] = m_u[2] - matrix_multiply(m_current_k[1], m_x[1]); m_u[1] = m_u[2] - matrix_multiply(m_current_k[1], m_x[1]);
m_u[0] = m_u[1] - matrix_multiply(m_current_k[0], m_x[0]); m_u[0] = m_u[1] - matrix_multiply(m_current_k[0], m_x[0]);
#ifdef DEBUG_LATTICE
int32_t err = m_x[9] + matrix_multiply(m_current_k[9], m_u[9]); //x_10, real chip doesn't use or calculate this int32_t err = m_x[9] + matrix_multiply(m_current_k[9], m_u[9]); //x_10, real chip doesn't use or calculate this
#endif
m_x[9] = m_x[8] + matrix_multiply(m_current_k[8], m_u[8]); m_x[9] = m_x[8] + matrix_multiply(m_current_k[8], m_u[8]);
m_x[8] = m_x[7] + matrix_multiply(m_current_k[7], m_u[7]); m_x[8] = m_x[7] + matrix_multiply(m_current_k[7], m_u[7]);
m_x[7] = m_x[6] + matrix_multiply(m_current_k[6], m_u[6]); m_x[7] = m_x[6] + matrix_multiply(m_current_k[6], m_u[6]);
@ -1321,21 +1281,20 @@ int32_t tms5220_device::lattice_filter()
m_x[1] = m_x[0] + matrix_multiply(m_current_k[0], m_u[0]); m_x[1] = m_x[0] + matrix_multiply(m_current_k[0], m_u[0]);
m_x[0] = m_u[0]; m_x[0] = m_u[0];
m_previous_energy = m_current_energy; m_previous_energy = m_current_energy;
#ifdef DEBUG_LATTICE
int i; LOGMASKED(LOG_LATTICE, "V:%04d ", m_u[10]);
logerror("V:%04d ", m_u[10]); for (int i = 9; i >= 0; i--)
for (i = 9; i >= 0; i--)
{ {
logerror("Y%d:%04d ", i+1, m_u[i]); LOGMASKED(LOG_LATTICE, "Y%d:%04d ", i+1, m_u[i]);
} }
logerror("\n"); LOGMASKED(LOG_LATTICE, "\n");
logerror("E:%04d ", err); LOGMASKED(LOG_LATTICE, "E:%04d ", err);
for (i = 9; i >= 0; i--) for (int i = 9; i >= 0; i--)
{ {
logerror("b%d:%04d ", i+1, m_x[i]); LOGMASKED(LOG_LATTICE, "b%d:%04d ", i+1, m_x[i]);
} }
logerror("\n"); LOGMASKED(LOG_LATTICE, "\n");
#endif
return m_u[0]; return m_u[0];
} }
@ -1348,16 +1307,15 @@ int32_t tms5220_device::lattice_filter()
void tms5220_device::process_command(unsigned char cmd) void tms5220_device::process_command(unsigned char cmd)
{ {
int i; LOGMASKED(LOG_COMMAND_DUMP, "process_command called with parameter %02X\n", cmd);
#ifdef DEBUG_COMMAND_DUMP
logerror("process_command called with parameter %02X\n",cmd);
#endif
/* parse the command */ /* parse the command */
switch (cmd & 0x70) switch (cmd & 0x70)
{ {
case 0x10 : /* read byte */ case 0x10 : /* read byte */
if (TALK_STATUS() == 0) /* TALKST must be clear for RDBY */ if (TALK_STATUS() == 0) /* TALKST must be clear for RDBY */
{ {
LOGMASKED(LOG_COMMAND_VERBOSE, "Read Byte command received\n");
if (m_schedule_dummy_read) if (m_schedule_dummy_read)
{ {
m_schedule_dummy_read = false; m_schedule_dummy_read = false;
@ -1368,39 +1326,49 @@ void tms5220_device::process_command(unsigned char cmd)
m_data_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; m_RDB_flag = true;
} }
else
LOGMASKED(LOG_COMMAND_VERBOSE, "Read Byte command received during TALK state, ignoring!\n");
break; break;
case 0x00: case 0x20: /* set rate (tms5220c and cd2501ecd only), otherwise NOP */ case 0x00: case 0x20: /* set rate (tms5220c and cd2501ecd only), otherwise NOP */
if (TMS5220_HAS_RATE_CONTROL) if (TMS5220_HAS_RATE_CONTROL)
{ {
LOGMASKED(LOG_COMMAND_VERBOSE, "Set Rate command received\n");
m_c_variant_rate = cmd&0x0F; m_c_variant_rate = cmd&0x0F;
} }
else
LOGMASKED(LOG_COMMAND_VERBOSE, "NOP command received\n");
break; break;
case 0x30 : /* read and branch */ case 0x30 : /* read and branch */
if (TALK_STATUS() == 0) /* TALKST must be clear for RB */ if (TALK_STATUS() == 0) /* TALKST must be clear for RB */
{ {
#ifdef VERBOSE LOGMASKED(LOG_COMMAND_VERBOSE, "Read and Branch command received\n");
logerror("read and branch command received\n");
#endif
m_RDB_flag = false; m_RDB_flag = false;
if (m_speechrom) if (m_speechrom)
m_speechrom->read_and_branch(); m_speechrom->read_and_branch();
} }
else
LOGMASKED(LOG_COMMAND_VERBOSE, "Read and Branch command received during TALK state, ignoring!\n");
break; break;
case 0x40 : /* load address */ case 0x40 : /* load address */
if (TALK_STATUS() == 0) /* TALKST must be clear for LA */ if (TALK_STATUS() == 0) /* TALKST must be clear for LA */
{ {
LOGMASKED(LOG_COMMAND_VERBOSE, "Load Address command received\n");
/* tms5220 data sheet says that if we load only one 4-bit nibble, it won't work. /* tms5220 data sheet says that if we load only one 4-bit nibble, it won't work.
This code does not care about this. */ This code does not care about this. */
if (m_speechrom) if (m_speechrom)
m_speechrom->load_address(cmd & 0x0f); m_speechrom->load_address(cmd & 0x0f);
m_schedule_dummy_read = true; m_schedule_dummy_read = true;
} }
else
LOGMASKED(LOG_COMMAND_VERBOSE, "Load Address command received during TALK state, ignoring!\n");
break; break;
case 0x50 : /* speak */ case 0x50 : /* speak */
LOGMASKED(LOG_COMMAND_VERBOSE, "Speak (VSM) command received\n");
if (m_schedule_dummy_read) if (m_schedule_dummy_read)
{ {
m_schedule_dummy_read = false; m_schedule_dummy_read = false;
@ -1423,15 +1391,17 @@ void tms5220_device::process_command(unsigned char cmd)
// following is semi-hack but matches idle state observed on chip // following is semi-hack but matches idle state observed on chip
m_new_frame_energy_idx = 0; m_new_frame_energy_idx = 0;
m_new_frame_pitch_idx = 0; m_new_frame_pitch_idx = 0;
for (i = 0; i < 4; i++) for (int i = 0; i < 4; i++)
m_new_frame_k_idx[i] = 0; m_new_frame_k_idx[i] = 0;
for (i = 4; i < 7; i++) for (int i = 4; i < 7; i++)
m_new_frame_k_idx[i] = 0xF; m_new_frame_k_idx[i] = 0xF;
for (i = 7; i < m_coeff->num_k; i++) for (int i = 7; i < m_coeff->num_k; i++)
m_new_frame_k_idx[i] = 0x7; m_new_frame_k_idx[i] = 0x7;
break; break;
case 0x60 : /* speak external */ case 0x60 : /* speak external */
LOGMASKED(LOG_COMMAND_VERBOSE, "Speak External command received\n");
// SPKEXT going active activates SPKEE which clears the fifo // SPKEXT going active activates SPKEE which clears the fifo
m_fifo_head = m_fifo_tail = m_fifo_count = m_fifo_bits_taken = 0; 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) // SPEN is enabled when the fifo passes half full (falling edge of BL signal)
@ -1447,16 +1417,17 @@ void tms5220_device::process_command(unsigned char cmd)
// following is semi-hack but matches idle state observed on chip // following is semi-hack but matches idle state observed on chip
m_new_frame_energy_idx = 0; m_new_frame_energy_idx = 0;
m_new_frame_pitch_idx = 0; m_new_frame_pitch_idx = 0;
for (i = 0; i < 4; i++) for (int i = 0; i < 4; i++)
m_new_frame_k_idx[i] = 0; m_new_frame_k_idx[i] = 0;
for (i = 4; i < 7; i++) for (int i = 4; i < 7; i++)
m_new_frame_k_idx[i] = 0xF; m_new_frame_k_idx[i] = 0xF;
for (i = 7; i < m_coeff->num_k; i++) for (int i = 7; i < m_coeff->num_k; i++)
m_new_frame_k_idx[i] = 0x7; m_new_frame_k_idx[i] = 0x7;
m_RDB_flag = false; m_RDB_flag = false;
break; break;
case 0x70 : /* reset */ case 0x70 : /* reset */
LOGMASKED(LOG_COMMAND_VERBOSE, "Reset command received\n");
if (m_schedule_dummy_read) if (m_schedule_dummy_read)
{ {
m_schedule_dummy_read = false; m_schedule_dummy_read = false;
@ -1495,10 +1466,8 @@ void tms5220_device::parse_frame()
if ((TMS5220_HAS_RATE_CONTROL) && (m_c_variant_rate & 0x04)) if ((TMS5220_HAS_RATE_CONTROL) && (m_c_variant_rate & 0x04))
{ {
i = extract_bits(2); i = extract_bits(2);
#ifdef DEBUG_PARSE_FRAME_DUMP
printbits(i, 2); printbits(i, 2);
logerror(" "); LOGMASKED(LOG_PARSE_FRAME_DUMP_BIN | LOG_PARSE_FRAME_DUMP_HEX, " ");
#endif
m_IP = reload_table[i]; m_IP = reload_table[i];
} }
else // non-5220C and 5220C in fixed rate mode else // non-5220C and 5220C in fixed rate mode
@ -1509,10 +1478,8 @@ void tms5220_device::parse_frame()
// attempt to extract the energy index // attempt to extract the energy index
m_new_frame_energy_idx = extract_bits(m_coeff->energy_bits); m_new_frame_energy_idx = extract_bits(m_coeff->energy_bits);
#ifdef DEBUG_PARSE_FRAME_DUMP
printbits(m_new_frame_energy_idx, m_coeff->energy_bits); printbits(m_new_frame_energy_idx, m_coeff->energy_bits);
logerror(" "); LOGMASKED(LOG_PARSE_FRAME_DUMP_BIN | LOG_PARSE_FRAME_DUMP_HEX, " ");
#endif
update_fifo_status_and_ints(); update_fifo_status_and_ints();
if (m_DDIS && m_buffer_empty) goto ranout; if (m_DDIS && m_buffer_empty) goto ranout;
// if the energy index is 0 or 15, we're done // if the energy index is 0 or 15, we're done
@ -1522,17 +1489,13 @@ void tms5220_device::parse_frame()
// attempt to extract the repeat flag // attempt to extract the repeat flag
rep_flag = extract_bits(1); rep_flag = extract_bits(1);
#ifdef DEBUG_PARSE_FRAME_DUMP
printbits(rep_flag, 1); printbits(rep_flag, 1);
logerror(" "); LOGMASKED(LOG_PARSE_FRAME_DUMP_BIN | LOG_PARSE_FRAME_DUMP_HEX, " ");
#endif
// attempt to extract the pitch // attempt to extract the pitch
m_new_frame_pitch_idx = extract_bits(m_coeff->pitch_bits); m_new_frame_pitch_idx = extract_bits(m_coeff->pitch_bits);
#ifdef DEBUG_PARSE_FRAME_DUMP
printbits(m_new_frame_pitch_idx, m_coeff->pitch_bits); printbits(m_new_frame_pitch_idx, m_coeff->pitch_bits);
logerror(" "); LOGMASKED(LOG_PARSE_FRAME_DUMP_BIN | LOG_PARSE_FRAME_DUMP_HEX, " ");
#endif
// if the new frame is unvoiced, be sure to zero out the k5-k10 parameters // if the new frame is unvoiced, be sure to zero out the k5-k10 parameters
m_uv_zpar = NEW_FRAME_UNVOICED_FLAG() ? 1 : 0; m_uv_zpar = NEW_FRAME_UNVOICED_FLAG() ? 1 : 0;
update_fifo_status_and_ints(); update_fifo_status_and_ints();
@ -1545,10 +1508,8 @@ void tms5220_device::parse_frame()
for (i = 0; i < 4; i++) for (i = 0; i < 4; i++)
{ {
m_new_frame_k_idx[i] = extract_bits(m_coeff->kbits[i]); m_new_frame_k_idx[i] = extract_bits(m_coeff->kbits[i]);
#ifdef DEBUG_PARSE_FRAME_DUMP
printbits(m_new_frame_k_idx[i], m_coeff->kbits[i]); printbits(m_new_frame_k_idx[i], m_coeff->kbits[i]);
logerror(" "); LOGMASKED(LOG_PARSE_FRAME_DUMP_BIN | LOG_PARSE_FRAME_DUMP_HEX, " ");
#endif
update_fifo_status_and_ints(); update_fifo_status_and_ints();
if (m_DDIS && m_buffer_empty) goto ranout; if (m_DDIS && m_buffer_empty) goto ranout;
} }
@ -1564,28 +1525,21 @@ void tms5220_device::parse_frame()
for (i = 4; i < m_coeff->num_k; i++) for (i = 4; i < m_coeff->num_k; i++)
{ {
m_new_frame_k_idx[i] = extract_bits(m_coeff->kbits[i]); m_new_frame_k_idx[i] = extract_bits(m_coeff->kbits[i]);
#ifdef DEBUG_PARSE_FRAME_DUMP
printbits(m_new_frame_k_idx[i], m_coeff->kbits[i]); printbits(m_new_frame_k_idx[i], m_coeff->kbits[i]);
logerror(" "); LOGMASKED(LOG_PARSE_FRAME_DUMP_BIN | LOG_PARSE_FRAME_DUMP_HEX, " ");
#endif
update_fifo_status_and_ints(); update_fifo_status_and_ints();
if (m_DDIS && m_buffer_empty) goto ranout; if (m_DDIS && m_buffer_empty) goto ranout;
} }
#ifdef DEBUG_PARSE_FRAME_DUMP LOGMASKED(LOG_PARSE_FRAME_DUMP_BIN | LOG_PARSE_FRAME_DUMP_HEX, "\n");
logerror("\n");
#endif
#ifdef VERBOSE
if (m_DDIS) if (m_DDIS)
logerror("Parsed a frame successfully in FIFO - %d bits remaining\n", (m_fifo_count*8)-(m_fifo_bits_taken)); LOGMASKED(LOG_GENERAL, "Parsed a frame successfully in FIFO - %d bits remaining\n", (m_fifo_count*8)-(m_fifo_bits_taken));
else else
logerror("Parsed a frame successfully in ROM\n"); LOGMASKED(LOG_GENERAL, "Parsed a frame successfully in ROM\n");
#endif
return; return;
ranout: ranout:
#ifdef DEBUG_FRAME_ERRORS LOGMASKED(LOG_FRAME_ERRORS, "Ran out of bits on a parse!\n");
logerror("Ran out of bits on a parse!\n");
#endif
return; return;
} }
@ -1598,9 +1552,9 @@ void tms5220_device::parse_frame()
void tms5220_device::set_interrupt_state(int state) 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 if (!TMS5220_IS_52xx) return; // bail out if not a 52xx chip, since there's no int pin
#ifdef DEBUG_PIN_READS
logerror("irq pin set to state %d\n", state); LOGMASKED(LOG_PIN_READS, "irq pin set to state %d\n", state);
#endif
if (!m_irq_handler.isnull() && state != m_irq_pin) if (!m_irq_handler.isnull() && state != m_irq_pin)
m_irq_handler(!state); m_irq_handler(!state);
m_irq_pin = state; m_irq_pin = state;
@ -1615,9 +1569,9 @@ void tms5220_device::set_interrupt_state(int state)
void tms5220_device::update_ready_state() void tms5220_device::update_ready_state()
{ {
int state = ready_read(); int state = ready_read();
#ifdef DEBUG_PIN_READS
logerror("ready pin set to state %d\n", state); LOGMASKED(LOG_PIN_READS, "ready pin set to state %d\n", state);
#endif
if (!m_readyq_handler.isnull() && state != m_ready_pin) if (!m_readyq_handler.isnull() && state != m_ready_pin)
m_readyq_handler(!state); m_readyq_handler(!state);
m_ready_pin = state; m_ready_pin = state;
@ -1780,10 +1734,8 @@ void tms5220_device::device_timer(emu_timer &timer, device_timer_id id, int para
case 0x02: case 0x02:
/* Write */ /* Write */
/* bring up to date first */ /* bring up to date first */
#ifdef DEBUG_IO_READY LOGMASKED(LOG_IO_READY, "Serviced write: %02x\n", m_write_latch);
logerror("Serviced write: %02x\n", m_write_latch); //LOGMASKED(LOG_IO_READY, "Processed write data: %02X\n", m_write_latch);
//logerror( "Processed write data: %02X\n", m_write_latch);
#endif
m_stream->update(); m_stream->update();
data_write(m_write_latch); data_write(m_write_latch);
break; break;
@ -1792,9 +1744,7 @@ void tms5220_device::device_timer(emu_timer &timer, device_timer_id id, int para
/* bring up to date first */ /* bring up to date first */
m_stream->update(); m_stream->update();
m_read_latch = status_read(); m_read_latch = status_read();
#ifdef DEBUG_IO_READY LOGMASKED(LOG_IO_READY, "Serviced read, returning %02x\n", m_read_latch);
logerror("Serviced read, returning %02x\n", m_read_latch);
#endif
break; break;
case 0x03: case 0x03:
/* High Impedance */ /* High Impedance */
@ -1815,14 +1765,11 @@ void tms5220_device::device_timer(emu_timer &timer, device_timer_id id, int para
*/ */
WRITE_LINE_MEMBER( tms5220_device::rsq_w ) WRITE_LINE_MEMBER( tms5220_device::rsq_w )
{ {
uint8_t new_val;
m_true_timing = 1; m_true_timing = 1;
state &= 0x01; state &= 0x01;
#ifdef DEBUG_RS_WS LOGMASKED(LOG_RS_WS, "/RS written with data: %d\n", state);
logerror("/RS written with data: %d\n", state);
#endif uint8_t new_val = (m_rs_ws & 0x01) | (state<<1);
new_val = (m_rs_ws & 0x01) | (state<<1);
if (new_val != m_rs_ws) if (new_val != m_rs_ws)
{ {
m_rs_ws = new_val; m_rs_ws = new_val;
@ -1830,11 +1777,9 @@ WRITE_LINE_MEMBER( tms5220_device::rsq_w )
{ {
if (TMS5220_HAS_RATE_CONTROL) // correct for 5220c, ? for cd2501ecd if (TMS5220_HAS_RATE_CONTROL) // correct for 5220c, ? for cd2501ecd
reset(); reset();
#ifdef DEBUG_RS_WS
else else
/* illegal */ /* illegal */
logerror("tms5220_rsq_w: illegal\n"); LOGMASKED(LOG_RS_WS, "tms5220_rsq_w: illegal\n");
#endif
return; return;
} }
else if ( new_val == 3) else if ( new_val == 3)
@ -1850,9 +1795,7 @@ WRITE_LINE_MEMBER( tms5220_device::rsq_w )
else else
{ {
/* high to low - schedule ready cycle */ /* high to low - schedule ready cycle */
#ifdef DEBUG_RS_WS LOGMASKED(LOG_RS_WS, "Scheduling ready cycle for /RS...\n");
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. */ /* 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 = 0; m_io_ready = 0;
update_ready_state(); update_ready_state();
@ -1867,14 +1810,11 @@ WRITE_LINE_MEMBER( tms5220_device::rsq_w )
*/ */
WRITE_LINE_MEMBER( tms5220_device::wsq_w ) WRITE_LINE_MEMBER( tms5220_device::wsq_w )
{ {
uint8_t new_val;
m_true_timing = 1; m_true_timing = 1;
state &= 0x01; state &= 0x01;
#ifdef DEBUG_RS_WS LOGMASKED(LOG_RS_WS, "/WS written with data: %d\n", state);
logerror("/WS written with data: %d\n", state);
#endif uint8_t new_val = (m_rs_ws & 0x02) | (state<<0);
new_val = (m_rs_ws & 0x02) | (state<<0);
if (new_val != m_rs_ws) if (new_val != m_rs_ws)
{ {
m_rs_ws = new_val; m_rs_ws = new_val;
@ -1882,11 +1822,9 @@ WRITE_LINE_MEMBER( tms5220_device::wsq_w )
{ {
if (TMS5220_HAS_RATE_CONTROL) // correct for 5220c, probably also correct for cd2501ecd if (TMS5220_HAS_RATE_CONTROL) // correct for 5220c, probably also correct for cd2501ecd
reset(); reset();
#ifdef DEBUG_RS_WS
else else
/* illegal */ /* illegal */
logerror("tms5220_wsq_w: illegal\n"); LOGMASKED(LOG_RS_WS, "tms5220_wsq_w: illegal\n");
#endif
return; return;
} }
else if ( new_val == 3) else if ( new_val == 3)
@ -1902,9 +1840,8 @@ WRITE_LINE_MEMBER( tms5220_device::wsq_w )
else else
{ {
/* high to low - schedule ready cycle */ /* high to low - schedule ready cycle */
#ifdef DEBUG_RS_WS LOGMASKED(LOG_RS_WS, "Scheduling ready cycle for /WS...\n");
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. */ /* 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 = 0; m_io_ready = 0;
update_ready_state(); update_ready_state();
@ -1931,13 +1868,11 @@ WRITE_LINE_MEMBER( tms5220_device::wsq_w )
*/ */
WRITE8_MEMBER( tms5220_device::combined_rsq_wsq_w ) WRITE8_MEMBER( tms5220_device::combined_rsq_wsq_w )
{ {
uint8_t new_val;
uint8_t falling_edges; uint8_t falling_edges;
m_true_timing = 1; m_true_timing = 1;
#ifdef DEBUG_RS_WS LOGMASKED(LOG_RS_WS, "/RS and /WS written with %d and %d respectively\n", (data&2)>>1, data&1);
logerror("/RS and /WS written with %d and %d respectively\n", (data&2)>>1, data&1);
#endif uint8_t new_val = data & 0x03;
new_val = data&0x03;
if (new_val != m_rs_ws) if (new_val != m_rs_ws)
{ {
falling_edges = ((m_rs_ws^new_val)&(~new_val)); falling_edges = ((m_rs_ws^new_val)&(~new_val));
@ -1947,11 +1882,9 @@ WRITE8_MEMBER( tms5220_device::combined_rsq_wsq_w )
case 0: case 0:
if (TMS5220_HAS_RATE_CONTROL) // correct for 5220c, probably also correct for cd2501ecd if (TMS5220_HAS_RATE_CONTROL) // correct for 5220c, probably also correct for cd2501ecd
reset(); reset();
#ifdef DEBUG_RS_WS
else else
/* illegal */ /* illegal */
logerror("tms5220_combined_rsq_wsq_w: illegal\n"); LOGMASKED(LOG_RS_WS, "tms5220_combined_rsq_wsq_w: illegal\n");
#endif
return; return;
case 3: case 3:
/* high impedance */ /* high impedance */
@ -1960,13 +1893,14 @@ WRITE8_MEMBER( tms5220_device::combined_rsq_wsq_w )
case 2: // /WS active, /RS not case 2: // /WS active, /RS not
/* check for falling or rising edge */ /* check for falling or rising edge */
if (!(falling_edges&0x01)) return; /* low to high, do nothing */ if (!(falling_edges&0x01)) return; /* low to high, do nothing */
/* high to low - schedule ready cycle */ /* high to low - schedule ready cycle */
#ifdef DEBUG_RS_WS LOGMASKED(LOG_RS_WS, "Scheduling ready cycle for /WS...\n");
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. */ /* 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 = 0; m_io_ready = 0;
update_ready_state(); 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... /* 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 Speak external mode: ~16 cycles
Command Mode: Command Mode:
@ -1983,13 +1917,14 @@ WRITE8_MEMBER( tms5220_device::combined_rsq_wsq_w )
case 1: // /RS active, /WS not case 1: // /RS active, /WS not
/* check for falling or rising edge */ /* check for falling or rising edge */
if (!(falling_edges&0x02)) return; /* low to high, do nothing */ if (!(falling_edges&0x02)) return; /* low to high, do nothing */
/* high to low - schedule ready cycle */ /* high to low - schedule ready cycle */
#ifdef DEBUG_RS_WS LOGMASKED(LOG_RS_WS, "Scheduling ready cycle for /RS...\n");
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. */ /* 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 = 0; m_io_ready = 0;
update_ready_state(); 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) */ /* 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 m_timer_io_ready->adjust(clocks_to_attotime(16), 1); // this should take around 10-16 (closer to ~11?) cycles to complete
return; return;
@ -2009,9 +1944,8 @@ void tms5220_device::write_data(uint8_t data)
// prevent debugger from changing the internal state // prevent debugger from changing the internal state
if (machine().side_effects_disabled()) return; if (machine().side_effects_disabled()) return;
#ifdef DEBUG_RS_WS LOGMASKED(LOG_RS_WS, "tms5220_data_w: data %02x\n", data);
logerror("tms5220_data_w: data %02x\n", data);
#endif
if (!m_true_timing) if (!m_true_timing)
{ {
/* bring up to date first */ /* bring up to date first */
@ -2021,10 +1955,8 @@ void tms5220_device::write_data(uint8_t data)
else else
{ {
/* actually in a write ? */ /* actually in a write ? */
#ifdef DEBUG_RS_WS
if (!(m_rs_ws == 0x02)) if (!(m_rs_ws == 0x02))
logerror("tms5220_data_w: data written outside ws, status: %02x!\n", m_rs_ws); LOGMASKED(LOG_RS_WS, "tms5220_data_w: data written outside ws, status: %02x!\n", m_rs_ws);
#endif
m_write_latch = data; m_write_latch = data;
} }
} }
@ -2053,10 +1985,8 @@ uint8_t tms5220_device::read_status()
/* actually in a read ? */ /* actually in a read ? */
if (m_rs_ws == 0x01) if (m_rs_ws == 0x01)
return m_read_latch; return m_read_latch;
#ifdef DEBUG_RS_WS
else else
logerror("tms5220_status_r: data read outside rs!\n"); LOGMASKED(LOG_RS_WS, "tms5220_status_r: data read outside rs!\n");
#endif
return 0xff; return 0xff;
} }
} }

View File

@ -123,6 +123,8 @@ private:
int cycles_to_ready(); int cycles_to_ready();
int int_read(); int int_read();
void process(int16_t *buffer, unsigned int size); void process(int16_t *buffer, unsigned int size);
int16_t clip_analog(int16_t cliptemp) const;
int32_t matrix_multiply(int32_t a, int32_t b) const;
int32_t lattice_filter(); int32_t lattice_filter();
void process_command(unsigned char cmd); void process_command(unsigned char cmd);
void parse_frame(); void parse_frame();
@ -136,6 +138,9 @@ private:
bool NEW_FRAME_SILENCE_FLAG() const { return m_new_frame_energy_idx == 0; } // ditto as above 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 bool NEW_FRAME_UNVOICED_FLAG() const { return m_new_frame_pitch_idx == 0; } // ditto as above
// debugging helper
void printbits(long data, int num);
// internal state // internal state
/* coefficient tables */ /* coefficient tables */