summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/sound/hc55516.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/devices/sound/hc55516.cpp')
-rw-r--r--src/devices/sound/hc55516.cpp572
1 files changed, 414 insertions, 158 deletions
diff --git a/src/devices/sound/hc55516.cpp b/src/devices/sound/hc55516.cpp
index 5414f378802..2d96ad2cb3b 100644
--- a/src/devices/sound/hc55516.cpp
+++ b/src/devices/sound/hc55516.cpp
@@ -1,8 +1,18 @@
// license:BSD-3-Clause
-// copyright-holders:Aaron Giles
+// copyright-holders:Aaron Giles, Jonathan Gevaryahu
+// thanks-to:Zonn Moore
/*****************************************************************************
- Harris HC-55516 (and related) emulator
+ Continuously Variable Slope Demodulator standalone chip emulator:
+ Harris HC-55516 (sometimes labeled HCI-55516 or HC1-55516)
+ Harris HC-55532 (sometimes labeled HCI-55532 or HC1-55532) [preliminary]
+ Motorola MC-3417/MC-34115
+ Motorola MC-3418
+ TODO: research HC-55536 and HC-55564 differences vs HC-55516 (better auto-zeroing, and removal of the encoder offset compensation DAC?)
+
+ Driver TODOs:
+ /src/mame/audio/exidy440.cpp has its own internal implementation of the MC3417 and MC3418, it should be using this file instead
+
*****************************************************************************/
@@ -10,7 +20,7 @@
#include "hc55516.h"
-/* 4x oversampling */
+/* fixed samplerate of 192khz */
#define SAMPLE_RATE (48000 * 4)
#define INTEGRATOR_LEAK_TC 0.001
@@ -21,33 +31,23 @@
#define SAMPLE_GAIN (10000.0 / 32768.0)
-
-
-DEFINE_DEVICE_TYPE(HC55516, hc55516_device, "hc55516", "HC-55516")
-
-hc55516_device::hc55516_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : hc55516_device(mconfig, HC55516, tag, owner, clock)
-{
-}
-
-hc55516_device::hc55516_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock)
- : device_t(mconfig, type, tag, owner, clock),
- device_sound_interface(mconfig, *this),
- m_channel(nullptr),
- m_active_clock_hi(0),
- m_shiftreg_mask(0),
- m_last_clock_state(0),
- m_digit(0),
- m_new_digit(0),
- m_shiftreg(0),
- m_curr_sample(0),
- m_next_sample(0),
- m_update_count(0),
- m_filter(0),
- m_integrator(0),
- m_charge(0),
- m_decay(0),
- m_leak(0)
+//#####################################
+// COMMON
+//#####################################
+cvsd_device_base::cvsd_device_base(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock, bool active_clock_edge, uint8_t shiftreg_mask)
+ : device_t(mconfig, type, tag, owner, clock)
+ , device_sound_interface(mconfig, *this)
+ , m_clock_state_push_cb(*this)
+ , m_digin_pull_cb(*this)
+ , m_digout_push_cb(*this)
+ , m_active_clock_edge(active_clock_edge)
+ , m_shiftreg_mask(shiftreg_mask)
+ , m_last_clock_state(false)
+ , m_buffered_bit(false)
+ , m_shiftreg(0)
+ , m_curr_sample(0)
+ , m_next_sample(0)
+ , m_samples_generated(0)
{
}
@@ -55,208 +55,466 @@ hc55516_device::hc55516_device(const machine_config &mconfig, device_type type,
// device_start - device-specific startup
//-------------------------------------------------
-void hc55516_device::device_start()
+void cvsd_device_base::device_start()
{
- start_common(0x07, true);
+ /* create the stream */
+ m_stream = stream_alloc(0, 1, SAMPLE_RATE);
+
+ save_item(NAME(m_last_clock_state));
+ save_item(NAME(m_buffered_bit));
+ save_item(NAME(m_shiftreg));
+ save_item(NAME(m_curr_sample));
+ save_item(NAME(m_next_sample));
+ save_item(NAME(m_samples_generated));
}
//-------------------------------------------------
// device_reset - device-specific reset
//-------------------------------------------------
-void hc55516_device::device_reset()
+void cvsd_device_base::device_reset()
{
m_last_clock_state = 0;
}
-DEFINE_DEVICE_TYPE(MC3417, mc3417_device, "mc3417", "MC3417")
+//-------------------------------------------------
+// device_clock_changed - device-specific samplerate change
+//-------------------------------------------------
+/*void cvsd_device_base::device_clock_changed()
+{
+ // do nothing.
+ //m_stream->set_sample_rate(clock());
+}*/
-mc3417_device::mc3417_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : hc55516_device(mconfig, MC3417, tag, owner, clock)
+READ_LINE_MEMBER( cvsd_device_base::clock_r )
{
+ // prevent debugger from changing the internal state
+ if (!machine().side_effects_disabled())
+ m_stream->update(); /* bring up to date first */
+ return clock_state_r();
}
-//-------------------------------------------------
-// device_start - device-specific startup
-//-------------------------------------------------
+WRITE_LINE_MEMBER( cvsd_device_base::mclock_w )
+{
+ clock_w(state);
+}
-void mc3417_device::device_start()
+WRITE_LINE_MEMBER( cvsd_device_base::digin_w )
{
- start_common(0x07, false);
+ digit_w(state);
}
+// the following encode related functions don't do anything yet, don't call them.
+/*void cvsd_device_base::audio_in_w(int16_t data)
+{
+ assert(0);
+}*/
-DEFINE_DEVICE_TYPE(MC3418, mc3418_device, "mc3418", "MC3418")
+WRITE_LINE_MEMBER( cvsd_device_base::dec_encq_w )
+{
+ assert(0);
+}
-mc3418_device::mc3418_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : hc55516_device(mconfig, MC3418, tag, owner, clock)
+READ_LINE_MEMBER( cvsd_device_base::digout_r )
{
+ return 0;
}
-//-------------------------------------------------
-// device_start - device-specific startup
-//-------------------------------------------------
+// default and stub implementations
-void mc3418_device::device_start()
+inline bool cvsd_device_base::is_external_oscillator()
{
- start_common(0x0f, false);
+ return clock() != 0;
}
+inline bool cvsd_device_base::is_clock_changed(bool clock_state)
+{
+ return ((!m_last_clock_state && clock_state) ||
+ (m_last_clock_state && !clock_state));
+}
-void hc55516_device::start_common(uint8_t _shiftreg_mask, int _active_clock_hi)
+inline bool cvsd_device_base::is_active_clock_transition(bool clock_state)
{
- /* compute the fixed charge, decay, and leak time constants */
- m_charge = pow(exp(-1.0), 1.0 / (FILTER_CHARGE_TC * 16000.0));
- m_decay = pow(exp(-1.0), 1.0 / (FILTER_DECAY_TC * 16000.0));
- m_leak = pow(exp(-1.0), 1.0 / (INTEGRATOR_LEAK_TC * 16000.0));
+ return ((clock_state != m_last_clock_state) &&
+ (clock_state == m_active_clock_edge));
+}
- m_shiftreg_mask = _shiftreg_mask;
- m_active_clock_hi = _active_clock_hi;
- m_last_clock_state = 0;
+inline bool cvsd_device_base::current_clock_state()
+{
+ // keep track of the clock state given its previous state and the number of samples produced
+ // i.e. if we generated m_samples_generated samples, at a sample rate of SAMPLE_RATE, then are we on a positive or negative level of a squarewave at clock() hz? SAMPLE_RATE may not be an integer multiple of clock()
+ //uint64_t fractions_of_second = (((uint64_t)m_samples_generated)<<32) / SAMPLE_RATE; // 32.32 bits of seconds passed so far
+ //uint32_t clock_edges_passed = (fractions_of_second * clock() * 2)>>32
+ //return (((((uint64_t)m_samples_generated<<32) * clock() * 2 / SAMPLE_RATE)>>32) & 0x1)?true:false;
+ return (((uint64_t)m_samples_generated * clock() * 2 / SAMPLE_RATE) & 0x01)?true:false;
+}
- /* create the stream */
- m_channel = stream_alloc(0, 1, SAMPLE_RATE);
+void cvsd_device_base::digit_w(int digit)
+{
+ m_stream->update();
+ m_buffered_bit = digit ? true : false;
+}
- save_item(NAME(m_last_clock_state));
- save_item(NAME(m_digit));
- save_item(NAME(m_new_digit));
- save_item(NAME(m_shiftreg));
- save_item(NAME(m_curr_sample));
- save_item(NAME(m_next_sample));
- save_item(NAME(m_update_count));
- save_item(NAME(m_filter));
- save_item(NAME(m_integrator));
+void cvsd_device_base::clock_w(int state)
+{
+ /* update the output buffer first */
+ m_stream->update();
+ bool clock_state = state ? true : false;
+
+ /* only makes sense for setups with a software driven clock */
+ assert(!is_external_oscillator());
+
+ /* speech clock changing? */
+ if (is_clock_changed(clock_state))
+ {
+ /* clear the update count */
+ m_samples_generated = 0;
+ process_bit(m_buffered_bit, clock_state);
+ }
+
+ /* update the clock */
+ m_last_clock_state = clock_state;
}
-inline int hc55516_device::is_external_oscillator()
+int cvsd_device_base::clock_state_r()
{
- return clock() != 0;
+ /* only makes sense for setups with an external oscillator */
+ assert(is_external_oscillator());
+
+ m_stream->update();
+
+ return current_clock_state();
+}
+
+void cvsd_device_base::process_bit(bool bit, bool clock_state)
+{
+ // stub
+}
+
+//-------------------------------------------------
+// sound_stream_update - handle a stream update
+//-------------------------------------------------
+
+void cvsd_device_base::sound_stream_update(sound_stream &stream, std::vector<read_stream_view> const &inputs, std::vector<write_stream_view> &outputs)
+{
+ // Stub, just return silence
+ auto &buffer = outputs[0];
+
+ m_samples_generated += buffer.samples();
+ if (m_samples_generated >= SAMPLE_RATE)
+ m_samples_generated -= SAMPLE_RATE;
+ buffer.fill(0);
}
-inline int hc55516_device::is_active_clock_transition(int clock_state)
+//#########################################
+// HC55516
+//#########################################
+DEFINE_DEVICE_TYPE(HC55516, hc55516_device, "hc55516", "HC-55516")
+
+hc55516_device::hc55516_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : hc55516_device(mconfig, HC55516, tag, owner, clock, 0xfc0, 6, 0xfc1, 4)
+{
+}
+
+// overridable type for hc55532 etc
+hc55516_device::hc55516_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock, uint32_t sylmask, int32_t sylshift, int32_t syladd, int32_t intshift)
+ : cvsd_device_base(mconfig, type, tag, owner, clock, RISING, 0x7)
+ , m_agc_push_cb(*this)
+ , m_fzq_pull_cb(*this)
+ , m_sylmask(sylmask)
+ , m_sylshift(sylshift)
+ , m_syladd(syladd)
+ , m_intshift(intshift)
+ , m_sylfilter(0)
+ , m_intfilter(0)
+ , m_agc(true)
+ , m_buffered_fzq(true)
{
- return (( m_active_clock_hi && !m_last_clock_state && clock_state) ||
- (!m_active_clock_hi && m_last_clock_state && !clock_state));
}
+//-------------------------------------------------
+// device_start - device-specific start
+//-------------------------------------------------
-inline int hc55516_device::current_clock_state()
+void hc55516_device::device_start()
{
- return ((uint64_t)m_update_count * clock() * 2 / SAMPLE_RATE) & 0x01;
+ cvsd_device_base::device_start();
+ save_item(NAME(m_sylfilter));
+ save_item(NAME(m_intfilter));
+ save_item(NAME(m_agc));
+ save_item(NAME(m_buffered_fzq));
+
+ /* resolve lines */
+ m_agc_push_cb.resolve();
+ m_fzq_pull_cb.resolve();
}
+//-------------------------------------------------
+// device_reset - device-specific reset
+//-------------------------------------------------
-void hc55516_device::process_digit()
+void hc55516_device::device_reset()
{
- double integrator = m_integrator, temp;
+ cvsd_device_base::device_reset();
+ // simulate /FZ having been held for a while
+ m_sylfilter = 0x3f;
+ m_intfilter = 0;
+ m_agc = true;
+ m_buffered_fzq = true; // assuming /FZ was just released and is now high/inactive
+}
- /* shift the bit into the shift register */
- m_shiftreg = (m_shiftreg << 1) | m_digit;
+// device specific functions
- /* move the estimator up or down a step based on the bit */
- if (m_digit)
- integrator += m_filter;
- else
- integrator -= m_filter;
+WRITE_LINE_MEMBER( hc55516_device::fzq_w )
+{
+ m_buffered_fzq = state;
+}
+
+READ_LINE_MEMBER( hc55516_device::agc_r )
+{
+ // prevent debugger from changing the internal state
+ if (!machine().side_effects_disabled())
+ m_stream->update(); /* bring up to date first */
+ return m_agc;
+}
- /* simulate leakage */
- integrator *= m_leak;
+void hc55516_device::process_bit(bool bit, bool clock_state)
+{
+ bool frozen = ( ( (m_intfilter >= 0x180) && (!bit) ) ||
+ ( (m_intfilter <= -0x180) && (bit) ) );
- /* if we got all 0's or all 1's in the last n bits, bump the step up */
- if (((m_shiftreg & m_shiftreg_mask) == 0) ||
- ((m_shiftreg & m_shiftreg_mask) == m_shiftreg_mask))
+ int32_t sum;
+ if (is_active_clock_transition(clock_state))
{
- m_filter = FILTER_MAX - ((FILTER_MAX - m_filter) * m_charge);
+ // grab the /FZ state; if the callback is present, use that, otherwise use the buffered state
+ bool fzq_state = false;
+ if (!m_fzq_pull_cb.isnull())
+ fzq_state = m_fzq_pull_cb();
+ else
+ fzq_state = m_buffered_fzq;
+
+ if (!fzq_state) // /FZ is active low, if it is active, the input bit is ignored and the inverse of the previous bit in the shifter is used instead
+ bit = !(m_shiftreg&1);
+
+ /* shift the new bit into the shift register */
+ m_shiftreg = (m_shiftreg << 1) | (bit?1:0);
+
+ /* if we got all 0's or all 1's in the last n bits... */
+ if (((m_shiftreg & m_shiftreg_mask) == 0) ||
+ ((m_shiftreg & m_shiftreg_mask) == m_shiftreg_mask))
+ {
+ // coincidence is true
+ if (!frozen) m_sylfilter += (((~m_sylfilter) & m_sylmask) >> m_sylshift);
+ }
+ else
+ {
+ // coincidence is false
+ if (!frozen) m_sylfilter += (((~m_sylfilter) & m_sylmask) >> m_sylshift) + m_syladd;
+ }
+ m_sylfilter &= 0xfff;
- if (m_filter > FILTER_MAX)
- m_filter = FILTER_MAX;
+ sum = ( ((~m_intfilter) >> m_intshift) + 1 ) & 0x3ff;
}
-
- /* simulate decay */
- else
+ else // inactive clock transition
{
- m_filter *= m_decay;
+ if (m_shiftreg&1)
+ {
+ sum = ( ( ~std::max(2, m_sylfilter >> 6) ) + 1 ) & 0x3ff;
+ }
+ else
+ {
+ sum = std::max(2, m_sylfilter >> 6) & 0x3ff;
+ }
+ }
- if (m_filter < FILTER_MIN)
- m_filter = FILTER_MIN;
+ if (sum & 0x200)
+ sum |= ~0x3ff; // sign extend
+
+ if (!frozen)
+ {
+ m_intfilter += sum;
+ m_intfilter &= 0x3ff;
+ if (m_intfilter & 0x200) m_intfilter |= ~0x3ff; // sign extend
}
- /* compute the sample as a 32-bit word */
- temp = integrator * SAMPLE_GAIN;
- m_integrator = integrator;
+ /* scale the result (-512 to 511) to -32768 thru 32767 */
+ /*
+ F E D C B A 9 8 7 6 5 4 3 2 1 0
+ 9 8 7 6 5 4 3 2 1 0/9 8 7 6 5 4
+ */
+ m_next_sample = ( (m_intfilter << 6) | ( ((m_intfilter & 0x3ff) ^ 0x200 ) >> 4 ) );
+
+ // update agc state
+ if ( (m_intfilter >= 0x100) || (m_intfilter <= -0x100) )
+ m_agc = false;
+ else
+ m_agc = true;
- m_next_sample = temp;
- /* compress the sample range to fit better in a 16-bit word */
-/* if (temp < 0)
- m_next_sample = (int)(temp / (-temp * (1.0 / 32768.0) + 1.0));
- else
- m_next_sample = (int)(temp / (temp * (1.0 / 32768.0) + 1.0));*/
+ // push agc state if a callback is present
+ if (!m_agc_push_cb.isnull())
+ m_agc_push_cb(m_agc);
}
-void hc55516_device::clock_w(int state)
+//-------------------------------------------------
+// sound_stream_update_legacy - handle a stream update
+//-------------------------------------------------
+
+void hc55516_device::sound_stream_update(sound_stream &stream, std::vector<read_stream_view> const &inputs, std::vector<write_stream_view> &outputs)
{
- uint8_t clock_state = state ? true : false;
+ auto &buffer = outputs[0];
- /* only makes sense for setups with a software driven clock */
- assert(!is_external_oscillator());
+/*
+ if (!is_external_oscillator())
+ {
+ // track how many samples we've updated without a clock; if it's been more than 1/32 of a second, output silence
+ m_samples_generated += buffer.samples();
+ if (m_samples_generated > SAMPLE_RATE / 32)
+ {
+ m_samples_generated = SAMPLE_RATE;
+ m_next_sample = 0;
+ }
+ }
+*/
- /* speech clock changing? */
- if (is_active_clock_transition(clock_state))
+ if (is_external_oscillator())
{
- /* update the output buffer before changing the registers */
- m_channel->update();
+ /* external oscillator */
+ for (int i = 0; i < buffer.samples(); i++)
+ {
+ buffer.put_int(i, m_next_sample, 32768);
- /* clear the update count */
- m_update_count = 0;
+ m_samples_generated++;
- process_digit();
+ uint8_t clock_state = current_clock_state();
+
+ /* pull in next digit on the appropriate edge of the clock */
+ if (is_clock_changed(clock_state))
+ {
+ process_bit(m_buffered_bit, clock_state);
+ }
+
+ m_last_clock_state = clock_state;
+ }
}
- /* update the clock */
- m_last_clock_state = clock_state;
+ /* software driven clock */
+ else
+ for (int i = 0; i < buffer.samples(); i++)
+ buffer.put_int(i, m_next_sample, 32768);
}
-void hc55516_device::digit_w(int digit)
+
+//#########################################
+// HC55532
+//#########################################
+DEFINE_DEVICE_TYPE(HC55532, hc55532_device, "hc55532", "HC-55532")
+
+hc55532_device::hc55532_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : hc55516_device(mconfig, HC55532, tag, owner, clock, 0xf80, 7, 0xfe1, 5)
{
- if (is_external_oscillator())
- {
- m_channel->update();
- m_new_digit = digit & 1;
- }
- else
- m_digit = digit & 1;
}
+//-------------------------------------------------
+// device_reset - device-specific reset
+//-------------------------------------------------
-int hc55516_device::clock_state_r()
+void hc55532_device::device_reset()
{
- /* only makes sense for setups with an external oscillator */
- assert(is_external_oscillator());
+ cvsd_device_base::device_reset();
+ // simulate /FZ having been held for a while
+ m_sylfilter = 0x7f;
+ m_intfilter = 0;
+ m_agc = true;
+ m_buffered_fzq = true; // assuming /FZ was just released and is now high/inactive
+}
- m_channel->update();
- return current_clock_state();
+
+//##########################################
+// MC3417
+//##########################################
+DEFINE_DEVICE_TYPE(MC3417, mc3417_device, "mc3417", "MC3417")
+
+mc3417_device::mc3417_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : mc3417_device(mconfig, MC3417, tag, owner, clock, 0x7)
+{
}
+// overridable type for mc3418 etc
+mc3417_device::mc3417_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock, uint8_t shiftreg_mask)
+ : cvsd_device_base(mconfig, type, tag, owner, clock, FALLING, shiftreg_mask)
+ , m_charge(pow(exp(-1.0), 1.0 / (FILTER_CHARGE_TC * 16000.0)))
+ , m_decay(pow(exp(-1.0), 1.0 / (FILTER_DECAY_TC * 16000.0)))
+ , m_leak(pow(exp(-1.0), 1.0 / (INTEGRATOR_LEAK_TC * 16000.0)))
+ , m_sylfilter_d(0.0)
+ , m_intfilter_d(0.0)
+{
+}
//-------------------------------------------------
-// sound_stream_update - handle a stream update
+// device_start - device-specific startup
//-------------------------------------------------
-void hc55516_device::sound_stream_update(sound_stream &stream, std::vector<read_stream_view> const &inputs, std::vector<write_stream_view> &outputs)
+void mc3417_device::device_start()
+{
+ cvsd_device_base::device_start();
+ save_item(NAME(m_sylfilter_d));
+ save_item(NAME(m_intfilter_d));
+}
+
+void mc3417_device::process_bit(bool bit, bool clock_state)
+{
+ if (is_active_clock_transition(clock_state))
+ {
+
+ /* shift the new bit into the shift register */
+ m_shiftreg = (m_shiftreg << 1) | (bit?1:0);
+
+ /* move the estimator up or down a step based on the bit */
+ if (!bit)
+ m_intfilter_d += m_sylfilter_d;
+ else
+ m_intfilter_d -= m_sylfilter_d;
+
+ /* simulate leakage */
+ m_intfilter_d *= m_leak;
+
+ /* if we got all 0's or all 1's in the last n bits, bump the step up */
+ if (((m_shiftreg & m_shiftreg_mask) == 0) ||
+ ((m_shiftreg & m_shiftreg_mask) == m_shiftreg_mask))
+ {
+ // coincidence is true
+ m_sylfilter_d = FILTER_MAX - ((FILTER_MAX - m_sylfilter_d) * m_charge);
+
+ if (m_sylfilter_d > FILTER_MAX)
+ m_sylfilter_d = FILTER_MAX;
+ }
+ else
+ {
+ m_sylfilter_d *= m_decay;
+
+ if (m_sylfilter_d < FILTER_MIN)
+ m_sylfilter_d = FILTER_MIN;
+ }
+
+ /* compute the sample as a 32-bit word */
+ m_next_sample = m_intfilter_d * SAMPLE_GAIN;
+ }
+}
+
+void mc3417_device::sound_stream_update(sound_stream &stream, std::vector<read_stream_view> const &inputs, std::vector<write_stream_view> &outputs)
{
auto &buffer = outputs[0];
- int i;
if (!is_external_oscillator())
{
- /* track how many samples we've updated without a clock */
- m_update_count += buffer.samples();
- if (m_update_count > SAMPLE_RATE / 32)
+ /* track how many samples we've updated without a clock; if it's been more than 1/32 of a second, output silence */
+ m_samples_generated += buffer.samples();
+ if (m_samples_generated > SAMPLE_RATE / 32)
{
- m_update_count = SAMPLE_RATE;
+ m_samples_generated = SAMPLE_RATE;
m_next_sample = 0;
}
}
@@ -269,22 +527,18 @@ void hc55516_device::sound_stream_update(sound_stream &stream, std::vector<read_
if (is_external_oscillator())
{
/* external oscillator */
- for (i = 0; i < buffer.samples(); i++, sample += slope)
+ for (int i = 0; i < buffer.samples(); i++, sample += slope)
{
- uint8_t clock_state;
+ buffer.put(i, sample);
- buffer.put(i, stream_buffer::sample_t(sample));
+ m_samples_generated++;
- m_update_count++;
-
- clock_state = current_clock_state();
+ uint8_t clock_state = current_clock_state();
/* pull in next digit on the appropriate edge of the clock */
- if (is_active_clock_transition(clock_state))
+ if (is_clock_changed(clock_state))
{
- m_digit = m_new_digit;
-
- process_digit();
+ process_bit(m_buffered_bit, clock_state);
}
m_last_clock_state = clock_state;
@@ -293,16 +547,18 @@ void hc55516_device::sound_stream_update(sound_stream &stream, std::vector<read_
/* software driven clock */
else
- for (i = 0; i < buffer.samples(); i++, sample += slope)
- buffer.put(i, stream_buffer::sample_t(sample));
+ for (int i = 0; i < buffer.samples(); i++, sample += slope)
+ buffer.put(i, sample);
}
-void mc3417_device::sound_stream_update(sound_stream &stream, std::vector<read_stream_view> const &inputs, std::vector<write_stream_view> &outputs)
-{
- hc55516_device::sound_stream_update(stream, inputs, outputs);
-}
-void mc3418_device::sound_stream_update(sound_stream &stream, std::vector<read_stream_view> const &inputs, std::vector<write_stream_view> &outputs)
+
+//##########################################
+// MC3418
+//##########################################
+DEFINE_DEVICE_TYPE(MC3418, mc3418_device, "mc3418", "MC3418")
+
+mc3418_device::mc3418_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : mc3417_device(mconfig, MC3418, tag, owner, clock, 0xf)
{
- hc55516_device::sound_stream_update(stream, inputs, outputs);
}