#include <csi_config.h>
#include <drv/uart.h>
#include <drv/pin.h>
#include <board_config.h>
#include "app_uart.h"
#include "asr_config.h"
#include <stdio.h>
extern volatile unsigned char f_asr_response;
extern unsigned short Beep_state_count;

static csi_uart_t g_uart;

/* 注意，如果该设备是小端 */
const unsigned int uart_tx_heartbeat = 0xBB0000AA;       //心跳包
const unsigned int uart_tx_normal_power_on = 0xBB0100AA; //正常启动

static volatile unsigned char uart_rx_fifo_flag = 0;
static volatile unsigned char uart_rx_async_flag = 0; //串口中断触发一次标志位，现在程序中当该标志位等于1，则表示接受到1byte数据
static volatile unsigned char uart_tx_async_flag = 0; //tx idle ; 1 tx start

#define UART_SEND_BUFFER_NUM 16      //发送缓存数量
#define UART_SEND_BUFFER_PER_SIZE 33 //串口命令长度

typedef struct uart_buffer
{
    unsigned char write;      //写入发送缓存命令数量
    unsigned char read;       //读取发送缓存命令数量
    unsigned char new_packet; //发送缓存剩余命令数量
} uart_buffer_t;
static char uart_send_buf[UART_SEND_BUFFER_NUM][UART_SEND_BUFFER_PER_SIZE];
static uart_buffer_t uart_send_buf_t;

#define UART1_RCV_BUFFER_NUM 5       //接收串口命令缓存数量
#define UART1_RCV_BUFFER_PER_SIZE 33 //接收串口命令缓存长度，接收的字符长度放在数组的最后一个字节

struct _uart1_rcv
{
    unsigned int cntEnd;
    unsigned int start;
    unsigned char dat[UART1_RCV_BUFFER_PER_SIZE];
} __attribute__((aligned(1)));

struct _uart1Buffer
{
    unsigned char writeIndex;          //接收串口数据写入缓存次数
    unsigned char readIndex;           //接收串口数据读取缓存次数
    volatile unsigned char new_packet; //缓存区还剩余串口数据条数
};

static struct _uart1_rcv uart_rcv;
static unsigned char uartRcvBuffer[UART1_RCV_BUFFER_NUM][UART1_RCV_BUFFER_PER_SIZE];
static struct _uart1Buffer uartRcvBufferArry;

/**
  \brief       Writes the received command to the cache.
  \param[in]   received data.
  \param[in]   The length of the received data.
  \return      TRUE/FALSE
*/
int asr_rcv_write_cache_uart1(unsigned char *buf, unsigned int bufLen)
{
    if ((uartRcvBufferArry.new_packet + 1) == UART1_RCV_BUFFER_NUM)
    {
        return 0;
    }
    memcpy(&uartRcvBuffer[uartRcvBufferArry.writeIndex], buf, bufLen);
    //接收的字符长度放在数组的最后一个字节
    uartRcvBuffer[uartRcvBufferArry.writeIndex][UART1_RCV_BUFFER_PER_SIZE - 1] = bufLen;
    uartRcvBufferArry.writeIndex++;
    uartRcvBufferArry.writeIndex %= UART1_RCV_BUFFER_NUM;
    uartRcvBufferArry.new_packet++;
    return 1;
}

/**
  \brief       Read data from the cache.
  \return      rcvdata  
*/
unsigned char *asr_rcv_read_cache_uart1()
{
    if (uartRcvBufferArry.new_packet)
    {
        unsigned short index = uartRcvBufferArry.readIndex;
        uartRcvBufferArry.readIndex++;
        uartRcvBufferArry.readIndex %= UART1_RCV_BUFFER_NUM;
        uartRcvBufferArry.new_packet--;
        return (unsigned char *)uartRcvBuffer[index];
    }
    return 0;
}

