/*************************************************************************** */
/* sg-generic-pic16F876A-skypic.c  Julio 2006                                */
/*---------------------------------------------------------------------------*/
/* Servidor Generico                                                         */
/* Servidor: sg-generic                                                      */
/* Implementado para la tarjeta Skypic a 20MHz                               */
/*---------------------------------------------------------------------------*/
/* Implementados los servicios de Identificacion, PING, LOAD y STORE         */
/* Inicialmente el led de la skypic esta encendido                           */
/*---------------------------------------------------------------------------*/
/*  Juan Gonzalez <juan@iearobotics.com>                                     */
/*---------------------------------------------------------------------------*/
/*  LICENCIA GPL                                                             */
/*****************************************************************************/

//-- Especificar el pic a emplear
#define __16f877
#include "pic16f877.h"


/*******************************/
/* DEFINICIONES                */
/*******************************/
#define LED 0x02     //-- Bit del puerto B donde se encuentra el LED

#include "sci.h"
#include "pic16f877.h"

/*----------------------------*/
/*   CONSTANTES DEL STARGATE  */
/*----------------------------*/

//-- Datos devueltos por el servicio de identificacion
#define IS  0x20  // IS. Identificacion del servidor
#define IM  0x30  // IM. Identificacion del microcontrolador (pic16F876A)
#define IPV 0x10  // IPV. Placa Skypic. Version 0.

//-- Identificadores de los servicios
#define SID   0x49 // Servicio de identificacion
#define SPING 0x50 // Servicio de PING (0x50)
#define SLD   0x4C // Servicio LOAD
#define SST   0x53 // Servicio STORE 

//-- Identificadores para la respuesta
#define RPING 0x4F // Respuesta al Servicio de PING (0x4F)
#define RSI   0x49 // RSI. Codigo de respuesta del servicio de identificacion        
#define RLD   0x4C // Codigo respuesta servicio LOAD
#define RST   0x53 // Codigo respuesta servicio STORE

/********************************************/
/* REGISTRO PARA DIRECCIONAMIENTO INDEXADO  */
/********************************************/
//-- Por razones que desconozco, si se utiliza el registro INDF tal y 
//-- y como esta definido en el fichero pic16f87X.h, el direccionaimento
//-- indirecto no funciona. Con la siguiente definicion no hay problemas
sfr  at INDF_ADDR INDF2;

/*-----------------------------*/
/* VARIABLES GLOBALES          */
/*-----------------------------*/
//-- Byte alto de la direccion de memoria donde hacer LOAD/STORE
unsigned char dirH; 
unsigned char valor;

/*********************************************************************/
/* Leer la direccion enviada y situarla en los registros adecuados   */
/* para poder hacer el direccionamienot indirecto                    */
/*********************************************************************/
void leer_dir()
{
  //-- El byte bajo se pone en el registro FSR
  FSR=sci_read();
  
  //-- Poner el bit menos significativo de dirH en el bit IRP del
  //-- registro de status, para indicar direccionamiento indirecto
  dirH=sci_read();
  IRP=dirH&0x01;
}


/**************************************************************************/
/* Servicio STORE: se almacena en la direccion indicada, el valor pasado  */
/**************************************************************************/
void store(void)
{
  //-- Leer la direccion
  leer_dir();
  
  //-- Realizar la escritura del valor pasado
  INDF2=sci_read();
  
  //-- Enviar la respuesta
  sci_write(RST);
}

/**************************************************************************/
/* Servicio LOAD: Se devuelve el valor que se encuentra en la direccion   */
/* indicada                                                               */
/**************************************************************************/
void load(void)
{
  //-- Leer la direccion
  leer_dir();
  
  //-- Leer el valor
  valor=INDF2;
  
  /* Devolver trama de respuesta con el valor leido */
 sci_write(RLD);
 sci_write(valor);
}


/*---------------------*/
/* PROGRAMA PRINCIPAL  */
/*---------------------*/
void main(void)
{
  unsigned char car;
  
  /*----------------------------*/
  /* Configurar el sistema      */
  /*----------------------------*/
  //-- Configurar el led de la skypic
  TRISB=~LED;
  
  //-- Activar LED de la Skypic
  PORTB=LED;
  
  /*-----------------------------*/
  /* Configurar el puerto serie  */
  /*-----------------------------*/
  sci_init();
  
  /*------------------*/
  /* Bucle principal  */
  /*------------------*/
  for (;;) {
    
    //-- Esperar a que se solicite un servicio
    car=sci_read();
    
    switch(car) {
      
      //-- Servicio de identificacion
      case SID: 
        sci_write(RSI);
        sci_write(IS);
        sci_write(IM);
        sci_write(IPV);
        break;
      
      //-- Servicio de PING
      case SPING: 
        sci_write(RPING);
        break;
      
      //-- Servicio de LOAD
      case SLD:
        load();
        break;
      
      //-- Servicio de STORE
      case SST:
        store();
        break;
    }
  }
}