/***********************************************************************************************//**
  @file         hal_uart_ti.c
  @date         $Date: $
  @version      $Revision: $

  @brief        HAL UART routines for TI MSP430 Series

**************************************************************************************************/

/***************************************************************************************************
 *                                             INCLUDES
 ***************************************************************************************************/

#include <string.h>
#include <stdint.h>
#include "ComTypeDefs.h"
//#include BOARD_HEADER
#include "cavalier_board_cfg_rev2.h"
#include "msp430_mcu.h"
#include "hal_uart_ti.h"
#include "sys_tick.h"     // urg

/**************************************************************************************************
*                                           DEFINES
**************************************************************************************************/
   
#define HAL_UART0_DISABLE_RX()     st( UCA0CTL1 |= UCDORM; )
#define HAL_UART0_ENABLE_RX()      st( UCA0CTL1 &= ~UCDORM; )
#define HAL_UART1_DISABLE_RX()     st( UCA1CTL1 |= UCDORM; )
#define HAL_UART1_ENABLE_RX()      st( UCA1CTL1 &= ~UCDORM; )

/**************************************************************************************************
*                                           TYPEDEFS / ENUMS
**************************************************************************************************/

typedef struct 
{
    uint16_t head;
    uint16_t tail;
    uint16_t size;
    uint8_t *buf;
} queue_t;

/**************************************************************************************************
*                                           LOCAL VARIABLES
**************************************************************************************************/

// Should be static, but easier to debug if not
/*static*/ uint16_t serialOverruns;
/*static*/ uint16_t serialParityErrors;
/*static*/ uint16_t serialFramingErrors;
/*static*/ uint16_t serialCollisionsErrors;

//#define UART_FIFO_SIZE  64
//char_t uartRxFifo[UART_FIFO_SIZE];
//uint32_t receivedChars;

//static bool uartOpenFlag = false;

/*static*/ queue_t rx_q[ HAL_UART_PORT_MAX ];
/*static*/ queue_t tx_q[ HAL_UART_PORT_MAX ];
//static halUARTCBack_t halUartRxCallback = NULL;

/**************************************************************************************************
*                                       FUNCTIONS - LOCAL PROTOTYPES
**************************************************************************************************/

static inline uartStatus_t enqueue(queue_t *q, uint8_t data);
static inline uartStatus_t dequeue(queue_t *q, uint8_t *data);
static uartStatus_t kickTxQueue( uint8_t port );
static uartStatus_t halUartSetBaud( uint8_t port, uint32_t baud );
static inline void transmitNextByte( uint8_t port );
static inline void receiveNextByte( uint8_t port );
#if defined(HAL_UART_ENABLE_PORT_0) && defined(HAL_UART_HALF_DUPLEX_PORT_0)
static void turnOffTransmit0_fired( void );
#endif
#if defined(HAL_UART_ENABLE_PORT_1) && defined(HAL_UART_HALF_DUPLEX_PORT_1)
static void turnOffTransmit1_fired( void );
#endif
#if defined(HAL_UART_HALF_DUPLEX_PORT_0) || defined(HAL_UART_HALF_DUPLEX_PORT_1)
static void clearTxQueue( uint8_t port );
static uartStatus_t listenForPulse( volatile uint8_t *port, uint8_t port_mask );
#endif

/**************************************************************************************************
                                      FUNCTIONS - PUBLIC API
**************************************************************************************************/

#if 0   /**********************************************************************************************//**
 * @brief   Initialize UART - Must only be called Once!
 *
 * @param   none
 *
 * @return  none
 ***************************************************************************************************/
void HalUARTInit( void )
{
    uint8_t i;
    
    for( i=0; i<HAL_UART_PORT_MAX; i++ )
    {
        memset( &rx_q[i], 0x00, sizeof(rx_q) );
        memset( &tx_q[i], 0x00, sizeof(tx_q) );
    }      
}
#endif


/**********************************************************************************************//**
 * @brief   Setup and open UART port
 *
 * @param   port - UART port number
 * @param   config - Configuration of UART port
 * @param   rxBuffer - Receive data buffer
 * @param   txBuffer - Transmit data buffer
 *
 * @return  uartStatus_t - Status (SUCCESS, FULL, EMPTY, BAD BAUD, etc)
 ***************************************************************************************************/
