/*!
* @file     CanHelpers.h
*
* @brief    Helper functions for testing the CAN driver.
*/

#ifndef CAN_HELPERS_H
#define CAN_HELPERS_H

#include "Can.h"
#include "CanIf_Types.h"
#include "Std_Types.h"
#include "SchM_Can.h"

/* The baudrate IDs defined in the configuration */
#define BAUDRATE_100K       100
#define BAUDRATE_1M_4M      1040

typedef enum
{
    SUCCESSFUL = 0U,
    FAILED
} RunResult;

typedef struct  /* Structure to store received CAN frames */
{
    uint32              timestamp;
    Can_IdType          canId;          /* Standard/Extended CAN ID of CAN L-PDU. */
    Can_HwHandleType    hoh;            /* ID of the corresponding Hardware Object Range */
    uint8               controllerId;   /* ControllerId provided by CanIf clearly identify the corresponding controller */
    PduLengthType       sduLength;      /* length of the SDU in bytes */
    uint8               sduData[64];    /* pointer to the SDU (i.e. payload data) of the PDU */
} CanRxFrameType;

typedef struct  /* Structure to store the TX confirmations */
{
    uint32      timestamp;
    uint8       txConfirmed;
    PduIdType   pduId;
} TxConfirmedType;

typedef struct  /* Structure to store the controller mode indications */
{
    uint8                       controllerId;
    CanIf_ControllerModeType    mode;
} ControllerModeType;

typedef struct  /* Structure to store the Icom notifications */
{
    uint8                   callback;
    uint8                   controllerId;
    IcomConfigIdType        configId;
    IcomSwitch_ErrorType    error;
} IcomStateType;

#define MAX_RX_FRAMES   10

extern CONST(Can_ConfigType, CAN_CONST) g_canConfig;
extern CanRxFrameType g_rxBuffer[MAX_RX_FRAMES];
extern uint8 g_rxCount;
extern TxConfirmedType g_txConfirm;
extern ControllerModeType g_controllerMode;
extern uint8 g_busOff;
extern IcomStateType g_icomState;
extern Can_DriverStatusType g_canDriverStatus;
extern uint8 g_lpduCalloutCounter;
extern boolean g_lpduCalloutReturn;
extern Can_PduType g_pdu1;
extern Can_PduType g_pdu2;
extern Can_PduType g_pdu3;
extern Can_PduType g_pdu4;
extern Can_PduType g_pdu5;
extern Can_PduType g_pdu6;
extern Can_PduType g_pdu7;
extern Can_PduType g_pdu8;
extern Can_PduType g_pdu8_2;
extern Can_PduType g_pdu64;
extern Can_PduType g_pdu64_2;

void Setup(void);
void Teardown(void);
RunResult Can0_FD_Tx(void);
RunResult Can0_FD_Rx(void);
void ResetTxConfirmation();
void ResetRxIndication();
void ResetControllerModeIndication();
void ResetBusOffIndication();
void ResetErrorNotification();
void ResetCanfdErrorNotification();
void ResetFifoWarning();
void ResetFifoOverflow();
void ResetIcomNotification();
void SysDelay(int Count);

/* Verify if the CAN ID matches expected value */
boolean VerifyCanId(Can_IdType CanId, Can_IdType ExpectedCanId);
boolean VerifyRxCanId(Can_IdType CanId, Can_IdType ExpectedCanId);

/* Verify if the CAN driver status matches expected value */
boolean VerifyDriverStatus(Can_DriverStatusType ExpectedState);

/* Verify if the CAN controller state matches expected value */
boolean VerifyControllerState(Can_ControllerStateType State, Can_ControllerStateType ExpectedState);

/* Verify if the CAN controller error state matches expected value */
boolean VerifyControllerErrorState(Can_ErrorStateType State, Can_ErrorStateType ExpectedState);

/* Verify if the register value matches expected value */
boolean VerifyRegister(const char* Name, uint32 Value, uint32 ExpectedValue);

/* Verify if the interrupt disable level matches expected value */
boolean VerifyInterruptDisableLevel(uint8 ControllerId, sint8 ExpectedValue);

/* Verify a CAN frame */
boolean VerifyCanFrame(Can_IdType CanId, Can_IdType ExpectedCanId, uint8 Length, uint8 Expectedength,
                       const uint8* Data, const uint8* ExpectedData);

/* Verify the number of received CAN frames */
boolean VerifyRxCount(uint8 ExpectedRxCount);

/* Verify if multiple CAN frames in the receive buffer matches the expected buffer */
boolean VerifyRxCanFrames(Can_PduType** ExpectedPduBuffer, uint8 ExpectedPduCount);

/* Verify if the version info is correct */
boolean VerifyVersionInfo(Std_VersionInfoType VersionInfo);

/* Verify if the callback function CanIf_TxConfirmation() has been called */
boolean VerifyTxConfirmation(PduIdType PduId);

/* Verify that the callback function CanIf_TxConfirmation() was not called */
boolean VerifyNoTxConfirmation();

/* Verify if the callback function CanIf_RxIndication() has been called */
boolean VerifyRxIndication(uint8 ControllerId, Can_HwHandleType Hoh, const Can_PduType* RxPdu);

/* Verify that the callback function CanIf_RxIndication() was not called */
boolean VerifyNoRxIndication();

/* Verify if the bus off event happened */
boolean VerifyBusOffEvent(uint8 ControllerId);

/* Verify that there was no bus off event */
boolean VerifyNoBusOffEvent();

/* Verify the error notification callback was called */
boolean VerifyErrorNotification();

/* Verify the CAN FD error notification callback was called */
boolean VerifyCanfdErrorNotification();

/* Verify the error notification callback was not called */
boolean VerifyNoErrorNotification();

/* Verify if the callback function CanIf_ControllerModeIndication() has been called */
boolean VerifyControllerModeIndication(uint8 ControllerId, CanIf_ControllerModeType ControllerMode);

/* Verify if the FIFO warning event happened */
boolean VerifyFifoWarning();

/* Verify if the FIFO overflow event happened */
boolean VerifyFifoOverflow();

/* Verify if the callback function CanIf_CurrentIcomConfiguration() has been called */
boolean VerifyIcomNotification(uint8 ControllerId, IcomConfigIdType ConfigurationId, IcomSwitch_ErrorType Error);

/* Verify if the LPDU callout function has been called */
boolean VerifyLPduCallout();

/* Verify if an byte array matches expected value */
boolean VerifyBuffer(const uint8* Buf, uint32 BufSize,
                     const uint8* ExpectedBuf, uint32 ExpectedBufSize,
                     const char* Name);
boolean VerifyRxBuffer(const uint8* Buf, uint32 BufSize,
                     const uint8* ExpectedBuf, uint32 ExpectedBufSize,
                     const char* Name);

/* Print a CAN frame */
void PrintCanFrame(const char* Message, const Can_PduType* PduPtr);

/* Print an array of bytes */
void PrintBytes(const char* Message, const uint8* Buf, uint32 BufSize);

/* Put the MCU to sleep mode */
void GoToSleep();

#endif /* CAN_HELPERS_H */
