Home : I/O Peripherals Library | I2C Peripheral

Description

<TODO>

Naming Conventions

<TODO>

Interface Functions

<TODO>

Example Usage

<TODO>

Configuration

<TODO>

Source Files

xperipherals_i2c.h I2C peripheral interface
xperipherals_i2c_1.xc I2C peripheral #1 implementation
xperipherals_i2c_2.xc I2C peripheral #2 implementation
xperipherals_i2c_1.xc I2C peripheral #3 implementation

Source Listings

xperipherals_i2c.h

#ifndef XPERIPHERALS_I2C__INCLUDED
#define XPERIPHERALS_I2C__INCLUDED

#include "xsystem_types.h"

// Configuration - These must be defined in "xconfig.h" for each peripheral bus being used
//
// XPERIPHERALS_I2C_n                     No value
// XPERIPHERALS_I2C_n__BUS_MASTER         TRUE or FALSE
// XPERIPHERALS_I2C_n__BIT_RATE           Non-zero, non-negative integer
// XPERIPHERALS_I2C_n__RESTARTS           TRUE or FALSE
// XPERIPHERALS_I2C_n__CLOCK_STRETCHING   TRUE or FALSE
// XPERIPHERALS_I2C_n__COLLISION_DET      TRUE or FALSE
// XPERIPHERALS_I2C_n__SCL_BIT_POS        Non-negative integer
// XPERIPHERALS_I2C_n__SDA_BIT_POS        Non-negative integer
// XPERIPHERALS_I2C_n__TILE_NUMBER        integer, XS1 tile number
// XPERIPHERALS_I2C_n__SCL_PORT           XS1 port identifier
// XPERIPHERALS_I2C_n__SDA_PORT           XS1 port identifier

// Status and Error Codes

#define XPERIPHERALS_I2C__STATUS__EVENT_START   (  5)  // Start or restart condition encountered (slave mode only)
#define XPERIPHERALS_I2C__STATUS__EVENT_STOP    (  4)  // Stop condition encountered (slave mode only)
#define XPERIPHERALS_I2C__STATUS__EVENT_WRITE   (  3)  // Write operation completed, no start/stop condition encountered
#define XPERIPHERALS_I2C__STATUS__EVENT_READ    (  2)  // Read operation completed, no start/stop condition encountered
#define XPERIPHERALS_I2C__STATUS__EVENT_ACK     (  1)  // ACK operation completed, no start/stop condition encountered
#define XPERIPHERALS_I2C__STATUS__NONE          (  0)  // I2C operation has not been started
#define XPERIPHERALS_I2C__STATUS__ERROR_TIMEOUT ( -1)  // Clock stretching (master mode) or wait for start/stop (slave) timeout
#define XPERIPHERALS_I2C__STATUS__ERROR_BUSERR  ( -2)  // Bus Error (invalid start/stop sequence)
#define XPERIPHERALS_I2C__STATUS__ERROR_ARBLOST ( -3)  // Bus arbitration failure (lost abitration)
#define XPERIPHERALS_I2C__STATUS__ERROR_        ( -4)  // I2S transaction error

#define XPERIPHERALS_I2C__ACK_VALUE  0
#define XPERIPHERALS_I2C__NACK_VALUE 1

// Master/Slave API Functions

#define XPERIPHERALS_I2C__INTERFACE( N ) \
\
void   xperipherals_i2c_##N##__initialize ( void ); \
\
/* Master/Slave Blocking API */ \
/* - Start, Stop, Write, Read and Ack functions will hold SCL low to give the application time to process. */ \
/* - The 'reset' function must be called if no other I/O operations are to follow. */ \
\
int    xperipherals_i2c_##N##__start      ( void );                    /* Assert (master) or wait for (slave) START condition */ \
int    xperipherals_i2c_##N##__stop       ( void );                    /* Assert (master) or wait for (slave) STOP condition */ \
int    xperipherals_i2c_##N##__write      ( xbyte data, xbyte& ack );  /* Write next byte (master or slave) */ \
int    xperipherals_i2c_##N##__read       ( xbyte& data );             /* Read next byte (master or slave) */ \
int    xperipherals_i2c_##N##__ack        ( xbyte ack_bit );           /* Assert ACK (sda=0) after a READ (master or slave) */ \
void   xperipherals_i2c_##N##__reset      ( void );                    /* Reset state machine and release SCL */ \
\
/* Master/Slave Non-Blocking API */ \
/* - Start, Stop, Write, Read and Ack functions will hold SCL low to give the application time to process. */ \
/* - The End function must be called if no other I/O operations are to follow. */ \
\
void   xperipherals_i2c_##N##__begin_start( void );                    /* Begin START condition */ \
void   xperipherals_i2c_##N##__begin_stop ( void );                    /* Begin STOP condition */ \
void   xperipherals_i2c_##N##__begin_write( xbyte data );              /* Begin data write */ \
void   xperipherals_i2c_##N##__begin_read ( void );                    /* Begin data read */ \
void   xperipherals_i2c_##N##__begin_ack  ( xbool ack_flag );          /* Begin ack flag write */ \
select xperipherals_i2c_##N##__continue_io( int& status );             /* Wait for event and advance I2C state machine */ \
xbyte  xperipherals_i2c_##N##__get_data   ( void );                    /* Data or ACK flag from last I/O Event */ \
xbyte  xperipherals_i2c_##N##__get_ackflag( void );                    /* ACK flag from last I/O Event */

XPERIPHERALS_I2C__INTERFACE( 1 )
XPERIPHERALS_I2C__INTERFACE( 2 )
XPERIPHERALS_I2C__INTERFACE( 3 )

#endif

xperipherals_i2c_1.xc

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

#include "xperipherals_i2c.h"

#ifdef XPERIPHERALS_I2C_1

#if XPERIPHERALS_I2C_1__SCL_PORT != XPERIPHERALS_I2C_1__SDA_PORT

    //on tile[XPERIPHERALS_I2C_1__TILE_NUMBER] :
    port _xperipherals_i2c_1__port_scl = XPERIPHERALS_I2C_1__SCL_PORT;
    //on tile[XPERIPHERALS_I2C_1__TILE_NUMBER] :
    port _xperipherals_i2c_1__port_sda = XPERIPHERALS_I2C_1__SDA_PORT;

#else

    //on tile[XPERIPHERALS_I2C_1__TILE_NUMBER] :
    port _xperipherals_i2c_1__port = XPERIPHERALS_I2C_1__SCL_PORT;

    xbyte _xperipherals_i2c_1__shadow = 0;

#endif

#if XPERIPHERALS_I2C_1__BUS_MASTER
timer _xperipherals_i2c_1__timer;
int   _xperipherals_i2c_1__time;
#else
xbyte _xperipherals_i2c_1__scl;
xbyte _xperipherals_i2c_1__sda;
xbyte _xperipherals_i2c_1__pins;
#endif

int   _xperipherals_i2c_1__state;
int   _xperipherals_i2c_1__shift;
xbyte _xperipherals_i2c_1__data;
xbyte _xperipherals_i2c_1__ackflag;

// <TODO> Calulate based on current system clock frequency
#define _XPERIPHERALS_I2C_1__TIME_BASE ((400000 / XPERIPHERALS_I2C_1__BIT_RATE) * 62)

#if XPERIPHERALS_I2C_1__SCL_PORT != XPERIPHERALS_I2C_1__SDA_PORT

    xbyte _xperipherals_i2c_1__read_scl( void )
    {
        unsigned char bit=0;
        #if XPERIPHERALS_I2C_1__ACTIVE_HIGH == TRUE
        _xperipherals_i2c_1__port_scl <: 1;
        #else
        _xperipherals_i2c_1__port_scl :> bit;
        #endif
        return bit;
    }

    xbyte _xperipherals_i2c_1__read_sda( void )
    {
        unsigned char bit=0;
        #if XPERIPHERALS_I2C_1__ACTIVE_HIGH == TRUE
        _xperipherals_i2c_1__port_sda <: 1;
        #else
        _xperipherals_i2c_1__port_sda :> bit;
        #endif
        return bit;
    }

#if XPERIPHERALS_I2C_1__BUS_MASTER
    void  _xperipherals_i2c_1__clear_scl( void ) {_xperipherals_i2c_1__port_scl <: 0;}
    void  _xperipherals_i2c_1__clear_sda( void ) {_xperipherals_i2c_1__port_sda <: 0;}
#else
    xbyte  _xperipherals_i2c_1__clear_scl( void ) {return 0;}
    xbyte  _xperipherals_i2c_1__clear_sda( void ) {return 0;}
#endif

#else

    xbyte _xperipherals_i2c_1__read_scl( void )
    {
        _xperipherals_i2c_1__shadow |= (1 << XPERIPHERALS_I2C_1__SCL_BIT_POS);
        _xperipherals_i2c_1__port <: _xperipherals_i2c_1__shadow;
        return 0;
    }

    xbyte _xperipherals_i2c_1__read_sda( void )
    {
        _xperipherals_i2c_1__shadow |= (1 << XPERIPHERALS_I2C_1__SDA_BIT_POS);
        _xperipherals_i2c_1__port <: _xperipherals_i2c_1__shadow;
        return 0;
    }

    void  _xperipherals_i2c_1__clear_scl( void )
    {
        _xperipherals_i2c_1__shadow &= ~(1 << XPERIPHERALS_I2C_1__SCL_BIT_POS);
        _xperipherals_i2c_1__port <: _xperipherals_i2c_1__shadow;
    }

    void  _xperipherals_i2c_1__clear_sda( void )
    {
        _xperipherals_i2c_1__shadow &= ~(1 << XPERIPHERALS_I2C_1__SDA_BIT_POS);
        _xperipherals_i2c_1__port <: _xperipherals_i2c_1__shadow;
    }

