/*
  ******************************************************************************
  * @file    APP.c
  * @author  PJ
  * @version V1.0.0
  * @date    2021
  * @brief   UART demo source code.
  ******************************************************************************
*/
#include "app.h"

uint8_t gu8_TxBuffer[512];
uint8_t gu8_RxBuffer[512];

volatile uint8_t  gu8_UART2RecvFlag =0;

Type_UART_t g_UART2Handle;

volatile uint8_t gu8_DMABuffer[DMA_TX_SIZE]={0xaa,0xbb};

/*********************************************************************************
* Function    : UartIRQ
* Description : UARTx Interrupt handler Function
* Input       : pUart 
* Output      : None
* Author      : PJ                       Data : 2021年
* Recv Data eg: "12345678912346789\n"
**********************************************************************************/
void UartIRQ(Type_UART_t *pUart)
{
	/* 接收中断 */
	if (UART_GetITStatus(pUart->uart, UART_IT_RXNE) != RESET)
	{ 
		UART_ClearITPendingBit(pUart->uart,UART_IT_RXNE);
		
		/* Read one byte from the receive data register */
		pUart->pRxBuf[pUart->lu32_RxWrite] = UART_ReceiveData(pUart->uart);
		if(pUart->pRxBuf[pUart->lu32_RxWrite]==0x0A)  //遇到回车符认定一帧数据结束
		{
			gu8_UART2RecvFlag =1;
			//回调函数
			if (pUart->ReciveNewFunc)
			{
				pUart->ReciveNewFunc();
			}
		}
		if (++pUart->lu32_RxWrite >= pUart->lu32_RxBufSize) //防止溢出
		{
			pUart->lu32_RxWrite = 0;
		}		
	}

	/* 发送中断 */
	if (UART_GetITStatus(pUart->uart, UART_IT_TXE) != RESET)
	{ 
		UART_ClearITPendingBit(pUart->uart,UART_IT_TXE);
		if (pUart->lu32_TxRead == pUart->lu32_TxWrite)
		{
			/* 发送完毕,禁止发送中断 */
			UART_ITConfig(pUart->uart, UART_IT_TXE, DISABLE);
			/* 回调函数,通知应用程序发送完毕 */
			if (pUart->SendOverFunc)
			{
				pUart->SendOverFunc();
			}
		} 
		else
		{		
			/* Write one byte to the transmit data register */
			UART_SendData(pUart->uart, pUart->pTxBuf[pUart->lu32_TxRead]);                    
			if (++pUart->lu32_TxRead >= pUart->lu32_TxBufSize)
			{
				 pUart->lu32_TxRead = 0;
			}
		}
	}
}



/*********************************************************************************
* Function    : UartParaInit
* Description : Load UARTx Parameters
* Input       : None
* Output      : None
* Author      : PJ                       Data : 2021年
**********************************************************************************/
static void UartParaInit(void)
{
	g_UART2Handle.uart = UART2;
	g_UART2Handle.pTxBuf = gu8_TxBuffer;
	g_UART2Handle.pRxBuf = gu8_RxBuffer;
	g_UART2Handle.lu32_TxBufSize = UART_TX_BUF_SIZE;
	g_UART2Handle.lu32_RxBufSize = UART_RX_BUF_SIZE;
	g_UART2Handle.lu32_TxWrite = 0;
	g_UART2Handle.lu32_TxRead = 0;
	g_UART2Handle.lu32_RxWrite = 0;
	g_UART2Handle.lu32_RxRead = 0;
	g_UART2Handle.SendOverFunc = NULL;	
	g_UART2Handle.ReciveNewFunc = NULL;
}

