summaryrefslogblamecommitdiffstatshomepage
path: root/src/mame/audio/vicdual.cpp
blob: e1041277ee752799751f66598622561cac3a7d39 (plain) (tree)
1
2
3
4
5
6
7
8
9
                       
                                                            





                                                                          
                
                             
 
                              
                           






                                                                          






                                       
 





                                        


                                               


                                                                                                                     
                                                


                               
                                                                 

            

                                                     


                                                                                 
                                                


                              
                                                                 

            
 
                                                                                

                                  
                                                
  
 
                                                                                

                                  
                                                                                               
  

                                                 





                                              

                                                 





                                                                       


                                                
                                           
                                    
                           
                               





                                                 








                                              








                                              









                                                                                 

  
                                                               



                                      
 
                                            
                                                         


                                                          








                                                         





                                                          




                                                                              


                              

                                                                                                        


                                                                                                          
                                                                            
                                                                 

                                                         

                                                          




                                                                              


                              

                                                                                                        


                                                                                                          
                                                                            
                                                               

                                                         

                                                          
 
                                                        



                                                                                                                                  

                                                          
 
                                                        


                                                                                                                                  

                                                          
 
                                                       
                                             


                                                                                                               








                                                                                       
                                                                  
                                                                                           
                                                                   

                                                         


                                                          
 
                                                       

                                                                                          
                                                    







                                                                                            
                                                    



                                                                       
                                                                                                          

                                                                          
                                                                 

                                                         

                                                          









                                                                                          




                                                        
 
                                                
 
                                  
                       






                                                             


 
                                                
 
                                  
                       






                                                             


 


                                      
                                


                                       

                                                                                                                                                                                                                                
                                               



                                                 


 
                                                                          

                                                
                                      

                                                    

















                                                                                                          

 
                                              



                                       
                                               









                                                                                           






                                       
                                                                                                           
















                                                                                                                              








                                                                                                                 
                                                                                                          
      

 





































































                                                                                                                                                                               
// license:BSD-3-Clause
// copyright-holders:Derrick Renaud, Couriersud, Aaron Giles
/*************************************************************************

    VIC Dual Game board

*************************************************************************/

#include "emu.h"
#include "includes/vicdual.h"

#include "audio/nl_brdrline.h"
#include "audio/nl_frogs.h"


/************************************************************************
 * headon Sound System Analog emulation
 * July 2007, couriersud
 ************************************************************************/

#define HEADON_HISPEED_CC_EN    NODE_01
#define HEADON_HISPEED_PC_EN    NODE_02
#define HEADON_CAR_ON_EN        NODE_03
#define HEADON_CRASH_EN         NODE_04
#define HEADON_SCREECH1_EN      NODE_05
#define HEADON_SCREECH2_EN      NODE_06
#define HEADON_BONUS_EN         NODE_07

#define HEADON_COMP_CAR_OUT     NODE_200
#define HEADON_PLAYER_CAR_OUT   NODE_201
#define HEADON_CRASH_OUT        NODE_202
#define HEADON_SCREECH1_OUT     NODE_203
#define HEADON_SCREECH2_OUT     NODE_204
#define HEADON_BONUS_OUT        NODE_205


static const discrete_mixer_desc headon_mixer =
{
	DISC_MIXER_IS_RESISTOR,
	{RES_K(130), RES_K(130), RES_K(100), RES_K(100), RES_K(100), RES_K(10)},   // 130 = 390/3, Bonus Res is dummy
	{0,0,0,0,0},    // no variable resistors
	{0,0,0,0,CAP_N(470),0},
	0, RES_K(100),
	0,
	CAP_U(1),       // not in schematics, used to suppress DC
	0, 1
};

static const discrete_mixer_desc headon_crash_mixer =
{
	DISC_MIXER_IS_OP_AMP,
	{RES_K(50), RES_K(10)},   // Resistors, in fact variable resistors (100k)
	{0,0,0,0,0},    // no variable resistors
	{CAP_N(100),CAP_U(1)},
	0, RES_K(100),
	0,
	CAP_U(1)*0,     // not in schematics, used to suppress DC
	0, 1
};

