//author: luoqinghua
// implementation of MS/TP simple 
// for multi DDC wireless sensor network
// status:successfule 2011.10.10
// for the simple ones 
#include <avr/wdt.h>
unsigned char  data_buffer[4000];
unsigned char  data_buffer0[2200];
unsigned char  receive_0=0;
unsigned int data_length_0=0;
unsigned char  data_buffer1[530]={0x55,0xff};
unsigned char frame_post[8]= {0x55,0xff};  //{0x55,0xff,0x07,0x00,0x40,0x00,0x00,0x07};
unsigned char token_frame[6]={0x55,0xff,0x08};
//unsigned char node_id[6]={0x00,0x00,0x00,0x00,0x00,0x00};
unsigned char receive_d=0;

unsigned char Resp_Label=0;//   Resp_Label; 
static unsigned char Rece_Resp_state=0;

static unsigned char token_label=0;
unsigned char *j0_begin[5];
unsigned int data_length[5]={0};
 unsigned char jj=0;
static unsigned int j1=2;
 unsigned int j0=0;
unsigned int j=0;
 static unsigned int j_0=0;
int EN = 2;
int frame_lenth=0;
int frame_lenth1=0;
// int data_length=0;
unsigned char temp_data=0;
unsigned char temp_data1=0;
static unsigned int send_i=0;

//boolean pream1=0; // 55 or not 
//boolean pream2=0; // 55 and ff or not 
static unsigned char receive_state[]={0,1, 2,3,4 };//0: initial;  1: 55; 2:ff; 3: data;  4: frame over 
static int state_temp=0; // inital the initia status 
static int state_temp1=0;
void setup() {
  // initialize both serial ports:
  Serial.begin(57600);
   Serial1.begin(9600);
     pinMode(EN, OUTPUT);
   digitalWrite(EN, LOW);//使能接收
    temp_data=0;
    temp_data1=0;
    j=0;
    j1=2;
    j0=0;
    receive_d=0;
    jj=0;
    Rece_Resp_state=0;
    Resp_Label=1;
     token_label=0;
      receive_0=0;
     data_length_0=0;
      send_i=0;
   //  wdt_enable(WDTO_120MS);
   //  wdt_reset();
}
 void buffer_copy(unsigned char * buffer_source, unsigned char * buffer_des,int length)
 {
   int j=length;
   while(j>0)
   {
      *(buffer_des++)=*(buffer_source++);
      j--;
   }
 }
unsigned char CRC_Cal_Header( unsigned char datavalue, unsigned char crcvalue)
{
  int crc;
  crc=crcvalue^datavalue;
  crc=crc^(crc<<1)^(crc<<2)^(crc<<3)^(crc<<4)^(crc<<5)^(crc<<6)^(crc<<7);
  return (crc&0xFE)^((crc>>8)&1);
}
unsigned char CRC_Header(unsigned char *buffer)
{
  unsigned char crc8=0xFF;
  crc8=CRC_Cal_Header(buffer[2],crc8); // type
  crc8=CRC_Cal_Header(buffer[3],crc8);
  crc8=CRC_Cal_Header(buffer[4],crc8);
  crc8=CRC_Cal_Header(buffer[5],crc8);
  crc8=CRC_Cal_Header(buffer[6],crc8);
  return(~crc8);
}
void PolResp_03_00( )
{     
  unsigned char data_buffer1[8];
     data_buffer1[0]=0x55; 
     data_buffer1[1]=0xFF;
     data_buffer1[2]=0x02;                /// POLL reply 
     data_buffer1[3]=0x00;   
     data_buffer1[4]=0x03;
     data_buffer1[5]=0x00;
     data_buffer1[6]=0x00;
     data_buffer1[7]=CRC_Header(data_buffer1);
                    // data_buffer1[7]=0x5E;
      delay(2);           
       digitalWrite(EN, HIGH);//使能接收
       delay(2);
        Serial1.write(data_buffer1,8); 
         delay(2); // 9600 19200   is ok      but  38400 : 800us 
      //  delayMicroseconds(800);
       digitalWrite(EN, LOW);//使能接收
}

