/*
   nRF905 SLAVE Program
   Implemented on a 16F88 with 868MHz tranceiver

   4x4 IO for annunciation and manual functions
   4 output leds  4 input pushbuttons
   UNIT ID = 1
   
   (c)2010 Jannie Hamman
   All rights reserved
   
   V1.0  -  20/08/2014  -  Base program

*/

#include <16F88.h>
#device *=16
#device adc=8

#FUSES NOWDT                    //No Watch Dog Timer
#FUSES INTRC_IO                 //Internal RC Osc, no CLKOUT
#FUSES PUT                      //Power Up Timer
#FUSES NOMCLR                   //Master Clear pin used for I/O
#FUSES NOBROWNOUT               //No brownout reset
#FUSES NOLVP                    //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O
#FUSES NOCPD                    //No EE protection
#FUSES NOWRT                    //Program memory not write protected
#FUSES NODEBUG                  //No Debug mode for ICD
#FUSES NOPROTECT                //Code not protected from reading
#FUSES FCMEN                    //Fail-safe clock monitor enabled
#FUSES IESO                     //Internal External Switch Over mode enabled
#FUSES RESERVED                 //Used to set the reserved FUSE bits

#use delay(clock=8000000)

//nRF905 command set defines
#define WC  0x00        //Write config
#define RC  0x10        //Read config
#define WTP 0x20        //Write TX payload
#define RTP 0x21        //Read TX payload
#define WTA 0x22        //Write TX address
#define RTA 0x23        //Read TX address
#define RRP 0x24        //Read RX payload

//Port declarations
#define txen   pin_a2
#define trxce  pin_a3
#define pwrup  pin_a4
#define csn    pin_a1
#define clk    pin_a0
#define mosi   pin_a7
#define miso   pin_a6
#define dr     pin_a5

//Variables declaration
int inbyte,outbyte,nrf_temp[12];
int nrfbase0,nrfbase1,nrfbase2,nrfbase3;
int txpl[32],rxpl[32];
int unitid,txadr,rxadr;
int flag;
#bit error  =  flag.0
#bit rxto   =  flag.1
#bit inb    =  inbyte.0
#bit outb   =  outbyte.7

//Local IO defines
//Inputs
#define in1    pin_b7      //Open/close gate
#define in2    pin_b6      //Alarm home arm      
#define in3    pin_b5      //Alarm arm/disarm
#define in4    pin_b4      //All leds on/off

//Outputs
#define out1   pin_b0      //Day/night indication
#define out2   pin_b1      //Gate/garage doors open indication
#define out3   pin_b2      //Alarm status - armed
#define out4   pin_b3      //Electric fence status

//IO buffers
int ins,outs;
#bit inp1=ins.0
#bit inp2=ins.1
#bit inp3=ins.2
#bit inp4=ins.3
#bit q1=outs.0
#bit q2=outs.1
#bit q3=outs.2
#bit q4=outs.3

//Initialize
void nrf_init(){
   output_low(pwrup);
   output_high(csn);
   output_low(clk);
   output_low(trxce);
   output_low(txen);

   output_high(pwrup);
   delay_ms(5);
}

//Start comms
void nrf_strt(){
   output_low(csn);
   delay_us(5);
}

//Stop comms
void nrf_stop(){
   output_high(csn);
   delay_us(5);
}

//Write 8 bits out (Write byte)
void nrf_out(){
   int i;
   for(i=0;i<=7;i++){                //8 bits, bit7 first
      output_low(mosi);
      if(outb)output_high(mosi);    //if 1 make mosi 1
      delay_us(2);                    //delay to stabilize output
      outbyte=outbyte<<1;           //rotate left once
      output_high(clk);             //give clock pulse
      delay_us(2);
      output_low(clk);
      delay_us(2);
   }
   delay_us(5);
}

//Read 8 bits in (Read byte)
void nrf_in(){
   int i;
   for(i=0;i<=7;i++){               //8 bits to read, msb first
      inbyte=inbyte<<1;             //rotate inbyte left once
      inb=false;
      delay_us(1);
      output_high(clk);
      delay_us(2);
      if(input(miso))inb=true;
      output_low(clk);
      delay_us(2);
   }
   delay_us(5);
}

//Write config register
void wr_config(){
   nrf_strt();
   outbyte=WC;
   nrf_out();
   outbyte=0x6C;        //For 915MHz - see datasheet
   nrf_out();
   outbyte=0x0E;        //For 915MHz - see datasheet
   nrf_out();
   outbyte=0x44;        //RX/TX adr length set to 4 - normal IP type
   nrf_out();
   outbyte=0x20;        //RX payload of 32bytes
   nrf_out();
   outbyte=0x20;        //TX payload of 32bytes
   nrf_out();
   outbyte=nrfbase0;      //Next 4 bytes is RX (Unit) address in IP format
   nrf_out();
   outbyte=nrfbase1;
   nrf_out();
   outbyte=nrfbase2;
   nrf_out();
   outbyte=nrfbase3;
   nrf_out();
   outbyte=0xD8;        //Datasheet - set for xtal of 16MHz, no uCclk, crc16
   nrf_out();
   nrf_stop();
}

