/* USER CODE BEGIN Header */
/* you can remove the copyright */

/*
 *  Copyright 2020-2023 Yuntu Microelectronics Co., Ltd.
 *  All rights reserved.
 * 
 *  SPDX-License-Identifier: BSD-3-Clause
 * 
 * @file main.c
 * @brief 
 * 
 */

/* USER CODE END Header */
#include "sdk_project_config.h"
/* Includes ------------------------------------------------------------------*/

/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include "printf.h"
#include "flexcan_hw_access.h"
/* USER CODE END Includes */

/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */
/* USER CODE END PTD */

/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
/* The instance of CAN0 silk-screen on EVB */
#define CAN0_INST (0U)
/* The instance of CAN1 silk-screen on EVB */
#define CAN1_INST (1U)

#define RX_STD_MSG_ID  (0x03UL)
#define RX_STD_MAILBOX (0x00UL)
#define RX_EXTMSG_ID   (0x70012UL)
#define RX_EXT_MAILBOX (0x02UL)
/* If self-test, TX ID need match RX ID */
#define TX_MSG_ID      (0x03UL)
#define TX_MAILBOX     (0x01UL)
#define TX_EXTMSG_ID   (0x70012UL)
#define TX_EXT_MAILBOX (0x03UL)
#define LED0_TOGGLE()  (PINS_DRV_TogglePins(GPIOE, (pins_channel_type_t)1 << 16U))
#define LED1_TOGGLE()  (PINS_DRV_TogglePins(GPIOA, (pins_channel_type_t)1 << 20U))

#define TEST_COUNT (10U)
/* USER CODE END PD */

/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */
/* USER CODE END PM */

/* Private variables ---------------------------------------------------------*/
/* USER CODE BEGIN PV */
/* CAN0 configuration */
/* Define receive buffer */
flexcan_msgbuff_t rxStdMsg1;
flexcan_msgbuff_t rxExtMsg1;
/* Prepare message to be sent */
flexcan_msgbuff_t txMsg1 = {
    .cs = 0U,
    .msgId = TX_MSG_ID,
    .data[0] = 0x00,
    .dataLen = 1U,
};
const flexcan_data_info_t rxMbExtInfo1 = {
    .msg_id_type = FLEXCAN_MSG_ID_EXT,
    .data_length = 8,
    .fd_enable = false,
    .fd_padding = 0,
    .enable_brs = false,
    .is_remote = false,
};
const flexcan_data_info_t rxMbStdInfo1 = {
    .msg_id_type = FLEXCAN_MSG_ID_STD,
    .data_length = 8,
    .fd_enable = false,
    .fd_padding = 0,
    .enable_brs = false,
    .is_remote = false,
};
const flexcan_data_info_t txMbStdInfo1 = {
    .msg_id_type = FLEXCAN_MSG_ID_STD,
    .data_length = 8,
    .fd_enable = false,
    .fd_padding = 0,
    .enable_brs = false,
    .is_remote = false,
};
const flexcan_data_info_t txMbExtInfo1 = {
    .msg_id_type = FLEXCAN_MSG_ID_EXT,
    .data_length = 8,
    .fd_enable = false,
    .fd_padding = 0,
    .enable_brs = false,
    .is_remote = false,
};

/* CAN1 configuration */
/* Define receive buffer */
flexcan_msgbuff_t rxStdMsg2;
flexcan_msgbuff_t rxExtMsg2;
/* Prepare message to be sent */
flexcan_msgbuff_t txMsg2 = {
    .cs = 0U,
    .msgId = TX_MSG_ID,
    .data[0] = 0x80,
    .dataLen = 1U,
};
const flexcan_data_info_t rxMbExtInfo2 = {
    .msg_id_type = FLEXCAN_MSG_ID_EXT,
    .data_length = 8,
    .fd_enable = false,
    .fd_padding = 0,
    .enable_brs = false,
    .is_remote = false,
};
const flexcan_data_info_t rxMbStdInfo2 = {
    .msg_id_type = FLEXCAN_MSG_ID_STD,
    .data_length = 8,
    .fd_enable = false,
    .fd_padding = 0,
    .enable_brs = false,
    .is_remote = false,
};
const flexcan_data_info_t txMbStdInfo2 = {
    .msg_id_type = FLEXCAN_MSG_ID_STD,
    .data_length = 8,
    .fd_enable = false,
    .fd_padding = 0,
    .enable_brs = false,
    .is_remote = false,
};
const flexcan_data_info_t txMbExtInfo2 = {
    .msg_id_type = FLEXCAN_MSG_ID_EXT,
    .data_length = 8,
    .fd_enable = false,
    .fd_padding = 0,
    .enable_brs = false,
    .is_remote = false,
};
volatile bool canError = false;

