
/**************** Preprocessor Constants ***************************************/
#define CONFIG             0x20
#define EN_AA              0x21
#define EN_RXADDR          0x22
#define SETUP_AW           0x23
#define SETUP_RETR         0x24
#define RF_CH              0x25
#define RF_SETUP           0x26
#define STATUS             0x27
#define RX_ADDR_P0         0x2A
#define TX_ADDR            0x30
#define RX_PW_P0           0x31
#define RX_PW_P1           0x32
#define RX_PW_P2           0x33
#define FLUSH_TX           0xE1
#define FLUSH_RX           0xE2
#define TX_PAYLOAD         0xA0
#define RX_PAYLOAD         0x61
#define NO_OP              0xFF
#define ZERO               0x00
#define EOT                0x04
#define PAYLOAD_SIZE       0x20

//*****************
//*   VARIABLES   *
//*****************
#BYTE INTCON    =  0x0B

//Variables internas
//static int         INTCON=0x0B;
static int1        interRF;
static int16       noRF;
static int1        RCVNW=0;
static int8        DATA_N_SND=0;
static int8        DATA_N_RCV=0;
static int16       RF_CE,RF_CS,RF_IRQ;

//Variables configurables
static int8        RF_DATA[8];
static int8        RF_DIR;


//**************
//*   CÓDIGO   *
//**************

/**************** Write To NRF24L01 Configuration Register *********************/
void set_register(unsigned int command,unsigned int data)
{
   output_low(RF_CS);                                                          // Engage SPI chip select
   spi_write(command);                                                         // Write to register
   if(data!=NO_OP){spi_write(data);}                                           // Write data to register
   output_high(RF_CS);                                                         // Dis-engage SPI chip select
   delay_us(10);
}


//*****************************************************
//*               RF_CONFIG_PINES()                   *
//*****************************************************
//*****************************************************
void RF_CONFIG_PINES(int16 CE, int16 CS, int16 IRQ)
{
   RF_CE=CE;
   RF_CS=CS;
   RF_IRQ=IRQ;
}


//*****************************************************


//*****************************************************
//* RF_CONFIG(int canal,int dir,boolean Mbps,int dBm) *
//*****************************************************
//*Descripción:Esta función se encarga de configurar  *
//*el transceptor habilitando su propia dirección de  *
//*escucha y el canal entre otros parámetros.         *
//*****************************************************
//*Variables de entrada:- Canal                       *
//*                     - Direccion                   *
//*                     - Velocidad de transmisión    *
//*                     - Potencia                    *
//*Variables de salida:                               *
//*****************************************************

void RF_CONFIG(int canal, int dir, unsigned boolean Mbps, unsigned int dBm)
{
   output_low(RF_CE);

   // TX_ADDR (0xFF)
   //Configuración de la dirección de envio aleatoria.
   //En la función de enviar se configura la direccion
   //deseada por el usuario.
   output_low(RF_CS);
   spi_write(0x30);
   spi_write(0xFF);
   spi_write(0xC2);
   spi_write(0xC2);
   spi_write(0xC2);
   spi_write(0xC2);
   output_high(RF_CS);
   
   // RX_ADDR_P0 (0xFF) ACK
   //Configuración de la direccióndel Pipe0 para la
   //recepción de ACK.
   output_low(RF_CS);
   spi_write(0x2A);
   spi_write(0xFF);
   spi_write(0xC2);
   spi_write(0xC2);
   spi_write(0xC2);
   spi_write(0xC2);
   output_high(RF_CS);
   
   // RX_ADDR_P1 (dir)
   //Configuración de la direccióndel Pipe1 para la
   //recepción de tramas.
   output_low(RF_CS);
   spi_write(0x2B);
   spi_write(dir);
   spi_write(0xC2);
   spi_write(0xC2);
   spi_write(0xC2);
   spi_write(0xC2);
   output_high(RF_CS);  
   
   // RX_ADDR_P2 (0x00) BROADCAST
   //Configuración de la direccióndel Pipe2 para la
   //recepción de tramas
   set_register(0x2C,0x00);
   
   // EN_AA
   //Habilitar AutoAck en los Pipe0,Pipe1 y Pipe2.
   set_register(EN_AA,0x07);
   
   // EN_RXADDR
   //Habilitar los Pipe0,Pipe1 y Pipe2.
   set_register(EN_RXADDR,0x07);

   // SETUP_AW
   //Configuración de la longitud de las direcciones.
   //Direcciones de 5 bytes.
   set_register(SETUP_AW,0x03);

   //SETUP_RETR
   //Configuración de las retrasmisiones en la transmisión.
   //Diez retransmisiones cada 336us.
   set_register(SETUP_RETR,0x0A);

   //RF_CH
   //Configuración del canal.
   //Canal elegido por el usuario (0x01 - 0x7F).
   set_register(RF_CH,canal);

   //RF_SETUP
   //Configuración aspectos RF.
   //Ganancia máxima de LNA, 0dBm potencia de salida y 1Mbps de velocidad.
//   set_register(RF_SETUP,0x07);
   set_register(RF_SETUP,(Mbps<<3)|(dBm<<1)|0x01);                              // Setea velocidad y nivel de potencia. Velocidad puede ser 250kbs(0), 1mbps(1) o 2mbps(2). Potencia puede ser 0dbm(3, el más potente), -6dbm(2), -12dbm(1), -18dbm(0)   

   //STATUS
   //Reseteo del registro STATUS
   set_register(STATUS,0x70);

   //RX_PW_P0
   //Nº de bytes en Pipe0.
   //1 byte (ACK).
   set_register(RX_PW_P0,0x01);

   //RX_PW_P1
   //Nº de bytes en Pipe1.
   //10 byte (Direccion emisor y trama).
   set_register(RX_PW_P1,0x0A);

   //RX_PW_P2
   //Nº de bytes en Pipe2.
   //10 byte (Direccion emisor y trama).
   set_register(RX_PW_P2,0x0A);
}   
//*****************************************************


