/*==================================================================================================
*   Project              : RTD AUTOSAR 4.4
*   Platform             : CORTEXM
*   Peripheral           : S32K3XX
*   Dependencies         : none
*
*   Autosar Version      : 4.4.0
*   Autosar Revision     : ASR_REL_4_4_REV_0000
*   Autosar Conf.Variant :
*   SW Version           : 1.0.0
*   Build Version        : S32K3_RTD_1_0_0_D2110_ASR_REL_4_4_REV_0000_20211007
*
*   (c) Copyright 2020 - 2021 NXP Semiconductors
*   All Rights Reserved.
*
*   NXP Confidential. This software is owned or controlled by NXP and may only be
*   used strictly in accordance with the applicable license terms. By expressly
*   accepting such terms or by downloading, installing, activating and/or otherwise
*   using the software, you are agreeing that you have read, and that you agree to
*   comply with and are bound by, such license terms. If you do not agree to be
*   bound by the applicable license terms, then you may not retain, install,
*   activate or otherwise use the software.
==================================================================================================*/

/**
 *   @file main.c
 *
 *   @addtogroup main_module main module documentation
 *   @{
 */

/* Including necessary configuration files. */
#include "Mcal.h"
#include "CAN.h"
#include "SchM_Can.h"
#include "Mcu.h"
#include "Mcl.h"
#include "Port.h"
#include "Dio.h"
#include "Uart.h"
#include "Platform.h"
#include "Lpuart_Uart_Ip_Irq.h"
#include "Flexio_Uart_Ip_Irq.h"
// extern ISR(CAN0_ORED_IRQHandler);
// extern ISR(CAN0_ORED_0_31_MB_IRQHandler);
// extern ISR(CAN0_ORED_32_63_MB_IRQHandler);
// extern ISR(CAN0_ORED_64_95_MB_IRQHandler);
// extern ISR(CAN1_ORED_IRQHandler);
// extern ISR(CAN1_ORED_0_31_MB_IRQHandler);
// extern ISR(CAN1_ORED_32_63_MB_IRQHandler);

/* User includes */

#include "hal_adapter.h"
#include "AppTaskBle.h"
/* Length of the message to be received from the console */
/*the Rx buffer need to be put in non cacheable section when cache enabled*/
/*==================================================================================================
*                          LOCAL TYPEDEFS (STRUCTURES, UNIONS, ENUMS)
==================================================================================================*/

/*==================================================================================================
*                                       LOCAL MACROS
==================================================================================================*/

/*==================================================================================================
*                                      LOCAL CONSTANTS
==================================================================================================*/

/*==================================================================================================
*                                      LOCAL VARIABLES
==================================================================================================*/

/*==================================================================================================
*                                      GLOBAL CONSTANTS
==================================================================================================*/

uint8 Can_au8Sdu8bytes[8U] = {0x01U, 0x02U, 0x03U, 0x04U, 0x05U, 0x06U, 0x07U, 0x08};
volatile uint8 pinValue = STD_LOW;
uint8 dummyData[64] = {1, 2, 3, 4, 5, 6, 7, 8};

/*==================================================================================================
*                                      GLOBAL VARIABLES
==================================================================================================*/
uint8 CanIf_u8TxConfirmCnt = 0U;
boolean CanIf_bTxFlag = FALSE;
uint8 CanIf_u8RxIndicationCnt = 0U;
boolean CanIf_bRxFlag = FALSE;

/*==================================================================================================
*                                   LOCAL FUNCTION PROTOTYPES
==================================================================================================*/
void TestDelay(uint32 delay);

/*==================================================================================================
*                                       LOCAL FUNCTIONS
==================================================================================================*/

/*==================================================================================================
*                                       GLOBAL FUNCTIONS
==================================================================================================*/
#if 1
typedef enum
{
    CAN_STANDARD_ID_TYPE = 0x00,   /**< * -00b CAN message with Standard CAN ID  */
    CANFD_STANDARD_ID_TYPE = 0x01, /**< * -01b CAN FD frame with Standard CAN ID  */
    CAN_EXTENDED_ID_TYPE = 0x02,   /**< * -10b CAN message with Extended CAN ID  */
    CANFD_EXTENDED_ID_TYPE = 0x03, /**< * -11b CAN FD frame with Extended CAN ID  */
} CAN_IdFrameType;

