/*
 * Aux_port.c
 *
 *  Created on: Feb 4, 2014
 *      Author: rob
 *  Modified: 2 Jan 2021
 *      Thom Maughan tm
 *       API changed to specify uart2 for substrate functions, high level functions named for specific driver
 *       Added support for Aanderaa Conductivity (Condo is Conductivity from Aanderaa)
 */

#include "System.h"
#include "Aux1.h"
#include "uartstdio.h"	// User local version with larger RX buffer

// AUX1 Port defines (Note: if UART2 is changed, the substrate functions should be changed to the new uart selected)
#define AUX1_UART_BASE           UART2_BASE
#define AUX1_UART_PERIPH         SYSCTL_PERIPH_UART2
#define AUX1_GPIO_PORT_BASE      GPIO_PORTG_BASE
#define AUX1_GPIO_PERIPH         SYSCTL_PERIPH_GPIOG
#define AUX1_GPIO_PIN_NAME_RX    GPIO_PG4_U2RX
#define AUX1_GPIO_PIN_NAME_TX    GPIO_PG5_U2TX
#define AUX1_GPIO_PIN_NUMBER_RX  GPIO_PIN_5
#define AUX1_GPIO_PIN_NUMBER_TX  GPIO_PIN_4
#define AUX1_UART_INT            INT_UART2

#define AUX1_UART_RX_BUFFER_SIZE     256
#define AUX1_UART_TX_BUFFER_SIZE     128

//struct condoDriver condo;   // struct defd in aux1.h


//*****************************************************************************
//
// This global controls whether or not we are echoing characters back to the
// transmitter.  By default, echo is enabled but if using this module as a
// convenient method of implementing a buffered serial interface over which
// you will be running an application protocol, you are likely to want to
// disable echo by calling UARTEchoSet(false).
//
//*****************************************************************************
static bool g_bDisableEcho;

//*****************************************************************************
//
// Output ring buffer.  Buffer is full if g_ui32UARTTxReadIndex is one ahead of
// g_ui32UARTTxWriteIndex.  Buffer is empty if the two indices are the same.
//
//*****************************************************************************
static unsigned char g_pcUARTTxBuffer[AUX1_UART_TX_BUFFER_SIZE];
static volatile uint32_t g_ui32UARTTxWriteIndex = 0;
static volatile uint32_t g_ui32UARTTxReadIndex = 0;

//*****************************************************************************
//
// Input ring buffer.  Buffer is full if g_ui32UARTTxReadIndex is one ahead of
// g_ui32UARTTxWriteIndex.  Buffer is empty if the two indices are the same.
//
//*****************************************************************************
static unsigned char g_pcUARTRxBuffer[AUX1_UART_RX_BUFFER_SIZE];
static volatile uint32_t g_ui32UARTRxWriteIndex = 0;
static volatile uint32_t g_ui32UARTRxReadIndex = 0;

//*****************************************************************************
//
// Macros to determine number of free and used bytes in the transmit buffer.
//
//*****************************************************************************
#define TX_BUFFER_USED          (GetBufferCount(&g_ui32UARTTxReadIndex,  \
                                                &g_ui32UARTTxWriteIndex, \
                                                UART_TX_BUFFER_SIZE))
#define TX_BUFFER_FREE          (UART_TX_BUFFER_SIZE - TX_BUFFER_USED)
#define TX_BUFFER_EMPTY         (IsBufferEmpty(&g_ui32UARTTxReadIndex,   \
                                               &g_ui32UARTTxWriteIndex))
#define TX_BUFFER_FULL          (IsBufferFull(&g_ui32UARTTxReadIndex,  \
                                              &g_ui32UARTTxWriteIndex, \
                                              UART_TX_BUFFER_SIZE))
#define ADVANCE_TX_BUFFER_INDEX(Index) \
                                (Index) = ((Index) + 1) % UART_TX_BUFFER_SIZE

//*****************************************************************************
//
// Macros to determine number of free and used bytes in the receive buffer.
//
//*****************************************************************************
#define RX_BUFFER_USED          (GetBufferCount(&g_ui32UARTRxReadIndex,  \
                                                &g_ui32UARTRxWriteIndex, \
                                                AUX1_UART_RX_BUFFER_SIZE))
#define RX_BUFFER_FREE          (AUX1_UART_RX_BUFFER_SIZE - RX_BUFFER_USED)
#define RX_BUFFER_EMPTY         (IsBufferEmpty(&g_ui32UARTRxReadIndex,   \
                                               &g_ui32UARTRxWriteIndex))
#define RX_BUFFER_FULL          (IsBufferFull(&g_ui32UARTRxReadIndex,  \
                                              &g_ui32UARTRxWriteIndex, \
                                              AUX1_UART_RX_BUFFER_SIZE))
#define ADVANCE_RX_BUFFER_INDEX(Index) \
                                (Index) = ((Index) + 1) % AUX1_UART_RX_BUFFER_SIZE

//*****************************************************************************
//
// The base address of the chosen UART.
//
//*****************************************************************************
static uint32_t g_ui32Base = 0;

//*****************************************************************************
//
// The list of possible base addresses for the console UART.
//
//*****************************************************************************
static const uint32_t g_ui32UARTBase[6] =
{
    UART0_BASE, UART1_BASE, UART2_BASE, UART3_BASE, UART4_BASE, UART5_BASE
};

//*****************************************************************************
//
// The list of possible interrupts for the console UART.
//
//*****************************************************************************
static const uint32_t g_ui32UARTInt[6] =
{
    INT_UART0, INT_UART1, INT_UART2, INT_UART3, INT_UART4, INT_UART5
};

//*****************************************************************************
//
// The port number in use.
//
//*****************************************************************************
static uint32_t g_ui32PortNum;

//*****************************************************************************
//
// The list of UART peripherals.
//
//*****************************************************************************
static const uint32_t g_ui32UARTPeriph[6] =
{
    SYSCTL_PERIPH_UART0, SYSCTL_PERIPH_UART1, SYSCTL_PERIPH_UART2, SYSCTL_PERIPH_UART3, SYSCTL_PERIPH_UART4, SYSCTL_PERIPH_UART5
};

