//888888888888888888888888888888888888888888888888888888888888888888888888888888//
//888888888888888888888888888888888888888888888888888888888888888888888888888888//
//PROPOSITO:controlar la posición de un servo_motor FUTABA por puerto serial    //
//                                                                              //
//PARA : el Foro TODOPIC (06/2007)                                              //
//POR  : Giovanny. gioxe86@hotmail.com                                          //
//                                                                              //
//para 0°   enviar el valor 43 luego del motor_id (cual->201)                   //
//para 180° enviar el valor 150 luego del motor_id (cual->201)                  //
//así se tendrán un poco más de 100 posibles posiciones para el servo           //
//                                                                              //
//888888888888888888888888888888888888888888888888888888888888888888888888888888//
//                                                                              //
//888888888888888888888888888888888888888888888888888888888888888888888888888888//
#include <16f877.h>
#fuses XT,NOWDT,NOPROTECT,NOLVP,PUT,NOBROWNOUT,NODEBUG
#use delay(clock=4000000)
#use standard_io(b)
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7)

#define SERVO1  PIN_B0

//88888888888888888888888888888_VARIABLES GLOBALES_88888888888888888888888888888//
const int AJUSTE_FINO_DE_RTCC = 30;
const int ticks_PULSO_MEDIO = 96;
int1 flagRTCC = 0;
int contRTCC = 0;
int1 flagSERVO1 = 0;
int tSERVO1 = ticks_PULSO_MEDIO;
int valor, cual;
//888888888888888888888888888888888888888888888888888888888888888888888888888888//
#int_rda               //interrupcion de recepcion serie
void rda_isr()                //'dato recibido disponible'
{
   disable_interrupts(int_rda);
   cual=getc();
   if(cual==201)            //Si el primer valor recibido es 201
   {               //Espera por el siguiente valor
      do
      {
         valor=getc();
      }
      while(valor==cual);
      
      if(valor!=tSERVO1)
      {
         tSERVO1=valor;      //y guarda este valor en tServo1
      }            //para luego cargarlo a timer0
   }
   enable_interrupts(int_rda);
}
//888888888888888888888888888888888888888888888888888888888888888888888888888888//
#int_RTCC
void RTCC_isr()               //interrupcion Timer0
{
   ++contRTCC;
   if(contRTCC==4)            //en este momento han transcurrido 16.384ms
   {               //XTAL=4M && RTCC_DIV_16. Carga 30 al timer0
      set_TIMER0(AJUSTE_FINO_DE_RTCC);//para de esta forma hacer la interrupcion
   }               //despues 3.616ms, asi asegura los 20ms
     if(contRTCC==5)            //if 20msok
   {
      flagRTCC=1;         //activa la bandera
      contRTCC=0x00;         //reinicia la cuenta
   }
}
//888888888888888888888888888_PROGRAMA PRINCIPAL_8888888888888888888888888888888//

void main()
{
   int ValTIMER0;            //variable local
   setup_counters(RTCC_INTERNAL,RTCC_DIV_16);
   enable_interrupts(int_rda);      //activa interrupcion rda
   enable_interrupts(global);      //activa interrupciones globales
   set_TIMER0(0);            //carga el Timer0 con valor 0
   enable_interrupts(INT_RTCC);      //activa interrupcion Timer0
   while (1);            //loop
   {               // aqui disparas el pulso pwm (high)
      if(flagRTCC==1)
      {
         flagRTCC=0;
         output_high(SERVO1);
         flagSERVO1=1;
      }
                  //luego de estar en alto 
      if(flagSERVO1==1)      //controlas el ancho del pulso (low)
      {
         valTIMER0 = get_TIMER0();
         if(valTIMER0>tSERVO1)
         {
            flagSERVO1=0;
            output_low(SERVO1);
         }
      }
   }
}