/* 开始接收数据 */
void asr_rcv_uart1_init()
{
    memset(uart_rcv.dat, 0, sizeof(uart_rcv.dat));
    uartRcvBufferArry.readIndex = 0;
    uartRcvBufferArry.writeIndex = 0;
    uartRcvBufferArry.new_packet = 0;
    /* 开始接受一个字节 */
    csi_uart_receive_async(&g_uart, uart_rcv.dat + uart_rcv.cntEnd, 1);
}

void asr_rcv_uart1_start(void)
{
    if (uart_rcv.dat[uart_rcv.cntEnd] == UART1_RCV_END && uart_rcv.start)
    {
        uart_rcv.start = 0;
        asr_rcv_write_cache_uart1(uart_rcv.dat, uart_rcv.cntEnd + 1);
        uart_rcv.cntEnd = 0;
        memset(uart_rcv.dat, 0, sizeof(uart_rcv.dat));
    }
    if (!uart_rcv.start)
    {
        if (uart_rcv.dat[uart_rcv.cntEnd] == UART1_RCV_HEAD)
        {
            uart_rcv.start = 1;
            uart_rcv.cntEnd++;
        }
    }
    else
    {
        uart_rcv.cntEnd++;
    }

    if (uart_rcv.cntEnd > sizeof(uart_rcv.dat))
    {
        uart_rcv.cntEnd = 0;
    }
    /* 开始接受一个字节 */
    csi_uart_receive_async(&g_uart, uart_rcv.dat + uart_rcv.cntEnd, 1);
	
}

static void uart_event_cb(csi_uart_t *uart, csi_uart_event_t event, void *arg)
{
    switch (event)
    {
    case UART_EVENT_SEND_COMPLETE:
        uart_tx_async_flag = 0;
        break;

    case UART_EVENT_RECEIVE_COMPLETE:
        asr_rcv_uart1_start();
        break;
    case UART_EVENT_RECEIVE_FIFO_READABLE:
        uart_rx_fifo_flag++;
        break;

    default:
        break;
    }
}

/* use console uart to show how to use dma mode */
int app_uart_init(void)
{
    csi_error_t ret;
    csi_pin_mode(EXAMPLE_PIN_UART_RX, GPIO_MODE_PULLUP);
    csi_pin_set_mux(EXAMPLE_PIN_UART_TX, EXAMPLE_PIN_UART_TX_FUNC);
    csi_pin_set_mux(EXAMPLE_PIN_UART_RX, EXAMPLE_PIN_UART_RX_FUNC);

    /* 通过设备号初始化对应的uart实例 编号0已经用于uart0了，这里是EXAMPLE_UART_IDX == 1*/
    ret = csi_uart_init(&g_uart, EXAMPLE_UART_IDX);
    if (ret != CSI_OK)
    {
        return -1;
    }

    /* 设置波特率 宏定义EXAMPLE_UART_BAUDRATE为波特率，可以去看定义是多少*/
    ret = csi_uart_baud(&g_uart, EXAMPLE_UART_BAUDRATE);
    if (ret != CSI_OK)
    {
        return -1;
    };

    /*uart设备配置数据位，奇偶校验位和停止位，详情见pdf：api*/
    ret = csi_uart_format(&g_uart, UART_DATA_BITS_8, UART_PARITY_NONE, UART_STOP_BITS_1);
    if (ret != CSI_OK)
    {
        return -1;
    };

    /*设置回调，不设置的话没法接收，基本上不需要修改*/
    ret = csi_uart_attach_callback(&g_uart, uart_event_cb, NULL);
    if (ret != CSI_OK)
    {
        return -1;
    };

    memset(uart_send_buf, 0, sizeof(uart_send_buf));
    uart_send_buf_t.read = 0;
    uart_send_buf_t.write = 0;
    uart_send_buf_t.new_packet = 0;

    app_uart_tx((unsigned char *)&uart_tx_normal_power_on, sizeof(uart_tx_normal_power_on)); //开机启动提示

    asr_rcv_uart1_init();
    return 0;
}