#ifdef MOVEDTOCONDOC

/*
 *  Initialize gpio pins, powered off, setup uart2 peripheral (condo_init replaces aux1_init)
 *    TODO: decouple instrument driver from uart2 and peripheral setup.
 */
void condo_init(void)
{
#if BOARD_MPHOX == 1
    // Setup J14 power pin (schematic AUXPwr3O PD3) and turn power switch OFF
    MAP_GPIOPinTypeGPIOOutput(GPIO_PORTD_BASE, GPIO_PIN_3);
    MAP_GPIOPinWrite(GPIO_PORTD_BASE, GPIO_PIN_3, 0x00);  // PD3 = 0, Power off

    // Setup MAX3221 rs232 driver (schematic Spare_Enable PM0, Spare_Shutdown PM1
    MAP_GPIOPinTypeGPIOOutput(GPIO_PORTM_BASE, GPIO_PIN_0);
    MAP_GPIOPinWrite(GPIO_PORTM_BASE, GPIO_PIN_0, 0xFF);  // Active lo enable (in active)
    MAP_GPIOPinTypeGPIOOutput(GPIO_PORTM_BASE, GPIO_PIN_1);
    MAP_GPIOPinWrite(GPIO_PORTM_BASE, GPIO_PIN_1, 0x00);  // Active hi, power on (max3221 power off)

    // setup uart2 pins
    ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_UART2);
    ROM_GPIOPinConfigure(GPIO_PG4_U2RX);
    ROM_GPIOPinConfigure(GPIO_PG5_U2TX);
    ROM_GPIOPinTypeUART(GPIO_PORTG_BASE, GPIO_PIN_4 | GPIO_PIN_5);

    // Use the internal 16MHz oscillator as the UART clock source.
    UARTClockSourceSet(UART2_BASE, UART_CLOCK_PIOSC);
	
    //#define CONDO_BAUD     9600  defd in aux1.h
    uart2_Config(2, CONDO_BAUD, 16000000); // Configure Conductivity (Condo) UART2  (9600,N,8,1)
    uart2_echoSet(0);   // Disable echo 
#endif
}

/*
 * condo_open() applies power, activates the RS-232 driver, sets up uart2 driver
 */
void condo_open(void)
{
#if BOARD_MPHOX == 1
#ifdef FUTURECODE
    // measure vbatt, if over 14v, abort
    if(gfBattMainV > 14.0v)
    {
        uprintf("\n5860 Conductivity Sensor requires 5v to 14v, MpHOx batt is %6.2f, OverVoltage Abort!\n", vBatv)
    }
#endif
	//AUX1_on();		// AUX1 power on
    MAP_GPIOPinWrite(GPIO_PORTD_BASE, GPIO_PIN_3, 0xFF);  // AuxPwr3O, PD3 = 1, Power on (SparePwr)

    // turn on rs232 driver and enable output
    MAP_GPIOPinWrite(GPIO_PORTM_BASE, GPIO_PIN_0, 0x00);  // Active lo enable (enabled)  Spare_Enable
    MAP_GPIOPinWrite(GPIO_PORTM_BASE, GPIO_PIN_1, 0xFF);  // Active hi, power on (max3221 power on)  Spare_Shutdown

	
    condo.state = 0;
    condo.bufIndx = 0;
    ROM_SysCtlDelay(MILLISECOND*1);  // allow power to stabilize for 1mec
    uart2_flushRx();
    uart2_flushTx(true);   // true says discard	
#endif
}

/*
 * condo_close turns off the Optode (removes power
 * and disables the UART).
 */
void condo_close(void)
{
#if BOARD_MPHOX == 1
    // turn rs232 driver ic off
    MAP_GPIOPinWrite(GPIO_PORTM_BASE, GPIO_PIN_0, 0xFF);  // Active lo enable (in active)
    MAP_GPIOPinWrite(GPIO_PORTM_BASE, GPIO_PIN_1, 0x00);  // Active hi, power on (max3221 power off)

    // turn off vbat supply to J14 on MPHOX
    MAP_GPIOPinWrite(GPIO_PORTD_BASE, GPIO_PIN_3, 0x00);  // AuxPwr3O, PD3 = 1, Power on (SparePwr)

    //MAP_GPIOPinWrite(GPIO_PORTK_BASE, GPIO_PIN_4, 0x00);  // disable uart2 RS-232 driver

#endif

}


/*
 * condo_stateMachine
 *
 * pass in state=1 to start it, check for finish when returned state value is 0
 *
 */