#endif

xbyte xperipherals_i2c_1__get_data( void ) {return _xperipherals_i2c_1__data;}
xbyte xperipherals_i2c_1__get_ackflag( void ) {return _xperipherals_i2c_1__ackflag;}

int xperipherals_i2c_1__start( void )
{
    int status = XPERIPHERALS_I2C__STATUS__NONE;
    xperipherals_i2c_1__begin_start();
    while( TRUE ) {
        select {case xperipherals_i2c_1__continue_io(status);}
        if( status != XPERIPHERALS_I2C__STATUS__NONE ) break;
    }
    return status;
}

int xperipherals_i2c_1__stop( void )
{
    int status = XPERIPHERALS_I2C__STATUS__NONE;
    xperipherals_i2c_1__begin_stop();
    while( TRUE ) {
        select {case xperipherals_i2c_1__continue_io(status);}
        if( status != XPERIPHERALS_I2C__STATUS__NONE ) break;
    }
    return status;
}

int xperipherals_i2c_1__write( xbyte data, xbyte& ack_flag )
{
    int status = XPERIPHERALS_I2C__STATUS__NONE;
    xperipherals_i2c_1__begin_write( data );
    while( TRUE ) {
        select {case xperipherals_i2c_1__continue_io(status);}
        if( status != XPERIPHERALS_I2C__STATUS__NONE ) break;
    }
    ack_flag = _xperipherals_i2c_1__ackflag;
    return status;
}

int xperipherals_i2c_1__read( xbyte& data )
{
    int status = XPERIPHERALS_I2C__STATUS__NONE;
    xperipherals_i2c_1__begin_read();
    while( TRUE ) {
        select {case xperipherals_i2c_1__continue_io(status);}
        if( status != XPERIPHERALS_I2C__STATUS__NONE ) break;
   }
    data = _xperipherals_i2c_1__data;
    return status;
}

int xperipherals_i2c_1__ack( xbyte ack_flag )
{
    int status = XPERIPHERALS_I2C__STATUS__NONE;
    xperipherals_i2c_1__begin_ack( ack_flag );
    while( TRUE ) {
        select {case xperipherals_i2c_1__continue_io(status);}
        if( status != XPERIPHERALS_I2C__STATUS__NONE ) break;
    }
    return status;
}

#if XPERIPHERALS_I2C_1__BUS_MASTER

void xperipherals_i2c_1__initialize( void )
{
    _xperipherals_i2c_1__state = 0;
    _xperipherals_i2c_1__read_scl();
    _xperipherals_i2c_1__read_sda();
    _xperipherals_i2c_1__timer :> _xperipherals_i2c_1__time;
    _xperipherals_i2c_1__timer when timerafter( _xperipherals_i2c_1__time + 10 * _XPERIPHERALS_I2C_1__TIME_BASE ) :> void;
}

void xperipherals_i2c_1__begin_start( void )
{
    _xperipherals_i2c_1__state = 1;
    _xperipherals_i2c_1__timer :> _xperipherals_i2c_1__time;
}

void xperipherals_i2c_1__begin_write( xbyte data )
{
    _xperipherals_i2c_1__data = data;
    _xperipherals_i2c_1__state = 4;
    _xperipherals_i2c_1__shift = 7;
    _xperipherals_i2c_1__timer :> _xperipherals_i2c_1__time;
}

void xperipherals_i2c_1__begin_read( void )
{
    _xperipherals_i2c_1__state = 11;
    _xperipherals_i2c_1__shift = 7;
    _xperipherals_i2c_1__timer :> _xperipherals_i2c_1__time;
}

void xperipherals_i2c_1__begin_ack( xbool ack_flag )
{
    _xperipherals_i2c_1__data = ack_flag != 0;
    _xperipherals_i2c_1__state = 16;
    _xperipherals_i2c_1__timer :> _xperipherals_i2c_1__time;
}

void xperipherals_i2c_1__begin_stop( void )
{
    _xperipherals_i2c_1__state = 20;
    _xperipherals_i2c_1__timer :> _xperipherals_i2c_1__time;
}

int _xperipherals_i2c_1__io_continue( void )
{
    switch( _xperipherals_i2c_1__state )
    {
        // Start Condition
        case 1:
        _xperipherals_i2c_1__clear_sda();
        _xperipherals_i2c_1__state = 2;
        _xperipherals_i2c_1__time += 1 * _XPERIPHERALS_I2C_1__TIME_BASE;
        break;
        case 2:
        _xperipherals_i2c_1__clear_scl();
        _xperipherals_i2c_1__state = 3;
        _xperipherals_i2c_1__time += 1 * _XPERIPHERALS_I2C_1__TIME_BASE;
        break;
        case 3:
        _xperipherals_i2c_1__state = 0;
        return XPERIPHERALS_I2C__STATUS__EVENT_START;
        break;

        // Write Bits 7-0
        case 4:
        if( (_xperipherals_i2c_1__data >> _xperipherals_i2c_1__shift) & 1 ) _xperipherals_i2c_1__read_sda();
        else _xperipherals_i2c_1__clear_sda();
        _xperipherals_i2c_1__shift--;
        _xperipherals_i2c_1__state = 5;
        _xperipherals_i2c_1__time += 1 * _XPERIPHERALS_I2C_1__TIME_BASE;
        break;
        case 5:
        _xperipherals_i2c_1__read_scl();
        _xperipherals_i2c_1__state = 6;
        _xperipherals_i2c_1__time += 2 * _XPERIPHERALS_I2C_1__TIME_BASE;
        break;
        case 6:
        _xperipherals_i2c_1__clear_scl();
        if( _xperipherals_i2c_1__shift < 0 ) {
            _xperipherals_i2c_1__state = 7;
            _xperipherals_i2c_1__time += 2 * _XPERIPHERALS_I2C_1__TIME_BASE;
        }
        else {
            _xperipherals_i2c_1__state = 4;
            _xperipherals_i2c_1__time += 1 * _XPERIPHERALS_I2C_1__TIME_BASE;
        }
        break;

         // Sense ACK/NACK
        case 7:
        _xperipherals_i2c_1__data = _xperipherals_i2c_1__read_sda();
        _xperipherals_i2c_1__state = 8;
        break;
        case 8:
        _xperipherals_i2c_1__read_scl();
        _xperipherals_i2c_1__state = 9;
        _xperipherals_i2c_1__time += 2 * _XPERIPHERALS_I2C_1__TIME_BASE;
        break;
        case 9:
        _xperipherals_i2c_1__clear_scl();
        _xperipherals_i2c_1__state = 10;
        _xperipherals_i2c_1__time += 1 * _XPERIPHERALS_I2C_1__TIME_BASE;
        break;
        case 10:
        _xperipherals_i2c_1__state = 0;
        return XPERIPHERALS_I2C__STATUS__EVENT_WRITE;
        break;

         // Read Bits 7-0
        case 11:
        _xperipherals_i2c_1__read_sda();
        _xperipherals_i2c_1__state = 12;
        _xperipherals_i2c_1__time += 1 * _XPERIPHERALS_I2C_1__TIME_BASE;
        break;
        case 12:
        _xperipherals_i2c_1__read_scl();
        _xperipherals_i2c_1__state = 13;
        _xperipherals_i2c_1__time += 1 * _XPERIPHERALS_I2C_1__TIME_BASE;
        break;
        case 13:
        (_xperipherals_i2c_1__data = _xperipherals_i2c_1__data >> 1) + _xperipherals_i2c_1__read_sda() << (_xperipherals_i2c_1__shift--);
        _xperipherals_i2c_1__state = 14;
        _xperipherals_i2c_1__time += 1 * _XPERIPHERALS_I2C_1__TIME_BASE; break;
        case 14:
        _xperipherals_i2c_1__clear_scl();
        if( _xperipherals_i2c_1__shift < 0 ) _xperipherals_i2c_1__state = 15;
        else _xperipherals_i2c_1__state = 11;
        _xperipherals_i2c_1__time += 1 * _XPERIPHERALS_I2C_1__TIME_BASE;
        break;
        case 15:
        _xperipherals_i2c_1__state = 0;
        return XPERIPHERALS_I2C__STATUS__EVENT_READ;
        break;

        // Assert ACK/NACK
        case 16:
        if( _xperipherals_i2c_1__data ) _xperipherals_i2c_1__read_sda();
        else _xperipherals_i2c_1__clear_sda();
        _xperipherals_i2c_1__state = 17;
        _xperipherals_i2c_1__time += 1 * _XPERIPHERALS_I2C_1__TIME_BASE;
        break;
        case 17: _xperipherals_i2c_1__read_scl();
        _xperipherals_i2c_1__state = 18;
        _xperipherals_i2c_1__time += 2 * _XPERIPHERALS_I2C_1__TIME_BASE;
        break;
        case 18:
        _xperipherals_i2c_1__clear_scl();
        _xperipherals_i2c_1__state = 19;
        _xperipherals_i2c_1__time += 1 * _XPERIPHERALS_I2C_1__TIME_BASE;
        break;
        case 19:
        _xperipherals_i2c_1__state = 0;
        return XPERIPHERALS_I2C__STATUS__EVENT_ACK;
        break;

        // Stop Condition
        case 20: _xperipherals_i2c_1__clear_sda();
        _xperipherals_i2c_1__state = 21;
        _xperipherals_i2c_1__time += 1 * _XPERIPHERALS_I2C_1__TIME_BASE;
        break;
        case 21: _xperipherals_i2c_1__read_scl();
        _xperipherals_i2c_1__state = 22;
        _xperipherals_i2c_1__time += 1 * _XPERIPHERALS_I2C_1__TIME_BASE;
        break;
        case 22: _xperipherals_i2c_1__read_sda();
        _xperipherals_i2c_1__state = 23;
        _xperipherals_i2c_1__time += 2 * _XPERIPHERALS_I2C_1__TIME_BASE;
        break;
        case 23:
        _xperipherals_i2c_1__state = 0;
        return XPERIPHERALS_I2C__STATUS__EVENT_STOP;
        break;

    }
    return XPERIPHERALS_I2C__STATUS__NONE;
}

