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, 57 insertions, 62 deletions
diff --git a/src/devices/sound/pokey.cpp b/src/devices/sound/pokey.cpp
index 3372ac70a81..487a1b4e83b 100644
--- a/src/devices/sound/pokey.cpp
+++ b/src/devices/sound/pokey.cpp
@@ -99,6 +99,11 @@
#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 */
@@ -147,10 +152,17 @@
#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;
@@ -241,8 +253,7 @@ void pokey_device::device_start()
m_pot_counter = 0;
m_kbd_cnt = 0;
m_out_filter = 0;
- m_out_raw = 0;
- m_old_raw_inval = true;
+ m_output = 0;
m_kbd_state = 0;
/* reset more internal state */
@@ -424,7 +435,14 @@ void pokey_device::execute_run()
{
do
{
- step_one_clock();
+ 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;
+ }
+
m_icount--;
} while (m_icount > 0);
@@ -528,8 +546,11 @@ void pokey_device::step_keyboard()
void pokey_device::step_pot()
{
- m_pot_counter++;
+ if ((m_SKCTL & SK_RESET) == 0)
+ return;
+
uint8_t upd = 0;
+ m_pot_counter++;
for (int pot = 0; pot < 8; pot++)
{
if ((m_POTx[pot]<m_pot_counter) || (m_pot_counter == 228))
@@ -538,9 +559,7 @@ void pokey_device::step_pot()
/* latching is emulated in read */
}
}
- // some pots latched?
- if (upd != 0)
- synchronize(SYNC_POT, upd);
+ synchronize(SYNC_POT, upd);
}
/*
@@ -551,38 +570,31 @@ void pokey_device::step_pot()
*
*/
-void pokey_device::step_one_clock(void)
+uint32_t pokey_device::step_one_clock(void)
{
- /* Clocks only count if we are not in a reset */
+ int const base_clock = (m_AUDCTL & CLK_15KHZ) ? CLK_114 : CLK_28;
+
if (m_SKCTL & SK_RESET)
{
- /* 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_28] = 0;
- clock_triggered[CLK_28] = 1;
- }
- /* CLK_114 prescaler 15.6999 kHz */
- if (++m_clock_cnt[CLK_114] >= DIV_15)
+ /* 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++)
{
- m_clock_cnt[CLK_114] = 0;
- clock_triggered[CLK_114] = 1;
+ m_clock_cnt[clk]++;
+ if (m_clock_cnt[clk] >= clock_divisors[clk])
+ {
+ m_clock_cnt[clk] = 0;
+ clock_triggered[clk] = 1;
+ }
}
- int const base_clock = (m_AUDCTL & CLK_15KHZ) ? CLK_114 : CLK_28;
- int clk = (m_AUDCTL & CH1_HICLK) ? CLK_1 : base_clock;
+ 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;
if (clock_triggered[clk])
m_channel[CHAN1].inc_chan();
@@ -666,23 +678,12 @@ void pokey_device::step_one_clock(void)
m_channel[CHAN1].m_filter_sample = 1;
}
- if (m_old_raw_inval)
+ uint32_t sum = 0;
+ for (int ch = 0; ch < 4; ch++)
{
- 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;
+ 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));
}
+ return sum;
}
//-------------------------------------------------
@@ -699,7 +700,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_out_raw >> (4*i)) & 0x0f);
+ out += ((m_output >> (4*i)) & 0x0f);
out *= POKEY_DEFAULT_GAIN;
out = (out > 0x7fff) ? 0x7fff : out;
while( samples > 0 )
@@ -710,7 +711,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_out_raw];
+ double rTot = m_voltab[m_output];
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());
@@ -726,7 +727,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_out_raw];
+ double rTot = m_voltab[m_output];
/* 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.
@@ -748,7 +749,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_out_raw];
+ double rTot = m_voltab[m_output];
/* This post-pokey stage usually has a low-pass filter behind it
* It is approximated by not adding in VRef below.
*/
@@ -766,7 +767,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_out_raw];
+ int32_t out = m_voltab[m_output];
while( samples > 0 )
{
*buffer++ = out;
@@ -779,7 +780,7 @@ void pokey_device::sound_stream_update(sound_stream &stream, stream_sample_t **i
// read - memory interface for reading the active status
//-------------------------------------------------
-uint8_t pokey_device::read(offs_t offset)
+READ8_MEMBER( pokey_device::read )
{
int data, pot;
@@ -875,7 +876,7 @@ uint8_t pokey_device::read(offs_t offset)
// write - memory interface for write
//-------------------------------------------------
-void pokey_device::write(offs_t offset, uint8_t data)
+WRITE8_MEMBER( pokey_device::write )
{
synchronize(SYNC_WRITE, (offset << 8) | data);
}
@@ -893,7 +894,6 @@ 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,7 +904,6 @@ 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:
@@ -915,7 +914,6 @@ 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:
@@ -926,7 +924,6 @@ 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:
@@ -951,7 +948,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:
@@ -1021,7 +1018,6 @@ 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;
@@ -1070,7 +1066,6 @@ 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;
}
}