uartStatus_t HalUARTOpen( uartPorts_t port, halUARTCfg_t *config, void *rxBuffer, void *txBuffer )
{
    queue_t *q;
    
    if ( !config || (!rxBuffer && (config->rx.maxBufSize != 0)) || (!txBuffer && (config->tx.maxBufSize != 0)) )
    {
        return HAL_UART_STATUS_ERROR;
    }
            
    switch ( port )
    {
        case HAL_UART_PORT_0:
            // Assumes ports already configured correctly
            UCA0CTL1 = UCSWRST;   // hold UART in reset
            UCA0CTL0 = UCMODE_0;   // async 8n1
            UCA0CTL1 |= UCSSEL_3;  // SMCLK
            //IE2 |= UCA0RXIE;   
            break;
        case HAL_UART_PORT_1:
            // Assumes ports already configured correctly
            UCA1CTL1 = UCSWRST;   // hold UART in reset
            UCA1CTL0 = UCMODE_0;   // async 8n1
            UCA1CTL1 |= UCSSEL_3;  // SMCLK
            break;
        default:    
            return HAL_UART_STATUS_BAD_PORT;
    }

    uartStatus_t status = halUartSetBaud( port, config->baudRate );
    if ( status != HAL_UART_STATUS_SUCCESS )
    {
        return status;
    }
    
    q = &rx_q[ port ];
    q->size = config->rx.maxBufSize;
    q->buf = rxBuffer;    
    q->head = q->tail = 0;
    
    q = &tx_q[ port ];
    q->size = config->tx.maxBufSize;
    q->buf = txBuffer;
    q->head = q->tail = 0;
    
    switch ( port )
    {
        case HAL_UART_PORT_0:
            UCA0CTL1 &= ~UCSWRST;   // release UART reset
            UCA0IE |= UCRXIE;        // enable RX interrupt
            UCA0IFG &= ~UCRXIFG;  // clear RX status
            break;
        case HAL_UART_PORT_1:
            UCA1CTL1 &= ~UCSWRST; // release UART reset
            UCA1IE |= UCRXIE;        // enable RX interrupt
            UCA1IFG &= ~UCRXIFG;  // clear RX status
            break;
    }
    
    //halUartRxCallback = config->callBackFunc;    
    //uartOpenFlag = true;
    //(void) uartOpenFlag;  // suppresses warning
    
    return HAL_UART_STATUS_SUCCESS;
}

/**********************************************************************************************//**
 * @brief   Read UART data buffer
 *
 * @param   port - UART port number
 * @param   dest - Destination data buffer
 * @param   length - Length of data to read
 *
 * @return  # of chars read
 ***************************************************************************************************/
uint16_t HalUARTRead( uartPorts_t port, uint8_t *dest, uint16_t length )
{
    uint16_t i;
    
    for( i=0; i<length; i++ )
    {
        uartStatus_t status = dequeue( &rx_q[ port ], &dest[ i ] );
        if ( status != HAL_UART_STATUS_SUCCESS )
        {
            break;
        }
    }
    return i;
}


/**********************************************************************************************//**
 * @brief   Check if RX queue is empty
 *
 * @param   port - UART port number
 *
 * @return  Is Rx buffer empy: TRUE or FALSE
 ***************************************************************************************************/
bool HalUARTRxEmpty( uartPorts_t port )
{
    bool isEmpty;
    halIntState_t intState;
    
    HAL_ENTER_CRITICAL_SECTION( intState );
    isEmpty = (rx_q[ port ].tail == rx_q[ port ].head);
    HAL_EXIT_CRITICAL_SECTION( intState );        
    
    return ( isEmpty );
}

/**********************************************************************************************//**
 * @brief   Flush Contents of RX queue
 *
 * @param   port - UART port number
 *
 * @return  none
 ***************************************************************************************************/
void HalUARTRxFlush( uartPorts_t port )
{
    halIntState_t intState;

    HAL_ENTER_CRITICAL_SECTION( intState );
    rx_q[ port ].tail = rx_q[ port ].head = 0;
    HAL_EXIT_CRITICAL_SECTION( intState );
}