int condo_stateMachine(int condoState)
{
#if BOARD_MPHOX == 1
    int nextState = 0;
    unsigned int indx;
    unsigned int tick1, tick2;
    unsigned char inChar;


    // example usage:
    //condoState = 1;
    //condoState = condo_statemachine(condoState);     //pass in 1 to start the state machine, hereafter pass retVal
    //call statemachine repeatedly until condoState == 0

    // condo_open  (turn on power, wait 1msec, flush rx and tx bufs
    // look for % within 600msec, then send crlf
    // look for !, then send do_sample and crlf
    // look for output terminated by crlf and # within 2000msec
    // trim crlf
    // closeOptde
    // look at retVal, if retVal=-1, that's a timeout, then terminate statemachine by sending it a 0 as arg




    condo.state = condoState;    // for debugging, condo.state not used at this time.

    switch(condoState)
    {
        case 0:
            // do nothing, caller needs to pass in state=1 to start things
            return(0);

        case 1:
            condo_open();   // power on condo 5v supply
            condo.old_tick10ms = Timer_10ms(false);
            return(2);

        case 2:
            if( uart2_rxBytesAvail() )
            {
                inChar = uart2_getc();
                //uprintf( "%c", inChar );
                if(inChar == '%')
                {
                    condo.old_tick10ms = Timer_10ms(false);
                    uart2_putc(0x0d);  // CR=13
                    uart2_putc(0x0a);  // LF=10
                    return(3);   // next state, look for !
                }
            }

            condo.new_tick10ms = Timer_10ms(false);
            if((condo.new_tick10ms - condo.old_tick10ms) >= 60)  // 600msec = 60*10msec
            {
				// if timeout waiting for % char, then send two crlf pairs
                uart2_putc(0x0d);  // CR=13
                uart2_putc(0x0a);  // LF=10

                uart2_putc(0x0d);  // CR=13
                uart2_putc(0x0a);  // LF=10

                uart2_write("do sample\r\n",12 );
                condo.old_tick10ms = Timer_10ms(false);
                return(4);

            }

            return(2);

        case 3:
            // look for !, then send do_sample and crlf
            if( uart2_rxBytesAvail() )
            {
                inChar = uart2_getc();
                //uprintf( "%c", inChar );
                if(inChar == '!')
                {
					//condo_poll();
                    uart2_write("do sample\r\n",12 );
                    condo.old_tick10ms = Timer_10ms(false);
                    return(4);
                }
            }
            condo.new_tick10ms = Timer_10ms(false);
            if((condo.new_tick10ms - condo.old_tick10ms) >= 50)  // 500msec = 50*10msec
            {
                //uprintf("\nOptode power on did not receive ! char delimiter in 500msec - check condo connection or setup\n");
                sprintf((char *)&condo.buf[0], "Optode not responding with ! char after crlf");
                condo_close();  // Close Optode, power off
                return(0);
            }
            return(3);

        case 4:
            // look for sample output terminated by crlf and # within 2000msec

            if( uart2_rxBytesAvail() )      // Optode
            {
                inChar = uart2_getc();

                condo.buf[condo.bufIndx] = inChar;
                condo.bufIndx++;
                if(condo.bufIndx >= CONDO_BUFFER_SIZE)		// defd in system.h
                {
                    condo.bufIndx = CONDO_BUFFER_SIZE-1;
                    uprintf("\nDEBUG: error in condo driver bufIndx exceeds buf size, condo.c\n");
                    condo_close();  // Close Optode, power off
                    return(0);
                }

            }

            if(inChar == '#')
            {

                //uprintf("\nDEBUG: Optode power off\n");

                // trim any leading chars, trim crlf and make it 0 terminated string
                for(indx=0; indx<condo.bufIndx; indx++)
                {
                    if(condo.buf[indx] == 0x0d)
                    {
                        condo.buf[indx] = 0;       // 0 terminated
                        break;
                    }

                }
                //uprintf("\nDEBUG OPTODE string=%s\n", &condo.buf[0]);
                condo_close();  // Close Optode, power off
                return(0);
                //break;  // from while(1), do sample is done
            }

            condo.new_tick10ms = Timer_10ms(false);
            if((condo.new_tick10ms - condo.old_tick10ms) >= 300)  // 2000msec = 200*10msec
            {
                //uprintf("\nOptode power on did not receive sample string after do sample - check condo connection or setup\n");
                sprintf((char *)&condo.buf[0], "Optode not responding with sample string after do sample");
                condo_close();  // Close Optode, power off
                return(0);
            }
            return(4);
            //break;

        default:
            return(0);
            //break;


    }

#endif
}

void condo_print_buf(void)
{
#if BOARD_MPHOX == 1
    uprintf("%s", condo.buf);
#endif
}

/*
 * condo_poll() sends "do_sample."  Data is received
 * via the UART2 interrupt handler
 */
void condo_poll()
{
#if BOARD_MPHOX == 1
    uart2_write("do sample\r\n",12 );
#endif
}




#endif // moved to condo.c



/*
 *  Initialize AUX 1 pins, power off, peripheral as uart2, 
 *
 *  THOM TODO:  MPHOX schematic needs to be checked for AUX1 implementation
 *              Need to have schematic update to use the same names as software.
 *
 */
void AUX1_init(void)
{
    // THOM TODO: this code is untested, likely has errors due to schematic and code mismatch
    // AUX1 power and AUX1 uart are not on J14 together, not sure what is correct... 17 Apr 2021

	// Set up AUX1 power pin
	MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOD);
	MAP_GPIOPinTypeGPIOOutput(GPIO_PORTD_BASE, GPIO_PIN_3);  // PD3 (pin 4) is AuxPwr3on
	MAP_GPIOPinWrite(GPIO_PORTD_BASE, GPIO_PIN_3, 0x00);	// Power off

	// AUX1 UART PWRDOWN (PM0 is spare enable, PM1 is spare shutdown, pin 112) pin
	MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOM);
	MAP_GPIOPinTypeGPIOOutput(GPIO_PORTM_BASE, GPIO_PIN_0);
	MAP_GPIOPinWrite(GPIO_PORTM_BASE, GPIO_PIN_0, 0xFF);	// Spare Enable active lo (off)

    MAP_GPIOPinTypeGPIOOutput(GPIO_PORTM_BASE, GPIO_PIN_1);
    MAP_GPIOPinWrite(GPIO_PORTM_BASE, GPIO_PIN_1, 0x00);    // Spare shutdown active lo (off)


	// Set up AUX1 UART2 pins
	MAP_SysCtlPeripheralEnable(AUX1_UART_PERIPH);
	MAP_SysCtlPeripheralEnable(AUX1_GPIO_PERIPH );
	MAP_GPIOPinConfigure(AUX1_GPIO_PIN_NAME_RX);			  //set up the pins
	MAP_GPIOPinConfigure(AUX1_GPIO_PIN_NAME_TX);
	MAP_GPIOPinTypeUART(AUX1_GPIO_PORT_BASE, AUX1_GPIO_PIN_NUMBER_RX | AUX1_GPIO_PIN_NUMBER_TX);

    // Use the internal 16MHz oscillator as the UART clock source.
    UARTClockSourceSet(UART2_BASE, UART_CLOCK_PIOSC);
	
    uart2_Config(2, 9600, 16000000); // Configure uart2 (9600,N,8,1)
    uart2_echoSet(0);   // Disable echo 
}

/*
 * Open_AUX2 applies power and activates the RS-232 driver
 */
