Home : I/O Peripherals Library | Serial / UART Peripheral

Description

<TODO>

Naming Conventions

<TODO>

Interface Functions

<TODO>

Example Usage

<TODO>

Configuration

<TODO>

Source Files

xperipherals_uart.h UART peripheral interface
xperipherals_uart_1.xc UART peripheral #1 implementation
xperipherals_uart_2.xc UART peripheral #2 implementation
xperipherals_uart_3.xc UART peripheral #3 implementation

Source Listings

xperipherals_uart.h

#ifndef XPERIPHERALS_UART__INCLUDED
#define XPERIPHERALS_UART__INCLUDED

#include "xsystem_types.h"

// These must be defined in "xconfig.h" for each peripheral bus being used
//
// USES_XPERIPHERALS_UART_n                No value
//
// XPERIPHERALS_UART_n__PARITY_MODE        Integer (0=none, 1=odd, 2=even, 3=mark/space)
// XPERIPHERALS_UART_n__STOP_BITS          Integer (1 or 2)
// XPERIPHERALS_UART_n__SUPPORT_TX         TRUE or FALSE
// XPERIPHERALS_UART_n__SUPPORT_RX         TRUE or FALSE
// XPERIPHERALS_UART_n__SUPPORT_TIMEOUTS   TRUE or FALSE
// XPERIPHERALS_UART_n__TXD_BIT_POS        Non-negative integer
// XPERIPHERALS_UART_n__RXD_BIT_POS        Non-negative integer
// XPERIPHERALS_UART_n__TILE_NUMBER        Integer, XS1 tile number
// XPERIPHERALS_UART_n__TXD_PORT           XS1 port identifier
// XPERIPHERALS_UART_n__RXD_PORT           XS1 port identifier

// Synchronous Data Write (Blocking Function Call):
//   xperipherals_uart__write_byte( byte value );
//
// Synchronous Data Read (Blocking Function Call - Can timeout):
//   error = xperipherals_uart__read_byte( byte value );
//
// Asynchronous Data I/O (Non-Blocking Function Calls):
//   xperipherals_uart__write_start( output byte value );
//   xperipherals_uart__read_start();
//   while( TRUE ) {
//       int read_done = write_done = 0;
//       select {
//           case xperipherals_uart__write_done( write_done );
//           case xperipherals_uart__read_done( read_done );
//       }
//       if( write_done ) ... // data output has finished
//       if( input byte reference ) ... // data input has finished
//   }

#define XPERIPHERALS_UART__INTERFACE( N ) \
\
void   xperipherals_uart_##N##__initialize ( void ); \
void   xperipherals_uart_##N##__configure  ( xuint baud_rate, xuint timeout_usec ); \
\
/* Blocking I/O Functions (for non-event driven I/O) */ \
\
void   xperipherals_uart_##N##__write_byte ( xbyte data ); \
void   xperipherals_uart_##N##__read_byte  ( xbyte& data ); \
\
/* Non-Blocking I/O Functions (for event driven I/O) */ \
\
void   xperipherals_uart_##N##__begin_write( xbyte data ); \
select xperipherals_uart_##N##__continue_wr( int& done );              /* Use 'xperipherals_uart_3__write_done' from 'xperipheral.i' */ \
void   xperipherals_uart_##N##__begin_read ( void ); \
select xperipherals_uart_##N##__continue_rd( int& done, xbyte& data ); /* Use 'xperipherals_uart_3__read_done' from 'xperipheral.i' */

XPERIPHERALS_UART__INTERFACE( 1 )
XPERIPHERALS_UART__INTERFACE( 2 )
XPERIPHERALS_UART__INTERFACE( 3 )

#endif

xperipherals_uart_1.xc

#include <xs1.h>
#include <platform.h>
#include <print.h>

#include "xperipherals_uart.h"

#ifdef XPERIPHERALS_UART_1

