#include <stdlib.h>

#ifndef RS485_DRIVER
#define RS485_DRIVER
/*
#ifndef RS485_ID
#define RS485_ID  0xff                 // The device's RS485 address or ID
#endif
*/
   #ifndef RS485_RX_PIN
   #define RS485_RX_PIN       PIN_C7   // Data receive pin
   #endif

   #ifndef RS485_TX_PIN
   #define RS485_TX_PIN       PIN_C6   // Data transmit pin
   #endif

   #ifndef RS485_ENABLE_PIN
   #define RS485_ENABLE_PIN   PIN_B4   // Controls DE pin.  RX low, TX high.
   #endif

   #ifndef RS485_RX_ENABLE
   #define RS485_RX_ENABLE    PIN_B5   // Controls RE pin.  Should keep low.
   #endif

  // #use rs232(baud=9600, xmit=RS485_TX_PIN, rcv=RS485_RX_PIN, enable=RS485_ENABLE_PIN, bits=9, long_data, errors, stream=RS485)
 //  #use rs232(baud=9600, xmit=RS485_TX_PIN, rcv=RS485_RX_PIN, enable=RS485_ENABLE_PIN, bits=9, long_data, force_sw, multi_master, errors, stream=RS485_CD)
#use rs232(baud=300, xmit=RS485_TX_PIN, rcv=RS485_RX_PIN, enable=RS485_ENABLE_PIN,bits=8,parity=n, errors, stream=RS485)
#use rs232(baud=300, xmit=RS485_TX_PIN, rcv=RS485_RX_PIN, enable=RS485_ENABLE_PIN,return=RS485_RX_ENABLE,multi_master, force_sw,parity=n, stream=RS485_CD,errors)

    //  #define RCV_OFF() {setup_uart(FALSE,RS485);setup_uart(TRUE,RS485_CD);}

#define RS485_wait_time 20             // Wait time in milliseconds

#bit    rs485_collision = rs232_errors.6

#ifndef RS485_RX_BUFFER_SIZE
#define RS485_RX_BUFFER_SIZE  32
#endif

int rs485_state, rs485_ni, rs485_no,newMessage;
int8 rcv_state;
//int rs485_buffer[RS485_RX_BUFFER_SIZE];
int8 rs485_InBuffer[6];

// Purpose:    Enable data reception
// Inputs:     None
// Outputs:    None
void RCV_ON(void) {
      while(kbhit(RS485)) {fgetc(RS485);} // Clear RX buffer. Clear RDA interrupt flag. Clear overrun error flag.
    //  while(kbhit(RS485_CD)) {fgetc(RS485_CD);} // Clear RX buffer. Clear RDA interrupt flag. Clear overrun error flag.
    
         setup_uart(UART_DATA);
         output_low(RS485_RX_ENABLE);
   		 output_low(RS485_ENABLE_PIN);
         setup_uart(TRUE);
    
  
}

void RCV_OFF(void) {
   output_high(RS485_RX_ENABLE);
   output_high(RS485_ENABLE_PIN);
   setup_uart(FALSE);
}


// Purpose:    Initialize RS485 communication. Call this before
//             using any other RS485 functions.
// Inputs:     None
// Outputs:    None
void rs485_init() {
   RCV_ON();
   rs485_state=0;
   rs485_ni=0;
   rs485_no=0;
   rcv_state=0;
   newMessage=FALSE;
   enable_interrupts(INT_RDA);
   enable_interrupts(GLOBAL);

}

// The index for the temporary receive buffer
int8 temp_ni;

