// Lab 4
// Prelab-Edited
// 9/27/04 
// BY: Jayme Cook, Jeff Schober, Justin Bjorum

#include <avr/io.h>
#include <avr/signal.h>
#include <avr/interrupt.h>
#include "sio_c.c"

#define P 4	// Changed From 1, 2, and 4
// -------------- Global Variables --------------------


int Ct;	       	// motor speed input
int Cd = 0;       	// setpoint



//-------------- IO Functions -----------------

void PWM_setup()
{
	DDRD = 0xFF; // Set PD7 as output
	TCCR2 = _BV(WGM21)|_BV(WGM20)|_BV(COM21)|_BV(CS20); // Fast PWM
	
	OCR2 = 0xFF; // 100% Duty cycle
}

void PWM_write(int var)
{
	OCR2 = var; // duty cycle
}

void AD_setup()
{
	ADMUX = 0xC0;   // set the input to channel 0
	ADCSRA = 0xE0;  // turn on ADC and set to free running
}


int AD_read()
{
	return ADCW>>2;
}

void IO_update()	// This routine will run once per interrupt for updates
{
	int Ce;		// System Error
	int Cc;    	// motor speed output. With the range of 0-255

	Ct = AD_read();
	Ce = Cd-Ct;
	Cc = P*Ce;

	if ( (0<=Cc) && (Cc<=255) )
	{ 
		Cc = Cc;
	}
	else
	{
		Cc = 0;
	}
	
	PWM_write(Cc);
}

// -------------- Clock/interrupt stuff ---------------------

#define CLK_ms 10 // set the updates for every 10 ms
unsigned int CNT_timer1; // the delay time

SIGNAL(SIG_OVERFLOW1)	// The interrupt calls this function
{	
	IO_update();
	TCNT1 = CNT_timer1;
}

void CLK_setup() // Start the interrupt service routine
{
	TCCR1A = (0<<COM1A1) | (0<<COM1A0)| (0<<COM1B1) | (0<<COM1B0)| (0<<WGM11) | (0<<WGM10) | (0<<FOC1A) | (0<<FOC1B);
	// disable PWM and Compare Output Modes
	TCCR1B = (0<<WGM12) | (0<<WGM13)| (0<<ICNC1) | (0<<ICES1)| (1<<CS12) | (0<<CS11) | (1<<CS10); // set to clk/1024
	CNT_timer1 = 0xFFFF - CLK_ms * 16; // 16 = 1ms, 160 = 10ms
	TCNT1 = CNT_timer1; // start at the right point
	// SFIOR &= PSR10; // reset the scaling bit
	// use CLK/1024 prescale value
	TIFR&=~(1<<TOV1); // set to use overflow interrupts
	TIMSK = (1<< TOIE1 );// enable TCNT1 overflow
	sei(); // enable interrupts flag
}

//------------ The main program loop ------------------

void IO_setup()
{
	
	DDRA = 0;  // all of port A are inputs

	// call other set up functions

	PWM_setup();
	AD_setup();
	CLK_setup();

}


int main()
{
	int c;
	sio_init();
	IO_setup();
	CLK_setup();


	for(;;){
		while((c = input()) == -1){} 		// wait for a keypress
		if(c == '+')			 	// increment the output on port B
		{	if(++Cd > 255) Cd = 255;
			outln("counter incremented");
		} 
		else if(c == '-')
		{	
			if(--Cd < 0) Cd = 0;
			outln("counter decremented");
		} 
		else if (c == 't')
		{
			outint(Ct);
		}
		else if(c == 'h')
		{
			outln("HELP: +, -, C,t,q");
		} 
		else if (c == 'd')
		{
			outint(Cd);
		}
		else if(c == 'q')
		{
			break;
		}
	}
	sio_cleanup();

	return 1;
}