/**********************************************************************************************//**
 * @brief   Check if TX queue is empty 
 *
 * @param   port - UART port number
 *
 * @return  Is Tx buffer empty: TRUE or FALSE
 ***************************************************************************************************/
bool HalUARTTxEmpty( uartPorts_t port )
{
    bool isEmpty;
    halIntState_t intState;
    
    HAL_ENTER_CRITICAL_SECTION( intState );
    isEmpty = (tx_q[ port ].tail == tx_q[ port ].head);
    HAL_EXIT_CRITICAL_SECTION( intState );
    return ( isEmpty );
}

/**********************************************************************************************//**
 * @brief   Check if Tx Bytes are available in the data buffer
 *
 * @param   port - UART port number
 *
 * @return  Length of data buffers available for Tx
 ***************************************************************************************************/
uint16_t HalUARTTxBytesAvailable( uartPorts_t port )
{
    int16_t len;
    halIntState_t intState;
    
    HAL_ENTER_CRITICAL_SECTION( intState );
    len = tx_q[ port ].head - tx_q[ port ].tail;
    
    if( len < 0 )  
    {
        len += tx_q[ port ].size;
    }
    len = tx_q[ port ].size - len - 1;
    HAL_EXIT_CRITICAL_SECTION( intState );        
    
    return (  len );
}


/**********************************************************************************************//**
 * @brief   Write the data out from the Tx queue
 *
 * @param   port - UART port number 
 * @param   src - source buffer 
 * @param   length - Length of source buffer to enqueue
 *
 * @return  Number of bytes queues for Tx
 ***************************************************************************************************/
uint16_t HalUARTWrite( uartPorts_t port, uint8_t *src, uint16_t length )
{
    uint16_t i;
    
    for( i=0; i<length; i++ )
    {
        uartStatus_t status = enqueue( &tx_q[ port ], src[ i ] );
        if ( status != HAL_UART_STATUS_SUCCESS )
        {
            break;
        }
        // Only kickstart TXing for full duplex operation
        switch( port )
        {
          case HAL_UART_PORT_0:
            kickTxQueue( port );
            break;
          case HAL_UART_PORT_1:
            kickTxQueue( port );
            break;
        }
    }
    return i;
}


/**********************************************************************************************//**
 * @brief   Start Transmitting TX buffer contents
 *          - Must have entire message queued in TX buffer prior to calling
 *          - Required for half duplex operation only
 *
 * @param   port - UART port number 
 *
 * @return  uartStatus_t - Status (SUCCESS, FULL, EMPTY, BAD BAUD, etc)
 ***************************************************************************************************/
uartStatus_t HalUARTTxStartTransmit( uartPorts_t port )
{
  uartStatus_t status = HAL_UART_STATUS_ERROR;
  (void) status;
  
  switch ( port )
  {      
    case HAL_UART_PORT_0:
      if( (status = listenForPulse( &HAL_UART0_PORT_IN, HAL_UART0_RXD_BV )) == HAL_UART_STATUS_SUCCESS )
      {
        HAL_UART0_DISABLE_RX();                                     // Disable Rx
        HAL_UART0_ENABLE_TX();                                      // Driver Enable    
        if( (status = kickTxQueue( port )) !=  HAL_UART_STATUS_SUCCESS )              // Let's party!
        {
          // TX already enabled error - shouldn't happen, but just in case...
          //HAL_UART0_DISABLE_TX();                                     // Driver Disable
          //HAL_UART0_ENABLE_RX();                                      // Enable Rx
          return( status );          
        }
      }
      else
      {
        // Bus contention.  Drop the packet
        clearTxQueue( port );
        serialCollisionsErrors++;
        return( status );
      }

    case HAL_UART_PORT_1:
      if( (status = listenForPulse( HAL_UART1_PORT_IN, HAL_UART1_RXD_BV )) == HAL_UART_STATUS_SUCCESS )
      {
        HAL_UART1_DISABLE_RX();                                     // Disable Rx
        HAL_UART1_ENABLE_TX();                                      // Driver Enable    
        if( (status = kickTxQueue( port )) !=  HAL_UART_STATUS_SUCCESS )              // Let's party!
        {
          // TX already enabled error - shouldn't happen, but just in case...
          //HAL_UART1_DISABLE_TX();                                     // Driver Disable
          //HAL_UART1_ENABLE_RX();                                      // Enable Rx
          return( status );          
        }
      }
      else
      {
        // Bus contention.  Just drop the packet for now... - TBD
        clearTxQueue( port );        
        serialCollisionsErrors++;
        return( status );
      }
    
    default:
      return(HAL_UART_STATUS_BAD_PORT);
  }  
}

