#include <12F683.h>
#device adc=10

#FUSES NOWDT,NOMCLR,PUT,INTRC_IO

#use delay(clock=4000000)
#use standard_io(a)

#include <math.h>

//--- Constantes ---
#define SERVO        PIN_A1   //linea de control por PWM para el servo
#define ADC_POT      0        //canal adc que se usa para el potenciometro
#define ANTIREBOTE   0        //antirebote del POT (0 = desactivado / 255 = maximo)
//------------------

//--- Variables ---
int1 flagLeerADC = FALSE;        //indica si se tiene que leer el adc
int1 flagPulsoAlto = FALSE;      //indica si esta el pulso en alto
int8 AnteriorADC;                //Lectura anterior del ADC
int16 DuracionPulsoAlto = 64035; //valor que toma el timer1 durante el pulso alto
int16 DuracionPulsoBajo = 47035; //valor que toma el timer1 durante el pulso bajo
//-----------------

//--- Funciones ---
void Calcular_Posicion(void);
//-----------------

// --- Timer 1 ---
#int_TIMER1 //timer control de servo
void TIMER1_isr(void) {
//Timer de 16 bits --> 65536 = 1 RTCC
//Pescaler de 1:1
//1 tick cada 1 uS

   if(flagPulsoAlto == TRUE){ //el pulso esta alto
      set_TIMER1(DuracionPulsoBajo);   //tiempo que durara el timer en "bajo"
      output_low(SERVO);
      flagPulsoAlto = FALSE;
      flagLeerADC = TRUE;
   }
   else{ //el pulso esta bajo
      set_TIMER1(DuracionPulsoAlto);   //tiempo que durara el timer en "alto"
      output_high(SERVO);
      flagPulsoAlto = TRUE;
   }
}
// ---------------

void main(void) {

   setup_adc_ports(sAN0|VSS_VDD);
   setup_adc(ADC_CLOCK_INTERNAL);
   setup_timer_0(RTCC_INTERNAL);
   setup_timer_1(T1_INTERNAL);
   setup_timer_2(T2_DISABLED,0,1);
   setup_comparator(NC_NC);
   setup_vref(FALSE);
   enable_interrupts(INT_TIMER1);
   enable_interrupts(GLOBAL);
   setup_oscillator(OSC_4MHZ);   //4Mhz Internos
   set_adc_channel(ADC_POT);
   
   set_TIMER1(DuracionPulsoAlto);
   output_high(SERVO);
   flagPulsoAlto = TRUE;

	do {
      //--- Calcula posicion servo segun lectura adc ---
      if(flagLeerADC == TRUE){
         flagLeerADC = FALSE;
         Calcular_Posicion();
      }
      //------------------------------------------------
	} while(true);
}

void Calcular_Posicion(void){
   int8 Diferencia;
   int16 ValorADC;
   int16 PosicionServo;

   ValorADC = read_adc();  //lee ADC

   //calcula la diferencia (en valor absoluto) entre el valor anterior y
   //el actual del adc, si es mayor a ANTIREBOTE, cambia la posicion del
   //servo. No utilice la funcion "ABS()" porque no me daba el resultado esperado
   if(ValorADC > AnteriorADC)
      Diferencia = ValorADC - AnteriorADC;
   else{
      if(AnteriorADC > ValorADC)
         Diferencia = AnteriorADC - ValorADC;
      else
         Diferencia = 0;
   }

   if(Diferencia > ANTIREBOTE){
      //PosicionServo = 500 + floor(ValorADC * 7.8125);    //8bit ADC
      PosicionServo = 500 + floor(ValorADC * 1.953125);  //10bit ADC
      AnteriorADC = ValorADC;
      
      DuracionPulsoAlto = 65535 - PosicionServo;
      DuracionPulsoBajo = 45535 + PosicionServo;
   }
}