//*****************************************************
//*                    RF_ON()                         *
//*****************************************************
//*Descripción:Esta rutina activa el módulo de        *
//*radiofrecuencia en modo escucha para poder recibir *
//*datos enviados a su dirección.                     *
//*****************************************************
//*Variables de entrada:                              *
//*Variables de salida:                               *
//*****************************************************
void RF_ON()
{

   output_low(RF_CE);

   // CONFIG
   //Se activa el modulo, se pone en recepción,
   //se activa el CRC para que utilice 2 bytes.
   set_register(CONFIG,0x0F);

   delay_ms(2);
   output_high(RF_CE);
   delay_us(150);
}
//*****************************************************


//*****************************************************
//*                 RF_OFF()                         *
//*****************************************************
//*Descripción:Este procedimiento desactiva el módulo *
//*de radiofrecuencia.                                *
//*****************************************************
//*Variables de entrada:                              *
//*Variables de salida:                               *
//*****************************************************
void RF_OFF()
{
   output_low(RF_CE);

   // CONFIG
   //Se desactiva el modulo
   set_register(CONFIG,0x0C);
}
//*****************************************************


//*****************************************************
//*                 RF_SEND()                         *
//*****************************************************
//*Descripción:Esta función envía 8 Bytes de datos a  *
//*la dirección indicada informando de la correcta    *
//*recepción en el destinatario.                      *
//*****************************************************
//*Variables de entrada:- RF_DATA[]                   *
//*                     - RF_DIR
//*Variables de salida: -                             *
//*Salida:              - 0: Envío correcto (ACK OK)  *
//*                     - 1: No recepcibido (NO ACK)  *
//*                     - 2: No enviado               *
//*****************************************************
int RF_SEND()
{
   int i;
   int estado;


   if(bit_test(INTCON,7))
      interRF=1;
   else
      interRF=0;

//   disable_interrupts(GLOBAL);                                               //Deshabilitar las interrupciones arruina el funcionamiento del control de riego

   // INICIO
   output_low(RF_CE);

   //STATUS
   //Reseteo del registro STATUS
   set_register(STATUS,0x70);

   // EN_RXADDR
   //Se habilita el Pipe0 para la recepción del ACK
   set_register(EN_RXADDR,0x01);

   // TX_ADDR
   //Se configura la dirección de transmisión=RF_DIR
   output_low(RF_CS);
   spi_write(0x30);
   spi_write(RF_DIR);
   spi_write(0xC2);
   spi_write(0xC2);
   spi_write(0xC2);
   spi_write(0xC2);
   output_high(RF_CS);

   // RX_ADDR_P0
   //Para la recepción del ACK se debe configurar el Pipe0 con
   //la misma dirección a trasmitir.
   output_low(RF_CS);
   spi_write(0x2A);
   spi_write(RF_DIR);
   spi_write(0xC2);
   spi_write(0xC2);
   spi_write(0xC2);
   spi_write(0xC2);
   output_high(RF_CS);

   // RX_ADDR_P1
   //Se mete en RF_DIR la direccion propia.
   //De esta manera el receptor sabe la dirección
   //del transmisor.
   output_low(RF_CS);
   spi_write(0x0B);
   RF_DIR=spi_read(0);
   spi_read(0);
   spi_read(0);
   spi_read(0);
   spi_read(0);
   output_high(RF_CS);
   
   // W_TX_PAYLOAD
   //Se manda los datos al transductor
   output_low(RF_CS);
   spi_write(0xA0);

   DATA_N_SND++;
   spi_write(DATA_N_SND);
   spi_write(RF_DIR);
   for (i=0;i<8;i++)
      spi_write(RF_DATA[i]);

   output_high(RF_CS);

   // CONFIG
   //Se pasa a modo transmisión.
   set_register(CONFIG,0x0E);

   // Pulso de comienzo de envío
   output_high(RF_CE);
   delay_us(15);
   output_low(RF_CE);

   noRF=0;

   while (input(RF_IRQ)==1) {
      noRF++;
      //Si no da respuesta en 7ms, no se ha enviado.
      if(noRF==500){
      break;
         }
   }


   // STATUS
   //Lectura del estado en el registro estatus.
   output_low(RF_CS);
   estado=spi_read(0x27);
   spi_write(0x70);
   output_high(RF_CS);


   // EN_RXADDR
   //Habilitar los Pipe0,Pipe1 y Pipe2.
   set_register(EN_RXADDR,0x07);

      // TX_FLUSH
   //Limpieza de la FIFO de salida
   output_low(RF_CS);
   spi_write(0xE1);
   output_high(RF_CS);

   // CONFIG
   //Paso a modo recepción
   set_register(CONFIG,0x0F);

   // FIN
   output_high(RF_CE);

   delay_us(150);

   //Si no da respuesta en 7ms, no se ha enviado.
   if(noRF==500){
        if(interRF==1)
        enable_interrupts(GLOBAL);
        clear_interrupt(int_ext);
        return(2);
   }

   //estado
   //Chequeo de los bit del registro STATUS que indican si se ha recibido
   //ACK y si se ha terminado las retrasmisiones sin ningun ACK.
   if ((bit_test(estado,4)==0) && (bit_test(estado,5)==1)){
      if(interRF==1)
      enable_interrupts(GLOBAL);
      clear_interrupt(int_ext);
      return(0);
      }
   else{
      if(interRF==1)
      enable_interrupts(GLOBAL);
      clear_interrupt(int_ext);
      return(1);
      }     
}
//*****************************************************


