//author: luoqinghua
// implementation of MS/TP simple 
// address is 0x00
// status:successfule
// more improve; to send all the data during the token time. 
// imp3 add the token_label to process the two case: 55 FF 06 00 40 when the 00 have token or not 
// imp3 is based on the imp2. 
// imp2  use the uart buffer to store the data, so the data can be many frame.not only one
// imp1  does not use the buffer. only one dara frame can be treated. com 23 24 
#include <avr/wdt.h>
unsigned char  data_buffer[2200];
unsigned char  data_buffer0[4000];
unsigned char  receive_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 received=0;
static unsigned char DDC_ID=0;
static unsigned char TOKEN=1;

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 char *j0_begin0[5];
unsigned int data_length[5]={0};
//unsigned int data_length_0[5]={0};
unsigned int data_length_0=0;
 unsigned char jj=0;
static unsigned int j1=2;
 unsigned int j0=0;
 static unsigned int j_0=0;
  
unsigned int j=0;
static unsigned int send_i=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;

//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 unsigned char state_temp=0; // inital the initia status 
static unsigned char state_temp1=0;

 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 Frame_Response( unsigned char destination, unsigned char DDC_ID)
  {
    unsigned char data_buffer1[5];   // my own protocl of the wireless communication
     data_buffer1[0]=0x5F; 
     data_buffer1[1]=0x5F;  
     data_buffer1[2]=0x04;    // Frame type          
     data_buffer1[3]=0x00;    // destination  address
     data_buffer1[4]=DDC_ID;    //  source address  
     Serial.write(data_buffer1,5);  // wireless broadcast 
  }
