summaryrefslogblamecommitdiffstatshomepage
path: root/src/devices/sound/disc_wav.hxx
blob: d767e6c6bd8076a37d46fff0702311f56df100fc (plain) (tree)
1
2
3
4
5
6
                       
                              


                                                                         
                                             














                                                                         
                                                            



                                                                          
 
 
 
 
 
 













                                                                          








                                                 


                                                                           
                          
 


                                   
                                                                                       
                           
                                     
 
                                      
                                                         

                                                                                   
                                                                     
                                     

                                                                 


            
                                       
                                             
                                          


         
                                                                                       
                                           
         
                                                      
                                                      



                       


                                                                           
                                          
         

                             
                                     




                                                                                     
                                                          
                                 

                                                                  






                                                             
                                               




                                                                      
                                                                     
                                     

                                     
                                             
                         
                                                

                         
                    

                                     
                                                                           
                         
                                                

                         
 
                                     
                                                                   
 
                                                    
                 
                                                                              
                                           
                         
                                                        
                                                        
                                              
                                                        
                                                                      
                                                           
                                                               
                                                                                       
                                            
                                                                                       


                                              
                                     
         

 
                           
 
                                                                
         




                                                    

            
         




                                                       
         

 
                                                                
                                                                      
 

                                                     
 


                         
                                                                           
















                                                                          





                                                 
 
                                                                                                    


                   

                       



                                   
                                           

                                  
                                           

                                   
                                           

                                    
                                           
                                                                       

                                   
                                           
                                                                       

                                    
                                           
                                                                       

                                   
                                     

                                   
                                     

                                       
                                               

                                       
                                               

                                       

                                              

                                           

                                                                

                                           

                                                                

                              
                                                                                              





                                 
 
                             
 

                                                 

                           
                                               
 
                                                 

                                                                                   
                                                                      
                                     
                                                      


                                           
                                                                     
         
                              


                       
                                 




                                                                             
                                            
                         
                                               
                                                              












                                                              
                    
         

                             



                                                                  
                                                                          
 
                                                                                  
                                                                                                                     
 
                                                                                              
                                                                            
                                                              
                                                     
                                                                                                        
                                                                                                                                              
 

                                                                       

                                                                            
                                                      

                                                                                                                                                         
 
                 
                                               
                                
                                                
                    
                                                                        

                                                 
                                                           

                                
                                                                                   
                                            


                                                     
 
                                          
                                   
                                                           
 
         

                                   
                                 


         
                              
 

                                                 
                                   
                     
 



                                                                              
 
                                                                                             
                                                                                                
 


                                                                                          
 
                                       


                                                       

                                                            
                                      

                                                                                                                                       

                                                 
                                                        

                                         
                                                                          

                        
                                                                           
                                    



                                      












                                                                          



                                             
 
                        
 

                     


                                                                 
                                          

                                                                           
                                                                                   

                                                                                 
                                                   
                                       
                                                                  
                            
                                                                  

                                                   

                                                 



                 
                                 


                                                  
                                            


                                                                                             
                                                                          


 
                         
 
                  
                     















                                                                          





                                                         
 
                       
 



                                                 
 
                                             

                                                                                   
                                                                      
                                     

                                                                 


            
                                                           
                                             
                                                 



                             
                                       
 
                                     




                                                                                     
                                                    
                                 

                                                                  

















                                                                                                  

                                                      

                                                                                           


                                                                            



                                 
                                 
                                            
                 
                                                                              
                                           

                                                        
                                                                      
                                                            
                                                                   
                                                                                           
                                            
                                                                                           

                                                        
                                                        


                                              
                                     

            
                                 

 
                        
 

                                                                 
 


                                           
 



                                       
                         













                                                                          


                                                 



                                                                        
                                                    
 
                             
 
                                                       
 




                                                                             
                                
                                                                
                        



                                                

                        
 

                         

                                                              
 
                                                    
                       


                                                        
                                                                                       
                                                            
                                                                           
                                                                                      





                                                                                  
                                                                        
                                         

                                           
                                                       

                                           
                                                        

                                                                                               
                                                                        




                                                                                     












                                                                                                               
                                               


                                                                              
                                                   



                                                        

                                                             








                                                                          

                                                

                                                                                                
                                          
                         
                                                  
                                                 



                                                                          
                                                   
                                              
                                                                        
                                         

                                           
                                                                


                                                                                           
                                                                      
                                         
                                                  


                                                                              
                                                          
                         
                                                        


                              
                    
         
                                                                                     
                                 





                                                                        
                                       
                 
                                                                          


                                                                         
                                                                                


                                                                      
                                                                  
                                 
                                                                    
                                                      


                                                          


                                                                                                                               

                                                                                  



                                                                                  
                                                                                                           
                                                            
                                                                              





                                                 
                                                                                
                                           

                                                                         
                                                                 
                                 
                                                                     
                                                      


                                                          
                                                                          
                                                                                                  
                                                    
                                                                     

                                 
                 
                                               

                                            
                                                                                        
                            
                                                                   
 
                                                                                          
                               
 
                                      
                         
                                                                      
                                                                  
                                 
                                                                                                                                             
                                                    
                                                                      
                                                      



                                                            
                            
                         
                                                                         
                                                                 
                                 
                                                                                                                          
                                                    
                                                                     
                                                      



                                                            
                 
                                   
                    

                                     

                          
                        
 
                                          
 
                              
         
                                                    
                                      


                                                       
                                                                                     

                                                    

                                                             
                                                                       
                            
                                                                 

                                                          
                                                                     

                                                          
                                                                      

                                                        
                                                     
                              
         
                             
                                

 
                       
 
                              
 

                                                       
                                 
                 
 

                                                         

                                                    
                                  

                                         
                                                                   
                                         
                                               
                             

         










                                                                      



                                                                                                    
                                            
                                                                            




                                                                                
                                                                                             
                                        
                                                            


                                                                                                                      

                              

                                                                      
                                            
                                                                                                      
                                        


                                                                

                                                                                                    


                              
                                                                      
                                               





                                                                                               


                                                                                          


                                          

                                                                      


                                          

                                                                                                        
                         










                                                                      

                                                                        



                                                                                                            
 
                                                                                                      
                                        



                                                                          
                                            
                                                                                            
                                        

                                                                                                    


                                                                            
                                                                                                              



                                                                                     


                                                                                           
                                                                                   
                                                                  
                                                                                    



                                                                          
                                            
                                                                                                      
                                        
                                                        

                                                                                                     


                                                                        
                                                                                   
                                                                                           
                                                                                    



                                                                          
                                            
                                                                                                      
                                        


                                                                

                                                                                                    
                         


                                                                                                    

                                                                                                 


                                                                        
                                                                                   
                                                                                           
                                                                                    


                              

                                                                                                                 
 
                     














                                                                          





                                                     
 
                               
 

                     

                                    

                                                                                                                                                                      
                                           
                                                       


            
                          
         
                             







                                                                       
                                                                                                              

 
                                
 


                                                                       
                                                                 
                                          
                                          

                                                                                 
                                                  

                                             
                     














                                                                          


                                                      
 
                              
 
                                                        
 
                                                    
                         

                                                                            

                              





                                                                                               




                                                                                                       

                                                                                                                                            
                                                                 
                            





                                                                  
                                                                                                                    
                                                                                    
                                                                     
                                                                     
                                            








                                                                  
                                                                                                    
                                                                                    
                                                                     
                                                                     
                                            



                         
                           
 
                              

                                                  
                                                                   

                                                   
                                                                      

                                                 
                                                                   

                                                  
                                                                      

                              

                                      

 
                               
 

                                                        

                       

                                                                                      

                                                                               
                                           

                                                                                   

                                                                                  
                                                     
                                                                          
                                 
                                         

                                                                   

                    
 
                                                                













                                                                          




                                                 
 
                           
 


                                
                                                                                              
                                           


            
                                 








                                                                       
                                                                                                        

 
                            
 


                                                                       
                                                             
                                          
                                          
                                                
                     














                                                                          





                                                 
 
                             
 
                                               
                                                              



                                  
                                     
                                                                                        
                    
                                                                                          
                                           


            
                                 








                                                                       
                                                                                                        

 
                              
 


                                                                       
                                                               
                                          
                                          

                             
                     













                                                                          





                                                 
 
                             
 
                                  

                                                                                
                             
         

                                                             





                                                    
                                                                        

                                                                    
 
                                                                                                                               


            
                                 


         
                              
 

                                                  

                                                                       



                                                                                               


                                                             
 
                             

                                                          
                             
         

                                                             


                             
                     














                                                                          





                                                 
 
                              
 




                                                               
                                                                                                                       







                                                                               
                                                                                                                               
                                                          
                                                     
 
                                           
                                     
                                                                                           
                    
                                                                                           


            
                                 


         
                               
 








                                                                                                                   
                                          

                             
                     












                                                                          
 



                                                                               
 
                                                                    
 
                                          

                         
                  
                                                                  



                                
                                                                 
 
                                          
 


                                
                                                                                       
            
                                                       

 
                               
 
                                          
                                       
                          
                    
                     

                           
                                    
                                          
         

                              


                                            
                              
                              
                                

                                            
                              
                              
                                                             
                                

                                            
                              
                              
                                                             
                                

                                            

                              
                                                                                                       
         
 













                                                    
 
                                          
         


                              
                                    
                         
                                                                       
                                                    

                                                                     
                                                           


                            

                                                              

                              
                              
                                                   
                                                                 
                                                                                    

                                                
                                                                
                                                  
                                                                                          
                                                                            
                         

                                                                                       
                              
                              
                                                   
                                                                 
                                                                                     
                                                   
                         
                                                                
                                                  
                                                                                             
                                                                            
                         

                                                                                     

                              
                                                                                                       
         
 

                           
 
                                                    
                            
            

                            
                                         


                                                

 
                                
 
                                          
 
              

                      

                                                                                            
                         

                        



                         


                                                                                                                                             


                                              
                                                                                                  
         












                                                                          




                                                     
 
                               
 

                                    
                                                                                                                
                                                                                                                                        

                                           

                                                 


            
                                 








                                                                       
                                                                                                            

 
                                
 


                                                                       
                                                                 
                                          
                                        

                                    
                     











                                                                          
                                             
 
                          
 

                            
                                 


            
                                 



         
                           
 
                     
 
// license:BSD-3-Clause
// copyright-holders:K.Wilkins
/************************************************************************
 *
 *  MAME - Discrete sound system emulation library
 *  Written by K.Wilkins (mame@esplexo.co.uk)
 *
 *  (c) K.Wilkins 2000
 *
 ************************************************************************
 *
 * DSS_COUNTER        - External clock Binary Counter
 * DSS_LFSR_NOISE     - Linear Feedback Shift Register Noise
 * DSS_NOISE          - Noise Source - Random source
 * DSS_NOTE           - Note/tone generator
 * DSS_OP_AMP_OSC     - Op Amp oscillator circuits
 * DSS_SAWTOOTHWAVE   - Sawtooth waveform generator
 * DSS_SCHMITT_OSC    - Schmitt Feedback Oscillator
 * DSS_SINEWAVE       - Sinewave generator source code
 * DSS_SQUAREWAVE     - Squarewave generator source code
 * DSS_SQUAREWFIX     - Squarewave generator - fixed frequency
 * DSS_SQUAREWAVE2    - Squarewave generator - by t_on/t_off
 * DSS_TRIANGLEWAVE   - Triangle waveform generator
 *
 ************************************************************************/







