Home : I/O Peripherals Library | I2S/TDM Peripheral

Description

<TODO>

Naming Conventions

<TODO>

Interface Functions

<TODO>

Example Usage

<TODO>

Configuration

<TODO>

Source Files

xperipherals_i2s.h I2S peripheral interface
xperipherals_i2s_1.xc I2S peripheral #1 implementation
xperipherals_i2s_2.xc I2S peripheral #2 implementation
xperipherals_i2s_3.xc I2S peripheral #3 implementation

Source Listings

xperipherals_i2s.h

#ifndef XPERIPHERALS_I2S__INCLUDED
#define XPERIPHERALS_I2S__INCLUDED

#include "xsystem_types.h"
#include <xs1.h>

// These must be defined in "xconfig.h" for each peripheral bus being used
//
// XPERIPHERALS_I2S_n                   No value
// XPERIPHERALS_I2S_n__BUS_MASTER       TRUE or FALSE
// XPERIPHERALS_I2S_n__MCLK_IS_BCLK     TRUE or FALSE
// XPERIPHERALS_I2S_n__SLOT_COUNT       Words per audio cycle, (2 for stereo)
// XPERIPHERALS_I2S_n__SYNC_FORMAT      0 for PCM, 1 for I2S, 2 for TDM
// XPERIPHERALS_I2S_n__DAC_WIRE_COUNT   Number of SDOUT lines, positive non-zero integer
// XPERIPHERALS_I2S_n__DAC_WORD_SIZE    Bits per word/slot (usually 32)
// XPERIPHERALS_I2S_n__DAC_WORD_JUST    Data justification within slot, 0 for left, 1 for right
// XPERIPHERALS_I2S_n__ADC_WIRE_COUNT   Number of SDOUT lines, positive non-zero integer
// XPERIPHERALS_I2S_n__ADC_WORD_SIZE    Bits per word/slot (usually 32)
// XPERIPHERALS_I2S_n__ADC_WORD_JUST    Data justification within slot, 0 for left, 1 for right
// XPERIPHERALS_I2S_n__TILE_NUMBER      Integer, XS1 tile number
// XPERIPHERALS_I2S_n__BIT_CLOCK        XS1 clock-block identifier
// XPERIPHERALS_I2S_n__BCLK_PORT        XS1 port identifier
// XPERIPHERALS_I2S_n__WCLK_PORT        XS1 port identifier
// XPERIPHERALS_I2S_n__DAC0_PORT        XS1 port identifier
// XPERIPHERALS_I2S_n__DAC1_PORT        XS1 port identifier
// XPERIPHERALS_I2S_n__DAC2_PORT        XS1 port identifier
// XPERIPHERALS_I2S_n__DAC3_PORT        XS1 port identifier
// XPERIPHERALS_I2S_n__ADC0_PORT        XS1 port identifier
// XPERIPHERALS_I2S_n__ADC1_PORT        XS1 port identifier
// XPERIPHERALS_I2S_n__ADC2_PORT        XS1 port identifier
// XPERIPHERALS_I2S_n__ADC3_PORT        XS1 port identifier

// Data transfer sequence for an audio cycle consisisting of N slots, X DAC wires, Y ADC wires:
//
//   transfer( output for slot 0 on DAC wire 1, value ref for slot 0 on ADC wire 1 )
//   transfer( output for slot 0 on DAC wire 2, value ref for slot 0 on ADC wire 2 )
//   transfer( output for slot 0 on DAC wire 3, value ref for slot 0 on ADC wire 3 )
//   transfer( output for slot 0 on DAC wire 4, value ref for slot 0 on ADC wire 4 )
//   ...
//   transfer( output for slot N-1 on DAC wire 1, value ref for slot N-1 on ADC wire 1 )
//   transfer( output for slot N-1 on DAC wire 2, value ref for slot N-1 on ADC wire 2 )
//   transfer( output for slot N-1 on DAC wire 3, value ref for slot N-1 on ADC wire 3 )
//   transfer( output for slot N-1 on DAC wire 4, value ref for slot N-1 on ADC wire 4 )
//
// Notes: 1) Supply a dummy output value for the DAC sample if the DAC wire does not exist
//           and the ADC wire does exist.
//        2) Supply a dummy input ref for the ADC sample if the ADC wire does not exist
//           and the DAC wire does exist.
//        3) Skip the transfer all-together for wires in which neither ADC or DAC wire exist.
//
// Important: The 'synchronize' function MUST be called just before the first 'transfer'
//            after a 'configuration' to sycnrhonize the BCLK, WCLK, SDOUT and SDIN ports.

#define XPERIPHERALS_I2S__INTERFACE( N ) \
\
void xperipherals_i2s_##N##__initialize  ( void ); \
void xperipherals_i2s_##N##__configure   ( clock bit_clock ); \
void xperipherals_i2s_##N##__synchronize ( xbool bclk_is_active ); \
void xperipherals_i2s_##N##__transfer_beg( void ); \
void xperipherals_i2s_##N##__transfer_dac( xsint  sample ); \
void xperipherals_i2s_##N##__transfer_adc( xsint& sample ); \
void xperipherals_i2s_##N##__transfer_end( void );

XPERIPHERALS_I2S__INTERFACE( 1 )
XPERIPHERALS_I2S__INTERFACE( 2 )
XPERIPHERALS_I2S__INTERFACE( 3 )

#endif

xperipherals_i2s_1.xc

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

#include "xperipherals_i2s.h"

#ifdef XPERIPHERALS_I2S_1

extern clock XPERIPHERALS_I2S_1__CLOCK_NAME;

#if XPERIPHERALS_I2S_1__DAC_WIRE_COUNT >= XPERIPHERALS_I2S_1__ADC_WIRE_COUNT
#define XPERIPHERALS_I2S_1__WIRE_COUNT XPERIPHERALS_I2S_1__DAC_WIRE_COUNT
#else
#define XPERIPHERALS_I2S_1__WIRE_COUNT XPERIPHERALS_I2S_1__ADC_WIRE_COUNT
#endif

