#include "usart.h"


    /*  \arg        COM_EC800:   EC800
        \arg        COM_485: 485
	    \arg        COM_232: 232
    */
static rcu_periph_enum COM_CLK[COMn] = {COM_EC800_CLK, COM_485_CLK, COM_232_CLK};
static uint32_t COM_TX_PIN[COMn] = {COM_EC800_TX_PIN, COM_485_TX_PIN, COM_232_TX_PIN};
static uint32_t COM_RX_PIN[COMn] = {COM_EC800_RX_PIN, COM_485_RX_PIN, COM_232_RX_PIN};
static uint32_t COM_GPIO_PORT[COMn] = {COM_EC800_GPIO_PORT, COM_485_GPIO_PORT, COM_232_GPIO_PORT};
static rcu_periph_enum COM_GPIO_CLK[COMn] = {COM_EC800_GPIO_CLK, COM_485_GPIO_CLK, COM_232_GPIO_CLK};	  
static uint32_t COM_IT_HANDLER[COMn] = {COM_EC800_IT_HANDLER, COM_485_IT_HANDLER, COM_232_IT_HANDLER};
static uint32_t COM_BAUDTATE[COMn]={COM_EC800_BAUDRATE,COM_485_BAUDRATE,COM_232_BAUDRATE};

		
uint8_t UART0_RX_BUF[UART0_RX_LEN];
uint8_t UART0_RX_STAT = 0;
uint8_t UART0_RX_MQTT_SUB_STAT=0;            //mqttt订阅信息标志位
uint32_t UART0_RX_NUM = 0;	

usart_data_buf_t usart1_rx_buf;
//清除dma buffer内数据
void Clear_DMA_Buffer(void)
{
   UART0_RX_NUM=0;
   memset(UART0_RX_BUF,0,UART0_RX_LEN);
}

/*!
    \brief      configure 485 DE gpio
    \param[out] none
    \retval     none
*/
void gd_485_DE_pin_init(void)
{
    /* enable the 485 DE pin clock */
    rcu_periph_clock_enable(RCU_GPIOA);
    /* configure 485 DE GPIO port */ 
    gpio_init(GPIOA, GPIO_MODE_OUT_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_8);

    GPIO_BC(GPIOA) = GPIO_PIN_8;
}

/*!
    \brief      turn 485 to tx
    \param[out] none
    \retval     none
*/
void gd_485_DE_tx(void)
{
    GPIO_BOP(GPIOA) = GPIO_PIN_8;
}

/*!
    \brief      turn 485 to rx
    \param[out] none
    \retval     none
*/
void gd_485_DE_rx(void)
{
    GPIO_BC(GPIOA) = GPIO_PIN_8;
}


/*!
    \brief      configure COM port
    \param[in]  com: COM on the board
        \arg        COM_EC800:   EC800
        \arg        COM_485: 485
	    \arg        COM_232: 232
    \param[out] none
    \retval     none
*/
void gd_com_init(uint32_t com)
{
    uint32_t com_id = 0U;
    if(COM_EC800 == com)
	{
        com_id = 0U;
    }
	else if(COM_485 == com)
	{
		com_id=1U;
	}
	else if(COM_232 == com)
	{
        com_id = 2U;
		//重映射usart2端口
				rcu_periph_clock_enable(RCU_AF);
				gpio_pin_remap_config(GPIO_USART2_FULL_REMAP, ENABLE);
    }

	//nvic_irq_enable(COM_IT_HANDLER[com_id], 0, 0);
    
    /* enable GPIO clock */
				
    rcu_periph_clock_enable(COM_GPIO_CLK[com_id]);

    /* enable USART clock */
    rcu_periph_clock_enable(COM_CLK[com_id]);
		
		
    /* connect port to USARTx_Tx */
    gpio_init(COM_GPIO_PORT[com_id], GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, COM_TX_PIN[com_id]);

    /* connect port to USARTx_Rx */
    gpio_init(COM_GPIO_PORT[com_id], GPIO_MODE_IN_FLOATING, GPIO_OSPEED_50MHZ, COM_RX_PIN[com_id]);
		
		
    /* USART configure */
    usart_deinit(com);
    usart_baudrate_set(com, COM_BAUDTATE[com_id]);
    usart_word_length_set(com, USART_WL_8BIT);
    usart_stop_bit_set(com, USART_STB_1BIT);
    usart_parity_config(com, USART_PM_NONE);
    usart_hardware_flow_rts_config(com, USART_RTS_DISABLE);
    usart_hardware_flow_cts_config(com, USART_CTS_DISABLE);
    usart_receive_config(com, USART_RECEIVE_ENABLE);
    usart_transmit_config(com, USART_TRANSMIT_ENABLE);
    usart_enable(com);
	// usart_interrupt_enable(com, USART_INT_TBE);
	  usart_interrupt_enable(com, USART_INT_RBNE);  //开启接受终端
   	usart_interrupt_enable(com, USART_INT_IDLE);    //开启空闲终端，也叫帧终端
    
}