/************************************************************************
 *
 * DSS_COUNTER - External clock Binary Counter
 *
 * input0    - Enable input value
 * input1    - Reset input (active high)
 * input2    - Clock Input
 * input3    - Max count
 * input4    - Direction - 0=down, 1=up
 * input5    - Reset Value
 * input6    - Clock type
 *
 * Jan 2004, D Renaud.
 ************************************************************************/
#define DSS_COUNTER__ENABLE     DISCRETE_INPUT(0)
#define DSS_COUNTER__RESET      DISCRETE_INPUT(1)
#define DSS_COUNTER__CLOCK      DISCRETE_INPUT(2)
#define DSS_COUNTER__MIN        DISCRETE_INPUT(3)
#define DSS_COUNTER__MAX        DISCRETE_INPUT(4)
#define DSS_COUNTER__DIR        DISCRETE_INPUT(5)
#define DSS_COUNTER__INIT       DISCRETE_INPUT(6)
#define DSS_COUNTER__CLOCK_TYPE DISCRETE_INPUT(7)
#define DSS_7492__CLOCK_TYPE     DSS_COUNTER__MIN

static const int disc_7492_count[6] = {0x00, 0x01, 0x02, 0x04, 0x05, 0x06};

DISCRETE_STEP(dss_counter)
{
	double  cycles;
	double  ds_clock;
	int     clock = 0, inc = 0;
	uint32_t  last_count = m_last_count;  /* it is different then output in 7492 */
	double  x_time = 0;
	uint32_t  count = last_count;

	ds_clock = DSS_COUNTER__CLOCK;
	if (UNEXPECTED(m_clock_type == DISC_CLK_IS_FREQ))
	{
		/* We need to keep clocking the internal clock even if disabled. */
		cycles = (m_t_left + this->sample_time()) * ds_clock;
		inc    = (int)cycles;
		m_t_left = (cycles - inc) / ds_clock;
		if (inc) x_time = m_t_left / this->sample_time();
	}
	else
	{
		clock  = (int)ds_clock;
		/* x_time from input clock */
		x_time = ds_clock - clock;
	}


	/* If reset enabled then set output to the reset value.  No x_time in reset. */
	if (UNEXPECTED(DSS_COUNTER__RESET))
	{
		m_last_count = (int)DSS_COUNTER__INIT;
		set_output(0, (int)DSS_COUNTER__INIT);
		return;
	}

	/*
	 * Only count if module is enabled.
	 * This has the effect of holding the output at it's current value.
	 */
	if (EXPECTED(DSS_COUNTER__ENABLE))
	{
		double v_out;

		switch (m_clock_type)
		{
			case DISC_CLK_ON_F_EDGE:
			case DISC_CLK_ON_R_EDGE:
				/* See if the clock has toggled to the proper edge */
				clock = (clock != 0);
				if (m_last_clock != clock)
				{
					m_last_clock = clock;
					if (m_clock_type == clock)
					{
						/* Toggled */
						inc = 1;
					}
				}
				break;

			case DISC_CLK_BY_COUNT:
				/* Clock number of times specified. */
				inc = clock;
				break;
		}

		/* use loops because init is not always min or max */
		if (DSS_COUNTER__DIR)
		{
			count += inc;
			while (count > m_max)
			{
				count -= m_diff;
			}
		}
		else
		{
			count -= inc;
			while (count < m_min || count > (0xffffffff - inc))
			{
				count += m_diff;
			}
		}

		m_last_count = count;
		v_out = m_is_7492 ? disc_7492_count[count] : count;

		if (UNEXPECTED(count != last_count))
		{
			/* the x_time is only output if the output changed. */
			switch (m_out_type)
			{
				case DISC_OUT_HAS_XTIME:
					v_out += x_time;
					break;
				case DISC_OUT_IS_ENERGY:
					if (x_time == 0) x_time = 1.0;
					v_out = last_count;
					if (count > last_count)
						v_out += (count - last_count) * x_time;
					else
						v_out -= (last_count - count) * x_time;
					break;
			}
		}
		set_output(0, v_out);
	}
}

DISCRETE_RESET(dss_counter)
{
	if ((int)DSS_COUNTER__CLOCK_TYPE & DISC_COUNTER_IS_7492)
	{
		m_is_7492    = 1;
		m_clock_type = DSS_7492__CLOCK_TYPE;
		m_max = 5;
		m_min = 0;
		m_diff = 6;
	}
	else
	{
		m_is_7492    = 0;
		m_clock_type = DSS_COUNTER__CLOCK_TYPE;
		m_max = DSS_COUNTER__MAX;
		m_min = DSS_COUNTER__MIN;
		m_diff = m_max - m_min + 1;
	}


	if (!m_is_7492 && (DSS_COUNTER__MAX < DSS_COUNTER__MIN))
		fatalerror("MAX < MIN in NODE_%02d\n", this->index());

	m_out_type    = m_clock_type & DISC_OUT_MASK;
	m_clock_type &= DISC_CLK_MASK;

	m_t_left = 0;
	m_last_count = 0;
	m_last_clock = 0;
	set_output(0, DSS_COUNTER__INIT); /* count starts at reset value */
}


/************************************************************************
 *
 * DSS_LFSR_NOISE - Usage of node_description values for LFSR noise gen
 *
 * input0    - Enable input value
 * input1    - Register reset
 * input2    - Clock Input
 * input3    - Amplitude input value
 * input4    - Input feed bit
 * input5    - Bias
 *
 * also passed dss_lfsr_context structure
 *
 ************************************************************************/
#define DSS_LFSR_NOISE__ENABLE  DISCRETE_INPUT(0)
#define DSS_LFSR_NOISE__RESET   DISCRETE_INPUT(1)
#define DSS_LFSR_NOISE__CLOCK   DISCRETE_INPUT(2)
#define DSS_LFSR_NOISE__AMP     DISCRETE_INPUT(3)
#define DSS_LFSR_NOISE__FEED    DISCRETE_INPUT(4)
#define DSS_LFSR_NOISE__BIAS    DISCRETE_INPUT(5)

static inline int dss_lfsr_function(discrete_device *dev, int myfunc, int in0, int in1, int bitmask)
{
	int retval;

	in0 &= bitmask;
	in1 &= bitmask;

	switch(myfunc)
	{
		case DISC_LFSR_XOR:
			retval = in0 ^ in1;
			break;
		case DISC_LFSR_OR:
			retval = in0 | in1;
			break;
		case DISC_LFSR_AND:
			retval = in0 & in1;
			break;
		case DISC_LFSR_XNOR:
			retval = in0 ^ in1;
			retval = retval ^ bitmask;  /* Invert output */
			break;
		case DISC_LFSR_NOR:
			retval = in0 | in1;
			retval = retval ^ bitmask;  /* Invert output */
			break;
		case DISC_LFSR_NAND:
			retval = in0 & in1;
			retval = retval ^ bitmask;  /* Invert output */
			break;
		case DISC_LFSR_IN0:
			retval = in0;
			break;
		case DISC_LFSR_IN1:
			retval = in1;
			break;
		case DISC_LFSR_NOT_IN0:
			retval = in0 ^ bitmask;
			break;
		case DISC_LFSR_NOT_IN1:
			retval = in1 ^ bitmask;
			break;
		case DISC_LFSR_REPLACE:
			retval = in0 & ~in1;
			retval = retval | in1;
			break;
		case DISC_LFSR_XOR_INV_IN0:
			retval = in0 ^ bitmask; /* invert in0 */
			retval = retval ^ in1;  /* xor in1 */
			break;
		case DISC_LFSR_XOR_INV_IN1:
			retval = in1 ^ bitmask; /* invert in1 */
			retval = retval ^ in0;  /* xor in0 */
			break;
		default:
			dev->discrete_log("dss_lfsr_function - Invalid function type passed");
			retval=0;
			break;
	}
	return retval;
}