#if XPERIPHERALS_UART_1__SUPPORT_TX
        //on tile[XPERIPHERALS_UART_1__TILE_NUMBER] :
    out port _xperipherals_uart_1__port_txd = XPERIPHERALS_UART_1__TXD_PORT;
        //#if $setting.handshake-mode == 1 // CTS/RTS
        //      on tile[$resource.tile-number] : out port _xperipherals_uart_1__port_rts = $resource.rts-port;
        //#endif
#endif

#if XPERIPHERALS_UART_1__SUPPORT_RX
        //on tile[XPERIPHERALS_UART_1__TILE_NUMBER] :
    in port _xperipherals_uart_1__port_rxd = XPERIPHERALS_UART_1__RXD_PORT;
        //#if $setting.handshake-mode == 1 // CTS/RTS
        //      on tile[$resource.tile-number] : out port _xperipherals_uart_1__port_cts = $resource.cts-port;
        //#endif
#endif

int   _xperipherals_uart_1__period = 0;
int   _xperipherals_uart_1__wbusy;
int   _xperipherals_uart_1__rbusy;
xbyte _xperipherals_uart_1__wdata;
xbyte _xperipherals_uart_1__rdata;
timer _xperipherals_uart_1__timer;
xuint _xperipherals_uart_1__time;
xuint _xperipherals_uart_1__count;

#define REFERENCE_CLOCK_FREQUENCY 100000000

// Initialize internal data and state information, configure clocks and ports

void xperipherals_uart_1__initialize( void )
{
    timer _xperipherals_uart_1__timer;
        #if XPERIPHERALS_UART_1__SUPPORT_TX
    int time;
    _xperipherals_uart_1__port_txd <: 1;
        //#if $setting.handshake-mode == 1
        //_xperipherals_uart_1__port_rts <: 1;
        //#endif
    _xperipherals_uart_1__timer :> time;
    time += 10 * _xperipherals_uart_1__period;
    _xperipherals_uart_1__timer when timerafter(time) :> void;
        #endif

        #if XPERIPHERALS_UART_1__SUPPORT_RX
        //#if $setting.handshake-mode == 1
        //_xperipherals_uart_1__port_cts <: 1;
        //#endif
        #endif

        _xperipherals_uart_1__wbusy = _xperipherals_uart_1__rbusy = FALSE;
}

// Configure clocks for a new MCLK frequency or sample rate

void xperipherals_uart_1__configure( xuint baud_rate, xuint timeout_usec )
{
    //_xperipherals_uart_1__bit_period_1 = (1 * REFERENCE_CLOCK_FREQUENCY) / (2 * baud_rate);
    _xperipherals_uart_1__period = (2 * REFERENCE_CLOCK_FREQUENCY) / (2 * baud_rate);
}

#if XPERIPHERALS_UART_1__SUPPORT_TX

void xperipherals_uart_1__write_byte( xbyte data )
{
        // Serial: START ................ 1 Byte of Data ............... STOP
        // Output: LLLLL 11111 22222 33333 44444 55555 66666 77777 88888 HHHHH
        // Timing: A     B     C     D     E     F     G     H     I     J

    timer _xperipherals_uart_1__timer;
    int time; _xperipherals_uart_1__timer :> time;

        _xperipherals_uart_1__port_txd <: 0;
    time += _xperipherals_uart_1__period;
    _xperipherals_uart_1__timer when timerafter(time) :> void; // A

    #pragma loop unroll
    for( int i = 0; i < 8; ++i ) // B,C,D,E,F,G,H,I
    {
        _xperipherals_uart_1__port_txd <: ((unsigned int)data & 1); data >>= 1;
        time += _xperipherals_uart_1__period;
        _xperipherals_uart_1__timer when timerafter(time) :> void;
    }

    _xperipherals_uart_1__port_txd <: 1;
    time += _xperipherals_uart_1__period;
    _xperipherals_uart_1__timer when timerafter(time) :> void; // J
}

void xperipherals_uart_1__begin_write( xbyte data )
{
    _xperipherals_uart_1__wdata = data;
    _xperipherals_uart_1__count = 0;
    _xperipherals_uart_1__timer :> _xperipherals_uart_1__time;
    _xperipherals_uart_1__port_txd <: 0;
    _xperipherals_uart_1__time += _xperipherals_uart_1__period;
    _xperipherals_uart_1__wbusy = TRUE;
}