/*!
    \brief      COM port to send buff
    \param[in]  com: COM on the board
    \arg        COM_485
    \param[out] none
    \retval     none
*/
void gd_com_485_send(uint8_t *message,uint16_t size){
	uint16_t i=0;
	gd_485_DE_tx();
	uint8_t data;
	for (i = 0; i < size; i++)
	{
		data = message[i];
		usart_data_transmit(COM_485, data);
		while (RESET == usart_flag_get(COM_485, USART_FLAG_TC));
	}
	gd_485_DE_rx();
}

void gd_com_232_send(uint8_t *message,uint16_t size){
	uint16_t i=0;
	for (i = 0; i < size; i++){
	usart_data_transmit(COM_232, *(message + i));
	while (RESET == usart_flag_get(COM_232, USART_FLAG_TC));
	}
}

void gd_com_232_Receive(void)
{ 
	uint8_t value;
	if(RESET != usart_interrupt_flag_get(COM_232, USART_INT_FLAG_RBNE))
	{
		/* receive data */
		value = (uint8_t)usart_data_receive(COM_232);
		usart_interrupt_flag_clear(COM_232,USART_INT_FLAG_ERR_FERR);

	}
}


/*!
    \brief      configure EC800M pin
    \param[out] none 
    \retval     none
*/
void gd_EC800M_pin_init(void)
{
    /* enable the EC800M power pin clock */
    rcu_periph_clock_enable(EC800M_PER_GPIO_CLK);
    /* configure EC800M GPIO port */ 
    gpio_init(EC800M_PER_GPIO_PORT, GPIO_MODE_OUT_PP, GPIO_OSPEED_50MHZ, EC800M_PER_PIN);

    GPIO_BC(EC800M_PER_GPIO_PORT) = EC800M_PER_PIN;

    /* enable the EC800M reset pin clock */
    rcu_periph_clock_enable(EC800M_RST_GPIO_CLK);
    /* configure EC800M GPIO port */ 
    gpio_init(EC800M_RST_GPIO_PORT, GPIO_MODE_OUT_PP, GPIO_OSPEED_50MHZ, EC800M_RST_PIN);

    GPIO_BC(EC800M_RST_GPIO_PORT) = EC800M_RST_PIN;
    
}

void gd_pull_EC800M_pwr_up(void)
{
	GPIO_BOP(EC800M_PER_GPIO_PORT) = EC800M_PER_PIN;
}

void gd_pull_EC800M_pwr_down(void)
{
	GPIO_BC(EC800M_PER_GPIO_PORT) = EC800M_PER_PIN;
}

void gd_pull_EC800M_rst_up(void)
{
	GPIO_BOP(EC800M_RST_GPIO_PORT) = EC800M_RST_PIN;
}

void gd_pull_EC800M_rst_down(void)
{
	GPIO_BC(EC800M_RST_GPIO_PORT) = EC800M_RST_PIN;
}

////////////////////////////////////////////////////////////////////

