I2S: Inter-IC Serial communcations

Introduction

I2S was designed for transfer of digital audio data.

The ESP8266 has two I2S modules (one transmitter and one receiver), both with hardware DMA support, which means transfers from RAM to the hardware SPI FIFO can be handled directly in hardware without any CPU involvement.

Sming I2S support

The Sming driver deals with the complicated of setting up the hardware, using an API similar to that in the Espressif RTOS SDK. In addition, DMA buffers may be accessed directly to avoid double-buffering and the associated RAM and copy overhead.

Applications

Audio

Playing MIDI files, MP3 files, speech synthesis, etc. is all possible using the ESP8266, though many audio applications require considerable processing power. That means you may need to disable WiFi and set the processor to run at full 160MHz speed.

High-quality multi-channel audio requires an external I2S DAC, which is what the protocol was designed for in the first place. You may find problems with insufficient RAM, but you can always add external SPI RAM.

More realistic uses include generating simple tones, beeps, playing pre-recorded WAV audio, etc. to supplement existing projects. This can all be done in the background without disrupting the system’s main purpose, whatever that may be.

For such applications you can generate single-channel audio via the I2S OUT pin, using Pulse-density modulation.

See the Tone Generator library for a demonstration of this.

GPIO Expansion

Expand GPIO using low-cost shift registers. https://github.com/lhartmann/esp8266_reprap.

Pixel-strip control

Devices such as WS2812-based NeoPixels use a simple, single-wire protocol. I2S is ideal for this as it can be used to generate a precisely-timed bitstream with very low CPU loading.

API Documentation

enum i2s_driver::i2s_bits_per_sample_t

I2S bit width per sample.

Values:

I2S_BITS_PER_SAMPLE_8BIT = 8

I2S bits per sample: 8-bits.

I2S_BITS_PER_SAMPLE_16BIT = 16

I2S bits per sample: 16-bits.

I2S_BITS_PER_SAMPLE_24BIT = 24

I2S bits per sample: 24-bits.

enum i2s_driver::i2s_channel_t

I2S channel.

Values:

I2S_CHANNEL_MONO = 1

I2S 1 channel (mono)

I2S_CHANNEL_STEREO = 2

I2S 2 channel (stereo)

enum i2s_driver::i2s_comm_format_t

I2S communication standard format.

Values:

I2S_COMM_FORMAT_I2S = 0x01

I2S communication format I2S.

I2S_COMM_FORMAT_I2S_MSB = 0x01

I2S format MSB.

I2S_COMM_FORMAT_I2S_LSB = 0x03

I2S format LSB.

enum i2s_driver::i2s_channel_fmt_t

I2S channel format type.

Values:

I2S_CHANNEL_FMT_RIGHT_LEFT = 0x00
I2S_CHANNEL_FMT_ALL_RIGHT
I2S_CHANNEL_FMT_ALL_LEFT
I2S_CHANNEL_FMT_ONLY_RIGHT
I2S_CHANNEL_FMT_ONLY_LEFT
enum i2s_driver::i2s_mode_t

I2S Mode, default is I2S_MODE_MASTER.

Values:

I2S_MODE_DISABLED
I2S_MODE_MASTER
I2S_MODE_SLAVE
enum i2s_driver::i2s_event_type_t

I2S event types.

Values:

I2S_EVENT_DMA_ERROR
I2S_EVENT_TX_DONE

I2S DMA finish sent 1 buffer

I2S_EVENT_RX_DONE

I2S DMA finish received 1 buffer

I2S_EVENT_MAX

I2S event max index

enum i2s_driver::i2s_pin_t

I2S pin enable for i2s_set_pin.

Values:

I2S_PIN_BCK_OUT = 0x01

GPIO 15 / TXD2 / D8.

I2S_PIN_WS_OUT = 0x02

GPIO 2 / TXD1 / D4.

I2S_PIN_DATA_OUT = 0x04

GPIO 3 / RXD0 / D9.

I2S_PIN_BC_IN = 0x10

GPIO 13 / RXD2 / D7.

I2S_PIN_WS_IN = 0x20

GPIO 14 / D5.

I2S_PIN_DATA_IN = 0x40

GPIO 12 / D6.

typedef void (*i2s_callback_t)(void *param, i2s_event_type_t event)

Callback function type.

Note
Function is called in interrupt context, so place in IRAM and keep it brief.

typedef unsigned TickType_t

Defines the wait interval (presently milliseconds)

typedef uint8_t i2s_pin_set_t
bool i2s_driver_install(const i2s_config_t *config)

Install and start I2S driver.

Note
This function must be called before any I2S driver read/write operations.
Parameters
  • config: I2S configuration
Return Value
  • true: on success, false if already installed or invalid config

void i2s_driver_uninstall()

Uninstall I2S driver.

bool i2s_start()

Start I2S driver.

Note
It is not necessary to call this function after i2s_driver_install() as it is started automatically, unless config.auto_start was set to false.
Return Value
  • bool: true on success, false if driver not initialised

bool i2s_stop()

