/////////////////////////////////////////////////////////////////////basic mode/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

#include <stdint.h>
#include <stdbool.h>
#include "driverlib/gpio.h"
#include "driverlib/sysctl.h"
#include "driverlib/uart.h"
#include "driverlib/udma.h"
#include "inc/hw_uart.h"

#define TX_BUFFER_SIZE  256
byte txBuffer[TX_BUFFER_SIZE];

// uDMA control table aligned to 1024-byte boundary
#pragma DATA_ALIGN(controlTable, 1024);
uint8_t controlTable[1024];

void setup()
{
  SysCtlClockSet(SYSCTL_SYSDIV_2_5 | SYSCTL_USE_PLL | SYSCTL_OSC_MAIN | SYSCTL_XTAL_16MHZ);  // 80MHz
  
  for(uint32_t ui32Idx = 0; ui32Idx < TX_BUFFER_SIZE; ui32Idx++)
  {    
    txBuffer[ui32Idx] = 65;
  }
    
  UARTConfiguration();
  UDMAConfiguration();
}

void UARTConfiguration()
{
  SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);
  SysCtlPeripheralEnable(SYSCTL_PERIPH_UART0);
  //SysCtlPeripheralSleepEnable(SYSCTL_PERIPH_UART0);
  
  GPIOPinConfigure(GPIO_PA0_U0RX);
  GPIOPinConfigure(GPIO_PA1_U0TX);

  GPIOPinTypeUART(GPIO_PORTA_BASE, GPIO_PIN_0 | GPIO_PIN_1);

  UARTConfigSetExpClk(UART0_BASE, SysCtlClockGet(), 115200, UART_CONFIG_WLEN_8 | UART_CONFIG_STOP_ONE | UART_CONFIG_PAR_NONE);

  UARTFIFOLevelSet(UART0_BASE, UART_FIFO_TX4_8, UART_FIFO_RX4_8);
    
  //UARTIntRegister(UART0_BASE, UART0IntHandler);
  
  UARTIntEnable(UART0_BASE, UART_INT_TX | UART_INT_RX);  
  
  UARTEnable(UART0_BASE);  
  
  UARTDMAEnable(UART0_BASE, UART_DMA_RX | UART_DMA_TX);
}

void UDMAConfiguration()
{
  SysCtlPeripheralEnable(SYSCTL_PERIPH_UDMA);
  //SysCtlPeripheralSleepEnable(SYSCTL_PERIPH_UDMA);
  
  uDMAEnable();
  uDMAControlBaseSet(&controlTable[0]);
  
  uDMAChannelAssign(UDMA_CH9_UART0TX);

  uDMAChannelAttributeDisable(UDMA_CH9_UART0TX, UDMA_ATTR_ALTSELECT | UDMA_ATTR_HIGH_PRIORITY | UDMA_ATTR_REQMASK);

  uDMAChannelAttributeEnable(UDMA_CH9_UART0TX, UDMA_ATTR_USEBURST);

  uDMAChannelControlSet(UDMA_CH9_UART0TX | UDMA_PRI_SELECT, UDMA_SIZE_8 | UDMA_SRC_INC_8 | UDMA_DST_INC_NONE | UDMA_ARB_4);

  uDMAChannelTransferSet(UDMA_CH9_UART0TX | UDMA_PRI_SELECT, UDMA_MODE_BASIC, txBuffer, (void *)(UART0_BASE + UART_O_DR), sizeof(txBuffer));
  
  uDMAChannelEnable(UDMA_CH9_UART0TX);
}

void UART0IntHandler()
{
  UARTIntClear(UART0_BASE, UART_INT_TX | UART_INT_RX);
  
  //if(!uDMAChannelIsEnabled(UDMA_CH9_UART0TX))  // 重複啟動
  //{
    //uDMAChannelTransferSet(UDMA_CH9_UART0TX | UDMA_PRI_SELECT, UDMA_MODE_BASIC, txBuffer, (void *)(UART0_BASE + UART_O_DR), sizeof(txBuffer));
    
    //uDMAChannelEnable(UDMA_CH9_UART0TX);
  //}
}

