#include "uart_ht7315.h"
#include "stdio.h"

#define QUEUE_SIZE 8

volatile char buffer[4];
volatile int buffer_index = 0;

typedef struct {
    char buffer[QUEUE_SIZE];
    int head;
    int tail;
    int size;
} CircularQueue;

// 閸忋劌鐪梼鐔峰灙
CircularQueue rxQueue = {{0}, 0, 0, 0};

void initQueue(CircularQueue *q) {
    q->head = 0;
    q->tail = 0;
    q->size = 0;
}

int isQueueFull(CircularQueue *q) {
    return q->size == QUEUE_SIZE;
}

int isQueueEmpty(CircularQueue *q) {
    return q->size == 0;
}

void enqueue(CircularQueue *q, char data) {
    if (!isQueueFull(q)) {
        q->buffer[q->tail] = data;
        q->tail = (q->tail + 1) % QUEUE_SIZE;
        q->size++;
    }
}

char dequeue(CircularQueue *q) {
    char data = 0;
    if (!isQueueEmpty(q)) {
        data = q->buffer[q->head];
        q->head = (q->head + 1) % QUEUE_SIZE;
        q->size--;
    }
    return data;
}

void clearQueue(CircularQueue *q) {
    q->head = 0;
    q->tail = 0;
    q->size = 0;
}


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

    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB| RCC_APB2Periph_USART1, ENABLE);
    //RCC_APB2PeriphClockCmd( RCC_APB2Periph_AFIO, ENABLE );

    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
    GPIO_Init( GPIOA, &GPIO_InitStructure );
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
    GPIO_Init( GPIOA, &GPIO_InitStructure );

    USART_InitStructure.USART_BaudRate = UART_U6710_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_Tx | USART_Mode_Rx;

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

    NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 4;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 4;
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStructure);

    NVIC_EnableIRQ(USART1_IRQn);
    USART_Cmd( USART1, ENABLE );
}

void USART1_SendData(PUINT8 txbuf, UINT16 length)
{
    //printf("USART1_SendData\r\n");
    UINT8 TxCnt = 0;
    while(TxCnt < length) {
        USART_SendData(USART1, txbuf[TxCnt++]);
        while(USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET) {
            /* 缁涘绶熼崣鎴︼拷浣哥暚閹达拷 */
            //printf("TxCnt:%d\r\n", TxCnt);
        }
    }
}

void USART1_IRQHandler(void) __attribute__((interrupt("WCH-Interrupt-fast")));
void USART1_IRQHandler(void)
{
    if (USART_GetITStatus(USART1, USART_IT_RXNE) != RESET) {
        char received_char = USART_ReceiveData(USART1);
        //printf("buffer_index: %d\n", buffer_index);
        switch (buffer_index) {
            case 0:
                if (received_char == 'P') {
                    buffer[buffer_index++] = received_char;
                }
                break;
            case 1:
                if (received_char == 'O') {
                    buffer[buffer_index++] = received_char;
                } else {
                    buffer_index = 0; // 闁插秶鐤嗙紓鎾冲暱閸栵拷
                }
                break;
            case 2:
                if (received_char == 'F') {
                    buffer[buffer_index++] = received_char;
                    // 閹垫挸宓冨☉鍫熶紖
                    printf("[PowerOFF!] \n");
                    buffer_index = 0; // 闁插秶鐤嗙紓鎾冲暱閸栵拷
                    // 鐟欙箑褰傜化鑽ょ埠婢跺秳缍�
                    NVIC_SystemReset();
                } else {
                    buffer_index = 0; // 闁插秶鐤嗙紓鎾冲暱閸栵拷
                }
                break;
            default:
                buffer_index = 0; // 闁插秶鐤嗙紓鎾冲暱閸栵拷
                break;
        }
    }
    // 濞撳懘娅庢稉顓熸焽閺嶅洤绻�
    USART_ClearITPendingBit(USART1, USART_IT_RXNE);
}