/**********************************************************************************************//**
 * @brief   Poll the UART data Queue
 *
 * @param   none
 *
 * @return  none
 ***************************************************************************************************/
// provided for compatibility with hal_drivers.c
// you could just as easily call HalUARTRead() and look for return > 0
void HalUARTPoll( void )
{
    if ( halUartRxCallback )
    {
        if ( !HalUARTRxEmpty( HAL_UART_PORT_0 ) )
        {
            halUartRxCallback( HAL_UART_PORT_0, 0 );
        }
    }
}

/**********************************************************************************************//**
 * @brief   Force transmit a "0" byte
 *
 * @param   none
 *
 * @return  none
 ***************************************************************************************************/
void HalUARTTxForcedZero( uartPorts_t port )
{
  uint8_t timeout = 250;
  
  switch ( port )
  {      
    case HAL_UART_PORT_0:
      UCA0TXBUF = 0x00;                                           // Buffer should be ready for byte, no need to check
      while( ((UCBUSY & UCA0STAT) != 0) && (timeout > 0) )        // Wait until finished
      {
        timeout--;
      }
      break;
    case HAL_UART_PORT_1:
      UCA1TXBUF = 0x00;                                           // Buffer should be ready for byte, no need to check
      while( ((UCBUSY & UCA1STAT) != 0) && (timeout > 0) )        // Wait until finished
      {
        timeout--;
      }
      break;
  }
}


/**************************************************************************************************
*                                          LOCAL FUNCTIONS
**************************************************************************************************/

/**********************************************************************************************//**
 * @brief   Enqueue a data byte for transmission
 *
 * @param   q - destination queue
 * @param   data - Byte to add
 *
 * @return  uartStatus_t - Status (SUCCESS, FULL, EMPTY, BAD BAUD, etc)
 ***************************************************************************************************/
static inline uartStatus_t enqueue(queue_t *q, uint8_t data)
{
    halIntState_t intState;
    HAL_ENTER_CRITICAL_SECTION( intState );
    
    uint16_t nextHead = q->head + 1;
    if ( nextHead == q->size )
    {
        nextHead = 0;
    }
    
    if ( nextHead == q->tail )
    {
        HAL_EXIT_CRITICAL_SECTION( intState );
        return HAL_UART_STATUS_QUEUE_FULL;
    }
    
    q->head = nextHead;
    
    q->buf[ q->head ] = data;
    
    HAL_EXIT_CRITICAL_SECTION( intState );
    return HAL_UART_STATUS_SUCCESS;
}

/**********************************************************************************************//**
 * @brief   Dequeue the data buffer
 *
 * @param   q - source queue
 * @param   data - Byte read from the queue 
 *
 * @return  uartStatus_t - Status (SUCCESS, FULL, EMPTY, BAD BAUD, etc)
 ***************************************************************************************************/
static inline uartStatus_t dequeue(queue_t *q, uint8_t *data)
{
    halIntState_t intState;
    
    if( !q || !data )
    {
        return HAL_UART_STATUS_ERROR;    
    }
    
    HAL_ENTER_CRITICAL_SECTION( intState );
    
    if( q->tail == q->head )
    {
        HAL_EXIT_CRITICAL_SECTION( intState );
        return HAL_UART_STATUS_QUEUE_EMPTY;
    }
    
    q->tail++;
    if( q->tail == q->size )
    {
        q->tail = 0;
    }
    
    *data = q->buf[ q->tail ];
    
    HAL_EXIT_CRITICAL_SECTION( intState );
    return HAL_UART_STATUS_SUCCESS;
}


