mm5837: unify implementations

* create base mm5837_source device to provide raw output
* mm5837_device is based on it
* mm5837_stream_device generates a sound stream from it
* frequency calculation now computed instead of table-based
This commit is contained in:
Aaron Giles 2020-09-20 13:55:08 -07:00
parent 7e2d6aa41e
commit dfa1168970
4 changed files with 151 additions and 89 deletions

View File

@ -12,22 +12,16 @@
#include "mm5837.h"
//**************************************************************************
// CONSTEXPR DEFINITIONS
//**************************************************************************
constexpr int mm5837_device::m_frequency[];
//**************************************************************************
// DEVICE DEFINITIONS
//**************************************************************************
DEFINE_DEVICE_TYPE(MM5837, mm5837_device, "mm5837", "MM5837 Digital Noise Source")
DEFINE_DEVICE_TYPE(MM5837_STREAM, mm5837_stream_device, "mm5837", "MM5837 Digital Noise Stream")
//**************************************************************************
// LIVE DEVICE
// MM5837 DEVICE
//**************************************************************************
//-------------------------------------------------
@ -37,12 +31,12 @@ DEFINE_DEVICE_TYPE(MM5837, mm5837_device, "mm5837", "MM5837 Digital Noise Source
mm5837_device::mm5837_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
device_t(mconfig, MM5837, tag, owner, clock),
m_output_cb(*this),
m_vdd(0),
m_timer(nullptr),
m_shift(0)
m_vdd(-12)
{
}
//-------------------------------------------------
// device_start - device-specific startup
//-------------------------------------------------
@ -56,36 +50,70 @@ void mm5837_device::device_start()
m_timer = timer_alloc(0);
// register for save states
save_item(NAME(m_shift));
save_item(NAME(m_source.m_shift));
}
//-------------------------------------------------
// device_reset - device-specific reset
//-------------------------------------------------
void mm5837_device::device_reset()
{
// initialize with something
m_shift = 123456;
m_source.reset();
if (m_vdd < 16)
m_timer->adjust(attotime::zero, 0, attotime::from_hz(m_frequency[m_vdd]));
m_timer->adjust(attotime::zero, 0, attotime::from_hz(mm5837_source::frequency(m_vdd)));
else
throw emu_fatalerror("%s: Invalid voltage: %d\n", tag(), m_vdd);
}
//-------------------------------------------------
// device_timer - handle timer callbacks
//-------------------------------------------------
void mm5837_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
{
int tap_14 = BIT(m_shift, 13);
int tap_17 = BIT(m_shift, 16);
int zero = (m_shift == 0) ? 1 : 0;
m_shift <<= 1;
m_shift |= tap_14 ^ tap_17 ^ zero;
m_output_cb(BIT(m_shift, 16));
m_output_cb(m_source.clock());
}
//**************************************************************************
// MM5837 STREAM DEVICE
//**************************************************************************
//-------------------------------------------------
// mm5837_stream_device - constructor
//-------------------------------------------------
mm5837_stream_device::mm5837_stream_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
device_t(mconfig, MM5837_STREAM, tag, owner, clock),
device_sound_interface(mconfig, *this),
m_stream(nullptr),
m_vdd(-12)
{
}
//-------------------------------------------------
// device_start - device-specific startup
//-------------------------------------------------
void mm5837_stream_device::device_start()
{
m_stream = stream_alloc(0, 1, mm5837_source::frequency(m_vdd));
save_item(NAME(m_source.m_shift));
}
//-------------------------------------------------
// sound_stream_update - fill the sound buffer
//-------------------------------------------------
void mm5837_stream_device::sound_stream_update(sound_stream &stream, std::vector<read_stream_view> const &inputs, std::vector<write_stream_view> &outputs)
{
for (int sampindex = 0; sampindex < outputs[0].samples(); sampindex++)
outputs[0].put(sampindex, m_source.clock() ? 1.0 : 0.0);
}

View File

