/*@!Encoding:1252*/
includes
{
  #include "CRC_Counter_C100.cin"
}

variables
{
  msTimer Timer1; 
  msTimer Timer2;
  msTimer Timer3000ms;
  msTimer Timer_TI_on;
  msTimer Timer_TI_off;
  msTimer TL_Ind_Cyc;
  int Step;
  
  byte ChkAvCnt_DLP3 = 255;  

 
  int direction = 1; //direction of stepper direction
  
  long ErrorCount = 0; //error counter
  //long Error_Count;
  byte ret = 0;
  //checksum error checks
  byte error_chcksum = 0; 

  //alive counter error checks
  byte error_alivecnt = 0; 
  
  long LocalTime[9];
  
  msTimer	TxMsg401;		/* NM Pdu Tx msg */
  
  message 0x401 msg401 = { DLC = 8,DIR = TX, byte(0)=0x01,byte(1)=0x10,byte(2)=0x00,byte(3)=0x00,byte(4)=0x00,byte(5)=0x00,byte(6)=0x00,byte(7)=0x00};
}

on start
{
 setTimer( TxMsg401, 500 );	 
}

on timer TxMsg401
{
  cancelTimer(TxMsg401);
  if(@can::NmPduOnOff==1)
  {
    if(@can::RepeatmessageRequest==1)
    {
      msg401.byte(1)=msg401.byte(1)|0x01;
    }
    else
    {
      msg401.byte(1)=msg401.byte(1)&0xFE;
    }
    output(msg401);
  }

  setTimer( TxMsg401, 500 );
}

on message *   //checks if Rx messages have the correct checksum and Alivecounter
{
  
  dword i;
  long aId;
  byte aDlc;
  byte data[63];
  byte Error_type;
    
  aId = this.id;
  
  switch(aId)  
    {
 
      case 0x2D3:  //DLP_3
        
        if(this.dir == Rx)
        {
          i = this.byte(1) & 0x0F; 
          Get_AliveCounter(i, aId);
          
          if(ret == 1)  //checking for AliveCounter errors
          {
            Error_type = 1; 
            Get_Error(error_alivecnt, aId, Error_type);
            error_alivecnt = 1;
            @can::DLP3_CntErr = 1;
          }
          else
          {
            @can::DLP3_CntErr = 0;
          }

          aDlc = this.dlc;            //getting the DLC
          data[1] = this.byte(1);     //Filling 1st byte of the buffer
          data[2] = this.byte(2);
          data[3] = this.byte(3);
          data[4] = this.byte(4);
          data[5] = this.byte(5);
          data[6] = this.byte(6);
          data[7] = this.byte(7);
          
          data[0] = Crc_8bit_1D(aId,data,aDlc); //Calculating CheckSum
  
          
          if(this.byte(0) != data[0])
          {
            Error_type = 0;                                       //Checking if the CheckSum is correct
            Get_Error(error_chcksum, aId, Error_type);
            error_chcksum = 1;
			@can::DLP3_ChksmErr = 1;
          }
		  else
		  {
			@can::DLP3_ChksmErr = 0;
		  }
        }
        break;
        
    case 0x401:
      break;
        
  default:
        break;     
 
    }
    //putValue(Error_Count, ErrorCount);
    
 
}