select xperipherals_i2c_1__continue_io( int& status )
{
    case _xperipherals_i2c_1__state > 0 => _xperipherals_i2c_1__timer when timerafter(_xperipherals_i2c_1__time) :> _xperipherals_i2c_1__time:
    status = _xperipherals_i2c_1__io_continue();
    break;
}

#else

void xperipherals_i2c_1__initialize( void )
{
    _xperipherals_i2c_1__state = 0;
}

void xperipherals_i2c_1__begin_start( void )
{
    while( TRUE )
    {
        _xperipherals_i2c_1__scl = _xperipherals_i2c_1__read_scl();
        _xperipherals_i2c_1__sda = _xperipherals_i2c_1__read_sda();
        if( _xperipherals_i2c_1__scl && _xperipherals_i2c_1__sda ) break;
    }
    _xperipherals_i2c_1__pins = 0b1111;
    _xperipherals_i2c_1__state = 1;
}

void xperipherals_i2c_1__begin_stop( void )
{
    _xperipherals_i2c_1__state = 1;
    _xperipherals_i2c_1__read_sda(); // Release SDA - allow posbbile resulting SDA change while SCL is low
    _xperipherals_i2c_1__read_scl(); // Release SCL
    _xperipherals_i2c_1__sda = _xperipherals_i2c_1__read_sda(); // Get current state
}

void xperipherals_i2c_1__begin_write( xbyte data )
{
    _xperipherals_i2c_1__data = data;
    _xperipherals_i2c_1__shift = 6;
    _xperipherals_i2c_1__state = 3;
    // Write first bit - SDA changes while SCL is low
    if( (_xperipherals_i2c_1__data >> 7) & 1 ) _xperipherals_i2c_1__sda = _xperipherals_i2c_1__read_sda();
    else _xperipherals_i2c_1__sda = _xperipherals_i2c_1__clear_sda();
    _xperipherals_i2c_1__scl = _xperipherals_i2c_1__read_scl(); // Release SCL, get current state
    _xperipherals_i2c_1__sda = _xperipherals_i2c_1__read_sda(); // Get current state
}

void xperipherals_i2c_1__begin_read()
{
    _xperipherals_i2c_1__state = 6;
    _xperipherals_i2c_1__shift = 7;
    _xperipherals_i2c_1__read_sda(); // Release SDA - allow posbbile resulting SDA change while SCL is low
    _xperipherals_i2c_1__scl = _xperipherals_i2c_1__read_scl(); // Release SCL, get current state
    _xperipherals_i2c_1__sda = _xperipherals_i2c_1__read_sda(); // Get current state
}

void xperipherals_i2c_1__begin_ack( xbool ack_flag )
{
    _xperipherals_i2c_1__data = ack_flag;
    _xperipherals_i2c_1__state = 7;
    // Write bit - SDA changes while SCL is low
    if( _xperipherals_i2c_1__data ) _xperipherals_i2c_1__sda = _xperipherals_i2c_1__read_sda();
    else _xperipherals_i2c_1__sda = _xperipherals_i2c_1__clear_sda();
    _xperipherals_i2c_1__scl = _xperipherals_i2c_1__read_scl(); // Release SCL, get current state
    _xperipherals_i2c_1__sda = _xperipherals_i2c_1__read_sda(); // Get current state
}

void xperipherals_i2c_1__end( void )
{
    _xperipherals_i2c_1__scl = _xperipherals_i2c_1__read_scl(); // Release SCL, get current state
    _xperipherals_i2c_1__sda = _xperipherals_i2c_1__read_sda(); // Get current state
    _xperipherals_i2c_1__state = 0;
}

int _xperipherals_i2c_1__continue_io( void )
{
    switch( _xperipherals_i2c_1__state )
    {
        // Wait for start/stop Condition

        case 1:

        if( _xperipherals_i2c_1__pins == 0b1110 ) { // scl=1 sda->0 --- START
            _xperipherals_i2c_1__state = 2;
        }
        else if( _xperipherals_i2c_1__pins == 0b1011 ) { // scl=1 sda->1 --- STOP
            _xperipherals_i2c_1__state = 0;
            return XPERIPHERALS_I2C__STATUS__EVENT_STOP;
        }
        break;

        case 2:
        if( _xperipherals_i2c_1__pins == 0b1101 || _xperipherals_i2c_1__pins == 0b1000 ) { // scl->0 sda=X
            _xperipherals_i2c_1__clear_scl(); // Hold SCL Low
            _xperipherals_i2c_1__read_sda();  // Release SDA
            _xperipherals_i2c_1__state = 0;
            return XPERIPHERALS_I2C__STATUS__EVENT_START;
        }
        break;

        // Write Bits 6-0

        case 3:
        if( _xperipherals_i2c_1__pins == 0b1101 || _xperipherals_i2c_1__pins == 0b1000 ) { // scl->0 sda=X
            if( (_xperipherals_i2c_1__data >> _xperipherals_i2c_1__shift) & 1 ) _xperipherals_i2c_1__sda = _xperipherals_i2c_1__read_sda();
            else _xperipherals_i2c_1__sda = _xperipherals_i2c_1__clear_sda();
            if( --_xperipherals_i2c_1__shift < 0 ) _xperipherals_i2c_1__state = 4;
            else _xperipherals_i2c_1__state = 3;
        }
        else if( _xperipherals_i2c_1__pins == 0b1011 ) { // scl=1 sda->1 --- STOP
            _xperipherals_i2c_1__state = 0;
            return XPERIPHERALS_I2C__STATUS__EVENT_STOP;
        }
        break;

         // Sense ACK/NACK

        case 4:
        if( _xperipherals_i2c_1__pins == 0b1101 || _xperipherals_i2c_1__pins == 0b1000 ) { // scl->0 sda=X
            _xperipherals_i2c_1__state = 5;
        }
        break;
        case 5:
        if( _xperipherals_i2c_1__pins == 0b0111 || _xperipherals_i2c_1__pins == 0b0010 ) { // scl->1 sda=X
            _xperipherals_i2c_1__ackflag = _xperipherals_i2c_1__read_sda();
        }
        if( _xperipherals_i2c_1__pins == 0b1101 || _xperipherals_i2c_1__pins == 0b1000 ) { // scl->0 sda=X
            _xperipherals_i2c_1__clear_scl(); // Hold SCL Low
            _xperipherals_i2c_1__read_sda();  // Release SDA
            _xperipherals_i2c_1__state = 0;
            return XPERIPHERALS_I2C__STATUS__EVENT_WRITE;
        }
        break;

        // Read Bits 7-0

        case 6:
        if( _xperipherals_i2c_1__pins == 0b0111 || _xperipherals_i2c_1__pins == 0b0010 ) { // scl->1 sda=X
            _xperipherals_i2c_1__data = (_xperipherals_i2c_1__data << 1) + _xperipherals_i2c_1__read_sda();
        }
        else if( _xperipherals_i2c_1__pins == 0b1101 || _xperipherals_i2c_1__pins == 0b1000 ) { // scl->0 sda=X
            if( --_xperipherals_i2c_1__shift >= 0 ) _xperipherals_i2c_1__state = 6;
            else {
                _xperipherals_i2c_1__clear_scl(); // Hold SCL Low
                _xperipherals_i2c_1__read_sda();  // Release SDA
                _xperipherals_i2c_1__state = 0;
                //printstr("READ: "); printhexln(_xperipherals_i2c_1__data);
                return XPERIPHERALS_I2C__STATUS__EVENT_READ;
            }
        }
        else if( _xperipherals_i2c_1__pins == 0b1011 ) { // scl=1 sda->1 --- STOP
            _xperipherals_i2c_1__state = 0;
            return XPERIPHERALS_I2C__STATUS__EVENT_STOP;
        }
        break;

        // Assert ACK/NACK

        case 7:
        if( _xperipherals_i2c_1__pins == 0b1101 || _xperipherals_i2c_1__pins == 0b1000 ) { // scl->0 sda=X
            _xperipherals_i2c_1__clear_scl(); // Hold SCL Low
            _xperipherals_i2c_1__read_sda();  // Release SDA
            _xperipherals_i2c_1__state = 0;
            return XPERIPHERALS_I2C__STATUS__EVENT_ACK;
        }
        else if( _xperipherals_i2c_1__pins == 0b1011 ) { // scl=1 sda->1 --- STOP
            _xperipherals_i2c_1__state = 0;
            return XPERIPHERALS_I2C__STATUS__EVENT_STOP;
        }
        break;
    }
    return XPERIPHERALS_I2C__STATUS__NONE;
}

select xperipherals_i2c_1__continue_io( int& status )
{
    case _xperipherals_i2c_1__port_scl when pinseq(!_xperipherals_i2c_1__scl) :> _xperipherals_i2c_1__scl:

        _xperipherals_i2c_1__pins = ((!_xperipherals_i2c_1__scl)<<3) + (_xperipherals_i2c_1__sda<<2) + (_xperipherals_i2c_1__scl<<1) + _xperipherals_i2c_1__sda;
        if( _xperipherals_i2c_1__scl == 0 ) _xperipherals_i2c_1__read_sda(); // release SDA on every SCL transition to low
        status = _xperipherals_i2c_1__io_continue();
        break;

    case _xperipherals_i2c_1__port_sda when pinseq(!_xperipherals_i2c_1__sda) :> _xperipherals_i2c_1__sda:

        _xperipherals_i2c_1__pins = (_xperipherals_i2c_1__scl<<3) + ((!_xperipherals_i2c_1__sda)<<2) + (_xperipherals_i2c_1__scl<<1) + _xperipherals_i2c_1__sda;
        status = _xperipherals_i2c_1__io_continue();
        break;
}