typedef struct
{
    Can_IdType id;

    CAN_IdFrameType idFrame;

    uint8 length; /**< @brief DLC = Data Length Code (part of L-PDU that describes
                                            the SDU length). */
    uint8 *sdu;   /**< @brief CAN L-SDU = Link Layer Service Data
                                                           Unit. Data that is transported inside
                                                           the L-PDU. */
} Can_Msg_Type;

Can_Msg_Type canRxMsg_Buff[100];

Can_PduType Can_CreatePduInfo(Can_IdType id, CAN_IdFrameType idFrame, PduIdType swPduHandle, uint8 length, uint8 *sdu)
{
    Can_PduType PduInfo;
    switch (idFrame)
    {
    case CAN_STANDARD_ID_TYPE:
        id = id & 0x7FF;
        break;
    case CANFD_STANDARD_ID_TYPE:
        id = (id & 0x7FF) | 0x40000000;
        break;
    case CAN_EXTENDED_ID_TYPE:
        id = id | 0x80000000;
        break;
    case CANFD_EXTENDED_ID_TYPE:
        id = id | 0xC0000000;
        break;
    default:
        id = id & 0x7FF;
        break;
    }
    PduInfo.id = id;
    PduInfo.swPduHandle = swPduHandle;
    PduInfo.length = length;
    PduInfo.sdu = sdu;

    return PduInfo;
}

Can_Msg_Type Can_GetMsgInfo(Can_IdType id, uint8 length, uint8 *sdu)
{
    Can_Msg_Type CanMsgInfo;

    CanMsgInfo.idFrame = (CAN_IdFrameType)((id >> 30) & 0x03);
    if (CanMsgInfo.idFrame & 0x01)
    {
        CanMsgInfo.id = id & 0x7FF;
    }
    else
    {
        CanMsgInfo.id = id & 0x1FFFFFFF;
    }
    CanMsgInfo.length = length;
    CanMsgInfo.sdu = sdu;

    return CanMsgInfo;
}

void CanIf_ControllerBusOff(uint8 ControllerId)
{
    (void)ControllerId;
}

void CanIf_ControllerModeIndication(uint8 ControllerId, Can_ControllerStateType ControllerMode)
{
    (void)ControllerId;
    (void)ControllerMode;
}
void CanIf_TxConfirmation(PduIdType CanTxPduId)
{
    CanIf_u8TxConfirmCnt++;
    CanIf_bTxFlag = TRUE;
    (void)CanTxPduId;
}

void CanIf_RxIndication(const Can_HwType *Mailbox, const PduInfoType *PduInfoPtr)
{

    CanIf_bRxFlag = TRUE; // should not be delete
    //    (void)Mailbox;
    //    (void)PduInfoPtr;

    // should put the msg into message quene
    canRxMsg_Buff[CanIf_u8RxIndicationCnt] = Can_GetMsgInfo(Mailbox->CanId, PduInfoPtr->SduLength, PduInfoPtr->SduDataPtr);
    CanIf_u8RxIndicationCnt++;
}

void CanIf_CurrentIcomConfiguration(uint8 ControllerId, IcomConfigIdType ConfigurationId, IcomSwitch_ErrorType Error)
{
    (void)ControllerId;
    (void)ConfigurationId;
    (void)Error;
}

void Can_DummyDelay(uint32 loops)
{
    VAR(volatile uint32, CAN_VAR)
    data = 0xAA55AA55;
    VAR(volatile uint32, CAN_VAR)
    contor1 = 0;
    VAR(volatile uint32, CAN_VAR)
    contor2 = loops;

    do
    {
        for (contor1 = 0; contor1 < 0x2FF; contor1++)
        {
            data ^= (1 << contor1) | (0xAAAAAA | contor2);
        }
        contor2--;
    } while (contor2 > 0);
}

