diff options
Diffstat (limited to 'src/devices/sound/tms5110.cpp')
-rw-r--r-- | src/devices/sound/tms5110.cpp | 178 |
1 files changed, 69 insertions, 109 deletions
diff --git a/src/devices/sound/tms5110.cpp b/src/devices/sound/tms5110.cpp index b7bef7f741e..e2d77d130fc 100644 --- a/src/devices/sound/tms5110.cpp +++ b/src/devices/sound/tms5110.cpp @@ -149,13 +149,10 @@ static int16_t clip_analog(int16_t cliptemp); void tms5110_device::new_int_write(uint8_t rc, uint8_t m0, uint8_t m1, uint8_t addr) { - if (!m_m0_cb.isnull()) - m_m0_cb(m0); - if (!m_m1_cb.isnull()) - m_m1_cb(m1); - if (!m_addr_cb.isnull()) - m_addr_cb((offs_t)0, addr); - if (!m_romclk_cb.isnull()) + m_m0_cb(m0); + m_m1_cb(m1); + m_addr_cb(offs_t(0), addr); + if (!m_romclk_cb.isunset()) { //printf("rc %d\n", rc); m_romclk_cb(rc); @@ -176,7 +173,7 @@ uint8_t tms5110_device::new_int_read() new_int_write(0, 1, 0, 0); // romclk 0, m0 1, m1 0, addr bus nybble = 0/open bus new_int_write(1, 0, 0, 0); // romclk 1, 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.isunset()) return m_data_cb(); if (DEBUG_5110) logerror("WARNING: CALLBACK MISSING, RETURNING 0!\n"); return 0; @@ -240,6 +237,7 @@ void tms5110_device::register_for_save_states() save_item(NAME(m_romclk_hack_state)); } + /********************************************************************************************** printbits helper function: takes a long int input and prints the resulting bits to stderr @@ -280,11 +278,11 @@ static void printbits(long data, int num) /****************************************************************************************** - extract_bits -- extract a specific number of bits from the VSM + read_bits -- read a specific number of bits from the VSM ******************************************************************************************/ -int tms5110_device::extract_bits(int count) +int tms5110_device::read_bits(int count) { int val = 0; if (DEBUG_5110) logerror("requesting %d bits", count); @@ -310,7 +308,6 @@ void tms5110_device::perform_dummy_read() - /********************************************************************************************** tms5110_process -- fill the buffer with a specific number of samples @@ -588,6 +585,7 @@ void tms5110_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 @@ -598,7 +596,8 @@ static int16_t clip_analog(int16_t cliptemp) { /* clipping, just like the patent shows: * the top 10 bits of this result are visible on the digital output IO pin. - * next, if the top 3 bits of the 14 bit result are all the same, the lowest of those 3 bits plus the next 7 bits are the signed analog output, otherwise the low bits are all forced to match the inverse of the topmost bit, i.e.: + * next, if the top 3 bits of the 14 bit result are all the same, the lowest of those 3 bits plus the next 7 bits are the signed analog output, + * otherwise the low bits are all forced to match the inverse of the topmost bit, i.e.: * 1x xxxx xxxx xxxx -> 0b10000000 * 11 1bcd efgh xxxx -> 0b1bcdefgh * 00 0bcd efgh xxxx -> 0b0bcdefgh @@ -636,6 +635,7 @@ static int16_t clip_analog(int16_t cliptemp) output, this makes almost no difference in the computation. **********************************************************************************************/ + static int32_t matrix_multiply(int32_t a, int32_t b) { int32_t result; @@ -651,6 +651,7 @@ static int32_t matrix_multiply(int32_t a, int32_t b) return result; } + /********************************************************************************************** lattice_filter -- executes one 'full run' of the lattice filter on a specific byte of @@ -727,7 +728,6 @@ int32_t tms5110_device::lattice_filter() - /****************************************************************************************** PDC_set -- set Processor Data Clock. Execute CTL_pins command on hi-lo transition. @@ -849,7 +849,7 @@ void tms5110_device::PDC_set(int data) fprintf(stderr,"actually reading a bit now\n"); #endif m_CTL_buffer >>= 1; - m_CTL_buffer |= (extract_bits(1)<<3); + m_CTL_buffer |= (read_bits(1)<<3); m_CTL_buffer &= 0xF; } break; @@ -927,7 +927,7 @@ void tms5110_device::parse_frame() m_uv_zpar = m_zpar = 0; // attempt to extract the energy index - m_new_frame_energy_idx = extract_bits(m_coeff->energy_bits); + m_new_frame_energy_idx = read_bits(m_coeff->energy_bits); #ifdef DEBUG_PARSE_FRAME_DUMP printbits(m_new_frame_energy_idx,m_coeff->energy_bits); fprintf(stderr," "); @@ -937,13 +937,13 @@ void tms5110_device::parse_frame() if ((m_new_frame_energy_idx == 0) || (m_new_frame_energy_idx == 15)) return; - rep_flag = extract_bits(1); + rep_flag = read_bits(1); #ifdef DEBUG_PARSE_FRAME_DUMP printbits(rep_flag, 1); fprintf(stderr," "); #endif - m_new_frame_pitch_idx = extract_bits(m_coeff->pitch_bits); + m_new_frame_pitch_idx = read_bits(m_coeff->pitch_bits); #ifdef DEBUG_PARSE_FRAME_DUMP printbits(m_new_frame_pitch_idx,m_coeff->pitch_bits); fprintf(stderr," "); @@ -957,7 +957,7 @@ void tms5110_device::parse_frame() // extract first 4 K coefficients for (i = 0; i < 4; i++) { - m_new_frame_k_idx[i] = extract_bits(m_coeff->kbits[i]); + m_new_frame_k_idx[i] = read_bits(m_coeff->kbits[i]); #ifdef DEBUG_PARSE_FRAME_DUMP printbits(m_new_frame_k_idx[i],m_coeff->kbits[i]); fprintf(stderr," "); @@ -974,7 +974,7 @@ void tms5110_device::parse_frame() // If we got here, we need the remaining 6 K's 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] = read_bits(m_coeff->kbits[i]); #ifdef DEBUG_PARSE_FRAME_DUMP printbits(m_new_frame_k_idx[i],m_coeff->kbits[i]); fprintf(stderr," "); @@ -987,29 +987,6 @@ void tms5110_device::parse_frame() } -#if 0 -/*This is an example word TEN taken from the TMS5110A datasheet*/ -static const unsigned int example_word_TEN[619]={ -/* 1*/1,0,0,0, 0, 0,0,0,0,0, 1,1,0,0,0, 0,0,0,1,0, 0,1,1,1, 0,1,0,1, -/* 2*/1,0,0,0, 0, 0,0,0,0,0, 1,0,0,1,0, 0,0,1,1,0, 0,0,1,1, 0,1,0,1, -/* 3*/1,1,0,0, 0, 1,0,0,0,0, 1,0,1,0,0, 0,1,0,1,0, 0,1,0,0, 1,0,1,0, 1,0,0,0, 1,0,0,1, 0,1,0,1, 0,0,1, 0,1,0, 0,1,1, -/* 4*/1,1,1,0, 0, 0,1,1,1,1, 1,0,1,0,1, 0,1,1,1,0, 0,1,0,1, 0,1,1,1, 0,1,1,1, 1,0,1,1, 1,0,1,0, 0,1,1, 0,1,0, 0,1,1, -/* 5*/1,1,1,0, 0, 1,0,0,0,0, 1,0,1,0,0, 0,1,1,1,0, 0,1,0,1, 1,0,1,0, 1,0,0,0, 1,1,0,0, 1,0,1,1, 1,0,0, 0,1,0, 0,1,1, -/* 6*/1,1,1,0, 0, 1,0,0,0,1, 1,0,1,0,1, 0,1,1,0,1, 0,1,1,0, 0,1,1,1, 0,1,1,1, 1,0,1,0, 1,0,1,0, 1,1,0, 0,0,1, 1,0,0, -/* 7*/1,1,1,0, 0, 1,0,0,1,0, 1,0,1,1,1, 0,1,1,1,0, 0,1,1,1, 0,1,1,1, 0,1,0,1, 0,1,1,0, 1,0,0,1, 1,1,0, 0,1,0, 0,1,1, -/* 8*/1,1,1,0, 1, 1,0,1,0,1, -/* 9*/1,1,1,0, 0, 1,1,0,0,1, 1,0,1,1,1, 0,1,0,1,1, 1,0,1,1, 0,1,1,1, 0,1,0,0, 1,0,0,0, 1,0,0,0, 1,1,0, 0,1,1, 0,1,1, -/*10*/1,1,0,1, 0, 1,1,0,1,0, 1,0,1,0,1, 0,1,1,0,1, 1,0,1,1, 0,1,0,1, 0,1,0,0, 1,0,0,0, 1,0,1,0, 1,1,0, 0,1,0, 1,0,0, -/*11*/1,0,1,1, 0, 1,1,0,1,1, 1,0,0,1,1, 1,0,0,1,0, 0,1,1,0, 0,0,1,1, 0,1,0,1, 1,0,0,1, 1,0,1,0, 1,0,0, 0,1,1, 0,1,1, -/*12*/1,0,0,0, 0, 1,1,1,0,0, 1,0,0,1,1, 0,0,1,1,0, 0,1,0,0, 0,1,1,0, 1,1,0,0, 0,1,0,1, 1,0,0,0, 1,0,0, 0,1,0, 1,0,1, -/*13*/0,1,1,1, 1, 1,1,1,0,1, -/*14*/0,1,1,1, 0, 1,1,1,1,0, 1,0,0,1,1, 0,0,1,1,1, 0,1,0,1, 0,1,0,1, 1,1,0,0, 0,1,1,1, 1,0,0,0, 1,0,0, 0,1,0, 1,0,1, -/*15*/0,1,1,0, 0, 1,1,1,1,0, 1,0,1,0,1, 0,0,1,1,0, 0,1,0,0, 0,0,1,1, 1,1,0,0, 1,0,0,1, 0,1,1,1, 1,0,1, 0,1,0, 1,0,1, -/*16*/1,1,1,1 -}; -#endif - - //------------------------------------------------- // device_start - device-specific startup //------------------------------------------------- @@ -1040,18 +1017,11 @@ void tms5110_device::device_start() fatalerror("Unknown variant in tms5110_create\n"); } - /* resolve lines */ - m_m0_cb.resolve(); - m_m1_cb.resolve(); - m_romclk_cb.resolve(); - m_addr_cb.resolve(); - m_data_cb.resolve(); - /* initialize a stream */ - m_stream = machine().sound().stream_alloc(*this, 0, 1, clock() / 80); + m_stream = stream_alloc(0, 1, clock() / 80); m_state = CTL_STATE_INPUT; /* most probably not defined */ - m_romclk_hack_timer = timer_alloc(0); + m_romclk_hack_timer = timer_alloc(FUNC(tms5110_device::romclk_hack_toggle), this); register_for_save_states(); } @@ -1108,6 +1078,10 @@ void tms5110_device::device_reset() m_next_is_address = false; m_address = 0; m_addr_bit = 0; + + m_romclk_hack_timer->adjust(attotime::never); + m_romclk_hack_timer_started = false; + m_romclk_hack_state = false; } @@ -1115,11 +1089,12 @@ void tms5110_device::device_reset() /****************************************************************************** tms5110_ctl_w -- write Control Command to the sound chip -commands like Speech, Reset, etc., are loaded into the chip via the CTL pins + + commands like Speech, Reset, etc., are loaded into the chip via the CTL pins ******************************************************************************/ -WRITE8_MEMBER( tms5110_device::ctl_w ) +void tms5110_device::ctl_w(uint8_t data) { /* bring up to date first */ m_stream->update(); @@ -1133,7 +1108,7 @@ WRITE8_MEMBER( tms5110_device::ctl_w ) ******************************************************************************/ -WRITE_LINE_MEMBER( tms5110_device::pdc_w ) +void tms5110_device::pdc_w(int state) { /* bring up to date first */ m_stream->update(); @@ -1159,7 +1134,7 @@ WRITE_LINE_MEMBER( tms5110_device::pdc_w ) ******************************************************************************/ -READ8_MEMBER( tms5110_device::ctl_r ) +uint8_t tms5110_device::ctl_r() { /* bring up to date first */ m_stream->update(); @@ -1180,25 +1155,23 @@ READ8_MEMBER( tms5110_device::ctl_r ) } } -READ8_MEMBER( m58817_device::status_r ) +uint8_t m58817_device::status_r() { /* bring up to date first */ m_stream->update(); - return (TALK_STATUS() << 0); /*CTL1 = still talking ? */ + return (TALK_STATUS() << 0); /* CTL1 = still talking ? */ } -/****************************************************************************** - - tms5110_romclk_hack_r -- read status of romclk - -******************************************************************************/ - -void tms5110_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) +TIMER_CALLBACK_MEMBER(tms5110_device::romclk_hack_toggle) { m_romclk_hack_state = !m_romclk_hack_state; } -READ_LINE_MEMBER( tms5110_device::romclk_hack_r ) +//------------------------------------------------- +// romclk_hack_r - read status of romclk +//------------------------------------------------- + +int tms5110_device::romclk_hack_r() { /* bring up to date first */ m_stream->update(); @@ -1215,32 +1188,25 @@ READ_LINE_MEMBER( tms5110_device::romclk_hack_r ) /****************************************************************************** - tms5110_update -- update the sound chip so that it is in sync with CPU execution + sound_stream_update -- update the sound chip so that it is in sync with CPU execution ******************************************************************************/ -//------------------------------------------------- -// sound_stream_update - handle a stream update -//------------------------------------------------- - -void tms5110_device::sound_stream_update(sound_stream &stream, stream_sample_t **inputs, stream_sample_t **outputs, int samples) +void tms5110_device::sound_stream_update(sound_stream &stream) { int16_t sample_data[MAX_SAMPLE_CHUNK]; - stream_sample_t *buffer = outputs[0]; /* loop while we still have samples to generate */ - while (samples) + for (int sampindex = 0; sampindex < stream.samples(); ) { - int length = (samples > MAX_SAMPLE_CHUNK) ? MAX_SAMPLE_CHUNK : samples; - int index; + int length = stream.samples() - sampindex; + if (length > MAX_SAMPLE_CHUNK) + length = MAX_SAMPLE_CHUNK; /* generate the samples and copy to the target buffer */ process(sample_data, length); - for (index = 0; index < length; index++) - *buffer++ = sample_data[index]; - - /* account for the samples */ - samples -= length; + for (int index = 0; index < length; index++) + stream.put_int(0, sampindex++, sample_data[index], 32768); } } @@ -1248,7 +1214,7 @@ void tms5110_device::sound_stream_update(sound_stream &stream, stream_sample_t * /****************************************************************************** - tms5110_set_frequency -- adjusts the playback frequency + device_clock_changed -- adjusts the playback frequency ******************************************************************************/ @@ -1324,7 +1290,7 @@ void tmsprom_device::update_prom_cnt() m_prom_cnt &= 0x0f; } -void tmsprom_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) +TIMER_CALLBACK_MEMBER(tmsprom_device::update_romclk) { /* only 16 bytes needed ... The original dump is bad. This * is what is needed to get speech to work. The prom data has @@ -1334,10 +1300,8 @@ void tmsprom_device::device_timer(emu_timer &timer, device_timer_id id, int para * static const int prom[16] = {0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, * 0x02, 0x00, 0x40, 0x00, 0x04, 0x06, 0x04, 0x84 }; */ - uint16_t ctrl; - update_prom_cnt(); - ctrl = (m_prom[m_prom_cnt] | 0x200); + uint16_t ctrl = (m_prom[m_prom_cnt] | 0x200); //if (m_enable && m_prom_cnt < 0x10) printf("ctrl %04x, enable %d cnt %d\n", ctrl, m_enable, m_prom_cnt); m_prom_cnt = ((m_prom_cnt + 1) & 0x0f) | (m_prom_cnt & 0x10); @@ -1357,11 +1321,7 @@ void tmsprom_device::device_timer(emu_timer &timer, device_timer_id id, int para void tmsprom_device::device_start() { - /* resolve lines */ - m_pdc_cb.resolve_safe(); - m_ctl_cb.resolve_safe(); - - m_romclk_timer = timer_alloc(0); + m_romclk_timer = timer_alloc(FUNC(tmsprom_device::update_romclk), this); m_romclk_timer->adjust(attotime::zero, 0, attotime::from_hz(clock())); m_bit = 0; @@ -1374,7 +1334,7 @@ void tmsprom_device::device_start() register_for_save_states(); } -WRITE_LINE_MEMBER( tmsprom_device::m0_w ) +void tmsprom_device::m0_w(int state) { /* falling edge counts */ if (m_m0 && !state) @@ -1385,24 +1345,24 @@ WRITE_LINE_MEMBER( tmsprom_device::m0_w ) m_m0 = state; } -READ_LINE_MEMBER( tmsprom_device::data_r ) +int tmsprom_device::data_r() { return (m_rom[m_base_address + m_address] >> m_bit) & 0x01; } -WRITE8_MEMBER( tmsprom_device::rom_csq_w ) +void tmsprom_device::rom_csq_w(offs_t offset, uint8_t data) { if (!data) m_base_address = offset * m_rom_size; } -WRITE8_MEMBER( tmsprom_device::bit_w ) +void tmsprom_device::bit_w(uint8_t data) { m_bit = data; } -WRITE_LINE_MEMBER( tmsprom_device::enable_w ) +void tmsprom_device::enable_w(int state) { if (state != m_enable) { @@ -1452,7 +1412,7 @@ tms5110_device::tms5110_device(const machine_config &mconfig, device_type type, , m_m0_cb(*this) , m_m1_cb(*this) , m_addr_cb(*this) - , m_data_cb(*this) + , m_data_cb(*this, 0) , m_romclk_cb(*this) { } @@ -1509,18 +1469,18 @@ m58817_device::m58817_device(const machine_config &mconfig, const char *tag, dev DEFINE_DEVICE_TYPE(TMSPROM, tmsprom_device, "tmsprom", "TMSPROM") tmsprom_device::tmsprom_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) - : device_t(mconfig, TMSPROM, tag, owner, clock), - m_rom(*this, DEVICE_SELF), - m_prom(*this, finder_base::DUMMY_TAG, 0x20), - m_rom_size(0), - m_pdc_bit(0), - m_ctl1_bit(0), - m_ctl2_bit(0), - m_ctl4_bit(0), - m_ctl8_bit(0), - m_reset_bit(0), - m_stop_bit(0), - m_pdc_cb(*this), - m_ctl_cb(*this) + : device_t(mconfig, TMSPROM, tag, owner, clock) + , m_rom(*this, DEVICE_SELF) + , m_prom(*this, finder_base::DUMMY_TAG) + , m_rom_size(0) + , m_pdc_bit(0) + , m_ctl1_bit(0) + , m_ctl2_bit(0) + , m_ctl4_bit(0) + , m_ctl8_bit(0) + , m_reset_bit(0) + , m_stop_bit(0) + , m_pdc_cb(*this) + , m_ctl_cb(*this) { } |