/*************************************************************************** */
/* servo8-int.c                                                              */
/*---------------------------------------------------------------------------*/
/* CONTROL DE SERVOS                                                         */
/*---------------------------------------------------------------------------*/
/* Ejemplo para la tarjeta SKYPIC                                            */
/*---------------------------------------------------------------------------*/
/* Ejemplo para posicionar hasta 8 servos                                    */
/* El posicionamiento se hace mediante INTERRUPCIONES                        */
/* Los servos 1 y 2 se llevan a sus posiciones extrenos alternativamente     */
/* El resto de servos permanecen en el centro                                */
/*---------------------------------------------------------------------------*/
/*  LICENCIA GPL                                                             */
/*****************************************************************************/

#include <pic16f876a.h>
#define ESTADO_ON  0
#define ESTADO_OFF 1

//-- Prescaler a 64
//-- Ventana temporal para el servo en ticks (2.5ms)
#define T           195

//-- Posiciones de los 8 servos
int pos[]={0,0,0,0,0,0,0,0};

//-- Mascara con la activacion de cada uno de los servos
unsigned char mask[]={0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80};
unsigned char estado=0;
unsigned char servo=0;
char Ton;

void isr() interrupt 0
{
  //-- En este estado se activa el pulso
  if (estado==ESTADO_ON) {

    //-- Calcular el ancho en funcion de los grados
    Ton = (78*pos[servo])/90 + 102;

    //-- Activar la senal del servo actual
    PORTB=mask[servo];

    //-- Dar valor inicial del timer
    TMR0=255-Ton;

    //-- Pasar al siguiente estado cuando llegue la interrupcion
    estado=ESTADO_OFF;
  }
  else {
    //-- Poner a cero todas las senales
    PORTB=0x00;

    //-- Esperar un tiempo Toff
    TMR0=255-T+Ton;

    //-- Pasar al siguiente servo
    servo=(servo + 1)%8;

    //-- Pasar al siguiente estado
    estado=ESTADO_ON;
  }

  //-- Flag de interrupcion a cero
  T0IF=0;
}

/**********************************************/
/* Funcion de pausa                           */
/* ENTRADA: unidades de tiempo para la pausa  */
/**********************************************/
void pausa(unsigned char tiempo)
{
  unsigned char i;
  unsigned int j;
  int temp=0;

  //-- Se realizan dos bucles anidados
  for (i=0; i<tiempo; i++) {
    for (j=0; j<0x8000; j++) {
      //-- Operacion inutil, para consumir tiempo
      temp=temp+1;
    }
  }
}

void main(void)
{
  //-- Puerto B de salida
  TRISB=0;

  //-- Configurar Timer 0
  //-- Modo temporizador
  T0CS=0; PSA=0;

  //-- Presscaler A 64
  PS2=1; PS1=0; PS0=1;

  //-- Activar interrupciones
  TMR0IE=1;
  GIE=1;

  while(1) {
    //-- Posicionar servos 1 y 2 en los extremos
    pos[0]=0;  pos[1]=-10;
	pos[2]=20; pos[3]=-30;
	pos[4]=40; pos[5]=-50;
	pos[6]=60; pos[7]=-70;
    pausa(14);

    //-- Posicionar servos 1 y 2 en los extremos contrarios
    pos[0]=-0;  pos[1]=10;
	pos[2]=-20; pos[3]=30;
	pos[4]=-40; pos[5]=50;
	pos[6]=-60; pos[7]=70;
    pausa(14); 
  } 

}