#if XPERIPHERALS_I2S_1__BUS_MASTER
    //on tile[XPERIPHERALS_I2S_1__TILE_NUMBER] :
    out buffered port:32 _xperipherals_i2s_1__port_wclk = XPERIPHERALS_I2S_1__WCLK_PORT;
#else
    //on tile[XPERIPHERALS_I2S_1__TILE_NUMBER] :
    in port _xperipherals_i2s_1__port_wclk = XPERIPHERALS_I2S_1__WCLK_PORT;
#endif

#if XPERIPHERALS_I2S_1__DAC_WIRE_COUNT > 0
    //on tile[XPERIPHERALS_I2S_1__TILE_NUMBER] :
    out buffered port:32 _xperipherals_i2s_1__port_dac[XPERIPHERALS_I2S_1__DAC_WIRE_COUNT] = {
        #if XPERIPHERALS_I2S_1__DAC_WIRE_COUNT == 1
            XPERIPHERALS_I2S_1__DAC0_PORT
        #elif XPERIPHERALS_I2S_1__DAC_WIRE_COUNT == 2
            XPERIPHERALS_I2S_1__DAC0_PORT, XPERIPHERALS_I2S_1__DAC1_PORT
        #elif XPERIPHERALS_I2S_1__DAC_WIRE_COUNT == 3
            XPERIPHERALS_I2S_1__DAC0_PORT, XPERIPHERALS_I2S_1__DAC1_PORT, XPERIPHERALS_I2S_1__DAC2_PORT
        #elif XPERIPHERALS_I2S_1__DAC_WIRE_COUNT == 4
            XPERIPHERALS_I2S_1__DAC0_PORT, XPERIPHERALS_I2S_1__DAC1_PORT, XPERIPHERALS_I2S_1__DAC2_PORT,
            XPERIPHERALS_I2S_1__DAC3_PORT
        #endif
    };
#endif

#if XPERIPHERALS_I2S_1__ADC_WIRE_COUNT > 0
    //on tile[XPERIPHERALS_I2S_1__TILE_NUMBER] :
    in buffered port:32 _xperipherals_i2s_1__port_adc[XPERIPHERALS_I2S_1__ADC_WIRE_COUNT] = {
        #if XPERIPHERALS_I2S_1__ADC_WIRE_COUNT == 1
            XPERIPHERALS_I2S_1__ADC0_PORT
        #elif XPERIPHERALS_I2S_1__ADC_WIRE_COUNT == 2
            XPERIPHERALS_I2S_1__ADC0_PORT, XPERIPHERALS_I2S_1__ADC1_PORT
        #elif XPERIPHERALS_I2S_1__ADC_WIRE_COUNT == 3
            XPERIPHERALS_I2S_1__ADC0_PORT, XPERIPHERALS_I2S_1__ADC1_PORT, XPERIPHERALS_I2S_1__ADC2_PORT
        #elif XPERIPHERALS_I2S_1__ADC_WIRE_COUNT == 4
            XPERIPHERALS_I2S_1__ADC0_PORT, XPERIPHERALS_I2S_1__ADC1_PORT, XPERIPHERALS_I2S_1__ADC2_PORT,
            XPERIPHERALS_I2S_1__ADC3_PORT
        #endif
    };
#endif

xuint _xperipherals_i2s_1__sync_word[XPERIPHERALS_I2S_1__SLOT_COUNT];
xuint _xperipherals_i2s_1__slot_index;
xuint _xperipherals_i2s_1__dac_index;
xuint _xperipherals_i2s_1__adc_index;

void xperipherals_i2s_1__initialize( void )
{
    for( int i = 0; i < XPERIPHERALS_I2S_1__SLOT_COUNT; ++i ) {

        #if XPERIPHERALS_I2S_1__SYNC_FORMAT == 0 // PCM

            if( i == 0 ) _xperipherals_i2s_1__sync_word[i] = 0xFFFFFFFF;
            else if( i < XPERIPHERALS_I2S_1__SLOT_COUNT-1 ) _xperipherals_i2s_1__sync_word[i] = 0;
            else _xperipherals_i2s_1__sync_word[i] = 0;

        #elif XPERIPHERALS_I2S_1__SYNC_FORMAT == 1 // I2S

            if( i == 0 ) _xperipherals_i2s_1__sync_word[i] = 0x80000000;
            else if( i < XPERIPHERALS_I2S_1__SLOT_COUNT-1 ) _xperipherals_i2s_1__sync_word[i] = 0;
            else _xperipherals_i2s_1__sync_word[i] = 0x7FFFFFFF;

        #elif XPERIPHERALS_I2S_1__SYNC_FORMAT == 2 // TDM

            if( i == 0 ) _xperipherals_i2s_1__sync_word[i] = 0;
            else if( i < XPERIPHERALS_I2S_1__SLOT_COUNT-1 ) _xperipherals_i2s_1__sync_word[i] = 0;
            else _xperipherals_i2s_1__sync_word[i] = 0x80000000;

        #endif
    }
    _xperipherals_i2s_1__slot_index = 0;
    _xperipherals_i2s_1__dac_index = 0;
    _xperipherals_i2s_1__adc_index = 0;
}

void xperipherals_i2s_1__configure( clock bit_clock )
{
    #if XPERIPHERALS_I2S_1__BUS_MASTER
        configure_out_port_no_ready( _xperipherals_i2s_1__port_wclk, bit_clock, 0 );
    #else
        configure_in_port_no_ready( _xperipherals_i2s_1__port_wclk, bit_clock );
    #endif

    #if XPERIPHERALS_I2S_1__DAC_WIRE_COUNT > 0
        for( int i = 0; i < XPERIPHERALS_I2S_1__DAC_WIRE_COUNT; ++i ) {
            configure_out_port_no_ready( _xperipherals_i2s_1__port_dac[i], bit_clock, 0 );
        }
    #endif
    #if XPERIPHERALS_I2S_1__ADC_WIRE_COUNT > 0
        for( int i = 0; i < XPERIPHERALS_I2S_1__ADC_WIRE_COUNT; ++i ) {
            configure_in_port_no_ready( _xperipherals_i2s_1__port_adc[i], bit_clock );
        }
    #endif
    _xperipherals_i2s_1__slot_index = 0;
    _xperipherals_i2s_1__dac_index = 0;
    _xperipherals_i2s_1__adc_index = 0;
}

