<< >>

I2S Master

This module is an I2S master transmitter and receiver in a single thread. It sends and receives samples over a pair of chanends and transmits audio over I2S. It can send and receive multiple I2S links on separate ports.

As a master it drives the bit clock (BCK) and word clock (WCK) on output ports. It is clocked by an external master clock (MCK) on an input port.

API

Symbolic constants

I2S_MASTER_NUM_IN

Number of input ports, each carries two channels of audio.

I2S_MASTER_NUM_OUT

Number of output ports, each carries two channels of audio.

MCK_BCK_RATIO

BCK is soft divided off MCK.

MCK frequency is MCK_BCK_RATIO times BCK frequency.

Structures

i2s_master

Resources for I2S_MASTER.

Structure Members:

clock cb1

Clock block for MCK.

clock cb2

Clock block for BCK.

in port mck

Clock port for MCK.

out buffered port:32 bck

Clock port for BCK.

out buffered port:32 wck

Clock port for WCK.

in buffered port:32 din

Array of I2S_MASTER_NUM_IN x 1-bit ports for audio input.

out buffered port:32 dout

Array of I2S_MASTER_NUM_OUT x 1-bit ports for audio output.

Functions

void i2s_master(struct i2s_master &r_i2s, streaming chanend c_in, streaming chanend c_out)

I2S Master function.

Samples are left-aligned signed values. e.g. 24-bit audio will look like 0x12345600 (positive) or 0xFF123400 (negative)

Parameters:
  • r_i2s – Structure to configure the i2s_master
  • c_in – Input streaming channel for sample data. Samples are returned in the following order: Left (din[0]), .., Left (din[I2S_MASTER_NUM_IN - 1]), Right (din[0]), .., Right (din[I2S_MASTER_NUM_IN - 1])
  • c_out – Output streaming channel for sample data Samples should be sent in the following order: Left (dout[0]), .., Left (dout[I2S_MASTER_NUM_OUT - 1]), Right (dout[0]), .., Right (dout[I2S_MASTER_NUM_OUT - 1])

Example

This example is designed to run on the XR-USB-AUDIO-2.0-MC board. It takes 3 stereo I2S inputs and sends them out over 4 stereo I2S outputs. I2S_MASTER_NUM_IN and I2S_MASTER_NUM_OUT are defined in the Makefile.

First of all i2s_master should be included and the structure i2s_master defined.

#include "i2s_master.h"

on stdcore[1] : struct i2s_master r_i2s =
{
  XS1_CLKBLK_1,
  XS1_CLKBLK_2,
  XS1_PORT_1L,  // MCK
  XS1_PORT_1I,  // BCK
  XS1_PORT_1E,  // WCK
  { XS1_PORT_1G, XS1_PORT_1A, XS1_PORT_1B },  // DIN
  { XS1_PORT_1M, XS1_PORT_1F, XS1_PORT_1H, XS1_PORT_1N },  // DOUT
};

The top level of this example creates the i2s_master on core 1, along with a 1KHz clock to the PLL and occupies the remaining 6 threads with computation.

Core 0 runs the loopback function which reads the I2S inputs from the i2s_master thread over a streaming channel and sends them over a streaming channel back to the i2s_master thread to the I2S outputs.

int main()
{
   streaming chan c_in, c_out;
   par {
      on stdcore[1] : {
         char name[3][4] = { "1/2", "3/4", "5/6" };

#ifndef SIM
         init_pll(r_i2c);
         reset_codec(rst);
         init_codec(r_i2c);
#endif
         printstr("looping back line input ");
         printstr(name[INPUT]);
         printstrln(" to line outputs 1/2 3/4 5/6 7/8");

         par {
            fsgen_busy(1000, fs);
            {
               mswait(300);
               i2s_master(r_i2s, c_in, c_out);
            }
            par (int i = 0; i < 6; i++) {
              traffic();
            }
         }
      }
      on stdcore[0] : loopback(c_in, c_out);
      //on stdcore[0] : input_test(c_in, c_out);
#ifdef SIM
      on stdcore[0] : {
         // generate 25MHz MCK
         set_clock_div(b_mck_sim, 2);
         set_port_clock(p_mck_sim, b_mck_sim);
         set_port_mode_clock(p_mck_sim);
         start_clock(b_mck_sim);
      }
#endif
   }
   return 0;
}