void loop()
{}

/////////////////////////////////////////////////////////////////////ping pong mode/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/*
#include <stdint.h>
#include <stdbool.h>
#include "driverlib/gpio.h"
#include "driverlib/sysctl.h"
#include "driverlib/uart.h"
#include "driverlib/udma.h"
#include "inc/hw_uart.h"

#define PINGPONG_BUFFER_SIZE  128
byte pingBuffer[PINGPONG_BUFFER_SIZE];
byte pongBuffer[PINGPONG_BUFFER_SIZE];

// uDMA control table aligned to 1024-byte boundary
#pragma DATA_ALIGN(controlTable, 1024);
uint8_t controlTable[1024];

void setup()
{
  SysCtlClockSet(SYSCTL_SYSDIV_2_5 | SYSCTL_USE_PLL | SYSCTL_OSC_MAIN | SYSCTL_XTAL_16MHZ);  // 80MHz
  
  for(uint16_t i = 0; i < PINGPONG_BUFFER_SIZE; i++)
  {
    pingBuffer[i] = 65;
    pongBuffer[i] = 66;
  }
    
  UARTConfiguration();
  UDMAConfiguration();
}

void UARTConfiguration()
{
  SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOE);
  SysCtlPeripheralEnable(SYSCTL_PERIPH_UART7);
  //SysCtlPeripheralSleepEnable(SYSCTL_PERIPH_UART0);
  
  GPIOPinConfigure(GPIO_PE0_U7RX);
  GPIOPinConfigure(GPIO_PE1_U7TX);

  GPIOPinTypeUART(GPIO_PORTE_BASE, GPIO_PIN_0 | GPIO_PIN_1);

  UARTConfigSetExpClk(UART7_BASE, SysCtlClockGet(), 115200, UART_CONFIG_WLEN_8 | UART_CONFIG_STOP_ONE | UART_CONFIG_PAR_NONE);

  UARTFIFOLevelSet(UART7_BASE, UART_FIFO_TX4_8, UART_FIFO_RX4_8);
    
  UARTIntRegister(UART7_BASE, UART0IntHandler);
  
  UARTIntEnable(UART7_BASE, UART_INT_TX | UART_INT_RX);  
  
  UARTEnable(UART7_BASE);

  UARTDMAEnable(UART7_BASE, UART_DMA_RX | UART_DMA_TX);  
}

void UDMAConfiguration()
{
  SysCtlPeripheralEnable(SYSCTL_PERIPH_UDMA);
  //SysCtlPeripheralSleepEnable(SYSCTL_PERIPH_UDMA);
  
  uDMAEnable();
  uDMAControlBaseSet(&controlTable[0]);
  
  uDMAChannelAssign(UDMA_CH21_UART7TX);

  uDMAChannelAttributeDisable(UDMA_CH21_UART7TX, UDMA_ATTR_ALL);

  uDMAChannelControlSet(UDMA_CH21_UART7TX | UDMA_PRI_SELECT, UDMA_SIZE_8 | UDMA_SRC_INC_8 | UDMA_DST_INC_NONE | UDMA_ARB_4);
  uDMAChannelControlSet(UDMA_CH21_UART7TX | UDMA_ALT_SELECT, UDMA_SIZE_8 | UDMA_SRC_INC_8 | UDMA_DST_INC_NONE | UDMA_ARB_4);

  uDMAChannelTransferSet(UDMA_CH21_UART7TX | UDMA_PRI_SELECT, UDMA_MODE_PINGPONG, pingBuffer, (void *)(UART7_BASE + UART_O_DR), sizeof(pingBuffer));  
  uDMAChannelTransferSet(UDMA_CH21_UART7TX | UDMA_ALT_SELECT, UDMA_MODE_PINGPONG, pongBuffer, (void *)(UART7_BASE + UART_O_DR), sizeof(pongBuffer));

  uDMAChannelEnable(UDMA_CH21_UART7TX);
}