#endif

#endif

xperipherals_i2c_2.xc

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

#include "xperipherals_i2c.h"

#ifdef XPERIPHERALS_I2C__2

#if XPERIPHERALS_I2C_2__SCL_PORT != XPERIPHERALS_I2C_2__SDA_PORT

    on tile[XPERIPHERALS_I2C_2__TILE_NUMBER] : port _xperipherals_i2c_2__port_scl = XPERIPHERALS_I2C_2__SCL_PORT;
    on tile[XPERIPHERALS_I2C_2__TILE_NUMBER] : port _xperipherals_i2c_2__port_sda = XPERIPHERALS_I2C_2__SDA_PORT;

#else

    on tile[XPERIPHERALS_I2C_2__TILE_NUMBER] : port _xperipherals_i2c_2__port = XPERIPHERALS_I2C_2__SCL_PORT;

    xbyte _xperipherals_i2c_2__shadow = 0;

#endif

#if XPERIPHERALS_I2C_2__BUS_MASTER
timer _xperipherals_i2c_2__timer;
int   _xperipherals_i2c_2__time;
#else
xbyte _xperipherals_i2c_2__scl;
xbyte _xperipherals_i2c_2__sda;
xbyte _xperipherals_i2c_2__pins;
#endif

int   _xperipherals_i2c_2__state;
int   _xperipherals_i2c_2__shift;
xbyte _xperipherals_i2c_2__data;
xbyte _xperipherals_i2c_2__ackflag;

// <TODO> Calulate based on current system clock frequency
#define _XPERIPHERALS_I2C_2__TIME_BASE ((400000 / XPERIPHERALS_I2C_2__BIT_RATE) * 62)

#if XPERIPHERALS_I2C_2__SCL_PORT != XPERIPHERALS_I2C_2__SDA_PORT

    xbyte _xperipherals_i2c_2__read_scl( void )
    {
        unsigned char bit=0;
        #if XPERIPHERALS_I2C_2__ACTIVE_HIGH == TRUE
        _xperipherals_i2c_2__port_scl <: 1;
        #else
        _xperipherals_i2c_2__port_scl :> bit;
        #endif
        return bit;
    }

    xbyte _xperipherals_i2c_2__read_sda( void )
    {
        unsigned char bit=0;
        #if XPERIPHERALS_I2C_2__ACTIVE_HIGH == TRUE
        _xperipherals_i2c_2__port_sda <: 1;
        #else
        _xperipherals_i2c_2__port_sda :> bit;
        #endif
        return bit;
    }

#if XPERIPHERALS_I2C_2__BUS_MASTER
    void  _xperipherals_i2c_2__clear_scl( void ) {_xperipherals_i2c_2__port_scl <: 0;}
    void  _xperipherals_i2c_2__clear_sda( void ) {_xperipherals_i2c_2__port_sda <: 0;}
#else
    xbyte  _xperipherals_i2c_2__clear_scl( void ) {return 0;}
    xbyte  _xperipherals_i2c_2__clear_sda( void ) {return 0;}
#endif

#else

    xbyte _xperipherals_i2c_2__read_scl( void )
    {
        _xperipherals_i2c_2__shadow |= (1 << XPERIPHERALS_I2C_2__SCL_BIT_POS);
        _xperipherals_i2c_2__port <: _xperipherals_i2c_2__shadow;
        return 0;
    }

    xbyte _xperipherals_i2c_2__read_sda( void )
    {
        _xperipherals_i2c_2__shadow |= (1 << XPERIPHERALS_I2C_2__SDA_BIT_POS);
        _xperipherals_i2c_2__port <: _xperipherals_i2c_2__shadow;
        return 0;
    }

    void  _xperipherals_i2c_2__clear_scl( void )
    {
        _xperipherals_i2c_2__shadow &= ~(1 << XPERIPHERALS_I2C_2__SCL_BIT_POS);
        _xperipherals_i2c_2__port <: _xperipherals_i2c_2__shadow;
    }

    void  _xperipherals_i2c_2__clear_sda( void )
    {
        _xperipherals_i2c_2__shadow &= ~(1 << XPERIPHERALS_I2C_2__SDA_BIT_POS);
        _xperipherals_i2c_2__port <: _xperipherals_i2c_2__shadow;
    }

#endif

xbyte xperipherals_i2c_2__get_data( void ) {return _xperipherals_i2c_2__data;}
xbyte xperipherals_i2c_2__get_ackflag( void ) {return _xperipherals_i2c_2__ackflag;}

int xperipherals_i2c_2__start( void )
{
    int status = XPERIPHERALS_I2C__STATUS__NONE;
    xperipherals_i2c_2__begin_start();
    while( TRUE ) {
        select {case xperipherals_i2c_2__continue_io(status);}
        if( status != XPERIPHERALS_I2C__STATUS__NONE ) break;
    }
    return status;
}

int xperipherals_i2c_2__stop( void )
{
    int status = XPERIPHERALS_I2C__STATUS__NONE;
    xperipherals_i2c_2__begin_stop();
    while( TRUE ) {
        select {case xperipherals_i2c_2__continue_io(status);}
        if( status != XPERIPHERALS_I2C__STATUS__NONE ) break;
    }
    return status;
}

int xperipherals_i2c_2__write( xbyte data, xbyte& ack_flag )
{
    int status = XPERIPHERALS_I2C__STATUS__NONE;
    xperipherals_i2c_2__begin_write( data );
    while( TRUE ) {
        select {case xperipherals_i2c_2__continue_io(status);}
        if( status != XPERIPHERALS_I2C__STATUS__NONE ) break;
    }
    ack_flag = _xperipherals_i2c_2__ackflag;
    return status;
}

int xperipherals_i2c_2__read( xbyte& data )
{
    int status = XPERIPHERALS_I2C__STATUS__NONE;
    xperipherals_i2c_2__begin_read();
    while( TRUE ) {
        select {case xperipherals_i2c_2__continue_io(status);}
        if( status != XPERIPHERALS_I2C__STATUS__NONE ) break;
   }
    data = _xperipherals_i2c_2__data;
    return status;
}

int xperipherals_i2c_2__ack( xbyte ack_flag )
{
    int status = XPERIPHERALS_I2C__STATUS__NONE;
    xperipherals_i2c_2__begin_ack( ack_flag );
    while( TRUE ) {
        select {case xperipherals_i2c_2__continue_io(status);}
        if( status != XPERIPHERALS_I2C__STATUS__NONE ) break;
    }
    return status;
}

#if XPERIPHERALS_I2C_2__BUS_MASTER

void xperipherals_i2c_2__initialize( void )
{
    _xperipherals_i2c_2__state = 0;
    _xperipherals_i2c_2__read_scl();
    _xperipherals_i2c_2__read_sda();
    _xperipherals_i2c_2__timer :> _xperipherals_i2c_2__time;
    _xperipherals_i2c_2__timer when timerafter( _xperipherals_i2c_2__time + 10 * _XPERIPHERALS_I2C_2__TIME_BASE ) :> void;
}

void xperipherals_i2c_2__begin_start( void )
{
    _xperipherals_i2c_2__state = 1;
    _xperipherals_i2c_2__timer :> _xperipherals_i2c_2__time;
}

void xperipherals_i2c_2__begin_write( xbyte data )
{
    _xperipherals_i2c_2__data = data;
    _xperipherals_i2c_2__state = 4;
    _xperipherals_i2c_2__shift = 7;
    _xperipherals_i2c_2__timer :> _xperipherals_i2c_2__time;
}

void xperipherals_i2c_2__begin_read( void )
{
    _xperipherals_i2c_2__state = 11;
    _xperipherals_i2c_2__shift = 7;
    _xperipherals_i2c_2__timer :> _xperipherals_i2c_2__time;
}

void xperipherals_i2c_2__begin_ack( xbool ack_flag )
{
    _xperipherals_i2c_2__data = ack_flag != 0;
    _xperipherals_i2c_2__state = 16;
    _xperipherals_i2c_2__timer :> _xperipherals_i2c_2__time;
}

void xperipherals_i2c_2__begin_stop( void )
{
    _xperipherals_i2c_2__state = 20;
    _xperipherals_i2c_2__timer :> _xperipherals_i2c_2__time;
}

