diff options
Diffstat (limited to 'src/devices/sound/pokey.cpp')
-rw-r--r-- | src/devices/sound/pokey.cpp | 119 |
1 files changed, 62 insertions, 57 deletions
diff --git a/src/devices/sound/pokey.cpp b/src/devices/sound/pokey.cpp index 487a1b4e83b..3372ac70a81 100644 --- a/src/devices/sound/pokey.cpp +++ b/src/devices/sound/pokey.cpp @@ -99,11 +99,6 @@ #define TIMER2 1 #define TIMER4 2 -/* values to add to the divisors for the different modes */ -#define DIVADD_LOCLK 1 -#define DIVADD_HICLK 4 -#define DIVADD_HICLK_JOINED 7 - /* AUDCx */ #define NOTPOLY5 0x80 /* selects POLY5 or direct CLOCK */ #define POLY4 0x40 /* selects POLY4 or POLY17 */ @@ -152,17 +147,10 @@ #define DIV_64 28 /* divisor for 1.78979 MHz clock to 63.9211 kHz */ #define DIV_15 114 /* divisor for 1.78979 MHz clock to 15.6999 kHz */ -#define P4(chip) chip->poly4[chip->p4] -#define P5(chip) chip->poly5[chip->p5] -#define P9(chip) chip->poly9[chip->p9] -#define P17(chip) chip->poly17[chip->p17] - #define CLK_1 0 #define CLK_28 1 #define CLK_114 2 -static const int clock_divisors[3] = {1, DIV_64, DIV_15}; - constexpr unsigned pokey_device::FREQ_17_EXACT; @@ -253,7 +241,8 @@ void pokey_device::device_start() m_pot_counter = 0; m_kbd_cnt = 0; m_out_filter = 0; - m_output = 0; + m_out_raw = 0; + m_old_raw_inval = true; m_kbd_state = 0; /* reset more internal state */ @@ -435,14 +424,7 @@ void pokey_device::execute_run() { do { - uint32_t new_out = step_one_clock(); - if (m_output != new_out) - { - //printf("forced update %08d %08x\n", m_icount, m_output); - m_stream->update(); - m_output = new_out; - } - + step_one_clock(); m_icount--; } while (m_icount > 0); @@ -546,11 +528,8 @@ void pokey_device::step_keyboard() void pokey_device::step_pot() { - if ((m_SKCTL & SK_RESET) == 0) - return; - - uint8_t upd = 0; m_pot_counter++; + uint8_t upd = 0; for (int pot = 0; pot < 8; pot++) { if ((m_POTx[pot]<m_pot_counter) || (m_pot_counter == 228)) @@ -559,7 +538,9 @@ void pokey_device::step_pot() /* latching is emulated in read */ } } - synchronize(SYNC_POT, upd); + // some pots latched? + if (upd != 0) + synchronize(SYNC_POT, upd); } /* @@ -570,31 +551,38 @@ void pokey_device::step_pot() * */ -uint32_t pokey_device::step_one_clock(void) +void pokey_device::step_one_clock(void) { - int const base_clock = (m_AUDCTL & CLK_15KHZ) ? CLK_114 : CLK_28; - + /* Clocks only count if we are not in a reset */ if (m_SKCTL & SK_RESET) { - /* Clocks only count if we are not in a reset */ - int clock_triggered[3] = {0,0,0}; - int clk; - for (clk = 0; clk < 3; clk++) + /* polynom pointers */ + if (++m_p4 == 0x0000f) + m_p4 = 0; + if (++m_p5 == 0x0001f) + m_p5 = 0; + if (++m_p9 == 0x001ff) + m_p9 = 0; + if (++m_p17 == 0x1ffff) + m_p17 = 0; + + /* CLK_1: no presacler */ + int clock_triggered[3] = {1,0,0}; + /* CLK_28: prescaler 63.9211 kHz */ + if (++m_clock_cnt[CLK_28] >= DIV_64) { - m_clock_cnt[clk]++; - if (m_clock_cnt[clk] >= clock_divisors[clk]) - { - m_clock_cnt[clk] = 0; - clock_triggered[clk] = 1; - } + m_clock_cnt[CLK_28] = 0; + clock_triggered[CLK_28] = 1; + } + /* CLK_114 prescaler 15.6999 kHz */ + if (++m_clock_cnt[CLK_114] >= DIV_15) + { + m_clock_cnt[CLK_114] = 0; + clock_triggered[CLK_114] = 1; } - m_p4 = (m_p4 + 1) % 0x0000f; - m_p5 = (m_p5 + 1) % 0x0001f; - m_p9 = (m_p9 + 1) % 0x001ff; - m_p17 = (m_p17 + 1 ) % 0x1ffff; - - clk = (m_AUDCTL & CH1_HICLK) ? CLK_1 : base_clock; + int const base_clock = (m_AUDCTL & CLK_15KHZ) ? CLK_114 : CLK_28; + int clk = (m_AUDCTL & CH1_HICLK) ? CLK_1 : base_clock; if (clock_triggered[clk]) m_channel[CHAN1].inc_chan(); @@ -678,12 +666,23 @@ uint32_t pokey_device::step_one_clock(void) m_channel[CHAN1].m_filter_sample = 1; } - uint32_t sum = 0; - for (int ch = 0; ch < 4; ch++) + if (m_old_raw_inval) { - sum |= (((((m_channel[ch].m_output ^ m_channel[ch].m_filter_sample) || (m_channel[ch].m_AUDC & VOLUME_ONLY)) ? (m_channel[ch].m_AUDC & VOLUME_MASK) : 0 )) << (ch * 4)); + uint32_t sum = 0; + for (int ch = 0; ch < 4; ch++) + { + sum |= (((m_channel[ch].m_output ^ m_channel[ch].m_filter_sample) || (m_channel[ch].m_AUDC & VOLUME_ONLY)) ? + ((m_channel[ch].m_AUDC & VOLUME_MASK) << (ch * 4)) : 0); + } + + if (m_out_raw != sum) + { + //printf("forced update %08d %08x\n", m_icount, m_out_raw); + m_stream->update(); + } + m_old_raw_inval = false; + m_out_raw = sum; } - return sum; } //------------------------------------------------- @@ -700,7 +699,7 @@ void pokey_device::sound_stream_update(sound_stream &stream, stream_sample_t **i { int32_t out = 0; for (int i = 0; i < 4; i++) - out += ((m_output >> (4*i)) & 0x0f); + out += ((m_out_raw >> (4*i)) & 0x0f); out *= POKEY_DEFAULT_GAIN; out = (out > 0x7fff) ? 0x7fff : out; while( samples > 0 ) @@ -711,7 +710,7 @@ void pokey_device::sound_stream_update(sound_stream &stream, stream_sample_t **i } else if (m_output_type == RC_LOWPASS) { - double rTot = m_voltab[m_output]; + double rTot = m_voltab[m_out_raw]; double V0 = rTot / (rTot+m_r_pullup) * m_v_ref / 5.0 * 32767.0; double mult = (m_cap == 0.0) ? 1.0 : 1.0 - exp(-(rTot + m_r_pullup) / (m_cap * m_r_pullup * rTot) * m_clock_period.as_double()); @@ -727,7 +726,7 @@ void pokey_device::sound_stream_update(sound_stream &stream, stream_sample_t **i } else if (m_output_type == OPAMP_C_TO_GROUND) { - double rTot = m_voltab[m_output]; + double rTot = m_voltab[m_out_raw]; /* In this configuration there is a capacitor in parallel to the pokey output to ground. * With a LM324 in LTSpice this causes the opamp circuit to oscillate at around 100 kHz. * We are ignoring the capacitor here, since this oscillation would not be audible. @@ -749,7 +748,7 @@ void pokey_device::sound_stream_update(sound_stream &stream, stream_sample_t **i } else if (m_output_type == OPAMP_LOW_PASS) { - double rTot = m_voltab[m_output]; + double rTot = m_voltab[m_out_raw]; /* This post-pokey stage usually has a low-pass filter behind it * It is approximated by not adding in VRef below. */ @@ -767,7 +766,7 @@ void pokey_device::sound_stream_update(sound_stream &stream, stream_sample_t **i } else if (m_output_type == DISCRETE_VAR_R) { - int32_t out = m_voltab[m_output]; + int32_t out = m_voltab[m_out_raw]; while( samples > 0 ) { *buffer++ = out; @@ -780,7 +779,7 @@ void pokey_device::sound_stream_update(sound_stream &stream, stream_sample_t **i // read - memory interface for reading the active status //------------------------------------------------- -READ8_MEMBER( pokey_device::read ) +uint8_t pokey_device::read(offs_t offset) { int data, pot; @@ -876,7 +875,7 @@ READ8_MEMBER( pokey_device::read ) // write - memory interface for write //------------------------------------------------- -WRITE8_MEMBER( pokey_device::write ) +void pokey_device::write(offs_t offset, uint8_t data) { synchronize(SYNC_WRITE, (offset << 8) | data); } @@ -894,6 +893,7 @@ void pokey_device::write_internal(offs_t offset, uint8_t data) case AUDC1_C: LOG_SOUND(("POKEY '%s' AUDC1 $%02x (%s)\n", tag(), data, audc2str(data))); m_channel[CHAN1].m_AUDC = data; + m_old_raw_inval = true; break; case AUDF2_C: @@ -904,6 +904,7 @@ void pokey_device::write_internal(offs_t offset, uint8_t data) case AUDC2_C: LOG_SOUND(("POKEY '%s' AUDC2 $%02x (%s)\n", tag(), data, audc2str(data))); m_channel[CHAN2].m_AUDC = data; + m_old_raw_inval = true; break; case AUDF3_C: @@ -914,6 +915,7 @@ void pokey_device::write_internal(offs_t offset, uint8_t data) case AUDC3_C: LOG_SOUND(("POKEY '%s' AUDC3 $%02x (%s)\n", tag(), data, audc2str(data))); m_channel[CHAN3].m_AUDC = data; + m_old_raw_inval = true; break; case AUDF4_C: @@ -924,6 +926,7 @@ void pokey_device::write_internal(offs_t offset, uint8_t data) case AUDC4_C: LOG_SOUND(("POKEY '%s' AUDC4 $%02x (%s)\n", tag(), data, audc2str(data))); m_channel[CHAN4].m_AUDC = data; + m_old_raw_inval = true; break; case AUDCTL_C: @@ -948,7 +951,7 @@ void pokey_device::write_internal(offs_t offset, uint8_t data) m_channel[i].m_output = 0; m_channel[i].m_filter_sample = (i<2 ? 1 : 0); } - + m_old_raw_inval = true; break; case SKREST_C: @@ -1018,6 +1021,7 @@ void pokey_device::write_internal(offs_t offset, uint8_t data) m_clock_cnt[0] = 0; m_clock_cnt[1] = 0; m_clock_cnt[2] = 0; + m_old_raw_inval = true; /* FIXME: Serial port reset ! */ } break; @@ -1066,6 +1070,7 @@ inline void pokey_device::process_channel(int ch) m_channel[ch].m_output = (m_poly9[m_p9] & 1); else m_channel[ch].m_output = (m_poly17[m_p17] & 1); + m_old_raw_inval = true; } } |