#include "hcs12dp256.h"
#include "basicLCD.h"

int speed = 22;			//arbitrary motor speed
int fanduty = 0;
int time = 0000;			//running time of the GMS
int oldRPS = 0;			//RPS of the last second
int olderRPS = 0;		//RPS of two seconds ago
int RPS = 0;			//RPS being calculated for the current second
int temperature = 00;
int tempDesired = 00;
//int iniTemp = 0;
int finished = 0;		//determines
int RTI_slower = 0;		//slow RTI handler occurence
int stop = 0;			//stop is 0 while the blind is not spinning
int delayCounter = 0;

void initHW(void) {
	DDRK = 0x0F;
	DDRM |= 0x88;
	DDRS |= 0x80;
	DDRP |= 0x6F;	   		  //P0-3 are outputs (rows)
	DDRH &= 0x0F;	   		  //H4-7 are inputs (columns)
	PTM = 0x80; //HEATER PN!!!!!
	SPI1CR1 = 0;
	Lcd2PP_Init();
	
	//RTI
    RTICTL = 0x7F; 			  	//set RTI scaling factor
    CRGFLG |= 0x80;			  	//clear RTI
	INTCR |= 0x40;
   	
	//stepper motor
	DDRT |= 0x6F;
	DDRP |= 0x20; 
	PTT = 0;
	PTP |= 0x20;
	
	//output compare
	TIOS |= 0x10;
	TSCR2 = 0x03;
	TSCR1 = 0x80;
	TIE |= 0x10;
	
	//PWM
	PWMPOL = 0x80;				//set polarity of channel 7 to high (low duty)
	PWMCLK &= 0x7F;				//set bit 7 to choose clock SB for channel 7
	PWMPRCLK = 0x77;			//set clock B prescale to /128
	PWMCAE &= 0xEF;				//set channel 7 PWM to left aligned mode
	PWMCTL &= 0xF3;				//PWM int wait and freeze modes;
	PWMPER7 = 100;				//set channel 7 period register to 100
	PWME = 0x90;				//enable PWM channel 7;
	PWMDTY7 = 0;
	PWMPER4 = 100; 				//Set period for PWM4
	PWMDTY4 = 0;
	//PA
	PAFLG |= 0x01;		//clear overflow interrupt
	PACTL = 0x51;		//enable PACA, event counter mode, active edge = rising
	
	
	//ATD
	//ATD0CTL2 = 0xC2;
	//ATD0CTL3 = 0x00;
	//ATD0CTL4 = 0x67;
	
	/*
	ATD0CTL2 = 0x83;
	ATD0CTL3 = 0x00;
	ATD0CTL4 = 0x67;
	*/
	
	
	ATD0CTL2 = 0xFA;
	ATD0CTL3 = 0x00;
	ATD0CTL4 = 0x60;
	//ATD0CTL5 = 0x86;
	
	asm("cli");				  //enable global interrupt
}

void initLCD(void) {
	int i;

	char *string1 = "GMS Time:";
	char *string2 = "T:  C P:   RPS";
	
	//print first line of LCD
	for(i = 0; i < strlen(string1); i++) {
		PTS |= 0x80;
		LCD_display(string1[i]);
		PTS &= 0x7F;
	}
	
	//next line
	LCD_instruction (0xC0 + 0x00);
	//print second line of LCD
	for(i = 0; i < strlen(string2); i++) {
		PTS |= 0x80;
		LCD_display(string2[i]);
		PTS &= 0x7F;
	}
}

void printTemperature(void) {
 	int i;
	char *digit;
	int temp = temperature;
	LCD_instruction(0xC0 + 0x02);
	for(i = 1; i >= 0; i--) {
		digit[i] = temp % 10 + 0x30;
		temp = temp /10;
	}
	for(i = 0; i < 2; i++) {
	 	PTS |= 0x80;
		LCD_display(digit[i]);
		PTS &= 0x7F;
	}
}

void printTime(void) {
 	int i;
	char *digit;
	int temp = time;
	LCD_instruction(0x80 + 0x09);
	for(i = 3; i >= 0; i--) {
		digit[i] = temp % 10 + 0x30;
		temp = temp /10;
	}
	for(i = 0; i < 4; i++) {
	 	PTS |= 0x80;
		LCD_display(digit[i]);
		PTS &= 0x7F;
	}
	LCD_display('s');
}

void printRPS(void) {
 	int i;
	char *digit;
	int temp = oldRPS;
	LCD_instruction(0xC0 + 0x08);
	for(i = 2; i >= 0; i--) {
		digit[i] = temp % 10 + 0x30;
		temp = temp /10;
	}
	for(i = 0; i < 3; i++) {
	 	PTS |= 0x80;
		LCD_display(digit[i]);
		PTS &= 0x7F;
	}
}