int _xperipherals_i2c_2__io_continue( void )
{
    switch( _xperipherals_i2c_2__state )
    {
        // Start Condition
        case 1:
        _xperipherals_i2c_2__clear_sda();
        _xperipherals_i2c_2__state = 2;
        _xperipherals_i2c_2__time += 1 * _XPERIPHERALS_I2C_2__TIME_BASE;
        break;
        case 2:
        _xperipherals_i2c_2__clear_scl();
        _xperipherals_i2c_2__state = 3;
        _xperipherals_i2c_2__time += 1 * _XPERIPHERALS_I2C_2__TIME_BASE;
        break;
        case 3:
        _xperipherals_i2c_2__state = 0;
        return XPERIPHERALS_I2C__STATUS__EVENT_START;
        break;

        // Write Bits 7-0
        case 4:
        if( (_xperipherals_i2c_2__data >> _xperipherals_i2c_2__shift) & 1 ) _xperipherals_i2c_2__read_sda();
        else _xperipherals_i2c_2__clear_sda();
        _xperipherals_i2c_2__shift--;
        _xperipherals_i2c_2__state = 5;
        _xperipherals_i2c_2__time += 1 * _XPERIPHERALS_I2C_2__TIME_BASE;
        break;
        case 5:
        _xperipherals_i2c_2__read_scl();
        _xperipherals_i2c_2__state = 6;
        _xperipherals_i2c_2__time += 2 * _XPERIPHERALS_I2C_2__TIME_BASE;
        break;
        case 6:
        _xperipherals_i2c_2__clear_scl();
        if( _xperipherals_i2c_2__shift < 0 ) {
            _xperipherals_i2c_2__state = 7;
            _xperipherals_i2c_2__time += 2 * _XPERIPHERALS_I2C_2__TIME_BASE;
        }
        else {
            _xperipherals_i2c_2__state = 4;
            _xperipherals_i2c_2__time += 1 * _XPERIPHERALS_I2C_2__TIME_BASE;
        }
        break;

         // Sense ACK/NACK
        case 7:
        _xperipherals_i2c_2__data = _xperipherals_i2c_2__read_sda();
        _xperipherals_i2c_2__state = 8;
        break;
        case 8:
        _xperipherals_i2c_2__read_scl();
        _xperipherals_i2c_2__state = 9;
        _xperipherals_i2c_2__time += 2 * _XPERIPHERALS_I2C_2__TIME_BASE;
        break;
        case 9:
        _xperipherals_i2c_2__clear_scl();
        _xperipherals_i2c_2__state = 10;
        _xperipherals_i2c_2__time += 1 * _XPERIPHERALS_I2C_2__TIME_BASE;
        break;
        case 10:
        _xperipherals_i2c_2__state = 0;
        return XPERIPHERALS_I2C__STATUS__EVENT_WRITE;
        break;

         // Read Bits 7-0
        case 11:
        _xperipherals_i2c_2__read_sda();
        _xperipherals_i2c_2__state = 12;
        _xperipherals_i2c_2__time += 1 * _XPERIPHERALS_I2C_2__TIME_BASE;
        break;
        case 12:
        _xperipherals_i2c_2__read_scl();
        _xperipherals_i2c_2__state = 13;
        _xperipherals_i2c_2__time += 1 * _XPERIPHERALS_I2C_2__TIME_BASE;
        break;
        case 13:
        (_xperipherals_i2c_2__data = _xperipherals_i2c_2__data >> 1) + _xperipherals_i2c_2__read_sda() << (_xperipherals_i2c_2__shift--);
        _xperipherals_i2c_2__state = 14;
        _xperipherals_i2c_2__time += 1 * _XPERIPHERALS_I2C_2__TIME_BASE; break;
        case 14:
        _xperipherals_i2c_2__clear_scl();
        if( _xperipherals_i2c_2__shift < 0 ) _xperipherals_i2c_2__state = 15;
        else _xperipherals_i2c_2__state = 11;
        _xperipherals_i2c_2__time += 1 * _XPERIPHERALS_I2C_2__TIME_BASE;
        break;
        case 15:
        _xperipherals_i2c_2__state = 0;
        return XPERIPHERALS_I2C__STATUS__EVENT_READ;
        break;

        // Assert ACK/NACK
        case 16:
        if( _xperipherals_i2c_2__data ) _xperipherals_i2c_2__read_sda();
        else _xperipherals_i2c_2__clear_sda();
        _xperipherals_i2c_2__state = 17;
        _xperipherals_i2c_2__time += 1 * _XPERIPHERALS_I2C_2__TIME_BASE;
        break;
        case 17: _xperipherals_i2c_2__read_scl();
        _xperipherals_i2c_2__state = 18;
        _xperipherals_i2c_2__time += 2 * _XPERIPHERALS_I2C_2__TIME_BASE;
        break;
        case 18:
        _xperipherals_i2c_2__clear_scl();
        _xperipherals_i2c_2__state = 19;
        _xperipherals_i2c_2__time += 1 * _XPERIPHERALS_I2C_2__TIME_BASE;
        break;
        case 19:
        _xperipherals_i2c_2__state = 0;
        return XPERIPHERALS_I2C__STATUS__EVENT_ACK;
        break;

        // Stop Condition
        case 20: _xperipherals_i2c_2__clear_sda();
        _xperipherals_i2c_2__state = 21;
        _xperipherals_i2c_2__time += 1 * _XPERIPHERALS_I2C_2__TIME_BASE;
        break;
        case 21: _xperipherals_i2c_2__read_scl();
        _xperipherals_i2c_2__state = 22;
        _xperipherals_i2c_2__time += 1 * _XPERIPHERALS_I2C_2__TIME_BASE;
        break;
        case 22: _xperipherals_i2c_2__read_sda();
        _xperipherals_i2c_2__state = 23;
        _xperipherals_i2c_2__time += 2 * _XPERIPHERALS_I2C_2__TIME_BASE;
        break;
        case 23:
        _xperipherals_i2c_2__state = 0;
        return XPERIPHERALS_I2C__STATUS__EVENT_STOP;
        break;

    }
    return XPERIPHERALS_I2C__STATUS__NONE;
}

select xperipherals_i2c_2__continue_io( int& status )
{
    case _xperipherals_i2c_2__state > 0 => _xperipherals_i2c_2__timer when timerafter(_xperipherals_i2c_2__time) :> _xperipherals_i2c_2__time:
    status = _xperipherals_i2c_2__io_continue();
    break;
}

#else

void xperipherals_i2c_2__initialize( void )
{
    _xperipherals_i2c_2__state = 0;
}

void xperipherals_i2c_2__begin_start( void )
{
    while( TRUE )
    {
        _xperipherals_i2c_2__scl = _xperipherals_i2c_2__read_scl();
        _xperipherals_i2c_2__sda = _xperipherals_i2c_2__read_sda();
        if( _xperipherals_i2c_2__scl && _xperipherals_i2c_2__sda ) break;
    }
    _xperipherals_i2c_2__pins = 0b1111;
    _xperipherals_i2c_2__state = 1;
}

void xperipherals_i2c_2__begin_stop( void )
{
    _xperipherals_i2c_2__state = 1;
    _xperipherals_i2c_2__read_sda(); // Release SDA - allow posbbile resulting SDA change while SCL is low
    _xperipherals_i2c_2__read_scl(); // Release SCL
    _xperipherals_i2c_2__sda = _xperipherals_i2c_2__read_sda(); // Get current state
}

void xperipherals_i2c_2__begin_write( xbyte data )
{
    _xperipherals_i2c_2__data = data;
    _xperipherals_i2c_2__shift = 6;
    _xperipherals_i2c_2__state = 3;
    // Write first bit - SDA changes while SCL is low
    if( (_xperipherals_i2c_2__data >> 7) & 1 ) _xperipherals_i2c_2__sda = _xperipherals_i2c_2__read_sda();
    else _xperipherals_i2c_2__sda = _xperipherals_i2c_2__clear_sda();
    _xperipherals_i2c_2__scl = _xperipherals_i2c_2__read_scl(); // Release SCL, get current state
    _xperipherals_i2c_2__sda = _xperipherals_i2c_2__read_sda(); // Get current state
}

void xperipherals_i2c_2__begin_read()
{
    _xperipherals_i2c_2__state = 6;
    _xperipherals_i2c_2__shift = 7;
    _xperipherals_i2c_2__read_sda(); // Release SDA - allow posbbile resulting SDA change while SCL is low
    _xperipherals_i2c_2__scl = _xperipherals_i2c_2__read_scl(); // Release SCL, get current state
    _xperipherals_i2c_2__sda = _xperipherals_i2c_2__read_sda(); // Get current state
}

void xperipherals_i2c_2__begin_ack( xbool ack_flag )
{
    _xperipherals_i2c_2__data = ack_flag;
    _xperipherals_i2c_2__state = 7;
    // Write bit - SDA changes while SCL is low
    if( _xperipherals_i2c_2__data ) _xperipherals_i2c_2__sda = _xperipherals_i2c_2__read_sda();
    else _xperipherals_i2c_2__sda = _xperipherals_i2c_2__clear_sda();
    _xperipherals_i2c_2__scl = _xperipherals_i2c_2__read_scl(); // Release SCL, get current state
    _xperipherals_i2c_2__sda = _xperipherals_i2c_2__read_sda(); // Get current state
}

void xperipherals_i2c_2__end( void )
{
    _xperipherals_i2c_2__scl = _xperipherals_i2c_2__read_scl(); // Release SCL, get current state
    _xperipherals_i2c_2__sda = _xperipherals_i2c_2__read_sda(); // Get current state
    _xperipherals_i2c_2__state = 0;
}

