//*****************************************************************************
//
// uart_echo.c - Example for reading data from and writing data to the UART in
//               an interrupt driven fashion.
//
// Copyright (c) 2013-2015 Texas Instruments Incorporated.  All rights reserved.
// Software License Agreement
//
// Texas Instruments (TI) is supplying this software for use solely and
// exclusively on TI's microcontroller products. The software is owned by
// TI and/or its suppliers, and is protected under applicable copyright
// laws. You may not combine this software with "viral" open-source
// software in order to form a larger program.
//
// THIS SOFTWARE IS PROVIDED "AS IS" AND WITH ALL FAULTS.
// NO WARRANTIES, WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT
// NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. TI SHALL NOT, UNDER ANY
// CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR CONSEQUENTIAL
// DAMAGES, FOR ANY REASON WHATSOEVER.
//
// This is part of revision 2.1.1.71 of the EK-TM4C1294XL Firmware Package.
//
//*****************************************************************************
#include "inc/hw_ints.h"

#include <stdint.h>
#include <stdbool.h>

#include "inc/hw_memmap.h"
//#include "inc/tm4c1294ncpdt.h"

#include "inc/sysctl.h"
#include "inc/hw_nvic.h"
#include "inc/hw_types.h"




#include <stdint.h>
#include <stdbool.h>
#include <string.h>
#include "inc/hw_memmap.h"
#include "driverlib/debug.h"
#include "driverlib/gpio.h"
#include "driverlib/interrupt.h"
#include "driverlib/pin_map.h"
#include "driverlib/rom.h"
#include "driverlib/rom_map.h"
#include "driverlib/sysctl.h"
#include "driverlib/uart.h"
//#include "uartstdio.h"
#include "inc/typedefs.h"

#define UART0_CTL_R             (*((volatile uint32_t *)0x4000C030))
#define UART3_CTL_R             (*((volatile uint32_t *)0x4000F030))

U8       byteCount, dataToSend, formerByte;
#define TERM_CHAR         0x9F
// GPIO definitions
#define clockLow     GPIO_PORTN_DATA_BITS_R[0x10] = 0x10; GPIO_PORTN_DATA_BITS_R[0x10] = 0x0; GPIO_PORTN_DATA_BITS_R[0x10] = 0x0; GPIO_PORTN_DATA_BITS_R[0x10] = 0x0; GPIO_PORTN_DATA_BITS_R[0x10] = 0x10;
#define clockHigh    GPIO_PORTN_DATA_BITS_R[0x20] = 0x20; GPIO_PORTN_DATA_BITS_R[0x20] = 0x0; GPIO_PORTN_DATA_BITS_R[0x20] = 0x0; GPIO_PORTN_DATA_BITS_R[0x20] = 0x0; GPIO_PORTN_DATA_BITS_R[0x20] = 0x20;
#define updateLowLed  GPIO_PORTK_DATA_BITS_R[0xFF] = dataToSend; clockLow;
#define updateHighLed GPIO_PORTK_DATA_BITS_R[0xFF] = dataToSend; clockHigh;

#define UART0_CTL_R             (*((volatile uint32_t *)0x4000C030))
const uint8_t *TxBuffer ;
uint32_t TxCount;
//unsigned char TrxBuffer[ 80] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ-!@#$0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ-!"; //80
//unsigned char TrxBuffer[ 80] = "All work and no play makes Jack a dull boy"; //80
unsigned char TrxBuffer[ 25] = { 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x9F, 0x00, 0x55, 0xAA};
//unsigned char TrxBuffer[ 25] = { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x80, 0x01, 0x01, 0x9F};
/*
unsigned char TrxBuffer[ 80] =
{ 0x80, 0x00, 0x81, 0x2D, 0x82, 0x13, 0x83, 0x05,
  0x9F, 0x00, 0x84, 0x00, 0x87, 0x17, 0x8A, 0x00,
  0x91, 0xFB, 0x8E, 0x2D, 0x90, 0x15, 0xB6, 0x05,
  0xB7, 0xFB, 0x93, 0x00, 0x94, 0xB4, 0x96, 0x00,
  0x99, 0x01, 0x97, 0x50, 0x98, 0x00, 0xB8, 0x01,
  0xB9, 0x05, 0xBA, 0x00, 0xB1, 0x04, 0xB2, 0xB0,
  0x89, 0x8A, 0x9F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
*/
unsigned int txcounter = 0;
unsigned int txlen;
unsigned char txcomplete = 0;
void UARTSend( const uint8_t *pui8Buffer, uint32_t ui32Count);
U8   byteCounter;


//*****************************************************************************
//
//! \addtogroup example_list
//! <h1>UART Echo (uart_echo)</h1>
//!
//! This example application utilizes the UART to echo text.  The first UART
//! (connected to the USB debug virtual serial port on the evaluation board)
//! will be configured in 4800 baud, 8-n-1 mode.  All characters received on
//! the UART are transmitted back to the UART.
//
//*****************************************************************************