/*********************************************************************************
* Function    : UART2_Init
* Description : Init  UART2 
* Input       : None
* Output      : None
**********************************************************************************/
static void UART2_Init(enum_TEST_MODE_t fe_Mode)
{
	  GPIO_InitTypeDef GPIO_InitStruct;
	  UART_InitTypeDef UART2_InitStruc;
	
	  //Enable GPIO and UART Clock
	  System_Module_Enable(EN_UART2);
	  System_Module_Enable(EN_GPIOAB);
	  //Config GPIO
	  /* A2:Tx  A3:Rx */
	  GPIO_InitStruct.Pin       = GPIO_PIN_2 | GPIO_PIN_3;
	  GPIO_InitStruct.Mode      = GPIO_MODE_AF_PP;
	  GPIO_InitStruct.Pull      = GPIO_PULLUP;
	  GPIO_InitStruct.Alternate = GPIO_FUNCTION_2;
	  GPIO_Init(GPIOA, &GPIO_InitStruct);
	  //UART Config
	  UART2_InitStruc.UART_BaudRate    = 9600;  
	  UART2_InitStruc.UART_WordLength  = UART_WORDLENGTH_8B;
	  UART2_InitStruc.UART_StopBits    = UART_STOPBITS_1;
      UART2_InitStruc.UART_Parity      = UART_PARITY_NONE;
      UART2_InitStruc.UART_Mode        = UART_MODE_TX_RX;
      UART2_InitStruc.UART_HardwareFlowControl =UART_HWCONTROL_NONE;    
      UART_Init(UART2,&UART2_InitStruc);
	  if(fe_Mode ==TEST_UART_IT)
	  { 						
		/* NVIC Config */
	    NVIC_ClearPendingIRQ(UART2_IRQn);
		NVIC_SetPriority(UART2_IRQn, 5);
		NVIC_EnableIRQ(UART2_IRQn);
		  
		UART_ITConfig(UART2, UART_IT_RXNE, ENABLE);	/* 使能接收中断 */	
	  }   
	  //Enable UART
	  UART_Cmd(UART2,ENABLE);
}

/*********************************************************************************
* Function    : UartSend_IT
* Description : Send Data By Interrupt Way 
* Input       : fe_Mode: Select the UART Send Method
* Input       : UARTx: Select the UART peripheral. 
* Input       : SendBuf: Send Data Buff
* Input       : DataLen: Send Data Length
* Output      : None
* Author      : PJ                       Data : 2021年
**********************************************************************************/
void UartSend(enum_TEST_MODE_t fe_Mode,Type_UART_t *pUart, uint8_t *SendBuf, uint32_t DataLen)
{
	uint32_t i;

	switch(fe_Mode)
	{
		case TEST_LOOP:
			for(i=0;i<DataLen;i++)
			{
				UART_SendData(pUart->uart,SendBuf[i]);
			}
			break;
			
		case TEST_UART_IT:
			//load data 
			for (i = 0; i < DataLen; i++)
			{	
				pUart->pTxBuf[pUart->lu32_TxWrite] = SendBuf[i];
				
				if (++pUart->lu32_TxWrite >= pUart->lu32_TxBufSize)
				{
					pUart->lu32_TxWrite = 0;
				}
			}		
			//send data
			UART_ITConfig(pUart->uart, UART_IT_TXE, ENABLE);
			pUart->uart->DR =pUart->pTxBuf[pUart->lu32_TxRead++];  //先填充一字节数据才能触发中断
			
			break;
		default:
			break;		
	}
}