int _xperipherals_i2c_2__continue_io( void )
{
    switch( _xperipherals_i2c_2__state )
    {
        // Wait for start/stop Condition

        case 1:

        if( _xperipherals_i2c_2__pins == 0b1110 ) { // scl=1 sda->0 --- START
            _xperipherals_i2c_2__state = 2;
        }
        else if( _xperipherals_i2c_2__pins == 0b1011 ) { // scl=1 sda->1 --- STOP
            _xperipherals_i2c_2__state = 0;
            return XPERIPHERALS_I2C__STATUS__EVENT_STOP;
        }
        break;

        case 2:
        if( _xperipherals_i2c_2__pins == 0b1101 || _xperipherals_i2c_2__pins == 0b1000 ) { // scl->0 sda=X
            _xperipherals_i2c_2__clear_scl(); // Hold SCL Low
            _xperipherals_i2c_2__read_sda();  // Release SDA
            _xperipherals_i2c_2__state = 0;
            return XPERIPHERALS_I2C__STATUS__EVENT_START;
        }
        break;

        // Write Bits 6-0

        case 3:
        if( _xperipherals_i2c_2__pins == 0b1101 || _xperipherals_i2c_2__pins == 0b1000 ) { // scl->0 sda=X
            if( (_xperipherals_i2c_2__data >> _xperipherals_i2c_2__shift) & 1 ) _xperipherals_i2c_2__sda = _xperipherals_i2c_2__read_sda();
            else _xperipherals_i2c_2__sda = _xperipherals_i2c_2__clear_sda();
            if( --_xperipherals_i2c_2__shift < 0 ) _xperipherals_i2c_2__state = 4;
            else _xperipherals_i2c_2__state = 3;
        }
        else if( _xperipherals_i2c_2__pins == 0b1011 ) { // scl=1 sda->1 --- STOP
            _xperipherals_i2c_2__state = 0;
            return XPERIPHERALS_I2C__STATUS__EVENT_STOP;
        }
        break;

         // Sense ACK/NACK

        case 4:
        if( _xperipherals_i2c_2__pins == 0b1101 || _xperipherals_i2c_2__pins == 0b1000 ) { // scl->0 sda=X
            _xperipherals_i2c_2__state = 5;
        }
        break;
        case 5:
        if( _xperipherals_i2c_2__pins == 0b0111 || _xperipherals_i2c_2__pins == 0b0010 ) { // scl->1 sda=X
            _xperipherals_i2c_2__ackflag = _xperipherals_i2c_2__read_sda();
        }
        if( _xperipherals_i2c_2__pins == 0b1101 || _xperipherals_i2c_2__pins == 0b1000 ) { // scl->0 sda=X
            _xperipherals_i2c_2__clear_scl(); // Hold SCL Low
            _xperipherals_i2c_2__read_sda();  // Release SDA
            _xperipherals_i2c_2__state = 0;
            return XPERIPHERALS_I2C__STATUS__EVENT_WRITE;
        }
        break;

        // Read Bits 7-0

        case 6:
        if( _xperipherals_i2c_2__pins == 0b0111 || _xperipherals_i2c_2__pins == 0b0010 ) { // scl->1 sda=X
            _xperipherals_i2c_2__data = (_xperipherals_i2c_2__data << 1) + _xperipherals_i2c_2__read_sda();
        }
        else if( _xperipherals_i2c_2__pins == 0b1101 || _xperipherals_i2c_2__pins == 0b1000 ) { // scl->0 sda=X
            if( --_xperipherals_i2c_2__shift >= 0 ) _xperipherals_i2c_2__state = 6;
            else {
                _xperipherals_i2c_2__clear_scl(); // Hold SCL Low
                _xperipherals_i2c_2__read_sda();  // Release SDA
                _xperipherals_i2c_2__state = 0;
                //printstr("READ: "); printhexln(_xperipherals_i2c_2__data);
                return XPERIPHERALS_I2C__STATUS__EVENT_READ;
            }
        }
        else if( _xperipherals_i2c_2__pins == 0b1011 ) { // scl=1 sda->1 --- STOP
            _xperipherals_i2c_2__state = 0;
            return XPERIPHERALS_I2C__STATUS__EVENT_STOP;
        }
        break;

        // Assert ACK/NACK

        case 7:
        if( _xperipherals_i2c_2__pins == 0b1101 || _xperipherals_i2c_2__pins == 0b1000 ) { // scl->0 sda=X
            _xperipherals_i2c_2__clear_scl(); // Hold SCL Low
            _xperipherals_i2c_2__read_sda();  // Release SDA
            _xperipherals_i2c_2__state = 0;
            return XPERIPHERALS_I2C__STATUS__EVENT_ACK;
        }
        else if( _xperipherals_i2c_2__pins == 0b1011 ) { // scl=1 sda->1 --- STOP
            _xperipherals_i2c_2__state = 0;
            return XPERIPHERALS_I2C__STATUS__EVENT_STOP;
        }
        break;
    }
    return XPERIPHERALS_I2C__STATUS__NONE;
}

select xperipherals_i2c_2__continue_io( int& status )
{
    case _xperipherals_i2c_2__port_scl when pinseq(!_xperipherals_i2c_2__scl) :> _xperipherals_i2c_2__scl:

        _xperipherals_i2c_2__pins = ((!_xperipherals_i2c_2__scl)<<3) + (_xperipherals_i2c_2__sda<<2) + (_xperipherals_i2c_2__scl<<1) + _xperipherals_i2c_2__sda;
        if( _xperipherals_i2c_2__scl == 0 ) _xperipherals_i2c_2__read_sda(); // release SDA on every SCL transition to low
        status = _xperipherals_i2c_2__continue_io();
        break;

    case _xperipherals_i2c_2__port_sda when pinseq(!_xperipherals_i2c_2__sda) :> _xperipherals_i2c_2__sda:

        _xperipherals_i2c_2__pins = (_xperipherals_i2c_2__scl<<3) + ((!_xperipherals_i2c_2__sda)<<2) + (_xperipherals_i2c_2__scl<<1) + _xperipherals_i2c_2__sda;
        status = _xperipherals_i2c_2__continue_io();
        break;
}

#endif

#endif

xperipherals_i2c_3.xc

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

#include "xperipherals_i2c.h"

#ifdef XPERIPHERALS_I2C__3

#if XPERIPHERALS_I2C_3__SCL_PORT != XPERIPHERALS_I2C_3__SDA_PORT

    on tile[XPERIPHERALS_I2C_3__TILE_NUMBER] : port _xperipherals_i2c_3__port_scl = XPERIPHERALS_I2C_3__SCL_PORT;
    on tile[XPERIPHERALS_I2C_3__TILE_NUMBER] : port _xperipherals_i2c_3__port_sda = XPERIPHERALS_I2C_3__SDA_PORT;

#else

    on tile[XPERIPHERALS_I2C_3__TILE_NUMBER] : port _xperipherals_i2c_3__port = XPERIPHERALS_I2C_3__SCL_PORT;

    xbyte _xperipherals_i2c_3__shadow = 0;

#endif

#if XPERIPHERALS_I2C_3__BUS_MASTER
timer _xperipherals_i2c_3__timer;
int   _xperipherals_i2c_3__time;
#else
xbyte _xperipherals_i2c_3__scl;
xbyte _xperipherals_i2c_3__sda;
xbyte _xperipherals_i2c_3__pins;
#endif

int   _xperipherals_i2c_3__state;
int   _xperipherals_i2c_3__shift;
xbyte _xperipherals_i2c_3__data;
xbyte _xperipherals_i2c_3__ackflag;

// <TODO> Calulate based on current system clock frequency
#define _XPERIPHERALS_I2C_3__TIME_BASE ((400000 / XPERIPHERALS_I2C_3__BIT_RATE) * 62)

#if XPERIPHERALS_I2C_3__SCL_PORT != XPERIPHERALS_I2C_3__SDA_PORT

    xbyte _xperipherals_i2c_3__read_scl( void )
    {
        unsigned char bit=0;
        #if XPERIPHERALS_I2C_3__ACTIVE_HIGH == TRUE
        _xperipherals_i2c_3__port_scl <: 1;
        #else
        _xperipherals_i2c_3__port_scl :> bit;
        #endif
        return bit;
    }

    xbyte _xperipherals_i2c_3__read_sda( void )
    {
        unsigned char bit=0;
        #if XPERIPHERALS_I2C_3__ACTIVE_HIGH == TRUE
        _xperipherals_i2c_3__port_sda <: 1;
        #else
        _xperipherals_i2c_3__port_sda :> bit;
        #endif
        return bit;
    }

#if XPERIPHERALS_I2C_3__BUS_MASTER
    void  _xperipherals_i2c_3__clear_scl( void ) {_xperipherals_i2c_3__port_scl <: 0;}
    void  _xperipherals_i2c_3__clear_sda( void ) {_xperipherals_i2c_3__port_sda <: 0;}
#else
    xbyte  _xperipherals_i2c_3__clear_scl( void ) {return 0;}
    xbyte  _xperipherals_i2c_3__clear_sda( void ) {return 0;}
#endif

#else

    xbyte _xperipherals_i2c_3__read_scl( void )
    {
        _xperipherals_i2c_3__shadow |= (1 << XPERIPHERALS_I2C_3__SCL_BIT_POS);
        _xperipherals_i2c_3__port <: _xperipherals_i2c_3__shadow;
        return 0;
    }

    xbyte _xperipherals_i2c_3__read_sda( void )
    {
        _xperipherals_i2c_3__shadow |= (1 << XPERIPHERALS_I2C_3__SDA_BIT_POS);
        _xperipherals_i2c_3__port <: _xperipherals_i2c_3__shadow;
        return 0;
    }

    void  _xperipherals_i2c_3__clear_scl( void )
    {
        _xperipherals_i2c_3__shadow &= ~(1 << XPERIPHERALS_I2C_3__SCL_BIT_POS);
        _xperipherals_i2c_3__port <: _xperipherals_i2c_3__shadow;
    }

    void  _xperipherals_i2c_3__clear_sda( void )
    {
        _xperipherals_i2c_3__shadow &= ~(1 << XPERIPHERALS_I2C_3__SDA_BIT_POS);
        _xperipherals_i2c_3__port <: _xperipherals_i2c_3__shadow;
    }

#endif

xbyte xperipherals_i2c_3__get_data( void ) {return _xperipherals_i2c_3__data;}
xbyte xperipherals_i2c_3__get_ackflag( void ) {return _xperipherals_i2c_3__ackflag;}

int xperipherals_i2c_3__start( void )
{
    int status = XPERIPHERALS_I2C__STATUS__NONE;
    xperipherals_i2c_3__begin_start();
    while( TRUE ) {
        select {case xperipherals_i2c_3__continue_io(status);}
        if( status != XPERIPHERALS_I2C__STATUS__NONE ) break;
    }
    return status;
}