/**
  \brief       Write send cache
  \param[in]   Send data.
  \param[in]   The length of the send data.
  \return      TRUE/FALSE
*/
uint8_t app_uart_tx(unsigned char *pbuf, unsigned char bufLen)
{
    if ((uart_send_buf_t.new_packet + 1) == UART_SEND_BUFFER_NUM)
    {
        return 0;
    }
#if APP_LOG_ENABLE
    unsigned char i = 0;
    printf("Send data len:%d\n",bufLen);
    printf("Send uart data:0x");
    for (i = 0; i < bufLen; i++)
    {
        printf("%02X ", pbuf[i]);
    }
    printf("\n");
#endif
    memcpy(&uart_send_buf[uart_send_buf_t.write][0], pbuf, UART_SEND_BUFFER_PER_SIZE);
    uart_send_buf[uart_send_buf_t.write][UART_SEND_BUFFER_PER_SIZE - 1] = bufLen;
    uart_send_buf_t.write++;
    uart_send_buf_t.write %= UART_SEND_BUFFER_NUM;
    uart_send_buf_t.new_packet++;

    app_uart_tx_polling(); //尝试立即发送tx包
    return 1;
}
/* 轮询发缓存的tx包/读取tx包 */
void app_uart_tx_polling(void)
{
    if (uart_tx_async_flag == 0)
    { //if tx idle
        if (uart_send_buf_t.new_packet)
        {
            uart_tx_async_flag = 1; //tx start
            unsigned int bufLen = uart_send_buf[uart_send_buf_t.read][UART_SEND_BUFFER_PER_SIZE - 1];
            csi_uart_send_async(&g_uart, &uart_send_buf[uart_send_buf_t.read][0], bufLen);
            uart_send_buf_t.read++;
            uart_send_buf_t.read %= UART_SEND_BUFFER_NUM;
            uart_send_buf_t.new_packet--;
        }
    }
}

void app_uart_tx_heartbeat(void) //定时500ms发心跳包
{
    app_uart_tx((unsigned char *)&uart_tx_heartbeat, sizeof(uart_tx_heartbeat));
}

/**
  \brief       Get received data:uart 1.
  \param[out]  The length of the received data.
  \return      Pointer to the rcvdata.hard = 0xAA，end = 0xBB
*/
unsigned char *app_uart_get_rx_data(unsigned char *bufLen)
{
    unsigned char *temPtr = NULL;
#if INTERRUPT_PLAYING
    temPtr = asr_rcv_read_cache_uart1(); //从接收缓存获取串口数据
#else
    if (!f_asr_response)                     //这一段代码：串口对应的提示音会依次播放，最多缓存5（UART1_RCV_BUFFER_NUM）条
    {                                        //在播放提示音的时候不读取uart1接收数据缓存
        temPtr = asr_rcv_read_cache_uart1(); //从接收缓存获取串口数据
    }
#endif
    if (temPtr)
    {
#if INTERRUPT_PLAYING
        if (Beep_state_count && f_asr_response)
        { //提示音播放的时候会被接收的串口数据打断
            Beep_state_count = 0;
            f_asr_response = 0;
#if APP_LOG_ENABLE
            printf("The beep is interrupted,Ready for the next one...\n");
#endif
        }
#endif
        //接收的字符长度放在数组的最后一个字节
        *bufLen = temPtr[UART1_RCV_BUFFER_PER_SIZE - 1];
#if APP_LOG_ENABLE
        printf("\n-----------------------------------------------\n");
        printf("RcvMacDataBuf Len: %d\n",*bufLen);
        printf("RcvMacDataBuf UART_1: 0x");
        unsigned int i = 0;
        for (i = 0; i < *bufLen; i++)
        {
            printf("%02X, ", temPtr[i]);
        }
        printf("\n-----------------------------------------------\n");
#endif
    }
    return (unsigned char *)temPtr;
}

void app_uart_uninit(void)
{
    csi_error_t ret;
    /* Unlink DMA */
    ret = csi_uart_link_dma(&g_uart, NULL, NULL);
    if (ret != CSI_OK)
    {
        return;
    };

    /* Detach the uart callback */
    csi_uart_detach_callback(&g_uart);

    /* Uninit the uart device */
    csi_uart_uninit(&g_uart);
}
