diff options
Diffstat (limited to 'src/devices/sound/hc55516.h')
-rw-r--r-- | src/devices/sound/hc55516.h | 165 |
1 files changed, 123 insertions, 42 deletions
diff --git a/src/devices/sound/hc55516.h b/src/devices/sound/hc55516.h index 96284167c52..48c1b768a4f 100644 --- a/src/devices/sound/hc55516.h +++ b/src/devices/sound/hc55516.h @@ -1,95 +1,176 @@ // license:BSD-3-Clause -// copyright-holders:Aaron Giles +// copyright-holders:Aaron Giles, Jonathan Gevaryahu +// thanks-to:Zonn Moore #ifndef MAME_SOUND_HC55516_H #define MAME_SOUND_HC55516_H #pragma once -class hc55516_device : public device_t, public device_sound_interface +class cvsd_device_base : public device_t, public device_sound_interface { public: - hc55516_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); - - /* sets the digit (0 or 1) */ - void digit_w(int digit); - - /* sets the clock state (0 or 1, clocked on the rising edge) */ - void clock_w(int state); - - /* returns whether the clock is currently LO or HI */ - int clock_state_r(); + enum + { + RISING=true, + FALLING=false + }; + + auto clock_state_cb() { return m_clock_state_push_cb.bind(); } // A clock state change callback. Using this is a bad idea due to lack of synchronization to other devices. TODO: remove this. + auto digin_cb() { return m_digin_pull_cb.bind(); } // Digital in pull callback function, for use if a clock is specified and we need to pull in the digital in pin state, otherwise unused. TODO: this is not hooked up yet, and should be. + auto digout_cb() { return m_digout_push_cb.bind(); } // Digital out push callback function. TODO: this is not hooked up or implemented yet, although it is only really relevant for devices which use the CVSD chips in encode mode. + + READ_LINE_MEMBER( clock_r ); // Clock pull, really only relevant of something manually polls the clock (and clock is specified), which is a very bad design pattern and will cause synchronization/missed clock transition issues. This function WILL ASSERT if it is called and the clock hz is NOT specified! TODO: remove all use of this, and remove it. + WRITE_LINE_MEMBER( mclock_w ); // Clock push; this function WILL ASSERT if it is called and the clock hz IS specified! + WRITE_LINE_MEMBER( digin_w ); // Digital in push to the pin, as a pseudo 'buffer' implemented within the cvsd device itself. This is not technically accurate to hardware, and in the future should be deprecated in favor of digin_cb once the latter is implemented. + WRITE_LINE_MEMBER( dec_encq_w ); //DEC/ENC decode/encode select push. This is not implemented yet, and relies on an input audio stream. TODO: implement this beyond a do-nothing stub + READ_LINE_MEMBER( digout_r ); // Digital out pull. TODO: this is not hooked up or implemented yet, although it is only really relevant for devices which use the CVSD chips in encode mode. + //void audio_in_w(stream_buffer::sample_t data); // Audio In pin, an analog value of the audio waveform being pushed to the chip. TODO: this is not hooked up or implemented yet, and this should really be handled as an input stream from a separate DAC device, not a value push function at all. + void digit_w(int digit); /* sets the buffered digit (0 or 1), common to all chips. TODO: replace all use of this with digin_cb once implemented */ + void clock_w(int state); /* sets the clock state (0 or 1, clocked on the rising edge), common to all chips */ + virtual int clock_state_r(); /* returns whether the clock is currently LO or HI, common to all chips. TODO: get rid of all use of this, then get rid of it. */ protected: - hc55516_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock); + 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-level overrides virtual void device_start() override; virtual void device_reset() override; + //virtual void device_clock_changed() override; // sound stream update overrides - virtual void sound_stream_update_legacy(sound_stream &stream, stream_sample_t const * const *inputs, stream_sample_t * const *outputs, int samples) override; + virtual void sound_stream_update(sound_stream &stream, std::vector<read_stream_view> const &inputs, std::vector<write_stream_view> &outputs) override; - void start_common(uint8_t _shiftreg_mask, int _active_clock_hi); + // callbacks + devcb_write_line m_clock_state_push_cb; ///TODO: get rid of this, if you use it you should feel bad + devcb_read_line m_digin_pull_cb; + devcb_write_line m_digout_push_cb; - // internal state - sound_stream *m_channel; - int m_active_clock_hi; - uint8_t m_shiftreg_mask; + // const state defined by constructor + const bool m_active_clock_edge; + const uint8_t m_shiftreg_mask; // it may be desirable to allow this to be changed by the user under some circumstances - uint8_t m_last_clock_state; - uint8_t m_digit; - uint8_t m_new_digit; + // internal state + sound_stream *m_stream; + bool m_last_clock_state; + bool m_buffered_bit; uint8_t m_shiftreg; + stream_buffer::sample_t m_curr_sample; + stream_buffer::sample_t m_next_sample; + uint32_t m_samples_generated; - int16_t m_curr_sample; - int16_t m_next_sample; + // specific internal handler overrides, overridden by each chip + virtual void process_bit(bool bit, bool clock_state); - uint32_t m_update_count; + ///TODO: get rid of these + inline bool is_external_oscillator(); + inline bool is_clock_changed(bool clock_state); + inline bool is_active_clock_transition(bool clock_state); + inline bool current_clock_state(); - double m_filter; - double m_integrator; - - double m_charge; - double m_decay; - double m_leak; - - inline int is_external_oscillator(); - inline int is_active_clock_transition(int clock_state); - inline int current_clock_state(); - void process_digit(); }; -class mc3417_device : public hc55516_device +class hc55516_device : public cvsd_device_base { public: - mc3417_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); + hc55516_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); + + auto fzq_cb() { return m_fzq_pull_cb.bind(); } // /FZ (partial reset) pull callback, ok to leave unconnected (we assume it is pulled high) + auto agc_cb() { return m_agc_push_cb.bind(); } // AGC callback function, called to push the state if the AGC pin changes, ok to leave unconnected + + WRITE_LINE_MEMBER( fzq_w ); // /FZ (partial reset) push + READ_LINE_MEMBER( agc_r ); // AGC pull + /* TODO: These are only relevant for encode mode, which isn't done yet! */ + //WRITE_LINE_MEMBER( aptq_w ); // /APT (silence encoder output) push + //WRITE_LINE_MEMBER( dec_encq_w ); // DEC/ENC decode/encode select push protected: + // overridable type for subclass + 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); + // device-level overrides virtual void device_start() override; + virtual void device_reset() override; // sound stream update overrides - virtual void sound_stream_update_legacy(sound_stream &stream, stream_sample_t const * const *inputs, stream_sample_t * const *outputs, int samples) override; + virtual void sound_stream_update(sound_stream &stream, std::vector<read_stream_view> const &inputs, std::vector<write_stream_view> &outputs) override; + + // callbacks + devcb_write_line m_agc_push_cb; + devcb_read_line m_fzq_pull_cb; + + // const coefficients defined by constructor + const uint32_t m_sylmask; + const int32_t m_sylshift; + const int32_t m_syladd; + const int32_t m_intshift; + + // internal state + int32_t m_sylfilter; + int32_t m_intfilter; + bool m_agc; + bool m_buffered_fzq; + + // internal handlers + virtual void process_bit(bool bit, bool clock_state) override; }; -class mc3418_device : public hc55516_device +class hc55532_device : public hc55516_device { public: - mc3418_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); + hc55532_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); +protected: + // device-level overrides + virtual void device_reset() override; +}; + + +class mc3417_device : public cvsd_device_base +{ +public: + mc3417_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); + + // override for clock_w + //virtual void clock_w(int state) override; protected: + // overridable type for subclass + mc3417_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock, uint8_t shiftreg_mask); + // device-level overrides virtual void device_start() override; // sound stream update overrides - virtual void sound_stream_update_legacy(sound_stream &stream, stream_sample_t const * const *inputs, stream_sample_t * const *outputs, int samples) override; + virtual void sound_stream_update(sound_stream &stream, std::vector<read_stream_view> const &inputs, std::vector<write_stream_view> &outputs) override; + + // const coefficients defined by constructor; should these be adjustable by the user or externally defined, as they are implemented using a set of two small lowpass filters outside the chip? + const double m_charge; + const double m_decay; + const double m_leak; + + // internal state + double m_sylfilter_d; + double m_intfilter_d; + + // internal handlers + virtual void process_bit(bool bit, bool clock_state) override; +}; + + +class mc3418_device : public mc3417_device +{ +public: + mc3418_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); }; DECLARE_DEVICE_TYPE(HC55516, hc55516_device) +DECLARE_DEVICE_TYPE(HC55532, hc55532_device) +//DECLARE_DEVICE_TYPE(HC55536, hc55536_device) +//DECLARE_DEVICE_TYPE(HC55564, hc55564_device) DECLARE_DEVICE_TYPE(MC3417, mc3417_device) +//DECLARE_DEVICE_TYPE(MC34115, mc34115_device) DECLARE_DEVICE_TYPE(MC3418, mc3418_device) #endif // MAME_SOUND_HC55516_H |