//************************************************************************//
//                                                                 
// PROYECTO COMUNICACION JOYSTICK PS2 WIRELESS CON PIC 16F877A
//            CODIGO ORIGINAL TRADUCIDO DEL PORTUGUES
//************************************************************************//
//Configuracion PIC
//************************************************************************//
#include <16F877A.h>
 
#FUSES NOWDT                                //Sin watch dog
#FUSES HS                                   //Cristal alta velocidad
#FUSES PUT                                  //Timer de alimentacion
#FUSES NOPROTECT                            //Código desprotegido
#FUSES NOBROWNOUT                           //Sin reset de brown out
#FUSES NOLVP                                //Programacion en alto voltaje
#FUSES NOCPD                                //Sin proteccion de memória eeprom
#FUSES NOWRT
 
#use delay(clock=20000000)                        // cristal de 20 Mhz
#use rs232(baud=9600,parity=N,xmit=PIN_A4,rcv=PIN_A5,bits=8)
 
//Definicion de los puertos
#byte porta = 0x05
#byte portb = 0x06
#byte portc = 0x07
#byte portd = 0x08
#byte porte = 0x09
 
//************************************************************************//
//CONTROL PLAYSTATION                                                      
//************************************************************************//
//Definicion de I/Os                                                            
//************************************************************************//
#define cmd           PIN_D6            
#define att           PIN_D4        
#define clk           PIN_D5     
#define data          PIN_D7     
 
#define LED_STATUS    PIN_E0             //Led indicador de status
 
#define start         PIN_A1
#define select        PIN_A0
#define servo_x_l     PIN_D0
#define servo_y_l     PIN_D1
#define servo_x_r     PIN_D2
#define servo_y_r     PIN_D3
#define up            PIN_B0
#define down          PIN_B1
#define der           PIN_B2
#define izq           PIN_B3
#define triangulo     PIN_B4
#define circulo       PIN_B5
#define cuadrado      PIN_B6
#define xis           PIN_B7
#define l1            PIN_C0
#define l2            PIN_C1
#define l3            PIN_C2
#define r1            PIN_C3
#define r2            PIN_C4
#define r3            PIN_C5
 
//************************************************************************//
//Definicion de parametros de comunicacion con un control PS2
//************************************************************************//
 
//Tiempos en micro-segundos (us)
#define tiempoInicio     20
#define tiempoClk        20
#define tiempoEntreByte  20
#define tiempoEntreCiclo 40 //ms 
 
//************************************************************************//
//VARIABLES GENERALES                                                          
//************************************************************************//
int psxData[6];      //Buffer de control
int psxDataAnt[6];   //Buffer de control
int ready=0;
int1 psxModo;
int1 error=0;
 
//Botones de Control
int1 bt_select = 0;
int1 bt_l3  = 0;
int1 bt_r3  = 0;
int1 bt_start = 0;
int1 bt_up  = 0;
int1 bt_down  = 0;
int1 bt_izq  = 0;
int1 bt_der = 0;
 
int1 bt_l1 = 0;
int1 bt_l2 = 0;
int1 bt_r1 = 0;
int1 bt_r2 = 0;
int1 bt_triangulo = 0;
int1 bt_circulo   = 0;
int1 bt_cuadrado  = 0;
int1 bt_xis = 0;
 
int X_Left=0;
int Y_Left=0;
int X_Right=0;
int Y_Right=0;
 
int psxCont;             //contador genérico
 
int1 estado;             //estado de led
 
//************************************************************************//
//CONSTRUCCIONES DE LAS FUNCIONES
//************************************************************************//
 
//************************************************************************//
//psxLeByte - Captura un byte, enviado para control através de pin DATA
//************************************************************************//
 
int psxLeByte()
{
   int aux=0;
   int c;
 
      for(c=0;c<=7;c++)           //Pasa por todos los bits de variable psxByte
   {
      output_bit(clk,false);      //baja el clock, para que el control
                                  //disponibilize el dato en pin "data"
      delay_us(tiempoClk);  
 
      if(INPUT(data)==1)
         bit_clear(aux, c);
      else
         bit_set(aux, c);
 
      output_bit(clk,true); //sube el clock
   }
 
   delay_us(tiempoEntreByte);
   return (aux);  
}
 
//************************************************************************//
//psxGrabaByte - Escribe un byte, enviado para control através de pin CMD
//************************************************************************//
 
void psxGrabaByte(int byteData)
{
   int c;
   for(c=0;c<=7;c++) //Pasa por todos los bits de variáble psxByte
   {
       //sube o baja el pin de acuerdo con cada bit de variáble psByte
       //significa que estamos enviando el comando 0x01h para el control
      if(bit_test(byteData,c))
         output_bit(cmd,true);
      else
         output_bit(cmd,false);        
 
      output_bit(clk,false);       //despues de setear el pin, manda clock 
                                   //       delay_us(tiempoClk);  
                                   //aguarda un tiempito...
      output_bit(clk,true);        //sube clock... NOTA: clock 
 }
 
   output_bit(cmd,true);           //sube comando para señalizar
   delay_us(tiempoEntreByte);       //espera un tiempo entre un byte y otro
}
 
//************************************************************************//
//psxCopiaData - copia buffer actual para anterior
//************************************************************************//
 