void xperipherals_i2s_1__synchronize( xbool bclk_is_active )
{
    // TODO/FIXME: Sync on port output completion if ports have been active already?

    //if( bclk_is_active )
    //{
    //    stop_clock( clk_audio_bclk );
    //    configure_clock_src( clk_audio_bclk, p_bclk );
    //    start_clock( clk_audio_bclk );
    //}

    clearbuf( _xperipherals_i2s_1__port_wclk );
    for( int i=0; i < XPERIPHERALS_I2S_1__DAC_WIRE_COUNT; ++i ) clearbuf(_xperipherals_i2s_1__port_dac[i]);
    for( int i=0; i < XPERIPHERALS_I2S_1__ADC_WIRE_COUNT; ++i ) clearbuf(_xperipherals_i2s_1__port_adc[i]);

    #if XPERIPHERALS_I2S_1__BUS_MASTER
    {
        if( !bclk_is_active )
        {
            _xperipherals_i2s_1__port_wclk <: 0;
            #pragma loop unroll
            #if XPERIPHERALS_I2S_1__DAC_WIRE_COUNT > 0
            for( int i=0; i < XPERIPHERALS_I2S_1__DAC_WIRE_COUNT; ++i )
                _xperipherals_i2s_1__port_dac[i] <: 0;
            #endif
        }
        else
        {
            unsigned int time;
            _xperipherals_i2s_1__port_wclk <: 0 @ time;
            _xperipherals_i2s_1__port_wclk @ (time+32) <: 0;
            #if XPERIPHERALS_I2S_1__DAC_WIRE_COUNT > 0
            #pragma loop unroll
            for( int i=0; i < XPERIPHERALS_I2S_1__DAC_WIRE_COUNT; ++i )
                _xperipherals_i2s_1__port_dac[i] @ (time+32) <: 0;
            #endif
            #if XPERIPHERALS_I2S_1__ADC_WIRE_COUNT > 0
            #pragma loop unroll
            for( int i=0; i < XPERIPHERALS_I2S_1__ADC_WIRE_COUNT; ++i )
                //asm("setpt res[%0], %1"::"r"(_xperipherals_i2s_1__port_adc[i]),"r"(time+31));
                asm("setpt res[%0], %1"::"r"(_xperipherals_i2s_1__port_adc[i]),"r"(time+31));
            #endif
        }
    }
    #else
    {
        unsigned int time;
        #if I2S_TDM_2__SYNC_FORMAT == 0 // PCM
            _xperipherals_i2s_1__port_wclk when pinseq(0) :> void;
            _xperipherals_i2s_1__port_wclk when pinseq(1) :> void @ time; time += 63;
        #elif I2S_TDM_2__SYNC_FORMAT == 1 // I2S
            _xperipherals_i2s_1__port_wclk when pinseq(1) :> void;
            _xperipherals_i2s_1__port_wclk when pinseq(0) :> void @ time; time += 64;
        #elif I2S_TDM_2__SYNC_FORMAT == 2 // TDM
            _xperipherals_i2s_1__port_wclk when pinseq(1) :> void;
            _xperipherals_i2s_1__port_wclk when pinseq(0) :> void @ time; time += 63;
        #endif

        #if XPERIPHERALS_I2S_1__DAC_WIRE_COUNT > 0
        #pragma loop unroll
        for( int i=0; i < XPERIPHERALS_I2S_1__DAC_WIRE_COUNT; ++i )
            _xperipherals_i2s_1__port_dac[i] @ (time) <: 0;
        #endif
        #if XPERIPHERALS_I2S_1__ADC_WIRE_COUNT > 0
        #pragma loop unroll
        for( int i=0; i < XPERIPHERALS_I2S_1__ADC_WIRE_COUNT; ++i )
            asm("setpt res[%0], %1"::"r"(_xperipherals_i2s_1__port_adc[i]),"r"(time+31));
        #endif

        /*
        configure_in_port_no_ready( p_lrclk, clk_audio_bclk );
        #if I2S_TDM__DAC_WIRE_COUNT > 0
            for( int i = 0; i < I2S_TDM__DAC_WIRE_COUNT; ++i )
                configure_out_port_no_ready( p_i2s_dac[i], clk_audio_bclk, 0 );
        #endif
        #if I2S_TDM__ADC_WIRE_COUNT > 0
            for( int i = 0; i < I2S_TDM__ADC_WIRE_COUNT; ++i )
                configure_in_port_no_ready( p_i2s_adc[i], clk_audio_bclk );
        #endif

        stop_clock( clk_audio_bclk );
        configure_clock_src( clk_audio_bclk, p_bclk );
        start_clock( clk_audio_bclk );

        //p_bclk <: 0x80000000;
        //sync(p_bclk);
        clearbuf( p_bclk );
        clearbuf( p_lrclk );
        for( int i = 0; i < I2S_TDM__DAC_WIRE_COUNT; ++i ) clearbuf( p_i2s_dac[i] );
        for( int i = 0; i < I2S_TDM__ADC_WIRE_COUNT; ++i ) clearbuf( p_i2s_adc[i] );

        int time;

        #if I2S_TDM__SYNC_FORMAT == 0 // PCM
            p_lrclk when pinseq(0) :> void;
            p_lrclk when pinseq(1) :> void @ time; time += 63;
        #elif I2S_TDM__SYNC_FORMAT == 1 // I2S
            p_lrclk when pinseq(1) :> void;
            p_lrclk when pinseq(0) :> void @ time; time += 64;
        #elif I2S_TDM__SYNC_FORMAT == 2 // TDM
            p_lrclk when pinseq(1) :> void;
            p_lrclk when pinseq(0) :> void @ time; time += 63;
        #endif
        for( int i=0; i < I2S_TDM__DAC_WIRE_COUNT; ++i )
            p_i2s_dac[i] @ (time+1) <: 0xFFFFFFFF;
        for( int i=0; i < I2S_TDM__ADC_WIRE_COUNT; ++i )
            asm("setpt res[%0], %1"::"r"(p_i2s_adc[i]),"r"(time));
        */
    }
    #endif
}