// Purpose:    Add a byte of data to the temporary receive buffer
// Inputs:     The byte of data
// Outputs:    None
/*
void rs485_add_to_temp(int8 b) {
   // Store the byte
   rs485_buffer[temp_ni] = b;

   // Make the index cyclic
   if(++temp_ni >= RS485_RX_BUFFER_SIZE)
   {
      temp_ni = 0;
   }
}*/
// Purpose:    Send a message over the RS485 bus
// Inputs:     1) To address
//             2) From address
//			   3) len
//             4) data (acknowlege, time to close)
// Outputs:    TRUE if successful
//             FALSE if failed
// Note:       Format:  msg typ | source | data 
int1 rs485_send_message(int8 to,int8 my_id, int8 len, int8* data) {
   int8 try, i, cs;
   int1 ret = FALSE;

   RCV_OFF();

   for(try=0; try<5; ++try) {
      rs485_collision = 0;
      fputc(to+48,RS485_CD);	//to
      fputc(my_id+48, RS485_CD);	//from
      fputc(len+48, RS485_CD);		//length

      for(i=0, cs=my_id^to^len; i<len; ++i) {
         cs ^= *data;
         fputc(*data, RS485_CD);
         ++data;
      }

    //  fputc(cs, RS485_CD);
      if(!rs485_collision) {
      delay_ms(my_id);
         ret = TRUE;
         break;
      }
      delay_ms(my_id);
   }

   RCV_ON();
 
   return(ret);
}
// Purpose:    Interrupt service routine for handling incoming RS485 data
#int_rda
void incomming_rs485() {
   int8 b;
   static int8  cs,len;
   static int8 state=0;
   static int8 to,source,command,data;
   char msg[8];
   int8 size;
   char a;
   int32 x=49;
   b=fgetc(RS485);
   cs^=(int8)b;
   
	    
	
   switch(rcv_state) {
      case 0:  // Get from address
         source=b;
       //  cs=b;
         rs485_InBuffer[0]=source;
        break;

      case 1:  // Get to address
          to=b;
          rs485_InBuffer[1]=to;
          break;

      case 2:  // Get len
         len=b;
     	 rs485_InBuffer[2]=len; 
        break;
        
      case 3:  // Get command
         command=b;
         rs485_InBuffer[3]=b;
         RCV_OFF();
	 	 fputc('c',RS485_CD);
	     fputc(b,RS485_CD);
		 RCV_ON();
		 --len;
       	 break;
       	 
      case 4:  // Get data
      	rs485_InBuffer[4]=b;
		 --len;
       	 break; 
       	 
      default: // Get data
     	
		  break;
		  
       
         
   	}
   	
   	
	   if ((rcv_state>=4) && (len=='0')) {
	     rs485_ni=temp_ni;
	     newMessage=TRUE;
         rcv_state=0;
          RCV_OFF();
	    fputc(rcv_state+48,RS485_CD);
	RCV_ON();
         }
	      
	   else {
	        rcv_state=rcv_state+1;
	        RCV_OFF();
	        printf("%d", rcv_state);
	 		RCV_ON();
	 		}
   
}

// Purpose:    Get a message from the RS485 bus and store it in a buffer
// Inputs:     1) A pointer to a buffer to store a message
//             2) TRUE  - wait for a message
//                FALSE - only check if a message is available
// Outputs:    TRUE if a message was received
//             FALSE if wait is FALSE and no message is available
// Note:       Data will be filled in at the pointer as follows:
//             FROM_ID  DATALENGTH  DATA...
/*
int1 rs485_get_message(int* data_ptr, int1 wait)
{
   while(wait && (rs485_ni == rs485_no)) {}

   if(rs485_ni == rs485_no)
      return FALSE;
   else {
      int n;
      n = rs485_buffer[(rs485_no+1)%sizeof(rs485_buffer)] + 2;

      for(; n>0; --n)
      {
         *data_ptr = rs485_buffer[rs485_no];
         if(++rs485_no >= sizeof(rs485_buffer))
         {
            rs485_no = 0;
         }
         ++data_ptr;
      }
      return TRUE;
   }
}

*/
int1 rs485_get_new_message(int8* data_ptr,int8* cmd,int8 my_ID, int1 wait)
{
   while(wait && (newMessage==FALSE)) {}

   if(newMessage==FALSE)
      return FALSE;
   else			
    {
   	  if(rs485_InBuffer[1]==my_ID+48)		//check if message is for this node
   	  {
   	
      *data_ptr=rs485_InBuffer[4];		//if yes, copy data and cmd type
      *cmd=rs485_InBuffer[3];
      newMessage=FALSE;					//clear newmessage flag
      return TRUE;}
      else	//message not for my address, clear new message flag but don't copy input data
      {
      newMessage=FALSE;
      return FALSE;}
   }
}

// Purpose:    Wait for wait time for the RS485 bus to become idle
// Inputs:     TRUE - restart the watch dog timer to prevent reset
//             FALSE - watch dog timer not restarted
// Outputs:    None
void rs485_wait_for_bus(int1 clrwdt)
{
   int16 i;

   RCV_OFF();
   for(i=0; i <= (rs485_wait_time*20); ++i)
   {
      if(input(RS485_RX_PIN))//this is inverted from original file
         i = 0;
      else
         delay_us(50);

      if(clrwdt)
         restart_wdt();
   }
}
#endif
