//******************************************************************************
//
//                          ComCanCrc.c
//
//******************************************************************************
//
//               Copyrights(c) 2013 by KNORR-BREMSE,
//           Systeme fuer Schienenfahrzeuge GmbH, Muenchen
//
//! @package ComCan
//! @library IBC_FWK
//! @author Heramb Phadke
//!
//! $LastChangedDate: 2017-03-31 17:35:45 +0530 (Fri, 31 Mar 2017) $
//! $LastChangedRevision: 82 $
//! $LastChangedBy: gaurde $
//!
//******************************************************************************
//!
//! @file
//! @brief File for 8-bit CRC of CAN id
//! This module contains the functions to calculate and check 8-bit CRC of
//! IBC CAN message.
//******************************************************************************
//
// History
// Date        Author          Changes
// 2013-07-09  Heramb Phadke   Created the file to calculate and check
//                             CRC of 29-bit CAN id
// 2013-07-11  C. Bhor         Added const to parameters of all functions
//                             Changed return type of functions to S16
// 2013-07-16  C. Bhor         Updated all functions for
//                             Changed return type of functions to S16
// 2013-07-17  Heramb Phadke   Changes as per coding guidelines
// 2013-08-21  C. Bhor         Adapted all functions for CoCheck
// 2013-11-06  C. Bhor         Adapted all functions for vCoCheck and
//                             CO_ERROR_AGGREGATE & CO_IS_NO_ERROR
// 2013-11-22  C. Bhor         Adapted all functions for vCoCheck_CtPtr
//                             and CO_CHECK_RANGE
// 2013-11-27  C. Bhor         Minor corrections to remove compiler
//                             warnings
// 2013-12-11  Heramb Phadke   Modifications as per the LINT messages.
// 2014-05-14  C. Bhor         CO_CHECK_RANGE replaced by CO_CHECK_MAX in
//                             all functions
// 2014-06-17  C. Bhor         Added cRevFwk_ComCanCrc
// 2014-07-08  C. Amrutkar     vCoCheck_CtStructPtr function used for
//                             NULL pointer check of const pointer
// 2014-07-17  C. Amrutkar     Code Clean up for lint
// 17.06.2014  C. Bhor         1.10  Added cRevFwk_ComCanCrc
//******************************************************************************

/*********************** Compiler options ( #pragma ) ***********************/
#define CO_IBC_FIRMWARE 1

/******************* Header / include files ( #include ) ********************/
#include "ComCanCrc.h"
#include "ComUtilCrc8.h"
#include "CoErrno.h"
#include "CoCheck.h"

/*********************** Type definitions ( typedef ) ***********************/

/************************* Global data definitions **************************/
#ifdef MODULTEST
const char cRevFwk_ComCanCrc[] ="$Revision: 82 $";
#else

#endif

/****************** Global constant definitions ( const ) *******************/

/******************* Modul global data segment ( static ) *******************/

/***************** Modul global constants ( static const ) ******************/
#define CANID_BYTE3_MASK        ( ( U32 ) 0x1F000000 )
#define CANID_BYTE2_MASK        ( ( U32 ) 0x00FF0000 )
#define CANID_BYTE1_MASK        ( ( U32 ) 0x0000FF00 )
#define CANID_BYTE0_MASK        ( ( U32 ) 0x000000FF )

#define CANID_BYTE_3_SHIFT      ( 24U )
#define CANID_BYTE_2_SHIFT      ( 16U )
#define CANID_BYTE_1_SHIFT      ( 8U )

#define CANID_BYTES_IN_CRC      ( ( U8 ) 3 )

#define CAN_PAYLOAD_MAX         ( ( U8 ) 8 )

#define CAN_ID_VALUE_MAX        ( ( U32 ) 0x1FFFFFFF )
/****************** Local func/proc prototypes ( static ) *******************/

/** EndOfHeader *************************************************************/

/** Function definitions ******************************************************/