select xperipherals_uart_1__continue_wr( int& done )
{
    case _xperipherals_uart_1__wbusy => _xperipherals_uart_1__timer when timerafter(_xperipherals_uart_1__time) :> void:

        if( _xperipherals_uart_1__count == 0 )
        {
            _xperipherals_uart_1__port_txd <: ((unsigned int)_xperipherals_uart_1__wdata & 1);
            _xperipherals_uart_1__wdata >>= 1;
            _xperipherals_uart_1__time += _xperipherals_uart_1__period;
            ++_xperipherals_uart_1__count;
            done = FALSE;
        }
        else if( _xperipherals_uart_1__count <= 8 )
        {
            _xperipherals_uart_1__port_txd <: ((unsigned int)_xperipherals_uart_1__wdata & 1);
            _xperipherals_uart_1__wdata >>= 1;
            _xperipherals_uart_1__time += _xperipherals_uart_1__period;
            ++_xperipherals_uart_1__count;
            done = FALSE;
        }
        else if( _xperipherals_uart_1__count <= 20 )
        {
            _xperipherals_uart_1__port_txd <: 1;
            _xperipherals_uart_1__time += _xperipherals_uart_1__period;
            ++_xperipherals_uart_1__count;
            done = _xperipherals_uart_1__count == 20;
            _xperipherals_uart_1__wbusy = !done;
        }
        break;
}

#endif

#if XPERIPHERALS_UART_1__SUPPORT_RX

void xperipherals_uart_1__read_byte( xbyte& data )
{
    timer _xperipherals_uart_1__timer;
    xbyte bit; int time;

    // Wait for START bit (Step A)
    _xperipherals_uart_1__port_rxd when pinseq(0) :> void;
    _xperipherals_uart_1__timer :> time;
    time += _xperipherals_uart_1__period / 2;

    // Sample 8 bits (Steps B,C,D,E,F,G,H,I)
    #pragma loop unroll
    for( int i = 0; i < 8; ++i )
    {
        time += _xperipherals_uart_1__period;
        _xperipherals_uart_1__timer when timerafter(time) :> void;
        _xperipherals_uart_1__port_rxd :> bit; data = (data>>1) + (bit<<7);
    }

    // Wait for STOP bit to pass ...
    time += _xperipherals_uart_1__period;
    _xperipherals_uart_1__timer when timerafter(time) :> void;
}

void xperipherals_uart_1__begin_read( void )
{
    _xperipherals_uart_1__count = 0;
    _xperipherals_uart_1__timer :> _xperipherals_uart_1__time;
    _xperipherals_uart_1__time += _xperipherals_uart_1__period;
    _xperipherals_uart_1__rbusy = TRUE;
}

select xperipherals_uart_1__continue_rd( int& done, unsigned char& data )
{
    case _xperipherals_uart_1__rbusy => _xperipherals_uart_1__timer when timerafter(_xperipherals_uart_1__time) :> void:

        if( _xperipherals_uart_1__count == 0 )
        {
            _xperipherals_uart_1__time += _xperipherals_uart_1__period;
            ++_xperipherals_uart_1__count;
            done = FALSE;
        }
        else if( _xperipherals_uart_1__count <= 8 )
        {
            _xperipherals_uart_1__time += _xperipherals_uart_1__period;
            ++_xperipherals_uart_1__count;
            done = FALSE;
        }
        else if( _xperipherals_uart_1__count <= 20 )
        {
            _xperipherals_uart_1__time += _xperipherals_uart_1__period;
            ++_xperipherals_uart_1__count;
            done = _xperipherals_uart_1__count == 20;
            _xperipherals_uart_1__rbusy = FALSE;
       }
        break;
}

#endif

#endif

xperipherals_uart_2.xc

#include <xs1.h>
#include <platform.h>
#include <print.h>

#include "xperipherals_uart.h"

#ifdef XPERIPHERALS_UART_2

