#include <16F628A.h> 
#fuses XT,NOWDT,NOPROTECT,NOLVP,NOMCLR 
#use delay(clock=3579545) 
#use rs232(baud=1200, float_high, bits=9, xmit=PIN_B0, rcv=PIN_B0) 


//-------------------------------------------------------------------------------------
 
#define OUR_ID 2 
#define SL1_ID 3 
#define SL2_ID 4 

/* 
#define OUR_ID 3 
#define SL1_ID 2 
#define SL2_ID 4 
 
#define OUR_ID 4 
#define SL1_ID 2 
#define SL2_ID 3 
*/ 

#define MAX_MESSAGES 4 
#define MAX_LENGTH   7 
#define INTS_PER_SECOND 50 
#define SAMPLET	4 
 
#BYTE port_a = 5 
#BYTE port_b = 6 
#BYTE tris_a = 0x85 
#BYTE tris_b = 0x86 
#bit  sw1=port_b.4 
#bit  sw2=port_b.5 
#bit  led1=port_a.1 
#bit  led2=port_a.0  
 
int1 dbutton4, dbutton5, data_avail; 
int current, last; 
long int_count, sampleb; 
byte pbus_buffer[MAX_MESSAGES][MAX_LENGTH+1]; 
byte next_in=0; 
byte next_out=0; 
enum pbus_states {PBUS_IDLE=0x80,PBUS_NEED_LEN=0x81,PBUS_NEED_TO=0x82, 
                  PBUS_NEED_FROM=0x83,PBUS_NEED_CS=0x84}; 
byte pbus_state=PBUS_IDLE; 
byte checksum; 
byte last_byte; 
byte to,len,i,msg[MAX_LENGTH]; 
int ori, dest, dest_s; 
int a; 
 
#bit ninth_bit = RS232_ERRORS.7 
#bit collision = RS232_ERRORS.6 
#bit intf = 11.1 

//-------------------------------------------------------------------------------------
 
 #int_TIMER0                        // This function is called every time      
 void clock_isr()                                                              
 {                 					// the RTCC (timer0) overflows (255->0).               
     set_timer0(116);                // For this program this is apx 139 times 
      if(--int_count==0) 			// per second.                                                                                              
       {                                                                                         
          int_count=INTS_PER_SECOND; 
           if (sampleb)                                                   
           {                                                
           	  	sampleb--; 
                 {                                                               
                 		led1=0; 
                        led2=0;
                        dest_s=0;
      	  	     }                                               
       	   }  
       } 
} 


//-------------------------------------------------------------------------------------

 #int_rb                       
 void detect_rb_change() 
 { 
                           
    current=input_b();     
     if ((!bit_test(current,4))&&(bit_test(last,4))) {dbutton4=1;}                                           
     if ((!bit_test(current,5))&&(bit_test(last,5))) {dbutton5=1;} 
     last=current;                                                               
      led1=0;
      led2=0; 
}

//-------------------------------------------------------------------------------------                                                                                 
                                                                                       
                                                                                       
                                                                                       
#int_ext                                                                               
void pbus_isr() {                                                                      
     byte data;                                                                                   
                                                                                       
    if(kbhit()) {                                                                      
                                                                                       
      data=getc();                                                                     
                                                                                       
      if(ninth_bit) {                                                                  
         switch(pbus_state) 
	     {                                                          
           case PBUS_IDLE : if(data==0xf1)                                             
                                pbus_state=PBUS_NEED_TO;                               
                            break;                                                     
           case PBUS_NEED_TO :                                                         
                            if(data==OUR_ID)                                           
                               pbus_state=PBUS_NEED_FROM;                              
                            else                                                       
                               pbus_state=PBUS_IDLE;                                   
                            checksum=data;                                             
                                                                                       
                            break;                                                     
           case PBUS_NEED_FROM :                                                       
                            pbus_buffer[next_in][0] = data;                            
                            pbus_state=PBUS_NEED_LEN;                                  
                            checksum^=data;                                            
                            break;                                                     
           case PBUS_NEED_LEN :                                                        
                            last_byte = data+1;                                        
                            pbus_buffer[next_in][1] = data;                            
                            pbus_state=2;                                              
                            checksum^=data;                                            
                            break;                                                     
         }                                                                             
      } else                                                                           
        if(pbus_state==PBUS_NEED_CS) {                                                 
           if(checksum==data)                                                          
               next_in = (next_in+1) % MAX_MESSAGES;                                   
           pbus_state=PBUS_IDLE;                                                       
        } else if(pbus_state<0x80) {                                                   
           pbus_buffer[next_in][pbus_state] = data;                                    
           checksum^=data;                                                             
           if(++pbus_state>last_byte)                                                  
              pbus_state=PBUS_NEED_CS;                                                 
      }                                                                                
    }                                                                                  
}                                                                                      
                                                                                       
                                                                                       
//-------------------------------------------------------------------------------------
                                                                                       
                                                                                       
                                                                                       
