/*@!Encoding:936*/
includes
{

}

variables
{
  char TPRevData[20] = "TPReceiveData";
  
  /****************TP Handle****************/
  long connHandle;
  long funcHandle;
  
  /****************TP Times*****************/
  int tmpBlockSize;
  int tmpSTmin;            //STmin
  int tmpN_AS;             //N_AS
  int tmpN_AR;             //N_AR
  int tmpN_BS;             //N_BS;
  int tmpN_BR;             //N_BR;
  int tmpN_CS;             //N_CS;
  int tmpN_CR;             //N_CR;
  
  /******************TP*********************/
  const int BlockSize = 0;
  const int STmin = 0x14;
  const int N_AS = 0x258;
  const int N_AR = 0x258;
  const int N_BS = 0x3E8;
  const int N_BR = 0xC8;
  const int N_CS = 0xC8;
  const int N_CR = 0x3E8;
  const byte UDSpadding = 0x00;
  
  long P2Server;
  long P2Client = 4000;
  long P2exClient = 5000;
  long P2ServerDelay;
  long P2ClientDelay;
  long S3Server;
  long S3Client;
  
  enum ResponseState{Timeout, Pos, Neg};
  enum AddressMode{physical, functional};
}

void InitDiagConfig()
{
  tmpBlockSize = BlockSize;
  tmpSTmin = STmin;
  tmpN_AS = N_AS;
  tmpN_AR = N_AR;
  tmpN_BS = N_BS;
  tmpN_BR = N_BR;
  tmpN_CS = N_CS;
  tmpN_CR = N_CR;
  CanTP_PHY_Config(PhyAddr, RespAddr);
  CanTP_FUN_Config(FuncAddr, RespAddr);
  testWaitForTimeout(1000);
}

long CanTP_PHY_Config(dword SourceID, dword TargetID)
{
  int DiagMode = 0;
  int AddrMode = 0;
  connHandle = CanTpCreateConnection(DiagMode);
  
  CanTpSetTxIdentifier(connHandle, SourceID);
  CanTpSetRxIdentifier(connHandle, TargetID);
  //CanTpSetMaxCANFDFrameLength(connHandle, 64);
 // CanTpSetBitRateSwitch(connHandle, 1);
  CanTpIsUseFlowControlFrames(connHandle);
  //CanTpSetFlowControlDelay(connHandle, 10);
  CanTpSetSTmin(connHandle, tmpSTmin);
  //CanTpUseFlowControlSTmin(connHandle, 0);
  CanTpSetBlockSize(connHandle, tmpBlockSize);
  CanTpSetAddressType(connHandle, AddrMode);
  CanTpSetTimeoutAs(connHandle, tmpN_AS);
  CanTpSetTimeoutAr(connHandle, tmpN_AR);
  CanTpSetTimeoutBs(connHandle, tmpN_BS);
  CanTpSetTimeBr(connHandle, tmpN_BR);
  CanTpSetTimeCs(connHandle, tmpN_CS);
  CanTpSetTimeoutCr(connHandle, tmpN_CR);
  CanTpSetPadding(connHandle, UDSpadding);
  return connHandle;
}


long CanTP_FUN_Config(dword SourceID, dword TargetID)
{
  int DiagMode = 0;
  int AddrMode = 1;
  funcHandle = CanTpCreateConnection(DiagMode);
  
  CanTpSetTxIdentifier(funcHandle, SourceID);
  CanTpSetRxIdentifier(funcHandle, TargetID);
 // CanTpSetMaxCANFDFrameLength(funcHandle, 64);
//  CanTpSetBitRateSwitch(funcHandle, 1);
  CanTpSetAddressType(funcHandle, AddrMode);
  //¹¦ÄÜÑ°Ö·
  CanTpUseFlowControlFrames(funcHandle, 0);
  CanTpSetTimeoutAs(funcHandle, tmpN_AS);
  CanTpSetTimeoutAr(funcHandle, tmpN_AR);
  CanTpSetTimeoutBs(funcHandle, tmpN_BS);
  CanTpSetTimeBr(funcHandle, tmpN_BR);
  CanTpSetTimeCs(funcHandle, tmpN_CS);
  CanTpSetTimeoutCr(funcHandle, tmpN_CR);
  CanTpSetPadding(funcHandle, UDSpadding);
  return funcHandle;
}