#if XPERIPHERALS_UART_2__SUPPORT_TX
        on tile[XPERIPHERALS_UART_2__TILE_NUMBER] : out port _xperipherals_uart_2__port_txd = XPERIPHERALS_UART_2__TXD_PORT;
        //#if $setting.handshake-mode == 1 // CTS/RTS
        //      on tile[$resource.tile-number] : out port _xperipherals_uart_2__port_rts = $resource.rts-port;
        //#endif
#endif

#if XPERIPHERALS_UART_2__SUPPORT_RX
        on tile[XPERIPHERALS_UART_2__TILE_NUMBER] : in port _xperipherals_uart_2__port_rxd = XPERIPHERALS_UART_2__RXD_PORT;
        //#if $setting.handshake-mode == 1 // CTS/RTS
        //      on tile[$resource.tile-number] : out port _xperipherals_uart_2__port_cts = $resource.cts-port;
        //#endif
#endif

int   _xperipherals_uart_2__period = 0;
int   _xperipherals_uart_2__wbusy;
int   _xperipherals_uart_2__rbusy;
xbyte _xperipherals_uart_2__wdata;
xbyte _xperipherals_uart_2__rdata;
timer _xperipherals_uart_2__timer;
xuint _xperipherals_uart_2__time;
xuint _xperipherals_uart_2__count;

#define REFERENCE_CLOCK_FREQUENCY 100000000

// Initialize internal data and state information, configure clocks and ports

void xperipherals_uart_2__initialize( void )
{
    timer _xperipherals_uart_2__timer;
        #if XPERIPHERALS_UART_2__SUPPORT_TX
    int time;
    _xperipherals_uart_2__port_txd <: 1;
        //#if $setting.handshake-mode == 1
        //_xperipherals_uart_2__port_rts <: 1;
        //#endif
    _xperipherals_uart_2__timer :> time;
    time += 10 * _xperipherals_uart_2__period;
    _xperipherals_uart_2__timer when timerafter(time) :> void;
        #endif

        #if XPERIPHERALS_UART_2__SUPPORT_RX
        //#if $setting.handshake-mode == 1
        //_xperipherals_uart_2__port_cts <: 1;
        //#endif
        #endif

        _xperipherals_uart_2__wbusy = _xperipherals_uart_2__rbusy = FALSE;
}

// Configure clocks for a new MCLK frequency or sample rate

void xperipherals_uart_2__configure( xuint baud_rate, xuint timeout_usec )
{
    //_xperipherals_uart_2__bit_period_1 = (1 * REFERENCE_CLOCK_FREQUENCY) / (2 * baud_rate);
    _xperipherals_uart_2__period = (2 * REFERENCE_CLOCK_FREQUENCY) / (2 * baud_rate);
}

#if XPERIPHERALS_UART_2__SUPPORT_TX

void xperipherals_uart_2__write_byte( xbyte data )
{
        // Serial: START ................ 1 Byte of Data ............... STOP
        // Output: LLLLL 11111 22222 33333 44444 55555 66666 77777 88888 HHHHH
        // Timing: A     B     C     D     E     F     G     H     I     J

    timer _xperipherals_uart_2__timer;
    int time; _xperipherals_uart_2__timer :> time;

        _xperipherals_uart_2__port_txd <: 0;
    time += _xperipherals_uart_2__period;
    _xperipherals_uart_2__timer when timerafter(time) :> void; // A

    #pragma loop unroll
    for( int i = 0; i < 8; ++i ) // B,C,D,E,F,G,H,I
    {
        _xperipherals_uart_2__port_txd <: ((unsigned int)data & 1); data >>= 1;
        time += _xperipherals_uart_2__period;
        _xperipherals_uart_2__timer when timerafter(time) :> void;
    }

    _xperipherals_uart_2__port_txd <: 1;
    time += _xperipherals_uart_2__period;
    _xperipherals_uart_2__timer when timerafter(time) :> void; // J
}