DISCRETE_STEP(dss_lfsr_noise)
{
	DISCRETE_DECLARE_INFO(discrete_lfsr_desc)

	double cycles;
	int clock, inc = 0;
	int fb0, fb1, fbresult = 0, noise_feed;

	if (info->clock_type == DISC_CLK_IS_FREQ)
	{
		/* We need to keep clocking the internal clock even if disabled. */
		cycles = (m_t_left + this->sample_time()) / m_t_clock;
		inc    = (int)cycles;
		m_t_left = (cycles - inc) * m_t_clock;
	}

	/* Reset everything if necessary */
	if(((DSS_LFSR_NOISE__RESET == 0) ? 0 : 1) == m_reset_on_high)
	{
		this->reset();
		return;
	}

	switch (info->clock_type)
	{
		case DISC_CLK_ON_F_EDGE:
		case DISC_CLK_ON_R_EDGE:
			/* See if the clock has toggled to the proper edge */
			clock = (DSS_LFSR_NOISE__CLOCK != 0);
			if (m_last != clock)
			{
				m_last = clock;
				if (info->clock_type == clock)
				{
					/* Toggled */
					inc = 1;
				}
			}
			break;

		case DISC_CLK_BY_COUNT:
			/* Clock number of times specified. */
			inc = (int)DSS_LFSR_NOISE__CLOCK;
			break;
	}

	if (inc > 0)
	{
		double v_out;

		noise_feed = (DSS_LFSR_NOISE__FEED ? 0x01 : 0x00);
		for (clock = 0; clock < inc; clock++)
		{
			/* Fetch the last feedback result */
			fbresult = (m_lfsr_reg >> info->bitlength) & 0x01;

			/* Stage 2 feedback combine fbresultNew with infeed bit */
			fbresult = dss_lfsr_function(m_device, info->feedback_function1, fbresult, noise_feed, 0x01);

			/* Stage 3 first we setup where the bit is going to be shifted into */
			fbresult = fbresult * info->feedback_function2_mask;
			/* Then we left shift the register, */
			m_lfsr_reg = m_lfsr_reg << 1;
			/* Now move the fbresult into the shift register and mask it to the bitlength */
			m_lfsr_reg = dss_lfsr_function(m_device, info->feedback_function2, fbresult, m_lfsr_reg, (1 << info->bitlength) - 1 );

			/* Now get and store the new feedback result */
			/* Fetch the feedback bits */
			fb0 = (m_lfsr_reg >> info->feedback_bitsel0) & 0x01;
			fb1 = (m_lfsr_reg >> info->feedback_bitsel1) & 0x01;
			/* Now do the combo on them */
			fbresult = dss_lfsr_function(m_device, info->feedback_function0, fb0, fb1, 0x01);
			m_lfsr_reg = dss_lfsr_function(m_device, DISC_LFSR_REPLACE, m_lfsr_reg, fbresult << info->bitlength, (2 << info->bitlength) - 1);

		}
		/* Now select the output bit */
		if (m_out_is_f0)
			v_out = fbresult & 0x01;
		else
			v_out = (m_lfsr_reg >> info->output_bit) & 0x01;

		/* Final inversion if required */
		if (m_invert_output) v_out = v_out ? 0 : 1;

		/* Gain stage */
		v_out = v_out ? DSS_LFSR_NOISE__AMP / 2 : -DSS_LFSR_NOISE__AMP / 2;
		/* Bias input as required */
		v_out = v_out + DSS_LFSR_NOISE__BIAS;

		set_output(0, v_out);

		/* output the lfsr reg ?*/
		if (m_out_lfsr_reg)
			set_output(1, (double) m_lfsr_reg);

	}
	if(!DSS_LFSR_NOISE__ENABLE)
	{
		set_output(0, 0);
	}
}

DISCRETE_RESET(dss_lfsr_noise)
{
	DISCRETE_DECLARE_INFO(discrete_lfsr_desc)

	int    fb0 , fb1, fbresult;
	double v_out;

	m_reset_on_high = (info->flags & DISC_LFSR_FLAG_RESET_TYPE_H) ? 1 : 0;
	m_invert_output = info->flags & DISC_LFSR_FLAG_OUT_INVERT;
	m_out_is_f0 = (info->flags & DISC_LFSR_FLAG_OUTPUT_F0) ? 1 : 0;
	m_out_lfsr_reg = (info->flags & DISC_LFSR_FLAG_OUTPUT_SR_SN1) ? 1 : 0;

	if ((info->clock_type < DISC_CLK_ON_F_EDGE) || (info->clock_type > DISC_CLK_IS_FREQ))
		m_device->discrete_log("Invalid clock type passed in NODE_%d\n", this->index());

	m_last = (DSS_COUNTER__CLOCK != 0);
	if (info->clock_type == DISC_CLK_IS_FREQ) m_t_clock = 1.0 / DSS_LFSR_NOISE__CLOCK;
	m_t_left = 0;

	m_lfsr_reg = info->reset_value;

	/* Now get and store the new feedback result */
	/* Fetch the feedback bits */
	fb0 = (m_lfsr_reg >> info->feedback_bitsel0) & 0x01;
	fb1=(m_lfsr_reg >> info->feedback_bitsel1) & 0x01;
	/* Now do the combo on them */
	fbresult = dss_lfsr_function(m_device, info->feedback_function0, fb0, fb1, 0x01);
	m_lfsr_reg=dss_lfsr_function(m_device, DISC_LFSR_REPLACE, m_lfsr_reg, fbresult << info->bitlength, (2<< info->bitlength ) - 1);

	/* Now select and setup the output bit */
	v_out = (m_lfsr_reg >> info->output_bit) & 0x01;

	/* Final inversion if required */
	if(info->flags & DISC_LFSR_FLAG_OUT_INVERT) v_out = v_out ? 0 : 1;

	/* Gain stage */
	v_out = v_out ? DSS_LFSR_NOISE__AMP / 2 : -DSS_LFSR_NOISE__AMP / 2;
	/* Bias input as required */
	v_out += DSS_LFSR_NOISE__BIAS;

	set_output(0, v_out);
	set_output(1, 0);
}


/************************************************************************
 *
 * DSS_NOISE - Usage of node_description values for white nose generator
 *
 * input0    - Enable input value
 * input1    - Noise sample frequency
 * input2    - Amplitude input value
 * input3    - DC Bias value
 *
 ************************************************************************/
#define DSS_NOISE__ENABLE   DISCRETE_INPUT(0)
#define DSS_NOISE__FREQ     DISCRETE_INPUT(1)
#define DSS_NOISE__AMP      DISCRETE_INPUT(2)
#define DSS_NOISE__BIAS     DISCRETE_INPUT(3)

DISCRETE_STEP(dss_noise)
{
	double v_out;

	if(DSS_NOISE__ENABLE)
	{
		/* Only sample noise on rollover to next cycle */
		if(m_phase > (2.0 * M_PI))
		{
			/* GCC's rand returns a RAND_MAX value of 0x7fff */
			int newval = (m_device->machine().rand() & 0x7fff) - 16384;

			/* make sure the peak to peak values are the amplitude */
			v_out = DSS_NOISE__AMP / 2;
			if (newval > 0)
				v_out *= ((double)newval / 16383);
			else
				v_out *= ((double)newval / 16384);

			/* Add DC Bias component */
			v_out += DSS_NOISE__BIAS;
			set_output(0, v_out);
		}
	}
	else
	{
		set_output(0, 0);
	}

	/* Keep the new phasor in the 2Pi range.*/
	m_phase = fmod(m_phase, 2.0 * M_PI);

	/* The enable input only curtails output, phase rotation still occurs. */
	/* We allow the phase to exceed 2Pi here, so we can tell when to sample the noise. */
	m_phase += ((2.0 * M_PI * DSS_NOISE__FREQ) / this->sample_rate());
}


DISCRETE_RESET(dss_noise)
{
	m_phase=0;
	this->step();
}


/************************************************************************
 *
 * DSS_NOTE - Note/tone generator
 *
 * input0    - Enable input value
 * input1    - Clock Input
 * input2    - data value
 * input3    - Max count 1
 * input4    - Max count 2
 * input5    - Clock type
 *
 * Mar 2004, D Renaud.
 ************************************************************************/
	#define DSS_NOTE__ENABLE        DISCRETE_INPUT(0)
	#define DSS_NOTE__CLOCK     DISCRETE_INPUT(1)
	#define DSS_NOTE__DATA          DISCRETE_INPUT(2)
	#define DSS_NOTE__MAX1          DISCRETE_INPUT(3)
	#define DSS_NOTE__MAX2          DISCRETE_INPUT(4)
	#define DSS_NOTE__CLOCK_TYPE    DISCRETE_INPUT(5)

DISCRETE_STEP(dss_note)
{
	double  cycles;
	int     clock  = 0, last_count2, inc = 0;
	double  x_time = 0;
	double  v_out;

	if (m_clock_type == DISC_CLK_IS_FREQ)
	{
		/* We need to keep clocking the internal clock even if disabled. */
		cycles = (m_t_left + this->sample_time()) / m_t_clock;
		inc    = (int)cycles;
		m_t_left = (cycles - inc) * m_t_clock;
		if (inc) x_time = m_t_left / this->sample_time();
	}
	else
	{
		/* separate clock info from x_time info. */
		clock = (int)DSS_NOTE__CLOCK;
		x_time = DSS_NOTE__CLOCK - clock;
	}

	if (DSS_NOTE__ENABLE)
	{
		last_count2 = m_count2;

		switch (m_clock_type)
		{
			case DISC_CLK_ON_F_EDGE:
			case DISC_CLK_ON_R_EDGE:
				/* See if the clock has toggled to the proper edge */
				clock = (clock != 0);
				if (m_last != clock)
				{
					m_last = clock;
					if (m_clock_type == clock)
					{
						/* Toggled */
						inc = 1;
					}
				}
				break;

			case DISC_CLK_BY_COUNT:
				/* Clock number of times specified. */
				inc = clock;
				break;
		}

		/* Count output as long as the data loaded is not already equal to max 1 count. */
		if (DSS_NOTE__DATA != DSS_NOTE__MAX1)
		{
			for (clock = 0; clock < inc; clock++)
			{
				m_count1++;
				if (m_count1 > m_max1)
				{
					/* Max 1 count reached.  Load Data into counter. */
					m_count1  = (int)DSS_NOTE__DATA;
					m_count2 += 1;
					if (m_count2 > m_max2) m_count2 = 0;
				}
			}
		}

		v_out = m_count2;
		if (m_count2 != last_count2)
		{
			/* the x_time is only output if the output changed. */
			switch (m_out_type)
			{
				case DISC_OUT_IS_ENERGY:
					if (x_time == 0) x_time = 1.0;
					v_out = last_count2;
					if (m_count2 > last_count2)
						v_out += (m_count2 - last_count2) * x_time;
					else
						v_out -= (last_count2 - m_count2) * x_time;
					break;
				case DISC_OUT_HAS_XTIME:
					v_out += x_time;
					break;
			}
		}
		set_output(0, v_out);
	}
	else
		set_output(0, 0);
}