void CanTp_ReceptionInd(long connHandle, byte data[])
{
  RevSize = elcount(data);
  memcpy(RevData, data, RevSize);
  write( "Recieve %d ,[%02x] ... ", connHandle, data[0]);
  testSupplyTextEvent(TPRevData);
}

int CanTP_Send(byte Data[], dword len, enum AddressMode Addr)
{
  testWaitForTimeout(5);
  if(Addr == 0)
  {
    CanTpSendData(connHandle, Data, len);
  }
  else
  {
    CanTpSendData(funcHandle, Data, len);
  }
  return 1;
}

enum ResponseState ECU_Response(dword P2)
{

  if(testWaitForTextEvent(TPRevData, P2) == 0){
    return Timeout;
  }
    
  if(RevData[0] == 0x7f)
  {
    switch(RevData[2])
    {
      case 0x78:
        return ECU_Response(P2exClient);
        break;
      default:
        return Neg;
        break;
    }
  }
  
  if(RevData[0] == 0x71)
  {
    if(RevData[4] == 0x01)
    {
      return Neg;
    }
    else
    {
      /* do nothing */
    }
  }
  else
  {
    /* do nothing */
  }
  
  if(RevData[0] == 0x77)
  {
    if(CurrentFlashedBlk == FlashDrvBlk)
    {
      CRC16BUF_TEMP[0] = CRC16BUF_DRIVER[0];
      CRC16BUF_TEMP[1] = CRC16BUF_DRIVER[1];
    }
    if(CurrentFlashedBlk == FlashFBLBlk)
    {
      CRC16BUF_TEMP[0] = CRC16BUF_FBL[0];
      CRC16BUF_TEMP[1] = CRC16BUF_FBL[1];
    }
     if(CurrentFlashedBlk == FlashAppBlk)
    {
      CRC16BUF_TEMP[0] = CRC16BUF_APP[0];
      CRC16BUF_TEMP[1] = CRC16BUF_APP[1];
    }
     if(CurrentFlashedBlk == FlashCodBlk)
    {
      CRC16BUF_TEMP[0] = CRC16BUF_CAL[0];
      CRC16BUF_TEMP[1] = CRC16BUF_CAL[1];
    }
    if((CRC16BUF_TEMP[0] == RevData[1]) && (CRC16BUF_TEMP[1] == RevData[2]))
    {
      write("CRC16 Verify Passed");
      write("CRC16 MSB Byte on PC: %X",CRC16BUF_TEMP[0]);
      write("CRC16 LSB Byte on PC: %X",CRC16BUF_TEMP[1]);
      write("CRC16 MSB Byte from ECU: %X",RevData[1]);
      write("CRC16 LSB Byte from ECU: %X",RevData[2]);
      /*CRC16 verify passed on PC Tester side*/
    }
    else
    {
      /*CRC16 verify failed on PC Tester side*/
      write("CRC16 Verify Failed");
      write("CRC16 MSB Byte on PC: %X",CRC16BUF_TEMP[0]);
      write("CRC16 LSB Byte on PC: %X",CRC16BUF_TEMP[1]);
      write("CRC16 MSB Byte from ECU: %X",RevData[1]);
      write("CRC16 LSB Byte from ECU: %X",RevData[2]);
      return Neg;
    }
  }
  
  return Pos;
}

long CanTp_Close(enum AddressMode Addr)
{
  if(Addr == physical)
    return CanTpCloseConnection(connHandle);
  
  return CanTpCloseConnection(funcHandle);
}