/*********************************************************************************
* Function    : UARTx_DMA_Config
* Description : Config UART DMA Channel
* Input       : None
* Output      : None

**********************************************************************************/
void UARTx_DMA_Config(void)
{    
	
	DMA_InitTypeDef  DMA_InitStructure;	
	
	UART_DMACmd(UART2, UART_DMACR_TXDMAE, DISABLE);
    /* Enable DMA Module */
    System_Module_Enable(EN_DMA);
    /* NVIC configuration */
    NVIC_ClearPendingIRQ(DMA_IRQn);
    NVIC_EnableIRQ(DMA_IRQn);
    /* DMA channel6 configuration */

    DMA_DeInit(DMA_Channel0);
    DMA_InitStructure.Request_ID = REQ7_UART2_SEND;
    DMA_InitStructure.SrcAddr = (uint32_t)gu8_DMABuffer;
    DMA_InitStructure.DstAddr = (uint32_t)(&UART2->DR);
    DMA_InitStructure.Data_Flow = DMA_DATA_FLOW_M2P;
    DMA_InitStructure.DMA_BufferSize = DMA_TX_SIZE;
    DMA_InitStructure.Source_Inc = DMA_SOURCE_ADDR_INCREASE_ENABLE;
    DMA_InitStructure.Desination_Inc = DMA_DST_ADDR_INCREASE_DISABLE;
    DMA_InitStructure.Source_Width = DMA_SRC_WIDTH_BYTE;
    DMA_InitStructure.Desination_Width = DMA_DST_WIDTH_BYTE;
    DMA_InitStructure.DMA_Mode = DMA_NORMAL;
    DMA_Init(DMA_Channel0, &DMA_InitStructure);	
}

/*********************************************************************************
* Function    : APP_Uart_Test
* Description : Test UART Function By Various Way
* Input       : fe_Mode
* Output      : None

**********************************************************************************/
void APP_Uart_Test(enum_TEST_MODE_t fe_Mode)
{
	static uint8_t gu8_UART2Test[] ={"UART2 Test Demo,Please enter any data and end it With \\n ->"};
	volatile uint16_t i;
	
    UartParaInit();
	
    switch (fe_Mode)
    {
        /* 循环模式 */
        case TEST_LOOP: 
        {
			UART2_Init(TEST_LOOP);
			
			UartSend(TEST_LOOP,&g_UART2Handle,gu8_UART2Test,strlen((char *)gu8_UART2Test));
			
			for(;;)
			{
				//Receive Data
				g_UART2Handle.pRxBuf[g_UART2Handle.lu32_RxWrite] =UART_ReceiveData(g_UART2Handle.uart);
				//Handle Data			
				if(g_UART2Handle.pRxBuf[g_UART2Handle.lu32_RxWrite]==0x0A)  //遇到回车符认定一帧数据结束
				{
					//send back
					UartSend(TEST_LOOP,&g_UART2Handle,g_UART2Handle.pRxBuf,g_UART2Handle.lu32_RxWrite);
					
					g_UART2Handle.lu32_RxWrite =0;
					
					continue;
				}
				if (++g_UART2Handle.lu32_RxWrite >= g_UART2Handle.lu32_RxBufSize) //防止溢出
				{
					g_UART2Handle.lu32_RxWrite = 0;
				}															
			}
		
        }break;

        /* 中断模式 */
        case TEST_UART_IT: 
        {
            UART2_Init(TEST_UART_IT);

			UartSend(TEST_UART_IT,&g_UART2Handle,gu8_UART2Test,strlen((char *)gu8_UART2Test));
			
			for(;;)
			{
				while(!gu8_UART2RecvFlag);	
				
				gu8_UART2RecvFlag =0;
				
				UartSend(TEST_UART_IT,&g_UART2Handle,g_UART2Handle.pRxBuf,g_UART2Handle.lu32_RxWrite);
				
				g_UART2Handle.lu32_RxWrite =0;
			}
        }break;        
        /* DMA模式 */
        case TEST_DMA: 
        {	
										
			UART2_Init(TEST_LOOP);	
					
			UARTx_DMA_Config();
			
			//load data	
		    for(i=0;i<DMA_TX_SIZE;i++)
			{
				gu8_DMABuffer[i] =i+1;
			}
			
			/* Enable DMA Channel0 transfer */
			DMA_Cmd(DMA_Channel0, ENABLE);
			//UART DMA Send
			UART_DMACmd(UART2, UART_DMACR_TXDMAE, ENABLE);			
			while (RESET == DMA_GetFlagStatus(DMA_IT_FLAG_TC6));
			          
        }break;

        default: break; 
    }
}