int xperipherals_i2c_3__stop( void )
{
    int status = XPERIPHERALS_I2C__STATUS__NONE;
    xperipherals_i2c_3__begin_stop();
    while( TRUE ) {
        select {case xperipherals_i2c_3__continue_io(status);}
        if( status != XPERIPHERALS_I2C__STATUS__NONE ) break;
    }
    return status;
}

int xperipherals_i2c_3__write( xbyte data, xbyte& ack_flag )
{
    int status = XPERIPHERALS_I2C__STATUS__NONE;
    xperipherals_i2c_3__begin_write( data );
    while( TRUE ) {
        select {case xperipherals_i2c_3__continue_io(status);}
        if( status != XPERIPHERALS_I2C__STATUS__NONE ) break;
    }
    ack_flag = _xperipherals_i2c_3__ackflag;
    return status;
}

int xperipherals_i2c_3__read( xbyte& data )
{
    int status = XPERIPHERALS_I2C__STATUS__NONE;
    xperipherals_i2c_3__begin_read();
    while( TRUE ) {
        select {case xperipherals_i2c_3__continue_io(status);}
        if( status != XPERIPHERALS_I2C__STATUS__NONE ) break;
   }
    data = _xperipherals_i2c_3__data;
    return status;
}

int xperipherals_i2c_3__ack( xbyte ack_flag )
{
    int status = XPERIPHERALS_I2C__STATUS__NONE;
    xperipherals_i2c_3__begin_ack( ack_flag );
    while( TRUE ) {
        select {case xperipherals_i2c_3__continue_io(status);}
        if( status != XPERIPHERALS_I2C__STATUS__NONE ) break;
    }
    return status;
}

#if XPERIPHERALS_I2C_3__BUS_MASTER

void xperipherals_i2c_3__initialize( void )
{
    _xperipherals_i2c_3__state = 0;
    _xperipherals_i2c_3__read_scl();
    _xperipherals_i2c_3__read_sda();
    _xperipherals_i2c_3__timer :> _xperipherals_i2c_3__time;
    _xperipherals_i2c_3__timer when timerafter( _xperipherals_i2c_3__time + 10 * _XPERIPHERALS_I2C_3__TIME_BASE ) :> void;
}

void xperipherals_i2c_3__begin_start( void )
{
    _xperipherals_i2c_3__state = 1;
    _xperipherals_i2c_3__timer :> _xperipherals_i2c_3__time;
}

void xperipherals_i2c_3__begin_write( xbyte data )
{
    _xperipherals_i2c_3__data = data;
    _xperipherals_i2c_3__state = 4;
    _xperipherals_i2c_3__shift = 7;
    _xperipherals_i2c_3__timer :> _xperipherals_i2c_3__time;
}

void xperipherals_i2c_3__begin_read( void )
{
    _xperipherals_i2c_3__state = 11;
    _xperipherals_i2c_3__shift = 7;
    _xperipherals_i2c_3__timer :> _xperipherals_i2c_3__time;
}

void xperipherals_i2c_3__begin_ack( xbool ack_flag )
{
    _xperipherals_i2c_3__data = ack_flag != 0;
    _xperipherals_i2c_3__state = 16;
    _xperipherals_i2c_3__timer :> _xperipherals_i2c_3__time;
}

void xperipherals_i2c_3__begin_stop( void )
{
    _xperipherals_i2c_3__state = 20;
    _xperipherals_i2c_3__timer :> _xperipherals_i2c_3__time;
}

int _xperipherals_i2c_3__io_continue( void )
{
    switch( _xperipherals_i2c_3__state )
    {
        // Start Condition
        case 1:
        _xperipherals_i2c_3__clear_sda();
        _xperipherals_i2c_3__state = 2;
        _xperipherals_i2c_3__time += 1 * _XPERIPHERALS_I2C_3__TIME_BASE;
        break;
        case 2:
        _xperipherals_i2c_3__clear_scl();
        _xperipherals_i2c_3__state = 3;
        _xperipherals_i2c_3__time += 1 * _XPERIPHERALS_I2C_3__TIME_BASE;
        break;
        case 3:
        _xperipherals_i2c_3__state = 0;
        return XPERIPHERALS_I2C__STATUS__EVENT_START;
        break;

        // Write Bits 7-0
        case 4:
        if( (_xperipherals_i2c_3__data >> _xperipherals_i2c_3__shift) & 1 ) _xperipherals_i2c_3__read_sda();
        else _xperipherals_i2c_3__clear_sda();
        _xperipherals_i2c_3__shift--;
        _xperipherals_i2c_3__state = 5;
        _xperipherals_i2c_3__time += 1 * _XPERIPHERALS_I2C_3__TIME_BASE;
        break;
        case 5:
        _xperipherals_i2c_3__read_scl();
        _xperipherals_i2c_3__state = 6;
        _xperipherals_i2c_3__time += 2 * _XPERIPHERALS_I2C_3__TIME_BASE;
        break;
        case 6:
        _xperipherals_i2c_3__clear_scl();
        if( _xperipherals_i2c_3__shift < 0 ) {
            _xperipherals_i2c_3__state = 7;
            _xperipherals_i2c_3__time += 2 * _XPERIPHERALS_I2C_3__TIME_BASE;
        }
        else {
            _xperipherals_i2c_3__state = 4;
            _xperipherals_i2c_3__time += 1 * _XPERIPHERALS_I2C_3__TIME_BASE;
        }
        break;

         // Sense ACK/NACK
        case 7:
        _xperipherals_i2c_3__data = _xperipherals_i2c_3__read_sda();
        _xperipherals_i2c_3__state = 8;
        break;
        case 8:
        _xperipherals_i2c_3__read_scl();
        _xperipherals_i2c_3__state = 9;
        _xperipherals_i2c_3__time += 2 * _XPERIPHERALS_I2C_3__TIME_BASE;
        break;
        case 9:
        _xperipherals_i2c_3__clear_scl();
        _xperipherals_i2c_3__state = 10;
        _xperipherals_i2c_3__time += 1 * _XPERIPHERALS_I2C_3__TIME_BASE;
        break;
        case 10:
        _xperipherals_i2c_3__state = 0;
        return XPERIPHERALS_I2C__STATUS__EVENT_WRITE;
        break;

         // Read Bits 7-0
        case 11:
        _xperipherals_i2c_3__read_sda();
        _xperipherals_i2c_3__state = 12;
        _xperipherals_i2c_3__time += 1 * _XPERIPHERALS_I2C_3__TIME_BASE;
        break;
        case 12:
        _xperipherals_i2c_3__read_scl();
        _xperipherals_i2c_3__state = 13;
        _xperipherals_i2c_3__time += 1 * _XPERIPHERALS_I2C_3__TIME_BASE;
        break;
        case 13:
        (_xperipherals_i2c_3__data = _xperipherals_i2c_3__data >> 1) + _xperipherals_i2c_3__read_sda() << (_xperipherals_i2c_3__shift--);
        _xperipherals_i2c_3__state = 14;
        _xperipherals_i2c_3__time += 1 * _XPERIPHERALS_I2C_3__TIME_BASE; break;
        case 14:
        _xperipherals_i2c_3__clear_scl();
        if( _xperipherals_i2c_3__shift < 0 ) _xperipherals_i2c_3__state = 15;
        else _xperipherals_i2c_3__state = 11;
        _xperipherals_i2c_3__time += 1 * _XPERIPHERALS_I2C_3__TIME_BASE;
        break;
        case 15:
        _xperipherals_i2c_3__state = 0;
        return XPERIPHERALS_I2C__STATUS__EVENT_READ;
        break;

        // Assert ACK/NACK
        case 16:
        if( _xperipherals_i2c_3__data ) _xperipherals_i2c_3__read_sda();
        else _xperipherals_i2c_3__clear_sda();
        _xperipherals_i2c_3__state = 17;
        _xperipherals_i2c_3__time += 1 * _XPERIPHERALS_I2C_3__TIME_BASE;
        break;
        case 17: _xperipherals_i2c_3__read_scl();
        _xperipherals_i2c_3__state = 18;
        _xperipherals_i2c_3__time += 2 * _XPERIPHERALS_I2C_3__TIME_BASE;
        break;
        case 18:
        _xperipherals_i2c_3__clear_scl();
        _xperipherals_i2c_3__state = 19;
        _xperipherals_i2c_3__time += 1 * _XPERIPHERALS_I2C_3__TIME_BASE;
        break;
        case 19:
        _xperipherals_i2c_3__state = 0;
        return XPERIPHERALS_I2C__STATUS__EVENT_ACK;
        break;

        // Stop Condition
        case 20: _xperipherals_i2c_3__clear_sda();
        _xperipherals_i2c_3__state = 21;
        _xperipherals_i2c_3__time += 1 * _XPERIPHERALS_I2C_3__TIME_BASE;
        break;
        case 21: _xperipherals_i2c_3__read_scl();
        _xperipherals_i2c_3__state = 22;
        _xperipherals_i2c_3__time += 1 * _XPERIPHERALS_I2C_3__TIME_BASE;
        break;
        case 22: _xperipherals_i2c_3__read_sda();
        _xperipherals_i2c_3__state = 23;
        _xperipherals_i2c_3__time += 2 * _XPERIPHERALS_I2C_3__TIME_BASE;
        break;
        case 23:
        _xperipherals_i2c_3__state = 0;
        return XPERIPHERALS_I2C__STATUS__EVENT_STOP;
        break;

    }
    return XPERIPHERALS_I2C__STATUS__NONE;
}