DISCRETE_RESET(dss_note)
{
	m_clock_type = (int)DSS_NOTE__CLOCK_TYPE & DISC_CLK_MASK;
	m_out_type   = (int)DSS_NOTE__CLOCK_TYPE & DISC_OUT_MASK;

	m_last    = (DSS_NOTE__CLOCK != 0);
	m_t_left  = 0;
	m_t_clock = 1.0 / DSS_NOTE__CLOCK;

	m_count1 = (int)DSS_NOTE__DATA;
	m_count2 = 0;
	m_max1   = (int)DSS_NOTE__MAX1;
	m_max2   = (int)DSS_NOTE__MAX2;
	set_output(0, 0);
}

/************************************************************************
 *
 * DSS_OP_AMP_OSC - Op Amp Oscillators
 *
 * input0    - Enable input value
 * input1    - vMod1 (if needed)
 * input2    - vMod2 (if needed)
 *
 * also passed discrete_op_amp_osc_info structure
 *
 * Mar 2004, D Renaud.
 ************************************************************************/
#define DSS_OP_AMP_OSC__ENABLE  DISCRETE_INPUT(0)
#define DSS_OP_AMP_OSC__VMOD1   DISCRETE_INPUT(1)
#define DSS_OP_AMP_OSC__VMOD2   DISCRETE_INPUT(2)

/* The inputs on a norton op-amp are (info->vP - OP_AMP_NORTON_VBE) */
/* which is the same as the output high voltage.  We will define them */
/* the same to save a calculation step */
#define DSS_OP_AMP_OSC_NORTON_VP_IN     m_v_out_high

DISCRETE_STEP(dss_op_amp_osc)
{
	DISCRETE_DECLARE_INFO(discrete_op_amp_osc_info)

	double i = 0;               /* Charging current created by vIn */
	double v = 0;           /* all input voltages mixed */
	double dt;              /* change in time */
	double v_cap;           /* Current voltage on capacitor, before dt */
	double v_cap_next = 0;  /* Voltage on capacitor, after dt */
	double charge[2]  = {0};
	double x_time  = 0;     /* time since change happened */
	double exponent;
	uint8_t force_charge = 0;
	uint8_t enable = DSS_OP_AMP_OSC__ENABLE;
	uint8_t update_exponent = 0;
	uint8_t flip_flop = m_flip_flop;
	int count_f = 0;
	int count_r = 0;

	double v_out = 0;

	dt = this->sample_time();   /* Change in time */
	v_cap = m_v_cap;    /* Set to voltage before change */

	/* work out the charge currents/voltages. */
	switch (m_type)
	{
		case DISC_OP_AMP_OSCILLATOR_VCO_1:
			/* Work out the charge rates. */
			/* i is not a current.  It is being used as a temp variable. */
			i = DSS_OP_AMP_OSC__VMOD1 * m_temp1;
			charge[0] = (DSS_OP_AMP_OSC__VMOD1 - i) / info->r1;
			charge[1] = (i - (DSS_OP_AMP_OSC__VMOD1 * m_temp2)) / m_temp3;
			break;

		case DISC_OP_AMP_OSCILLATOR_1 | DISC_OP_AMP_IS_NORTON:
		{
			/* resistors can be nodes, so everything needs updating */
			double i1, i2;
			/* add in enable current if using real enable */
			if (m_has_enable)
			{
				if (enable)
					i = m_i_enable;
				enable = 1;
			}
			/* Work out the charge rates. */
			charge[0] = DSS_OP_AMP_OSC_NORTON_VP_IN / *m_r[1-1] - i;
			charge[1] = (m_v_out_high - OP_AMP_NORTON_VBE) / *m_r[2-1] - charge[0];
			/* Work out the Inverting Schmitt thresholds. */
			i1 = DSS_OP_AMP_OSC_NORTON_VP_IN / *m_r[5-1];
			i2 = (0.0 - OP_AMP_NORTON_VBE) / *m_r[4-1];
			m_threshold_low  = (i1 + i2) * *m_r[3-1] + OP_AMP_NORTON_VBE;
			i2 = (m_v_out_high - OP_AMP_NORTON_VBE) / *m_r[4-1];
			m_threshold_high = (i1 + i2) * *m_r[3-1] + OP_AMP_NORTON_VBE;
			break;
		}

		case DISC_OP_AMP_OSCILLATOR_VCO_1 | DISC_OP_AMP_IS_NORTON:
			/* Millman the input voltages. */
			if (info->r7 == 0)
			{
				/* No r7 means that the modulation circuit is fed directly into the circuit. */
				v = DSS_OP_AMP_OSC__VMOD1;
			}
			else
			{
				/* we need to mix any bias and all modulation voltages together. */
				i  = m_i_fixed;
				i += DSS_OP_AMP_OSC__VMOD1 / info->r7;
				if (info->r8 != 0)
					i += DSS_OP_AMP_OSC__VMOD2 / info->r8;
				v  = i * m_r_total;
			}

			/* Work out the charge rates. */
			v -= OP_AMP_NORTON_VBE;
			charge[0] = v / info->r1;
			charge[1] = v / info->r2 - charge[0];

			/* use the real enable circuit */
			force_charge = !enable;
			enable = 1;
			break;

		case DISC_OP_AMP_OSCILLATOR_VCO_2 | DISC_OP_AMP_IS_NORTON:
			/* Work out the charge rates. */
			i = DSS_OP_AMP_OSC__VMOD1 / info->r1;
			charge[0] = i - m_temp1;
			charge[1] = m_temp2 - i;
			/* if the negative pin current is less then the positive pin current, */
			/* then the osc is disabled and the cap keeps charging */
			if (charge[0] < 0)
			{
				force_charge =  1;
				charge[0]  *= -1;
			}
			break;

		case DISC_OP_AMP_OSCILLATOR_VCO_3 | DISC_OP_AMP_IS_NORTON:
			/* start with fixed bias */
			charge[0] = m_i_fixed;
			/* add in enable current if using real enable */
			if (m_has_enable)
			{
				if (enable)
					charge[0] -= m_i_enable;
				enable = 1;
			}
			/* we need to mix any bias and all modulation voltages together. */
			v = DSS_OP_AMP_OSC__VMOD1 - OP_AMP_NORTON_VBE;
			if (v < 0) v = 0;
			charge[0] += v / info->r1;
			if (info->r6 != 0)
			{
				v = DSS_OP_AMP_OSC__VMOD2 - OP_AMP_NORTON_VBE;
				charge[0] += v / info->r6;
			}
			charge[1] = m_temp1 - charge[0];
			break;
	}

	if (!enable)
	{
		/* we will just output 0 for oscillators that have no real enable. */
		set_output(0, 0);
		return;
	}

	/* Keep looping until all toggling in time sample is used up. */
	do
	{
		if (m_is_linear_charge)
		{
			if ((flip_flop ^ m_flip_flop_xor) || force_charge)
			{
				/* Charging */
				/* iC=C*dv/dt  works out to dv=iC*dt/C */
				v_cap_next = v_cap + (charge[1] * dt / info->c);
				dt = 0;

				/* has it charged past upper limit? */
				if (v_cap_next > m_threshold_high)
				{
					flip_flop = m_flip_flop_xor;
					if (flip_flop)
						count_r++;
					else
						count_f++;
					if (force_charge)
					{
						/* we need to keep charging the cap to the max thereby disabling the circuit */
						if (v_cap_next > m_v_out_high)
							v_cap_next = m_v_out_high;
					}
					else
					{
						/* calculate the overshoot time */
						dt = info->c * (v_cap_next - m_threshold_high) / charge[1];
						x_time = dt;
						v_cap_next = m_threshold_high;
					}
				}
			}
			else
			{
				/* Discharging */
				v_cap_next = v_cap - (charge[0] * dt / info->c);
				dt     = 0;

				/* has it discharged past lower limit? */
				if (v_cap_next < m_threshold_low)
				{
					flip_flop = !m_flip_flop_xor;
					if (flip_flop)
						count_r++;
					else
						count_f++;
					/* calculate the overshoot time */
					dt = info->c * (m_threshold_low - v_cap_next) / charge[0];
					x_time = dt;
					v_cap_next = m_threshold_low;
				}
			}
		}
		else    /* non-linear charge */
		{
			if (update_exponent)
				exponent = RC_CHARGE_EXP_DT(m_charge_rc[flip_flop], dt);
			else
				exponent = m_charge_exp[flip_flop];

			v_cap_next = v_cap + ((m_charge_v[flip_flop] - v_cap) * exponent);
			dt = 0;

			if (flip_flop)
			{
				/* Has it charged past upper limit? */
				if (v_cap_next > m_threshold_high)
				{
					dt = m_charge_rc[1]  * log(1.0 / (1.0 - ((v_cap_next - m_threshold_high) / (m_v_out_high - v_cap))));
					x_time = dt;
					v_cap_next = m_threshold_high;
					flip_flop = 0;
					count_f++;
					update_exponent = 1;
				}
			}
			else
			{
				/* has it discharged past lower limit? */
				if (v_cap_next < m_threshold_low)
				{
					dt = m_charge_rc[0] * log(1.0 / (1.0 - ((m_threshold_low - v_cap_next) / v_cap)));
					x_time = dt;
					v_cap_next = m_threshold_low;
					flip_flop = 1;
					count_r++;
					update_exponent = 1;
				}
			}
		}
		v_cap = v_cap_next;
	} while(dt);
	if (v_cap > m_v_out_high)
		v_cap = m_v_out_high;
	if (v_cap < 0)
		v_cap = 0;
	m_v_cap = v_cap;

	x_time = dt / this->sample_time();

	switch (m_output_type)
	{
		case DISC_OP_AMP_OSCILLATOR_OUT_CAP:
			v_out = v_cap;
			break;
		case DISC_OP_AMP_OSCILLATOR_OUT_ENERGY:
			if (x_time == 0) x_time = 1.0;
			v_out = m_v_out_high * (flip_flop ? x_time : (1.0 - x_time));
			break;
		case DISC_OP_AMP_OSCILLATOR_OUT_SQW:
			if (count_f + count_r >= 2)
				/* force at least 1 toggle */
				v_out = m_flip_flop ? 0 : m_v_out_high;
			else
				v_out = flip_flop * m_v_out_high;
			break;
		case DISC_OP_AMP_OSCILLATOR_OUT_COUNT_F_X:
			v_out = count_f ? count_f + x_time : count_f;
			break;
		case DISC_OP_AMP_OSCILLATOR_OUT_COUNT_R_X:
			v_out =  count_r ? count_r + x_time : count_r;
			break;
		case DISC_OP_AMP_OSCILLATOR_OUT_LOGIC_X:
			v_out = m_flip_flop + x_time;
			break;
	}
	set_output(0, v_out);
	m_flip_flop = flip_flop;
}