Stop I2S driver.

Note
Disables I2S TX/RX, until i2s_start() is called
Return Value
  • bool: true on success, false if driver not initialised

bool i2s_set_sample_rates(uint32_t rate)

Parameters
  • rate: Sample rate in Hz (ex 44100, 48000) for TX/RX

bool i2s_set_dividers(uint8_t bck_div, uint8_t mclk_div)

Direct control over output rate

float i2s_get_real_rate()

Return Value
  • float: The actual Sample Rate on output

bool i2s_dma_read(i2s_buffer_info_t *info, size_t max_bytes)

Fetch a DMA buffer containing received data (zero-copy)

Note
On success, info->buffer specifies where to read the data from, and info->size how many bytes are actually available (always > 0).
Note
Returns at most one DMA buffer
Parameters
  • info: Pointer to structure to receive buffer information
  • max_bytes: Number of bytes to read
Return Value
  • bool: true on success, false if no data available or info is null

bool i2s_dma_write(i2s_buffer_info_t *info, size_t max_bytes)

Fetch a DMA buffer for direct writing (zero-copy)

Note
On success, info->buffer specifies where to write the data, and info->size how many bytes should be written - may be less than max_bytes, but always > 0.
Note
Returns at most one DMA buffer
Parameters
  • info: Pointer to structure to receive buffer information
  • max_bytes: Number of bytes required in buffer
Return Value
  • bool: true on success, false if buffer unavailable or info is null

size_t i2s_write(const void *src, size_t size, TickType_t ticks_to_wait)

writes a buffer of frames into the DMA memory, returns the amount of frames written.

Note
Data is copied into DMA buffers
Parameters
  • src: Data to write
  • size: Size in bytes
  • ticks_to_wait: Wait timeout in ticks
Return Value
  • size_t: Data actually written, may be less than size

size_t i2s_read(void *dest, size_t size, TickType_t ticks_to_wait)

Reads a block of received data.

Parameters
  • dest: Buffer to store data
  • size: Max. bytes to read
  • ticks_to_wait: Wait timeout in ticks
Return Value
  • size_t: Number of bytes read

bool i2s_zero_dma_buffer()

Zero the contents of the TX DMA buffer.

Note
Pushes zero-byte samples into the TX DMA buffer, until it is full

void i2s_set_pins(i2s_pin_set_t pins, bool enable)

Configure I2S pins.

You can alternatively use arduino functions.

Note
Call this after initialising driver to specify which pins are required
Parameters
  • pins: Mask of i2s_pin_t values
  • enable: true to enable for I2S use, false to revert to GPIO

Example: i2s_set_pins(_BV(I2S_BCK_OUT), true)

bool i2s_enable_loopback(bool enable)
bool i2s_stat_tx(i2s_buffer_stat_t *stat)

Obtain state information for TX buffers.

Parameters
  • stat:
Return Value
  • bool: true on success

bool i2s_stat_rx(i2s_buffer_stat_t *stat)

Obtain state information for RX buffers.

Parameters
  • stat:
Return Value
  • bool: true on success

union i2s_sample_t
#include <i2s.h>

I2S sample.

An I2S frame can contain various types of data:

8-bit, 16-bit or 24-bit mono samples 8-bit or 16-bit stereo samples

Public Members

uint32_t u32
int16_t left
int16_t right
struct i2s_sample_t::[anonymous] [anonymous]
struct i2s_module_config_t
#include <i2s.h>

I2S module configuration (TX or RX)

Public Members

i2s_mode_t mode

I2S work mode (combination of i2s_mode_t)

i2s_bits_per_sample_t bits_per_sample

I2S bits per sample.

i2s_channel_fmt_t channel_format

I2S channel format.

i2s_comm_format_t communication_format

I2S communication format.

uint16_t dma_buf_len

I2S DMA Buffer Length (in samples)

uint8_t dma_buf_count

I2S DMA Buffer Count.

uint8_t callback_threshold

TX: callback when available buffers > threshold RX: Callback when slc_queue_len > threshold

struct i2s_config_t
#include <i2s.h>

I2S configuration parameters.

Public Members

i2s_module_config_t tx

TX module configuration.

i2s_module_config_t rx

RX module configuration.

unsigned sample_rate

I2S sample rate.

bool tx_desc_auto_clear

I2S auto clear tx descriptor if there is underflow condition (Mutes output)

bool auto_start

Start immediately on successful initialisation.

i2s_callback_t callback

Callback handler.

void *param

Callback parameter.

uint8_t bits_mod

Evaluate what this does (4 bits)

struct i2s_buffer_info_t
#include <i2s.h>

Defines a buffer with available content.

Public Members

void *buffer
i2s_sample_t *samples
union i2s_buffer_info_t::[anonymous] [anonymous]
size_t size

Available space (TX) or data (RX) in bytes.

uint16_t buf
uint16_t pos
struct i2s_buffer_stat_t
#include <i2s.h>

Contains I2S buffer status information.

Note
Size excludes buffer in use by DMA

Public Members

uint16_t size
uint16_t used