void UART0IntHandler()
{
  uint32_t DMAMode;
  
  UARTIntClear(UART7_BASE, UART_INT_TX | UART_INT_RX);
  
  DMAMode = uDMAChannelModeGet(UDMA_CH21_UART7TX | UDMA_PRI_SELECT);  
  
  if(DMAMode == UDMA_MODE_STOP)
  {
    uDMAChannelTransferSet(UDMA_CH21_UART7TX | UDMA_PRI_SELECT, UDMA_MODE_PINGPONG, pingBuffer, (void *)(UART7_BASE + UART_O_DR), sizeof(pingBuffer));
  }

  DMAMode = uDMAChannelModeGet(UDMA_CH21_UART7TX | UDMA_ALT_SELECT);
  
  if(DMAMode == UDMA_MODE_STOP)
  {
    uDMAChannelTransferSet(UDMA_CH21_UART7TX | UDMA_ALT_SELECT, UDMA_MODE_PINGPONG, pongBuffer, (void *)(UART7_BASE + UART_O_DR), sizeof(pongBuffer));
  }
}

void loop()
{}
*/
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/*
#include <stdint.h>
#include <stdbool.h>
#include "driverlib/gpio.h"
#include "driverlib/sysctl.h"
#include "driverlib/uart.h"
#include "driverlib/udma.h"
#include "inc/hw_uart.h"

#define TX_BUFFER_SIZE  533
#define PINGPONG_BUFFER_SIZE  640
byte txBuffer[TX_BUFFER_SIZE];
byte pingBuffer[PINGPONG_BUFFER_SIZE];
byte pongBuffer[PINGPONG_BUFFER_SIZE];

// uDMA control table aligned to 1024-byte boundary
#pragma DATA_ALIGN(controlTable, 1024);
uint8_t controlTable[1024];

void setup()
{
  SysCtlClockSet(SYSCTL_SYSDIV_2_5 | SYSCTL_USE_PLL | SYSCTL_OSC_MAIN | SYSCTL_XTAL_16MHZ);  // 80MHz
  
  for(uint16_t i = 0; i < 640; i++)
  {
    pingBuffer[i] = 65;
    //pongBuffer[i] = 66;
  }
  
  //pingBuffer[638] = 13;
  //pongBuffer[638] = 13;
  //pingBuffer[639] = 10;
  //pongBuffer[639] = 10;
  
  UARTConfiguration();
  UDMAConfiguration();
  
  uint32_t ui32Idx;

  // Initialize transmit buffer with some data
  for(ui32Idx = 0; ui32Idx < TX_BUFFER_SIZE; ui32Idx++)
  {    
    txBuffer[ui32Idx] = 65;
  }

  SysCtlPeripheralEnable(SYSCTL_PERIPH_UART0);
  //SysCtlPeripheralSleepEnable(SYSCTL_PERIPH_UART0);

  // Configure and enable the UART with DMA
  UARTConfigSetExpClk(UART0_BASE, SysCtlClockGet(), 115200, UART_CONFIG_WLEN_8 | UART_CONFIG_STOP_ONE | UART_CONFIG_PAR_NONE);

  UARTFIFOLevelSet(UART0_BASE, UART_FIFO_TX4_8, UART_FIFO_RX4_8);

  UARTEnable(UART0_BASE);
  UARTDMAEnable(UART0_BASE, UART_DMA_RX | UART_DMA_TX);

  // Loopback mode
  //HWREG(UART0_BASE + UART_O_CTL) |= UART_CTL_LBE;

  //IntEnable(INT_UART1);

  // Receive channel setup for ping and pong
  //uDMAChannelAttributeDisable(UDMA_CH8_UART0RX, UDMA_ATTR_ALTSELECT | UDMA_ATTR_USEBURST | UDMA_ATTR_HIGH_PRIORITY | UDMA_ATTR_REQMASK);

  //uDMAChannelControlSet(UDMA_CH8_UART0RX | UDMA_PRI_SELECT, UDMA_SIZE_8 | UDMA_SRC_INC_NONE | UDMA_DST_INC_8 | UDMA_ARB_4);

  //uDMAChannelControlSet(UDMA_CH8_UART0RX | UDMA_ALT_SELECT, UDMA_SIZE_8 | UDMA_SRC_INC_NONE | UDMA_DST_INC_8 | UDMA_ARB_4);

  //uDMAChannelTransferSet(UDMA_CH8_UART0RX | UDMA_PRI_SELECT, UDMA_MODE_PINGPONG, (void *)(UART0_BASE + UART_O_DR), pingBuffer, sizeof(pingBuffer));

  //uDMAChannelTransferSet(UDMA_CH8_UART0RX | UDMA_ALT_SELECT, UDMA_MODE_PINGPONG, (void *)(UART0_BASE + UART_O_DR), pongBuffer, sizeof(pongBuffer));

  // Transmit channel setup for a basic transfer
  uDMAChannelAttributeDisable(UDMA_CH9_UART0TX, UDMA_ATTR_ALTSELECT | UDMA_ATTR_HIGH_PRIORITY | UDMA_ATTR_REQMASK);

  uDMAChannelAttributeEnable(UDMA_CH9_UART0TX, UDMA_ATTR_USEBURST);

  uDMAChannelControlSet(UDMA_CH9_UART0TX | UDMA_PRI_SELECT, UDMA_SIZE_8 | UDMA_SRC_INC_8 | UDMA_DST_INC_NONE | UDMA_ARB_4);

  uDMAChannelTransferSet(UDMA_CH9_UART0TX | UDMA_PRI_SELECT, UDMA_MODE_BASIC, txBuffer, (void *)(UART0_BASE + UART_O_DR), sizeof(txBuffer));

  //uDMAChannelEnable(UDMA_CH8_UART0RX);
  uDMAChannelEnable(UDMA_CH9_UART0TX);
}

void UARTConfiguration()
{
  SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);
  SysCtlPeripheralEnable(SYSCTL_PERIPH_UART0);
  //SysCtlPeripheralSleepEnable(SYSCTL_PERIPH_GPIOA);
  
  GPIOPinConfigure(GPIO_PA0_U0RX);
  GPIOPinConfigure(GPIO_PA1_U0TX);

  GPIOPinTypeUART(GPIO_PORTA_BASE, GPIO_PIN_0 | GPIO_PIN_1);

  UARTConfigSetExpClk(UART0_BASE, SysCtlClockGet(), 115200, UART_CONFIG_WLEN_8 | UART_CONFIG_STOP_ONE | UART_CONFIG_PAR_NONE);

  UARTFIFOLevelSet(UART0_BASE, UART_FIFO_TX4_8, UART_FIFO_RX4_8);
    
  UARTIntRegister(UART0_BASE, UART0IntHandler);
  
  UARTIntEnable(UART0_BASE, UART_INT_TX | UART_INT_RX);  
  
  UARTDMAEnable(UART0_BASE, UART_DMA_RX | UART_DMA_TX);

  UARTEnable(UART0_BASE);  
}

void UDMAConfiguration()
{
  SysCtlPeripheralEnable(SYSCTL_PERIPH_UDMA);
  //SysCtlPeripheralSleepEnable(SYSCTL_PERIPH_UDMA);
  
  uDMAEnable();
  uDMAControlBaseSet(&controlTable[0]);
  
  uDMAChannelAssign(UDMA_CH9_UART0TX);

  //uDMAChannelAttributeDisable(UDMA_CH9_UART0TX, UDMA_ATTR_ALL);

  //uDMAChannelControlSet(UDMA_CH9_UART0TX | UDMA_PRI_SELECT, UDMA_SIZE_8 | UDMA_SRC_INC_8 | UDMA_DST_INC_NONE | UDMA_ARB_4);

  //uDMAChannelControlSet(UDMA_CH9_UART0TX | UDMA_ALT_SELECT, UDMA_SIZE_8 | UDMA_SRC_INC_8 | UDMA_DST_INC_NONE | UDMA_ARB_4);

  //uDMAChannelTransferSet(UDMA_CH9_UART0TX | UDMA_PRI_SELECT, UDMA_MODE_BASIC, pingBuffer, (void *)(UART0_BASE + UART_O_DR), sizeof(pingBuffer));  
  //uDMAChannelTransferSet(UDMA_CH9_UART0TX | UDMA_PRI_SELECT, UDMA_MODE_PINGPONG, pingBuffer, (void *)(UART0_BASE + UART_O_DR), sizeof(pingBuffer));  
  
  //uDMAChannelTransferSet(UDMA_CH9_UART0TX | UDMA_ALT_SELECT, UDMA_MODE_PINGPONG, pongBuffer, (void *)(UART0_BASE + UART_O_DR), sizeof(pongBuffer));
}

void UART0IntHandler()
{
  uint32_t DMAMode;
  
  //GPIOIntClear(GPIO_PORTE_BASE, GPIO_PIN_4);
  UARTIntClear(UART0_BASE, UART_INT_TX | UART_INT_RX);
  
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////  
  //DMAMode = uDMAChannelModeGet(UDMA_CH8_UART0RX | UDMA_PRI_SELECT);
  //DMAMode = uDMAChannelModeGet(UDMA_CH9_UART0TX | UDMA_PRI_SELECT);  
  
  //if(DMAMode == UDMA_MODE_STOP)
  //{
    //pingBuffer[0] = GPIOPinRead(GPIO_PORTB_BASE, 0xFF);
    
    //uDMAChannelTransferSet(UDMA_CH8_UART0RX | UDMA_PRI_SELECT, UDMA_MODE_PINGPONG, (void *)(UART0_BASE + UART_O_DR), pingBuffer, sizeof(pingBuffer));
    //uDMAChannelTransferSet(UDMA_CH9_UART0TX | UDMA_PRI_SELECT, UDMA_MODE_PINGPONG, pingBuffer, (void *)(UART0_BASE + UART_O_DR), sizeof(pingBuffer));
  //}

  //DMAMode = uDMAChannelModeGet(UDMA_CH8_UART0RX | UDMA_ALT_SELECT);  
  //DMAMode = uDMAChannelModeGet(UDMA_CH9_UART0TX | UDMA_ALT_SELECT);
  
  //if(DMAMode == UDMA_MODE_STOP)
  //{
    //pongBuffer[0] = GPIOPinRead(GPIO_PORTB_BASE, 0xFF);
    
    //uDMAChannelTransferSet(UDMA_CH8_UART0RX | UDMA_ALT_SELECT, UDMA_MODE_PINGPONG, (void *)(UART0_BASE + UART_O_DR), pongBuffer, sizeof(pongBuffer));    
    //uDMAChannelTransferSet(UDMA_CH9_UART0TX | UDMA_ALT_SELECT, UDMA_MODE_PINGPONG, pongBuffer, (void *)(UART0_BASE + UART_O_DR), sizeof(pongBuffer));
  //}
  
  //if(!uDMAChannelIsEnabled(UDMA_CH9_UART0TX))
  //{
    //uDMAChannelTransferSet(UDMA_CH9_UART0TX | UDMA_PRI_SELECT, UDMA_MODE_BASIC, txBuffer, (void *)(UART0_BASE + UART_O_DR), sizeof(txBuffer));
    
    //uDMAChannelEnable(UDMA_CH9_UART0TX);
  //}
}

void loop()
{}
*/