void xperipherals_uart_2__begin_write( xbyte data )
{
    _xperipherals_uart_2__wdata = data;
    _xperipherals_uart_2__count = 0;
    _xperipherals_uart_2__timer :> _xperipherals_uart_2__time;
    _xperipherals_uart_2__port_txd <: 0;
    _xperipherals_uart_2__time += _xperipherals_uart_2__period;
    _xperipherals_uart_2__wbusy = TRUE;
}

select xperipherals_uart_2__continue_wr( int& done )
{
    case _xperipherals_uart_2__wbusy => _xperipherals_uart_2__timer when timerafter(_xperipherals_uart_2__time) :> void:

        if( _xperipherals_uart_2__count == 0 )
        {
            _xperipherals_uart_2__port_txd <: ((unsigned int)_xperipherals_uart_2__wdata & 1);
            _xperipherals_uart_2__wdata >>= 1;
            _xperipherals_uart_2__time += _xperipherals_uart_2__period;
            ++_xperipherals_uart_2__count;
            done = FALSE;
        }
        else if( _xperipherals_uart_2__count <= 8 )
        {
            _xperipherals_uart_2__port_txd <: ((unsigned int)_xperipherals_uart_2__wdata & 1);
            _xperipherals_uart_2__wdata >>= 1;
            _xperipherals_uart_2__time += _xperipherals_uart_2__period;
            ++_xperipherals_uart_2__count;
            done = FALSE;
        }
        else if( _xperipherals_uart_2__count <= 20 )
        {
            _xperipherals_uart_2__port_txd <: 1;
            _xperipherals_uart_2__time += _xperipherals_uart_2__period;
            ++_xperipherals_uart_2__count;
            done = _xperipherals_uart_2__count == 20;
            _xperipherals_uart_2__wbusy = !done;
        }
        break;
}

#endif

#if XPERIPHERALS_UART_2__SUPPORT_RX

void xperipherals_uart_2__read_byte( xbyte& data )
{
    timer _xperipherals_uart_2__timer;
    xbyte bit; int time;

    // Wait for START bit (Step A)
    _xperipherals_uart_2__port_rxd when pinseq(0) :> void;
    _xperipherals_uart_2__timer :> time;
    time += _xperipherals_uart_2__period / 2;

    // Sample 8 bits (Steps B,C,D,E,F,G,H,I)
    #pragma loop unroll
    for( int i = 0; i < 8; ++i )
    {
        time += _xperipherals_uart_2__period;
        _xperipherals_uart_2__timer when timerafter(time) :> void;
        _xperipherals_uart_2__port_rxd :> bit; data = (data>>1) + (bit<<7);
    }

    // Wait for STOP bit to pass ...
    time += _xperipherals_uart_2__period;
    _xperipherals_uart_2__timer when timerafter(time) :> void;
}

void xperipherals_uart_2__begin_read( void )
{
    _xperipherals_uart_2__count = 0;
    _xperipherals_uart_2__timer :> _xperipherals_uart_2__time;
    _xperipherals_uart_2__time += _xperipherals_uart_2__period;
    _xperipherals_uart_2__rbusy = TRUE;
}

select xperipherals_uart_2__continue_rd( int& done, unsigned char& data )
{
    case _xperipherals_uart_2__rbusy => _xperipherals_uart_2__timer when timerafter(_xperipherals_uart_2__time) :> void:

        if( _xperipherals_uart_2__count == 0 )
        {
            _xperipherals_uart_2__time += _xperipherals_uart_2__period;
            ++_xperipherals_uart_2__count;
            done = FALSE;
        }
        else if( _xperipherals_uart_2__count <= 8 )
        {
            _xperipherals_uart_2__time += _xperipherals_uart_2__period;
            ++_xperipherals_uart_2__count;
            done = FALSE;
        }
        else if( _xperipherals_uart_2__count <= 20 )
        {
            _xperipherals_uart_2__time += _xperipherals_uart_2__period;
            ++_xperipherals_uart_2__count;
            done = _xperipherals_uart_2__count == 20;
            _xperipherals_uart_2__rbusy = FALSE;
       }
        break;
}

#endif

#endif

xperipherals_uart_3.xc

#include <xs1.h>
#include <platform.h>
#include <print.h>

#include "xperipherals_uart.h"

