#include <stdlib.h>

#ifndef RS485_DRIVER
#define RS485_DRIVER

//#ifndef RS485_ID
//#define RS485_ID  0x10                 // 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=300, xmit=RS485_TX_PIN, rcv=RS485_RX_PIN, enable=RS485_ENABLE_PIN,bits=8, stream=RS485,errors)//rcv

#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. 
         output_low(RS485_RX_ENABLE);
   		 output_low(RS485_ENABLE_PIN);
   
}

void RCV_OFF(void) {
   output_high(RS485_RX_ENABLE);
   output_high(RS485_ENABLE_PIN);
}


// 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);

}


// 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);	//to
      fputc(my_id+48, RS485);	//from
      fputc(len+48, RS485);		//length

      for(i=0, cs=my_id^to^len; i<len; ++i) {
         cs ^= *data;
         fputc(*data, RS485);
         ++data;
      }

      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
// data format: from address, to address, length, command, data (each 1 byte)
#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;
		 --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;
		fputc('t',RS485); 
         rcv_state=0;
         }
	      
	   else {
	        rcv_state=rcv_state+1;
	 		}
*/
 b=fgetc(RS485);
          if (b == '\r')
            {
                putc('\r', RS485);
                putc('\n',RS485);
            }               
            else
            {
				RCV_OFF();
 				putc(b,RS485);
				RCV_ON();
 
            }
       

   
}


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();
   }
	RCV_ON();
}
#endif