/**********************************************************************************************//**
 * @brief   Receive & store next byte from UART (called from ISR)
 *
 * @param   port - UART port
 *
 * @return  none
 ***************************************************************************************************/
static inline void receiveNextByte( uint8_t port )
{
    uint8_t ch;
    uint8_t rxStatus;
    
    uint8_t overrun = 0;
    
    switch ( port )
    {
        case HAL_UART_PORT_0:
            rxStatus = UCA0STAT;
                    
            if (rxStatus & UCRXERR)
            {
                if (rxStatus & UCFE)
                {
                    //NetworkTxStatistics.serialFramingErrors++;
                    serialFramingErrors++;
                }
                
                if (rxStatus & UCPE)
                {
                    //NetworkTxStatistics.serialParityErrors++;
                    serialParityErrors++;
                }
                
                if (rxStatus & UCOE)
                {
                    //NetworkTxStatistics.serialOverruns++;
                    serialOverruns++;
                    overrun = 1;
                }
            }
            
            ch = UCA0RXBUF;
            
            rxStatus = UCA0STAT;
            if (!overrun && (rxStatus & UCOE))
            {
                serialOverruns++;
                //NetworkTxStatistics.serialOverruns++;
            }
            
            break;
        case HAL_UART_PORT_1:
            rxStatus = UCA1STAT;
                    
            if (rxStatus & UCRXERR)
            {
                if (rxStatus & UCFE)
                {
                    //NetworkTxStatistics.serialFramingErrors++;
                    serialFramingErrors++;
                }
                
                if (rxStatus & UCPE)
                {
                    //NetworkTxStatistics.serialParityErrors++;
                    serialParityErrors++;
                }
                
                if (rxStatus & UCOE)
                {
                    //NetworkTxStatistics.serialOverruns++;
                    serialOverruns++;
                    overrun = 1;
                }
            }
            
            ch = UCA1RXBUF;
            
            rxStatus = UCA1STAT;
            if (!overrun && (rxStatus & UCOE))
            {
                serialOverruns++;
                //NetworkTxStatistics.serialOverruns++;
            }
            break;
    }
    
    enqueue( &rx_q[ port ], ch );
    //uartRxFifo[receivedChars & (UART_FIFO_SIZE - 1)] = ch;
    //receivedChars++;
}


/**********************************************************************************************//**
 * @brief   Transmit next byte from buffer to UART (called from ISR)
 *
 * @param   port - UART port
 *
 * @return  none
 ***************************************************************************************************/
static inline void transmitNextByte( uint8_t port )
{
    uint8_t ch;
    uartStatus_t status = dequeue( &tx_q[ port ], &ch );
    
    if ( status == HAL_UART_STATUS_SUCCESS )
    {
        switch ( port )
        {
            case HAL_UART_PORT_0:
                UCA0TXBUF = ch;
                UCA0IE |= UCTXIE; // uart tx enable
                break;
            case HAL_UART_PORT_1:
                UCA1TXBUF = ch;
                UCA1IE |= UCTXIE; // uart tx enable
                break;
        }
    }
    else
    {
        switch ( port )
        {
            case HAL_UART_PORT_0:
            	UCA0IFG &= ~UCTXIFG;     // clear tx status
            	UCA0IE &= ~UCTXIE;       // uart tx disable
                break;
            case HAL_UART_PORT_1:
            	UCA1IFG &= ~UCTXIFG;     // clear tx status
            	UCA1IE &= ~UCTXIE;       // uart tx disable
                break;
        }
    }
}

/**********************************************************************************************//**
 * @brief   Enable the Tx UART interrupt
 *
 * @param   port - UART port
 *
 * @return  none
 ***************************************************************************************************/
static uartStatus_t kickTxQueue( uint8_t port )
{
    // only kick if tx int is disabled
    switch ( port )
    {
        case HAL_UART_PORT_0:
            if ( UCA0IE & UCTXIE )
            {
                return(HAL_UART_STATUS_TX_ACTIVE);
            }
            break;
        case HAL_UART_PORT_1:
            if ( UCA1IE & UCTXIE )
            {
                return(HAL_UART_STATUS_TX_ACTIVE);
            }
            break;
    }
    
    transmitNextByte( port );
    return(HAL_UART_STATUS_SUCCESS);    
}