void xperipherals_i2s_1__transfer_beg( void )
{
    #if XPERIPHERALS_I2S_1__BUS_MASTER
    _xperipherals_i2s_1__port_wclk <: _xperipherals_i2s_1__sync_word[_xperipherals_i2s_1__slot_index];
    #endif
    _xperipherals_i2s_1__dac_index = _xperipherals_i2s_1__adc_index = 0;
}

void xperipherals_i2s_1__transfer_dac( xsint dac_sample )
{
    xuint sample = dac_sample;
    #if XPERIPHERALS_I2S_1__DAC_WORD_SIZE == 32
        sample = bitrev( sample );
    #elif XPERIPHERALS_I2S_1__DAC_WORD_SIZE == 24
        #if XPERIPHERALS_I2S_1__DAC_WORD_JUST == 0 // left
            sample = bitrev( sample & 0xFFFFFF00 );
        #elif XPERIPHERALS_I2S_1__DAC_WORD_JUST == 1 // right
            sample = bitrev( sample >> 8 );
        #endif
    #elif XPERIPHERALS_I2S_1__DAC_WORD_SIZE == 16
        #if XPERIPHERALS_I2S_1__DAC_WORD_JUST == 0 // left
            sample = bitrev( sample & 0xFFFF0000 );
        #elif XPERIPHERALS_I2S_1__DAC_WORD_JUST == 1 // right
            sample = bitrev( sample >> 16 );
        #endif
    #endif
    _xperipherals_i2s_1__port_dac[_xperipherals_i2s_1__dac_index++] <: sample;
}

void xperipherals_i2s_1__transfer_adc( xsint& adc_sample )
{
    xuint sample;
    _xperipherals_i2s_1__port_adc[_xperipherals_i2s_1__adc_index++] :> sample;
    #if XPERIPHERALS_I2S_1__ADC_WORD_SIZE == 32
        sample = bitrev( sample );
    #elif XPERIPHERALS_I2S_1__ADC_WORD_SIZE == 24
        #if XPERIPHERALS_I2S_1__ADC_WORD_JUST == 0 // left
            sample = bitrev( sample ) & 0xFFFFFF00;
        #elif XPERIPHERALS_I2S_1__ADC_WORD_JUST == 1 // right
            sample = bitrev( sample ) << 8;
        #endif
    #elif XPERIPHERALS_I2S_1__ADC_WORD_SIZE == 16
        #if XPERIPHERALS_I2S_1__ADC_WORD_JUST == 0 // left
            sample = bitrev( sample ) & 0xFFFF0000;
        #elif XPERIPHERALS_I2S_1__ADC_WORD_JUST == 1 // right
            sample = bitrev( sample ) << 16;
        #endif
    #endif
    adc_sample = sample;
}

void xperipherals_i2s_1__transfer_end( void )
{
    if( ++_xperipherals_i2s_1__slot_index == XPERIPHERALS_I2S_1__SLOT_COUNT ) {
        _xperipherals_i2s_1__slot_index = 0;
    }
}

#endif

xperipherals_i2s_2.xc

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

#include "xperipherals_i2s.h"

#ifdef XPERIPHERALS_I2S_2

extern clock XPERIPHERALS_I2S_2__CLOCK_NAME;

#if XPERIPHERALS_I2S_2__DAC_WIRE_COUNT >= XPERIPHERALS_I2S_2__ADC_WIRE_COUNT
#define XPERIPHERALS_I2S_2__WIRE_COUNT XPERIPHERALS_I2S_2__DAC_WIRE_COUNT
#else
#define XPERIPHERALS_I2S_2__WIRE_COUNT XPERIPHERALS_I2S_2__ADC_WIRE_COUNT
#endif

#if XPERIPHERALS_I2S_2__BUS_MASTER
    on tile[XPERIPHERALS_I2S_2__TILE_NUMBER] :
    out buffered port:32 _xperipherals_i2s_2__port_wclk = XPERIPHERALS_I2S_2__WCLK_PORT;
#else
    on tile[XPERIPHERALS_I2S_2__TILE_NUMBER] :
    in port _xperipherals_i2s_2__port_wclk = XPERIPHERALS_I2S_2__WCLK_PORT;
#endif

#if XPERIPHERALS_I2S_2__DAC_WIRE_COUNT > 0
    on tile[XPERIPHERALS_I2S_2__TILE_NUMBER] :
    out buffered port:32 _xperipherals_i2s_2__port_dac[XPERIPHERALS_I2S_2__DAC_WIRE_COUNT] = {
        #if   XPERIPHERALS_I2S_2__DAC_WIRE_COUNT == 1
        XPERIPHERALS_I2S_2__DAC0_PORT
        #elif XPERIPHERALS_I2S_2__DAC_WIRE_COUNT == 2
        XPERIPHERALS_I2S_2__DAC0_PORT, XPERIPHERALS_I2S_2__DAC1_PORT
        #elif XPERIPHERALS_I2S_2__DAC_WIRE_COUNT == 3
        XPERIPHERALS_I2S_2__DAC0_PORT, XPERIPHERALS_I2S_2__DAC1_PORT, XPERIPHERALS_I2S_2__DAC2_PORT
        #elif XPERIPHERALS_I2S_2__DAC_WIRE_COUNT == 4
        XPERIPHERALS_I2S_2__DAC0_PORT, XPERIPHERALS_I2S_2__DAC1_PORT, XPERIPHERALS_I2S_2__DAC2_PORT,
        XPERIPHERALS_I2S_2__DAC3_PORT
        #endif
};
#endif

