diff options
Diffstat (limited to 'src/devices/sound/va_vca.h')
| -rw-r--r-- | src/devices/sound/va_vca.h | 121 |
1 files changed, 77 insertions, 44 deletions
diff --git a/src/devices/sound/va_vca.h b/src/devices/sound/va_vca.h index 2ae9dbe9073..3938fd0ee19 100644 --- a/src/devices/sound/va_vca.h +++ b/src/devices/sound/va_vca.h @@ -44,6 +44,9 @@ DECLARE_DEVICE_TYPE(CA3280_VCA_LIN, ca3280_vca_lin_device) // (input 1), by a device in va_eg.h, for example. When the cv is provided via a // stream, this is also a ring modulator. // +// This can also emulate a differential amplifier, by supplying a fixed or +// streaming inverting input. +// // The CV for this device is simply the gain (output = gain * input). class va_vca_device : public device_t, public device_sound_interface { @@ -52,6 +55,7 @@ public: { INPUT_AUDIO = 0, INPUT_GAIN, + INPUT_AUDIO_INV, }; va_vca_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock = 0) ATTR_COLD; @@ -60,12 +64,24 @@ public: // each (sub)class documentation. void set_fixed_gain_cv(float gain_cv); + // Sets the inverting (-) input to a fixed value. Defaults to 0. + void set_fixed_inv_input(float x); + + // Applies input differencing. This happens before gain is applied. + // Subclasses can override diff() to apply additional processing such as + // prescaling and distortion. + // Public because it is useful for calibrating and debugging. + // p ~ non-inverting input ("plus"). + // m ~ inverting input ("minus"). + virtual float diff(float p, float m) const; + protected: va_vca_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) ATTR_COLD; + void update(); + virtual float cv_to_gain(float cv) const; - virtual float distorted(float s) const; - virtual bool has_distortion() const { return false; } + virtual u32 preferred_sample_rate() const; void device_start() override ATTR_COLD; void sound_stream_update(sound_stream &stream) override; @@ -73,6 +89,7 @@ protected: private: sound_stream *m_stream; float m_fixed_gain; + float m_fixed_inv_input; }; @@ -84,27 +101,30 @@ private: // considered linear for very small input voltages (~[-0.02 - 0.02]). See // figure 3B in the datasheet. // -// ______ Iabc -// | \ | -// A --- Rin ---+--- B --- |+ \ | -// | | \ | -// Rgnd | \ | -// | | OO---- C ----+ -// GND | / | -// | / Rout -// +--------- |- Id / | -// | |___|__/ GND -// Rgnd | -// | | -// GND V- +// ______ Iabc +// | \ | +// A --- Rin+ ---+--- B --- |+ \ | +// | | \ | +// Rgnd+ | \ | +// | | OO---- F ----+ +// GND | / | +// | / Rout +// [D -- Rin- --]+--- E --- |- Id / | +// | |___|__/ GND +// Rgnd- | +// | | +// GND V- // // The streaming input should either be the voltage at point B, or at point A, // depending on how the object is configured. // +// An (optional) inverting input (fixed or streaming) is also supported. It +// should be the voltage at point E, or at point D, depending on configuration. +// // The gain CV (fixed or streaming) should be the control current (Iabc), in // Amperes. // -// The streaming output will be the output current at point C (the CA3280 is a +// The streaming output will be the output current at point F (the CA3280 is a // current source), but the object can be configured to output a voltage instead. // class ca3280_vca_device : public va_vca_device @@ -112,22 +132,27 @@ class ca3280_vca_device : public va_vca_device public: ca3280_vca_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock = 0) ATTR_COLD; - // By default, the streaming input should be the voltage at point B. - // This method will configure the input to be the voltage at point A. - ca3280_vca_device &configure_input_divider(float r_in, float r_gnd) ATTR_COLD; + // By default, the inputs should be the voltages at points B and E. + // A common setup is to have voltage dividers at the input(s), which can be + // configured by these methods. If dividers are configured, the inputs + // should be the voltages at points A and D. + ca3280_vca_device &configure_plus_divider(float r_in, float r_gnd) ATTR_COLD; + ca3280_vca_device &configure_minus_divider(float r_in, float r_gnd) ATTR_COLD; - // By default, the streaming output will be the current at point C. This - // method will configure the output to be the voltage at point C. + // By default, the streaming output will be the current at point F. This + // method will configure the output to be the voltage at point F. ca3280_vca_device &configure_voltage_output(float r_out) ATTR_COLD; + float diff(float p, float m) const override; + protected: float cv_to_gain(float cv) const override; - float distorted(float s) const override; - bool has_distortion() const override { return true; } + u32 preferred_sample_rate() const override; private: // Configuration. Not needed in save state. - float m_input_scale; + float m_plus_scale; + float m_minus_scale; float m_output_scale; }; @@ -136,36 +161,31 @@ private: // to a current source, often a resistor to the positive supply. // // In this configuration, the CA3280 is linear for a wide voltage range, but it -// will hard-clip when Iout approaches Iabc (TODO: clipping is not currently +// will hard-clip when Iin approaches Id (TODO: clipping is not currently // emulated). See figure 3A in the datasheet. // -// Note that, in contrast to the non-linearized configuration above, it is more -// appropriate to treat the inputs as current inputs, rather than voltage inputs. -// // ______ Iabc // | \ | -// A --- Rin+ --- B --- |+ \ | +// A ---- Rin+ ---- |+ \ | // | \ | // | \ | -// | OO---- C ----+ +// | OO---- F ----+ // | / | // | / Rout -// GND --- Rin- --- |- Id / | +// B ---- Rin- ---- |- Id / | // |___|__/ GND // | // + ---- Rd --- V+ // -// The streaming input should be the *current* at point B (the + input is at near -// ground potential). But it can be configured to be the voltage at point A. +// Usually, Rin+ = Rin- and B = GND. When that's the case: +// In = V_A / Rin+ and Iout = In * 0.82 * Iabc / Id. // // The gain CV (fixed or streaming) should be the control current (Iabc), in // Amperes. // -// The streaming output will be the output current at point C (the CA3280 is a +// The streaming output will be the output current at point F (the CA3280 is a // current source), but the object can be configured to output a voltage instead. // -// This implementation assumes Rin- == Rin+, which is typical. -// class ca3280_vca_lin_device : public va_vca_device { public: @@ -182,27 +202,40 @@ public: // Don't use. ca3280_vca_lin_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) ATTR_COLD; - // By default, the streaming input should be the *current* at point B. - // This method will configure the input to be the voltage at point A. - ca3280_vca_lin_device &configure_voltage_input(float r_in) ATTR_COLD; - - // By default, the streaming output will be the current at point C. This - // method will configure the output to be the voltage at point C. + // By default, the streaming output will be the current at point F. This + // method will configure the output to be the voltage at point F. ca3280_vca_lin_device &configure_voltage_output(float r_out) ATTR_COLD; + // These set Rin+ and Rin-. They must be called at least once and they + // can change at runtime. + // If the input voltage is applied though a resistor network, such as a + // trimming circuit, use the Thevenin-equivalent resistance. Remember to + // also feed the Thevenin-equivalent voltage to the input(s) in that case. + ca3280_vca_lin_device &set_rplus(float r); + ca3280_vca_lin_device &set_rminus(float r); + + float diff(float p, float m) const override; + protected: float cv_to_gain(float cv) const override; + void device_start() override ATTR_COLD; + void device_reset() override ATTR_COLD; + private: void update_cv_scale(); static float i_d(float r, float v_r, float v_minus) ATTR_COLD; // Configuration. Not needed in save state. - const float m_i_d_inv; - float m_input_scale; + const float m_id; float m_output_scale; float m_cv_scale; + + // state + float m_rp; + float m_rm; + float m_r_inv; }; #endif // MAME_SOUND_VA_VCA_H |