void Open_AUX1(void)
{
	//AUX1_on();

    //AuxPwr3on = OFF
    MAP_GPIOPinWrite(GPIO_PORTD_BASE, GPIO_PIN_3, 0xFF);    // Power on

	//RS232 driver on
    MAP_GPIOPinWrite(GPIO_PORTM_BASE, GPIO_PIN_0, 0x00);    // Spare Enable active lo (on)
    MAP_GPIOPinWrite(GPIO_PORTM_BASE, GPIO_PIN_1, 0xFF);    // Spare shutdown active lo (on)

    //MAP_GPIOPinWrite(GPIO_PORTK_BASE, GPIO_PIN_4, 0xff);	// COM2 RS-232 driver on
	uart2_echoSet(0);	// Disable echo
}

/*
 * Close_AUX2 removes power and shuts down the RS-232 driver
 */
void Close_AUX1(void)
{
	//AUX1_off();

    //AuxPwr3on = OFF
    MAP_GPIOPinWrite(GPIO_PORTD_BASE, GPIO_PIN_3, 0x00);    // Power off

	//RS232 driver off
    MAP_GPIOPinWrite(GPIO_PORTM_BASE, GPIO_PIN_0, 0xFF);    // Spare Enable active lo (off)
    MAP_GPIOPinWrite(GPIO_PORTM_BASE, GPIO_PIN_1, 0x00);    // Spare shutdown active lo (off)

	//MAP_GPIOPinWrite(GPIO_PORTK_BASE, GPIO_PIN_4, 0x00);	// COM2 RS-232 driver off
}


/*
 * ASCII characters.
 */
#define SPACE 0x20
#define OPENBRACE 0x7b
#define TAB 0x09


//*****************************************************************************
//
//! Determines whether the ring buffer whose pointers and size are provided
//! is full or not.
//!
//! \param pui32Read points to the read index for the buffer.
//! \param pui32Write points to the write index for the buffer.
//! \param ui32Size is the size of the buffer in bytes.
//!
//! This function is used to determine whether or not a given ring buffer is
//! full.  The structure of the code is specifically to ensure that we do not
//! see warnings from the compiler related to the order of volatile accesses
//! being undefined.
//!
//! \return Returns \b true if the buffer is full or \b false otherwise.
//
//*****************************************************************************
static bool
IsBufferFull(volatile uint32_t *pui32Read,
             volatile uint32_t *pui32Write, uint32_t ui32Size)
{
    uint32_t ui32Write;
    uint32_t ui32Read;

    ui32Write = *pui32Write;
    ui32Read = *pui32Read;

    return((((ui32Write + 1) % ui32Size) == ui32Read) ? true : false);
}

//*****************************************************************************
//
//! Determines whether the ring buffer whose pointers and size are provided
//! is empty or not.
//!
//! \param pui32Read points to the read index for the buffer.
//! \param pui32Write points to the write index for the buffer.
//!
//! This function is used to determine whether or not a given ring buffer is
//! empty.  The structure of the code is specifically to ensure that we do not
//! see warnings from the compiler related to the order of volatile accesses
//! being undefined.
//!
//! \return Returns \b true if the buffer is empty or \b false otherwise.
//
//*****************************************************************************
static bool
IsBufferEmpty(volatile uint32_t *pui32Read,
              volatile uint32_t *pui32Write)
{
    uint32_t ui32Write;
    uint32_t ui32Read;

    ui32Write = *pui32Write;
    ui32Read = *pui32Read;

    return((ui32Write == ui32Read) ? true : false);
}

//*****************************************************************************
//
//! Determines the number of bytes of data contained in a ring buffer.
//!
//! \param pui32Read points to the read index for the buffer.
//! \param pui32Write points to the write index for the buffer.
//! \param ui32Size is the size of the buffer in bytes.
//!
//! This function is used to determine how many bytes of data a given ring
//! buffer currently contains.  The structure of the code is specifically to
//! ensure that we do not see warnings from the compiler related to the order
//! of volatile accesses being undefined.
//!
//! \return Returns the number of bytes of data currently in the buffer.
//
//*****************************************************************************
static uint32_t
GetBufferCount(volatile uint32_t *pui32Read,
               volatile uint32_t *pui32Write, uint32_t ui32Size)
{
    uint32_t ui32Write;
    uint32_t ui32Read;

    ui32Write = *pui32Write;
    ui32Read = *pui32Read;

    return((ui32Write >= ui32Read) ? (ui32Write - ui32Read) :
           (ui32Size - (ui32Read - ui32Write)));
}

//*****************************************************************************
//
// Take as many bytes from the transmit buffer as we have space for and move
// them into the UART transmit FIFO.
//
//*****************************************************************************
static void
UARTPrimeTransmit(uint32_t ui32Base)
{
    //
    // Do we have any data to transmit?
    //
    if(!TX_BUFFER_EMPTY)
    {
        //
        // Disable the UART interrupt.  If we don't do this there is a race
        // condition which can cause the read index to be corrupted.
        //
        MAP_IntDisable(g_ui32UARTInt[g_ui32PortNum]);

        //
        // Yes - take some characters out of the transmit buffer and feed
        // them to the UART transmit FIFO.
        //
        while(MAP_UARTSpaceAvail(ui32Base) && !TX_BUFFER_EMPTY)
        {
            MAP_UARTCharPutNonBlocking(ui32Base,
                                      g_pcUARTTxBuffer[g_ui32UARTTxReadIndex]);
            ADVANCE_TX_BUFFER_INDEX(g_ui32UARTTxReadIndex);
        }

        //
        // Reenable the UART interrupt.
        //
        MAP_IntEnable(g_ui32UARTInt[g_ui32PortNum]);
    }
}

