
/******************************************************************************
*@file  : app.c
*@brief : application
******************************************************************************/

#include "app.h" 

#define    DMA_TRANSFER_BUF_SIZE    ( 10U )

__attribute__ ((aligned (4)))	uint8_t g_buf[DMA_TRANSFER_BUF_SIZE];

volatile uint32_t g_send_complete;
volatile uint32_t g_send_error;
volatile uint32_t g_recv_complete;
volatile uint32_t g_recv_error;

DMA_InitTypeDef DMA1CH0_InitStruct = {0};
DMA_InitTypeDef DMA1CH1_InitStruct = {0};

/******************************************************************************
*@brief : app test
*@param : none
*@return: none
******************************************************************************/
void APP_Test(void)
{
    uint32_t i;
    GPIO_InitTypeDef  GPIO_InitStruct = {0};
    LPUART_InitTypeDef LPUART_InitStruct = {0};
    
	printfS("SPL LPUART1 Demo: DMA Mode.\r\n");
	printfS("\r\n");
    
	BSP_LED_Init();
    BSP_LED_On();
    DelayMs(500);
    BSP_LED_Off();
    DelayMs(500);
    BSP_LED_On();
    DelayMs(500);
    BSP_LED_Off();
    DelayMs(500);
    
    // Init LPUART1
    __RCC_LPUART1_CLK_ENABLE();
    __RCC_LPUART1_RESET();
    
    // TX:PC1, RX:PC0
    __RCC_GPIOC_CLK_ENABLE();
    
    GPIO_InitStruct.Pin       = GPIO_PIN_1 | GPIO_PIN_0;
    GPIO_InitStruct.Mode      = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Pull      = GPIO_PULLUP;
    GPIO_InitStruct.Drive     = GPIO_DRIVE_LEVEL3;
    GPIO_InitStruct.Alternate = GPIO_FUNCTION_0;

    GPIO_Init(GPIOC, &GPIO_InitStruct);
    
    LPUART_SetClockSource(LPUART1, LPUART_CLOCKSOURCE_PCLK_DIV4);
    LPUART_SetWakeupMode(LPUART1, LPUART_WAKEUPMODE_NONE);
    
    LPUART_InitStruct.BaudRate    = 115200;
    LPUART_InitStruct.WordLength  = LPUART_WORDLENGTH_8B;
    LPUART_InitStruct.StopBits    = LPUART_STOPBITS_1B;
    LPUART_InitStruct.Parity      = LPUART_PARITY_NONE;
    LPUART_InitStruct.Mode        = LPUART_MODE_TXRX;
    
    LPUART_Init(LPUART1, &LPUART_InitStruct);
    
    // Init DMA1 Channel0: TX
    __RCC_DMA1_CLK_ENABLE();
    
    DMA_DeInit(DMA1_Channel0);
    
    DMA1CH0_InitStruct.Mode        = DMA_MODE_NORMAL;
    DMA1CH0_InitStruct.DataFlow    = DMA_DATAFLOW_M2P;
    DMA1CH0_InitStruct.ReqID       = DMA1_REQ30_LPUART1_SEND;
    DMA1CH0_InitStruct.RawInt      = DMA_RAWINT_ENABLE;
    DMA1CH0_InitStruct.SrcWidth    = DMA_SRCWIDTH_BYTE;
    DMA1CH0_InitStruct.DestWidth   = DMA_DESTWIDTH_BYTE;
    DMA1CH0_InitStruct.SrcInc      = DMA_SRCINC_ENABLE;
    DMA1CH0_InitStruct.DestInc     = DMA_DESTINC_DISABLE;
    DMA1CH0_InitStruct.SrcBurst    = DMA_SRCBURST_1;
    DMA1CH0_InitStruct.DestBurst   = DMA_DESTBURST_1;
    
    DMA1CH0_InitStruct.SrcAddr     = (uint32_t)g_buf;
    DMA1CH0_InitStruct.DestAddr    = (uint32_t)&LPUART1->TXDR;
    DMA1CH0_InitStruct.Size        = DMA_TRANSFER_BUF_SIZE;
    
    DMA_Init(DMA1_Channel0, &DMA1CH0_InitStruct);
    
    // Enable interrupt
    DMA_ClearFlag(DMA1_Channel0, DMA_FLAG_RTC | DMA_IT_ERR);
    DMA_ITConfig(DMA1_Channel0, DMA_IT_TC | DMA_IT_ERR, ENABLE);
    
    
    // Init DMA1 Channel1: RX
    __RCC_DMA1_CLK_ENABLE();
    
    DMA_BigEndianConfig(DMA1, DISABLE);
    
    DMA_DeInit(DMA1_Channel1);
    
    DMA1CH1_InitStruct.Mode        = DMA_MODE_NORMAL;
    DMA1CH1_InitStruct.DataFlow    = DMA_DATAFLOW_P2M;
    DMA1CH1_InitStruct.ReqID       = DMA1_REQ31_LPUART1_RECV;
    DMA1CH1_InitStruct.RawInt      = DMA_RAWINT_ENABLE;
    DMA1CH1_InitStruct.SrcWidth    = DMA_SRCWIDTH_BYTE;
    DMA1CH1_InitStruct.DestWidth   = DMA_DESTWIDTH_BYTE;
    DMA1CH1_InitStruct.SrcInc      = DMA_SRCINC_DISABLE;
    DMA1CH1_InitStruct.DestInc     = DMA_DESTINC_ENABLE;
    DMA1CH1_InitStruct.SrcBurst    = DMA_SRCBURST_1;
    DMA1CH1_InitStruct.DestBurst   = DMA_DESTBURST_1;
    
    DMA1CH1_InitStruct.SrcAddr     = (uint32_t)&LPUART1->RXDR;
    DMA1CH1_InitStruct.DestAddr    = (uint32_t)g_buf;
    DMA1CH1_InitStruct.Size        = DMA_TRANSFER_BUF_SIZE;
    
    DMA_Init(DMA1_Channel1, &DMA1CH1_InitStruct);
    
    // Enable interrupt
    DMA_ClearFlag(DMA1_Channel1, DMA_FLAG_RTC | DMA_IT_ERR);
    DMA_ITConfig(DMA1_Channel1, DMA_IT_TC | DMA_IT_ERR, ENABLE);
    
    // Enable NVIC IRQ
    NVIC_ClearPendingIRQ(DMA1_IRQn);
    NVIC_SetPriority(DMA1_IRQn, 0x00);
    NVIC_EnableIRQ(DMA1_IRQn);
    
    LPUART_DMACmd(LPUART1, ENABLE);
    
    while (1)
    {
        memset((void *)g_buf, 0, DMA_TRANSFER_BUF_SIZE);
        
        g_recv_complete = 0;
        g_recv_error = 0;
        
        printfS("LPUART1 starts receiving: 115200, 8, 1, N. length: 10 bytes.\r\n");
        
        DMA1CH1_InitStruct.Size = DMA_TRANSFER_BUF_SIZE;
        DMA_Init(DMA1_Channel1, &DMA1CH1_InitStruct);
        
        DMA_Cmd(DMA1_Channel1, ENABLE);
        
        while ((g_recv_complete == 0) && (g_recv_error == 0));
        
        if (g_recv_error)
        {
            g_recv_error = 0;
            printfS("Receive failed.\r\n");
        }
        else if (g_recv_complete)
        {
            g_recv_complete = 0;
            printfS("Received successfully.\r\n");
            printfS("Send the received data.\r\n");
            printfS("Start sending.\r\n");
            
            g_send_complete = 0;
            g_send_error = 0;
            
            DMA1CH0_InitStruct.Size = DMA_TRANSFER_BUF_SIZE;
            DMA_Init(DMA1_Channel0, &DMA1CH0_InitStruct);
            
            DMA_Cmd(DMA1_Channel0, ENABLE);
            
            while ((g_send_complete == 0) && (g_send_error == 0));
            
            if (g_send_error)
            {
                g_send_error = 0;
                printfS("Sending failed.\r\n");
            }
            else if (g_send_complete)
            {
                g_send_complete = 0;
                printfS("Sending succeeded.\r\n");
            }
        }
        printfS("\r\n");
    }
}

void DMA1CH0_SendComplete(void)
{
    g_send_complete = 1;
}

void DMA1CH0_SendError(void)
{
    g_send_error = 1;
}

void DMA1CH1_RecvComplete(void)
{
    g_recv_complete = 1;
}

void DMA1CH1_RecvError(void)
{
    g_recv_error = 1;
}

