/**
 * @file        main.c
 *
 * @brief       Main program body
 *
 * @version     V1.0.0
 *
 * @date        2023-12-01
 *
 * @attention
 *
 *  Copyright (C) 2023 Geehy Semiconductor
 *
 *  You may not use this file except in compliance with the
 *  GEEHY COPYRIGHT NOTICE (GEEHY SOFTWARE PACKAGE LICENSE).
 *
 *  The program is only for reference, which is distributed in the hope
 *  that it will be useful and instructional for customers to develop
 *  their software. Unless required by applicable law or agreed to in
 *  writing, the program is distributed on an "AS IS" BASIS, WITHOUT
 *  ANY WARRANTY OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the GEEHY SOFTWARE PACKAGE LICENSE for the governing permissions
 *  and limitations under the License.
 */

/* Includes ***************************************************************/
#include "main.h"

/* Private includes *******************************************************/
#include "apm32f4xx_device_cfg.h"
#include "log.h"

/* Private macro **********************************************************/

/* Private typedef ********************************************************/

/* Private variables ******************************************************/
static const char* tag = "main";

/* Private function prototypes ********************************************/
static DAL_StatusTypeDef CAN_LoopBackPolling(void);

/* External variables *****************************************************/
extern CAN_HandleTypeDef hcan1;

/* External functions *****************************************************/

/**
 * @brief   Main program
 *
 * @param   None
 *
 * @retval  None
 */
int main(void)
{
    /* Device configuration */
    DAL_DeviceConfig();

    if (CAN_LoopBackPolling() != DAL_OK)
    {
        BOARD_LED_On(LED2);
        LOGE(tag,"CAN1 polling test is FAILED\r\n");
    }
    else
    {
        BOARD_LED_On(LED3);
        LOGI(tag,"CAN1 polling test is PASSED\r\n");
    }

    /* Infinite loop */
    while (1)
    {
    }
}

/* Private functions ******************************************************/

/**
 * @brief   CAN loopback polling
 *
 * @param   None
 *
 * @retval  DAL status
 */
static DAL_StatusTypeDef CAN_LoopBackPolling(void)
{
    CAN_TxHeaderTypeDef txHeader = {0};
    uint8_t txData[8];

    CAN_RxHeaderTypeDef rxHeader = {0};
    uint8_t rxData[8];
    uint32_t txMailbox;

    if (DAL_CAN_Start(&hcan1) != DAL_OK)
    {
        Error_Handler();
    }

    /* Transmission */
    txHeader.StdId              = 0x11U;
    txHeader.RTR                = CAN_RTR_DATA;
    txHeader.IDE                = CAN_ID_STD;
    txHeader.DLC                = 2U;
    txData[0]                   = 0xCAU;
    txData[1]                   = 0xFEU;

    /* Request transmission */
    if (DAL_CAN_AddTxMessage(&hcan1, &txHeader, txData, &txMailbox) != DAL_OK)
    {
        Error_Handler();
    }

    /* Wait transmission complete */
    while (DAL_CAN_GetTxMailboxesFreeLevel(&hcan1) != 3U)
    {
    }

    /* Reception process */
    if (DAL_CAN_GetRxFifoFillLevel(&hcan1, CAN_RX_FIFO0) != 1U)
    {
        Error_Handler();
    }

    if (DAL_CAN_GetRxMessage(&hcan1, CAN_RX_FIFO0, &rxHeader, rxData) != DAL_OK)
    {
        Error_Handler();
    }

    if (rxHeader.StdId != 0x11U)
    {
        return DAL_ERROR;
    }

    if (rxHeader.IDE != CAN_ID_STD)
    {
        return DAL_ERROR;
    }

    if (rxHeader.RTR != CAN_RTR_DATA)
    {
        return DAL_ERROR;
    }

    if (rxHeader.DLC != 0x02U)
    {
        return DAL_ERROR;
    }

    if ((rxData[0] << 8U | rxData[1]) != 0xCAFE)
    {
        return DAL_ERROR;
    }

    return DAL_OK;
}