void dma_config(void)
{
    dma_parameter_struct dma_init_struct;

    rcu_periph_clock_enable(RCU_DMA0);

    dma_deinit(DMA0, DMA_CH4);
    dma_init_struct.direction = DMA_PERIPHERAL_TO_MEMORY;		
    dma_init_struct.memory_addr = (uint32_t)UART0_RX_BUF;		
    dma_init_struct.memory_inc = DMA_MEMORY_INCREASE_ENABLE;	
    dma_init_struct.memory_width = DMA_MEMORY_WIDTH_8BIT;		
    dma_init_struct.number = UART0_RX_LEN;						
    dma_init_struct.periph_addr = (uint32_t)(&USART_DATA(USART0));// ((uint32_t)0x40013804);		
    dma_init_struct.periph_inc = DMA_PERIPH_INCREASE_DISABLE;	
    dma_init_struct.periph_width = DMA_PERIPHERAL_WIDTH_8BIT;	
    dma_init_struct.priority = DMA_PRIORITY_ULTRA_HIGH;			
    dma_init(DMA0, DMA_CH4, &dma_init_struct);
    
    dma_circulation_disable(DMA0, DMA_CH4);
    dma_memory_to_memory_disable(DMA0, DMA_CH4);

    usart_dma_transmit_config(USART0, USART_DENT_ENABLE|USART_DENR_ENABLE);
		//nvic_irq_enable(DMA0_Channel4_IRQn, 2, 2);
	
    dma_interrupt_enable(DMA0, DMA_CH4, DMA_INT_FTF|DMA_INT_HTF|DMA_INT_ERR);
    dma_channel_enable(DMA0, DMA_CH4);
	 

}
//手动控制dma搬运的数据地址和大小，在使用完成后需要恢复到默认的dma配置
void dma_config_change(char *dmaBuffer,uint32_t bufferSize)
{
	  dma_parameter_struct dma_init_struct;

    rcu_periph_clock_enable(RCU_DMA0);

    dma_deinit(DMA0, DMA_CH4);
    dma_init_struct.direction = DMA_PERIPHERAL_TO_MEMORY;		
    dma_init_struct.memory_addr = (uint32_t)dmaBuffer;		
    dma_init_struct.memory_inc = DMA_MEMORY_INCREASE_ENABLE;	
    dma_init_struct.memory_width = DMA_MEMORY_WIDTH_8BIT;		
    dma_init_struct.number = bufferSize;						
    dma_init_struct.periph_addr = (uint32_t)(&USART_DATA(USART0));// ((uint32_t)0x40013804);		
    dma_init_struct.periph_inc = DMA_PERIPH_INCREASE_DISABLE;	
    dma_init_struct.periph_width = DMA_PERIPHERAL_WIDTH_8BIT;	
    dma_init_struct.priority = DMA_PRIORITY_ULTRA_HIGH;			
    dma_init(DMA0, DMA_CH4, &dma_init_struct);
    
    dma_circulation_disable(DMA0, DMA_CH4);
    dma_memory_to_memory_disable(DMA0, DMA_CH4);

    usart_dma_transmit_config(USART0, USART_DENT_ENABLE|USART_DENR_ENABLE);
		//nvic_irq_enable(DMA0_Channel4_IRQn, 2, 2);
	
    dma_interrupt_enable(DMA0, DMA_CH4, DMA_INT_FTF|DMA_INT_ERR);
    dma_channel_enable(DMA0, DMA_CH4);
}
/*
 *  函数名：void config_485_port(uint32_t com,uint32_t baudrate, uint8_t databits, uint8_t stopbits, uint8_t parity, uint8_t flowcontrol)
 *  输入参数：com 串口，baudrate,databits,stopbits,parity,flowcontol 串口的配置参数
 *  输出参数：无
 *  返回值：无
 *  函数作用：配置485串口参数
 */
void config_485_port(uint32_t com,uint32_t baudrate, uint8_t databits, uint8_t stopbits, uint8_t parity)
{
	 uint32_t com_id = 0U;
	 uint8_t wordLength;
		if(parity!=0)
		{
			wordLength=databits+1;
		}else wordLength=databits;
    if(COM_485 == com){
			com_id=1U;
//			nvic_irq_enable(COM_IT_HANDLER[com_id], 0, 0);
			/* enable GPIO clock */
			rcu_periph_clock_enable(COM_GPIO_CLK[com_id]);
			/* enable USART clock */
			rcu_periph_clock_enable(COM_CLK[com_id]);
			/* connect port to USARTx_Tx */
    gpio_init(COM_GPIO_PORT[com_id], GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, COM_TX_PIN[com_id]);

    /* connect port to USARTx_Rx */
    gpio_init(COM_GPIO_PORT[com_id], GPIO_MODE_IN_FLOATING, GPIO_OSPEED_50MHZ, COM_RX_PIN[com_id]);
			
		
			//usart_deinit(com);
			usart_baudrate_set(com, baudrate);
			usart_word_length_set(com, (wordLength == 9) ? USART_WL_9BIT : USART_WL_8BIT);
			usart_stop_bit_set(com, (stopbits == 2) ? USART_STB_2BIT : USART_STB_1BIT);
			usart_parity_config(com, parity == 1 ? (USART_PM_ODD) : (parity == 2 ? USART_PM_EVEN : USART_PM_NONE));
			usart_hardware_flow_rts_config(com, USART_RTS_DISABLE);
			usart_hardware_flow_cts_config(com, USART_CTS_DISABLE);
			
			usart_receive_config(com, USART_RECEIVE_ENABLE);
			usart_transmit_config(com, USART_TRANSMIT_ENABLE);
			
			/* 使能串口 */
			usart_enable(com);
		  usart_interrupt_enable(com, USART_INT_RBNE);
			usart_interrupt_enable(com, USART_INT_IDLE);
			//nvic_irq_enable(USART1_IRQn, 1, 0);
			//解决485第一个帧数据第一个字节丢失问题
			usart_flag_clear(COM_485,USART_FLAG_TC);
		}

}

void nvic_config(void)
{
    nvic_priority_group_set(NVIC_PRIGROUP_PRE2_SUB2);  // 设置抢占优先级和子优先级的位数为 2
		nvic_irq_enable(USART0_IRQn, 0, 0);
		nvic_irq_enable(USART1_IRQn, 1, 0);
		nvic_irq_enable(USART2_IRQn, 2, 0);
		nvic_irq_enable(DMA0_Channel4_IRQn, 2, 1);
	
}


