From 1f49d873fb6860f68405d549e02ab0a8c82932aa Mon Sep 17 00:00:00 2001 From: Couriersud Date: Wed, 9 Jul 2014 19:20:11 +0000 Subject: [PATCH] AY8910_RESISTOR_OUTPUT now selects resistance calculation by simple saturation mosfet model in ay8910.c. Currently only two drivers use this: 1942 and popeye. --- src/emu/sound/ay8910.c | 73 +++++++++++++++++++++++++++++++++------ src/emu/sound/ay8910.h | 11 +++++- src/mame/drivers/1942.c | 10 ++++-- src/mame/drivers/popeye.c | 2 ++ 4 files changed, 82 insertions(+), 14 deletions(-) diff --git a/src/emu/sound/ay8910.c b/src/emu/sound/ay8910.c index b5c62246e11..00d371bded7 100644 --- a/src/emu/sound/ay8910.c +++ b/src/emu/sound/ay8910.c @@ -88,13 +88,13 @@ * * Whilst conducting, the FET operates in saturation mode: * - * Id = Kn * (Vgs - Vtn)^2 + * Id = Kn * (Vgs - Vth)^2 * * Using Id = Vs / RD * - * Vs = Kn * RD * (Vg - Vs - Vtn)^2 + * Vs = Kn * RD * (Vg - Vs - Vth)^2 * - * finally using Vg' = Vg - Vtn + * finally using Vg' = Vg - Vth * * Vs = Vg' + 1 / (2 * Kn * RD) - sqrt((Vg' + 1 / (2 * Kn * RD))^2 - Vg'^2) * @@ -386,14 +386,43 @@ static const ay8910_device::ay_ym_param ay8910_param = * RD was measured on a real chip to be 8m Ohm, RU was 0.8m Ohm. */ + static const ay8910_device::ay_ym_param ay8910_param = { - 800000, 8000000, - 16, - { 15950, 15350, 15090, 14760, 14275, 13620, 12890, 11370, - 10600, 8590, 7190, 5985, 4820, 3945, 3017, 2345 } + 800000, 8000000, + 16, + { 15950, 15350, 15090, 14760, 14275, 13620, 12890, 11370, + 10600, 8590, 7190, 5985, 4820, 3945, 3017, 2345 } }; +static const ay8910_device::mosfet_param ay8910_mosfet_param = +{ + 1.465385778, + 4.9, + 16, + { + 0.00076, + 0.80536, + 1.13106, + 1.65952, + 2.42261, + 3.60536, + 5.34893, + 8.96871, + 10.97202, + 19.32370, + 29.01935, + 38.82026, + 55.50539, + 78.44395, + 109.49257, + 153.72985, + } +}; + + + + /************************************* * * Inline @@ -492,7 +521,7 @@ INLINE void build_single_table(double rl, const ay8910_device::ay_ym_param *par, } -INLINE void build_resisor_table(const ay8910_device::ay_ym_param *par, INT32 *tab, int zero_is_off) +INLINE void build_resistor_table(const ay8910_device::ay_ym_param *par, INT32 *tab, int zero_is_off) { int j; @@ -507,6 +536,23 @@ INLINE void build_resisor_table(const ay8910_device::ay_ym_param *par, INT32 *ta } } +INLINE void build_mosfet_resistor_table(const ay8910_device::mosfet_param &par, const double rd, INT32 *tab) +{ + int j; + + for (j=0; j < par.m_count; j++) + { + const double Vd = 5.0; + const double Vg = par.m_Vg - par.m_Vth; + const double kn = par.m_Kn[j] / 1.0e6; + const double p2 = 1.0 / (2.0 * kn * rd); + const double Vs = Vg + p2 - sqrt(p2 * p2 - Vg * Vg); + + const double res = rd * ( Vd / Vs - 1.0); + tab[j] = res; + } +} + UINT16 ay8910_device::mix_3D() { @@ -782,10 +828,13 @@ void ay8910_device::build_mixer_table() if ((m_flags & AY8910_RESISTOR_OUTPUT) != 0) { - for (chan=0; chan < AY8910_NUM_CHANNELS; chan++) + if (m_type != PSG_TYPE_AY) + fatalerror("AY8910_RESISTOR_OUTPUT currently only supported for AY8910 devices."); + + for (chan=0; chan < AY8910_NUM_CHANNELS; chan++) { - build_resisor_table(m_par, m_vol_table[chan], m_zero_is_off); - build_resisor_table(m_par_env, m_env_table[chan], 0); + build_mosfet_resistor_table(ay8910_mosfet_param, m_res_load[chan], m_vol_table[chan]); + build_mosfet_resistor_table(ay8910_mosfet_param, m_res_load[chan], m_vol_table[chan]); } } else @@ -1075,6 +1124,7 @@ const device_type AY8910 = &device_creator; ay8910_device::ay8910_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) : device_t(mconfig, AY8910, "AY-3-8910A", tag, owner, clock, "ay8910", __FILE__), device_sound_interface(mconfig, *this), + m_type(PSG_TYPE_AY), m_streams(3), m_ioports(2), m_ready(0), @@ -1116,6 +1166,7 @@ ay8910_device::ay8910_device(const machine_config &mconfig, device_type type, co psg_type_t psg_type, int streams, int ioports, const char *shortname, const char *source) : device_t(mconfig, type, name, tag, owner, clock, shortname, source), device_sound_interface(mconfig, *this), + m_type(psg_type), m_streams(streams), m_ioports(ioports), m_ready(0), diff --git a/src/emu/sound/ay8910.h b/src/emu/sound/ay8910.h index 62c92f96e4b..537f7ec6109 100644 --- a/src/emu/sound/ay8910.h +++ b/src/emu/sound/ay8910.h @@ -133,7 +133,15 @@ public: int res_count; double res[32]; }; - + + struct mosfet_param + { + double m_Vth; + double m_Vg; + int m_count; + double m_Kn[32]; + }; + void ay8910_write_ym(int addr, int data); int ay8910_read_ym(); void ay8910_reset_ym(); @@ -154,6 +162,7 @@ private: void ay8910_statesave(); // internal state + psg_type_t m_type; int m_streams; int m_ioports; int m_ready; diff --git a/src/mame/drivers/1942.c b/src/mame/drivers/1942.c index c5eb3b39f57..213378bb3eb 100644 --- a/src/mame/drivers/1942.c +++ b/src/mame/drivers/1942.c @@ -84,6 +84,7 @@ static NETLIST_START(nl_1942) SOLVER(Solver, 48000) ANALOG_INPUT(V5, 5) + PARAM(Solver.ACCURACY, 1e-10) /* AY 8910 internal resistors */ @@ -138,7 +139,9 @@ static NETLIST_START(nl_1942) NET_C(CC6.1, VR.2) NET_C(CC6.2, R1.1) - NET_C(R1.2, GND) + CAP(CC3, 220e-6) + NET_C(R1.2, CC3.1) + NET_C(CC3.2, GND) NETLIST_END() @@ -549,12 +552,15 @@ static MACHINE_CONFIG_START( 1942, _1942_state ) MCFG_SOUND_ADD("ay1", AY8910, AUDIO_CLOCK) /* 1.5 MHz */ MCFG_AY8910_OUTPUT_TYPE(AY8910_RESISTOR_OUTPUT) + MCFG_AY8910_RES_LOADS(10000.0, 10000.0, 10000.0) MCFG_SOUND_ROUTE_EX(0, "snd_nl", 1.0, 0) MCFG_SOUND_ROUTE_EX(1, "snd_nl", 1.0, 1) MCFG_SOUND_ROUTE_EX(2, "snd_nl", 1.0, 2) + MCFG_SOUND_ADD("ay2", AY8910, AUDIO_CLOCK) /* 1.5 MHz */ MCFG_AY8910_OUTPUT_TYPE(AY8910_RESISTOR_OUTPUT) + MCFG_AY8910_RES_LOADS(10000.0, 10000.0, 10000.0) MCFG_SOUND_ROUTE_EX(0, "snd_nl", 1.0, 3) MCFG_SOUND_ROUTE_EX(1, "snd_nl", 1.0, 4) @@ -565,7 +571,6 @@ static MACHINE_CONFIG_START( 1942, _1942_state ) MCFG_SOUND_ADD("snd_nl", NETLIST_SOUND, 48000) MCFG_NETLIST_SETUP(nl_1942) MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 5.0) - MCFG_NETLIST_STREAM_INPUT("snd_nl", 0, "R_AY1_1.R") MCFG_NETLIST_STREAM_INPUT("snd_nl", 1, "R_AY1_2.R") MCFG_NETLIST_STREAM_INPUT("snd_nl", 2, "R_AY1_3.R") @@ -574,6 +579,7 @@ static MACHINE_CONFIG_START( 1942, _1942_state ) MCFG_NETLIST_STREAM_INPUT("snd_nl", 5, "R_AY2_3.R") MCFG_NETLIST_STREAM_OUTPUT("snd_nl", 0, "R1.1") + //MCFG_NETLIST_STREAM_OUTPUT("snd_nl", 0, "VR.2") MCFG_NETLIST_ANALOG_MULT_OFFSET(100000.0, 0.0) MACHINE_CONFIG_END diff --git a/src/mame/drivers/popeye.c b/src/mame/drivers/popeye.c index c3bf61bffca..84993f88246 100644 --- a/src/mame/drivers/popeye.c +++ b/src/mame/drivers/popeye.c @@ -53,6 +53,7 @@ static NETLIST_START(nl_popeye) SOLVER(Solver, 48000) PARAM(Solver.ACCURACY, 1e-5) + PARAM(Solver.LTE, 5e-2) // Default is not enough for paddle control ANALOG_INPUT(V5, 5) /* AY 8910 internal resistors */ @@ -481,6 +482,7 @@ static MACHINE_CONFIG_DERIVED( popeye, skyskipr ) MCFG_SOUND_MODIFY("aysnd") MCFG_SOUND_ROUTES_RESET() MCFG_AY8910_OUTPUT_TYPE(AY8910_RESISTOR_OUTPUT) /* Does Sky Skipper have the same filtering? */ + MCFG_AY8910_RES_LOADS(2000.0, 2000.0, 2000.0) MCFG_AY8910_PORT_A_READ_CB(IOPORT("DSW0")) MCFG_AY8910_PORT_B_WRITE_CB(WRITE8(popeye_state, popeye_portB_w)) MCFG_SOUND_ROUTE_EX(0, "snd_nl", 1.0, 0)