#define DIODE_DROP  0.7

DISCRETE_RESET(dss_op_amp_osc)
{
	DISCRETE_DECLARE_INFO(discrete_op_amp_osc_info)

	const double *r_info_ptr;
	int loop;

	double i1 = 0;  /* inverting input current */
	double i2 = 0;  /* non-inverting input current */

	/* link to resistor static or node values */
	r_info_ptr    = &info->r1;
	for (loop = 0; loop < 8; loop ++)
	{
		m_r[loop] = m_device->node_output_ptr(*r_info_ptr);
		if (m_r[loop] == nullptr)
			m_r[loop] = r_info_ptr;
		r_info_ptr++;
	}

	m_is_linear_charge = 1;
	m_output_type = info->type & DISC_OP_AMP_OSCILLATOR_OUT_MASK;
	m_type        = info->type & DISC_OP_AMP_OSCILLATOR_TYPE_MASK;
	m_charge_rc[0] = 0;
	m_charge_rc[1] = 0;
	m_charge_v[0] = 0;
	m_charge_v[1] = 0;
	m_i_fixed = 0;
	m_has_enable = 0;

	switch (m_type)
	{
		case DISC_OP_AMP_OSCILLATOR_VCO_1:
			/* The charge rates vary depending on vMod so they are not precalculated. */
			/* Charges while FlipFlop High */
			m_flip_flop_xor = 0;
			/* Work out the Non-inverting Schmitt thresholds. */
			m_temp1 = (info->vP / 2) / info->r4;
			m_temp2 = (info->vP - OP_AMP_VP_RAIL_OFFSET) / info->r3;
			m_temp3 = 1.0 / (1.0 / info->r3 + 1.0 / info->r4);
			m_threshold_low  =  m_temp1 * m_temp3;
			m_threshold_high = (m_temp1 + m_temp2) * m_temp3;
			/* There is no charge on the cap so the schmitt goes high at init. */
			m_flip_flop = 1;
			/* Setup some commonly used stuff */
			m_temp1 = info->r5 / (info->r2 + info->r5);         /* voltage ratio across r5 */
			m_temp2 = info->r6 / (info->r1 + info->r6);         /* voltage ratio across r6 */
			m_temp3 = 1.0 / (1.0 / info->r1 + 1.0 / info->r6);  /* input resistance when r6 switched in */
			break;

		case DISC_OP_AMP_OSCILLATOR_1 | DISC_OP_AMP_IS_NORTON:
			/* Charges while FlipFlop High */
			m_flip_flop_xor = 0;
			/* There is no charge on the cap so the schmitt inverter goes high at init. */
			m_flip_flop = 1;
			/* setup current if using real enable */
			if (info->r6 > 0)
			{
				m_has_enable = 1;
				m_i_enable = (info->vP - OP_AMP_NORTON_VBE) / (info->r6 + RES_K(1));
			}
			break;

		case DISC_OP_AMP_OSCILLATOR_2 | DISC_OP_AMP_IS_NORTON:
			m_is_linear_charge = 0;
			/* First calculate the parallel charge resistors and volatges. */
			/* We can cheat and just calcuate the charges in the working area. */
			/* The thresholds are well past the effect of the voltage drop */
			/* and the component tolerances far exceed the .5V charge difference */
			if (info->r1 != 0)
			{
				m_charge_rc[0] = 1.0 / info->r1;
				m_charge_rc[1] = 1.0 / info->r1;
				m_charge_v[1] = (info->vP - OP_AMP_NORTON_VBE) / info->r1;
			}
			if (info->r5 != 0)
			{
				m_charge_rc[0] += 1.0 / info->r5;
				m_charge_v[0] = DIODE_DROP / info->r5;
			}
			if (info->r6 != 0)
			{
				m_charge_rc[1] += 1.0 / info->r6;
				m_charge_v[1] += (info->vP - OP_AMP_NORTON_VBE - DIODE_DROP) / info->r6;
			}
			m_charge_rc[0] += 1.0 / info->r2;
			m_charge_rc[0] = 1.0 / m_charge_rc[0];
			m_charge_v[0] += OP_AMP_NORTON_VBE / info->r2;
			m_charge_v[0] *= m_charge_rc[0];
			m_charge_rc[1] += 1.0 / info->r2;
			m_charge_rc[1] = 1.0 / m_charge_rc[1];
			m_charge_v[1] += OP_AMP_NORTON_VBE / info->r2;
			m_charge_v[1] *= m_charge_rc[1];

			m_charge_rc[0] *= info->c;
			m_charge_rc[1] *= info->c;
			m_charge_exp[0] = RC_CHARGE_EXP(m_charge_rc[0]);
			m_charge_exp[1] = RC_CHARGE_EXP(m_charge_rc[1]);
			m_threshold_low  = (info->vP - OP_AMP_NORTON_VBE) / info->r4;
			m_threshold_high = m_threshold_low + (info->vP - 2 * OP_AMP_NORTON_VBE) / info->r3;;
			m_threshold_low  = m_threshold_low * info->r2 + OP_AMP_NORTON_VBE;
			m_threshold_high = m_threshold_high * info->r2 + OP_AMP_NORTON_VBE;

			/* There is no charge on the cap so the schmitt inverter goes high at init. */
			m_flip_flop = 1;
			break;

		case DISC_OP_AMP_OSCILLATOR_VCO_1 | DISC_OP_AMP_IS_NORTON:
			/* Charges while FlipFlop Low */
			m_flip_flop_xor = 1;
			/* There is no charge on the cap so the schmitt goes low at init. */
			m_flip_flop = 0;
			/* The charge rates vary depending on vMod so they are not precalculated. */
			/* But we can precalculate the fixed currents. */
			if (info->r6 != 0) m_i_fixed += info->vP / info->r6;
			m_i_fixed += OP_AMP_NORTON_VBE / info->r1;
			m_i_fixed += OP_AMP_NORTON_VBE / info->r2;
			/* Work out the input resistance to be used later to calculate the Millman voltage. */
			m_r_total = 1.0 / info->r1 + 1.0 / info->r2 + 1.0 / info->r7;
			if (info->r6) m_r_total += 1.0 / info->r6;
			if (info->r8) m_r_total += 1.0 / info->r8;
			m_r_total = 1.0 / m_r_total;
			/* Work out the Non-inverting Schmitt thresholds. */
			i1 = (info->vP - OP_AMP_NORTON_VBE) / info->r5;
			i2 = (info->vP - OP_AMP_NORTON_VBE - OP_AMP_NORTON_VBE) / info->r4;
			m_threshold_low = (i1 - i2) * info->r3 + OP_AMP_NORTON_VBE;
			i2 = (0.0 - OP_AMP_NORTON_VBE) / info->r4;
			m_threshold_high = (i1 - i2) * info->r3 + OP_AMP_NORTON_VBE;
			break;

		case DISC_OP_AMP_OSCILLATOR_VCO_2 | DISC_OP_AMP_IS_NORTON:
			/* Charges while FlipFlop High */
			m_flip_flop_xor = 0;
			/* There is no charge on the cap so the schmitt inverter goes high at init. */
			m_flip_flop = 1;
			/* Work out the charge rates. */
			m_temp1 = (info->vP - OP_AMP_NORTON_VBE) / info->r2;
			m_temp2 = (info->vP - OP_AMP_NORTON_VBE) * (1.0 / info->r2 + 1.0 / info->r6);
			/* Work out the Inverting Schmitt thresholds. */
			i1 = (info->vP - OP_AMP_NORTON_VBE) / info->r5;
			i2 = (0.0 - OP_AMP_NORTON_VBE) / info->r4;
			m_threshold_low = (i1 + i2) * info->r3 + OP_AMP_NORTON_VBE;
			i2 = (info->vP - OP_AMP_NORTON_VBE - OP_AMP_NORTON_VBE) / info->r4;
			m_threshold_high = (i1 + i2) * info->r3 + OP_AMP_NORTON_VBE;
			break;

		case DISC_OP_AMP_OSCILLATOR_VCO_3 | DISC_OP_AMP_IS_NORTON:
			/* Charges while FlipFlop High */
			m_flip_flop_xor = 0;
			/* There is no charge on the cap so the schmitt inverter goes high at init. */
			m_flip_flop = 1;
			/* setup current if using real enable */
			if (info->r8 > 0)
			{
				m_has_enable = 1;
				m_i_enable = (info->vP - OP_AMP_NORTON_VBE) / (info->r8 + RES_K(1));
			}
			/* Work out the charge rates. */
			/* The charge rates vary depending on vMod so they are not precalculated. */
			/* But we can precalculate the fixed currents. */
			if (info->r7 != 0) m_i_fixed = (info->vP - OP_AMP_NORTON_VBE) / info->r7;
			m_temp1 = (info->vP - OP_AMP_NORTON_VBE - OP_AMP_NORTON_VBE) / info->r2;
			/* Work out the Inverting Schmitt thresholds. */
			i1 = (info->vP - OP_AMP_NORTON_VBE) / info->r5;
			i2 = (0.0 - OP_AMP_NORTON_VBE) / info->r4;
			m_threshold_low = (i1 + i2) * info->r3 + OP_AMP_NORTON_VBE;
			i2 = (info->vP - OP_AMP_NORTON_VBE - OP_AMP_NORTON_VBE) / info->r4;
			m_threshold_high = (i1 + i2) * info->r3 + OP_AMP_NORTON_VBE;
			break;
	}

	m_v_out_high = info->vP - ((m_type & DISC_OP_AMP_IS_NORTON) ? OP_AMP_NORTON_VBE : OP_AMP_VP_RAIL_OFFSET);
	m_v_cap      = 0;

	this->step();
}