//*****************************************************************************
//
//! Configures the UART console.
//!
//! \param ui32PortNum is the number of UART port to use for the serial console
//! (0-2)
//! \param ui32Baud is the bit rate that the UART is to be configured to use.
//! \param ui32SrcClock is the frequency of the source clock for the UART
//! module.
//!
//! This function will configure the specified serial port to be used as a
//! serial console.  The serial parameters are set to the baud rate
//! specified by the \e ui32Baud parameter and use 8 bit, no parity, and 1 stop
//! bit.
//!
//! This function must be called prior to using any of the other UART console
//! functions: uprintf() or UARTgets().  This function assumes that the
//! caller has previously configured the relevant UART pins for operation as a
//! UART rather than as GPIOs.
//!
//! \return None.
//
//*****************************************************************************
void
uart2_Config(uint32_t ui32PortNum, uint32_t ui32Baud, uint32_t ui32SrcClock)
{
    //
    // Check to make sure the UART peripheral is present.
    //
    if(!MAP_SysCtlPeripheralPresent(g_ui32UARTPeriph[ui32PortNum]))
    {
        return;
    }

    //
    // Select the base address of the UART.
    //
    g_ui32Base = g_ui32UARTBase[ui32PortNum];

    //
    // Enable the UART peripheral for use.
    //
    MAP_SysCtlPeripheralEnable(g_ui32UARTPeriph[ui32PortNum]);

    //
    // Configure the UART for 115200, n, 8, 1
    //
    MAP_UARTConfigSetExpClk(g_ui32Base, ui32SrcClock, ui32Baud,
                            (UART_CONFIG_PAR_NONE | UART_CONFIG_STOP_ONE |
                             UART_CONFIG_WLEN_8));

    //
    // Set the UART to interrupt whenever the TX FIFO is almost empty or
    // when any character is received.
    //
    MAP_UARTFIFOLevelSet(g_ui32Base, UART_FIFO_TX1_8, UART_FIFO_RX1_8);

    //
    // Flush both the buffers.
    //
    uart2_flushRx();
    uart2_flushTx(true);

    //
    // Remember which interrupt we are dealing with.
    //
    g_ui32PortNum = ui32PortNum;

    //
    // We are configured for buffered output so enable the master interrupt
    // for this UART and the receive interrupts.  We don't actually enable the
    // transmit interrupt in the UART itself until some data has been placed
    // in the transmit buffer.
    //
    MAP_UARTIntDisable(g_ui32Base, 0xFFFFFFFF);
    MAP_UARTIntEnable(g_ui32Base, UART_INT_RX | UART_INT_RT);
    MAP_IntEnable(g_ui32UARTInt[ui32PortNum]);

    //
    // Enable the UART operation.
    //
    MAP_UARTEnable(g_ui32Base);
}

//*****************************************************************************
//
//! Writes a string of characters to the UART output.
//!
//! \param pcBuf points to a buffer containing the string to transmit.
//! \param ui32Len is the length of the string to transmit.
//!
//! This function will transmit the string to the UART output.  The number of
//! characters transmitted is determined by the \e ui32Len parameter.  This
//! function does no interpretation or translation of any characters.  Since
//! the output is sent to a UART, any LF (/n) characters encountered will be
//! replaced with a CRLF pair.
//!
//! Besides using the \e ui32Len parameter to stop transmitting the string, if
//! a null character (0) is encountered, then no more characters will be
//! transmitted and the function will return.
//!
//! In non-buffered mode, this function is blocking and will not return until
//! all the characters have been written to the output FIFO.  In buffered mode,
//! the characters are written to the UART transmit buffer and the call returns
//! immediately.  If insufficient space remains in the transmit buffer,
//! additional characters are discarded.
//!
//! \return Returns the count of characters written.
//
//*****************************************************************************
int
uart2_write(const char *pcBuf, uint32_t ui32Len)			// AUX1
{
    unsigned int uIdx;

    //
    // Send the characters
    //
    for(uIdx = 0; uIdx < ui32Len; uIdx++)
    {
        //
        // If the character to the UART is \n, then add a \r before it so that
        // \n is translated to \n\r in the output.
        //
        if(pcBuf[uIdx] == '\n')
        {
            if(!TX_BUFFER_FULL)
            {
                g_pcUARTTxBuffer[g_ui32UARTTxWriteIndex] = '\r';
                ADVANCE_TX_BUFFER_INDEX(g_ui32UARTTxWriteIndex);
            }
            else
            {
                //
                // Buffer is full - discard remaining characters and return.
                //
                break;
            }
        }

        //
        // Send the character to the UART output.
        //
        if(!TX_BUFFER_FULL)
        {
            g_pcUARTTxBuffer[g_ui32UARTTxWriteIndex] = pcBuf[uIdx];
            ADVANCE_TX_BUFFER_INDEX(g_ui32UARTTxWriteIndex);
        }
        else
        {
            //
            // Buffer is full - discard remaining characters and return.
            //
            break;
        }
    }

    //
    // If we have anything in the buffer, make sure that the UART is set
    // up to transmit it.
    //
    if(!TX_BUFFER_EMPTY)
    {
        UARTPrimeTransmit(g_ui32Base);
        MAP_UARTIntEnable(g_ui32Base, UART_INT_TX);
    }

    //
    // Return the number of characters written.
    //
    return(uIdx);
}


/*****************************************************************************
 * uart2_putc()  (from uart3_putc)
 ******************************************************************************/

int uart2_putc(const char c)
{

    // Send the character to the UART output.
    if(!TX_BUFFER_FULL)
    {
        g_pcUARTTxBuffer[g_ui32UARTTxWriteIndex] = c;
        ADVANCE_TX_BUFFER_INDEX(g_ui32UARTTxWriteIndex);
    }
    else return 0;  // Buffer full. No character written

    // Flush the TX buffer
    if(!TX_BUFFER_EMPTY)
    {
        UARTPrimeTransmit(g_ui32Base);
        MAP_UARTIntEnable(g_ui32Base, UART_INT_TX);
    }

    return 1; // Success
}


