/* USER CODE BEGIN Header */
/* you can remove the copyright */
/*
 *  Copyright 2020-2024 Yuntu Microelectronics co.,ltd
 *  All rights reserved.
 * 
 *  YUNTU Confidential. This software is owned or controlled by YUNTU 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. The production use license in
 *  Section 2.3 is expressly granted for this software.
 * 
 * @file main.c
 * @brief 
 * 
 */

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

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

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

/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
#define CAN_INST        (0U)
#define SW_PORT         (GPIOE)
#define SW3_PORT_INDEX  (11U)
#define SW2_PORT_INDEX  (3U)
/* Receive Standard ID*/
#define RX_STD_MSG_ID   (0x201UL)
/* Receive Standard MB*/
#define RX_STD_MAILBOX  (0x00UL)

#define TX_MSG_ID       (0x200UL)
#define TX_MAILBOX      (0x01UL)
/* USER CODE END PD */

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

/* Private variables ---------------------------------------------------------*/
/* USER CODE BEGIN PV */
volatile uint16_t timerOverflowInterruptCount = 0U;
volatile uint16_t can_1s_Send = 0U;
uint16_t CANReciveRPM = 0U;       
uint8_t CANReciveStop = 0U;
uint8_t CANReciveReset = 0U; 
uint16_t MotorTemp = 0U;
uint16_t VBus = 0U;
/* Standard receive message buffer */
flexcan_msgbuff_t rxStdMsg;

/* Prepare message to be sent */
flexcan_msgbuff_t txMsg = {
    .cs = 0U,
    .msgId = TX_MSG_ID,
    .data[0] = 0x00U,
    .dataLen = 8U,
};

const flexcan_data_info_t rxMbStdInfo = {
    .msg_id_type = FLEXCAN_MSG_ID_STD,
    .data_length = 8U,
    .fd_enable = false,
    .fd_padding = 0U,
    .enable_brs = false,
    .is_remote = false,
};
const flexcan_data_info_t txMbStdInfo = {
    .msg_id_type = FLEXCAN_MSG_ID_STD,
    .data_length = 8U,
    .fd_enable = false,
    .fd_padding = 0U,
    .enable_brs = false,
    .is_remote = false,
};
/* USER CODE END PV */

/* Private function declare --------------------------------------------------*/
/* USER CODE BEGIN PFDC */
static void Flexcan_Init(void);
/* USER CODE END PFDC */
static void Board_Init(void);

/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */
void ptmr0_interrupt_isr(void)
{
    if (pTMR_DRV_GetInterruptFlagTimerChannels(pTMR0_INST, pTMR0_CH0))
    {
        /* Increment overflow count */
        timerOverflowInterruptCount++;

        can_1s_Send++;
        if(can_1s_Send >= 16000U)
        {
            if (FLEXCAN_DRV_GetTransferStatus(CAN_INST, TX_MAILBOX) != STATUS_BUSY)
            {
                if(gs.state == STATE_WORK )
                {
                    txMsg.data[0] = (gp.rpm & 0xFFFFU)>> 8U;
                    txMsg.data[1] = (gp.rpm & 0xFF);
                    txMsg.data[2] = (MotorTemp & 0xFFFFU)>> 8U;
                    txMsg.data[3] = (MotorTemp & 0xFF);
                    txMsg.data[4] = (VBus & 0xFFFFU)>> 8U;
                    txMsg.data[5] = (VBus & 0xFF);
                }
                else
                {
                    txMsg.data[0] = 0U;
                    txMsg.data[1] = 0U;
                    txMsg.data[2] = 0U;
                    txMsg.data[3] = 0U;
                    txMsg.data[4] = 0U;
                    txMsg.data[5] = 0U;
                }
                FLEXCAN_DRV_Send(CAN_INST, TX_MAILBOX, &txMbStdInfo, TX_MSG_ID, txMsg.data);
            }
            can_1s_Send = 0U;
        }
        /* Clear compare flag */
        pTMR_DRV_ClearInterruptFlagTimerChannels(pTMR0_INST, pTMR0_CH0);
    }

}

