var dt = 20 ;
var numPoints = 280; // width of the graph
var yOffset = 200; // height of the graph
var xOffset = 0;
var currentPoint = 0;


function controller(Kp, Ki, Kd) {
	this.Kp = Kp;
	this.Ki = Ki;
	this.Kd = Kd;
	
	this.error_old = 0;
	this.error = 0;
	this.P = 0;
	this.I = 0;
	this.D = 0;
	this.output = 0;
	this.input = 0;
	
	this.iterate = function(dt) {
		this.error_old = this.error;
		this.error = this.input - this.output;
		this.P = this.Kp * this.error;
		this.I = this.I + this.Ki * this.error * dt;
		this.D = (this.Kd / dt) * (this.error - this.error_old);
		this.output = this.P + this.I + this.D;
	}
	
}

var c1;
var points =  new Array();
var prevValue=0;

function mainLoop() {
	if(currentPoint % 40 == 0) {
		c1.input = Math.floor(Math.random()*200);
	}
	c1.iterate(dt/1000);
	document.getElementById("field").innerHTML = "Input: " + c1.input.toFixed(3) + "<br />"+
					  "Kp="+c1.Kp.toFixed(3)+" Ki="+c1.Ki.toFixed(3)+" Kd="+c1.Kd.toFixed(3)+"<br />"+
					  "P="+c1.P.toFixed(3)+" I="+c1.I.toFixed(3)+" D="+c1.D.toFixed(3)+"<br />"+
					  "Output: "+c1.output.toFixed(3);
	
	points[currentPoint] = c1.output;
	thisPoint = document.getElementById("point"+currentPoint);
	if(c1.output < prevValue) {
		thisPoint.style.top = yOffset-prevValue+'px';
		thisPoint.style.height = prevValue - c1.output + 1 +'px';
	} else {
		thisPoint.style.top = yOffset-c1.output+'px';
		thisPoint.style.height = c1.output - prevValue + 1 +'px';
	}
	currentPoint++;
	if(currentPoint >= numPoints) currentPoint = 0;
	
	prevValue = c1.output;
}

function fillGraph() {
	var graph = document.getElementById("graph");
	for(i=0; i<numPoints; i++) {
		var p = document.createElement('div');
		p.className = "point"
		p.id = "point"+i;
		p.style.top = yOffset-points[i]+'px';
		p.style.left = xOffset+i+'px';
		graph.appendChild(p);
	}
}
var interval;

playing = true;
function toggle() {
	var stop = document.getElementById("stopButton");
	if(playing == true) {
		clearInterval(interval);
		stop.style.backgroundColor = '#009900';
		playing = false;
	} else {
		interval = setInterval("mainLoop()", dt/3);
		stop.style.backgroundColor = '#990000';
		playing = true;
	}
}
	
function init() {
	c1 = new controller(0.01, 15, 0.001);
	for(i=0; i<numPoints; i++)
		points[i]=0;
	document.getElementById("stopButton").onclick = toggle;
	fillGraph();
	interval = setInterval("mainLoop()", dt/3);
}

/* for Mozilla/Opera9 */
if (document.addEventListener) {
    document.addEventListener("DOMContentLoaded", init, false);
}

/* for Internet Explorer */
/*@cc_on @*/
/*@if (@_win32)
    document.write("<script id=__ie_onload defer src=javascript:void(0)><\/script>");
    var script = document.getElementById("__ie_onload");
    script.onreadystatechange = function() {
        if (this.readyState == "complete") {
            init(); // call the onload handler
        }
    };
/*@end @*/