void psxCopiaData()
{
   int i;
   for(i=0;i<6;i++)
      psxDataAnt[i] = psxData[i];
}
 
//*************************************************************************//
//psxComparaData - Compara lectura anterior con la actual
//************************************************************************//
 
boolean psxComparaData()
{
   int j;
   for(j=0;j<6;j++)
   {
      if(psxDataAnt[j]!=psxData[j])
         return (1);
   }
   return (0);
}
 
//************************************************************************//
//psxAtualizaVariables - convierte buffer de lectura para variables discretas 
//************************************************************************//
 
void psxActualizaVariables()
{
   if((psxData[0] & 1) == 1)
      bt_select = 1;
   else
      bt_select = 0;
 
   if((psxData[0] & 2) == 2)
      bt_l3 = 1;
   else
      bt_l3 = 0;
 
   if((psxData[0] & 4) == 4)
      bt_r3 = 1;
   else
      bt_r3 = 0;
 
   if((psxData[0] & 8) == 8)
      bt_start = 1;
   else
      bt_start = 0;
 
   if((psxData[0] & 16) == 16)
      bt_up    = 1;
   else
      bt_up    = 0;
 
   if((psxData[0] & 32) == 32)
      bt_der = 1;
   else
      bt_der = 0;
 
   if((psxData[0] & 64) == 64)
      bt_down  = 1;
   else
      bt_down  = 0;
 
   if((psxData[0] & 128) == 128)
      bt_izq  = 1;
   else
      bt_izq  = 0;
 
   if((psxData[1] & 1) == 1)
      bt_l2 = 1;
   else
      bt_l2 = 0;
 
   if((psxData[1] & 2) == 2)
      bt_r2 = 1;
   else
      bt_r2 = 0;
 
   if((psxData[1] & 4) == 4)
      bt_l1 = 1;
   else
      bt_l1 = 0;
 
   if((psxData[1] & 8) == 8)
      bt_r1 = 1;
   else
      bt_r1 = 0;
 
   if((psxData[1] & 16) == 16)
      bt_triangulo = 1;
   else
      bt_triangulo = 0;
 
   if((psxData[1] & 32) == 32)
      bt_cuadrado  = 1;
   else
      bt_cuadrado  = 0;
 
   if((psxData[1] & 64) == 64)
      bt_xis= 1;
   else
      bt_xis= 0;
 
   if((psxData[1] & 128) == 128)
      bt_circulo = 1;
   else
      bt_circulo = 0;
 
   x_right = psxData[2];
   y_right = psxData[3];
   x_Left = psxData[4];
   y_Left = psxData[5];
}
 
//************************************************************************//
//psxLeControl - Ejecuta la lectura del control de playstation   
//************************************************************************//
 
void psxLeControl()
{
   int psxByte = 0;
 
   output_bit(cmd,true);    //up comando
   output_bit(clk,true);    //up clock
   output_bit(att,false);   //att en low - habilita el joystick
   delay_us(tiempoInicio);   //aguarda el control entender el att en low
 
   //Envia el primer byte para el control - 0x01
   psxByte = 1;        
   psxGrabaByte(psxByte);
 
   //Envia el segundo byte para el control - 0x42h
   psxByte = 66;
   psxGrabaByte(psxByte);
 
   //Envia el tercer byte para el control - 0x00
   psxByte = 0;
   psxGrabaByte(psxByte);
 
   //Recupera los 6 próximos bytes
      for(psxCont=0; psxCont<6; psxCont++)
         psxData[psxCont] = psxLeByte();
 
   //Vuelca el att para alto... libera el control indicando que este puede
   //parar de enviar datos
 
   output_bit(att,true);  
 
   //Compara con la variáble anterior y verifica si será
   //necesário actualizar las variables discretas
   if(psxComparaData()==1)
   {
      psxActualizaVariables();
      psxModo = true;
   }
   else
      psxModo = false;
 
   psxCopiaData();
 
}
 
//************************************************************************//
//atualizaSalidas - Atualiza el status de todas las saídas del PIC
//************************************************************************//
 
void actualizaSalidas()
{
   output_bit(start,bt_start);
   output_bit(select,bt_select);
   output_bit(up,bt_up);
   output_bit(down,bt_down);
   output_bit(der,bt_der);
   output_bit(izq,bt_izq);
   output_bit(triangulo,bt_triangulo);
   output_bit(circulo,bt_circulo);
   output_bit(cuadrado,bt_cuadrado);
   output_bit(xis,bt_xis);
   output_bit(l1,bt_l1);
   output_bit(l2,bt_l2);
   output_bit(l3,bt_l3);
   output_bit(r1,bt_r1);
   output_bit(r2,bt_r2);
   output_bit(r3,bt_r3);
}
 
//************************************************************************//
//PROGRAMA PRINCIPAL
//************************************************************************//
 
void main()
{
 
set_tris_a(0b00000100);
set_tris_b(0b00000000);
set_tris_c(0b00000000);
set_tris_d(0b00000001);
set_tris_e(0b00000000);
porta=0x00;
portb=0x00;
portc=0x00;
portd=0x00;
porte=0x00;
 
   while(1)
   {
         psxLeControl();
 
        delay_ms(20);
 
        estado=!estado;
        
        output_bit(LED_STATUS,estado);
 
        actualizaSalidas();
 
   } //Fin del programa principal
}//Fim del programa
 
//************************************************************************//