void Token_03_00( )
{     
  unsigned char data_buffer1[8];
     data_buffer1[0]=0x55; 
     data_buffer1[1]=0xFF;
     data_buffer1[2]=0x00;                /// POLL reply 
     data_buffer1[3]=0x00;   
     data_buffer1[4]=0x03;
     data_buffer1[5]=0x00;
     data_buffer1[6]=0x00;
     data_buffer1[7]=CRC_Header(data_buffer1);
                    // data_buffer1[7]=0x5E;
     delay(2);           
      digitalWrite(EN, HIGH);//使能接收
       delay(2);
       Serial1.write(data_buffer1,8); 
        delay(2); // 9600 19200   is ok      but  38400 : 800us 
     //  delayMicroseconds(800);
       digitalWrite(EN, LOW);//使能接收
}

void Token_03_40( )
{     
  unsigned char data_buffer1[8];
     data_buffer1[0]=0x55; 
     data_buffer1[1]=0xFF;
     data_buffer1[2]=0x00;                /// POLL reply 
     data_buffer1[3]=0x40;   
     data_buffer1[4]=0x03;
     data_buffer1[5]=0x00;
     data_buffer1[6]=0x00;
     data_buffer1[7]=CRC_Header(data_buffer1);
                    // data_buffer1[7]=0x5E;
      delay(2);           
      digitalWrite(EN, HIGH);//使能接收
       delay(2);
       Serial1.write(data_buffer1,8); 
       delay(2); // 9600 19200   is ok      but  38400 : 800us 
       // delayMicroseconds(800);
       digitalWrite(EN, LOW);//使能接收
}




void Token_40_00( )
{     
     unsigned char data_buffer1[8];  
     data_buffer1[0]=0x55; 
     data_buffer1[1]=0xFF;
     data_buffer1[2]=0x00;                /// POLL reply 
     data_buffer1[3]=0x00;   
     data_buffer1[4]=0x40;
     data_buffer1[5]=0x00;
     data_buffer1[6]=0x00;
     data_buffer1[7]=CRC_Header(data_buffer1);
                    // data_buffer1[7]=0x5E;
       delay(2);           
      digitalWrite(EN, HIGH);//使能接收
       delay(2);
       Serial1.write(data_buffer1,8); 
             delay(2); // 9600 19200   is ok      but  38400 : 800us 
       //delayMicroseconds(800);
       digitalWrite(EN, LOW);//使能接收
}

  void Frame_Request( unsigned char destination)
  {
    unsigned char data_buffer1[5];   // my own protocl of the wireless communication
     data_buffer1[0]=0x5F; 
     data_buffer1[1]=0x5F;  
     data_buffer1[2]=0x03;    // Frame type          
     data_buffer1[3]=destination;    // destination  address
     data_buffer1[4]=0x00;    //  source address  
     Serial.write(data_buffer1,5);  // wireless broadcast 
  }

