#include "drv_clk.h"
#include "drv_dma.h"
#include "drv_gpio.h"
#include "drv_uart.h"
#include "drv_misc.h"
#include "kit_debug.h"

#define USART_BRR_2400_AT_72M    ((uint16_t)0x7530)
#define USART_BRR_2400_AT_36M    ((uint16_t)0x3A98)
#define USART_BRR_2400_AT_84M    ((uint16_t)0x88B8)
#define USART_BRR_2400_AT_42M    ((uint16_t)0x445C)
#define USART_BRR_2400_AT_96M    ((uint16_t)0x9C40)
#define USART_BRR_2400_AT_48M    ((uint16_t)0x4E20)
#define USART_BRR_2400_AT_120M   ((uint16_t)0xC350)
#define USART_BRR_2400_AT_60M    ((uint16_t)0x61A8)

typedef struct 
{
    KitIrqCall call[kUartInterrupt_End];
    
    uint16_t buf_len;
    uint16_t send_pos;
    uint8_t  *send_buf;
    
}UartIntItem;

UartIntItem uart_int_item[kUartDev_End];

typedef struct
{
    uint8_t     irq;
    
	DmaStream  rx_dma_stream;
    DmaStream  tx_dma_stream;
    DmaChannel dma_channel;
    USART_TypeDef* reg;
    uint32_t base_baudrate;
}STM32UsartProp;

static const STM32UsartProp stm32_uart[kUartDev_End] = 
{
    {USART1_IRQn, kDma2Stream_2, kDma2Stream_7, kDmaChannel_4, USART1, USART_BRR_2400_AT_84M},
    {USART2_IRQn, kDma1Stream_5, kDma1Stream_6, kDmaChannel_4, USART2, USART_BRR_2400_AT_42M},
    {USART3_IRQn, kDma1Stream_1, kDma1Stream_3, kDmaChannel_4, USART3, USART_BRR_2400_AT_42M},
	{UART4_IRQn,  kDma1Stream_2, kDma1Stream_4, kDmaChannel_4, UART4, USART_BRR_2400_AT_42M},
    {UART5_IRQn,  kDma1Stream_0, kDma1Stream_7, kDmaChannel_5, UART5, USART_BRR_2400_AT_42M},
    {USART6_IRQn, kDma2Stream_1, kDma2Stream_6, kDmaChannel_5, USART6, USART_BRR_2400_AT_84M},     
};



#define UART_FLAG_TXE	KIT_BIT_MASK_32(7)
kit_ret_e drv_uart_series_sync_send(UartDev dev, uint8_t *buf, uint16_t len)
{
    uint32_t i = 0, dly;
    USART_TypeDef *reg = stm32_uart[dev].reg;
    while(i < len)
    {
        dly = 0;
        while((reg->SR & UART_FLAG_TXE) != UART_FLAG_TXE)
        {          
            if(dly++ > 20000)
			{
				return kKit_Ret_TimeOut;
			} 
        }       
        reg->DR = buf[i++];
    }
	
	return kKit_Ret_Ok;
}

kit_ret_e drv_uart_dma_async_send(UartDev dev, uint8_t *buf, uint16_t len)
{
    kit_ret_e res;
    KIT_ASSERT_PARAM((dev < kUartDev_End) && (buf != NULL) && (len > 0));
    
    if((dev < kUartDev_End) && (buf != NULL) && (len > 0))
    {      
        stm32_uart[dev].reg->SR &= ~USART_SR_TC;
        drv_dma_set_buf(stm32_uart[dev].tx_dma_stream, buf, len);
        res = kKit_Ret_Ok;
    }
    else
    {
        res = kKit_Ret_ParamErr;
    }
    return res;
}

