/*
 *  ======== readIsrTextBlocking ========
 *  Function that is called by the ISR
 */
static bool readIsrTextBlocking(UART_Handle handle)
{
    int                       readIn;
    UARTMSP432_Object        *object = handle->object;
    UARTMSP432_HWAttrs const *hwAttrs = handle->hwAttrs;

    readIn = MAP_UART_receiveData(hwAttrs->baseAddr);

    if (readIn == '\r') {
        /* Echo character if enabled. */
        if (object->state.readEcho) {
            MAP_UART_transmitData(hwAttrs->baseAddr, '\r');
        }
        readIn = '\n';
    }

    if (RingBuf_put(&object->ringBuffer, (unsigned char) readIn) == -1) {
        DebugP_log1("UART:(%p) Ring buffer full!!", hwAttrs->baseAddr);
        return (false);
    }

    DebugP_log2("UART:(%p) buffered '0x%02x'", hwAttrs->baseAddr,
        (unsigned char) readIn);

    if (object->state.readEcho) {
        MAP_UART_transmitData(hwAttrs->baseAddr, (unsigned char) readIn);
    }
    if (object->state.callCallback) {
        object->state.callCallback = false;
        object->readCallback(handle, NULL, 0);
    }

    return (true);
}
/*
 *  ======== UARTMSP432_readPolling ========
 */
int UARTMSP432_readPolling(UART_Handle handle, void *buf, size_t size)
{
    int32_t                   count = 0;
    unsigned char            *buffer = (unsigned char *)buf;
    UARTMSP432_Object        *object = handle->object;
    UARTMSP432_HWAttrs const *hwAttrs = handle->hwAttrs;

    /* Read characters. */
    while (size) {
        /* Grab data from the RingBuf before getting it from the RX data reg */
        MAP_UART_disableInterrupt(hwAttrs->baseAddr,
            EUSCI_A_UART_RECEIVE_INTERRUPT);
        if (RingBuf_get(&object->ringBuffer, buffer) == -1) {
            /* RX interrupts are disabled; driverlib will poll for us */
            *buffer = MAP_UART_receiveData(hwAttrs->baseAddr);
        }
        if (object->state.rxEnabled) {
            MAP_UART_enableInterrupt(hwAttrs->baseAddr,
                EUSCI_A_UART_RECEIVE_INTERRUPT);
        }

        DebugP_log2("UART:(%p) Read character 0x%x", hwAttrs->baseAddr,
            *buffer);
        count++;
        size--;

        if (object->state.readDataMode == UART_DATA_TEXT && *buffer == '\r') {
            /* Echo character if enabled. */
            if (object->state.readEcho) {
                while (!MAP_UART_getInterruptStatus(hwAttrs->baseAddr,
                    EUSCI_A_UART_TRANSMIT_INTERRUPT_FLAG));
                MAP_UART_transmitData(hwAttrs->baseAddr,  '\r');
            }
            *buffer = '\n';
        }

        /* Echo character if enabled. */
        if (object->state.readDataMode == UART_DATA_TEXT &&
                object->state.readEcho) {
            while (!MAP_UART_getInterruptStatus(hwAttrs->baseAddr,
                EUSCI_A_UART_TRANSMIT_INTERRUPT_FLAG));
            MAP_UART_transmitData(hwAttrs->baseAddr,  *buffer);
        }

        /* If read return mode is newline, finish if a newline was received. */
        if (object->state.readDataMode == UART_DATA_TEXT &&
                object->state.readReturnMode == UART_RETURN_NEWLINE &&
                *buffer == '\n') {
            return (count);
        }

        buffer++;
    }

    DebugP_log2("UART:(%p) Read polling finished, %d bytes read",
        hwAttrs->baseAddr, count);

    return (count);
}
int main(void)
{
    /* Halting WDT  */
    MAP_WDT_A_holdTimer();

    /* Selecting P1.2 and P1.3 in UART mode and P1.0 as output (LED) */
    MAP_GPIO_setAsPeripheralModuleFunctionInputPin(GPIO_PORT_P1,
             GPIO_PIN2 | GPIO_PIN3, GPIO_PRIMARY_MODULE_FUNCTION);
    MAP_GPIO_setAsOutputPin(GPIO_PORT_P1, GPIO_PIN0);
    MAP_GPIO_setOutputLowOnPin(GPIO_PORT_P1, GPIO_PIN0);

    /* Setting DCO to 48MHz (upping Vcore) */
    MAP_PCM_setCoreVoltageLevel(PCM_VCORE1);
    CS_setDCOCenteredFrequency(CS_DCO_FREQUENCY_48);

    /* Configuring UART Module */
    MAP_UART_initModule(EUSCI_A0_MODULE, &uartConfig);

    /* Enable UART module */
    MAP_UART_enableModule(EUSCI_A0_MODULE);

    /* Enabling interrupts */
    MAP_UART_enableInterrupt(EUSCI_A0_MODULE, EUSCI_A_UART_RECEIVE_INTERRUPT);
    MAP_Interrupt_enableInterrupt(INT_EUSCIA0);
    MAP_Interrupt_enableSleepOnIsrExit();

    while(1)
    {
        MAP_UART_transmitData(EUSCI_A0_MODULE, TXData);

        MAP_Interrupt_enableSleepOnIsrExit();
        MAP_PCM_gotoLPM0InterruptSafe();
    }
}
/*
 *  ======== writeData ========
 */