/****************************************************************************/
S16 s16ComCanCRC_Calc
(
    const U8* const pu8Payload,
    const U8 u8PayloadSize,
    U32* const pu32CanId
)
{
    /*
     * Initialization of local variables
     */
    S16 s16AggregatedError = CO_ERROR_NONE;
    U8 u8Index;
    U8 u8Checksum = (U8) 0U;
    U8 u8Buffersize;
    U8 u8DataBuffer[11] = { 0U };

    //! Check Pointers parameters only for Component Testing
    vCoCheck_CtStructPtr((void*) pu8Payload, CO_ERROR_FATAL, &s16AggregatedError);

    vCoCheck_CtStructPtr((void*) pu32CanId, CO_ERROR_FATAL, &s16AggregatedError);

    CO_CHECK_MAX(s16AggregatedError, CO_ERROR_ARG, u8PayloadSize, CAN_PAYLOAD_MAX);

    if (CO_IS_NO_ERROR( s16AggregatedError ))
    {
        // Copy all payload data bytes to buffer if any
        for (u8Index = 0U; u8Index < u8PayloadSize; u8Index++)
        {
            u8DataBuffer[u8Index] = pu8Payload[u8Index];
        }

        // process CAN Id byte 3(Bit 28 to Bit 24 with filled bits 000)
        u8DataBuffer[u8Index] = (U8) ((*pu32CanId & CANID_BYTE3_MASK) >> CANID_BYTE_3_SHIFT);
        u8Index++;

        // process CAN Id byte 2(Bit 23 to Bit 16)
        u8DataBuffer[u8Index] = (U8) ((*pu32CanId & CANID_BYTE2_MASK) >> CANID_BYTE_2_SHIFT);
        u8Index++;

        // process CAN Id byte 1(Bit 15 to Bit 8)
        u8DataBuffer[u8Index] = (U8) ((*pu32CanId & CANID_BYTE1_MASK) >> CANID_BYTE_1_SHIFT);

        // Get Buffer size
        u8Buffersize = u8PayloadSize + CANID_BYTES_IN_CRC;

        // Calculate Checksum
        s16AggregatedError = s16ComUtilCrc8_Calc(&u8DataBuffer[0], u8Buffersize, &u8Checksum);

        //initialize CRC to zero
        *pu32CanId &= ~(CANID_BYTE0_MASK);

        // fill CAN id with calculated checksum
        *pu32CanId |= (U32) ((U32) u8Checksum & CANID_BYTE0_MASK);

    }
    else
    {
        // nothing to do
    }

    return (s16AggregatedError);
}

/****************************************************************************/
S16 s16ComCanCRC_Check
(
    const U8* const pu8Payload,
    const U8 u8PayloadSize,
    const U32 u32CanId
)
{
    // Initialization of local variables
    S16 s16AggregatedError = CO_ERROR_NONE;
    U8 u8Index;
    U8 u8Checksum;
    U8 u8Buffersize;
    U8 u8DataBuffer[11] = {0U};

    //! Check inputs parameters
    //! Check Pointers parameters only for Component Testing
    vCoCheck_CtStructPtr((void*) pu8Payload, CO_ERROR_FATAL, &s16AggregatedError);

    CO_CHECK_MAX(s16AggregatedError, CO_ERROR_ARG, u8PayloadSize, CAN_PAYLOAD_MAX);

    CO_CHECK_MAX(s16AggregatedError, CO_ERROR_ARG, u32CanId, CAN_ID_VALUE_MAX);

    if (CO_IS_NO_ERROR( s16AggregatedError ))
    {
        // Copy all payload data bytes to buffer if any
        for (u8Index = 0U; u8Index < u8PayloadSize; u8Index++)
        {
            u8DataBuffer[u8Index] = pu8Payload[u8Index];
        }

        // process CAN Id byte 3(Bit 28 to Bit 24 with filled bits 000)
        u8DataBuffer[u8Index] = (U8) ((u32CanId & CANID_BYTE3_MASK) >> CANID_BYTE_3_SHIFT);
        u8Index++;

        // process CAN Id byte 2(Bit 23 to Bit 16)
        u8DataBuffer[u8Index] = (U8) ((u32CanId & CANID_BYTE2_MASK) >> CANID_BYTE_2_SHIFT);
        u8Index++;

        // process CAN Id byte 1(Bit 15 to Bit 8)
        u8DataBuffer[u8Index] = (U8) ((u32CanId & CANID_BYTE1_MASK) >> CANID_BYTE_1_SHIFT);

        // Extract Checksum
        u8Checksum = (U8) (u32CanId & CANID_BYTE0_MASK);

        // Get Buffer size
        u8Buffersize = u8PayloadSize + CANID_BYTES_IN_CRC;

        // Verify Checksum
        s16AggregatedError = s16ComUtilCrc8_Check(&u8DataBuffer[0], u8Buffersize, u8Checksum);

        if (s16AggregatedError == COMUTIL_CRC8_VALID)
        {
            s16AggregatedError = COMCAN_CRC_VALID;
        }
        else
        {
            //Do Nothing
        }
    }
    else
    {
        // nothing to do
    }
    return (s16AggregatedError);
}

/** EndOfFile ComCanCrc.c *************************************************/
