#include "uart.h"
#include "systick.h"
#include <stdio.h>
#include <sys/unistd.h>

static uint8_t usart1_tx_buf[256];
static uint8_t usart1_rx_buf[256];

static uint8_t usart2_tx_buf[256];
static uint8_t usart2_rx_buf[256];

static uint8_t usart3_tx_buf[256];
static uint8_t usart3_rx_buf[256];

#define UART1_TX_PORT   GPIOA
#define UART1_TX_PIN    GPIO_Pin_9
#define UART1_TX_SOURCE GPIO_PinSource9
#define UART1_RX_PORT   GPIOA
#define UART1_RX_PIN    GPIO_Pin_10
#define UART1_RX_SOURCE GPIO_PinSource10

#define UART2_TX_PORT   GPIOA
#define UART2_TX_PIN    GPIO_Pin_2
#define UART2_TX_SOURCE GPIO_PinSource2
#define UART2_RX_PORT   GPIOA
#define UART2_RX_PIN    GPIO_Pin_3
#define UART2_RX_SOURCE GPIO_PinSource3

#define UART3_TX_PORT   GPIOB
#define UART3_TX_PIN    GPIO_Pin_10
#define UART3_TX_SOURCE GPIO_PinSource2
#define UART3_RX_PORT   GPIOB
#define UART3_RX_PIN    GPIO_Pin_11
#define UART3_RX_SOURCE GPIO_PinSource3

int usart1_snd_tx_cnt = 0;

// 加入以下代码,支持printf函数,而不需要选择use MicroLIB
// 确保没有从 C 库链接使用半主机的函数
#pragma import(__use_no_semihosting)
#pragma import(__use_no_semihosting_swi)
// 定义_sys_exit() 以避免使用半主机模式
void _sys_exit(int x)
{
    x = x;
}

// 加入以下代码,支持printf函数,而不需要选择use MicroLIB
// 标准库需要的支持函数
struct __FILE
{
    int handle;
};
/* FILE is typedef ’ d in stdio.h. */
FILE __stdout;
FILE __stdin;

int _ttywrch(int ch)
{
    ch = ch;
    return ch;
}

// && !defined(__clang__)
#if defined(__GNUC__)
#define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
#define GETCHAR_PROTOTYPE int __io_getchar(void)
#else
#define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
#define GETCHAR_PROTOTYPE int fgetc(FILE *f)
#endif

PUTCHAR_PROTOTYPE
{
    uint32_t tick;
    usart1_snd_tx_cnt++;

    usart_send_it(&usart1_context, &ch, 1);
    tick = get_systick_ms();

    while (RESET == USART_GetFlagStatus(USART1, USART_FLAG_TXE))
    {
        if (get_systick_ms() - tick > 10)
            break;
    }
    return ch;
}

GETCHAR_PROTOTYPE
{
    uint8_t ch;
    if (0 != usart_receive_read(&usart1_context, &ch, 1))
    {
        return ch;
    }
    return -1;
}

// &&!defined(__clang__)
#if defined(__GNUC__)
__attribute__((weak)) int _write(int file, char *ptr, int len)
{
    (void)file;
    if ((file != STDOUT_FILENO) && (file != STDERR_FILENO))
    {
        return -1;
    }

    for (int index = 0; index < len; index++)
        __io_putchar(*ptr++);
    return len;
}

__attribute__((weak)) int _read(int file, char *ptr, int len)
{
    (void)file;
    if (file != STDIN_FILENO)
    {
        return -1;
    }

    uint8_t ch;
    for (int index = 0; index < len; index++)
    {
        // *ptr++ = __io_getchar();
        if (0 != usart_receive_read(&usart1_context, &ch, 1))
        {
            return ch;
        }
        return -1;
    }
    return len;
}
#endif

