AY8910_RESISTOR_OUTPUT now selects resistance calculation by simple saturation mosfet model in ay8910.c. Currently only two drivers use this: 1942 and popeye.

This commit is contained in:
Couriersud 2014-07-09 19:20:11 +00:00
parent cb96fc035c
commit 1f49d873fb
4 changed files with 82 additions and 14 deletions

View File

@ -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::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),

View File

@ -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;

View File

@ -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

View File

@ -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)