void LCDOFF(void) {
	int i;

	char *string1 = "Goodbye         ";
	char *string2 = "                ";

	LCD_instruction (0x80 + 0x00);
	//print first line of LCD
	for(i = 0; i < 16; i++) {
		PTS |= 0x80;
		LCD_display(string1[i]);
		PTS &= 0x7F;
	}
	
	//next line
	LCD_instruction (0xC0 + 0x00);
	//print second line of LCD
	for(i = 0; i < strlen(string2); i++) {
		PTS |= 0x80;
		LCD_display(string2[i]);
		PTS &= 0x7F;
	}
}

void delay10ms(void) {
	int i;
	for (i = 0; i < 0x0FFF; i++) {
	 	i++;
		i--;
	}
}

void rotateCW(void) {
    char i;
	{
    PTT |= 0x60;
	delay10ms();
	PTT &= 0xDF;
	delay10ms();
	PTT &= 0xBF;
	delay10ms();
	PTT |= 0x20;
	delay10ms();
	}
}

void rotateCCW(void) {
 	char i;
	{
    PTT |= 0x60;
	delay10ms();
	PTT &= 0xBF;
	delay10ms();
	PTT &= 0xDF;
	delay10ms();
	PTT |= 0x40;
	delay10ms();
	}
}

#pragma interrupt_handler RTIISR()
void RTIISR(void) {
	RTI_slower++;
	
	if(RTI_slower % 2 == 0) {
		ATD0CTL5 = 0x86; //trigger ATD conversion
	}
	if (RTI_slower == 4) {
		time++;
		olderRPS = oldRPS;
		oldRPS = RPS;
		RPS = 0;
		if (time == 10000) time = 0;
		RTI_slower = 0;
	}
	
	//acknowledge interrupt
	CRGFLG |= 0x80;
}

#pragma interrupt_handler TIMER_ISR()
void TIMER_ISR(void) {
	TC4 = TCNT + 50000;
 	if(++delayCounter == 100) {
  		stop = 0;
  		delayCounter = 0;
 	}
 	TFLG1 |= 0x10;
}

#pragma interrupt_handler PA_ISR()
void PA_ISR(void) {
	RPS ++;
	PAFLG |= 0x01;
}

#pragma interrupt_handler ATD_ISR()
void ATD_ISR(void) {
	temperature = ATD0DR6 & 0x03FF;
	temperature = temperature / 8 - 5;
	temperature = (temperature - 32) * 5 / 9;
	if(tempDesired == 0) {
		tempDesired = temperature + 2;
	}
	ATD0CTL2 |= 0x01;
}

void main(void) {
	int i;
	int col;
	
	initHW();
	initLCD();
	printTemperature();
	printTime();
	printRPS();
	
	CRGINT |= 0x80;			  	//enable RTI
	PWMDTY7 = speed;		  	//start motor
	
	while(finished == 0) {
		PTM |= 0x08;  			//latch enable for keypad
		PTT = 0;
		//CHECK F
		PTP = 0x08;			//set row to scan
		col = PTH & 0xF0;
		if(col == 0x40) {
			PORTK = 0x00;
			finished = 1;
			PWMDTY7 = 0;
			LCDOFF();
			break;
		}

		//CHECK 1 to increase pump speed
		PTP = 0x01;				//set row to scan
		col = PTH & 0xF0;
		if(col == 0x10) {
			//increase motor speed
			if (speed <= 40) {
				speed += 2;
				PWMDTY7 = speed;
			}
		}

		//CHECK 2 to decrease pump speed
		PTP = 0x01;				//set row to scan
		col = PTH & 0xF0;
		if(col == 0x20) {
		    //decrease motor speed
			if (speed >= 14) {
				speed -= 2;
				PWMDTY7 = speed;
			}
		}

		//CHECK 4 to raise blinds
		PTP = 0x02;				//set row to scan
		col = PTH & 0xF0;
		if(col == 0x10 && stop == 0) {
			//turn stepper motor CCW
			TC4 = TCNT;			//write current time to TC4
   			delayCounter = 0;
   			stop = 1;
		}
		if (stop == 1) {
			PTP |= 0x20;
			rotateCCW();
		}

		//CHECK 5 to lower blinds
		PTP = 0x02;				//set row to scan
		col = PTH & 0xF0;
		if(col == 0x20 && stop == 0) {
			//turn stepper motor CW
			delayCounter = 0;
   			TC4 = TCNT;
   			stop = 2;
  		}
  		if(stop == 2) {
			PTP |= 0x20;
   			rotateCW();
		}
		
		//update LCD
		printTemperature();
		printTime();
		//if there has been a significant change in the RPS, update the RPS to the display
		if (abs(oldRPS - olderRPS) > 2) {
			printRPS();
		}
		
		if(temperature > tempDesired) {
			//turn heater off and turn fan on
			PTM&=0x7F;
			fanduty = 50;
			PWMDTY4 = fanduty;
		}
		else if (temperature < tempDesired){
			//turn heater on and fan off
			PTM|=0x80;
			fanduty = 0;
			PWMDTY4 = fanduty;
		}
		PTM &= 0xF7;
	}
}