#if XPERIPHERALS_I2S_2__ADC_WIRE_COUNT > 0
    on tile[XPERIPHERALS_I2S_2__TILE_NUMBER] :
    in buffered port:32 _xperipherals_i2s_2__port_adc[XPERIPHERALS_I2S_2__ADC_WIRE_COUNT] = {
        #if XPERIPHERALS_I2S_2__ADC_WIRE_COUNT == 1
        XPERIPHERALS_I2S_2__ADC0_PORT
        #elif XPERIPHERALS_I2S_2__ADC_WIRE_COUNT == 2
        XPERIPHERALS_I2S_2__ADC0_PORT, XPERIPHERALS_I2S_2__ADC1_PORT
        #elif XPERIPHERALS_I2S_2__ADC_WIRE_COUNT == 3
        XPERIPHERALS_I2S_2__ADC0_PORT, XPERIPHERALS_I2S_2__ADC1_PORT, XPERIPHERALS_I2S_2__ADC2_PORT
        #elif XPERIPHERALS_I2S_2__ADC_WIRE_COUNT == 4
        XPERIPHERALS_I2S_2__ADC0_PORT, XPERIPHERALS_I2S_2__ADC1_PORT, XPERIPHERALS_I2S_2__ADC2_PORT,
        XPERIPHERALS_I2S_2__ADC3_PORT
        #endif
};
#endif

static xuint _xperipherals_i2s_2__sync_word[XPERIPHERALS_I2S_2__SLOT_COUNT];

void xperipherals_i2s_2__initialize( void )
{
    for( int i = 0; i < XPERIPHERALS_I2S_2__SLOT_COUNT; ++i ) {

        #if XPERIPHERALS_I2S_2__SYNC_FORMAT == 0 // PCM

            if( i == 0 ) _xperipherals_i2s_2__sync_word[i] = 0xFFFFFFFF;
            else if( i < XPERIPHERALS_I2S_2__SLOT_COUNT-1 ) _xperipherals_i2s_2__sync_word[i] = 0;
            else _xperipherals_i2s_2__sync_word[i] = 0;

        #elif XPERIPHERALS_I2S_2__SYNC_FORMAT == 1 // I2S

            if( i == 0 ) _xperipherals_i2s_2__sync_word[i] = 0x80000000;
            else if( i < XPERIPHERALS_I2S_2__SLOT_COUNT-1 ) _xperipherals_i2s_2__sync_word[i] = 0;
            else _xperipherals_i2s_2__sync_word[i] = 0x7FFFFFFF;

        #elif XPERIPHERALS_I2S_2__SYNC_FORMAT == 2 // TDM

            if( i == 0 ) _xperipherals_i2s_2__sync_word[i] = 0;
            else if( i < XPERIPHERALS_I2S_2__SLOT_COUNT-1 ) _xperipherals_i2s_2__sync_word[i] = 0;
            else _xperipherals_i2s_2__sync_word[i] = 0x80000000;

        #endif
    }
}

void xperipherals_i2s_2__configure( clock bit_clock )
{
    #if XPERIPHERALS_I2S_2__BUS_MASTER
    configure_out_port_no_ready( _xperipherals_i2s_2__port_wclk, bit_clock, 0 );
    #else
    configure_in_port_no_ready( _xperipherals_i2s_2__port_wclk, bit_clock );
    #endif

    #if XPERIPHERALS_I2S_2__DAC_WIRE_COUNT > 0
        for( int i = 0; i < XPERIPHERALS_I2S_2__DAC_WIRE_COUNT; ++i ) {
            configure_out_port_no_ready( _xperipherals_i2s_2__port_dac[i], bit_clock, 0 );
        }
    #endif
    #if XPERIPHERALS_I2S_2__ADC_WIRE_COUNT > 0
        for( int i = 0; i < XPERIPHERALS_I2S_2__ADC_WIRE_COUNT; ++i ) {
            configure_in_port_no_ready( _xperipherals_i2s_2__port_adc[i], bit_clock );
        }
    #endif
}

static inline xuint _xperipherals_i2s_2__pack_dac_sample( xuint sample )
{
    #if XPERIPHERALS_I2S_2__DAC_WORD_SIZE == 32
        return bitrev( sample );
    #elif XPERIPHERALS_I2S_2__DAC_WORD_SIZE == 24
        #if XPERIPHERALS_I2S_2__DAC_WORD_JUST == 0 // left
            return bitrev( sample & 0xFFFFFF00 );
        #elif XPERIPHERALS_I2S_2__DAC_WORD_JUST == 1 // right
            return bitrev( sample >> 8 );
        #endif
    #elif XPERIPHERALS_I2S_2__DAC_WORD_SIZE == 16
        #if XPERIPHERALS_I2S_2__DAC_WORD_JUST == 0 // left
            return bitrev( sample & 0xFFFF0000 );
        #elif XPERIPHERALS_I2S_2__DAC_WORD_JUST == 1 // right
            return bitrev( sample >> 16 );
        #endif
    #endif
}

static inline xuint _xperipherals_i2s_2__unpack_adc_sample( xuint sample )
{
    #if XPERIPHERALS_I2S_2__ADC_WORD_SIZE == 32
        return bitrev( sample );
    #elif XPERIPHERALS_I2S_2__ADC_WORD_SIZE == 24
        #if XPERIPHERALS_I2S_2__ADC_WORD_JUST == 0 // left
            return bitrev( sample ) & 0xFFFFFF00;
        #elif XPERIPHERALS_I2S_2__ADC_WORD_JUST == 1 // right
            return bitrev( sample ) << 8;
        #endif
    #elif XPERIPHERALS_I2S_2__ADC_WORD_SIZE == 16
        #if XPERIPHERALS_I2S_2__ADC_WORD_JUST == 0 // left
            return bitrev( sample ) & 0xFFFF0000;
        #elif XPERIPHERALS_I2S_2__ADC_WORD_JUST == 1 // right
            return bitrev( sample ) << 16;
        #endif
    #endif
}