select xperipherals_i2c_3__continue_io( int& status )
{
    case _xperipherals_i2c_3__state > 0 => _xperipherals_i2c_3__timer when timerafter(_xperipherals_i2c_3__time) :> _xperipherals_i2c_3__time:
    status = _xperipherals_i2c_3__io_continue();
    break;
}

#else

void xperipherals_i2c_3__initialize( void )
{
    _xperipherals_i2c_3__state = 0;
}

void xperipherals_i2c_3__begin_start( void )
{
    while( TRUE )
    {
        _xperipherals_i2c_3__scl = _xperipherals_i2c_3__read_scl();
        _xperipherals_i2c_3__sda = _xperipherals_i2c_3__read_sda();
        if( _xperipherals_i2c_3__scl && _xperipherals_i2c_3__sda ) break;
    }
    _xperipherals_i2c_3__pins = 0b1111;
    _xperipherals_i2c_3__state = 1;
}

void xperipherals_i2c_3__begin_stop( void )
{
    _xperipherals_i2c_3__state = 1;
    _xperipherals_i2c_3__read_sda(); // Release SDA - allow posbbile resulting SDA change while SCL is low
    _xperipherals_i2c_3__read_scl(); // Release SCL
    _xperipherals_i2c_3__sda = _xperipherals_i2c_3__read_sda(); // Get current state
}

void xperipherals_i2c_3__begin_write( xbyte data )
{
    _xperipherals_i2c_3__data = data;
    _xperipherals_i2c_3__shift = 6;
    _xperipherals_i2c_3__state = 3;
    // Write first bit - SDA changes while SCL is low
    if( (_xperipherals_i2c_3__data >> 7) & 1 ) _xperipherals_i2c_3__sda = _xperipherals_i2c_3__read_sda();
    else _xperipherals_i2c_3__sda = _xperipherals_i2c_3__clear_sda();
    _xperipherals_i2c_3__scl = _xperipherals_i2c_3__read_scl(); // Release SCL, get current state
    _xperipherals_i2c_3__sda = _xperipherals_i2c_3__read_sda(); // Get current state
}

void xperipherals_i2c_3__begin_read()
{
    _xperipherals_i2c_3__state = 6;
    _xperipherals_i2c_3__shift = 7;
    _xperipherals_i2c_3__read_sda(); // Release SDA - allow posbbile resulting SDA change while SCL is low
    _xperipherals_i2c_3__scl = _xperipherals_i2c_3__read_scl(); // Release SCL, get current state
    _xperipherals_i2c_3__sda = _xperipherals_i2c_3__read_sda(); // Get current state
}

void xperipherals_i2c_3__begin_ack( xbool ack_flag )
{
    _xperipherals_i2c_3__data = ack_flag;
    _xperipherals_i2c_3__state = 7;
    // Write bit - SDA changes while SCL is low
    if( _xperipherals_i2c_3__data ) _xperipherals_i2c_3__sda = _xperipherals_i2c_3__read_sda();
    else _xperipherals_i2c_3__sda = _xperipherals_i2c_3__clear_sda();
    _xperipherals_i2c_3__scl = _xperipherals_i2c_3__read_scl(); // Release SCL, get current state
    _xperipherals_i2c_3__sda = _xperipherals_i2c_3__read_sda(); // Get current state
}

void xperipherals_i2c_3__end( void )
{
    _xperipherals_i2c_3__scl = _xperipherals_i2c_3__read_scl(); // Release SCL, get current state
    _xperipherals_i2c_3__sda = _xperipherals_i2c_3__read_sda(); // Get current state
    _xperipherals_i2c_3__state = 0;
}

int _xperipherals_i2c_3__continue_io( void )
{
    switch( _xperipherals_i2c_3__state )
    {
        // Wait for start/stop Condition

        case 1:

        if( _xperipherals_i2c_3__pins == 0b1110 ) { // scl=1 sda->0 --- START
            _xperipherals_i2c_3__state = 2;
        }
        else if( _xperipherals_i2c_3__pins == 0b1011 ) { // scl=1 sda->1 --- STOP
            _xperipherals_i2c_3__state = 0;
            return XPERIPHERALS_I2C__STATUS__EVENT_STOP;
        }
        break;

        case 2:
        if( _xperipherals_i2c_3__pins == 0b1101 || _xperipherals_i2c_3__pins == 0b1000 ) { // scl->0 sda=X
            _xperipherals_i2c_3__clear_scl(); // Hold SCL Low
            _xperipherals_i2c_3__read_sda();  // Release SDA
            _xperipherals_i2c_3__state = 0;
            return XPERIPHERALS_I2C__STATUS__EVENT_START;
        }
        break;

        // Write Bits 6-0

        case 3:
        if( _xperipherals_i2c_3__pins == 0b1101 || _xperipherals_i2c_3__pins == 0b1000 ) { // scl->0 sda=X
            if( (_xperipherals_i2c_3__data >> _xperipherals_i2c_3__shift) & 1 ) _xperipherals_i2c_3__sda = _xperipherals_i2c_3__read_sda();
            else _xperipherals_i2c_3__sda = _xperipherals_i2c_3__clear_sda();
            if( --_xperipherals_i2c_3__shift < 0 ) _xperipherals_i2c_3__state = 4;
            else _xperipherals_i2c_3__state = 3;
        }
        else if( _xperipherals_i2c_3__pins == 0b1011 ) { // scl=1 sda->1 --- STOP
            _xperipherals_i2c_3__state = 0;
            return XPERIPHERALS_I2C__STATUS__EVENT_STOP;
        }
        break;

         // Sense ACK/NACK

        case 4:
        if( _xperipherals_i2c_3__pins == 0b1101 || _xperipherals_i2c_3__pins == 0b1000 ) { // scl->0 sda=X
            _xperipherals_i2c_3__state = 5;
        }
        break;
        case 5:
        if( _xperipherals_i2c_3__pins == 0b0111 || _xperipherals_i2c_3__pins == 0b0010 ) { // scl->1 sda=X
            _xperipherals_i2c_3__ackflag = _xperipherals_i2c_3__read_sda();
        }
        if( _xperipherals_i2c_3__pins == 0b1101 || _xperipherals_i2c_3__pins == 0b1000 ) { // scl->0 sda=X
            _xperipherals_i2c_3__clear_scl(); // Hold SCL Low
            _xperipherals_i2c_3__read_sda();  // Release SDA
            _xperipherals_i2c_3__state = 0;
            return XPERIPHERALS_I2C__STATUS__EVENT_WRITE;
        }
        break;

        // Read Bits 7-0

        case 6:
        if( _xperipherals_i2c_3__pins == 0b0111 || _xperipherals_i2c_3__pins == 0b0010 ) { // scl->1 sda=X
            _xperipherals_i2c_3__data = (_xperipherals_i2c_3__data << 1) + _xperipherals_i2c_3__read_sda();
        }
        else if( _xperipherals_i2c_3__pins == 0b1101 || _xperipherals_i2c_3__pins == 0b1000 ) { // scl->0 sda=X
            if( --_xperipherals_i2c_3__shift >= 0 ) _xperipherals_i2c_3__state = 6;
            else {
                _xperipherals_i2c_3__clear_scl(); // Hold SCL Low
                _xperipherals_i2c_3__read_sda();  // Release SDA
                _xperipherals_i2c_3__state = 0;
                //printstr("READ: "); printhexln(_xperipherals_i2c_3__data);
                return XPERIPHERALS_I2C__STATUS__EVENT_READ;
            }
        }
        else if( _xperipherals_i2c_3__pins == 0b1011 ) { // scl=1 sda->1 --- STOP
            _xperipherals_i2c_3__state = 0;
            return XPERIPHERALS_I2C__STATUS__EVENT_STOP;
        }
        break;

        // Assert ACK/NACK

        case 7:
        if( _xperipherals_i2c_3__pins == 0b1101 || _xperipherals_i2c_3__pins == 0b1000 ) { // scl->0 sda=X
            _xperipherals_i2c_3__clear_scl(); // Hold SCL Low
            _xperipherals_i2c_3__read_sda();  // Release SDA
            _xperipherals_i2c_3__state = 0;
            return XPERIPHERALS_I2C__STATUS__EVENT_ACK;
        }
        else if( _xperipherals_i2c_3__pins == 0b1011 ) { // scl=1 sda->1 --- STOP
            _xperipherals_i2c_3__state = 0;
            return XPERIPHERALS_I2C__STATUS__EVENT_STOP;
        }
        break;
    }
    return XPERIPHERALS_I2C__STATUS__NONE;
}

select xperipherals_i2c_3__continue_io( int& status )
{
    case _xperipherals_i2c_3__port_scl when pinseq(!_xperipherals_i2c_3__scl) :> _xperipherals_i2c_3__scl:

        _xperipherals_i2c_3__pins = ((!_xperipherals_i2c_3__scl)<<3) + (_xperipherals_i2c_3__sda<<2) + (_xperipherals_i2c_3__scl<<1) + _xperipherals_i2c_3__sda;
        if( _xperipherals_i2c_3__scl == 0 ) _xperipherals_i2c_3__read_sda(); // release SDA on every SCL transition to low
        status = _xperipherals_i2c_3__io_continue();
        break;

    case _xperipherals_i2c_3__port_sda when pinseq(!_xperipherals_i2c_3__sda) :> _xperipherals_i2c_3__sda:

        _xperipherals_i2c_3__pins = (_xperipherals_i2c_3__scl<<3) + ((!_xperipherals_i2c_3__sda)<<2) + (_xperipherals_i2c_3__scl<<1) + _xperipherals_i2c_3__sda;
        status = _xperipherals_i2c_3__io_continue();
        break;
}

#endif

#endif