dword applILTxPending(long aId, dword aDlc, byte data[])
{
  
  dword i;
  dword ret = 1;
  int index;
  //--- begin generated part --- Block start #Hdr_applILTxPending#; do not delete this line and do not add application code in this code block!
  /* #ChannelStart# |CAN2| #BusStart# |AFLSubCANDD1920| */
  /* #ChannelEnd# |CAN2| #BusEnd# |AFLSubCANDD1920| */
  //--- end generated part --- Block end #Hdr_applILTxPending#; do not delete this line! Add application code below this line.
  //--- begin generated part --- Block start #Body_applILTxPending#; do not delete this line and do not add application code in this code block!
  /* #ChannelStart# |CAN2| #BusStart# |AFLSubCANDD1920| */
  /* #ChannelEnd# |CAN2| #BusEnd# |AFLSubCANDD1920| */
  //--- end generated part --- Block end #Body_applILTxPending#; do not delete this line! Add application code below this line.
  
  
    switch(aId)  
    {
      case 0x2CC:  //BDCM_14_LightCtrl
        
        i = data[1] & 0x0F;     // get the old counter value
        i += @can::BDCM14_Cnt_Step;                    // increment
        i = i % 15;

        
        //data[1] = i & 0x0F;     //set the new message counter
        data[1] = data[1] & 0xF0;
        data[1] = data[1] | i;
        //Calculate CRC
        data[0] = Crc_8bit_1D(aId,data,aDlc);
     
        if(@can::BDCM14_ChksmErr==1)    //error CRC
        {
        //  write("Checksum of %X is not correct", aId);
          data[0] = data[0] | 0xFF;
          break;
        }

        break;        
        
      case 0x130:  //BDCM_RT_3
        
        i = data[1] & 0x0F;     // get the old counter value
        i+=@can::BDCM_RT3_Cnt_Step;                    // increment
        i = i % 15;
        
        //data[1] = i & 0x0F;     //set the new message counter
        data[1] = data[1] & 0xF0;
        data[1] = data[1] | i;

        //Calculate CRC      
        data[0] = Crc_8bit_1D(aId,data,aDlc);
        
        if(@can::BDCM_RT3_ChksmErr ==1)    //error CRC
        {
          data[0] = data[0] | 0xFF;
          break;
        }
        
        break;
        
      case 0x131:  //BDCM_RT_4
        
        i = data[1] & 0x0F;     // get the old counter value
        i+=@can::BDCM_RT4_CntStep;                    // increment
        i = i % 15;
        
        //data[1] = i & 0x0F;     //set the new message counter
        data[1] = data[1] & 0xF0;
        data[1] = data[1] | i;

        //Calculate CRC
        data[0] = Crc_8bit_1D(aId,data,aDlc);
        if(@can::BDCM_RT4_ChksmErr ==1)    //error CRC
        {
          data[0] = data[0] | 0xFF;
          break;
        }
        break;
        
      case 0x132:  //BDCM_RT_5
        
        i = data[1] & 0x0F;     // get the old counter value
        i+=@can::BDCM_RT5_Cnt_Step;                    // increment
        i = i % 15;
        
        //data[1] = i & 0x0F;     //set the new message counter
        data[1] = data[1] & 0xF0;
        data[1] = data[1] | i;

        //Calculate CRC       
        data[0] = Crc_8bit_1D(aId,data,aDlc);
        if(@can::BDCM_RT5_ChksmErr ==1)    //error CRC
        {
          data[0] = data[0] | 0xFF;
          break;
        }
        break;
        
      case 0x133:  //BDCM_RT_6
        
        i = data[1] & 0x0F;     // get the old counter value
        i+=@can::BDCM_RT6_Cnt_Step;                    // increment
        i = i % 15;
        
        //data[1] = i & 0x0F;     //set the new message counter
        data[1] = data[1] & 0xF0;
        data[1] = data[1] | i;
        //Calculate CRC
       
        data[0] = Crc_8bit_1D(aId,data,aDlc);
        if(@can::BDCM_RT6_ChksmErr ==1)    //error CRC
        {
          data[0] = data[0] | 0xFF;
          break;
        }
        break;
        
      case 0x134:  //BDCM_RT_14
        
        i = data[1] & 0x0F;     // get the old counter value
        i+=@can::BDCM_RT14_Cnt_Step;                    // increment
        i = i % 15;
       
        //data[1] = i & 0x0F;     //set the new message counter
        data[1] = data[1] & 0xF0;
        data[1] = data[1] | i;

        //Calculate CRC      
        data[0] = Crc_8bit_1D(aId,data,aDlc);
        if(@can::BDCM_RT14_ChksmErr ==1)    //error CRC
        {
          data[0] = data[0] | 0xFF;
          break;
        }

        break;
        
      case 0x1D6:  //BDCM_RT_30
        
        i = data[1] & 0x0F;     // get the old counter value
        i+=@can::BDCM_RT30_Cnt_Step;                    // increment
        i = i % 15;
       
        //data[1] = i & 0x0F;     //set the new message counter
        data[1] = data[1] & 0xF0;
        data[1] = data[1] | i;

        //Calculate CRC      
        data[0] = Crc_8bit_1D(aId,data,aDlc);
        if(@can::BDCM_RT30_ChksmErr ==1)    //error CRC
        {
          data[0] = data[0] | 0xFF;
          break;
        }
        break;
        
      case 0x138:  //BDCM_RT_31
        
        i = data[1] & 0x0F;     // get the old counter value
        i+=@can::BDCM_RT31_Cnt_Step;                    // increment
        i = i % 15;

        data[1] = data[1] & 0xF0;
        data[1] = data[1] | i;

        //Calculate CRC      
        data[0] = Crc_8bit_1D(aId,data,aDlc);
        if(@can::BDCM_RT31_ChksmErr ==1)    //error CRC
        {
          data[0] = data[0] | 0xFF;
          break;
        }
        break;
        
      case 0x360:  //BDCM_RT_2
        if(@can::Get_LocalTime){
          getLocalTime(LocalTime);
          data[0] = LocalTime[5]-70;//Year
          data[1] = (LocalTime[4]+1);//Month
          data[2] = LocalTime[3];//Day
          data[3] = LocalTime[2];//Hour
          data[4] = LocalTime[1];//Minute
          data[5] = LocalTime[0];//Second
        }
        break;
     default:
        break;   
    }  
     
    return ret;
  
}