#if 0
int getchar(void)
{
    char c = 0;

    // ssize_t
    int bytes_read = read(STDIN_FILENO, &c, sizeof(char));

    if (bytes_read == -1)
    {
        // 读取错误
        return EOF;
    }
    else if (bytes_read == 0)
    {
        // 读取结束
        return EOF;
    }
    else
    {
        // 返回读取的字符
        return (int)c;
    }
}
#else
int getchar(void)
{
    uint8_t ch;
    if (0 != usart_receive_read(&usart1_context, &ch, 1))
    {
        return ch;
    }
    return -1;
}
#endif

static void usart1_config(void)
{
    GPIO_InitTypeDef GPIO_StructInit;
    NVIC_InitTypeDef NVIC_InitStructure;
    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);

    GPIO_StructInit.GPIO_Mode  = GPIO_Mode_AF;
    GPIO_StructInit.GPIO_OType = GPIO_OType_PP;
    GPIO_StructInit.GPIO_Speed = GPIO_Speed_100MHz;
    GPIO_StructInit.GPIO_PuPd  = GPIO_PuPd_UP;
    GPIO_StructInit.GPIO_Pin   = UART1_TX_PIN;
    GPIO_PinAFConfig(UART1_TX_PORT, UART1_TX_SOURCE, GPIO_AF_USART1);
    GPIO_Init(UART1_TX_PORT, &GPIO_StructInit);

    GPIO_StructInit.GPIO_Pin = UART1_RX_PIN;
    GPIO_PinAFConfig(UART1_RX_PORT, UART1_RX_SOURCE, GPIO_AF_USART1);
    GPIO_Init(UART1_RX_PORT, &GPIO_StructInit);

    // Usart1 NVIC 配置
    NVIC_InitStructure.NVIC_IRQChannel                   = USART1_IRQn; // 串口1中断通道
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;           // 抢占优先级
    NVIC_InitStructure.NVIC_IRQChannelSubPriority        = 0;           // 子优先级
    NVIC_InitStructure.NVIC_IRQChannelCmd                = ENABLE;      // IRQ通道使能
    NVIC_Init(&NVIC_InitStructure);
}

static void usart1_deconfig(void)
{
}

static void usart2_config(void)
{
    GPIO_InitTypeDef GPIO_StructInit;
    NVIC_InitTypeDef NVIC_InitStructure;
    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE);

    GPIO_StructInit.GPIO_Mode  = GPIO_Mode_AF;
    GPIO_StructInit.GPIO_OType = GPIO_OType_PP;
    GPIO_StructInit.GPIO_Speed = GPIO_Speed_100MHz;
    GPIO_StructInit.GPIO_PuPd  = GPIO_PuPd_UP;
    GPIO_StructInit.GPIO_Pin   = UART2_TX_PIN;
    GPIO_PinAFConfig(UART2_TX_PORT, UART2_TX_SOURCE, GPIO_AF_USART2);
    GPIO_Init(UART2_TX_PORT, &GPIO_StructInit);

    GPIO_StructInit.GPIO_Pin = UART2_RX_PIN;
    GPIO_PinAFConfig(UART2_RX_PORT, UART2_RX_SOURCE, GPIO_AF_USART2);
    GPIO_Init(UART2_RX_PORT, &GPIO_StructInit);

    // Usart1 NVIC 配置
    NVIC_InitStructure.NVIC_IRQChannel                   = USART2_IRQn; // 串口1中断通道
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;           // 抢占优先级
    NVIC_InitStructure.NVIC_IRQChannelSubPriority        = 0;           // 子优先级
    NVIC_InitStructure.NVIC_IRQChannelCmd                = ENABLE;      // IRQ通道使能
    NVIC_Init(&NVIC_InitStructure);
}

static void usart2_deconfig(void)
{
}