static const discrete_dss_inverter_osc_node::description headon_inverter_osc_1 =
{
	DEFAULT_CD40XX_VALUES(12),
	discrete_dss_inverter_osc_node::IS_TYPE4
};

static const discrete_dss_inverter_osc_node::description headon_inverter_osc_2 =
{
	DEFAULT_CD40XX_VALUES(12),
	discrete_dss_inverter_osc_node::IS_TYPE5 | discrete_dss_inverter_osc_node::OUT_IS_LOGIC
};

static const discrete_555_desc headon_555_bonus =
{
	DISC_555_OUT_ENERGY | DISC_555_OUT_DC,
	12,
	DEFAULT_555_CHARGE,
	12.0-0.5
};

static const discrete_555_desc headon_555_crash =
{
	DISC_555_OUT_SQW | DISC_555_OUT_DC | DISC_555_TRIGGER_IS_LOGIC,
	12,
	DEFAULT_555_CHARGE,
	12.0-0.5
};

static const discrete_555_cc_desc headon_555cc =
{
	DISC_555_OUT_SQW | DISC_555_OUT_DC,
	12,     // B+ voltage of 555
	DEFAULT_555_VALUES,
	0.6     // Q16, Q10 Vbe
};


/*
 * From : http://www.vego.nl/8/08/03/08_08_03.htm
 *
 *- voeding:  -7 V, clock-frequency:  2.267 Hz
 *- voeding:  -8 V, clock-frequency:  8.731 Hz
 *- voeding:  -9 V, clock-frequency: 16,38 kHz
 *- voeding: -10 V, clock-frequency: 23,53 kHz
 *- voeding: -11 V, clock-frequency: 32,56 kHz
 *- voeding: -12 V, clock-frequency: 38,34 kHz
 *- voeding: -13 V, clock-frequency: 40,00 kHz
 *- voeding: -14 V, clock-frequency: 37,80 kHz
 *- voeding: -15 V, clock-frequency: 33,17 kHz
 *
 *  However all other mame sources say 100kHz.
 */

#define MM5837_CLOCK_12V 100000

static const discrete_lfsr_desc mm5837_lfsr =
{
	DISC_CLK_IS_FREQ,
	17,                   /* Bit Length */
	0,                    /* Reset Value */
	13,                   /* Use Bit 14 as F0 input 0 */
	16,                   /* Use Bit 17 as F0 input 1 */
	DISC_LFSR_XOR,        /* F0 is XOR */
	DISC_LFSR_NOT_IN0,    /* F1 is inverted F0*/
	DISC_LFSR_REPLACE,    /* F2 replaces the shifted register contents */
	0x000001,             /* Everything is shifted into the first bit only */
	0,                    /* Flags */
	16                    /* Output bit */
};

static const discrete_op_amp_filt_info headon_sallen_key_info =
{
	RES_K(15), RES_K(15), 0, 0, 0,
	CAP_N(470), CAP_N(47), 0
};

static DISCRETE_SOUND_START(headon_discrete)
	/************************************************
	 * Input register mapping for headon
	 *
	 ************************************************/
	DISCRETE_INPUT_LOGIC(HEADON_HISPEED_CC_EN)
	DISCRETE_INPUT_LOGIC(HEADON_HISPEED_PC_EN)
	DISCRETE_INPUT_LOGIC(HEADON_CAR_ON_EN)
	DISCRETE_INPUT_LOGIC(HEADON_CRASH_EN)
	DISCRETE_INPUT_LOGIC(HEADON_SCREECH1_EN)
	DISCRETE_INPUT_LOGIC(HEADON_SCREECH2_EN)
	DISCRETE_INPUT_LOGIC(HEADON_BONUS_EN)

	/************************************************
	 * CAR Sound generation Player Car
	 * The ramp values are taken from a
	 * SWITCHER CAD III simulation of the
	 * respective circuit. Using ramps may not be
	 * 100% accurate but comes very close.
	 ************************************************/

	DISCRETE_RAMP(NODE_20, 1, HEADON_CAR_ON_EN, (12-10.8)/7, 12, 10.8, 12)
	DISCRETE_RAMP(NODE_21, 1, HEADON_HISPEED_PC_EN, 2.0 / 0.8, 0, -2, 0)
	DISCRETE_ADDER2(NODE_22, 1, NODE_20, NODE_21)

