//////////////////////////////////////////////////////////////////////////////////////
var PRECISION = 4;
var low_threshold;
var high_threshold;
var Vref;
var Vout_high;
var Vout_low;

var typ_r1;
var min_r1;
var max_r1;

var typ_r2;
var min_r2;
var max_r2;

var typ_high_threshold;
var min_high_threshold;
var max_high_threshold;

var typ_low_threshold;
var min_low_threshold;
var max_low_threshold;

//////////////////////////////////////////////////////////////////////////////////////

function calc_high_threshold(r1, r2, Vref)
{
	return (Vref + r1*(Vref-Vout_low)/r2);
}
//////////////////////////////////////////////////////////////////////////////////////

function calc_low_threshold(r1, r2, Vref)
{
	return (Vref + r1*(Vref-Vout_high)/r2);
}
//////////////////////////////////////////////////////////////////////////////////////

function update_real_values()
{
	document.schmitt_trigger_form.typ_r1.value  = parseFloat( typ_r1.toPrecision(PRECISION) );
	document.schmitt_trigger_form.min_r1.value  = parseFloat( min_r1.toPrecision(PRECISION) );
	document.schmitt_trigger_form.max_r1.value  = parseFloat( max_r1.toPrecision(PRECISION) );

	document.schmitt_trigger_form.typ_r2.value  = parseFloat( typ_r2.toPrecision(PRECISION) );
	document.schmitt_trigger_form.min_r2.value  = parseFloat( min_r2.toPrecision(PRECISION) );
	document.schmitt_trigger_form.max_r2.value  = parseFloat( max_r2.toPrecision(PRECISION) );
	
	document.schmitt_trigger_form.typ_low_threshold.value  = parseFloat( typ_low_threshold.toPrecision(PRECISION) );
	document.schmitt_trigger_form.min_low_threshold.value  = parseFloat( min_low_threshold.toPrecision(PRECISION) );
	document.schmitt_trigger_form.max_low_threshold.value  = parseFloat( max_low_threshold.toPrecision(PRECISION) );

	document.schmitt_trigger_form.typ_high_threshold.value  = parseFloat( typ_high_threshold.toPrecision(PRECISION) );
	document.schmitt_trigger_form.min_high_threshold.value  = parseFloat( min_high_threshold.toPrecision(PRECISION) );
	document.schmitt_trigger_form.max_high_threshold.value  = parseFloat( max_high_threshold.toPrecision(PRECISION) );

}
//////////////////////////////////////////////////////////////////////////////////////////

function set_preff_series()
{		
	if(document.schmitt_trigger_form.series[0].checked == true)
	{
		preff_array = new Array(100,150,220,330,470,680,1000,1500);
		preff_array_size = 6;
	}

	if(document.schmitt_trigger_form.series[1].checked == true)
	{		
		preff_array = new Array(100,120,150,180,220,270,330,390,470,560,680,820,1000,1200);
		preff_array_size = 12;
	}

	if(document.schmitt_trigger_form.series[2].checked == true)
	{
		preff_array = new Array(100,110,120,130,150,160,180,200,220,240,270,300,330,360,390,430,470,510,560,620,680,750,820,910,1000, 1100);
		preff_array_size = 24;
	}

	if(document.schmitt_trigger_form.series[3].checked == true)
	{
		preff_array = new Array(100,105,110,115,121,127,133,140,147,154,162,169,
					178,187,196,205,215,226,237,249,261,274,287,301,
					316,332,348,365,383,402,422,442,464,487,511,536,
					562,590,619,649,681,715,750,787,825,866,909,953,1000, 1050);
		preff_array_size = 48;
	}

	if(document.schmitt_trigger_form.series[4].checked == true)
	{
		preff_array = new Array(100,102,105,107,110,113,115,118,121,124,127,130,133,137,140,143,147,150,154,158,162,165,169,174,
						178,182,187,191,196,200,205,210,215,221,226,232,237,243,249,255,261,267,274,280,287,294,301,309,
						316,324,332,340,348,357,365,374,383,392,402,412,422,432,442,453,464,475,487,499,511,523,536,549,
						562,576,590,604,619,634,649,665,681,698,715,732,750,768,787,806,825,845,866,887,909,931,953,976,1000, 1020);
		preff_array_size = 96;
	}
}

//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

function preff_values(i)
{		
	if(i >= preff_array_size)
	{
		return preff_array[preff_array_size -1];
	}

	return preff_array[i];
}
//////////////////////////////////////////////////////////////////////////////////////

function nearest_above(r1_significand)
{
	// trap values which may cause infinite loop

	if(r1_significand <= 0)
		return 0;
	if( !isFinite(r1_significand) ) 
		return r1_significand;


	var multiply_factor = 0;

	while(r1_significand <= 100.0)
	{
		r1_significand = r1_significand*10.0
		multiply_factor--
	}

	while(r1_significand > 1000.0)
	{
		r1_significand = r1_significand/10.0
		multiply_factor++
	}

	var i = 0;
	while(r1_significand > preff_array[i])
	{
		i++;
	}

	return ( preff_array[i]*Math.pow(10,multiply_factor) );
}
//////////////////////////////////////////////////////////////////////////////////////

