/*
2页菜单：1：设定速度、实时速度； 2：母线电压、电流显示。
Designed by Cache.lee from UET company
Ported to CW32L012
*/
#include "main.h"
#include "motor.h"
#include "globalv.h"
#include "init.h"
#include "pid.h"
#include "compu.h"
#include "control.h"

unsigned int Menu = 0;

#define DEBUG_UARTx                   CW_UART3
#define DEBUG_UART_CLK                SYSCTRL_APB1_PERIPH_UART3
#define DEBUG_UART_APBClkENx          SYSCTRL_APBPeriphClk_Enable1
#define DEBUG_UART_BaudRate           115200
#define DEBUG_UART_UclkFreq           64000000

#define DEBUG_UART_GPIO_CLK           SYSCTRL_AHB_PERIPH_GPIOB
#define DEBUG_UART_TX_GPIO_PORT       CW_GPIOB
#define DEBUG_UART_TX_GPIO_PIN        GPIO_PIN_6
#define DEBUG_UART_RX_GPIO_PORT       CW_GPIOB
#define DEBUG_UART_RX_GPIO_PIN        GPIO_PIN_7

#define DEBUG_UART_AFTX               PB06_AFx_UART3TXD()
#define DEBUG_UART_AFRX               PB07_AFx_UART3RXD()

#ifdef __GNUC__
#define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
#else
#define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
#endif

void UART_Configuration(void)
{
    UART_InitTypeDef UART_InitStructure = {0};
    GPIO_InitTypeDef GPIO_InitStructure = {0};

    SYSCTRL_AHBPeriphClk_Enable(DEBUG_UART_GPIO_CLK, ENABLE);
    DEBUG_UART_APBClkENx(DEBUG_UART_CLK, ENABLE);

    DEBUG_UART_AFTX;
    DEBUG_UART_AFRX;

    GPIO_InitStructure.Pins = DEBUG_UART_TX_GPIO_PIN;
    GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_PP;
    GPIO_InitStructure.Speed = GPIO_SPEED_HIGH;
    GPIO_Init(DEBUG_UART_TX_GPIO_PORT, &GPIO_InitStructure);

    GPIO_InitStructure.Pins = DEBUG_UART_RX_GPIO_PIN;
    GPIO_InitStructure.Mode = GPIO_MODE_INPUT_PULLUP;
    GPIO_Init(DEBUG_UART_RX_GPIO_PORT, &GPIO_InitStructure);

    UART_InitStructure.UART_BaudRate = DEBUG_UART_BaudRate;
    UART_InitStructure.UART_Over = UART_Over_16;
    UART_InitStructure.UART_Source = UART_Source_PCLK;
    UART_InitStructure.UART_UclkFreq = DEBUG_UART_UclkFreq;
    UART_InitStructure.UART_StartBit = UART_StartBit_FE;
    UART_InitStructure.UART_StopBits = UART_StopBits_1;
    UART_InitStructure.UART_Parity = UART_Parity_No;
    UART_InitStructure.UART_HardwareFlowControl = UART_HardwareFlowControl_None;
    UART_InitStructure.UART_Mode = UART_Mode_Rx | UART_Mode_Tx;
    UART_Init(DEBUG_UARTx, &UART_InitStructure);
}

PUTCHAR_PROTOTYPE
{
    UART_SendData(DEBUG_UARTx, (uint8_t)ch);
    while (UART_GetFlagStatus(DEBUG_UARTx, UART_FLAG_TXE) == RESET)
    {
    }
    return ch;
}

#ifdef USE_FULL_ASSERT
void assert_failed(uint8_t *file, uint32_t line)
{
    (void)file;
    (void)line;
}
#endif

void PowerOnDelay(void)
{
    unsigned int i;

    for (i = 0; i < 6; i++)
    {
        volatile unsigned int j;
        for (j = 0; j < 60000; j++)
        {
        }
    }

    KKN = (MAXSPEED - MINSPEED);
    KKN = KKN / (NMAXVD - NMINVD);
}

unsigned int hte = 0;

