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" #include "mm5837.h"
//**************************************************************************
// CONSTEXPR DEFINITIONS
//**************************************************************************
constexpr int mm5837_device::m_frequency[];
//************************************************************************** //**************************************************************************
// DEVICE DEFINITIONS // DEVICE DEFINITIONS
//************************************************************************** //**************************************************************************
DEFINE_DEVICE_TYPE(MM5837, mm5837_device, "mm5837", "MM5837 Digital Noise Source") 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) : mm5837_device::mm5837_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
device_t(mconfig, MM5837, tag, owner, clock), device_t(mconfig, MM5837, tag, owner, clock),
m_output_cb(*this), m_output_cb(*this),
m_vdd(0),
m_timer(nullptr), m_timer(nullptr),
m_shift(0) m_vdd(-12)
{ {
} }
//------------------------------------------------- //-------------------------------------------------
// device_start - device-specific startup // device_start - device-specific startup
//------------------------------------------------- //-------------------------------------------------
@ -56,36 +50,70 @@ void mm5837_device::device_start()
m_timer = timer_alloc(0); m_timer = timer_alloc(0);
// register for save states // register for save states
save_item(NAME(m_shift)); save_item(NAME(m_source.m_shift));
} }
//------------------------------------------------- //-------------------------------------------------
// device_reset - device-specific reset // device_reset - device-specific reset
//------------------------------------------------- //-------------------------------------------------
void mm5837_device::device_reset() void mm5837_device::device_reset()
{ {
// initialize with something m_source.reset();
m_shift = 123456;
if (m_vdd < 16) 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 else
throw emu_fatalerror("%s: Invalid voltage: %d\n", tag(), m_vdd); throw emu_fatalerror("%s: Invalid voltage: %d\n", tag(), m_vdd);
} }
//------------------------------------------------- //-------------------------------------------------
// device_timer - handle timer callbacks // device_timer - handle timer callbacks
//------------------------------------------------- //-------------------------------------------------
void mm5837_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) void mm5837_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
{ {
int tap_14 = BIT(m_shift, 13); m_output_cb(m_source.clock());
int tap_17 = BIT(m_shift, 16); }
int zero = (m_shift == 0) ? 1 : 0;
m_shift <<= 1;
m_shift |= tap_14 ^ tap_17 ^ zero; //**************************************************************************
// MM5837 STREAM DEVICE
m_output_cb(BIT(m_shift, 16)); //**************************************************************************
//-------------------------------------------------
// 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 // 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 class mm5837_device : public device_t
{ {
public: public:
@ -101,7 +161,7 @@ public:
mm5837_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock = 0); mm5837_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock = 0);
// configuration // 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(); } auto output_callback() { return m_output_cb.bind(); }
protected: protected:
@ -111,24 +171,42 @@ protected:
virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override; virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override;
private: private:
// taken from the book 'mims circuit scrapbook, vol. 1' // internal state
// this is the frequency the chip runs at when given a vdd voltage of -0 to -15 devcb_write_line m_output_cb; // output callback
static constexpr int m_frequency[16] = { 0, 0, 0, 0, 0, 0, 1, 2267, 8731, 16382, 23531, 32564, 38347, 40010, 37800, 33173 }; emu_timer *m_timer; // output timer
double m_vdd; // configured voltage
// callbacks mm5837_source m_source; // noise source
devcb_write_line m_output_cb;
// voltage (as positive number)
int m_vdd;
// output timer
emu_timer *m_timer;
// state
uint32_t m_shift;
}; };
// 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, mm5837_device)
DECLARE_DEVICE_TYPE(MM5837_STREAM, mm5837_stream_device)
#endif // MAME_SOUND_MM5837_H #endif // MAME_SOUND_MM5837_H

View File

@ -55,6 +55,7 @@
***************************************************************************/ ***************************************************************************/
#include "emu.h" #include "emu.h"
#include "sound/mm5837.h"
#include "audio/sente6vb.h" #include "audio/sente6vb.h"
#include "cpu/z80/z80.h" #include "cpu/z80/z80.h"
#include "machine/clock.h" #include "machine/clock.h"
@ -66,53 +67,6 @@
DEFINE_DEVICE_TYPE(SENTE6VB, sente6vb_device, "sente6vb", "Bally Sente 6VB Audio Board") 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(); 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) 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_vco_zero_freq(431.894);
cem_device->set_filter_zero_freq(1300.0); cem_device->set_filter_zero_freq(1300.0);
cem_device->add_route(ALL_OUTPUTS, "mono", 0.90); 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 // schematics show an input labeled VCO to channel 2, but the source is unknown
mm5837_device &noise(MM5837(config, "noise")); mm5837_device &noise(MM5837(config, "noise"));
noise.set_vdd_voltage(12); noise.set_vdd(-12);
noise.output_callback().set(FUNC(beezer_state::noise_w)); noise.output_callback().set(FUNC(beezer_state::noise_w));
SPEAKER(config, "speaker").front_center(); SPEAKER(config, "speaker").front_center();