#define HO_R56      RES_K(10)
#define HO_R72      RES_K(1)
#define HO_C31      CAP_N(100)

	DISCRETE_555_CC(NODE_25, HEADON_CAR_ON_EN, NODE_22, HO_R56, HO_C31, 0, 0, HO_R72, &headon_555cc)
	DISCRETE_COUNTER(NODE_26, 1, 0, NODE_25, 0, 1, DISC_COUNT_UP, 0, DISC_CLK_ON_R_EDGE) //divide by 2
	DISCRETE_COUNTER(NODE_27, 1, 0, NODE_25, 0, 3, DISC_COUNT_UP, 0, DISC_CLK_ON_R_EDGE) //divide by 4
	DISCRETE_COUNTER(NODE_28, 1, 0, NODE_25, 0, 2, DISC_COUNT_UP, 0, DISC_CLK_ON_R_EDGE) //divide by 3
	DISCRETE_TRANSFORM5(NODE_29,NODE_26,NODE_27,NODE_28,1,2,"13>24=+0+")
	DISCRETE_MULTIPLY(HEADON_PLAYER_CAR_OUT, NODE_29, 12 / 3)

	/************************************************
	 * CAR Sound generation Computer Car
	 ************************************************/

	DISCRETE_RAMP(NODE_30, 1, HEADON_CAR_ON_EN, (12-10.8)/7, 12, 10.8, 12)
	DISCRETE_RAMP(NODE_31, 1, HEADON_HISPEED_CC_EN, 2.0 / 0.8, 0, -2, 0)
	DISCRETE_ADDER2(NODE_32, 1, NODE_30, NODE_31)