//****************************************************************************
//
// System clock rate in Hz.
//
//****************************************************************************
uint32_t g_ui32SysClock;

//*****************************************************************************
//
// The error routine that is called if the driver library encounters an error.
//
//*****************************************************************************
#ifdef DEBUG
void
__error__(char *pcFilename, uint32_t ui32Line)
{
}
#endif
/*
    Install a GPS port on UART2...
*/
void GPS_Init( void)
{
  SysCtlPeripheralEnable( SYSCTL_PERIPH_UART2);
  SysCtlPeripheralEnable( SYSCTL_PERIPH_GPIOA);
  GPIOPinConfigure( GPIO_PA6_U2RX);
  GPIOPinConfigure( GPIO_PA7_U2TX);
  GPIOPinTypeUART( GPIO_PORTA_BASE, GPIO_PIN_6 | GPIO_PIN_7);
  UARTConfigSetExpClk( UART2_BASE, g_ui32SysClock , 4800,( UART_CONFIG_WLEN_8 | UART_CONFIG_STOP_ONE | UART_CONFIG_PAR_NONE));
}

//*****************************************************************************
//
// The UART interrupt handler.
//
//*****************************************************************************
void UARTIntHandler(void)
{
    uint32_t ui32Status;
    uint8_t  int_type;
    TxCount = 16;
    //
    // Get the interrupt status.
    //
    ui32Status = UARTIntStatus( UART0_BASE, true);

    int_type = ( uint8_t)(( ui32Status & 0x0F0) >> 4);

    //
    // Clear the asserted interrupts.
    //
    UARTIntClear( UART0_BASE, ui32Status);

    switch( int_type)
    {
    case 1 :
      // Loop while there are characters in the receive FIFO.
      //
      while( UARTCharsAvail( UART0_BASE))
      {
        //
        // Read the next character from the UART and write it back to the UART.
        //
        UARTCharPutNonBlocking( UART0_BASE, UARTCharGetNonBlocking( UART0_BASE));

        //
        // Blink the LED to show a character transfer is occurring.
        //
        GPIOPinWrite( GPIO_PORTN_BASE, GPIO_PIN_1, GPIO_PIN_1);

        //
        // Delay for 1 millisecond.  Each SysCtlDelay is about 3 clocks.
        //
        SysCtlDelay( g_ui32SysClock / (1000 * 3));

        //
        // Turn off the LED
        //
        GPIOPinWrite( GPIO_PORTN_BASE, GPIO_PIN_1, 0);
      }
      break;

    case 2:
      dataToSend = TrxBuffer[ txcounter];
      UARTSend(( uint8_t *)&TrxBuffer[ txcounter++], 1);
      if (byteCount != txcounter)
      {
        GPIOPinWrite( GPIO_PORTN_BASE, GPIO_PIN_1, GPIO_PIN_1);
        byteCounter++;
      }
      else
        byteCounter = 0;
      if (byteCounter & 1)
      {
  //      updateLowLed;
      }
      else
      {
        dataToSend = formerByte;
  //      updateHighLed;
        formerByte = TrxBuffer[ txcounter];
      }
      formerByte = dataToSend;
      if( txcounter > txlen )
      {
        txcomplete = 1;
        txcounter = 0;
//        UARTprintf( "\n");
        //
        // Blink the LED to show a character transfer is occurring.
        //
        GPIOPinWrite( GPIO_PORTN_BASE, GPIO_PIN_0, GPIO_PIN_0);

        //
        // Delay for 1 millisecond.  Each SysCtlDelay is about 3 clocks.
        //
        SysCtlDelay( g_ui32SysClock / (1000 * 3));

        //
        // Turn off the LED
        //
        GPIOPinWrite( GPIO_PORTN_BASE, GPIO_PIN_0, 0);
      }
      GPIOPinWrite( GPIO_PORTN_BASE, GPIO_PIN_1, 0);
      break;

    default:
        break;


    }
}

//*****************************************************************************
//
// Configure the UART and its pins.  This must be called before UARTprintf().
//
//*****************************************************************************
void ConfigureUART( void)
{
    //
    // Enable the GPIO Peripheral used by the UART.
    //
    SysCtlPeripheralEnable( SYSCTL_PERIPH_GPIOA);

    //
    // Enable UART0
    //
    SysCtlPeripheralEnable( SYSCTL_PERIPH_UART0);

    //
    // Configure GPIO Pins for UART mode.
    //
    GPIOPinConfigure( GPIO_PA0_U0RX);
    GPIOPinConfigure( GPIO_PA1_U0TX);
    GPIOPinTypeUART( GPIO_PORTA_BASE, GPIO_PIN_0 | GPIO_PIN_1);

    //
    // Initialize the UART for console I/O.
    //
//    UARTStdioConfig( 0, 4800, g_ui32SysClock);
}