kit_ret_e drv_uart_int_async_send(UartDev dev, uint8_t *buf, uint16_t len)
{
    kit_ret_e res;
    KIT_ASSERT_PARAM((dev < kUartDev_End) && (buf != NULL) && (len > 0));
    
    if((dev < kUartDev_End) && (buf != NULL) && (len > 0))
    {      
        stm32_uart[dev].reg->SR &= ~USART_SR_TC;

        uart_int_item[dev].buf_len = len;
        uart_int_item[dev].send_pos = 1;
        uart_int_item[dev].send_buf = buf;
        
        stm32_uart[dev].reg->DR = buf[0];
        stm32_uart[dev].reg->CR1 |= USART_CR1_TXEIE;
        
        res = kKit_Ret_Ok;
    }
    else
    {
        res = kKit_Ret_ParamErr;
    }
    return res;
}

#define GPIO_REMAP_UART0            KIT_BIT_MASK_32(2)
#define GPIO_REMAP_UART1            KIT_BIT_MASK_32(3)
#define GPIO_PARTIAL_REMAP_UART2    KIT_BIT_MASK_32(4)
#define GPIO_FULL_REMAP2_UART2      KIT_BIT_MASK_32S(4,5)
/********************************************************************************
  Func   UART0_REMAP = 0  UART0_REMAP = 1 | UART1_REMAP = 0   UART1_REMAP = 1 | UART2_REMAP = 0  UART2_REMAP = 1   UART1_REMAP = 2
UART_TX 	PA9 	           PB6	      |    PA2 	              PD5         |      PB10 	        PC10                PD8
UART_RX 	PA10 	           PB7	      |    PA3 	              PD6         |      PB11 	        PC11                PD9
********************************************************************************/
static kit_ret_e drv_uart_set_clock_gpio(UartDev dev, uint16_t tx_idx, uint16_t rx_idx)
{
    kit_ret_e res = kKit_Ret_Ok;
    
    uint32_t tx_io = drv_gpio_get_actual_io(tx_idx);
    uint32_t rx_io = drv_gpio_get_actual_io(rx_idx);   
    switch (dev)
    {
        case kUartDev_1:
			RCC->APB2ENR |= RCC_APB2ENR_USART1EN;
            if((tx_io == GPIO_PORT_PIN(kGpioPort_A, 9)) && (rx_io == GPIO_PORT_PIN(kGpioPort_A, 10))) 
            {
				drv_gpio_set_af(kGpioPort_A, 9, 7);
				drv_gpio_set_af(kGpioPort_A, 10, 7);
			}
            else if((tx_io == GPIO_PORT_PIN(kGpioPort_B, 6)) && (rx_io == GPIO_PORT_PIN(kGpioPort_B, 7))) 
            {
                drv_gpio_set_af(kGpioPort_B, 6, 7);//设置复用功能，7表示复用未usart1-3;
				drv_gpio_set_af(kGpioPort_B, 7, 7);
            }
            else
            {
                res |= kKit_Ret_ParamErr;
            } 
            break;
        
        case kUartDev_2:
			RCC->APB1ENR |= RCC_APB1Periph_USART2;
            if((tx_io == GPIO_PORT_PIN(kGpioPort_A, 2)) && (rx_io == GPIO_PORT_PIN(kGpioPort_A, 3))) 
            {
				drv_gpio_set_af(kGpioPort_A, 2, 7);
				drv_gpio_set_af(kGpioPort_A, 3, 7);
			}
            else if((tx_io == GPIO_PORT_PIN(kGpioPort_D, 5)) && (rx_io == GPIO_PORT_PIN(kGpioPort_D, 6))) 
            {
                drv_gpio_set_af(kGpioPort_D, 5, 7);
				drv_gpio_set_af(kGpioPort_D, 6, 7);
            }
            else if((tx_io == GPIO_PORT_PIN(kGpioPort_D, 5)) && (rx_io == GPIO_PORT_PIN(kGpioPort_A, 3))) 
            {
                drv_gpio_set_af(kGpioPort_D, 5, 7);
				drv_gpio_set_af(kGpioPort_A, 3, 7);
            }
            else
            {
                res |= kKit_Ret_ParamErr;
            }
            break;         
        case kUartDev_3:
			RCC->APB1ENR |= RCC_APB1Periph_USART3;
            if((tx_io == GPIO_PORT_PIN(kGpioPort_B, 10)) && (rx_io == GPIO_PORT_PIN(kGpioPort_B, 11))) 
            {
				drv_gpio_set_af(kGpioPort_B, 10, 7);
				drv_gpio_set_af(kGpioPort_B, 11, 7);
			}
            else if((tx_io == GPIO_PORT_PIN(kGpioPort_C, 10)) && (rx_io == GPIO_PORT_PIN(kGpioPort_C, 11))) 
            {
                drv_gpio_set_af(kGpioPort_C, 10, 7);
				drv_gpio_set_af(kGpioPort_C, 11, 7);
            }
            else if((tx_io == GPIO_PORT_PIN(kGpioPort_D, 8)) && (rx_io == GPIO_PORT_PIN(kGpioPort_B, 11))) 
            {
                drv_gpio_set_af(kGpioPort_D, 8, 7);
				drv_gpio_set_af(kGpioPort_B, 11, 7);
            }
            else if((tx_io == GPIO_PORT_PIN(kGpioPort_D, 8)) && (rx_io == GPIO_PORT_PIN(kGpioPort_D, 9))) 
            {
                drv_gpio_set_af(kGpioPort_D, 8, 7);
				drv_gpio_set_af(kGpioPort_D, 9, 7);
            }
            else if((tx_io == GPIO_PORT_PIN(kGpioPort_B, 10)) && (rx_io == GPIO_PORT_PIN(kGpioPort_D, 9))) 
            {
				drv_gpio_set_af(kGpioPort_B, 10, 7);
                drv_gpio_set_af(kGpioPort_D, 9, 7);
            }
            else
            {
                res |= kKit_Ret_ParamErr;
            }             
            break;
		case kUartDev_4:
			RCC->APB1ENR |= RCC_APB1Periph_UART4;
            if((tx_io == GPIO_PORT_PIN(kGpioPort_A, 0)) && (rx_io == GPIO_PORT_PIN(kGpioPort_A, 1))) 
            {
				drv_gpio_set_af(kGpioPort_A, 0, 8);
				drv_gpio_set_af(kGpioPort_A, 1, 8);
			}
            else if((tx_io == GPIO_PORT_PIN(kGpioPort_C, 10)) && (rx_io == GPIO_PORT_PIN(kGpioPort_C, 11))) 
            {
                drv_gpio_set_af(kGpioPort_C, 10, 8);
				drv_gpio_set_af(kGpioPort_C, 11, 8);
            }
            else
            {
                res |= kKit_Ret_ParamErr;
            }             
            break;             
	case kUartDev_5:
			RCC->APB1ENR |= RCC_APB1Periph_UART5;
            if((tx_io == GPIO_PORT_PIN(kGpioPort_C, 12)) && (rx_io == GPIO_PORT_PIN(kGpioPort_D, 2))) 
            {
                drv_gpio_set_af(kGpioPort_C, 12, 8);
				drv_gpio_set_af(kGpioPort_D, 2, 8);
            }
            else
            {
                res |= kKit_Ret_ParamErr;
            }             
            break;             
	case kUartDev_6:
			RCC->APB2ENR |= RCC_APB2ENR_USART6EN;
            if((tx_io == GPIO_PORT_PIN(kGpioPort_C, 6)) && (rx_io == GPIO_PORT_PIN(kGpioPort_C, 7))) 
            {
                drv_gpio_set_af(kGpioPort_C, 6, 8);
				drv_gpio_set_af(kGpioPort_C, 7, 8);
            }
            else
            {
                res |= kKit_Ret_ParamErr;
            }             
            break;
#if defined(STM32F429_439xx)             
    case kUartDev_7:
			RCC->APB1ENR |= RCC_APB1ENR_UART7EN;
            if((tx_io == GPIO_PORT_PIN(kGpioPort_F, 7)) && (rx_io == GPIO_PORT_PIN(kGpioPort_F, 6))) 
            {
                drv_gpio_set_af(kGpioPort_F, 6, 8);
				drv_gpio_set_af(kGpioPort_F, 7, 8);
            }
            else
            {
                res |= kKit_Ret_ParamErr;
            }             
            break;
#endif            
        default:
            res = kKit_Ret_ParamErr;
            break;
    }
    
    return res;
}


