#include<pic.h>
#include<math.h>
#include "Delay.c"
#include "lcd.c"
#include "uart.c" 
#include <string.h>
//configurazioni pin globali
#define dataAviable RA4
#define led RC3
#define verso RC1
#define stepPin RC2
#define serviceMode RC0
#define RL1 RC4
#define RL2 RC5
////////////////////////////

//variabili globali
int keyPressed=0;
int gap=0;//lo spostamento da eseguire
const double kI=2.0;//costante della corona-ingranaggio
const char pause=255;//pausa per i delay ciclo macchina
unsigned long totalStep;//il numero di passi totali
unsigned long acceleration=0; //i passi fatti per l'accelerazione
unsigned int indexStep=0;
unsigned int tmr1Value=30000;
unsigned char adj=0;
unsigned char hft=0;
unsigned char togle=0;
	char readChar;
	char rIndex=0;
	char line[25];
	char nl[2]={'\r','\n'};
///////////////////

/**
*Funzione di pausa piu precisa di Delay, realizzata con il timer
*value indica il valore con cui caricare il timer.
*/
void myAccTimer(unsigned int value){
	acceleration--;//decremento l'indice del while;
	TMR1H=value>>8;
	TMR1L=value&0xFF;
	TMR1ON=1;
	while(!TMR1IF);
	TMR1IF=0;
	TMR1ON=0;
}
/**
*Esegue un accelerazione per una lungezza pari a *percents* passi totali
*/
void fixedMovements(int versus){
	verso=versus;
	stepPin=!stepPin;
	TMR1H=0xFF;
	TMR1L=hft;//imposto il valore letto dalla eeprom all'accensione
	TMR1ON=1;
	while(!TMR1IF);
	TMR1IF=0;
	TMR1ON=0;
	
}
	
void accellera(int percents){
		acceleration=(totalStep/100)*percents;

		tmr1Value=60000; //reimposto il valore per permettere di accelerare di nuovo
		/////////////////////////
		while(acceleration>0){
			stepPin=!stepPin;
			
				if(tmr1Value+1200<63000){
					myAccTimer(tmr1Value+=1200);
				}
				else
					myAccTimer(65535);
				}
		}