//*****************************************************************************
//
// Send a string to the UART.
//
//*****************************************************************************
void UARTSend( const uint8_t *pui8Buffer, uint32_t ui32Count)
{
  //
  // Loop while there are more characters to send.
  //
  while( ui32Count--)
  {
    //
    // Write the next character to the UART.
    //
    UARTCharPut( UART0_BASE, *pui8Buffer);
  }
}

//*****************************************************************************
//
// This example demonstrates how to send a string of data to the UART.
//
//*****************************************************************************

void Enable_Interrupt_Tx_Transmission( void)
{
  /* Disable and flush the uart... */
  UARTDisable( UART0_BASE);

  while( UARTCharsAvail( UART0_BASE) && ( UARTSpaceAvail( UART0_BASE)));

  txcomplete = 0;
  UARTTxIntModeSet( UART0_BASE, UART_TXINT_MODE_EOT);


  UARTConfigSetExpClk( UART0_BASE, g_ui32SysClock, 4800,
  ( UART_CONFIG_WLEN_8 | UART_CONFIG_STOP_ONE | UART_CONFIG_PAR_NONE));

  IntMasterEnable();

  IntEnable( INT_UART0);
  /* Enable the interrupt for transmit & receive with a receive timeout...*/
  UARTIntEnable( UART0_BASE, UART_INT_TX | UART_INT_RX | UART_INT_RT);
  UART0_CTL_R |= 0x10;
  UARTEnable( UART0_BASE);
}
/* ======================================================================================================================================= */
/*
    Going to try switching the UART from #0...
*/
int main(void)
{
  //
  // Set the clocking to run directly from the crystal at 120MHz.
  //
  g_ui32SysClock = MAP_SysCtlClockFreqSet(( SYSCTL_XTAL_25MHZ |

  /*  QPN MLKJ HGFE DCBA
  *   001 0110 0011 0011
  */
  //SYSCTL_RCGCGPIO_R = 0x1633;


  SYSCTL_OSC_MAIN |
  SYSCTL_USE_PLL |
  SYSCTL_CFG_VCO_480), 120000000);
  byteCount = 0;
  ConfigureUART();
  GPS_Init();
//  UARTprintf( "\n Serial Port Code \n");
  //
  // Enable the GPIO port that is used for the on-board LED.
  //
  SysCtlPeripheralEnable( SYSCTL_PERIPH_GPION);

  //
  // Enable the GPIO pins for the LED (PN0).
  //
//GPIOPinTypeGPIOOutput( GPIO_PORTN_BASE, GPIO_PIN_0);
  GPIOPinTypeGPIOOutput( GPIO_PORTN_BASE, 3);     // GPIO_PIN_0);

  //
  // Enable the peripherals used by this example.
  //
  SysCtlPeripheralEnable (SYSCTL_PERIPH_UART0);
  SysCtlPeripheralEnable( SYSCTL_PERIPH_GPIOA);

  //
  // Enable processor interrupts.
  //
  IntMasterEnable();

  //
  // Set GPIO A0 and A1 as UART pins.
  //
  GPIOPinConfigure( GPIO_PA0_U0RX);
  GPIOPinConfigure( GPIO_PA1_U0TX);
  GPIOPinTypeUART( GPIO_PORTA_BASE, GPIO_PIN_0 | GPIO_PIN_1);

  IntMasterDisable();
  UARTDisable( UART0_BASE);

  UARTTxIntModeSet( UART0_BASE, UART_TXINT_MODE_EOT);

  UARTConfigSetExpClk( UART0_BASE, g_ui32SysClock, 4800,
    ( UART_CONFIG_WLEN_8 | UART_CONFIG_STOP_ONE |
    UART_CONFIG_PAR_NONE));

  IntMasterEnable();

  IntEnable( INT_UART0);
  UARTIntEnable( UART0_BASE, UART_INT_TX | UART_INT_RX | UART_INT_RT);

  UARTEnable( UART0_BASE);
  //    UARTFIFOEnable(UART0_BASE);

  txlen = 10;

  Enable_Interrupt_Tx_Transmission();


  UARTSend(( uint8_t *)&TrxBuffer[ txcounter++], 1);

  //
  // Loop forever echoing data through the UART.
  //
  while( 1)
  {
    /* Sit inside this loop until the full length of the sentence is sent... */
    while( !( txcomplete));
    /* Reset txcomplete for the next cycle... */
    txcomplete = 0;
//    SysCtlDelay( g_ui32SysClock / (1000 * 25));


//    if ( UARTCharsAvail( UART2_BASE))
//      UARTprintf( "> %s", UARTCharGet( UART2_BASE));
  }
}