void DRV_CAN_RxEventCall(uint8_t instance,
                         flexcan_event_type_t eventType,
                         uint32_t buffIdx,
                         flexcan_state_t *flexcanState)
{
    switch (eventType)
    {
        case FLEXCAN_EVENT_RX_COMPLETE:
        {
            if (buffIdx == RX_STD_MAILBOX)
            {
                FLEXCAN_DRV_Receive(CAN_INST, RX_STD_MAILBOX, &rxStdMsg);

                /* message data[0] == 0x01 will change system mode to standby mode, 
                     * data[0] == 0x02 will change system mode to powerdown mode. 
                     * others data don't care
                    */
                if (rxStdMsg.msgId == 0x201U)
                {
                    CANReciveRPM = (rxStdMsg.data[0] << 8)|(rxStdMsg.data[1]);
                    CANReciveStop = rxStdMsg.data[2];
                    CANReciveReset =  rxStdMsg.data[3];
                    if((CANReciveRPM >= 300U)&&(CANReciveRPM<=1500U))
                    {
                        UserSetRMP = (int32_t)CANReciveRPM;
                    }
                    if(CANReciveStop == 1U)
                    {
                        gs.state = 0;
                    }
                    if(CANReciveReset == 1U)
                    {
                        SystemSoftwareReset();
                    }
                }
            }
            else
            {}
        }
        break;

        default:
            /* Default */
            break;
    }
}

void GPIO_IRQHandler(void)
{
    if (PINS_DRV_GetPortIntFlag(SW_PORT) & (1 << SW3_PORT_INDEX))
    {
        /* SW3 is pressed, speed up 100RPM */
        if(UserSetRMP < 1600)
        {
            UserSetRMP = UserSetRMP + 100;
        }
        /* Clear interrupt flag. */
        PINS_DRV_ClearPinIntFlagCmd(SW_PORT, SW3_PORT_INDEX);
    }
    if (PINS_DRV_GetPortIntFlag(SW_PORT) & (1 << SW2_PORT_INDEX))
    {
        /* SW2 is pressed, speed down 100RPM */
        if(UserSetRMP > 400)
        {
            UserSetRMP = UserSetRMP - 100;
        }
        /* Clear interrupt flag. */
        PINS_DRV_ClearPinIntFlagCmd(SW_PORT, SW2_PORT_INDEX);
    }
}
/* USER CODE END 0 */


/**
 * @brief  The application entry point.
 * @retval int
 */
int main(void)
{
    /* USER CODE BEGIN 1 */
    uint16_t lastTimerOverflowInterruptCount = 0U;
    CIM->CTRL |= CIM_CTRL_ADCTSS(1);
    INT_SYS_InstallHandler(pTMR0_IRQn, ptmr0_interrupt_isr, NULL);
    /* USER CODE END 1 */ 
    Board_Init();
    /* USER CODE BEGIN 2 */
    Flexcan_Init();
    /* enable the SW GPIO IRQ interrupt */
    INT_SYS_ConfigInit();

    Motor_CtrlInit();
    pTMR_DRV_StartTimerChannels(pTMR0_INST, pTMR0_CH0);
    Motor_Ctrl_Start();
    /* USER CODE END 2 */

    /* Infinite loop */
    /* USER CODE BEGIN WHILE */
    while (1)
    {
        if (lastTimerOverflowInterruptCount != timerOverflowInterruptCount)
        {
            /* 1ms task */
            lastTimerOverflowInterruptCount = timerOverflowInterruptCount;
            /* Motor state and speed loop service */
            Motor_StateSpeedLoopService();
            /* Timer Interrupt Handler */
            //LIN_DRV_TimeoutService(INST_LIN);
        }
        /* USER CODE END WHILE */
        /* USER CODE BEGIN 3 */
    }
    /* 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);
    TMU_DRV_Init(0,&tmu_config0);
    pTMR_DRV_Init(0,&PTMR_Config);
    pTMR_DRV_InitChannel(0,0,&ptmr_channel_0);
    FLASH_DRV_Init(0,&flash_config0,&flash_config0_State);
}

/* USER CODE BEGIN 4 */
static void Flexcan_Init(void)
{
    FLEXCAN_DRV_Init(CAN_INST, &flexcanInitConfig0_State, &flexcanInitConfig0);
    FLEXCAN_DRV_ConfigRxMb(CAN_INST, RX_STD_MAILBOX, &rxMbStdInfo, RX_STD_MSG_ID);

    /* Install tx/rx callback */
    FLEXCAN_DRV_InstallEventCallback(CAN_INST, DRV_CAN_RxEventCall, NULL);

    /* Start receiving data in RX_STD_MAILBOX. */
    FLEXCAN_DRV_Receive(CAN_INST, RX_STD_MAILBOX, &rxStdMsg);
}
/* USER CODE END 4 */