Std_ReturnType CanIf_SendMessage(uint8 ControllerId, Can_Msg_Type CanMsg)
{
    volatile Can_PduType Can_PduInfo;
    volatile Std_ReturnType CAN_Write_Status;
    Std_ReturnType retVal = E_NOT_OK;
    uint8 u8TimeOut = 100U;
    Can_HwHandleType Hth = Can0HardwareObject_TX + (Can_HwHandleType)ControllerId; // controller 0 --> Can0HardwareObject_TX

    Can_PduInfo = Can_CreatePduInfo(CanMsg.id, CanMsg.idFrame, 0, CanMsg.length, CanMsg.sdu);

    CAN_Write_Status = Can_Write(Hth, &Can_PduInfo);

    CanIf_bTxFlag = FALSE;
    if (CAN_Write_Status == E_OK)
    {
        while ((!CanIf_bTxFlag) && (u8TimeOut != 0U))
        {
            Can_MainFunction_Write();
            Can_DummyDelay(100U);
            u8TimeOut--;
        }
    }

    if (CanIf_bTxFlag == TRUE)
    {
        retVal = E_OK;
    }
    else
    {
        retVal = E_NOT_OK;
    }
    return retVal;
}

#endif

void TestDelay(uint32 delay)
{
    static volatile uint32 DelayTimer = 0;
    while (DelayTimer < delay)
    {
        DelayTimer++;
    }
    DelayTimer = 0;
}

// boolean User_Str_Cmp(const uint8 * txBuffer1, const uint8 * txBuffer2, const uint32 length)
//{
//     uint32 idx = 0;
//     for (idx = 0; idx < length; idx++)
//     {
//         if(txBuffer1[idx] != txBuffer2[idx])
//         {
//             return FALSE;
//         }
//     }
//     return TRUE;
// }