/**********************************************************************************************//**
 * @brief   Clear the Tx UART queue
 *
 * @param   port - UART port
 *
 * @return  none
 ***************************************************************************************************/
static void clearTxQueue( uint8_t port )
{
	halIntState_t intState;

	queue_t *q = &tx_q[ port ];

	HAL_ENTER_CRITICAL_SECTION( intState );
	q->head = q->tail = 0;
	HAL_EXIT_CRITICAL_SECTION( intState );
}

/**********************************************************************************************//**
 * @brief   Set the UART Baud Rate
 *
 * @param   port - UART port
 * @param   baud - Baud rate
 *
 * @return  uartStatus_t - Status (SUCCESS, FULL, EMPTY, BAD BAUD, etc)
 ***************************************************************************************************/
static uartStatus_t halUartSetBaud( uint8_t port, uint32_t baud )
{
#if    HAL_CPU_CLOCK_MHZ == 1    // actually 1048576
    static const uint32_t validBauds[] =   { 1200, 2400, 4800, 9600, 19200, 38400, 57600, 115200 };
    static const uint8_t UCBRSx_val[] =    { 7,    5,    2,    2,    5,     2,     1,     1 };
    static const uint16_t UCBRx_val[] =    { 873,  436,  218,  109,  54,    27,    18,    9 };
#elif  HAL_CPU_CLOCK_MHZ == 8    
  //*** NEED TO RECALCULATE/RECHECK
    static const uint32_t validBauds[] =   { 2400, 4800, 9600, 19200, 38400, 57600, 115200 };    
    static const uint8_t UCBRSx_val[] =    { 2,    5,    2,    5,     2,     7,     3  };    
    static const uint16_t UCBRx_val[] =    { 3333, 1666, 833,  416,   208,   138,   69 };    
#elif  HAL_CPU_CLOCK_MHZ == 12    
    static const uint32_t validBauds[] =   { 2400, 4800, 9600, 19200, 38400, 57600, 115200 };    
    static const uint8_t UCBRSx_val[] =    { 0,    0,    0,    0,     4,     2,     1   };    
    static const uint16_t UCBRx_val[] =    { 5000, 2500, 1250, 625,   312,   208,   104 };    
#elif  HAL_CPU_CLOCK_MHZ == 16    
    static const uint32_t validBauds[] =   { 2400, 4800, 9600, 19200, 38400, 57600, 115200 };    
    static const uint8_t UCBRSx_val[] =    { 5,    2,    5,    2,     5,     6,     7   };    
    static const uint16_t UCBRx_val[] =    { 6666, 3333, 1666, 833,   416,   277,   138 };    
#else
#error Non supported MCLK rate        
#endif    
    uint8_t i;
    
    for( i=0; i<sizeof(validBauds)/sizeof(validBauds[0]); i++ )
    {
        if ( validBauds[i] == baud )
        {
            switch ( port )
            {
#ifdef HAL_UART_ENABLE_PORT_0
                case HAL_UART_PORT_0:
                    UCA0BR0 = UCBRx_val[i] & 0xff;
                    UCA0BR1 = UCBRx_val[i] >> 8;
                    UCA0MCTL = UCBRSx_val[i] << 1;
                    return HAL_UART_STATUS_SUCCESS;
#endif
#ifdef HAL_UART_ENABLE_PORT_1
                case HAL_UART_PORT_1:
                    UCA1BR0 = UCBRx_val[i] & 0xff;
                    UCA1BR1 = UCBRx_val[i] >> 8;
                    UCA1MCTL = UCBRSx_val[i] << 1;
                    return HAL_UART_STATUS_SUCCESS;
#endif
            }
            return HAL_UART_STATUS_BAD_PORT;
        }
    }
    
    return HAL_UART_STATUS_BAD_BAUD;
}