on sysvar can::Get_LocalTime2
{
  if( @can::Get_LocalTime2 ){
    getLocalTime(LocalTime);
    setSignal(IDCM_FestivalLightShowSet_Year, LocalTime[5]+1900);//year
    setSignal(IDCM_FestivalLightShowSet_Month, LocalTime[4]+1);//Month
    setSignal(IDCM_FestivalLightShowSet_Day, LocalTime[3]);//Day
  }
}

on sysvar_update can::TL_Ind_Cmd
{
  if(@can::TL_Ind_Cmd==1)
  {
    setSignal(BDCM_LeftTurnLamp_Cmd, 1);
    setSignal(BDCM_RightTurnLamp_Cmd, 1);
    setTimer(Timer_TI_off, @can::TL_Ind_CycTm);
  }
  if(@can::TL_Ind_Cmd==0)
  {
    cancelTimer(Timer_TI_on);
    cancelTimer(Timer_TI_off);
    setSignal(BDCM_LeftTurnLamp_Cmd, 0);
    setSignal(BDCM_RightTurnLamp_Cmd, 0);
  }
}

on timer Timer_TI_off
{
  setSignal(BDCM_LeftTurnLamp_Cmd, 0);
  setSignal(BDCM_RightTurnLamp_Cmd, 0);
  setTimer(Timer_TI_on, @can::TL_Ind_CycTm);
}

on timer Timer_TI_on
{
  setSignal(BDCM_LeftTurnLamp_Cmd, 1);
  setSignal(BDCM_RightTurnLamp_Cmd, 1);
  setTimer(Timer_TI_off, @can::TL_Ind_CycTm);
}

word Get_AliveCounter(byte AliveCounter, long aId)
{  
    ret = 0;

    switch(aId)
    {
      case 0x2D3:

        if(ChkAvCnt_DLP3 == 255)
        {
          ChkAvCnt_DLP3 = AliveCounter;
        }
        if(ChkAvCnt_DLP3 != AliveCounter)
        {
          //write("AliveCounter at %X is: %d", aId, AliveCounter);
          //Write("Check at %X is: %d", aId, ChkAvCnt_DLP3);
          
          ret = 1;
          ChkAvCnt_DLP3 = AliveCounter;
          ChkAvCnt_DLP3++;
        }
        else
        {
          ChkAvCnt_DLP3++;
        }
        if(ChkAvCnt_DLP3 > 14)
        {
          ChkAvCnt_DLP3 = 0; 
        }        
        
       break;
        
      
      default:
          break;
   }
   return ret;
}

void Get_Error(byte is_error, long aId, byte Error_type)
{
    if(is_error == 0)
    {
      ErrorCount++;
      if(Error_type == 0)
      {   
        write("Error no. %d found at message %X , CHECKSUM", ErrorCount, aId);     
      }
      else if(Error_type == 1)
      {
        write("Error no. %d found at message %X , ALIVECOUNTER", ErrorCount, aId);
      }
      
    }
    else
    {
      
    }
}

on busOff
{
 
  // Resets the CAN controller. Can be used to reset the CAN controller after a BUSOFF or to activate configuration changes.
  //   Since execution of the function takes some time and the CAN controller is disconnected from the bus briefly, messages can be lost when this is performed.
  // Note: With this function you can reset CAN1 and CAN2.
  //   If only one specific CAN channel is used, resetCan stops with an error and the CAN channels keep offline.
  //   In this case the ResetCanEx function has to be used.
  // The function resetCanEx can be used for all channels.
  resetCan();

}