#define USER_CR1_UE             KIT_BIT_MASK_32(13)  //enable usart
#define USER_CR1_TXEIE          KIT_BIT_MASK_32(7)
#define USER_CR1_TCIE           KIT_BIT_MASK_32(6)
#define USER_CR1_RXNEIE         KIT_BIT_MASK_32(5)
#define USER_CR1_TXEIE          KIT_BIT_MASK_32(7)
#define USER_CR1_PCE_EN         KIT_BIT_MASK_32(10)  //enable parity 

#define USER_SR1_TXEIE          KIT_BIT_MASK_32(7)
#define USER_SR1_TCIE           KIT_BIT_MASK_32(6)
#define USER_SR1_RXNEIE         KIT_BIT_MASK_32(5)
#define USART_Mode_Rx           KIT_BIT_MASK_32(2)
#define USART_Mode_Tx           KIT_BIT_MASK_32(3)
#define USART_FLAG_ORE          ((uint16_t)0x0008)
#define USART_FLAG_RXNE         ((uint16_t)0x0020)


kit_ret_e drv_uart_init(UartDev dev, uint32_t baudrate, uint32_t uart_config,  uint8_t tx_io, uint8_t rx_io)
{
    uint32_t tmp;
    USART_TypeDef *reg;
	kit_ret_e res = kKit_Ret_Ok;

    KIT_ASSERT_PARAM((dev < kUartDev_End) && ((baudrate % 2400) == 0));
    
	if (((baudrate % 2400) == 0) && (dev < kUartDev_End))
	{
		reg = stm32_uart[dev].reg;
		drv_uart_set_clock_gpio(dev, tx_io, rx_io);
		//计算波特率，基于2400
		reg->BRR = stm32_uart[dev].base_baudrate / (baudrate / 2400);
		//使能收、发和uart
		tmp = USER_CR1_UE | USART_Mode_Rx | USART_Mode_Tx;
		//设置数据长度
		tmp |= (uart_config & 0x0001) << 12;
		//设置校验
		tmp |= ((uart_config & 0x0006) >> 1) << 9;
		//停止位长度
		reg->CR2 |= ((uart_config & 0x0018) >> 3) << 12;
		
		reg->CR1 |= tmp;
		
	}
	else
	{
		res = kKit_Ret_ParamErr;
	}

    return res;
}