#if defined(HAL_UART_HALF_DUPLEX_PORT_0) || defined(HAL_UART_HALF_DUPLEX_PORT_1)
/**********************************************************************************************//**
 * @brief   Check for any active bus activity for 500usecs
 *
 * @param   port_mask - UART RX port mask
 *
 * @return  uartStatus_t - Status (SUCCESS, BUS_CONTENTION)
 ***************************************************************************************************/
static uartStatus_t listenForPulse( volatile uint8_t *port, uint8_t port_mask )
{
#if HAL_CPU_CLOCK_MHZ == 8  
  uint16_t timeout = 350;       // = ~500usec
#elif HAL_CPU_CLOCK_MHZ == 1
  uint16_t timeout = 44;       // = ~500usec  *** SWAG - CHECK ME
#else
#error Non supported MCLK rate 
#endif

// ***ALERT - time dependent code
  //HAL_UART0_ENABLE_TX();    //***DEBUG bad!  only for timing measurement
  while( timeout > 0 )                                        // Check if RXD goes high at any time during next .5 mSec
  {
    timeout--;
    if( (*port & port_mask) == 0 )
    {
      return( HAL_UART_STATUS_BUS_CONTENTION );
    }
  }
  //HAL_UART0_DISABLE_TX();   //***DEBUG bad!  only for timing measurement
  return( HAL_UART_STATUS_SUCCESS );
}
#endif

#if defined(HAL_UART_ENABLE_PORT_0) && defined(HAL_UART_HALF_DUPLEX_PORT_0)
/**********************************************************************************************//**
 * @brief   One shot timer callback function to turn off TX'r for Half Duplex operation
 *
 * @param   none 
 *
 * @return  none
 ***************************************************************************************************/
static void turnOffTransmit0_fired( void )
{
  HAL_UART0_DISABLE_TX();                                     // Driver Disable
  HAL_UART0_ENABLE_RX();                                      // Enable Rx  
}
#endif

#if defined(HAL_UART_ENABLE_PORT_1) && defined(HAL_UART_HALF_DUPLEX_PORT_1)
/**********************************************************************************************//**
 * @brief   One shot timer callback function to turn off TX'r for Half Duplex operation
 *
 * @param   none 
 *
 * @return  none
 ***************************************************************************************************/
static void turnOffTransmit1_fired( void )
{
  HAL_UART1_DISABLE_TX();                                     // Driver Disable
  HAL_UART1_ENABLE_RX();                                      // Enable Rx  
}
#endif


/**************************************************************************************************
*                                     * * * ISR's * * *
**************************************************************************************************/

#ifdef HAL_UART_ENABLE_PORT_0
/**********************************************************************************************//**
 * @brief   USCI A0 UART TX/RX ISR
 *
 * @param   
 *
 * @return  it's an ISR for gods sake!
 ***************************************************************************************************/
#pragma vector=USCI_A0_VECTOR
__interrupt void halUsciA0Isr (void)
{

	switch(__even_in_range(UCA0IV,4))
	{
  		case 0:
  		    break;        // Vector 0 - no interrupt

  		case 2:  // Vector 2 - RXIFG
  			receiveNextByte( HAL_UART_PORT_0 );
    		break;

  		case 4:  // Vector 4 - TXIFG
  	        transmitNextByte( HAL_UART_PORT_0 );
  			break;

  		default:
  			break;
  	}

}
#endif  // HAL_UART_ENABLE_PORT_0

#ifdef HAL_UART_ENABLE_PORT_1
/**********************************************************************************************//**
 * @brief   USCI A1 UART TX/RX ISR
 *
 * @param
 *
 * @return  it's an ISR for gods sake!
 ***************************************************************************************************/
#pragma vector=USCI_A1_VECTOR
__interrupt void halUsciA1Isr (void)
{
    //__disable_interrupt();

	switch(__even_in_range(UCA1IV,4))
	{
  		case 0:
  		    break;        // Vector 0 - no interrupt

  		case 2:  // Vector 2 - RXIFG
  			receiveNextByte( HAL_UART_PORT_1 );
    		break;

  		case 4:  // Vector 4 - TXIFG
  	        transmitNextByte( HAL_UART_PORT_1 );
  			break;

  		default:
  			break;
  	}
	//__enable_interrupt();

}
#endif  // HAL_UART_ENABLE_PORT_1