/*!
  \brief The main function for the project.
  \details The startup initialization sequence is the following:
 * - startup asm routine
 * - main()
*/
int main(void)
{
    /* Write your code here */
    volatile Std_ReturnType T_Uart_Status1;
    volatile Std_ReturnType T_Uart_Status2;
    volatile Std_ReturnType T_Uart_Status3;
    volatile Std_ReturnType R_Uart_Status1;
    volatile Std_ReturnType R_Uart_Status2;
    static Can_Msg_Type Can_MsgInfo;
    //	static Can_PduType Can_PduInfo1;
    volatile Std_ReturnType CAN_Write_Status;
    uint8 rxBuffer[100];

    uint8 u8TimeOut = 100U;
    CanIf_bTxFlag = FALSE;
    CanIf_bRxFlag = FALSE;

    /* Initialize the Mcu driver */
#if (MCU_PRECOMPILE_SUPPORT == STD_ON)
    Mcu_Init(NULL_PTR);
#elif (MCU_PRECOMPILE_SUPPORT == STD_OFF)
    Mcu_Init(&Mcu_Config_VS_0);
#endif /* (MCU_PRECOMPILE_SUPPORT == STD_ON) */

    Mcu_InitClock(McuClockSettingConfig_0);

    /* Wait until PLL is locked */
    // while ( MCU_PLL_LOCKED != Mcu_GetPllStatus() )
    {
        /* Busy wait until the System PLL is locked */
    }
    // Mcu_DistributePllClock();
    /* Initialize Mcl module */
    Mcl_Init(NULL_PTR);

    Mcu_SetMode(McuModeSettingConf_0);
    OsIf_Init(NULL_PTR);
    Platform_Init(NULL_PTR);
    Platform_InstallIrqHandler(LPUART0_RxTx_IRQn, LPUART_UART_IP_0_IRQHandler, NULL_PTR);
    Platform_InstallIrqHandler(LPUART1_RxTx_IRQn, LPUART_UART_IP_1_IRQHandler, NULL_PTR);
    Platform_InstallIrqHandler(LPUART2_RxTx_IRQn, LPUART_UART_IP_2_IRQHandler, NULL_PTR);
    Platform_InstallIrqHandler(FLEXIO_IRQn, MCL_FLEXIO_ISR, NULL_PTR);
    Platform_InstallIrqHandler(DMA0_IRQn, Dma0_Ch0_IRQHandler, NULL_PTR);
    Platform_InstallIrqHandler(DMA1_IRQn, Dma0_Ch1_IRQHandler, NULL_PTR);
    Platform_InstallIrqHandler(DMA2_IRQn, Dma0_Ch2_IRQHandler, NULL_PTR);
    Platform_InstallIrqHandler(DMA3_IRQn, Dma0_Ch3_IRQHandler, NULL_PTR);
    Platform_InstallIrqHandler(DMA4_IRQn, Dma0_Ch4_IRQHandler, NULL_PTR);
    Platform_InstallIrqHandler(DMA5_IRQn, Dma0_Ch5_IRQHandler, NULL_PTR);

    //    Platform_InstallIrqHandler(CAN0_ORed_IRQn,IRQHandler,NULL_PTR);
    //    Platform_InstallIrqHandler(CAN0_Error_IRQn,Dma0_Ch5_IRQHandler,NULL_PTR);
    //    Platform_InstallIrqHandler(CAN0_Wake_Up_IRQn,Dma0_Ch5_IRQHandler,NULL_PTR);
    //    Platform_InstallIrqHandler(CAN0_ORed_0_15_MB_IRQn,Dma0_Ch5_IRQHandler,NULL_PTR);
    //    Platform_InstallIrqHandler(CAN0_ORed_16_31_MB_IRQn,Dma0_Ch5_IRQHandler,NULL_PTR);

    /* Initialize all pins*/
#if (PORT_PRECOMPILE_SUPPORT == STD_ON)
    Port_Init(NULL_PTR);
#elif (PORT_PRECOMPILE_SUPPORT == STD_OFF)
    Port_Init(&Port_Config_VS_0);
#endif

    /* Initializes an UART driver*/
#if (UART_PRECOMPILE_SUPPORT == STD_ON)
    Uart_Init(NULL_PTR);
#elif (UART_PRECOMPILE_SUPPORT == STD_OFF)
    Uart_Init(&Uart_xConfig_VS_0);
#endif

#if 1 /* Initialize Platform driver */

#if (CAN_PRECOMPILE_SUPPORT == STD_ON)
    Can_Init(NULL_PTR);
#elif (CAN_PRECOMPILE_SUPPORT == STD_OFF)
    Can_Init(&Can_Config_VS_0);
#endif
    Can_SetControllerMode(CanController_0, CAN_CS_STARTED);

#endif
#if 0
	Platform_InstallIrqHandler(FlexCAN0_0_IRQn, CAN0_ORED_IRQHandler, NULL);
	Platform_SetIrq(FlexCAN0_0_IRQn, TRUE);
	Platform_InstallIrqHandler(FlexCAN0_1_IRQn, CAN0_ORED_0_15_MB_IRQHandler, NULL);
	Platform_SetIrq(FlexCAN0_1_IRQn, TRUE);
	Platform_InstallIrqHandler(FlexCAN0_2_IRQn, CAN0_ORED_16_31_MB_IRQHandler, NULL);
	Platform_SetIrq(FlexCAN0_2_IRQn, TRUE);


//	Platform_InstallIrqHandler(FlexCAN1_0_IRQn, CAN1_ORED_IRQHandler, NULL);
//	Platform_SetIrq(FlexCAN1_0_IRQn, TRUE);
//	Platform_InstallIrqHandler(FlexCAN0_1_IRQn, CAN1_ORED_0_31_MB_IRQHandler, NULL);
//	Platform_SetIrq(FlexCAN1_1_IRQn, TRUE);
//	Platform_InstallIrqHandler(FlexCAN1_2_IRQn, CAN1_ORED_32_63_MB_IRQHandler, NULL);
//	Platform_SetIrq(FlexCAN1_2_IRQn, TRUE);
#endif

    // Dio_WriteChannel(DioConf_DioChannel_LED, STD_HIGH);

    // Dio_WriteChannel(DioConf_DioChannel_DIO_TEST, value);
    /* Send greeting string 1 from Flexio_0_Tx */
    // T_Uart_Status1 = Send_Data(UART_LPUART0_INTERNAL_CHANNEL, (const uint8 *)WELCOME_MSG_1, strlen(WELCOME_MSG_1));

    /* Send greeting string 2 from Flexio_0_Tx */
    // T_Uart_Status2 = Send_Data(UART_LPUART0_INTERNAL_CHANNEL, (const uint8 *)WELCOME_MSG_2, strlen(WELCOME_MSG_2));

    /* Can_CreatePduInfo(id, swPduHandle,length, sdu) */
    //	Can_PduInfo = Can_CreatePduInfo(0x55U, CAN_EXTENDED_ID_TYPE, 0U, 8U, Can_au8Sdu8bytes);
    //	Can_PduInfo1 = Can_CreatePduInfo(0x66U, 0U, 2U, Can_au8Sdu8bytes);
    Can_MsgInfo.id = 0x18123456;
    Can_MsgInfo.idFrame = CAN_EXTENDED_ID_TYPE;
    Can_MsgInfo.length = 8;
    Can_MsgInfo.sdu = Can_au8Sdu8bytes;

    /* Initilize Can driver */

    // Can_Init(&Can_Config_VS_0);

    //	Can_SetControllerMode(CanController_1, CAN_CS_STARTED);
    //	Dio_WriteChannel(DioConf_DioChannel_PTE4_GPIO_OUT_MCU_4G_POW_EN,STD_ON);  //使能power
    //	Dio_WriteChannel(DioConf_DioChannel_PTB20_GPIO_OUT_MCU_4G_PWRKEY,STD_ON); //正向脉冲使其开机
    // TestDelay(5000000);
    // Dio_WriteChannel(DioConf_DioChannel_PTB20_GPIO_OUT_MCU_4G_PWRKEY,STD_OFF);

    //	Dio_WriteChannel(DioConf_DioChannel_PTB19_GPIO_OUT_MCU_4G_DTR,STD_ON); //DTR 拉低
    //	TestDelay(80000000);
    // Dio_WriteChannel(DioConf_DioChannel_PTB19_GPIO_OUT_MCU_4G_DTR,STD_OFF); //DTR 拉低

    // Dio_WriteChannel(DioConf_DioChannel_PTB19_GPIO_OUT_MCU_4G_DTR,STD_ON);
    // Dio_WriteChannel(DioConf_DioChannel_PTB18_GPIO_OUT_MCU_4G_RESET,STD_ON);
    // TestDelay(100000);
    Dio_WriteChannel(DioConf_DioChannel_PTE9_GPIO_OUT_MCU_BT_POW_EN,STD_ON);
    Dio_WriteChannel(DioConf_DioChannel_PTE7_GPIO_OUT_MCU_BT_MOD,STD_ON);
    // Dio_WriteChannel(DioConf_DioChannel_PTB18_GPIO_OUT_MCU_4G_RESET,STD_OFF);
    // DioConf_DioChannel_PTB18_GPIO_OUT_MCU_4G_RESET
    // My_Tja1153_Init();
    vSemaphoreCreateBinary(sem_handle);
    xTaskCreate( BleTask, ( const char * const ) "BleTask", configMINIMAL_STACK_SIZE+1024, (void*)0, main_TASK_PRIORITY, NULL );
    xTaskCreate( ReceiveTask, ( const char * const ) "RecTask" , configMINIMAL_STACK_SIZE, (void*)0, main_TASK_PRIORITY + 1, NULL );
    vTaskStartScheduler();
    while (1)
    {
        pinValue = ~pinValue;
        CanIf_SendMessage(0, Can_MsgInfo);
        TestDelay(100000);
        Can_MainFunction_Read();
        CanIf_bRxFlag = false;
        TestDelay(100000);
        //		  memset(RX_Buffer[UART_LPUART0_RS232],0,BUFFER_SIZE);
        //		  bufferIdx = 0;
        //		  /* Send greeting string 2 from Flexio_0_Tx */
        //		  T_Uart_Status1 = UART_Query_Data(UART_LPUART0_RS232,UART_LPUART0_RS232, (const uint8 *)WELCOME_MSG_1,  strlen(WELCOME_MSG_1), RX_Buffer[UART_LPUART0_RS232], 100000);
        //		  TestDelay(1000);
        //
        //		  memset(RX_Buffer[UART_LPUART0_RS232],0,BUFFER_SIZE);
        //		  bufferIdx = 0;
        //		  T_Uart_Status2 = UART_Query_Data(UART_LPUART0_RS232,UART_LPUART0_RS232, (const uint8 *)WELCOME_MSG_2,  strlen(WELCOME_MSG_2), RX_Buffer[UART_LPUART0_RS232], 100000);
        //		  //TestDelay(1000);
        ////		  memset(rxBuffer,0,100);
        ////		  R_Uart_Status2 = Rece_Data(UART_LPUART0_RS232, rxBuffer, strlen(WELCOME_MSG_2),0xFFFF);
        //		  //TestDelay(2000000);
        //		  memset(RX_Buffer[UART_LPUART0_RS232],0,BUFFER_SIZE);
        //		  bufferIdx = 0;
        //		  T_Uart_Status3 = UART_Query_Data(UART_LPUART0_RS232,UART_LPUART0_RS232, (const uint8 *)WELCOME_MSG_3,  strlen(WELCOME_MSG_3), RX_Buffer[UART_LPUART0_RS232], 100000);
    }
}

/** @} */
