/*** ATmega Timer/Counter/Prescaler Calculator ***/

/**
 * Calculate Timer/Counter/Prescaler values.
 */
function calcFt() {
	var form = document.forms["OCCR"];
	var Fc = replacePrefixes(form.Fc.value);
	var Ft = replacePrefixes(form.Ft.value);
	var factor = replacePrefixes(form.factor.value);
	var factor = 0;
	
	if(Fc > 0 && Ft > 0) {
		factor = Fc/Ft;
		form.factor.value = roundWithPrefix(factor,2);
		var pre1val = Math.round(factor/1);
		var pre8val = Math.round(factor/8);
		var pre64val = Math.round(factor/64);
		var pre256val = Math.round(factor/256);
		var pre1024val = Math.round(factor/1024);
		var lowestPre0 = 1, lowestPre1 = 1;
		
		//Timer/Counter1 is 16 bit
		if(pre1val <= 65536) {
			document.getElementById("pre1").style.background="#F60";
		} else {
			document.getElementById("pre1").style.background="#F00";
			lowestPre1 = 8;
		}
		if(pre8val <= 65536) {
			document.getElementById("pre8").style.background="#F60";
		} else {
			document.getElementById("pre8").style.background="#F00";
			lowestPre1 = 64;
		}
		if(pre64val <= 65536) {
			document.getElementById("pre64").style.background="#F60";
		} else {
			document.getElementById("pre64").style.background="#F00";
			lowestPre1 = 256;
		}
		if(pre256val <= 65536) {
			document.getElementById("pre256").style.background="#F60";
		} else {
			document.getElementById("pre256").style.background="#F00";
			lowestPre1 = 1024;
		}
		if(pre1024val <= 65536) {
			document.getElementById("pre1024").style.background="#F60";
		} else {
			document.getElementById("pre1024").style.background="#F00";
			lowestPre1 = "NaN";
		}
		
		//Timer/Counter0 is 8 bit
		if(pre1val <= 256) {
			document.getElementById("pre1").style.background="#6C0";
		} else {
			lowestPre0 = 8;
		}
		if(pre8val <= 256) {
			document.getElementById("pre8").style.background="#6C0";
		} else {
			lowestPre0 = 64;
		}
		if(pre64val <= 256) {
			document.getElementById("pre64").style.background="#6C0";
		} else {
			lowestPre0 = 256;
		}
		if(pre256val <= 256) {
			document.getElementById("pre256").style.background="#6C0";
		} else {
			lowestPre0 = 1024;
		}
		if(pre1024val <= 256) {
			document.getElementById("pre1024").style.background="#6C0";
		} else {
			lowestPre0 = "NaN";
		}
		
		setRegsTimer0(factor, lowestPre0);
		setRegsTimer1(factor, lowestPre1);
		document.getElementById("regTitle").innerHTML = " (<span style=\"color:#6C0\">prescaler "+lowestPre0+"</span> and <span style=\"color:#F60\">prescaler "+lowestPre1+"</span>)";
		
		document.getElementById("pre1dec").innerHTML = pre1val;
		document.getElementById("pre8dec").innerHTML = pre8val;
		document.getElementById("pre64dec").innerHTML = pre64val;
		document.getElementById("pre256dec").innerHTML = pre256val;
		document.getElementById("pre1024dec").innerHTML = pre1024val;
		
		document.getElementById("pre1hex").innerHTML = "0x"+(pre1val.toString(16)).toUpperCase();
		document.getElementById("pre8hex").innerHTML = "0x"+(pre8val.toString(16)).toUpperCase();
		document.getElementById("pre64hex").innerHTML = "0x"+(pre64val.toString(16)).toUpperCase();
		document.getElementById("pre256hex").innerHTML = "0x"+(pre256val.toString(16)).toUpperCase();
		document.getElementById("pre1024hex").innerHTML = "0x"+(pre1024val.toString(16)).toUpperCase();
		
		pre1val = ((factor-(pre1val*1))/100);
		pre8val = ((factor-(pre8val*8))/100);
		pre64val = ((factor-(pre64val*64))/100);
		pre256val = ((factor-(pre256val*256))/100);
		pre1024val = ((factor-(pre1024val*1024))/100);
		
		document.getElementById("pre1err").innerHTML =
			 Math.round(pre1val*Math.pow(10,2))/Math.pow(10,2);
		document.getElementById("pre8err").innerHTML =
			 Math.round(pre8val*Math.pow(10,2))/Math.pow(10,2);
		document.getElementById("pre64err").innerHTML =
			 Math.round(pre64val*Math.pow(10,2))/Math.pow(10,2);
		document.getElementById("pre256err").innerHTML =
			 Math.round(pre256val*Math.pow(10,2))/Math.pow(10,2);
		document.getElementById("pre1024err").innerHTML =
			 Math.round(pre1024val*Math.pow(10,2))/Math.pow(10,2);
	}
	else {
		form.factor.value = "NaN";
	}
	
	return false;
}