/************************************************************************
 *
 * DSS_SAWTOOTHWAVE - Usage of node_description values for step function
 *
 * input0    - Enable input value
 * input1    - Frequency input value
 * input2    - Amplitde input value
 * input3    - DC Bias Value
 * input4    - Gradient
 * input5    - Initial Phase
 *
 ************************************************************************/
#define DSS_SAWTOOTHWAVE__ENABLE    DISCRETE_INPUT(0)
#define DSS_SAWTOOTHWAVE__FREQ      DISCRETE_INPUT(1)
#define DSS_SAWTOOTHWAVE__AMP       DISCRETE_INPUT(2)
#define DSS_SAWTOOTHWAVE__BIAS      DISCRETE_INPUT(3)
#define DSS_SAWTOOTHWAVE__GRAD      DISCRETE_INPUT(4)
#define DSS_SAWTOOTHWAVE__PHASE     DISCRETE_INPUT(5)

DISCRETE_STEP(dss_sawtoothwave)
{
	double v_out;

	if(DSS_SAWTOOTHWAVE__ENABLE)
	{
		v_out = (m_type == 0) ? m_phase * (DSS_SAWTOOTHWAVE__AMP / (2.0 * M_PI)) : DSS_SAWTOOTHWAVE__AMP - (m_phase * (DSS_SAWTOOTHWAVE__AMP / (2.0 * M_PI)));
		v_out -= DSS_SAWTOOTHWAVE__AMP / 2.0;
		/* Add DC Bias component */
		v_out = v_out + DSS_SAWTOOTHWAVE__BIAS;
	}
	else
	{
		v_out = 0;
	}
	set_output(0, v_out);

	/* Work out the phase step based on phase/freq & sample rate */
	/* The enable input only curtails output, phase rotation     */
	/* still occurs                                              */
	/*     phase step = 2Pi/(output period/sample period)        */
	/*                    boils out to                           */
	/*     phase step = (2Pi*output freq)/sample freq)           */
	/* Also keep the new phasor in the 2Pi range.                */
	m_phase = fmod((m_phase + ((2.0 * M_PI * DSS_SAWTOOTHWAVE__FREQ) / this->sample_rate())), 2.0 * M_PI);
}

DISCRETE_RESET(dss_sawtoothwave)
{
	double start;

	/* Establish starting phase, convert from degrees to radians */
	start = (DSS_SAWTOOTHWAVE__PHASE / 360.0) * (2.0 * M_PI);
	/* Make sure its always mod 2Pi */
	m_phase = fmod(start, 2.0 * M_PI);

	/* Invert gradient depending on sawtooth type /|/|/|/|/| or |\|\|\|\|\ */
	m_type = (DSS_SAWTOOTHWAVE__GRAD) ? 1 : 0;

	/* Step the node to set the output */
	this->step();
}


/************************************************************************
 *
 * DSS_SCHMITT_OSC - Schmitt feedback oscillator
 *
 * input0    - Enable input value
 * input1    - Vin
 * input2    - Amplitude
 *
 * also passed discrete_schmitt_osc_disc structure
 *
 * Mar 2004, D Renaud.
 ************************************************************************/
#define DSS_SCHMITT_OSC__ENABLE (int)DISCRETE_INPUT(0)
#define DSS_SCHMITT_OSC__VIN    DISCRETE_INPUT(1)
#define DSS_SCHMITT_OSC__AMP    DISCRETE_INPUT(2)

DISCRETE_STEP(dss_schmitt_osc)
{
	DISCRETE_DECLARE_INFO(discrete_schmitt_osc_desc)

	double supply, v_cap, new_vCap, t, exponent;
	double v_out = 0;

	/* We will always oscillate.  The enable just affects the output. */
	v_cap    = m_v_cap;
	exponent = m_exponent;

	/* Keep looping until all toggling in time sample is used up. */
	do
	{
		t = 0;
		/* The charging voltage to the cap is the sum of the input voltage and the gate
		 * output voltage in the ratios determined by their resistors in a divider network.
		 * The input voltage is selectable as straight voltage in or logic level that will
		 * use vGate as its voltage.  Note that ration_in is just the ratio of the total
		 * voltage and needs to be multipled by the input voltage.  ratio_feedback has
		 * already been multiplied by vGate to save time because that voltage never changes. */
		supply   = m_input_is_voltage ? m_ration_in * DSS_SCHMITT_OSC__VIN : (DSS_SCHMITT_OSC__VIN ? m_ration_in * info->vGate : 0);
		supply  += (m_state ? m_ratio_feedback : 0);
		new_vCap = v_cap + ((supply - v_cap) * exponent);
		if (m_state)
		{
			/* Charging */
			/* has it charged past upper limit? */
			if (new_vCap > info->trshRise)
			{
				/* calculate the overshoot time */
				t = m_rc * log(1.0 / (1.0 - ((new_vCap - info->trshRise) / (info->vGate - v_cap))));
				/* calculate new exponent because of reduced time */
				exponent = RC_CHARGE_EXP_DT(m_rc, t);
				v_cap    = new_vCap = info->trshRise;
				m_state = 0;
			}
		}
		else
		{
			/* Discharging */
			/* has it discharged past lower limit? */
			if (new_vCap < info->trshFall)
			{
				/* calculate the overshoot time */
				t = m_rc * log(1.0 / (1.0 - ((info->trshFall - new_vCap) / v_cap)));
				/* calculate new exponent because of reduced time */
				exponent = RC_CHARGE_EXP_DT(m_rc, t);
				v_cap    = new_vCap = info->trshFall;
				m_state = 1;
			}
		}
	} while(t);

	m_v_cap = new_vCap;

	switch (m_enable_type)
	{
		case DISC_SCHMITT_OSC_ENAB_IS_AND:
			v_out = DSS_SCHMITT_OSC__ENABLE && m_state;
			break;
		case DISC_SCHMITT_OSC_ENAB_IS_NAND:
			v_out = !(DSS_SCHMITT_OSC__ENABLE && m_state);
			break;
		case DISC_SCHMITT_OSC_ENAB_IS_OR:
			v_out = DSS_SCHMITT_OSC__ENABLE || m_state;
			break;
		case DISC_SCHMITT_OSC_ENAB_IS_NOR:
			v_out = !(DSS_SCHMITT_OSC__ENABLE || m_state);
			break;
	}
	v_out *= DSS_SCHMITT_OSC__AMP;
	set_output(0, v_out);
}

DISCRETE_RESET(dss_schmitt_osc)
{
	DISCRETE_DECLARE_INFO(discrete_schmitt_osc_desc)

	double rSource;

	m_enable_type      =  info->options & DISC_SCHMITT_OSC_ENAB_MASK;
	m_input_is_voltage = (info->options & DISC_SCHMITT_OSC_IN_IS_VOLTAGE) ? 1 : 0;

	/* The 2 resistors make a voltage divider, so their ratios add together
	 * to make the charging voltage. */
	m_ration_in      = info->rFeedback / (info->rIn + info->rFeedback);
	m_ratio_feedback = info->rIn / (info->rIn + info->rFeedback) * info->vGate;

	/* The voltage source resistance works out to the 2 resistors in parallel.
	 * So use this for the RC charge constant. */
	rSource     = 1.0 / ((1.0 / info->rIn) + (1.0 / info->rFeedback));
	m_rc = rSource * info->c;
	m_exponent = RC_CHARGE_EXP(m_rc);

	/* Cap is at 0V on power up.  Causing output to be high. */
	m_v_cap = 0;
	m_state = 1;

	set_output(0, info->options ? 0 : DSS_SCHMITT_OSC__AMP);
}