static const uint16_t uart_irq_flag[kUartInterrupt_End] = {USER_CR1_RXNEIE, USER_CR1_TXEIE};
kit_ret_e drv_uart_set_interrupt(UartDev dev, UartInterrupt it_type, uint16_t priority, KitIrqCall call)
{
    kit_ret_e res;
    KIT_ASSERT_PARAM((dev < kUartDev_End) && (it_type < kUartInterrupt_End));
    
    if((dev < kUartDev_End) && (it_type < kUartInterrupt_End))
    {
        uart_int_item[dev].call[it_type] = call;
        drv_misc_set_nvic(stm32_uart[dev].irq, priority);
        res = kKit_Ret_Ok;
    }
    else
    {
        res = kKit_Ret_ParamErr;
    }
    
    return res;
}

void drv_uart_ctrl_interrupt(UartDev dev, UartInterrupt it_type, bool is_enable)
{
    KIT_ASSERT_PARAM((dev < kUartDev_End) && (it_type < kUartInterrupt_End));
    
    if(is_enable == true)
    {
        stm32_uart[dev].reg->CR1 |= uart_irq_flag[it_type];
    }
    else
    {
        stm32_uart[dev].reg->CR1 &= ~uart_irq_flag[it_type];
    }
}


kit_ret_e drv_uart_set_dma(UartDev dev, bool is_rx_en, bool is_tx_en)
{
    uint32_t    tmp;
    kit_ret_e   res= kKit_Ret_Ok;
    USART_TypeDef *reg;
    
    KIT_ASSERT_PARAM(dev < kUartDev_End);
    
    if(dev < kUartDev_End)
    {
        reg = stm32_uart[dev].reg;
        tmp = reg->CR3;
        if(is_rx_en == true)
        {
            drv_dma_init(stm32_uart[dev].rx_dma_stream, stm32_uart[dev].dma_channel, DMA_CFG_DATA_DIR_P2M|DMA_CFG_CYCLE_NONE|DMA_CFG_DATA_M_I|DMA_CFG_DATA_P_N|DMA_CFG_DATA_LEN_1B, (uint32_t)&reg->DR);
            tmp |= USART_CR3_DMAR;
        } 
        else
		{
			tmp &= ~USART_CR3_DMAR;
		}
        
        if(is_tx_en == true)
        {
            drv_dma_init(stm32_uart[dev].tx_dma_stream, stm32_uart[dev].dma_channel, DMA_CFG_DATA_DIR_M2P|DMA_CFG_CYCLE_NONE|DMA_CFG_DATA_M_I|DMA_CFG_DATA_P_N|DMA_CFG_DATA_LEN_1B, (uint32_t)&reg->DR);
            tmp |= USART_CR3_DMAT;
        } 
        else
		{
			tmp &= ~USART_CR3_DMAT;
		}
        reg->CR3 = tmp;
    }
    else
    {
        res = kKit_Ret_OutRange;
    }
    
    return res;    
}