void xperipherals_i2s_2__synchronize( xbool bclk_is_active )
{
    // TODO/FIXME: Sync on port output completion if ports have been active already?

    clearbuf( _xperipherals_i2s_2__port_wclk );
    for( int i=0; i < XPERIPHERALS_I2S_2__DAC_WIRE_COUNT; ++i ) clearbuf(_xperipherals_i2s_2__port_dac[i]);
    for( int i=0; i < XPERIPHERALS_I2S_2__ADC_WIRE_COUNT; ++i ) clearbuf(_xperipherals_i2s_2__port_adc[i]);

    #if XPERIPHERALS_I2S_2__BUS_MASTER
    {
        if( !bclk_is_active )
        {
            _xperipherals_i2s_2__port_wclk <: 0;
            #pragma loop unroll
            #if XPERIPHERALS_I2S_2__DAC_WIRE_COUNT > 0
            for( int i=0; i < XPERIPHERALS_I2S_2__DAC_WIRE_COUNT; ++i )
                _xperipherals_i2s_2__port_dac[i] <: 0;
            #endif
        }
        else
        {
            //p_lrclk <: 0 @ tmp;
            //tmp += 100;
            //for(int i = 0; i < I2S_WIRES_DAC; i++) p_i2s_dac[i] @ tmp <: 0;
            //p_lrclk @ tmp <: 0x7FFFFFFF;

            unsigned int time;
            _xperipherals_i2s_2__port_wclk <: 0 @ time;
            _xperipherals_i2s_2__port_wclk @ (time+32) <: 0;

            #if XPERIPHERALS_I2S_2__DAC_WIRE_COUNT > 0
            #pragma loop unroll
            for( int i=0; i < XPERIPHERALS_I2S_2__DAC_WIRE_COUNT; ++i )
                _xperipherals_i2s_2__port_dac[i] @ (time+32) <: 0;
            #endif
            #if XPERIPHERALS_I2S_2__ADC_WIRE_COUNT > 0
            #pragma loop unroll
            for( int i=0; i < XPERIPHERALS_I2S_2__ADC_WIRE_COUNT; ++i )
                asm("setpt res[%0], %1"::"r"(_xperipherals_i2s_2__port_adc[i]),"r"(time+31));
            #endif
        }
    }
    #else
    {
        //p_lrclk when pinseq(0) :> void @ tmp; tmp+=97;
        //for(int i = 0; i < I2S_WIRES_DAC; i++) p_i2s_dac[i] @ tmp <: 0;
        //for(int i = 0; i < I2S_WIRES_ADC; i++) asm("setpt res[%0], %1"::"r"(p_i2s_adc[i]),"r"(tmp+31));

        unsigned int time;
        #if I2S_TDM_2__SYNC_FORMAT == 0 // PCM
            _xperipherals_i2s_2__port_wclk when pinseq(0) :> void;
            _xperipherals_i2s_2__port_wclk when pinseq(1) :> void @ time; time += 63;
        #elif I2S_TDM_2__SYNC_FORMAT == 1 // I2S
            _xperipherals_i2s_2__port_wclk when pinseq(1) :> void;
            _xperipherals_i2s_2__port_wclk when pinseq(0) :> void @ time; time += 64;
        #elif I2S_TDM_2__SYNC_FORMAT == 2 // TDM
            _xperipherals_i2s_2__port_wclk when pinseq(1) :> void;
            _xperipherals_i2s_2__port_wclk when pinseq(0) :> void @ time; time += 63;
        #endif

        #if XPERIPHERALS_I2S_2__DAC_WIRE_COUNT > 0
        #pragma loop unroll
        for( int i=0; i < XPERIPHERALS_I2S_2__DAC_WIRE_COUNT; ++i )
            _xperipherals_i2s_2__port_dac[i] @ (time) <: 0;
        #endif
        #if XPERIPHERALS_I2S_2__ADC_WIRE_COUNT > 0
        #pragma loop unroll
        for( int i=0; i < XPERIPHERALS_I2S_2__ADC_WIRE_COUNT; ++i )
            asm("setpt res[%0], %1"::"r"(_xperipherals_i2s_2__port_adc[i]),"r"(time+31));
        #endif
    }
    #endif
}

void xperipherals_i2s_2__transfer_beg( xuint slot )
{
    #if XPERIPHERALS_I2S_2__BUS_MASTER
        _xperipherals_i2s_2__port_wclk <: _xperipherals_i2s_2__sync_word[slot];
    #else
    #endif
}

void xperipherals_i2s_2__transfer_dac( xuint wire, xuint sample )
{
    _xperipherals_i2s_2__port_dac[wire] <: _xperipherals_i2s_2__pack_dac_sample( sample );
}

void xperipherals_i2s_2__transfer_adc( xuint wire, xuint& sample )
{
    _xperipherals_i2s_2__port_adc[wire] :> sample;
    sample = _xperipherals_i2s_2__unpack_adc_sample( sample );
}

#endif

xperipherals_i2s_3.xc

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

#include "xperipherals_i2s.h"

#ifdef XPERIPHERALS_I2S_3

extern clock XPERIPHERALS_I2S_3__CLOCK_NAME;

#if XPERIPHERALS_I2S_3__DAC_WIRE_COUNT >= XPERIPHERALS_I2S_3__ADC_WIRE_COUNT
#define XPERIPHERALS_I2S_3__WIRE_COUNT XPERIPHERALS_I2S_3__DAC_WIRE_COUNT
#else
#define XPERIPHERALS_I2S_3__WIRE_COUNT XPERIPHERALS_I2S_3__ADC_WIRE_COUNT
#endif

#if XPERIPHERALS_I2S_3__BUS_MASTER
    on tile[XPERIPHERALS_I2S_3__TILE_NUMBER] :
    out buffered port:32 _xperipherals_i2s_3__port_wclk = XPERIPHERALS_I2S_3__WCLK_PORT;
#else
    on tile[XPERIPHERALS_I2S_3__TILE_NUMBER] :
    in port _xperipherals_i2s_3__port_wclk = XPERIPHERALS_I2S_3__WCLK_PORT;
#endif