@ -94,6 +94,66 @@
// TYPE DEFINITIONS
//**************************************************************************
// ======================> mm5837_source
class mm5837_source
{
public:
// construction/destruction
mm5837_source() :
m_shift(0x1ffff)
{
}
// reset to base state
void reset()
{
m_shift = 0x1ffff;
}
// clock one time and return the shift value
u8 clock()
{
int tap_14 = BIT(m_shift, 13);
int tap_17 = BIT(m_shift, 16);
int zero = (m_shift == 0) ? 1 : 0;
m_shift <<= 1;
m_shift |= tap_14 ^ tap_17 ^ zero;
return BIT(m_shift, 16);
}
// taken from the book 'mims circuit scrapbook, vol. 1'
static u32 frequency(double vdd)
{
// Vdd should be negative -6.2..-15V
if (vdd > -6.2 || vdd < -15)
throw emu_fatalerror("mm5837 frequency should be -6.2V .. -15V");
// curve fitting done in excel from this table:
// { 0, 0, 0, 0, 0, 0, 1, 2267, 8731, 16382, 23531, 32564, 38347, 40010, 37800, 33173 }
double result = 191.98*vdd*vdd*vdd + 5448.4*vdd*vdd + 43388*vdd + 105347;
// datasheet claims frequency range 24-56kHz at Vdd=-14V, but also lists
// maximum cycle times as ranging from 1.1-2.4s; since the 17-bit shift
// register cycles after 131072 clocks, we would expect the actual cycle
// times to be 2.34-5.46s at the 24-56kHz frequency range, so I'm presuming
// that it ticks 2x per "clock", effectively running at 2x the frequency
result *= 2;
// make sure the result isn't TOO crazy
result = std::max(result, 100.0);
return u32(result);
}
// leave this public for easy saving
u32 m_shift;
};
// ======================> mm5837_device
class mm5837_device : public device_t
{
public:
@ -101,7 +161,7 @@ public:
mm5837_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock = 0);
// configuration
void set_vdd_voltage(int voltage) { m_vdd = voltage; }
void set_vdd(double voltage) { m_vdd = voltage; }
auto output_callback() { return m_output_cb.bind(); }
protected:
@ -111,24 +171,42 @@ protected:
virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override;
private:
// taken from the book 'mims circuit scrapbook, vol. 1'
// this is the frequency the chip runs at when given a vdd voltage of -0 to -15
static constexpr int m_frequency[16] = { 0, 0, 0, 0, 0, 0, 1, 2267, 8731, 16382, 23531, 32564, 38347, 40010, 37800, 33173 };
// callbacks
devcb_write_line m_output_cb;
// voltage (as positive number)
int m_vdd;
// output timer
emu_timer *m_timer;
// state
uint32_t m_shift;
// internal state
devcb_write_line m_output_cb; // output callback
emu_timer *m_timer; // output timer
double m_vdd; // configured voltage
mm5837_source m_source; // noise source
};
// device type definition
// ======================> mm5837_stream_device
class mm5837_stream_device : public device_t, public device_sound_interface
{
public:
// construction/destruction
mm5837_stream_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
// configuration
void set_vdd(double voltage) { m_vdd = voltage; }
protected:
// device-level overrides
virtual void device_start() override;
// sound stream update overrides
virtual void sound_stream_update(sound_stream &stream, std::vector<read_stream_view> const &inputs, std::vector<write_stream_view> &outputs) override;
private:
sound_stream *m_stream; // sound stream
double m_vdd; // configured voltage
mm5837_source m_source; // noise source
};
// device type definitions
DECLARE_DEVICE_TYPE(MM5837, mm5837_device)
DECLARE_DEVICE_TYPE(MM5837_STREAM, mm5837_stream_device)
#endif // MAME_SOUND_MM5837_H

View File

@ -55,6 +55,7 @@
***************************************************************************/
#include "emu.h"
#include "sound/mm5837.h"
#include "audio/sente6vb.h"
#include "cpu/z80/z80.h"
#include "machine/clock.h"
@ -66,53 +67,6 @@
DEFINE_DEVICE_TYPE(SENTE6VB, sente6vb_device, "sente6vb", "Bally Sente 6VB Audio Board")
/*************************************
*
* Trivial sound device to spew
* a MM5837 noise stream to CEM3394
* inputs
*
*************************************/
DECLARE_DEVICE_TYPE(MM5837_NOISE_SOURCE, mm5837_noise_source)
class mm5837_noise_source : public device_t, public device_sound_interface
{
public:
mm5837_noise_source(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
device_t(mconfig, MM5837_NOISE_SOURCE, tag, owner, clock),
device_sound_interface(mconfig, *this),
m_stream(nullptr),
m_noise_state(0x1ffff)
{
}
protected:
// device-level overrides
virtual void device_start() override
{
m_stream = stream_alloc(0, 1, clock());
save_item(NAME(m_noise_state));
}
// sound stream update overrides
virtual void sound_stream_update(sound_stream &stream, std::vector<read_stream_view> const &inputs, std::vector<write_stream_view> &outputs) override
{
for (int sampindex = 0; sampindex < outputs[0].samples(); sampindex++)
{
outputs[0].put(sampindex, BIT(m_noise_state, 0) ? 1.0 : 0.0);
m_noise_state = (m_noise_state >> 1) | ((BIT(m_noise_state, 0) ^ BIT(m_noise_state, 3)) << 16);
}
}
private:
sound_stream *m_stream; // sound stream
u32 m_noise_state; // noise state
};
DEFINE_DEVICE_TYPE(MM5837_NOISE_SOURCE, mm5837_noise_source, "mm5837noise", "MM5837")
/*************************************
*
@ -172,7 +126,9 @@ void sente6vb_device::device_add_mconfig(machine_config &config)
SPEAKER(config, "mono").front_center();
mm5837_noise_source &noise(MM5837_NOISE_SOURCE(config, "noise", 100000));
mm5837_stream_device &noise(MM5837_STREAM(config, "noise", 0));
// noise.set_vdd(-6.5); // seems too low -- possible the mapping in mm5837 is wrong
noise.set_vdd(-8.0);
for (auto &cem_device : m_cem_device)
{
@ -180,7 +136,7 @@ void sente6vb_device::device_add_mconfig(machine_config &config)
cem_device->set_vco_zero_freq(431.894);
cem_device->set_filter_zero_freq(1300.0);
cem_device->add_route(ALL_OUTPUTS, "mono", 0.90);
noise.add_route(0, *cem_device, 1.0);
noise.add_route(0, *cem_device, 0.5);
}
}

View File

@ -554,7 +554,7 @@ void beezer_state::beezer(machine_config &config)
// schematics show an input labeled VCO to channel 2, but the source is unknown
mm5837_device &noise(MM5837(config, "noise"));
noise.set_vdd_voltage(12);
noise.set_vdd(-12);
noise.output_callback().set(FUNC(beezer_state::noise_w));
SPEAKER(config, "speaker").front_center();