summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/sound/pokey.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/devices/sound/pokey.cpp')
-rw-r--r--src/devices/sound/pokey.cpp119
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;
}
}