static void usart3_config(void)
{
    GPIO_InitTypeDef GPIO_StructInit;
    NVIC_InitTypeDef NVIC_InitStructure;
    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE);
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3, ENABLE);

    GPIO_StructInit.GPIO_Mode  = GPIO_Mode_AF;
    GPIO_StructInit.GPIO_OType = GPIO_OType_PP;
    GPIO_StructInit.GPIO_Speed = GPIO_Speed_100MHz;
    GPIO_StructInit.GPIO_PuPd  = GPIO_PuPd_UP;
    GPIO_StructInit.GPIO_Pin   = UART3_TX_PIN;
    GPIO_PinAFConfig(UART3_TX_PORT, UART3_TX_SOURCE, GPIO_AF_USART3);
    GPIO_Init(UART3_TX_PORT, &GPIO_StructInit);

    GPIO_StructInit.GPIO_Pin = UART3_RX_PIN;
    GPIO_PinAFConfig(UART3_RX_PORT, UART3_RX_SOURCE, GPIO_AF_USART3);
    GPIO_Init(UART3_RX_PORT, &GPIO_StructInit);

    // Usart1 NVIC 配置
    NVIC_InitStructure.NVIC_IRQChannel                   = USART3_IRQn; // 串口1中断通道
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;           // 抢占优先级
    NVIC_InitStructure.NVIC_IRQChannelSubPriority        = 0;           // 子优先级
    NVIC_InitStructure.NVIC_IRQChannelCmd                = ENABLE;      // IRQ通道使能
    NVIC_Init(&NVIC_InitStructure);
}

static void usart3_deconfig(void)
{
}

usart_context_t usart1_context = {
    USART1,
    usart1_tx_buf,
    sizeof(usart1_tx_buf),
    0,
    0,
    0,
    usart1_rx_buf,
    sizeof(usart1_rx_buf),
    0,
    0,
    0,
    usart1_config,
    usart1_deconfig};

usart_context_t usart2_context = {
    USART2,
    usart2_tx_buf,
    sizeof(usart2_tx_buf),
    0,
    0,
    0,
    usart2_rx_buf,
    sizeof(usart2_rx_buf),
    0,
    0,
    0,
    usart2_config,
    usart2_deconfig};

usart_context_t usart3_context = {
    USART3,
    usart3_tx_buf,
    sizeof(usart3_tx_buf),
    0,
    0,
    0,
    usart3_rx_buf,
    sizeof(usart3_rx_buf),
    0,
    0,
    0,
    usart3_config,
    usart3_deconfig};

void usart_config_init(usart_context_t *p_usart_content, uint32_t band_rate)
{
    p_usart_content->config();

    USART_InitTypeDef USART_InitStructure;

    USART_InitStructure.USART_BaudRate            = band_rate;
    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(p_usart_content->usart_periph, &USART_InitStructure); // 初始化串口

    USART_ITConfig(p_usart_content->usart_periph, USART_IT_RXNE, ENABLE);

    USART_Cmd(p_usart_content->usart_periph, ENABLE); // 使能串口
}

void usart_config_deinit(usart_context_t *p_usart_content)
{
    USART_DeInit(p_usart_content->usart_periph);
    p_usart_content->deconfig();
}

void usart_send(usart_context_t *p_usart_content, const void *_send_buf, const uint16_t send_count)
{
    const uint8_t *send_buf = (const uint8_t *)_send_buf;
    uint16_t       i;
    for (i = 0; i < send_count; i++)
    {
        while (RESET == USART_GetFlagStatus(p_usart_content->usart_periph, USART_FLAG_TXE))
            ;
        USART_SendData(p_usart_content->usart_periph, (uint8_t)send_buf[i]);
    }
    while (RESET == USART_GetFlagStatus(p_usart_content->usart_periph, USART_FLAG_TC))
        ;
}

int32_t usart_read_until_char(usart_context_t *p_usart_content, char c)
{
    uint32_t i;

    for (i = p_usart_content->rx_rd; i < p_usart_content->rx_wr; i++)
    {
        if (p_usart_content->rx_buf[i % p_usart_content->rx_buf_size] == c)
        {
            return i;
        }
    }
    return -1;
}