//*****************************************************************************
//
//! A simple UART based get string function, with some line processing.
//!
//! \param pcBuf points to a buffer for the incoming string from the UART.
//! \param ui32Len is the length of the buffer for storage of the string,
//! including the trailing 0.
//!
//! This function will receive a string from the UART input and store the
//! characters in the buffer pointed to by \e pcBuf.  The characters will
//! continue to be stored until a termination character is received.  The
//! termination characters are CR, LF, or ESC.  A CRLF pair is treated as a
//! single termination character.  The termination characters are not stored in
//! the string.  The string will be terminated with a 0 and the function will
//! return.
//!
//! In both buffered and unbuffered modes, this function will block until
//! a termination character is received.  If non-blocking operation is required
//! in buffered mode, a call to UARTPeek() may be made to determine whether
//! a termination character already exists in the receive buffer prior to
//! calling UARTgets().
//!
//! Since the string will be null terminated, the user must ensure that the
//! buffer is sized to allow for the additional null character.
//!
//! \return Returns the count of characters that were stored, not including
//! the trailing 0.
//
//*****************************************************************************
int
uart2_gets(char *pcBuf, uint32_t ui32Len)		// AUX1
{
    uint32_t ui32Count = 0;
    int8_t cChar;

    //
    // Adjust the length back by 1 to leave space for the trailing
    // null terminator.
    //
    ui32Len--;

    //
    // Process characters until a newline is received.
    //
    while(1)
    {
        //
        // Read the next character from the receive buffer.
        //
        if(!RX_BUFFER_EMPTY)
        {
            cChar = g_pcUARTRxBuffer[g_ui32UARTRxReadIndex];
            ADVANCE_RX_BUFFER_INDEX(g_ui32UARTRxReadIndex);

            //
            // See if a newline or escape character was received.
            //
            if((cChar == '\r') || (cChar == '\n') || (cChar == 0x1b))
            {
                //
                // Stop processing the input and end the line.
                //
                break;
            }

            //
            // Process the received character as long as we are not at the end
            // of the buffer.  If the end of the buffer has been reached then
            // all additional characters are ignored until a newline is
            // received.
            //
            if(ui32Count < ui32Len)
            {
                //
                // Store the character in the caller supplied buffer.
                //
                pcBuf[ui32Count] = cChar;

                //
                // Increment the count of characters received.
                //
                ui32Count++;
            }
        }
    }

    //
    // Add a null termination to the string.
    //
    pcBuf[ui32Count] = 0;

    //
    // Return the count of int8_ts in the buffer, not counting the trailing 0.
    //
    return(ui32Count);
}

//*****************************************************************************
//
//! Read a single character from the UART, blocking if necessary.
//!
//! This function will receive a single character from the UART and store it at
//! the supplied address.
//!
//! In both buffered and unbuffered modes, this function will block until a
//! character is received.  If non-blocking operation is required in buffered
//! mode, a call to UARTRxAvail() may be made to determine whether any
//! characters are currently available for reading.
//!
//! \return Returns the character read.
//
//*****************************************************************************
unsigned char
uart2_getc(void)		// AUX1
{
    unsigned char cChar;

    //
    // Wait for a character to be received.
    //
    while(RX_BUFFER_EMPTY)
    {
        //
        // Block waiting for a character to be received (if the buffer is
        // currently empty).
        //
    }

    //
    // Read a character from the buffer.
    //
    cChar = g_pcUARTRxBuffer[g_ui32UARTRxReadIndex];
    ADVANCE_RX_BUFFER_INDEX(g_ui32UARTRxReadIndex);

    //
    // Return the character to the caller.
    //
    return(cChar);
}

//*****************************************************************************
//
//! Returns the number of bytes available in the receive buffer.
//!
//! This function, available only when the module is built to operate in
//! buffered mode using \b UART_BUFFERED, may be used to determine the number
//! of bytes of data currently available in the receive buffer.
//!
//! \return Returns the number of available bytes.
//
//*****************************************************************************
#if defined(UART_BUFFERED) || defined(DOXYGEN)
int
uart2_rxBytesAvail(void)
{
    return(RX_BUFFER_USED);
}
#endif

//*****************************************************************************
//
//! Returns the number of bytes free in the transmit buffer.
//!
//! This function, available only when the module is built to operate in
//! buffered mode using \b UART_BUFFERED, may be used to determine the amount
//! of space currently available in the transmit buffer.
//!
//! \return Returns the number of free bytes.
//
//*****************************************************************************
int
uart2_txBytesFree(void)
{
    return(TX_BUFFER_FREE);
}

//*****************************************************************************
//
//! Looks ahead in the receive buffer for a particular character.
//!
//! \param ucChar is the character that is to be searched for.
//!
//! This function, available only when the module is built to operate in
//! buffered mode using \b UART_BUFFERED, may be used to look ahead in the
//! receive buffer for a particular character and report its position if found.
//! It is typically used to determine whether a complete line of user input is
//! available, in which case ucChar should be set to CR ('\\r') which is used
//! as the line end marker in the receive buffer.
//!
//! \return Returns -1 to indicate that the requested character does not exist
//! in the receive buffer.  Returns a non-negative number if the character was
//! found in which case the value represents the position of the first instance
//! of \e ucChar relative to the receive buffer read pointer.
//
//*****************************************************************************
int
uart2_peek(unsigned char ucChar)
{
    int iCount;
    int iAvail;
    uint32_t ui32ReadIndex;

    //
    // How many characters are there in the receive buffer?
    //
    iAvail = (int)RX_BUFFER_USED;
    ui32ReadIndex = g_ui32UARTRxReadIndex;

    //
    // Check all the unread characters looking for the one passed.
    //
    for(iCount = 0; iCount < iAvail; iCount++)
    {
        if(g_pcUARTRxBuffer[ui32ReadIndex] == ucChar)
        {
            //
            // We found it so return the index
            //
            return(iCount);
        }
        else
        {
            //
            // This one didn't match so move on to the next character.
            //
            ADVANCE_RX_BUFFER_INDEX(ui32ReadIndex);
        }
    }

    //
    // If we drop out of the loop, we didn't find the character in the receive
    // buffer.
    //
    return(-1);
}

//*****************************************************************************
//
//! Flushes the receive buffer.
//!
//! This function, available only when the module is built to operate in
//! buffered mode using \b UART_BUFFERED, may be used to discard any data
//! received from the UART but not yet read using UARTgets().
//!
//! \return None.
//
//*****************************************************************************
void
uart2_flushRx(void)
{
    uint32_t ui32Int;

    //
    // Temporarily turn off interrupts.
    //
    ui32Int = MAP_IntMasterDisable();

    //
    // Flush the receive buffer.
    //
    g_ui32UARTRxReadIndex = 0;
    g_ui32UARTRxWriteIndex = 0;

    //
    // If interrupts were enabled when we turned them off, turn them
    // back on again.
    //
    if(!ui32Int)
    {
        MAP_IntMasterEnable();
    }
}