/************************************************************************
 *
 * DSS_SINEWAVE - Usage of node_description values for step function
 *
 * input0    - Enable input value
 * input1    - Frequency input value
 * input2    - Amplitude input value
 * input3    - DC Bias
 * input4    - Starting phase
 *
 ************************************************************************/
#define DSS_SINEWAVE__ENABLE    DISCRETE_INPUT(0)
#define DSS_SINEWAVE__FREQ      DISCRETE_INPUT(1)
#define DSS_SINEWAVE__AMPL      DISCRETE_INPUT(2)
#define DSS_SINEWAVE__BIAS      DISCRETE_INPUT(3)
#define DSS_SINEWAVE__PHASE     DISCRETE_INPUT(4)

DISCRETE_STEP(dss_sinewave)
{
	/* Set the output */
	if(DSS_SINEWAVE__ENABLE)
	{
		set_output(0, (DSS_SINEWAVE__AMPL / 2.0) * sin(m_phase) + DSS_SINEWAVE__BIAS);
		/* Add DC Bias component */
	}
	else
	{
		set_output(0, 0);
	}

	/* Work out the phase step based on phase/freq & sample rate */
	/* The enable input only curtails output, phase rotation     */
	/* still occurs                                              */
	/*     phase step = 2Pi/(output period/sample period)        */
	/*                    boils out to                           */
	/*     phase step = (2Pi*output freq)/sample freq)           */
	/* Also keep the new phasor in the 2Pi range.                */
	m_phase=fmod((m_phase + ((2.0 * M_PI * DSS_SINEWAVE__FREQ) / this->sample_rate())), 2.0 * M_PI);
}

DISCRETE_RESET(dss_sinewave)
{
	double start;

	/* Establish starting phase, convert from degrees to radians */
	start = (DSS_SINEWAVE__PHASE / 360.0) * (2.0 * M_PI);
	/* Make sure its always mod 2Pi */
	m_phase = fmod(start, 2.0 * M_PI);
	/* Step the output to make it correct */
	this->step();
}


/************************************************************************
 *
 * DSS_SQUAREWAVE - Usage of node_description values for step function
 *
 * input0    - Enable input value
 * input1    - Frequency input value
 * input2    - Amplitude input value
 * input3    - Duty Cycle
 * input4    - DC Bias level
 * input5    - Start Phase
 *
 ************************************************************************/
#define DSS_SQUAREWAVE__ENABLE  DISCRETE_INPUT(0)
#define DSS_SQUAREWAVE__FREQ    DISCRETE_INPUT(1)
#define DSS_SQUAREWAVE__AMP     DISCRETE_INPUT(2)
#define DSS_SQUAREWAVE__DUTY    DISCRETE_INPUT(3)
#define DSS_SQUAREWAVE__BIAS    DISCRETE_INPUT(4)
#define DSS_SQUAREWAVE__PHASE   DISCRETE_INPUT(5)

DISCRETE_STEP(dss_squarewave)
{
	/* Establish trigger phase from duty */
	m_trigger=((100-DSS_SQUAREWAVE__DUTY)/100)*(2.0*M_PI);

	/* Set the output */
	if(DSS_SQUAREWAVE__ENABLE)
	{
		if(m_phase>m_trigger)
			set_output(0, DSS_SQUAREWAVE__AMP / 2.0 + DSS_SQUAREWAVE__BIAS);
		else
			set_output(0, - DSS_SQUAREWAVE__AMP / 2.0 + DSS_SQUAREWAVE__BIAS);
		/* Add DC Bias component */
	}
	else
	{
		set_output(0, 0);
	}

	/* Work out the phase step based on phase/freq & sample rate */
	/* The enable input only curtails output, phase rotation     */
	/* still occurs                                              */
	/*     phase step = 2Pi/(output period/sample period)        */
	/*                    boils out to                           */
	/*     phase step = (2Pi*output freq)/sample freq)           */
	/* Also keep the new phasor in the 2Pi range.                */
	m_phase=fmod(m_phase + ((2.0 * M_PI * DSS_SQUAREWAVE__FREQ) / this->sample_rate()), 2.0 * M_PI);
}

DISCRETE_RESET(dss_squarewave)
{
	double start;

	/* Establish starting phase, convert from degrees to radians */
	start = (DSS_SQUAREWAVE__PHASE / 360.0) * (2.0 * M_PI);
	/* Make sure its always mod 2Pi */
	m_phase = fmod(start, 2.0 * M_PI);

	/* Step the output */
	this->step();
}

/************************************************************************
 *
 * DSS_SQUAREWFIX - Usage of node_description values for step function
 *
 * input0    - Enable input value
 * input1    - Frequency input value
 * input2    - Amplitude input value
 * input3    - Duty Cycle
 * input4    - DC Bias level
 * input5    - Start Phase
 *
 ************************************************************************/
#define DSS_SQUAREWFIX__ENABLE  DISCRETE_INPUT(0)
#define DSS_SQUAREWFIX__FREQ    DISCRETE_INPUT(1)
#define DSS_SQUAREWFIX__AMP     DISCRETE_INPUT(2)
#define DSS_SQUAREWFIX__DUTY    DISCRETE_INPUT(3)
#define DSS_SQUAREWFIX__BIAS    DISCRETE_INPUT(4)
#define DSS_SQUAREWFIX__PHASE   DISCRETE_INPUT(5)

DISCRETE_STEP(dss_squarewfix)
{
	m_t_left -= m_sample_step;

	/* The enable input only curtails output, phase rotation still occurs */
	while (m_t_left <= 0)
	{
		m_flip_flop = m_flip_flop ? 0 : 1;
		m_t_left   += m_flip_flop ? m_t_on : m_t_off;
	}

	if(DSS_SQUAREWFIX__ENABLE)
	{
		/* Add gain and DC Bias component */

		m_t_off  = 1.0 / DSS_SQUAREWFIX__FREQ;  /* cycle time */
		m_t_on   = m_t_off * (DSS_SQUAREWFIX__DUTY / 100.0);
		m_t_off -= m_t_on;

		set_output(0, (m_flip_flop ? DSS_SQUAREWFIX__AMP / 2.0 : -(DSS_SQUAREWFIX__AMP / 2.0)) + DSS_SQUAREWFIX__BIAS);
	}
	else
	{
		set_output(0, 0);
	}
}

DISCRETE_RESET(dss_squarewfix)
{
	m_sample_step = 1.0 / this->sample_rate();
	m_flip_flop   = 1;

	/* Do the intial time shift and convert freq to off/on times */
	m_t_off   = 1.0 / DSS_SQUAREWFIX__FREQ; /* cycle time */
	m_t_left  = DSS_SQUAREWFIX__PHASE / 360.0;  /* convert start phase to % */
	m_t_left  = m_t_left - (int)m_t_left;   /* keep % between 0 & 1 */
	m_t_left  = (m_t_left < 0) ? 1.0 + m_t_left : m_t_left; /* if - then flip to + phase */
	m_t_left *= m_t_off;
	m_t_on    = m_t_off * (DSS_SQUAREWFIX__DUTY / 100.0);
	m_t_off  -= m_t_on;

	m_t_left = -m_t_left;

	/* toggle output and work out intial time shift */
	while (m_t_left <= 0)
	{
		m_flip_flop = m_flip_flop ? 0 : 1;
		m_t_left   += m_flip_flop ? m_t_on : m_t_off;
	}

	/* Step the output */
	this->step();
}


/************************************************************************
 *
 * DSS_SQUAREWAVE2 - Usage of node_description values
 *
 * input0    - Enable input value
 * input1    - Amplitude input value
 * input2    - OFF Time
 * input3    - ON Time
 * input4    - DC Bias level
 * input5    - Initial Time Shift
 *
 ************************************************************************/
#define DSS_SQUAREWAVE2__ENABLE DISCRETE_INPUT(0)
#define DSS_SQUAREWAVE2__AMP    DISCRETE_INPUT(1)
#define DSS_SQUAREWAVE2__T_OFF  DISCRETE_INPUT(2)
#define DSS_SQUAREWAVE2__T_ON   DISCRETE_INPUT(3)
#define DSS_SQUAREWAVE2__BIAS   DISCRETE_INPUT(4)
#define DSS_SQUAREWAVE2__SHIFT  DISCRETE_INPUT(5)

DISCRETE_STEP(dss_squarewave2)
{
	double newphase;

	if(DSS_SQUAREWAVE2__ENABLE)
	{
		/* Establish trigger phase from time periods */
		m_trigger = (DSS_SQUAREWAVE2__T_OFF / (DSS_SQUAREWAVE2__T_OFF + DSS_SQUAREWAVE2__T_ON)) * (2.0 * M_PI);

		/* Work out the phase step based on phase/freq & sample rate */
		/* The enable input only curtails output, phase rotation     */
		/* still occurs                                              */

		/*     phase step = 2Pi/(output period/sample period)        */
		/*                    boils out to                           */
		/*     phase step = 2Pi/(output period*sample freq)          */
		newphase = m_phase + ((2.0 * M_PI) / ((DSS_SQUAREWAVE2__T_OFF + DSS_SQUAREWAVE2__T_ON) * this->sample_rate()));
		/* Keep the new phasor in the 2Pi range.*/
		m_phase = fmod(newphase, 2.0 * M_PI);

		/* Add DC Bias component */
		if(m_phase>m_trigger)
			set_output(0, DSS_SQUAREWAVE2__AMP / 2.0  + DSS_SQUAREWAVE2__BIAS);
		else
			set_output(0, -DSS_SQUAREWAVE2__AMP / 2.0 + DSS_SQUAREWAVE2__BIAS);
	}
	else
	{
		set_output(0, 0);
	}
}