// read until memory
// return:第一次出现mem位置， -1 没找到
int32_t usart_read_until_mem(usart_context_t *p_usart_content, char *mem, int len)
{
    int32_t i, j, pos;

    for (i = p_usart_content->rx_rd; i < p_usart_content->rx_wr; i++)
    {
        // overflow
        for (j = 0; j < len; j++)
        {
            pos = i + j;
            if (p_usart_content->rx_buf[pos % p_usart_content->rx_buf_size] != mem[j])
            {
                break;
            }
        }
        // 找到内存快
        if (j == len)
        {
            return i;
        }
    }
    return -1;
}

// read ble format 04 FC code len data
// return 满足format条件结束位置， -1 没找到
int32_t usart_read_ble_format(usart_context_t *p_usart_content)
{
    uint16_t rx_wr = p_usart_content->rx_wr;
    uint16_t rx_rd = p_usart_content->rx_rd;

    if (rx_wr < rx_rd)
    {
        rx_wr += p_usart_content->rx_buf_size;
    }

    if (rx_wr - rx_rd < 4)
    {
        return -1;
    }

    // 第一次开机跳过特殊桢处理 00 04，跳过00
    if (p_usart_content->rx_buf[rx_rd % p_usart_content->rx_buf_size] == 0x00 || p_usart_content->rx_buf[(rx_rd + 1) % p_usart_content->rx_buf_size] == 0x04)
    {
        p_usart_content->rx_rd++;
        p_usart_content->rx_rd %= p_usart_content->rx_buf_size;
        return -4;
    }

    if (p_usart_content->rx_buf[rx_rd % p_usart_content->rx_buf_size] != 0x04 || p_usart_content->rx_buf[(rx_rd + 1) % p_usart_content->rx_buf_size] != 0xFC)
    {
        return -2;
    }

    // 蓝牙长度不够
    if (rx_wr - rx_rd < p_usart_content->rx_buf[(rx_rd + 3) % p_usart_content->rx_buf_size] + 4)
    {
        return -3;
    }
    return p_usart_content->rx_buf[(rx_rd + 3) % p_usart_content->rx_buf_size] + 4;
}

int32_t usart_copy_data(usart_context_t *p_usart_content, int rlen, char *data)
{
    int32_t i, p;

    // 拷贝rlen + 1个数据
    for (i = 0; i < rlen; i++)
    {
        p       = (p_usart_content->rx_rd + i) % p_usart_content->rx_buf_size;
        data[i] = p_usart_content->rx_buf[p];
    }

    return 0;
}

int32_t usart_read_update(usart_context_t *p_usart_content, int rlen, char *data)
{
    int32_t i, p;

    // 拷贝rlen + 1个数据
    for (i = 0; i < rlen; i++)
    {
        p       = (p_usart_content->rx_rd + i) % p_usart_content->rx_buf_size;
        data[i] = p_usart_content->rx_buf[p];
    }

    // 指定pos下一个位置
    // return p_usart_content->rx_rd = (p_usart_content->rx_rd + rlen) % p_usart_content->rx_buf_size;
    p = p_usart_content->rx_rd = (p_usart_content->rx_rd + rlen) % p_usart_content->rx_buf_size;
    return p;
}

void usart_send_it(usart_context_t *p_usart_content, const void *_send_buf, const uint16_t send_count)
{
    const uint8_t *send_buf = (const uint8_t *)_send_buf;
    uint16_t       i;
    uint16_t       left;

    // 空间不够直接返回
    if (p_usart_content->tx_wr >= p_usart_content->tx_rd)
    {
        left = p_usart_content->tx_buf_size - (p_usart_content->tx_wr - p_usart_content->tx_rd);
    }
    else
    {
        left = p_usart_content->tx_rd - p_usart_content->tx_wr;
        if (send_count > left)
        {
            p_usart_content->tx_err++;
            return;
        }
    }

    // 内存拷贝
    for (i = 0; i < send_count; i++)
    {
        // send buffer overflow just wait
        p_usart_content->tx_buf[p_usart_content->tx_wr++] = send_buf[i];
        p_usart_content->tx_wr %= p_usart_content->tx_buf_size;
    }

    // 使能发送缓存空中断
    USART_ITConfig(p_usart_content->usart_periph, USART_IT_TXE, ENABLE);
}