//*****************************************************************************
//
//! Flushes the transmit buffer.
//!
//! \param bDiscard indicates whether any remaining data in the buffer should
//! be discarded (\b true) or transmitted (\b false).
//!
//! This function, available only when the module is built to operate in
//! buffered mode using \b UART_BUFFERED, may be used to flush the transmit
//! buffer, either discarding or transmitting any data received via calls to
//! uprintf() that is waiting to be transmitted.  On return, the transmit
//! buffer will be empty.
//!
//! \return None.
//
//*****************************************************************************
void
uart2_flushTx(bool bDiscard)
{
    uint32_t ui32Int;

    //
    // Should the remaining data be discarded or transmitted?
    //
    if(bDiscard)
    {
        //
        // The remaining data should be discarded, so temporarily turn off
        // interrupts.
        //
        ui32Int = MAP_IntMasterDisable();

        //
        // Flush the transmit buffer.
        //
        g_ui32UARTTxReadIndex = 0;
        g_ui32UARTTxWriteIndex = 0;

        //
        // If interrupts were enabled when we turned them off, turn them
        // back on again.
        //
        if(!ui32Int)
        {
            MAP_IntMasterEnable();
        }
    }
    else
    {
        //
        // Wait for all remaining data to be transmitted before returning.
        //
        while(!TX_BUFFER_EMPTY)
        {
        }
    }
}

//*****************************************************************************
//
//! Enables or disables echoing of received characters to the transmitter.
//!
//! \param bEnable must be set to \b true to enable echo or \b false to
//! disable it.
//!
//! This function, available only when the module is built to operate in
//! buffered mode using \b UART_BUFFERED, may be used to control whether or not
//! received characters are automatically echoed back to the transmitter.  By
//! default, echo is enabled and this is typically the desired behavior if
//! the module is being used to support a serial command line.  In applications
//! where this module is being used to provide a convenient, buffered serial
//! interface over which application-specific binary protocols are being run,
//! however, echo may be undesirable and this function can be used to disable
//! it.
//!
//! \return None.
//
//*****************************************************************************
void
uart2_echoSet(bool bEnable)
{
    g_bDisableEcho = !bEnable;
}

//*****************************************************************************
//
//! Handles UART interrupts.
//!
//! This function handles interrupts from the UART.  It will copy data from the
//! transmit buffer to the UART transmit FIFO if space is available, and it
//! will copy data from the UART receive FIFO to the receive buffer if data is
//! available.
//!
//! \return None.
//
//*****************************************************************************
void
uart2_IntHandler(void)          // was AUX1_UARTIntHandler(void)
{
    uint32_t ui32Ints;
    int8_t cChar;
    int32_t i32Char;
    static bool bLastWasCR = false;

    //
    // Get and clear the current interrupt source(s)
    //
    ui32Ints = MAP_UARTIntStatus(g_ui32Base, true);
    MAP_UARTIntClear(g_ui32Base, ui32Ints);

    //
    // Are we being interrupted because the TX FIFO has space available?
    //
    if(ui32Ints & UART_INT_TX)
    {
        //
        // Move as many bytes as we can into the transmit FIFO.
        //
        UARTPrimeTransmit(g_ui32Base);

        //
        // If the output buffer is empty, turn off the transmit interrupt.
        //
        if(TX_BUFFER_EMPTY)
        {
            MAP_UARTIntDisable(g_ui32Base, UART_INT_TX);
        }
    }

    //
    // Are we being interrupted due to a received character?
    //
    if(ui32Ints & (UART_INT_RX | UART_INT_RT))
    {
        //
        // Get all the available characters from the UART.
        //
        while(MAP_UARTCharsAvail(g_ui32Base))
        {
            //
            // Read a character
            //
            i32Char = MAP_UARTCharGetNonBlocking(g_ui32Base);
            cChar = (unsigned char)(i32Char & 0xFF);

            //
            // If echo is disabled, we skip the various text filtering
            // operations that would typically be required when supporting a
            // command line.
            //
            if(!g_bDisableEcho)
            {
                //
                // Handle backspace by erasing the last character in the
                // buffer.
                //
                if(cChar == '\b')
                {
                    //
                    // If there are any characters already in the buffer, then
                    // delete the last.
                    //
                    if(!RX_BUFFER_EMPTY)
                    {
                        //
                        // Rub out the previous character on the users
                        // terminal.
                        //
                        UARTwrite("\b \b", 3);

                        //
                        // Decrement the number of characters in the buffer.
                        //
                        if(g_ui32UARTRxWriteIndex == 0)
                        {
                            g_ui32UARTRxWriteIndex = AUX1_UART_RX_BUFFER_SIZE - 1;
                        }
                        else
                        {
                            g_ui32UARTRxWriteIndex--;
                        }
                    }

                    //
                    // Skip ahead to read the next character.
                    //
                    continue;
                }

                //
                // If this character is LF and last was CR, then just gobble up
                // the character since we already echoed the previous CR and we
                // don't want to store 2 characters in the buffer if we don't
                // need to.
                //
                if((cChar == '\n') && bLastWasCR)
                {
                    bLastWasCR = false;
                    continue;
                }

                //
                // See if a newline or escape character was received.
                //
                if((cChar == '\r') || (cChar == '\n') || (cChar == 0x1b))
                {
                    //
                    // If the character is a CR, then it may be followed by an
                    // LF which should be paired with the CR.  So remember that
                    // a CR was received.
                    //
                    if(cChar == '\r')
                    {
                        bLastWasCR = 1;
                    }

                    //
                    // Regardless of the line termination character received,
                    // put a CR in the receive buffer as a marker telling
                    // UARTgets() where the line ends.  We also send an
                    // additional LF to ensure that the local terminal echo
                    // receives both CR and LF.
                    //
                    cChar = '\r';
                    UARTwrite("\n", 1);
                }
            }

            //
            // If there is space in the receive buffer, put the character
            // there, otherwise throw it away.
            //
            if(!RX_BUFFER_FULL)
            {
                //
                // Store the new character in the receive buffer
                //
                g_pcUARTRxBuffer[g_ui32UARTRxWriteIndex] =
                    (unsigned char)(i32Char & 0xFF);
                ADVANCE_RX_BUFFER_INDEX(g_ui32UARTRxWriteIndex);

                //
                // If echo is enabled, write the character to the transmit
                // buffer so that the user gets some immediate feedback.
                //
                if(!g_bDisableEcho)
                {
                    UARTwrite((const char *)&cChar, 1);
                }
            }
        }

        //
        // If we wrote anything to the transmit buffer, make sure it actually
        // gets transmitted.
        //
        UARTPrimeTransmit(g_ui32Base);
        MAP_UARTIntEnable(g_ui32Base, UART_INT_TX);
    }
}