function setRegsTimer0(factor, pre) {
	document.getElementById("OCR0").innerHTML =
		"0x"+((Math.round(factor/pre)).toString(16)).toUpperCase();
	document.getElementById("OCR0").style.color="green";
	
	switch(pre) {
		case 1 : {
			document.getElementById("CS02").style.background="#CCC";
			document.getElementById("CS01").style.background="#CCC";
			document.getElementById("CS00").style.background="#6C0";
			break;
		}
		case 8 : {
			document.getElementById("CS02").style.background="#CCC";
			document.getElementById("CS01").style.background="#6C0";
			document.getElementById("CS00").style.background="#CCC";
			break;
		}
		case 64 : {
			document.getElementById("CS02").style.background="#CCC";
			document.getElementById("CS01").style.background="#6C0";
			document.getElementById("CS00").style.background="#6C0";
			break;
		}
		case 256 : {
			document.getElementById("CS02").style.background="#6C0";
			document.getElementById("CS01").style.background="#CCC";
			document.getElementById("CS00").style.background="#CCC";
			break;
		}
		case 1024 : {
			document.getElementById("CS02").style.background="#6C0";
			document.getElementById("CS01").style.background="#CCC";
			document.getElementById("CS00").style.background="#6C0";
			break;
		}
		default : {
			document.getElementById("CS02").style.background="#CCC";
			document.getElementById("CS01").style.background="#CCC";
			document.getElementById("CS00").style.background="#CCC";
			break;
		}
	}
}

function setRegsTimer1(factor, pre) {
	document.getElementById("OCR1").innerHTML =
		"0x"+((Math.round(factor/pre)).toString(16)).toUpperCase();
	document.getElementById("OCR1").style.color="#F60";
	
	switch(pre) {
		case 1 : {
			document.getElementById("CS12").style.background="#CCC";
			document.getElementById("CS11").style.background="#CCC";
			document.getElementById("CS10").style.background="#F60";
			break;
		}
		case 8 : {
			document.getElementById("CS12").style.background="#CCC";
			document.getElementById("CS11").style.background="#F60";
			document.getElementById("CS10").style.background="#CCC";
			break;
		}
		case 64 : {
			document.getElementById("CS12").style.background="#CCC";
			document.getElementById("CS11").style.background="#F60";
			document.getElementById("CS10").style.background="#F60";
			break;
		}
		case 256 : {
			document.getElementById("CS12").style.background="#F60";
			document.getElementById("CS11").style.background="#CCC";
			document.getElementById("CS10").style.background="#CCC";
			break;
		}
		case 1024 : {
			document.getElementById("CS12").style.background="#F60";
			document.getElementById("CS11").style.background="#CCC";
			document.getElementById("CS10").style.background="#F60";
			break;
		}
		default : {
			document.getElementById("CS12").style.background="#CCC";
			document.getElementById("CS11").style.background="#CCC";
			document.getElementById("CS10").style.background="#CCC";
			break;
		}
	}
}

/**
 * Replace all SI prefixes in a string to scientific (e-3, e3, e6, etc.).
 */
function replacePrefixes(val) {
	var tmp = val.replace(/ /, "");
	tmp = tmp.replace(/Y/, "e24");
	tmp = tmp.replace(/Z/, "e21");
	tmp = tmp.replace(/E/, "e18");
	tmp = tmp.replace(/P/, "e15");
	tmp = tmp.replace(/T/, "e12");
	tmp = tmp.replace(/G/, "e9");
	tmp = tmp.replace(/M/, "e6");
	tmp = tmp.replace(/k/, "e3");
	tmp = tmp.replace(/m/, "e-3");
	tmp = tmp.replace(/u/, "e-6");
	tmp = tmp.replace(/n/, "e-9");
	tmp = tmp.replace(/p/, "e-12");
	tmp = tmp.replace(/f/, "e-15");
	tmp = tmp.replace(/a/, "e-18");
	tmp = tmp.replace(/z/, "e-21");
	tmp = tmp.replace(/y/, "e-24");
	return tmp;
}

/**
 * Round a value to desired precision decimals and use SI prefixes.
 */
function roundWithPrefix(val, prec) {
	var tmp = val;
	var prefixes = new Array("e-24","e-21","e-18","e-15","e-12","e-9","e-6","e-3","","e3","e6","e9","e12","e15","e18","e21","e24");
	var index = 8;
	
	if(0 < tmp && tmp < 1) {
		while(tmp < 1) {
			tmp *= 1000;
			index--;
		}
	}
	else {
		while(tmp > 1000) {
			tmp /= 1000;
			index++;
		}
	}
	
	tmp = Math.round(tmp*Math.pow(10,prec))/Math.pow(10,prec);
	return tmp+prefixes[index];
}