static void writeData(UART_Handle handle)
{
    unsigned char            *writePtr;
    UARTMSP432_Object        *object = handle->object;
    UARTMSP432_HWAttrs const *hwAttrs = handle->hwAttrs;

    if (object->writeCount) {
        writePtr = (unsigned char*) object->writeBuf + object->writeSize -
            object->writeCount;

        /* If mode is TEXT process the characters */
        if (object->state.writeDataMode == UART_DATA_TEXT) {
            if (object->state.writeCR) {
                MAP_UART_transmitData(hwAttrs->baseAddr, '\r');
                object->writeCount--;
                object->state.writeCR = false;
                DebugP_log2("UART:(%p) Wrote 0x%x", hwAttrs->baseAddr, '\r');
            }
            else {
                /* Add a return if next character is a newline. */
                MAP_UART_transmitData(hwAttrs->baseAddr, *writePtr);
                if (*writePtr != '\n') {
                    object->writeCount--;
                }
                else {
                    object->state.writeCR = true;
                }
                DebugP_log2("UART:(%p) Wrote 0x%x", hwAttrs->baseAddr, *writePtr);
            }
        }
        else {
            MAP_UART_transmitData(hwAttrs->baseAddr, *writePtr);
            object->writeCount--;
            DebugP_log2("UART:(%p) Wrote 0x%x", hwAttrs->baseAddr, *writePtr);
        }

        if (!object->writeCount) {
            MAP_UART_disableInterrupt(hwAttrs->baseAddr,
                EUSCI_A_UART_TRANSMIT_INTERRUPT);
            Power_releaseConstraint(PowerMSP432_DISALLOW_DEEPSLEEP_0);
            Power_releaseConstraint(PowerMSP432_DISALLOW_PERF_CHANGES);
            object->writeCallback(handle, (void *) object->writeBuf,
                object->writeSize);
        }
    }
}
/*
 *  ======== readIsrTextCallback ========
 */
static bool readIsrTextCallback(UART_Handle handle)
{
    int                       readIn;
    bool                      ret = true;
    UARTMSP432_Object        *object = handle->object;
    UARTMSP432_HWAttrs const *hwAttrs = handle->hwAttrs;

    readIn = MAP_UART_receiveData(hwAttrs->baseAddr);

    if (readIn == '\r') {
        /* Echo character if enabled. */
        if (object->state.readEcho) {
            /* Wait until TX is ready */
            while (!MAP_UART_getInterruptStatus(hwAttrs->baseAddr,
                EUSCI_A_UART_TRANSMIT_INTERRUPT_FLAG)) {}
            MAP_UART_transmitData(hwAttrs->baseAddr, '\r');
        }
        readIn = '\n';
    }
    if (RingBuf_put(&object->ringBuffer, (unsigned char) readIn) == -1) {
        DebugP_log1("UART:(%p) Ring buffer full!!", hwAttrs->baseAddr);
        ret = false;
    }
    DebugP_log2("UART:(%p) buffered '0x%02x'", hwAttrs->baseAddr,
        (unsigned char) readIn);

    if (object->state.readEcho) {
        /* Wait until TX is ready */
        while (!MAP_UART_getInterruptStatus(hwAttrs->baseAddr,
            EUSCI_A_UART_TRANSMIT_INTERRUPT_FLAG)) {}
        MAP_UART_transmitData(hwAttrs->baseAddr, (unsigned char)readIn);
    }

    /*
     * Check and see if a UART_read in callback mode told use to continue
     * servicing the user buffer...
     */
    if (object->state.drainByISR) {
        readTaskCallback(handle);
    }

    return (ret);
}
/* EUSCI A0 UART ISR - Echoes data back to PC host */
void euscia0_isr(void)
{
    uint32_t status = MAP_UART_getEnabledInterruptStatus(EUSCI_A0_MODULE);

    MAP_UART_clearInterruptFlag(EUSCI_A0_MODULE, status);

    if(status & EUSCI_A_UART_RECEIVE_INTERRUPT)
    {
        MAP_UART_transmitData(EUSCI_A0_MODULE, MAP_UART_receiveData(EUSCI_A0_MODULE));
    }

}
/*
 *  ======== UARTMSP432_writePolling ========
 */
int UARTMSP432_writePolling(UART_Handle handle, const void *buf, size_t size)
{
    int32_t                   count = 0;
    unsigned char            *buffer = (unsigned char *)buf;
    UARTMSP432_Object        *object = handle->object;
    UARTMSP432_HWAttrs const *hwAttrs = handle->hwAttrs;

    /* Set power constraint to prevent a performance level change. */
    Power_setConstraint(PowerMSP432_DISALLOW_PERF_CHANGES);

    /* Write characters. */
    while (size) {
        if (object->state.writeDataMode == UART_DATA_TEXT && *buffer == '\n') {
            /* Wait until we can TX a byte */
            while (!MAP_UART_getInterruptStatus(hwAttrs->baseAddr,
                EUSCI_A_UART_TRANSMIT_INTERRUPT_FLAG));
            MAP_UART_transmitData(hwAttrs->baseAddr,  '\r');
            count++;
        }
        /* Wait until we can TX a byte */
        while (!MAP_UART_getInterruptStatus(hwAttrs->baseAddr,
            EUSCI_A_UART_TRANSMIT_INTERRUPT_FLAG));
        MAP_UART_transmitData(hwAttrs->baseAddr,  *buffer);

        DebugP_log2("UART:(%p) Wrote character 0x%x", hwAttrs->baseAddr,
            *buffer);
        buffer++;
        count++;
        size--;
    }

    Power_releaseConstraint(PowerMSP432_DISALLOW_PERF_CHANGES);

    DebugP_log2("UART:(%p) Write polling finished, %d bytes written",
        hwAttrs->baseAddr, count);

    return (count);
}