#ifdef XPERIPHERALS_UART_3

#if XPERIPHERALS_UART_3__SUPPORT_TX
        on tile[XPERIPHERALS_UART_3__TILE_NUMBER] : out port _xperipherals_uart_3__port_txd = XPERIPHERALS_UART_3__TXD_PORT;
        //#if $setting.handshake-mode == 1 // CTS/RTS
        //      on tile[$resource.tile-number] : out port _xperipherals_uart_3__port_rts = $resource.rts-port;
        //#endif
#endif

#if XPERIPHERALS_UART_3__SUPPORT_RX
        on tile[XPERIPHERALS_UART_3__TILE_NUMBER] : in port _xperipherals_uart_3__port_rxd = XPERIPHERALS_UART_3__RXD_PORT;
        //#if $setting.handshake-mode == 1 // CTS/RTS
        //      on tile[$resource.tile-number] : out port _xperipherals_uart_3__port_cts = $resource.cts-port;
        //#endif
#endif

int   _xperipherals_uart_3__period = 0;
int   _xperipherals_uart_3__wbusy;
int   _xperipherals_uart_3__rbusy;
xbyte _xperipherals_uart_3__wdata;
xbyte _xperipherals_uart_3__rdata;
timer _xperipherals_uart_3__timer;
xuint _xperipherals_uart_3__time;
xuint _xperipherals_uart_3__count;

#define REFERENCE_CLOCK_FREQUENCY 100000000

// Initialize internal data and state information, configure clocks and ports

void xperipherals_uart_3__initialize( void )
{
    timer _xperipherals_uart_3__timer;
        #if XPERIPHERALS_UART_3__SUPPORT_TX
    int time;
    _xperipherals_uart_3__port_txd <: 1;
        //#if $setting.handshake-mode == 1
        //_xperipherals_uart_3__port_rts <: 1;
        //#endif
    _xperipherals_uart_3__timer :> time;
    time += 10 * _xperipherals_uart_3__period;
    _xperipherals_uart_3__timer when timerafter(time) :> void;
        #endif

        #if XPERIPHERALS_UART_3__SUPPORT_RX
        //#if $setting.handshake-mode == 1
        //_xperipherals_uart_3__port_cts <: 1;
        //#endif
        #endif

        _xperipherals_uart_3__wbusy = _xperipherals_uart_3__rbusy = FALSE;
}

// Configure clocks for a new MCLK frequency or sample rate

void xperipherals_uart_3__configure( xuint baud_rate, xuint timeout_usec )
{
    //_xperipherals_uart_3__bit_period_1 = (1 * REFERENCE_CLOCK_FREQUENCY) / (2 * baud_rate);
    _xperipherals_uart_3__period = (2 * REFERENCE_CLOCK_FREQUENCY) / (2 * baud_rate);
}

#if XPERIPHERALS_UART_3__SUPPORT_TX

void xperipherals_uart_3__write_byte( xbyte data )
{
        // Serial: START ................ 1 Byte of Data ............... STOP
        // Output: LLLLL 11111 22222 33333 44444 55555 66666 77777 88888 HHHHH
        // Timing: A     B     C     D     E     F     G     H     I     J

    timer _xperipherals_uart_3__timer;
    int time; _xperipherals_uart_3__timer :> time;

        _xperipherals_uart_3__port_txd <: 0;
    time += _xperipherals_uart_3__period;
    _xperipherals_uart_3__timer when timerafter(time) :> void; // A

    #pragma loop unroll
    for( int i = 0; i < 8; ++i ) // B,C,D,E,F,G,H,I
    {
        _xperipherals_uart_3__port_txd <: ((unsigned int)data & 1); data >>= 1;
        time += _xperipherals_uart_3__period;
        _xperipherals_uart_3__timer when timerafter(time) :> void;
    }

    _xperipherals_uart_3__port_txd <: 1;
    time += _xperipherals_uart_3__period;
    _xperipherals_uart_3__timer when timerafter(time) :> void; // J
}