#define HO_R43      RES_K(10)
#define HO_R35      RES_K(1)
#define HO_C20      CAP_N(100)

	DISCRETE_555_CC(NODE_35, HEADON_CAR_ON_EN, NODE_32, HO_R43, HO_C20, 0, 0, HO_R35, &headon_555cc)
	DISCRETE_COUNTER(NODE_36, 1, 0, NODE_35, 0, 1, DISC_COUNT_UP, 0, DISC_CLK_ON_R_EDGE) //divide by 2
	DISCRETE_COUNTER(NODE_37, 1, 0, NODE_35, 0, 3, DISC_COUNT_UP, 0, DISC_CLK_ON_R_EDGE) //divide by 4
	DISCRETE_COUNTER(NODE_38, 1, 0, NODE_35, 0, 2, DISC_COUNT_UP, 0, DISC_CLK_ON_R_EDGE) //divide by 3
	DISCRETE_TRANSFORM5(NODE_39,NODE_36,NODE_37,NODE_38,1,2,"13>24=+0+")
	DISCRETE_MULTIPLY(HEADON_COMP_CAR_OUT, NODE_39, 12 / 3)

	/************************************************
	 * Screech #1
	 ************************************************/

	DISCRETE_MULTIPLY(NODE_50,HEADON_SCREECH1_EN,12)
	DISCRETE_LFSR_NOISE(NODE_51, 1, 1, MM5837_CLOCK_12V, 12.0, 0, 6.0, &mm5837_lfsr)
	DISCRETE_INVERTER_OSC(HEADON_SCREECH1_OUT,NODE_50,NODE_51,RES_K(10),RES_K(100),CAP_N(47),RES_K(10),&headon_inverter_osc_1)

	/************************************************
	 * Screech #2
	 ************************************************/

	DISCRETE_MULTIPLY(NODE_60,HEADON_SCREECH2_EN,12)
	DISCRETE_INVERTER_OSC(HEADON_SCREECH2_OUT,NODE_60,NODE_51,RES_K(10),RES_K(100),CAP_N(57),RES_K(10),&headon_inverter_osc_1)

	/************************************************
	 * Bonus
	 ************************************************/

	DISCRETE_LOGIC_INVERT(NODE_70, HEADON_BONUS_EN)
	DISCRETE_MULTIPLY(NODE_71,NODE_70,12)
	DISCRETE_INVERTER_OSC(NODE_73,NODE_71,0,RES_K(22),RES_M(1),CAP_N(470),RES_M(10),&headon_inverter_osc_2)

	/* FIXME: the following is a bit of a hack
	 * The NE555 is operating at a frequency of 400Hz
	 * The output of the oscillator is connectred through a 150K resistor to
	 * the discharge pin.
	 * The simulation gives a frequency of roughly 600Hz if the osc output is high.
	 * This is equivalent to R1 being 47k || 150k = 35K
	 * The simulation gives a frequency of roughly 375Hz if the osc output is low.
	 * This is not emulated exactly. We will just use 200k for R1.
	 *
	 */
	DISCRETE_TRANSFORM3(NODE_74,NODE_73,200000,165000,"102*-")
	DISCRETE_555_ASTABLE(NODE_75, 1, NODE_74, RES_K(100), CAP_N(10), &headon_555_bonus)
	DISCRETE_MULTIPLY(HEADON_BONUS_OUT,NODE_75,HEADON_BONUS_EN)

	/************************************************
	 * Crash
	 * FIXME: Just a prototype several filter missing
	 ************************************************/

	DISCRETE_LOGIC_INVERT(NODE_80, HEADON_CRASH_EN)
	DISCRETE_555_MSTABLE(NODE_81, 1, NODE_80, RES_K(470), CAP_U(1), &headon_555_crash)
	// Mix with noise
	DISCRETE_MULTIPLY(NODE_84, NODE_81, NODE_51)
	// Taken from simulation
	// Center frequency is 500 Hz
	// roughly 6db per octave
	DISCRETE_FILTER1(NODE_85, 1, NODE_84, 500, DISC_FILTER_BANDPASS)


	DISCRETE_555_MSTABLE(NODE_86, 1, NODE_80, RES_K(470), CAP_U(2.2), &headon_555_crash)
	// Mix with noise
	DISCRETE_MULTIPLY(NODE_87, NODE_86, NODE_51)
	// Sallen Key filter ...
	// http://www.t-linespeakers.org/tech/filters/Sallen-Key.html
	// f = w / 2 / pi  = 1 / ( 2 * pi * 15k*sqrt(470n*47n)) = 71 Hz
	// Q = 1/2 * sqrt(470n/47n)= 1.58
	DISCRETE_SALLEN_KEY_FILTER(NODE_88, 1, NODE_87, DISC_SALLEN_KEY_LOW_PASS, &headon_sallen_key_info)

	DISCRETE_MIXER2(NODE_95, 1, NODE_85, NODE_88, &headon_crash_mixer)
	DISCRETE_TRANSFORM2(HEADON_CRASH_OUT, NODE_95, 12, "01/")

	/************************************************
	 * Mixer Stage
	 ************************************************/

	DISCRETE_MIXER6(NODE_210, 1, HEADON_PLAYER_CAR_OUT, HEADON_COMP_CAR_OUT,
					HEADON_SCREECH1_OUT, HEADON_SCREECH2_OUT,
					HEADON_BONUS_OUT, HEADON_CRASH_OUT, &headon_mixer)

	DISCRETE_OUTPUT(NODE_210, 37000.0 / 12.0)
	//DISCRETE_CSVLOG3(HEADON_CRASH_EN,NODE_81,NODE_80)

DISCRETE_SOUND_END

void vicdual_state::headon_audio(machine_config &config)
{
	DISCRETE(config, m_discrete, headon_discrete);
	m_discrete->add_route(ALL_OUTPUTS, "mono", 1.0);
}

void vicdual_state::headon_audio_w(uint8_t data)
{
	if (m_discrete == nullptr)
		return;
	m_discrete->write(HEADON_HISPEED_PC_EN, data & 0x01);
	m_discrete->write(HEADON_SCREECH1_EN, data & 0x02);
	m_discrete->write(HEADON_CRASH_EN, data & 0x04);
	m_discrete->write(HEADON_HISPEED_CC_EN, data & 0x08);
	m_discrete->write(HEADON_SCREECH2_EN, data & 0x10);
	m_discrete->write(HEADON_BONUS_EN, data & 0x20);
	m_discrete->write(HEADON_CAR_ON_EN, data & 0x40);

}