static void uart_irq_handler(UartDev dev)
{
    uint8_t data;
    UartIntItem *item = &uart_int_item[dev];
    USART_TypeDef* reg = stm32_uart[dev].reg;
    /* USART接收溢出中断ORE清标志位,只要使能RXNE,ORE中断默认使能*/
    if(((reg->CR1 & USER_CR1_RXNEIE) == USER_CR1_RXNEIE)  
   && (((reg->SR & USART_FLAG_RXNE) != 0) || ((reg->SR & USART_FLAG_ORE) != 0)))    
    {
        data = reg->DR;

        if(item->call[kUartInterrupt_Rx] != NULL)
        {
            item->call[kUartInterrupt_Rx](kKit_Ret_Ok, &data);
        }
    }
    else if((reg->SR & USER_SR1_TCIE) != 0)
    {
        //清除标志位
        stm32_uart[dev].reg->SR &= ~USART_SR_TC;
        //关闭发送完成中断
        stm32_uart[dev].reg->CR1 &= ~USER_CR1_TCIE;
		if(item->call[kUartInterrupt_Tx] != NULL)
        {
        	item->call[kUartInterrupt_Tx](kKit_Ret_Ok, &dev);//拉电平使能接收
		}
    }
    else if((reg->SR & USER_SR1_TXEIE) != 0)
    {
        if(item->send_pos < item->buf_len)
        {
            reg->DR = item->send_buf[item->send_pos++];
            if(item->send_pos >= item->buf_len)
            {
                //关闭发送缓冲区空中断
                stm32_uart[dev].reg->CR1 &= ~USER_CR1_TXEIE;
                //打开发送完成中断
                stm32_uart[dev].reg->CR1 |= USER_CR1_TCIE;
            }
        }
        else
        {
            //关闭发送缓冲区空中断
            stm32_uart[dev].reg->CR1 &= ~USER_CR1_TXEIE;
            //打开发送完成中断
            stm32_uart[dev].reg->CR1 |= USER_CR1_TCIE;
        }
    }
}

void USART1_IRQHandler(void)
{
    uart_irq_handler(kUartDev_1);
}

void USART2_IRQHandler(void)
{
    uart_irq_handler(kUartDev_2); 
}

void USART3_IRQHandler(void)
{
    uart_irq_handler(kUartDev_3);   
}

void UART4_IRQHandler(void)
{
    uart_irq_handler(kUartDev_4);   
}

void UART5_IRQHandler(void)
{
    uart_irq_handler(kUartDev_5);   
}

void USART6_IRQHandler(void)
{
    uart_irq_handler(kUartDev_6);   
}

#if defined(STM32F429_439xx)
void UART7_IRQHandler(void)
{
    uart_irq_handler(kUartDev_7);   
}
#endif