// easter egg
const char* arr[] =
{
    "As a rule, you will get out of it what you put into it.",
    "Life is not fair.  Don’t expect it to be.",
    "You have to be at the table to win.  Give yourself a fighting chance.  Get in the game.",
    "90% of what you worry about won’t happen.",
    "Much of what \"everybody knows\" is based on bad information.  Never be afraid to question what \"everybody knows\"",
    "Sometimes people with the best of intentions and high character will let you down.  Seek guidance, do your research, but always make your own decisions.",
    "Never, ever measure your worth by the size of your bank account.",
    "Most kids would benefit from a summer or two of hard physical labor.",
    "Despite what we were told as kids, not all of us can be \"anything we want to be\".  Some of us simply lack the necessary skill sets - And that’s Ok.",
    "Play to your strengths.",
    "Work on to your weaknesses.",
    "Life’s personal tragedies aren’t always disasters.  Sometimes they are the setup to something great that couldn’t come about any other way.",
    "Be open to friendship from anybody.  Some of my best friends started out as the most unlikely.",
    "Work with a net whenever possible, but NEVER be afraid to take a risk.",
    "Never take advice from a cynic.",
    "Make a coast to coast drive across the U.S. at least once.",
    "Learn the language.  Words have meaning.  A misused, expensive word can cause you to lose credibility.",
    "See a doctor for a full physical at least once a year.",
    "To the greatest extent possible, don’t act or speak out of anger.  Too much damage can be done, and some of it cannot be undone.",
    "Eliminate vices everywhere possible.  There is always some price to be paid for them.",
    "Stay curious about the world and never let the fear of appearing ignorant stop you from asking questions.  Nobody is born knowing anything.",
    "Cognitive dissonance renders the arguing of deeply held beliefs virtually pointless.",
    "It is much easier to stay in shape than it is to get in shape.",
    "The music of each generation, with certain exceptions, is largely ephemeral.  But Bach, Beethoven, Mozart, and Vivaldi live on.  There is a reason for that.",
    "Some people, for reasons they don’t even understand, are simply not going to like you.  Learn this as early in life as possible, accept it, and don’t lose a wink of sleep over it.  It’s not your problem.",
    "Sir Isaac Newton was right – Entropy increases.  Things must be tended to regularly.",
    "The soul needs time in nature to recenter itself.  Mountains, Oceans, Forests, and vast Prairie lands have seen billions of days, and they have a way of putting our contracts, meetings, projects, and reports, into perspective.",
    "Don’t be too quick to judge.  Life altering mistakes can be made from a hasty misperception.",
    "Learn to argue both sides of any issue as if you had to defend it in court.",
    "Always buy something from a kid selling anything.",
    "An ounce of prevention truly is worth a pound of cure.",
    "Political arguments are pointless.  Avoid them.",
    "Mental health should be treated no differently than physical health.  We don’t feel shame if we break an arm or spot a new, oddly shaped mole.  We tend to it.  If your brain is broken – tend to it, and don’t feel an ounce of shame about it.",
    "Homemade anything is better than store bought.",
    "Everybody has a story and most of them are quite interesting.  Take the time to listen.",
    "Procrastination is not your friend.",
    "Taking a good shot and missing is far better than the regret of not taking the shot at all.",
    "Don’t overthink it.",
    "Sometimes in working through a problem, you can be doing everything right but get to a solution.  In those cases, the missing variable is just \"time\".  Be Patient.",
    "Be sure that what you heard is what they actually meant.",
    "Data may not lie, but results can be manipulated and filtered.",
    "Be very careful about what you say to a kid and how you say it.  You never know what a kid is going to remember, and many times it will just be a passing, fleeting, comment.",
    "When people tell you to \"enjoy it while you can, because you’ll miss it when it’s gone\", listen carefully.  There is a reason they’re saying that.",
    "The feeling of finding or losing a love is the same at 50 as it was at 15.",
    "Save painting with a broad brush for barns.  It is otherwise not a good idea.",
    "Never compare yourself to others.  Compare yourself to your own potential.",
    "The one doing all the talking is the ringleader, and usually the more they say, the less able they are to back it up.",
    "Some set of circumstances brought everybody to where they are now.  Don’t judge too harshly.",
    "Don’t take a window seat and then ride the whole way with the shade pulled down.",
    "Take some self defense training or play a combative sport for a while, even if you never get good at it.",
    "Invest in people.  Most of the best memories of your life are not made alone.",
    "Whatever the dress code at a meeting – kick it up a notch.",
    "Coach a little league team at least once.",
    "Karma, or whatever you want to call it, is real.  What you put out will eventually come back around.",
    "Never put off calling an old friend.",
    "Never let anybody substitute caramel for butterscotch.  They are not the same thing.",
    "The situation usually isn’t as good or bad as it seems.",
    "Simple answers are for simple minds.  Dig deep.  Ask tough questions",
    "Yogi Berra was right – \"It ain’t over til it’s over.\"",
    "Measure twice, cut once.",
    "Choose your parents wisely."
    ,0
};