/**
* Muove il motore nel senso indicato da versus
*/
void move(char versus){
	verso=versus; //imposto il verso di rotazione 1 avanti, 0 indietro;
	
	accellera(100);
}
/**
*Stampa la misura value sul display dopo la scritta 'corsa'
*/
void printOnDisplay(int value){
			LCD_GOTO(1,8);
			LCD_PUTUN(value);
			LCD_PUTS(" mm");
			led=0;
			DelayMs(20);
}
/**
*calcola i passi totali da fare e li memorizza in totalStep(var.glob)
*/
void calcTotalStep(){
	totalStep=(long)(gap/kI)*1600;
	totalStep+=adj;
}
/**
*legge il valore premuto sulla tastiera, se non ่ premuto nessun tasto 
*restituisce il valore 22;
*/
int readKeypad(){
	return (dataAviable==1?PORTA & 0x0F:22);
}
/**
*calcola la potenza base-esponente
*/
int myPow(int base,int exp){
	return (int)pow(base,exp);
}
/**
* legge la cifra (max 3 cifre) dal tastierino numerico
*/
int getGap(){

	int cifre=2; //numero di cifre da inserire
	int readValue=0; //il numero letto dal keypad
	int gapValue=0;

	while(cifre>=0){
		led=1;
		DelayMs(20);
		readValue=readKeypad();
		DelayMs(20);
		led=0;
		switch(readValue){
			case 0:
					led=1;
					gapValue+=1*myPow(10,cifre);
					printOnDisplay(gapValue);
					cifre--;
					DelayMs(20);
					led=0;
					break;
			case 1:
					led=1;
					gapValue+=2*myPow(10,cifre);
					printOnDisplay(gapValue);
					cifre--;
					DelayMs(20);
					led=0;
					break;
			case 2:
					led=1;
					gapValue+=3*myPow(10,cifre);
					printOnDisplay(gapValue);
					cifre--;
					DelayMs(20);
					led=0;
					break;
			case 4:
					led=1;
					gapValue+=4*myPow(10,cifre);
					printOnDisplay(gapValue);
					cifre--;
					DelayMs(20);
					led=0;
					break;
			case 5:
					led=1;
					gapValue+=5*myPow(10,cifre);
					printOnDisplay(gapValue);
					cifre--;
					DelayMs(20);
					led=0;
					break;
			case 6:
					led=1;
					gapValue+=6*myPow(10,cifre);
					printOnDisplay(gapValue);
					cifre--;
					DelayMs(20);
					led=0;
					break;
			case 8:
					led=1;
					gapValue+=7*myPow(10,cifre);
					printOnDisplay(gapValue);
					cifre--;
					DelayMs(20);
					led=0;
					break;
			case 9:
					led=1;
					gapValue+=8*myPow(10,cifre);
					printOnDisplay(gapValue);
					cifre--;
					DelayMs(20);
					led=0;
					break;
			case 10:
					led=1;
					gapValue+=9*myPow(10,cifre);
					printOnDisplay(gapValue);
					cifre--;
					DelayMs(20);
					led=0;
					break;

			case 13:
					led=1;
					gapValue+=0;
					printOnDisplay(gapValue);
					cifre--;
					DelayMs(20);
					led=0;
					break;

			default:
					break;
					
		}
 	}
return gapValue;
}
void intToStr(char n){
	unsigned char unit,dec,cent;
	cent=(n/100) % 10;                       // Numero de Cientos
	dec=(n/10) % 10;                       // Numero de Decenas
	unit=n % 10;                           // numero de Unidades
	if (cent==0)   UartPutch(' ');                 // Elimina el primer cero 
	else        UartPutch(48+cent);                // Imprime al LCD Millares  (48 is the ASCII offset) 
	UartPutch(48+dec);                           // Imprime al LCD Cientos
	UartPutch(48+unit);                          // Imprime al LCD Decenas  
}