void pbus_send( byte * message, byte to, byte len) {                                   
   byte checksum,i;                                                                    
                                                                                       
   retry:                                                                              
      checksum=len^OUR_ID^to;                                                          
      disable_interrupts(GLOBAL);                                                      
      collision=false;                                                                 
      ninth_bit=1;                                                                     
                                                                                       
      putc(0xf1);           if(collision) goto error;                                  
      putc(to);             if(collision) goto error;                                  
      putc(OUR_ID);         if(collision) goto error;                                  
      putc(len);            if(collision) goto error;                                  
      ninth_bit=0;                                                                     
      for(i=1;i<=len;++i)                                                              
	  {                                                                                   
        checksum^=*message;                                                            
        putc(*(message++)); if(collision) goto error;                                  
      }                                                                                
      putc(checksum);       if(collision) goto error;                                  
      intf=false;                                                                      
      enable_interrupts(GLOBAL);                                                       
      return;                                                                          
                                                                                       
   error:                                                                              
      delay_ms(16);                                                                    
      enable_interrupts(GLOBAL);                                                       
      goto retry;                                                                      
}                                                                                      
                                                                                       
                                                                                       
                                                                                       
                                                                                       
//-------------------------------------------------------------------------------------



                                                                                       
void led_t(int l)                                                                                                          
 {              
 	if(l==SL1_ID) 
     {                                         
     	led2=1;
     	led1=0; 
     } 
     else                                                                                                    
	{        
		led2=0;     
		led1=1;     
	}        
 }         
 
 
 #include <input.c>

//-------------------------------------------------------------------------------------

#zero_ram                                                             
void main()  
{ 

	setup_timer_0 (RTCC_DIV_128 | RTCC_INTERNAL);                                                      
	set_timer0(116);                                              
	int_count=INTS_PER_SECOND; 
	port_b_pullups(TRUE);                                                                        
	tris_a=0b11111100;                                                                             
	ext_int_edge( h_to_l );                                                                       
	enable_interrupts(INT_TIMER0);                                                                 
	enable_interrupts(INT_RB);                                       
	enable_interrupts(int_ext);                                                 
	enable_interrupts(global);                                                           
	to=1;                                                                                         
	len=1; 
	do 
	{                                                                                
		if(next_in!=next_out)                                                                   
		{                                           
		   	ori=pbus_buffer[next_out][0];                                                           
		 	dest=pbus_buffer[next_out][2];        
			if(ori=1)                                                                 
	   		{                                                                               
	   			if((dest==dest_s))                                                
	 			{                                    
		  			led_t(dest);                        
		     		dest_s=0;                           
		  			sampleb=SAMPLET;                    
		  		}                              
		 		else                                                                                  
		   		{                                    
		   			led_t(dest);                        
		            sampleb=0;                                                                      
		      	}                                    
		   	}                                        
		    next_out=(next_out+1) % MAX_MESSAGES;                                                   
		}         	                                                                                      
		if(dbutton5)                                                           
		{                                            
			led2=1;                                                                         
			msg[0]=SL1_ID;                                                                             
			dest_s=SL1_ID;                                                                                
			pbus_send(msg,to,len);                      
			led2=0;                                     
			dbutton5=0;                                                                                
		}                                            
		if(dbutton4)                                 
		{                                            
			led1=1;                                     
			msg[0]=SL2_ID;                                                                             
			dest_s=SL2_ID;                                                                               
			pbus_send(msg,to,len);                      
			led1=0;                                      
			dbutton4=0;                                    
		}                                            
		delay_ms(500);                                                                              
	} while (TRUE);                             
 }                                              
                                                                     