DISCRETE_RESET(dss_squarewave2)
{
	double start;

	/* Establish starting phase, convert from degrees to radians */
	/* Only valid if we have set the on/off time                 */
	if((DSS_SQUAREWAVE2__T_OFF + DSS_SQUAREWAVE2__T_ON) != 0.0)
		start = (DSS_SQUAREWAVE2__SHIFT / (DSS_SQUAREWAVE2__T_OFF + DSS_SQUAREWAVE2__T_ON)) * (2.0 * M_PI);
	else
		start = 0.0;
	/* Make sure its always mod 2Pi */
	m_phase = fmod(start, 2.0 * M_PI);

	/* Step the output */
	this->step();
}

/************************************************************************
 *
 * DSS_INVERTER_OSC - Usage of node_description values
 *
 * input0    - Enable input value
 * input1    - RC Resistor
 * input2    - RP Resistor
 * input3    - C Capacitor
 * input4    - Desc
 *
 ************************************************************************/

/*
 * Taken from the transfer characteristerics diagram in CD4049UB datasheet (TI)
 * There is no default trigger point and vI-vO is a continuous function
 */

inline double DISCRETE_CLASS_FUNC(dss_inverter_osc, tftab)(double x)
{
	DISCRETE_DECLARE_INFO(description)

	x = x / info->vB;
	if (x > 0)
		return info->vB * exp(-mc_tf_a * pow(x, mc_tf_b));
	else
		return info->vB;
}

inline double DISCRETE_CLASS_FUNC(dss_inverter_osc, tf)(double x)
{
	DISCRETE_DECLARE_INFO(description)

	if (x < 0.0)
		return info->vB;
	else if (x <= info->vB)
		return mc_tf_tab[(int)((double)(DSS_INV_TAB_SIZE - 1) * x / info->vB)];
	else
		return mc_tf_tab[DSS_INV_TAB_SIZE - 1];
}

DISCRETE_STEP(dss_inverter_osc)
{
	DISCRETE_DECLARE_INFO(description)
	double diff, vG1, vG2, vG3, vI;
	double vMix, rMix;
	int clamped;
	double v_out;

	/* Get new state */
	vI = mc_v_cap + mc_v_g2_old;
	switch (info->options & TYPE_MASK)
	{
		case IS_TYPE1:
		case IS_TYPE3:
			vG1 = this->tf(vI);
			vG2 = this->tf(vG1);
			vG3 = this->tf(vG2);
			break;
		case IS_TYPE2:
			vG1 = 0;
			vG3 = this->tf(vI);
			vG2 = this->tf(vG3);
			break;
		case IS_TYPE4:
			vI  = std::min(I_ENABLE(), vI + 0.7);
			vG1 = 0;
			vG3 = this->tf(vI);
			vG2 = this->tf(vG3);
			break;
		case IS_TYPE5:
			vI  = std::max(I_ENABLE(), vI - 0.7);
			vG1 = 0;
			vG3 = this->tf(vI);
			vG2 = this->tf(vG3);
			break;
		default:
			fatalerror("DISCRETE_INVERTER_OSC - Wrong type on NODE_%02d\n", this->index());
	}

	clamped = 0;
	if (info->clamp >= 0.0)
	{
		if (vI < -info->clamp)
		{
			vI = -info->clamp;
			clamped = 1;
		}
		else if (vI > info->vB+info->clamp)
		{
			vI = info->vB + info->clamp;
			clamped = 1;
		}
	}

	switch (info->options & TYPE_MASK)
	{
		case IS_TYPE1:
		case IS_TYPE2:
		case IS_TYPE3:
			if (clamped)
			{
				double ratio = mc_rp / (mc_rp + mc_r1);
				diff = vG3 * (ratio)
						- (mc_v_cap + vG2)
						+ vI * (1.0 - ratio);
				diff = diff - diff * mc_wc;
			}
			else
			{
				diff = vG3 - (mc_v_cap + vG2);
				diff = diff - diff * mc_w;
			}
			break;
		case IS_TYPE4:
			/*  FIXME handle r2 = 0  */
			rMix = (mc_r1 * mc_r2) / (mc_r1 + mc_r2);
			vMix = rMix* ((vG3 - vG2) / mc_r1 + (I_MOD() -vG2) / mc_r2);
			if (vMix < (vI-vG2-0.7))
			{
				rMix = 1.0 / rMix + 1.0 / mc_rp;
				rMix = 1.0 / rMix;
				vMix = rMix* ( (vG3-vG2) / mc_r1 + (I_MOD() - vG2) / mc_r2
						+ (vI - 0.7 - vG2) / mc_rp);
			}
			diff = vMix - mc_v_cap;
			diff = diff - diff * exp(-this->sample_time() / (mc_c * rMix));
			break;
		case IS_TYPE5:
			/*  FIXME handle r2 = 0  */
			rMix = (mc_r1 * mc_r2) / (mc_r1 + mc_r2);
			vMix = rMix* ((vG3 - vG2) / mc_r1 + (I_MOD() - vG2) / mc_r2);
			if (vMix > (vI -vG2 + 0.7))
			{
				rMix = 1.0 / rMix + 1.0 / mc_rp;
				rMix = 1.0 / rMix;
				vMix = rMix * ( (vG3 - vG2) / mc_r1 + (I_MOD() - vG2) / mc_r2
						+ (vI + 0.7 - vG2) / mc_rp);
			}
			diff = vMix - mc_v_cap;
			diff = diff - diff * exp(-this->sample_time()/(mc_c * rMix));
			break;
		default:
			fatalerror("DISCRETE_INVERTER_OSC - Wrong type on NODE_%02d\n", this->index());
	}

	mc_v_cap   += diff;
	mc_v_g2_old = vG2;

	if ((info->options & TYPE_MASK) == IS_TYPE3)
		v_out = vG1;
	else
		v_out = vG3;

	if (info->options & OUT_IS_LOGIC)
		v_out = (v_out > info->vInFall);

	set_output(0, v_out);
}

DISCRETE_RESET(dss_inverter_osc)
{
	DISCRETE_DECLARE_INFO(description)

	int i;

	/* exponent */
	mc_w  = exp(-this->sample_time() / (I_RC() * I_C()));
	mc_wc = exp(-this->sample_time() / ((I_RC() * I_RP()) / (I_RP() + I_RC()) * I_C()));
	set_output(0, 0);
	mc_v_cap    = 0;
	mc_v_g2_old = 0;
	mc_rp   = I_RP();
	mc_r1   = I_RC();
	mc_r2   = I_R2();
	mc_c    = I_C();
	mc_tf_b = (log(0.0 - log(info->vOutLow/info->vB)) - log(0.0 - log((info->vOutHigh/info->vB))) ) / log(info->vInRise / info->vInFall);
	mc_tf_a = log(0.0 - log(info->vOutLow/info->vB)) - mc_tf_b * log(info->vInRise/info->vB);
	mc_tf_a = exp(mc_tf_a);

	for (i = 0; i < DSS_INV_TAB_SIZE; i++)
	{
		mc_tf_tab[i] = this->tftab((double)i / (double)(DSS_INV_TAB_SIZE - 1) * info->vB);
	}
}

/************************************************************************
 *
 * DSS_TRIANGLEWAVE - Usage of node_description values for step function
 *
 * input0    - Enable input value
 * input1    - Frequency input value
 * input2    - Amplitde input value
 * input3    - DC Bias value
 * input4    - Initial Phase
 *
 ************************************************************************/
#define DSS_TRIANGLEWAVE__ENABLE    DISCRETE_INPUT(0)
#define DSS_TRIANGLEWAVE__FREQ      DISCRETE_INPUT(1)
#define DSS_TRIANGLEWAVE__AMP       DISCRETE_INPUT(2)
#define DSS_TRIANGLEWAVE__BIAS      DISCRETE_INPUT(3)
#define DSS_TRIANGLEWAVE__PHASE     DISCRETE_INPUT(4)

DISCRETE_STEP(dss_trianglewave)
{
	if(DSS_TRIANGLEWAVE__ENABLE)
	{
		double v_out = m_phase < M_PI ? (DSS_TRIANGLEWAVE__AMP * (m_phase / (M_PI / 2.0) - 1.0)) / 2.0 :
									(DSS_TRIANGLEWAVE__AMP * (3.0 - m_phase / (M_PI / 2.0))) / 2.0 ;

		/* Add DC Bias component */
		v_out  += DSS_TRIANGLEWAVE__BIAS;
		set_output(0, v_out);
	}
	else
	{
		set_output(0, 0);
	}

	/* Work out the phase step based on phase/freq & sample rate */
	/* The enable input only curtails output, phase rotation     */
	/* still occurs                                              */
	/*     phase step = 2Pi/(output period/sample period)        */
	/*                    boils out to                           */
	/*     phase step = (2Pi*output freq)/sample freq)           */
	/* Also keep the new phasor in the 2Pi range.                */
	m_phase=fmod((m_phase + ((2.0 * M_PI * DSS_TRIANGLEWAVE__FREQ) / this->sample_rate())), 2.0 * M_PI);
}

DISCRETE_RESET(dss_trianglewave)
{
	double start;

	/* Establish starting phase, convert from degrees to radians */
	start = (DSS_TRIANGLEWAVE__PHASE / 360.0) * (2.0 * M_PI);
	/* Make sure its always mod 2Pi */
	m_phase=fmod(start, 2.0 * M_PI);

	/* Step to set the output */
	this->step();
}


/************************************************************************
 *
 * DSS_ADSR - Attack Decay Sustain Release
 *
 * input0    - Enable input value
 * input1    - Trigger value
 * input2    - gain scaling factor
 *
 ************************************************************************/
#define DSS_ADSR__ENABLE    DISCRETE_INPUT(0)

DISCRETE_STEP(dss_adsrenv)
{
	if(DSS_ADSR__ENABLE)
	{
		set_output(0, 0);
	}
	else
	{
		set_output(0, 0);
	}
}


DISCRETE_RESET(dss_adsrenv)
{
	this->step();
}