void vicdual_state::invho2_audio_w(uint8_t data)
{
	if (m_discrete == nullptr)
		return;
	m_discrete->write(HEADON_HISPEED_PC_EN, data & 0x10);
	m_discrete->write(HEADON_SCREECH1_EN, data & 0x08);
	m_discrete->write(HEADON_CRASH_EN, data & 0x80);
	m_discrete->write(HEADON_HISPEED_CC_EN, data & 0x40);
	m_discrete->write(HEADON_SCREECH2_EN, data & 0x04);
	m_discrete->write(HEADON_BONUS_EN, data & 0x02);
	m_discrete->write(HEADON_CAR_ON_EN, data & 0x20);

}


/*************************************
 *
 *  Netlist-based Vic Dual Audio
 *
 *************************************/

vicdual_audio_device_base::vicdual_audio_device_base(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock, u8 inputs_mask, void (*netlist)(netlist::nlparse_t &), double output_scale) :
	device_t(mconfig, type, tag, owner, clock),
	device_mixer_interface(mconfig, *this),
	m_input_line(*this, "sound_nl:in_%u", 0),
	m_inputs_mask(inputs_mask),
	m_netlist(netlist),
	m_output_scale(output_scale)
{
}

void vicdual_audio_device_base::device_add_mconfig(machine_config &config)
{
	NETLIST_SOUND(config, "sound_nl", 48000)
		.set_source(m_netlist)
		.add_route(ALL_OUTPUTS, *this, 1.0);

	if (BIT(m_inputs_mask, 0))
		NETLIST_LOGIC_INPUT(config, m_input_line[0], "I_SOUND_0.IN", 0);
	if (BIT(m_inputs_mask, 1))
		NETLIST_LOGIC_INPUT(config, m_input_line[1], "I_SOUND_1.IN", 0);
	if (BIT(m_inputs_mask, 2))
		NETLIST_LOGIC_INPUT(config, m_input_line[2], "I_SOUND_2.IN", 0);
	if (BIT(m_inputs_mask, 3))
		NETLIST_LOGIC_INPUT(config, m_input_line[3], "I_SOUND_3.IN", 0);
	if (BIT(m_inputs_mask, 4))
		NETLIST_LOGIC_INPUT(config, m_input_line[4], "I_SOUND_4.IN", 0);
	if (BIT(m_inputs_mask, 5))
		NETLIST_LOGIC_INPUT(config, m_input_line[5], "I_SOUND_5.IN", 0);
	if (BIT(m_inputs_mask, 6))
		NETLIST_LOGIC_INPUT(config, m_input_line[6], "I_SOUND_6.IN", 0);
	if (BIT(m_inputs_mask, 7))
		NETLIST_LOGIC_INPUT(config, m_input_line[7], "I_SOUND_7.IN", 0);

	NETLIST_STREAM_OUTPUT(config, "sound_nl:cout0", 0, "OUTPUT").set_mult_offset(m_output_scale, 0.0);
}

void vicdual_audio_device_base::device_start()
{
	save_item(NAME(m_input_state));
}

void vicdual_audio_device_base::write(u8 value)
{
	if (value != m_input_state)
	{
		m_input_state = value;
		for (int index = 0; index < 8; index++)
			if (m_input_line[index] != nullptr)
				m_input_line[index]->write_line(BIT(m_input_state, index));
	}
}


/*************************************
 *
 *  Borderline/Tranquilizer Gun
 *
 *************************************/

DEFINE_DEVICE_TYPE(BORDERLINE_AUDIO, borderline_audio_device, "borderline_audio", "Borderline Sound Board")

borderline_audio_device::borderline_audio_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) :
	vicdual_audio_device_base(mconfig, BORDERLINE_AUDIO, tag, owner, clock, 0xff, NETLIST_NAME(brdrline), 1.0)
{
}



/*************************************
 *
 *  Frogs
 *
 *************************************/

DEFINE_DEVICE_TYPE(FROGS_AUDIO, frogs_audio_device, "frogs_audio", "Frogs Sound Board")