//Read the config register 
void rd_config(){
   int i;
   nrf_strt();
   outbyte=RC; nrf_out();
      for(i=0;i<10;i++){
         delay_us(2);
         nrf_in();
         nrf_temp[i]=inbyte;
   }
   nrf_stop();
}

//Write tx address
void nrf_wr_txadr(){
   nrf_strt();
   outbyte=WTA;
   nrf_out();
   outbyte=nrfbase0;
   nrf_out();
   outbyte=nrfbase1;
   nrf_out();
   outbyte=nrfbase2;
   nrf_out();
   outbyte=txadr;           //Master unit is 0
   nrf_out();
   nrf_stop();
}

//Write tx payload register
void nrf_wr_txpl(){
   int i;
   nrf_strt();
   outbyte=WTP;
   nrf_out();
   for(i=0;i<=31;i++){
      outbyte=txpl[i];
      nrf_out();
   }
   nrf_stop();
}

//Read the rx payload registers
void nrf_rd_rxpl(){
   int i;
   nrf_strt();
   outbyte=RRP;
   nrf_out();
   delay_us(2);
   for(i=0;i<=31;i++){
      nrf_in();
      rxpl[i]=inbyte;
   }
   nrf_stop();
}

//Clear the rx payload
void rxpl_clr(){
   int i;
   for (i=0;i<=31;i++){
      rxpl[i]=0;
   }
}

//Clear tx payload
void txpl_clr(){
   int i;
   for(i=0;i<=31;i++){
      txpl[i]=0;
   }
}

//Set system address and write to chip, init also
void nrf_setup(){
//Setup of nrf905 radio
   nrfbase0=0x12;         //Next 3 bytes with id forms IP adr
   nrfbase1=0xAB;         //Can be whatever!
   nrfbase2=0x79;         //This is aa.bb.cc.id
   nrfbase3=unitid;
   nrf_init();
   wr_config();
   txpl_clr();
   rxpl_clr();
}

//Transmit a 32 byte payload to the system, only 11 used in function
void nrf_tx(int adrto,int adrfrm,int cmd=0,int dta1=0,int dta2=0,int dta3=0,
      int dta4=0,int dta5=0,int dta6=0,int dta7=0,int dta8=0){
   txpl[0]=adrto;
   txpl[1]=adrfrm;
   txpl[2]=cmd;
   txpl[3]=dta1;
   txpl[4]=dta2;
   txpl[5]=dta3;
   txpl[6]=dta4;
   txpl[7]=dta5;
   txpl[8]=dta6;
   txpl[9]=dta7;
   txpl[10]=dta8;   
   nrf_wr_txpl();
   txadr=adrto;
   nrf_wr_txadr();   
   delay_ms(1);
   output_high(txen);   //Tx enable
   output_high(trxce);  //Shockburst enable
   delay_us(20);        //Pulse trxce min 10uS
   output_low(trxce);   //Finish tx and go to standby
   while(!input(dr));   //Wait till transmission is completed
}

//Listen and reply if talked to
void nrf_rx(){
      output_low(txen);          //Rx enable
      output_high(trxce);        //Shockburst enable
      delay_ms(1);               //Wait 1mS before checking
      if(input(dr)){             //Check if radio received package
         output_low(trxce);      //Go to standby mode
         rxpl_clr();             //Clear the payload
         nrf_rd_rxpl();          //Read data received
         rxadr=rxpl[1];          //Holds the sender's id           
         outs=rxpl[2];           //Update data as asked by sender
         nrf_tx(rxadr,unitid,outs,ins);   //Ack with data to sender                         
      }       
}

#int_RTCC
void  RTCC_isr(void) 
{
   if(input(in1))inp1=true;else inp1=false;
   if(input(in2))inp2=true;else inp2=false;
   if(input(in3))inp3=true;else inp3=false;
   if(input(in4))inp4=true;else inp4=false;
   if(q1)output_high(out1);else output_low(out1);
   if(q2)output_high(out2);else output_low(out2);
   if(q3)output_high(out3);else output_low(out3);
   if(q4)output_high(out4);else output_low(out4);   
}

//Main program
void main()
{
   setup_adc_ports(NO_ANALOGS|VSS_VDD);
   setup_adc(ADC_CLOCK_DIV_2);
   setup_spi(SPI_SS_DISABLED);
   setup_timer_0(RTCC_INTERNAL|RTCC_DIV_256|RTCC_8_bit);    //32.7 ms overflow
   setup_comparator(NC_NC_NC_NC);
   setup_vref(FALSE);
   enable_interrupts(INT_RTCC);
   ins=outs=0;
   enable_interrupts(GLOBAL);
   setup_oscillator(OSC_8MHZ|OSC_INTRC);

//Setup of nrf905 radio
   unitid=1;
   nrf_setup(); 

//Do slave processing 
   while(true){
   nrf_rx();
 
   }     //while
}        //main