static CAN_Type * const flexcanBase[] = CAN_BASE_PTRS;
/* USER CODE END PV */

/* Private function declare --------------------------------------------------*/
/* USER CODE BEGIN PFDC */
void Can_Init(uint8_t instance)
{
    DEV_ASSERT(instance < CAN_INSTANCE_COUNT);
    CAN_Type * base = flexcanBase[instance];
    base->MCR |= CAN_MCR_MDIS_MASK; /* MDIS=1: Disable module before selecting clock */
    base->CTRL1 &= ~CAN_CTRL1_CLKSRC_MASK; /* CLKSRC=0: Clock Source = oscillator */
    base->MCR &= ~CAN_MCR_MDIS_MASK; /* MDIS=0; Enable module config. (Sets FRZ, HALT) */

    while (!((base->MCR & CAN_MCR_FRZACK_MASK) >> CAN_MCR_FRZACK_SHIFT))
    {
    }
    /* Wait for FRZACK=1 on freeze mode entry/exit */
    base->CTRL1 =  0x02DBC406; /* Configure for 500 KHz bit time for 24MHz oscillator */

    /* Time quanta freq = 16 time quanta x 500 KHz bit time= 8MHz */
    /* PRESDIV + 1 = Fclksrc/Ftq = 24 MHz/8 MHz = 3，->PRESDIV = 2*/
    /* PSEG2 = 3 */
    /* PSEG1 = 3 */
    /* PROPSEG = 6 */
    /* RJW: since Phase_Seg1 = PSEG1 + 1 = 4, so RJW ≤4，so set RJW = 3. */
    /* SMP = 0: use one bit per CAN sample */

    /* Payload size is set to default value(8 bytes) here */
    if (instance < 2)
    {
        /* CAN0 and CAN1 have 128 MBs */
        for (uint16_t i = 0; i < 128 * 4; i++)
        { 
            /* CAN0: clear 128 MBs */
            base->RAM[i] = 0; /* Clear msg buf word */
        }
    }
    else if (1 < instance && instance < 5)
    {
        /* CAN3、CAN4 and CAN5 have 64 MBs */
        for (uint8_t i = 0; i < 64 * 4; i++)
        { 
            /* Clear 64 MBs */
            base->RAM[i] = 0; /* Clear msg buf word */
        }
    }
    else
    {
        /* Other CAN controllers only have 32 MBs */
        for (uint8_t i = 0; i < 32 * 4; i++)
        { 
            /* Clear 32 MBs */
            base->RAM[i] = 0; /* Clear msg buf word */
        }
    }
    
    /* Clear RXMGMASK,RX14MASK,RX15MASK,RXFGMASK Regions*/
    base->RXMGMASK = 0xFFFFFFFFU;
    base->RX14MASK = 0xFFFFFFFFU;
    base->RX15MASK = 0xFFFFFFFFU;
    base->RXFGMASK = 0xFFFFFFFFU;
        
    base->MCR = 0x0000007F | (1 << 17); /* Negate FlexCAN 1 halt state for 32 MBs */
				
    base->IMASK1 = 0x00000003;
        
    while ((base->MCR && CAN_MCR_FRZACK_MASK) >> CAN_MCR_FRZACK_SHIFT)
    {
    }
    /* Wait for FRZACK to clear (not in freeze mode) */
    while ((base->MCR && CAN_MCR_NOTRDY_MASK) >> CAN_MCR_NOTRDY_SHIFT)
    {
    }
    /* Wait for NOTRDY to clear (module ready)  */
}