//*****************************************************
//*                 RF_RECEIVE()                      *
//*****************************************************
//*Descripción: Esta rutina se encarga de comprobar si*
//*se ha producido una recepción y de ser así,        *
//*devuelve la trama recibida.                        *
//*****************************************************
//*Variables de entrada:-                             *
//*Variables de salida: - RF_DATA[]                   *
//*                     - RF_DIR                      *
//*Salida:         - 0: Recepción correcta y única    *
//*                - 1: Recepción correcta y múltiple *
//*                - 2: No se ha producido recepción  *
//*                - 3: No se ha producido recepción  *
//*****************************************************
int RF_RECEIVE()
{

   int i;
   int mas;
   int estado;

   if (input(RF_IRQ)==1 && RCVNW==0){
      return (2);
      }

   //STATUS
   //Lectura y reseteo del registro STATUS
   output_low(RF_CS);
   estado=spi_read(0x27);
   spi_write(0x70);
   output_high(RF_CS);

   //estado
   //Chequeo de la interrupción de recepción.
   if (bit_test(estado,6)==0 && RCVNW==0){
      return(3);
      }

   //R_RX_PAYLOAD
   //Lectura de los datos recibidos.
   output_low(RF_CS);
   spi_write(0x61);
   DATA_N_RCV=spi_read(0);
   RF_DIR=spi_read(0);
   for (i=0;i<8;i++)
   {
      RF_DATA[i]=spi_read(0);
   }
   output_high(RF_CS);

   //FIFO_STATUS
   //Comprobación del estado de la FIFO de
   //recepción para comprobar si hay más datos
   output_low(RF_CS);
   spi_write(0x17);
   mas=spi_read(0);
   output_high(RF_CS);

   if (bit_test(mas,0)==0){
      RCVNW=1;
      return(1);
   }
      RCVNW=0;
      return(0);
}
//*****************************************************
