#include <string.h>
#include "uart5.h"

#define UART_BUFF_SIZE  1024
u8 RxBuffer[UART_BUFF_SIZE] = {0};
volatile u8 RxCnt = 0;
volatile u8 Rxfinish = 0;

char *pbuf;
uint16_t len;

void Uart5_GPIO_Init()
{
    GPIO_InitTypeDef GPIO_InitStructure = { 0 };
    USART_InitTypeDef USART_InitStructure = { 0 };
    NVIC_InitTypeDef NVIC_InitStructure = { 0 };

    RCC_APB1PeriphClockCmd( RCC_APB1Periph_UART5, ENABLE );
    RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOC, ENABLE );
    RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOD, ENABLE );

    RCC_APB2PeriphClockCmd( RCC_APB2Periph_AFIO, ENABLE );

    /* UART5 TX-->C.12   RX-->D.2 */
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
    GPIO_Init( GPIOC, &GPIO_InitStructure );

    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
    GPIO_Init( GPIOD, &GPIO_InitStructure );

    USART_InitStructure.USART_BaudRate = UART5_BAUDRATE;
    USART_InitStructure.USART_WordLength = USART_WordLength_8b;
    USART_InitStructure.USART_StopBits = USART_StopBits_1;
    USART_InitStructure.USART_Parity = USART_Parity_No;
    USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
    USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;

    USART_Init( UART5, &USART_InitStructure );
    USART_ITConfig( UART5, USART_IT_RXNE, ENABLE );

    NVIC_InitStructure.NVIC_IRQChannel = UART5_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 3;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStructure);

    USART_Cmd( UART5, ENABLE );
}

void USART5_SendData(PUINT8 txbuf, UINT16 length)
{
    UINT8 TxCnt = 0;

    while(TxCnt < length)
    {
        //printf("TxCnt:%d\r\n", TxCnt);
        USART_SendData(UART5, txbuf[TxCnt++]);
        while(USART_GetFlagStatus(UART5, USART_FLAG_TXE) == RESET)
        {
            /* waiting for sending finish */
        }
//        while(USART_GetFlagStatus(UART5, USART_FLAG_RXNE) == RESET)
//        {
//            /* waiting for receiving finish */
//        }
//        RxBuffer[RxCnt++] = (USART_ReceiveData(UART5));

        //PRINT("TxCnt:%d\r\n", TxCnt);
    }
}

u16 crc16(u8* data_p, u16 length){
    u8 x;
    u16 crc = 0xFFFF;

    while (length--){
        x = crc >> 8 ^ *data_p++;
        x ^= x>>4;
        crc = (crc << 8) ^ ((u16)(x << 12)) ^ ((u16)(x <<5)) ^ ((u16)x);
    }
    return crc;
}

void SendUart5DataPacket(u8 cmd, u8* data, u8 len)
{
    UART2_PACKAGE_TypeDef packet;

    // 设置数据包内容
    packet.Head1 = 0x5A;
    packet.Head2 = 0xA5;
    packet.Len = sizeof(packet);
    packet.Cmd = cmd;
    // set data
    memset(packet.Data, 0, DATA_LEN);

    for (int i = 0; i < len; i++) {
        packet.Data[i] = data[i];
    }

    // 计算并设置 CRC16 校验值
    packet.CRC16 = crc16((u8*)&packet, sizeof(packet)-(sizeof(packet.CRC16)+sizeof(packet.End)));
    //printf("%04x\n", packet.CRC16);
    packet.End = 0xFF;

    // send data
    USART5_SendData((PUINT8)&packet, sizeof(packet));
}

//获取接收到的data and length
char *get_rebuff(uint16_t *len)
{
    *len = RxCnt;
    return (char *)&RxBuffer;
}

//clean data buffer
void clean_rebuff(void)
{
    uint16_t i = UART_BUFF_SIZE + 1;
    RxCnt = 0;
    while (i)
        RxBuffer[--i]=0;
}

void USART5_IRQHandler(void) __attribute__((interrupt("WCH-Interrupt-fast")));
void USART5_IRQHandler(void)
{
    if(RxCnt < 5)
    {
        if(USART_GetITStatus(UART5, USART_IT_RXNE) != RESET)
        {
            RxBuffer[RxCnt] = USART_ReceiveData(UART5);
            RxCnt ++;

            pbuf = get_rebuff(&len);
            clean_rebuff();
        }

    }
    else
    {
        RxCnt=0;
        USART_ClearITPendingBit(UART5, USART_IT_RXNE);
    }
}