void loop() {
  // read from port 1, send to port 0:
  digitalWrite(EN, LOW);//使能接收
  
  
    if (Serial.available()) {
         
    switch(state_temp){
      
       
      case 0: // initial 
       temp_data=Serial.read();
            if (temp_data==0x55) {
              // Serial.println("state 55 ");
              data_buffer[j0]=temp_data;
             // j0_begin[receive_d]=&data_buffer[j0];
                   j=1;
                   j0++;
                 state_temp=1;
                     }
             else
                  {
                  state_temp=0;
                  j=0;
                  }
                 //  pream1=1;
          break;
       case 1: // pream
               temp_data=Serial.read();
            if (temp_data==0xFF) {
              data_buffer[j0]=temp_data;
                  j=2;
                    j0++;
                  state_temp=2;
                    }
          else if (temp_data==0x55){
             data_buffer[j0-1]=temp_data;
                  j0++;
                   j=1;
                 state_temp=1;
             }
            
             else 
            {
              j=0;
             state_temp=0;
            }
            break;
      case 2:  // header  
                
              if (j==2) // frame type // may use the case structure 
              {
                // temp_data=Serial.read();
                data_buffer[j0]=Serial.read();
                 j0++;
                 j=3;
              }
              else if (j==3)// destination address
                {
                 // temp_data=Serial.read();
                 
                 data_buffer[j0]=Serial.read();
                   j0++;
                   j=4;
              }
                 else if (j==4)// source address
                {
                   data_buffer[j0]= Serial.read();
                  j0++;
                  j=5;
                  

                  }  
                 else if (j==5)// length high
                {
                 data_buffer[j0]=Serial.read();
                
                  frame_lenth=data_buffer[j0]*256;
                     j0++;
                 j=6;
                  }  
                else if (j==6)// length low
                {
                 data_buffer[j0]=Serial.read();
                
                  frame_lenth=frame_lenth+data_buffer[j0]; // the frame length 
                    j0++;
                 j=7;
                  }  
                  else if (j==7)// header crc
                {
                 data_buffer[j0]=Serial.read();
                //   Serial.println("state 2 lenth 7 ");// #################################
                           j++;
                            j0++;
                     if (frame_lenth==0)
                      { 
                        state_temp=0; //  &&&&&&&&&&&&&&7 very important
                            j=0;//  &&&&&&&&&&&&&&7 very important 
                        }
                      else 
                      {state_temp=3;
                        }
                  }  
                  break;
         case 3: // data and data crc
                if (j<frame_lenth+9) 
                   {
                 data_buffer[j0]=Serial.read();
                  j0++;
                   j++;
                 state_temp=3;
                   }
               else        
                 {
                   data_buffer[j0]=Serial.read(); 
                 
                    
                     data_length[receive_d]=frame_lenth+10;
                     
                     // try 
                     j0_begin[receive_d]=&data_buffer[j0-frame_lenth-9];
                    
                    
                     j0++;
                     
                     
                //  Serial.println("state 2 lenth 7 ");
                //  Serial.println(receive_d, BYTE); 
                //   Serial.write(&((char)(j0&0xFF00)),2); 
               //    Serial.println(j0, BYTE); 
                //   Serial.println(receive_d, BYTE); 
               //   Serial.write(j0_begin[receive_d],data_length[receive_d]);  
                 //   Serial.write(data_buffer,frame_lenth+10);  
                //   Serial.println(j, BYTE); 
                  //  Serial.println(j0_begin, BYTE); 
                    receive_d=receive_d+1;
                 state_temp=0; //  &&&&&&&&&&&&&&7 very important
                 j=0;//  &&&&&&&&&&&&&&7 very important 
                   }
              break;
               
       case 4:
                 state_temp=0;
                 j=0;
                 break; 
        default: 
                 state_temp=0;
                 j=0;  
          
    
    }// end of  switch 
    
    // to judege the first oc   
}  // end of if serial.avaible
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%5
  
if (Serial1.available()) {
      
    switch(state_temp1){
      
      case 0: // initial 
       temp_data1=Serial1.read();
            if (temp_data1==0x55) {
                 state_temp1=1;
                     }
            else {
                  state_temp1=0;
                  }
                 //  pream1=1;
          break;
  case 1: // pream
               temp_data1=Serial1.read();
            if (temp_data1==0xff) {
                 state_temp1=2;
                    }
             else if (temp_data1==0x55){
                 state_temp1=1;
             }
             else  {state_temp1=0;}
            break;
  case 2:  // header  
                
         if (j1==2) // frame type // may use the case structure 
              {
                 data_buffer1[j1]=Serial1.read();
                  j1=3;
              }
         else if (j1==3)// destination address
                {
                 data_buffer1[j1]=Serial1.read();
                 j1=4;
              }
         else if (j1==4)// source address
            {
                 data_buffer1[j1]=Serial1.read();
                 if ((data_buffer1[2]==0x01)&(data_buffer1[3]==0x03))   // 00 POLL 03
                      { 
                     //   Frame_Requst(data_buffer1[3]);// send  data request to DDC 03 through wireless 
                        PolResp_03_00();   // response 
                      //  Resp_Label=2;
                        
                        state_temp1=0; //  &&&&&&&&&&&&&&7 very important
                         j1=2;//  &&&&&&&&&&&&&&7 very important 
                         //     Serial.println("poll "); //$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
                       }
                       
                 else if (data_buffer1[2]==0x07) //((data_buffer1[2]==0x07) &(data_buffer1[3]==0x40))   // pose pone,send token
                   { data_buffer1[0]=0x55;
                     data_buffer1[1]=0xFF;
                     data_buffer1[2]=0x00;  
                     unsigned char destination_temp= data_buffer1[3];
                     /// POLL reply 
                     data_buffer1[3]=data_buffer1[4];   
                     data_buffer1[4]=destination_temp;
                     data_buffer1[5]=0x00;
                     data_buffer1[6]=0x00;
                     data_buffer1[7]=CRC_Header(data_buffer1);
                    // delay(2);
                  
                     digitalWrite(EN, HIGH);//使能接收
                     delay(2);
                     Serial1.write(data_buffer1,8); 
                            delay(2); // 9600 19200   is ok      but  38400 : 800us 
                        // delayMicroseconds(800);
                     digitalWrite(EN, LOW);//使能接收
                    token_label=0;
                      state_temp1=0; //  &&&&&&&&&&&&&&7 very important
                       j1=2;//  &&&&&&&&&&&&&&7 very important 
                      //     Serial.println("poll "); //$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
                    } 
                 else  if ((data_buffer1[2]==0x00)&(data_buffer1[3]==0x03))   // 00 send token agent 03 
                     { 
                       
                    
                     
                     /*
                        if ( receive_0>0)  // send wireless 
                        {
                          token_frame[3]=data_buffer0[3];
                          Serial.write(token_frame,4); 
                          delay(1);
                          Serial.write(data_buffer0,data_length_0);
                          
                          receive_0=0;
                        }
                       
                       */
                       
                     if (jj<receive_d) 
                         {                  
                           while (jj<receive_d)
                              {
                             delay(2);
                              digitalWrite(EN, HIGH);//使能接收
                     //  digitalWrite(EN, HIGH);//使能接收
                                 delay(2);
                       
                    //   j0_begin[receive_d]=data_buffer;
                    // data_length[receive_d]=frame_lenth+10;
                   //   Serial.println(jj, BYTE); 
                   //   Serial.println(receive_d, BYTE); 
                     //  Serial.write(j0_begin[receive_d],data_length[receive_d]);  
                      // data_length=data_buffer[5]*256+data_buffer[6];
                       Serial1.write(j0_begin[jj],data_length[jj]);  
                      
                      // j0_begin=j0_begin+data_length+10;
                              delay(2);  //  9600 19200   is ok      but  38400 : 800us 
                          //  delayMicroseconds(800);
                       digitalWrite(EN, LOW);//使能接收
                       delay (4); 
                     // delay(2);
                          jj++;            
                     }
                  
                   //
                 
              //    Token_40_00();  // add  new 
                   
                      if (jj>3) 
                   {
                      jj=0;
                      receive_d=0;
                      j0=0;
                   }
                    token_label=1;
                    //  Token_40_00();
                   //   state_temp1=0; //  &&&&&&&&&&&&&&7 very important
                  //     j1=2;//  &&&&&&&&&&&&&&7 very important 
                     }
                     
                  //  else 
                 //    {
                         //Token_03_40();
                       //   delay(10);
                       Token_40_00();
                      token_label=0;
                      //     Serial.println("poll "); //$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
                    //   } 
                   state_temp1=0; //  &&&&&&&&&&&&&&7 very important
                       j1=2;//  &&&&&&&&&&&&&&7 very important 
                
                 }                               
              else {
                      j1=5;
                      }
            } 
         else if (j1==5)// length high
            {
                 data_buffer1[j1]=Serial1.read();
                  frame_lenth1=data_buffer1[5]*256;
                 j1=6;
             }  
         else if (j1==6)// length low
           {
                 data_buffer1[j1]=Serial1.read();
                  frame_lenth1=frame_lenth1+data_buffer1[6]; // the frame length 
                 j1=7;
            }  
          else if (j1==7)// header crc
             {
                 data_buffer1[j1]=Serial1.read();
                //   Serial.println("state 2 lenth 7 ");// #################################
                           j1++;
                    if ( frame_lenth1==0)
                     
                     {
                      state_temp1=0; //  &&&&&&&&&&&&&&7 very important
                      j1=2;//  &&&&&&&&&&&&&&7 very important 
                     }
                      else 
                      {state_temp1=3;}
             }  
                  break;
  case 3: // data and data crc
            if (j1<frame_lenth1+9) 
                   {
                 data_buffer1[j1]=Serial1.read();
                //   Serial.print(j, BYTE); //##############################
                //  Serial.print(data_buffer[j], BYTE); //##############################
                //  Serial.println("state 3  proceding ");// #################################
                //  Serial.print(data_buffer[j], BYTE); 
                   j1++;
                 state_temp1=3;
                   }
               else        
                 {
                   data_buffer1[j1]=Serial1.read(); 
                   // data_buffer[j+1]=0xff;
                  //  Serial.print(data_buffer[j], BYTE); //########################
                  //   Serial.println("state 3  OVER ");// #################################
                  // Serial.print(data_buffer[j], BYTE); 
                  /*
               if (data_buffer1[3]!=0xFF)  // may can be improved 
                    {
                       if (frame_lenth1<80)
                         {
                     token_frame[3]=data_buffer1[3];
                     Serial.write(token_frame,4); 
                     delay(1);
                     Serial.write(data_buffer1,frame_lenth1+10);  
                         }
                         else
                          {
                            buffer_copy( data_buffer1,data_buffer0,frame_lenth1+10) ; 
                            data_length_0=frame_lenth1+10;
                            receive_0=1;}
                        }*/
                        
                         if (data_buffer1[3]!=0xFF)  // may can be improved 
                    {
                          token_frame[3]=data_buffer1[3];
                          Serial.write(token_frame,4); 
                          
                          
                         buffer_copy( data_buffer1,&(data_buffer0[j_0]),frame_lenth1+10) ; 
                           // data_length_0=frame_lenth1+10;
                        // Serial2.println(j_0,DEC) ;
                        //  Serial2.println(" "); 
                         //  Serial2.println(&(data_buffer0[j_0]),DEC) ;
                           j_0=j_0+frame_lenth1+10;
                    }
                        
                      
                   if ((data_buffer1[2]==0x05))  
                  // if (data_buffer1[3]==0x40) 
                   { 
                   frame_post[0]=0x55;
                   frame_post[1]=0xff;
                   frame_post[2]=0x07;
                   frame_post[3]=data_buffer1[4];
                   frame_post[4]=data_buffer1[3];
                   frame_post[5]=0x00;
                   frame_post[6]=0x00;
                   frame_post[7]=CRC_Header(frame_post);
                   
                    // delay(2);
                    digitalWrite(EN, HIGH);//使能接收
                      delay(2);
                     Serial1.write(frame_post,8); 
                           delay(2); // 9600 19200   is ok      but  38400 : 800us 
                      //  delayMicroseconds(800);
                     digitalWrite(EN, LOW);//使能接收
                     } 
                     
                     else if ((data_buffer1[2]==0x06) &(data_buffer1[3]!=0xff)&(token_label==1)) 
                     {   frame_post[0]=0x55;
                         frame_post[1]=0xff;
                         frame_post[2]=0x00;
                         frame_post[3]=data_buffer1[4];
                         frame_post[4]=data_buffer1[3];
                         frame_post[5]=0x00;
                         frame_post[6]=0x00;
                         frame_post[7]=CRC_Header(frame_post);
                     //     delay(2); 
                       
                          digitalWrite(EN, HIGH);//使能接收
                          delay(2);
                           Serial1.write(frame_post,8); 
                                 delay(2);  // 9600 19200   is ok      but  38400 : 800us 
                               //delayMicroseconds(800);
                           digitalWrite(EN, LOW);//使能接收 
                            token_label=0;
                         }
                    
               // Serial.flush();
                 state_temp1=0; //  &&&&&&&&&&&&&&7 very important
                 j1=2;//  &&&&&&&&&&&&&&7 very important 
                   }
              break;
               
       case 4:
                 state_temp1=0;
                 
          
    
    }// end of  switch 
    
    // to judege the first oc   
}  // end of if serial.avaible
  
   if(send_i<j_0)
                          {
                          Serial.write(&(data_buffer0[send_i]),1);
                          send_i=send_i+1;
                          
                            }
                            else
                            {
                              j_0=0;
                              send_i=0;
                              
                            }






}  // end loop 
   
   