#if XPERIPHERALS_I2S_3__DAC_WIRE_COUNT > 0
    on tile[XPERIPHERALS_I2S_3__TILE_NUMBER] :
    out buffered port:32 _xperipherals_i2s_3__port_dac[XPERIPHERALS_I2S_3__DAC_WIRE_COUNT] = {
        #if   XPERIPHERALS_I2S_3__DAC_WIRE_COUNT == 1
        XPERIPHERALS_I2S_3__DAC0_PORT
        #elif XPERIPHERALS_I2S_3__DAC_WIRE_COUNT == 2
        XPERIPHERALS_I2S_3__DAC0_PORT, XPERIPHERALS_I2S_3__DAC1_PORT
        #elif XPERIPHERALS_I2S_3__DAC_WIRE_COUNT == 3
        XPERIPHERALS_I2S_3__DAC0_PORT, XPERIPHERALS_I2S_3__DAC1_PORT, XPERIPHERALS_I2S_3__DAC2_PORT
        #elif XPERIPHERALS_I2S_3__DAC_WIRE_COUNT == 4
        XPERIPHERALS_I2S_3__DAC0_PORT, XPERIPHERALS_I2S_3__DAC1_PORT, XPERIPHERALS_I2S_3__DAC2_PORT,
        XPERIPHERALS_I2S_3__DAC3_PORT
        #endif
};
#endif

#if XPERIPHERALS_I2S_3__ADC_WIRE_COUNT > 0
    on tile[XPERIPHERALS_I2S_3__TILE_NUMBER] :
    in buffered port:32 _xperipherals_i2s_3__port_adc[XPERIPHERALS_I2S_3__ADC_WIRE_COUNT] = {
        #if XPERIPHERALS_I2S_3__ADC_WIRE_COUNT == 1
        XPERIPHERALS_I2S_3__ADC0_PORT
        #elif XPERIPHERALS_I2S_3__ADC_WIRE_COUNT == 2
        XPERIPHERALS_I2S_3__ADC0_PORT, XPERIPHERALS_I2S_3__ADC1_PORT
        #elif XPERIPHERALS_I2S_3__ADC_WIRE_COUNT == 3
        XPERIPHERALS_I2S_3__ADC0_PORT, XPERIPHERALS_I2S_3__ADC1_PORT, XPERIPHERALS_I2S_3__ADC2_PORT
        #elif XPERIPHERALS_I2S_3__ADC_WIRE_COUNT == 4
        XPERIPHERALS_I2S_3__ADC0_PORT, XPERIPHERALS_I2S_3__ADC1_PORT, XPERIPHERALS_I2S_3__ADC2_PORT,
        XPERIPHERALS_I2S_3__ADC3_PORT
        #endif
};
#endif

static xuint _xperipherals_i2s_3__sync_word[XPERIPHERALS_I2S_3__SLOT_COUNT];

void xperipherals_i2s_3__initialize( void )
{
    for( int i = 0; i < XPERIPHERALS_I2S_3__SLOT_COUNT; ++i ) {

        #if XPERIPHERALS_I2S_3__SYNC_FORMAT == 0 // PCM

            if( i == 0 ) _xperipherals_i2s_3__sync_word[i] = 0xFFFFFFFF;
            else if( i < XPERIPHERALS_I2S_3__SLOT_COUNT-1 ) _xperipherals_i2s_3__sync_word[i] = 0;
            else _xperipherals_i2s_3__sync_word[i] = 0;

        #elif XPERIPHERALS_I2S_3__SYNC_FORMAT == 1 // I2S

            if( i == 0 ) _xperipherals_i2s_3__sync_word[i] = 0x80000000;
            else if( i < XPERIPHERALS_I2S_3__SLOT_COUNT-1 ) _xperipherals_i2s_3__sync_word[i] = 0;
            else _xperipherals_i2s_3__sync_word[i] = 0x7FFFFFFF;

        #elif XPERIPHERALS_I2S_3__SYNC_FORMAT == 2 // TDM

            if( i == 0 ) _xperipherals_i2s_3__sync_word[i] = 0;
            else if( i < XPERIPHERALS_I2S_3__SLOT_COUNT-1 ) _xperipherals_i2s_3__sync_word[i] = 0;
            else _xperipherals_i2s_3__sync_word[i] = 0x80000000;

        #endif
    }
}

void xperipherals_i2s_3__configure( clock bit_clock )
{
    #if XPERIPHERALS_I2S_3__BUS_MASTER
    configure_out_port_no_ready( _xperipherals_i2s_3__port_wclk, bit_clock, 0 );
    #else
    configure_in_port_no_ready( _xperipherals_i2s_3__port_wclk, bit_clock );
    #endif

    #if XPERIPHERALS_I2S_3__DAC_WIRE_COUNT > 0
        for( int i = 0; i < XPERIPHERALS_I2S_3__DAC_WIRE_COUNT; ++i ) {
            configure_out_port_no_ready( _xperipherals_i2s_3__port_dac[i], bit_clock, 0 );
        }
    #endif
    #if XPERIPHERALS_I2S_3__ADC_WIRE_COUNT > 0
        for( int i = 0; i < XPERIPHERALS_I2S_3__ADC_WIRE_COUNT; ++i ) {
            configure_in_port_no_ready( _xperipherals_i2s_3__port_adc[i], bit_clock );
        }
    #endif
}

static inline xuint _xperipherals_i2s_3__pack_dac_sample( xuint sample )
{
    #if XPERIPHERALS_I2S_3__DAC_WORD_SIZE == 32
        return bitrev( sample );
    #elif XPERIPHERALS_I2S_3__DAC_WORD_SIZE == 24
        #if XPERIPHERALS_I2S_3__DAC_WORD_JUST == 0 // left
            return bitrev( sample & 0xFFFFFF00 );
        #elif XPERIPHERALS_I2S_3__DAC_WORD_JUST == 1 // right
            return bitrev( sample >> 8 );
        #endif
    #elif XPERIPHERALS_I2S_3__DAC_WORD_SIZE == 16
        #if XPERIPHERALS_I2S_3__DAC_WORD_JUST == 0 // left
            return bitrev( sample & 0xFFFF0000 );
        #elif XPERIPHERALS_I2S_3__DAC_WORD_JUST == 1 // right
            return bitrev( sample >> 16 );
        #endif
    #endif
}