int main(void)
{
    unsigned char DZCount = 0;
    char temp_buff[100], temp_buff1[50];

    PowerOnDelay();
    RCC_Configuration();
    UART_Configuration();
    GPIOInit();
    LEDON();
    ADC_Configuration();
    PWMtimer_init();
    BTIM_init();
    Halltimer_init();

    PWM_AL_ON;
    PWM_BL_ON;
    PWM_CL_ON;
    TimeCountTemp = 0;
    while (TimeCountTemp < 50)
    {
    }
    TimeCountTemp = 0;
    PWM_AL_OFF;
    PWM_BL_OFF;
    PWM_CL_OFF;

    printf("Update %s %s\r\n", __DATE__, __TIME__);
    printf("CW32L012 BLDC Hall PID\r\n");
    printf("ADC[0]:%d ADC[1]:%d ADC[2]:%d ADC[3]:%d\r\n",
           SampleData[0], SampleData[1], SampleData[2], SampleData[3]);

    SampleVI();
    startflag = 1;
    EnDirCheck();

    DIin = 0x500;
    if (SampleData[1] > 1117 && SampleData[1] <= 1500)
    {
        DIin = SampleData[1];
    }
    else
    {
        printf("Current read err\r\n");
    }
    if (SampleData[2] > 3000 || SampleData[2] < 700)
    {
        printf("Speed read err\r\n");
    }
    if (HALL_Check() == 0 || HALL_Check() == 7)
    {
        printf("HALL Read Err\r\n");
    }
    if (CanshuV < 30)
    {
        printf("Votage read err\r\n");
    }
    sprintf(temp_buff1, "Set :%4d RPM  ", SetSpeed);
    sprintf(temp_buff, "Real:%4d RPM  ", RealS);
    printf("%s\r\n", temp_buff);
    printf("%s\r\n", temp_buff1);
    sprintf(temp_buff1, "Vbus :%d.%d V  ", CanshuV / 10, CanshuV % 10);
    sprintf(temp_buff, "I(MA):%d      ", CanshuI);
    printf("%s\r\n", temp_buff);
    printf("%s\r\n", temp_buff1);
    GPIO_WritePin(VOUT_EN_GPIO_PORT, VOUT_EN_GPIO_PIN, GPIO_Pin_SET);

    while (1)
    {
        if (TimeCountCompuSpeed > 20)
        {
            TimeCountCompuSpeed = 0;
            SampleSpeed();
            HALL_Check();
        }

        if (TimeCountVI >= 200)
        {
            printf("ADC[0]:%d ADC[1]:%d ADC[2]:%d ADC[3]:%d\r\n",
                   SampleData[0], SampleData[1], SampleData[2], SampleData[3]);

            TimeCountVI = 0;
            SampleVI();

            RealS = hte * 50 / MPolePairs;

            if (MOTORSTATE == STATESTARTPID || MOTORSTATE == STATERUNPID)
            {
                if (RealS == 0)
                {
                    DZCount++;
                    if (DZCount >= 10)
                    {
                        DZCount = 0;
                        ErrorCode = 7;
                    }
                }
                else
                {
                    DZCount = 0;
                }
            }
        }

        if (ErrorCode != 0 && MOTORSTATE != STATEERROR && MOTORSTATE != STATEERROROVER)
        {
            MOTORSTATE = STATEERROR;
            printf("ErrorCode=%d\r\n", ErrorCode);
            GPIO_WritePin(VOUT_EN_GPIO_PORT, VOUT_EN_GPIO_PIN, GPIO_Pin_RESET);
        }

        if (TimeCountkey >= 500)
        {
            LEDTOG();
            TimeCountkey = 0;
            sprintf(temp_buff1, "Set :%4d RPM  ", SetSpeed);
            sprintf(temp_buff, "Real:%4d RPM  ", RealS);
            printf("%s\r\n", temp_buff);
            printf("%s\r\n", temp_buff1);
            sprintf(temp_buff1, "Vbus :%d.%d V  ", CanshuV / 10, CanshuV % 10);
            sprintf(temp_buff, "I(MA):%d      ", CanshuI);
            printf("%s\r\n", temp_buff);
            printf("%s\r\n", temp_buff1);
        }

        MotorBreak();
        EnDirCheck();

        switch (MOTORSTATE)
        {
        case STATESTARTCHECK:
            MotorStartCheck();
            break;
        case STATESTARTPID:
            MotorStartPID();
            break;
        case STATERUNPID:
            MotorRunPID();
            break;
        case STATESTOP:
            MotorStop();
            break;
        case STATEERROR:
            MotorError();
            break;
        case STATEERROROVER:
            MotorErrorOver();
            break;
        default:
            break;
        }
    }
}

void BTIM1_IRQHandler(void)
{
    if (BTIM_GetITStatus(CW_BTIM1, BTIM_IT_UPDATE) != RESET)
    {
        BTIM_ClearITPendingBit(CW_BTIM1, BTIM_IT_UPDATE);

        TimeCountTemp++;
        TimeCountCompuSpeed++;
        TimeCountRealSpd++;
        if (TimeCountAvgSpd >= 200)
        {
            hte = HALLcount1;
            HALLcount1 = 0;
            TimeCountAvgSpd = 0;
        }
        if (TimeCountRealSpd >= 20)
        {
            HALLcountTemp = HALLcount;
            HALLcount = 0;
            TimeCountRealSpd = 0;
        }
        TimeCountPID++;
        TimeCountAvgSpd++;
        TimeCountVI++;
        TimeCountkey++;
    }
}