function nearest_below(r1_significand)
{
	// trap values which may cause infinite loop

	if(r1_significand <= 0)
		return 0;
	if( !isFinite(r1_significand) ) 
		return r1_significand;


	var multiply_factor = 0;

	while(r1_significand <= 100.0)
	{
		r1_significand = r1_significand*10.0
		multiply_factor--
	}

	while(r1_significand > 1000.0)
	{
		r1_significand = r1_significand/10.0
		multiply_factor++
	}

	var i = 0;
	while(r1_significand > preff_array[i])
	{
		i++;
	}

	return ( preff_array[i-1]*Math.pow(10,multiply_factor) );
}
//////////////////////////////////////////////////////////////////////////////////////

function get_r_tol()
{
	if(document.schmitt_trigger_form.r_tol[0].checked == true)
	{
		// 5% tolerance
		return 0.05;
	}

	if(document.schmitt_trigger_form.r_tol[1].checked == true)
	{		
		// 1% tolerance
		return 0.01;
	}

	if(document.schmitt_trigger_form.r_tol[2].checked == true)
	{
		// 0.5% tolerance
		return 0.005;
	}

	if(document.schmitt_trigger_form.r_tol[3].checked == true)
	{
		// 0.1% tolerance
		return 0.001;
	}

	if(document.schmitt_trigger_form.r_tol[4].checked == true)
	{
		// other tolerance, so read from text field
		var r_tol = parseFloat(document.schmitt_trigger_form.r_tolerance.value) / 100.0;

		if( isNaN(r_tol) )
			r_tol = 0;
		return r_tol;
	}
}
//////////////////////////////////////////////////////////////////////////////////////

function calculate()
{
	set_preff_series();
	var r_tol = get_r_tol();
		
	// read values from form
	low_threshold =  parseFloat(document.schmitt_trigger_form.low_threshold.value);
	high_threshold = parseFloat(document.schmitt_trigger_form.high_threshold.value);
	
	if(low_threshold > high_threshold)
	{
		alert("You have entered a High Threshold which is lower than the Low Threshold.  The values will therefore be swapped");
		var temp = high_threshold;
		high_threshold = low_threshold;
		low_threshold = temp;
		
		document.schmitt_trigger_form.low_threshold.value = low_threshold;
		document.schmitt_trigger_form.high_threshold.value = high_threshold;
	}
	
	Vout_high = parseFloat(document.schmitt_trigger_form.Vout_high.value);
	Vout_low = parseFloat(document.schmitt_trigger_form.Vout_low.value);

	Vref = (high_threshold*Vout_high - low_threshold*Vout_low) / (high_threshold - low_threshold + Vout_high - Vout_low);
		
	var R2 = 1;	// choose arbitary value for R2 to start with
		
		
	var R1 = (high_threshold - Vref)/(Vref - Vout_low);
	
	document.schmitt_trigger_form.R1.value = parseFloat( 10*R1.toPrecision(PRECISION) );
	document.schmitt_trigger_form.R2.value = parseFloat( 10*R2.toPrecision(PRECISION) );
	document.schmitt_trigger_form.Vref.value = parseFloat( Vref.toPrecision(PRECISION) );
	
	//find best stardard values
	
	var best_r1 = 0;
	var best_r2 = 0;
	
	var best_error = 999999999999.9;
	var error;
	var r1;
	var r2;
	
	for(var i = 0; i < preff_array_size; i++)
	{
		r2 = preff_values(i)/10;
		
		r1 = nearest_above(r2*R1);
		
		error = (calc_high_threshold(r1, r2, Vref) - high_threshold)*(calc_high_threshold(r1, r2, Vref) - high_threshold) 
			+ (calc_low_threshold(r1, r2, Vref) - low_threshold)*(calc_low_threshold(r1, r2, Vref) - low_threshold);
		if(error < best_error)
		{
			best_r1 = r1;
			best_r2 = r2;

			best_error = error;
		}

		r1 = nearest_below(r2*R1);
		
		error = (calc_high_threshold(r1, r2, Vref) - high_threshold)*(calc_high_threshold(r1, r2, Vref) - high_threshold) 
			+ (calc_low_threshold(r1, r2, Vref) - low_threshold)*(calc_low_threshold(r1, r2, Vref) - low_threshold);
		if(error < best_error)
		{
			best_r1 = r1;
			best_r2 = r2;

			best_error = error;
		}
	}
	
	typ_r1 = best_r1;
	typ_r2 = best_r2;
	
	max_r1 = best_r1*(1+r_tol);
	max_r2 = best_r2*(1+r_tol);
	
	min_r1 = best_r1*(1-r_tol);
	min_r2 = best_r2*(1-r_tol);
	
	typ_high_threshold = calc_high_threshold(typ_r1, typ_r2, Vref);
	typ_low_threshold = calc_low_threshold(typ_r1, typ_r2, Vref);
	
	min_high_threshold = calc_high_threshold(max_r1, min_r2, Vref);
	min_low_threshold = calc_low_threshold(max_r1, min_r2, Vref);

	max_high_threshold = calc_high_threshold(min_r1, max_r2, Vref);
	max_low_threshold = calc_low_threshold(min_r1, max_r2, Vref);
	
	update_real_values();
	
}