static inline xuint _xperipherals_i2s_3__unpack_adc_sample( xuint sample )
{
    #if XPERIPHERALS_I2S_3__ADC_WORD_SIZE == 32
        return bitrev( sample );
    #elif XPERIPHERALS_I2S_3__ADC_WORD_SIZE == 24
        #if XPERIPHERALS_I2S_3__ADC_WORD_JUST == 0 // left
            return bitrev( sample ) & 0xFFFFFF00;
        #elif XPERIPHERALS_I2S_3__ADC_WORD_JUST == 1 // right
            return bitrev( sample ) << 8;
        #endif
    #elif XPERIPHERALS_I2S_3__ADC_WORD_SIZE == 16
        #if XPERIPHERALS_I2S_3__ADC_WORD_JUST == 0 // left
            return bitrev( sample ) & 0xFFFF0000;
        #elif XPERIPHERALS_I2S_3__ADC_WORD_JUST == 1 // right
            return bitrev( sample ) << 16;
        #endif
    #endif
}

void xperipherals_i2s_3__synchronize( xbool bclk_is_active )
{
    // TODO/FIXME: Sync on port output completion if ports have been active already?

    clearbuf( _xperipherals_i2s_3__port_wclk );
    for( int i=0; i < XPERIPHERALS_I2S_3__DAC_WIRE_COUNT; ++i ) clearbuf(_xperipherals_i2s_3__port_dac[i]);
    for( int i=0; i < XPERIPHERALS_I2S_3__ADC_WIRE_COUNT; ++i ) clearbuf(_xperipherals_i2s_3__port_adc[i]);

    #if XPERIPHERALS_I2S_3__BUS_MASTER
    {
        if( !bclk_is_active )
        {
            _xperipherals_i2s_3__port_wclk <: 0;
            #pragma loop unroll
            #if XPERIPHERALS_I2S_3__DAC_WIRE_COUNT > 0
            for( int i=0; i < XPERIPHERALS_I2S_3__DAC_WIRE_COUNT; ++i )
                _xperipherals_i2s_3__port_dac[i] <: 0;
            #endif
        }
        else
        {
            //p_lrclk <: 0 @ tmp;
            //tmp += 100;
            //for(int i = 0; i < I2S_WIRES_DAC; i++) p_i2s_dac[i] @ tmp <: 0;
            //p_lrclk @ tmp <: 0x7FFFFFFF;

            unsigned int time;
            _xperipherals_i2s_3__port_wclk <: 0 @ time;
            _xperipherals_i2s_3__port_wclk @ (time+32) <: 0;

            #if XPERIPHERALS_I2S_3__DAC_WIRE_COUNT > 0
            #pragma loop unroll
            for( int i=0; i < XPERIPHERALS_I2S_3__DAC_WIRE_COUNT; ++i )
                _xperipherals_i2s_3__port_dac[i] @ (time+32) <: 0;
            #endif
            #if XPERIPHERALS_I2S_3__ADC_WIRE_COUNT > 0
            #pragma loop unroll
            for( int i=0; i < XPERIPHERALS_I2S_3__ADC_WIRE_COUNT; ++i )
                asm("setpt res[%0], %1"::"r"(_xperipherals_i2s_3__port_adc[i]),"r"(time+31));
            #endif
        }
    }
    #else
    {
        //p_lrclk when pinseq(0) :> void @ tmp; tmp+=97;
        //for(int i = 0; i < I2S_WIRES_DAC; i++) p_i2s_dac[i] @ tmp <: 0;
        //for(int i = 0; i < I2S_WIRES_ADC; i++) asm("setpt res[%0], %1"::"r"(p_i2s_adc[i]),"r"(tmp+31));

        unsigned int time;
        #if I2S_TDM_3__SYNC_FORMAT == 0 // PCM
            _xperipherals_i2s_3__port_wclk when pinseq(0) :> void;
            _xperipherals_i2s_3__port_wclk when pinseq(1) :> void @ time; time += 63;
        #elif I2S_TDM_3__SYNC_FORMAT == 1 // I2S
            _xperipherals_i2s_3__port_wclk when pinseq(1) :> void;
            _xperipherals_i2s_3__port_wclk when pinseq(0) :> void @ time; time += 64;
        #elif I2S_TDM_3__SYNC_FORMAT == 2 // TDM
            _xperipherals_i2s_3__port_wclk when pinseq(1) :> void;
            _xperipherals_i2s_3__port_wclk when pinseq(0) :> void @ time; time += 63;
        #endif

        #if XPERIPHERALS_I2S_3__DAC_WIRE_COUNT > 0
        #pragma loop unroll
        for( int i=0; i < XPERIPHERALS_I2S_3__DAC_WIRE_COUNT; ++i )
            _xperipherals_i2s_3__port_dac[i] @ (time) <: 0;
        #endif
        #if XPERIPHERALS_I2S_3__ADC_WIRE_COUNT > 0
        #pragma loop unroll
        for( int i=0; i < XPERIPHERALS_I2S_3__ADC_WIRE_COUNT; ++i )
            asm("setpt res[%0], %1"::"r"(_xperipherals_i2s_3__port_adc[i]),"r"(time+31));
        #endif
    }
    #endif
}

void xperipherals_i2s_3__transfer_beg( xuint slot )
{
    #if XPERIPHERALS_I2S_3__BUS_MASTER
        _xperipherals_i2s_3__port_wclk <: _xperipherals_i2s_3__sync_word[slot];
    #else
    #endif
}

void xperipherals_i2s_3__transfer_dac( xuint wire, xuint sample )
{
    _xperipherals_i2s_3__port_dac[wire] <: _xperipherals_i2s_3__pack_dac_sample( sample );
}

void xperipherals_i2s_3__transfer_adc( xuint wire, xuint& sample )
{
    _xperipherals_i2s_3__port_adc[wire] :> sample;
    sample = _xperipherals_i2s_3__unpack_adc_sample( sample );
}

#endif