frogs_audio_device::frogs_audio_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) :
#if (FROGS_TEST_INDEPENDENT_NETLISTS)
	vicdual_audio_device_base(mconfig, FROGS_AUDIO, tag, owner, clock, 0xff, NETLIST_NAME(frogs_mixer), 1.0),
	m_jump(*this, "frogs_jump:input"),
	m_tongue(*this, "frogs_tongue:input"),
	m_hop(*this, "frogs_hop:input"),
	m_capture(*this, "frogs_capture:input"),
	m_splash(*this, "frogs_splash:input"),
	m_fly(*this, "frogs_fly:input")
#else
	vicdual_audio_device_base(mconfig, FROGS_AUDIO, tag, owner, clock, 0xff, NETLIST_NAME(frogs), 1.0)
#endif
{
}

#if (FROGS_TEST_INDEPENDENT_NETLISTS)

frogs_audio_component_device::frogs_audio_component_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock, void (*netlist)(netlist::nlparse_t &)) :
	device_t(mconfig, FROGS_AUDIO_COMPONENT, tag, owner, clock),
	device_mixer_interface(mconfig, *this),
	m_netlist(netlist)
{
}

void frogs_audio_component_device::device_start()
{
}

void frogs_audio_component_device::device_add_mconfig(machine_config &config)
{
	NETLIST_SOUND(config, "frogs_component", 48000)
		.set_source(m_netlist)
		.add_route(ALL_OUTPUTS, *this, 1.0);
	NETLIST_LOGIC_INPUT(config, "input", "I_INPUT.IN", 0);
	NETLIST_STREAM_OUTPUT(config, "frogs_component:cout0", 0, "OUTPUT").set_mult_offset(1.0, 0.0);
}

DEFINE_DEVICE_TYPE(FROGS_AUDIO_COMPONENT, frogs_audio_component_device, "frogs_audio_component_device", "Frogs Sound Component")

void frogs_audio_device::device_add_mconfig(machine_config &config)
{
	NETLIST_SOUND(config, "sound_nl", 48000)
		.set_source(NETLIST_NAME(frogs_mixer))
		.add_route(ALL_OUTPUTS, *this, 1.0);
	NETLIST_STREAM_INPUT(config, "sound_nl:cin0", 0, "BOING.IN");
	NETLIST_STREAM_INPUT(config, "sound_nl:cin1", 1, "ZIP.IN");
	NETLIST_STREAM_INPUT(config, "sound_nl:cin2", 2, "HOP.IN");
	NETLIST_STREAM_INPUT(config, "sound_nl:cin3", 3, "CROAK.IN");
	NETLIST_STREAM_INPUT(config, "sound_nl:cin4", 4, "SPLASH.IN");
	NETLIST_STREAM_INPUT(config, "sound_nl:cin5", 5, "FLY.IN");
	NETLIST_STREAM_OUTPUT(config, "sound_nl:cout0", 0, "OUTPUT").set_mult_offset(1.0, 0.0);

	FROGS_AUDIO_COMPONENT(config, "frogs_jump", 48000, NETLIST_NAME(frogs_jump))
		.add_route(0, "sound_nl", 1.0, 0);

	FROGS_AUDIO_COMPONENT(config, "frogs_tongue", 48000, NETLIST_NAME(frogs_tongue))
		.add_route(0, "sound_nl", 1.0, 1);

	FROGS_AUDIO_COMPONENT(config, "frogs_hop", 48000, NETLIST_NAME(frogs_hop))
		.add_route(0, "sound_nl", 1.0, 2);

	FROGS_AUDIO_COMPONENT(config, "frogs_capture", 48000, NETLIST_NAME(frogs_capture))
		.add_route(0, "sound_nl", 1.0, 3);

	FROGS_AUDIO_COMPONENT(config, "frogs_splash", 48000, NETLIST_NAME(frogs_splash))
		.add_route(0, "sound_nl", 1.0, 4);

	FROGS_AUDIO_COMPONENT(config, "frogs_fly", 48000, NETLIST_NAME(frogs_fly))
		.add_route(0, "sound_nl", 1.0, 5);
}

void frogs_audio_device::write(u8 value)
{
	m_jump->write_line(BIT(value, 1));
	m_tongue->write_line(BIT(value, 2));
	m_hop->write_line(BIT(value, 0));
	m_capture->write_line(BIT(value, 3));
	m_splash->write_line(BIT(value, 7));
	m_fly->write_line(BIT(value, 4));
}

#endif