int findNumber(char caller){

	char len=(rIndex-1)-caller;
	if(len==1){
		return ((line[caller])-48);
	}else 	if(len==2){
		return ((line[caller]-48)*10+line[caller+1]-48);
		
	}else	if(len==3){
		return ((line[caller]-48)*100 + (line[caller+1]-48)*10+(line[caller+2]-48));
	}
return -1;
}
void SerialMenu(){
	UartPuts("admin@strafante$>");
	while(strncmp(line,"exit",4)!=0){
		while(readChar!=0x0D){
		readChar=UartGetch();
		UartPutch(readChar);
		line[rIndex++]=readChar;
		}
		if(strncmp(line,"write adj ",10)==0){
			eeprom_write(0x00,findNumber(10));
		}
		if(strncmp(line,"write hft ",10)==0){
		    eeprom_write(0x01,findNumber(10));	
		}
		if(strncmp(line,"read adj",8)==0){
			UartPuts(nl);
			UartPuts("adj value:[");
			intToStr(eeprom_read(0x00));
			UartPuts(" ]");
		}
		if(strncmp(line,"read hft",8)==0){
			UartPuts(nl);
			UartPuts("hft value:[");
			intToStr(eeprom_read(0x01));
			UartPuts(" ]");
		}
		rIndex=0;
		readChar=' ';
		UartPuts(nl);
		UartPuts("admin@strafante$>");
	
	}
	UartPuts(nl);
	UartPuts("Exited, please reboot pic");
	line[0]='a';

}
void main()
{

	TRISA=0xFF; //porte -a in input
	PORTA=0; //azzero i valori di port-a
	ADCON0=0b00000000;//disabilito il modulo ad
	ADCON1=0b00000110;//tutte porta in digitale
	TRISB=0; //porte -b in output
	PORTB=0; //azzero i valori di port -b

	PORTC=0;
	TRISC=0x81;

	//imposto il timer
	T1CKPS0=1;
	T1CKPS1=1;
	TMR1CS=0;
	//--

	
	DelayMs(100);
	LCD_INIT();
	DelayMs(100);
	LCD_CLEAR();
	DelayMs(100);
	LCD_CMD(LCD_line1);	
	DelayMs(100);
	//////////FECDBA9876543210
	LCD_PUTS("RHM-1 for C.A.M.");
	LCD_CMD(LCD_line2);
	LCD_PUTS("  By D.Dal Fra ");
	DelayMs(250);
	LCD_CLEAR();
	DelayMs(100);
	LCD_CMD(LCD_line1);
	LCD_PUTS("Corsa: ");
	UartInit(4, 9600, UART_CFG_BITSTOP_1); 
	UartPuts("--Serial init complete--");
//	DelayMs(250);

	//carico i valori che ho in eeprom
	adj=eeprom_read(0x00);
	hft=eeprom_read(0x01);
	
	while(1)
	{
		keyPressed=readKeypad(); //leggo il valore dal keypad;

		if(keyPressed==12){
			LCD_CLEAR();
			LCD_CMD(LCD_line1);
			LCD_PUTS("Corsa: ");
			gap=getGap();;
			calcTotalStep();
			LCD_CMD(LCD_line2);
			DelayMs(40);
			//////////FEDCBA9876543210
			LCD_PUTS(" ENTER TO START");		
		}
		if(keyPressed==3){//premuto enter, inizio ciclo lavoro
				//test rel่
			   /*RL1=1;
				DelayMs(50);
				RL1=0;	
				DelayMs(50);
				RL2=1;
				DelayMs(50);
				RL2=0;
				*/
				RL1=1; //chiudo rel่ slitta

				//pausa di due secondi tra chiusura e apertura slitta morsa

			//	DelayMs(pause);
			//	DelayMs(pause);
				DelayMs(pause);
				DelayMs(pause);
				/////////////////////////////////////////////

				RL2=0;//apro rel่ morsa

				//pausa di un 0.5s prima di far partire il motore
				DelayMs(pause);
				DelayMs(pause);
				//////////////////////////////////////////////////////
				
				//faccio partire il motore
				led=1;
				move(0); // vado avanti
				led=0;
				//Breve pausa prima della chiusura della morsa
				DelayMs(pause);				
				led=1;
				RL2=1; //chiudo rel่ morsa
				
				//attesa
				DelayMs(pause);
				led=0;	

				
				DelayMs(pause);
				DelayMs(pause);
				led=1;
				RL1=0;//apro rel่ slitta
				DelayMs(pause);
				DelayMs(pause);
				led=0;
				//ritorno in posizione home
				led=1;
				move(1);
				DelayMs(pause);
				//DelayMs(pause);
				led=0;
				RL1=1;
				RL2=1;
		}
		if(keyPressed==14){//movimenti by frecce (sistemare hft come timing motore non come delay per tasto!)
		 /*		togle++;
				while(togle<2){
				fixedMovements(0);
	
				if(readKeypad()==14){DelayMs(90);togle++;}
				}
			togle=0;
		*/
			DelayMs(10);
			while(keyPressed==14){
				fixedMovements(0);
				keyPressed=readKeypad();
			}
		}
		if(keyPressed==15){//movimenti by frecce
		/*		togle++;
				while(togle<2){
				fixedMovements(1);
	
				if(readKeypad()==15){DelayMs(90);togle++;}
				}
			togle=0;
		*/
			DelayMs(10);
			while(keyPressed==15){
				fixedMovements(1);
				keyPressed=readKeypad();
			}
		}
		if(serviceMode==0){
	
			led=1;
			SerialMenu();
			DelayMs(250);
			led=0;
			
		}
	}
}