void setup() {
  // initialize both serial ports:
  Serial.begin(57600);
   Serial1.begin(9600);
   //   Serial2.begin(9600);
     pinMode(EN, OUTPUT);
   digitalWrite(EN, LOW);//使能接收
    temp_data=0;
    temp_data1=0;
    j=0;
    j1=2;
    j0=0;
  received=0;
    jj=0;
   token_label=0;
   receive_0=0;
   j_0=0;
   data_length_0=0;
   send_i=0;
  // wdt_enable(WDTO_120MS);// 1S,2S,4S,8S,15MS,30MS,60MS,120MS,250MS,500MS
  // wdt_reset();

}

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[received]=&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){
                j0=j0-1;
             data_buffer[j0]=temp_data;
                  j0++;
                   j=1;
                 state_temp=1;
             }
             
             else 
            {
              j=0;
              j0=j0-1;
             state_temp=0;
            }
            break;
      case 2:  // header  
                
              if (j==2) // frame type // may use the case structure 
              {
                temp_data=Serial.read();
                if ((temp_data==0x05)|| (temp_data==0x06))
                {
                 data_buffer[j0]=temp_data;
                 j0++;
                 j=3;}
                 else
                {
                   j0=j0-2;
                    j=0;
                 state_temp=0;
                 } 
              }
              else if (j==3)// destination address
                {
                   temp_data=Serial.read();
                 
                 
                  if (temp_data==DDC_ID){                // for me 
               
                      if (data_buffer[j0-1]==0x08)   // token frame 
                          {
                            TOKEN=1;
                            j0=j0-3;
                            j=0;
                           state_temp=0; 
                        }
                     data_buffer[j0]=temp_data;
                      j0++;
                      j=4;}
                      
                  else if (data_buffer[j0-1]==0x08)   // token frame 
                          {
                            TOKEN=0;
                            j0=j0-3;
                            j=0;
                           state_temp=0; 
                        }
                   else
                   {                                    // not for me 
                       Resp_Label=0;
                       Rece_Resp_state=0;
                       j=0;
                       j0=j0-3;
                       state_temp=0; //  &&&&&&&&&&&&&&7 very important
                   }
              }
                 else if (j==4)// source address
                {
                    temp_data=Serial.read();
                 
                 data_buffer[j0]= temp_data;
                  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(); 
                   j0++;
                    
                     data_length[received]=frame_lenth+10;
                     
                //  Serial.println("state 2 lenth 7 ");
                //  Serial.println(received, BYTE); 
                //   Serial.write(&((char)(j0&0xFF00)),2); 
               //    Serial.println(j0, BYTE); 
                //   Serial.println(received, BYTE); 
               //   Serial.write(j0_begin[received],data_length[received]);  
                 //   Serial.write(data_buffer,frame_lenth+10);  
                //   Serial.println(j, BYTE); 
                  //  Serial.println(j0_begin, BYTE); 
                    received=received+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

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 
              {
                 temp_data=Serial1.read();
                 if ((temp_data>=0x00)&&(temp_data<=0x07))
                 {
                 data_buffer1[j1]=temp_data;
                 j1=3;}
                  else 
                   {
              
                   state_temp1=0;
                   }
              }
          else if (j1==3)// destination address
                {
                 data_buffer1[j1]=Serial1.read();
                 j1=4;
                    }
          else if (j1==4)// source address
              {
                  data_buffer1[j1]=Serial1.read();
                     DDC_ID=data_buffer1[j1];
                  if ((data_buffer1[2]==0x01)&&(data_buffer1[3]==0x00))   //55 FF 01 00 40 00 00 16   poll frame 
                   {                                                    //55 FF 02 40 00 00 00 D3 
                     data_buffer1[0]=0x55;
                     data_buffer1[1]=0xFF;
                     data_buffer1[2]=0x02;
                     data_buffer1[3]=data_buffer1[4];
                     data_buffer1[4]=0x00;
                     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);//使能接收
                    
                      state_temp1=0; //  &&&&&&&&&&&&&&7 very important
                       j1=2;//  &&&&&&&&&&&&&&7 very important 
                      //     Serial.println("poll "); //$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
                    
                       }
                   
                   else if ((data_buffer1[2]==0x07)&&(data_buffer1[3]==0x00))   // if the postpone, send token back 
                     {
                        data_buffer1[0]=0x55; 
                        data_buffer1[1]=0xFF; 
                        data_buffer1[2]=0x00;
                      // unsigned char  destination_temp= data_buffer1[3];
                        data_buffer1[3]=data_buffer1[4];
                        data_buffer1[4]=0x00;
                        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 
                      } 
                     
                 else  if ((data_buffer1[2]==0x00)&&(data_buffer1[3]==0x00))  // 55 FF 00 00 40 00 00 90   token ################
                      {     
               
                        
                        
                       /* 
                        if ( receive_0>0)  // send wireless 
                        {
                          
                          Serial.write(data_buffer0,data_length_0);
                          
                          receive_0=0;
                          //
                          int i=0;
                          while(i<receive_0)
                          {
                            //  Serial.write(data_buffer1,frame_lenth1+10);
                             Serial.write(j0_begin0[i],data_length[i]);  
                             i++;
                             } // 
                          
                        } */



                        //55 FF 00 40 00 00 00 DC 
                        // data_buffer1[0]=0x55; 
                       //  data_buffer1[1]=0xff; 
                         data_buffer1[2]=0x00; 
                         data_buffer1[3]=data_buffer1[4];
                        data_buffer1[4]=0x00; 
                        data_buffer1[5]=0x00;
                        data_buffer1[6]=0x00;
                        data_buffer1[7]=CRC_Header(data_buffer1);
                        
                     if ((jj<received) )
                     {
                       while (jj<received) // if there are data needed to be sent
                          {
                               delay(2); 
                              digitalWrite(EN, HIGH);//使能接收
                             // digitalWrite(EN, HIGH);//使能接收
                              delay(2); 
                              //data_length=data_buffer[5]*256+data_buffer[6];
                            Serial1.write(j0_begin[jj],data_length[jj]);  
                             
                          delay(2); //  9600 19200   is ok      but  38400 : 800us 
                          //  delayMicroseconds(800);
                             digitalWrite(EN, LOW);//使能接收
                           //  state_temp1=0; //  &&&&&&&&&&&&&&7 very important
                           //  j1=2;//  &&&&&&&&&&&&&&7 very important     return back to idle 
                           
                               if (*(j0_begin[jj]+2)==0x06)
                               {
                           //  frame_post[0]=0x55;
                           //   frame_post[1]=0xff;
                               frame_post[2]=0x00;
                              frame_post[3]=DDC_ID;
                             frame_post[4]=0x00; 
                              frame_post[5]=0x00;
                              frame_post[6]=0x00;
                              frame_post[7]=CRC_Header( frame_post);//0x4B;// 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;  
                             }
                              jj++;  
                           }
                           
                          /*  if (*(j0_begin[jj]+2)==0x06)  //((*(j0_begin[jj]+2)==0x06)&*(j0_begin[jj]+2)==0x04))
                            {
                             //   frame_post[0]=0x55;
                     //    frame_post[1]=0xff;
                        frame_post[2]=0x00;
                        frame_post[3]=data_buffer1[4];
                        frame_post[4]=0x00; 
                        frame_post[5]=0x00;
                         frame_post[6]=0x00;
                         
                         frame_post[7]=0xDC;// CRC_Header( frame_post);//!!!!!!!!!!!!!!!!!!!!!!!!!!!
                     //  delay(3); 
                       
                    digitalWrite(EN, HIGH);//使能接收
                      delay(2);
                     Serial1.write(frame_post,8); 
                     delay(2);
                     digitalWrite(EN, LOW);//使能接收
                     token_label=0;
                     
                     
                     
                            }*/ 
                           if (jj>3) 
                                {
                                      jj=0;
                                      received=0;
                                       j0=0;
                                   }
                                   
                          token_label=1;
                       }
                           else 
                           {
                              delay(2);
                           // digitalWrite(EN, HIGH);//使能接收
                            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  return idle 
                         //  j1=2;//  &&&&&&&&&&&&&&7 very important 
                           }
                           
                
                        
                    state_temp1=0; //  &&&&&&&&&&&&&&7 very important  return idle 
                           j1=2;//  &&&&&&&&&&&&&&7 very important        
                        
                       //  Serial.println("token "); //$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
                     // break;  
                     }
             else {
                     j1=5;
                   }
                  }  
         else if (j1==5)// length high
                {
                 data_buffer1[j1]=Serial1.read();
                  frame_lenth1=data_buffer1[j1]*256;
                 j1=6;
                  }  
          else if (j1==6)// length low
                {
                 data_buffer1[j1]=Serial1.read();
                  frame_lenth1=frame_lenth1+data_buffer1[j1]; // 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(); 
                       if (TOKEN==1)  // if ((TOKEN==1)||(data_buffer1[3]==0xff)) // broadcast can be transmit 
                       {
                      
                        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) &&(data_buffer1[3]==0x00))  // 40 send a data request  
                         {
                              // frame_post[7]={0x55,0xff,0x07,0x40,0x00,0x00,0x00,0x4B};55 FF 07 40 00 00 00 4B 
                           //  frame_post[0]=0x55;
                           //   frame_post[1]=0xff;
                               frame_post[2]=0x07;
                              frame_post[3]=data_buffer1[4];
                             frame_post[4]=0x00; 
                              frame_post[5]=0x00;
                              frame_post[6]=0x00;
                              frame_post[7]=CRC_Header( frame_post);//0x4B;// 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]==0x00)&(token_label==1))//55 FF 00 40 00 00 00 DC 
                       {  
                      //   frame_post[0]=0x55;
                     //    frame_post[1]=0xff;
                        frame_post[2]=0x00;
                        frame_post[3]=data_buffer1[4];
                        frame_post[4]=0x00; 
                        frame_post[5]=0x00;
                         frame_post[6]=0x00;
                         
                         frame_post[7]= CRC_Header( frame_post);//0xDC;// 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;
                     }
                  
                   // 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[2]!=0xFF) &(data_buffer1[3]==0x00))  
                   //   { 
                 state_temp1=0; //  &&&&&&&&&&&&&&7 very important
                 j1=2;  //  &&&&&&&&&&&&&&7 very important      
   
                  //  }
               // Serial.flush();

                   }
              break;
               
       case 4:
                 state_temp1=0;
                 
          
    
    }// end of  switch 
    
    // to judege the first oc   
}  // end of if serial.avaible


                      
              
                
                          if((send_i<j_0)&&(TOKEN==1) ) //  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 
   
   
