// -----------------------------------------------------------------------
// Receive/Transmit buffers
// -----------------------------------------------------------------------
volatile    uint8_t    SIOLIB_rx_buffer    [SIO_BUFFER_SIZE];
volatile    uint8_t    SIOLIB_tx_buffer    [SIO_BUFFER_SIZE];
volatile    uint8_t    SIOLIB_rx_w_ptr;
volatile    uint8_t    SIOLIB_rx_r_ptr;
volatile    uint8_t    SIOLIB_tx_w_ptr;
volatile    uint8_t    SIOLIB_tx_r_ptr;

// -----------------------------------------------------------------------
// UART Rx complete interrupt
// -----------------------------------------------------------------------
SIGNAL( SIG_UART_RECV ) {
    uint8_t    rxbyte;

    rxbyte = UDR;
    // Is there room in the receive buffer ?
    if    ( ((SIOLIB_rx_w_ptr + 1) & (SIO_BUFFER_SIZE - 1)) != SIOLIB_rx_r_ptr ) {
        SIOLIB_rx_buffer[SIOLIB_rx_w_ptr] = rxbyte;
        SIOLIB_rx_w_ptr = (SIOLIB_rx_w_ptr + 1) & (SIO_BUFFER_SIZE - 1);
    }
}

// -----------------------------------------------------------------------
// UART Data Register Empty Interrupt

// This interrupt assumes that there is always some data present in TX buffer.

// If the byte to transmit next is the last one from the buffer - this

// interrupt will be disabled until enabled again by the write function.

// -----------------------------------------------------------------------
SIGNAL( SIG_UART_DATA ) {
    uint8_t    txbyte;

    // Get the byte to transmit
    txbyte = SIOLIB_tx_buffer[SIOLIB_tx_r_ptr];

    // Increment pointer
    SIOLIB_tx_r_ptr = (SIOLIB_tx_r_ptr + 1) & (SIO_BUFFER_SIZE - 1);

    UDR = txbyte;

    // Did we drain out the TX buffer ?
    // Disable this type of interrupt if we did.
    if    ( SIOLIB_tx_r_ptr == SIOLIB_tx_w_ptr ) {
        UCR &= (_BV(UDRIE) ^ 0xFF);
    }
}

// -----------------------------------------------------------------------
// public:    Initialize the serial interface
// -----------------------------------------------------------------------
extern    void        Rs232Init        ( uint8_t    aBaudRate,
                                      uint8_t    aMode ) {
    SIOLIB_rx_w_ptr = 0;
    SIOLIB_rx_r_ptr = 0;
    SIOLIB_tx_w_ptr = 0;
    SIOLIB_tx_r_ptr = 0;

    // Set the baudrate
    UBRR = aBaudRate;

    // Initially disable everything in the controller
    UCR = 0x00;
    
    // Set interface data mode
    SIOLIB_data_mode = aMode;
    switch    ( aMode ) {
        case    SER_MODE_7O1:
        case    SER_MODE_7E1:
        case    SER_MODE_7N2:
        case    SER_MODE_8N1:
            UCR = _BV(RXCIE) | _BV(RXEN) | _BV(TXEN);
            break;

        default:
            UCR = _BV(CHR9) | _BV(RXCIE) | _BV(RXEN) | _BV(TXEN);
            break;
    }

    // Read any carbage out of the controller
    while    ( UDR != 0 );
}

// -----------------------------------------------------------------------
// EOF: Rs232Init.c
// -----------------------------------------------------------------------