void Can_SendFrame(uint8_t instance, flexcan_msgbuff_t frame, uint8_t mb_idx)
{
    CAN_Type * base = flexcanBase[instance];
    base->IFLAG1 = 1 << mb_idx; /* Clear IRQ flag */
    /* Write data to RAM */
    base->RAM[mb_idx * 4 + 2] = (((uint32_t) frame.data[0]) << 24) \
                                | (((uint32_t) frame.data[1]) << 16) \
                                | (((uint32_t) frame.data[2]) << 8) \
                                | frame.data[3]; 
    base->RAM[mb_idx * 4 + 3] = (((uint32_t) frame.data[4]) << 24) \
                                | (((uint32_t) frame.data[5]) << 16) \
                                | (((uint32_t) frame.data[6]) << 8) \
                                | frame.data[7];

    base->RAM[mb_idx * 4 + 1] &= ~CAN_ID_STD_MASK;
    base->RAM[mb_idx * 4 + 1] |= (frame.msgId << CAN_ID_STD_SHIFT) & CAN_ID_STD_MASK;

    base->RAM[mb_idx * 4 + 0] &= ~(CAN_CS_IDE_MASK | CAN_CS_SRR_MASK);
    base->RAM[mb_idx * 4 + 0] |= ((uint32_t)8 << CAN_CS_DLC_SHIFT) & CAN_CS_DLC_MASK; /* dlc = 8 */
    base->RAM[mb_idx * 4 + 0] |= (FLEXCAN_TX_DATA << CAN_CS_CODE_SHIFT) & CAN_CS_CODE_MASK;
}
/* USER CODE END PFDC */
static void Board_Init(void);

/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */
/* USER CODE END 0 */


/**
 * @brief  The application entry point.
 * @retval int
 */
int main(void)
{
    /* USER CODE BEGIN 1 */
    status_t status = STATUS_SUCCESS;
    /* USER CODE END 1 */ 
    Board_Init();
    /* USER CODE BEGIN 2 */
    Board_Init();
    /* USER CODE BEGIN 2 */
    Can_Init(1);
    // FLEXCAN_DRV_Init(1, &flexcanInitConfig0_State, &flexcanInitConfig0);
    // INT_SYS_EnableIRQ(CAN1_ORed_0_15_MB_IRQn);

    for (uint8_t i = 0; i < 8; i++)
    {
        txMsg1.data[i] = i % 8;
    }
    
    while (1)
    {
        Can_SendFrame(1, txMsg1, 0);
        // FLEXCAN_DRV_Send(1, 0, &txMbStdInfo1, 0x03, txMsg1.data);
        OSIF_TimeDelay(300);
    }
    /* USER CODE END 2 */

    /* Infinite loop */
    /* USER CODE BEGIN WHILE */
    while (1)
    {
        if (status != STATUS_SUCCESS)
        {
            break;
        }
        /* USER CODE END WHILE */
        /* USER CODE BEGIN 3 */
    }
    return status;
    /* USER CODE END 3 */
}

static void Board_Init(void)
{
    CLOCK_SYS_Init(g_clockManConfigsArr,CLOCK_MANAGER_CONFIG_CNT,g_clockManCallbacksArr,CLOCK_MANAGER_CALLBACK_CNT);
    if(STATUS_SUCCESS != CLOCK_SYS_UpdateConfiguration(CLOCK_MANAGER_ACTIVE_INDEX,CLOCK_MANAGER_POLICY_AGREEMENT))
    {
        /* USER CODE BEGIN ERROR_HANDLER 1 */
        SystemSoftwareReset();
        /* USER CODE END ERROR_HANDLER 1 */
    }
    PINS_DRV_Init(NUM_OF_CONFIGURED_PINS0,g_pin_mux_InitConfigArr0);
    UTILITY_PRINT_Init();
    // FLASH_ECC_Fault_Init(&flash_ecc_fault_config0,&flash_ecc_fault_config0_State);
}

/* USER CODE BEGIN 4 */
/* USER CODE END 4 */