void usart_wait_send_finished(usart_context_t *p_usart_content)
{
    while (p_usart_content->tx_wr != p_usart_content->tx_rd)
        ;
    while (RESET == USART_GetFlagStatus(p_usart_content->usart_periph, USART_FLAG_TC))
        ;
}

int usart_receive_read(usart_context_t *p_usart_context, void *_receive_buf, const int receive_count)
{
    uint8_t *receive_buf = (uint8_t *)_receive_buf;
    int      i, receive_count_real;

    /* Read data from receive buffer.
     *The buffer have data that received from usart.
     */
    for (i = 0, receive_count_real = 0; i < receive_count; i++)
    {
        if (p_usart_context->rx_rd == p_usart_context->rx_wr)
        {
            return receive_count_real;
        }
        else
        {
            receive_buf[i] = p_usart_context->rx_buf[p_usart_context->rx_rd++];
            p_usart_context->rx_rd %= p_usart_context->rx_buf_size;
            receive_count_real++;
        }
    }
    return receive_count_real;
}

static void usart_rxne_it(usart_context_t *p_usart_content)
{
    p_usart_content->rx_buf[p_usart_content->rx_wr++] = USART_ReceiveData(p_usart_content->usart_periph);
    p_usart_content->rx_wr %= p_usart_content->rx_buf_size;

    // overflow handle
    if (p_usart_content->rx_wr == p_usart_content->rx_rd)
    {
        p_usart_content->rx_rd++;
        p_usart_content->rx_rd %= p_usart_content->rx_buf_size;
    }
}

static void usart_txe_it(usart_context_t *p_usart_content)
{
    if (p_usart_content->tx_rd != p_usart_content->tx_wr)
    {
        USART_SendData(p_usart_content->usart_periph, p_usart_content->tx_buf[p_usart_content->tx_rd++]);
        p_usart_content->tx_rd %= p_usart_content->tx_buf_size;
    }
    else
    {
        USART_ITConfig(p_usart_content->usart_periph, USART_IT_TXE, DISABLE);
    }
}

void usart_it(usart_context_t *p_usart_content)
{
    // 读取缓沖区非空中断
    if (SET == USART_GetFlagStatus(p_usart_content->usart_periph, USART_FLAG_RXNE))
    {
        USART_ClearFlag(p_usart_content->usart_periph, USART_FLAG_RXNE);
        usart_rxne_it(p_usart_content);
    }

    // 发送缓沖区空中断
    if (SET == USART_GetFlagStatus(p_usart_content->usart_periph, USART_FLAG_TXE))
    {
        USART_ClearFlag(p_usart_content->usart_periph, USART_FLAG_TXE);
        usart_txe_it(p_usart_content);
    }

    // // 发送完成中断
    // if (RESET != USART_GetFlagStatus(p_usart_content->usart_periph, USART_FLAG_TC))
    // {
    //     USART_ITConfig(p_usart_content->usart_periph, USART_FLAG_TC, DISABLE);
    //     USART_ITConfig(p_usart_content->usart_periph, USART_FLAG_RXNE, ENABLE);
    // }

    // 发送错误
    if (RESET != USART_GetFlagStatus(p_usart_content->usart_periph, USART_FLAG_ORE))
        USART_ClearFlag(p_usart_content->usart_periph, USART_FLAG_ORE);
}

void USART1_IRQHandler(void)
{
    usart_it(&usart1_context);
}

void USART2_IRQHandler(void)
{
    usart_it(&usart2_context);
}

void USART3_IRQHandler(void)
{
    usart_it(&usart3_context);
}