void xperipherals_uart_3__begin_write( xbyte data )
{
    _xperipherals_uart_3__wdata = data;
    _xperipherals_uart_3__count = 0;
    _xperipherals_uart_3__timer :> _xperipherals_uart_3__time;
    _xperipherals_uart_3__port_txd <: 0;
    _xperipherals_uart_3__time += _xperipherals_uart_3__period;
    _xperipherals_uart_3__wbusy = TRUE;
}

select xperipherals_uart_3__continue_wr( int& done )
{
    case _xperipherals_uart_3__wbusy => _xperipherals_uart_3__timer when timerafter(_xperipherals_uart_3__time) :> void:

        if( _xperipherals_uart_3__count == 0 )
        {
            _xperipherals_uart_3__port_txd <: ((unsigned int)_xperipherals_uart_3__wdata & 1);
            _xperipherals_uart_3__wdata >>= 1;
            _xperipherals_uart_3__time += _xperipherals_uart_3__period;
            ++_xperipherals_uart_3__count;
            done = FALSE;
        }
        else if( _xperipherals_uart_3__count <= 8 )
        {
            _xperipherals_uart_3__port_txd <: ((unsigned int)_xperipherals_uart_3__wdata & 1);
            _xperipherals_uart_3__wdata >>= 1;
            _xperipherals_uart_3__time += _xperipherals_uart_3__period;
            ++_xperipherals_uart_3__count;
            done = FALSE;
        }
        else if( _xperipherals_uart_3__count <= 20 )
        {
            _xperipherals_uart_3__port_txd <: 1;
            _xperipherals_uart_3__time += _xperipherals_uart_3__period;
            ++_xperipherals_uart_3__count;
            done = _xperipherals_uart_3__count == 20;
            _xperipherals_uart_3__wbusy = !done;
        }
        break;
}

#endif

#if XPERIPHERALS_UART_3__SUPPORT_RX

void xperipherals_uart_3__read_byte( xbyte& data )
{
    timer _xperipherals_uart_3__timer;
    xbyte bit; int time;

    // Wait for START bit (Step A)
    _xperipherals_uart_3__port_rxd when pinseq(0) :> void;
    _xperipherals_uart_3__timer :> time;
    time += _xperipherals_uart_3__period / 2;

    // Sample 8 bits (Steps B,C,D,E,F,G,H,I)
    #pragma loop unroll
    for( int i = 0; i < 8; ++i )
    {
        time += _xperipherals_uart_3__period;
        _xperipherals_uart_3__timer when timerafter(time) :> void;
        _xperipherals_uart_3__port_rxd :> bit; data = (data>>1) + (bit<<7);
    }

    // Wait for STOP bit to pass ...
    time += _xperipherals_uart_3__period;
    _xperipherals_uart_3__timer when timerafter(time) :> void;
}

void xperipherals_uart_3__begin_read( void )
{
    _xperipherals_uart_3__count = 0;
    _xperipherals_uart_3__timer :> _xperipherals_uart_3__time;
    _xperipherals_uart_3__time += _xperipherals_uart_3__period;
    _xperipherals_uart_3__rbusy = TRUE;
}

select xperipherals_uart_3__continue_rd( int& done, unsigned char& data )
{
    case _xperipherals_uart_3__rbusy => _xperipherals_uart_3__timer when timerafter(_xperipherals_uart_3__time) :> void:

        if( _xperipherals_uart_3__count == 0 )
        {
            _xperipherals_uart_3__time += _xperipherals_uart_3__period;
            ++_xperipherals_uart_3__count;
            done = FALSE;
        }
        else if( _xperipherals_uart_3__count <= 8 )
        {
            _xperipherals_uart_3__time += _xperipherals_uart_3__period;
            ++_xperipherals_uart_3__count;
            done = FALSE;
        }
        else if( _xperipherals_uart_3__count <= 20 )
        {
            _xperipherals_uart_3__time += _xperipherals_uart_3__period;
            ++_xperipherals_uart_3__count;
            done = _xperipherals_uart_3__count == 20;
            _xperipherals_uart_3__rbusy = FALSE;
       }
        break;
}

#endif

#endif