PMSIS API
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
I2S Interface

I2S (Inter-IC Sound) Interface. More...

Data Structures

struct  pi_i2s_conf
 Interface configuration options. More...
 

Macros

#define PI_I2S_FMT_DATA_FORMAT_I2S
 Standard I2S Data Format. More...
 
#define PI_I2S_FMT_DATA_FORMAT_PDM
 Pulse-Density Modulation Format. More...
 
#define PI_I2S_CH_FMT_DATA_ORDER_MSB
 Data order MSB. More...
 
#define PI_I2S_CH_FMT_DATA_ORDER_LSB
 Data order LSB. More...
 
#define PI_I2S_CH_FMT_DATA_ALIGN_LEFT
 Data alignment left. More...
 
#define PI_I2S_CH_FMT_DATA_ALIGN_RIGHT
 Data alignment right. More...
 
#define PI_I2S_CH_FMT_DATA_SIGN_NO_EXTEND
 Data sign extension disabled. More...
 
#define PI_I2S_CH_FMT_DATA_SIGN_EXTEND
 Data sign extension enabled. More...
 
#define PI_I2S_OPT_PINGPONG
 Ping pong mode. More...
 
#define PI_I2S_OPT_MEM_SLAB
 Mem slab mode. More...
 
#define PI_I2S_OPT_FULL_DUPLEX
 Full duplex mode. More...
 
#define PI_I2S_OPT_DISABLED
 Disable the channel. More...
 
#define PI_I2S_OPT_ENABLED
 Enable the channel. More...
 
#define PI_I2S_OPT_IS_TX
 Configure TX channel. More...
 
#define PI_I2S_OPT_IS_RX
 Configure RX channel. More...
 
#define PI_I2S_OPT_LOOPBACK
 TX loopback. More...
 
#define PI_I2S_OPT_TDM
 TDM mode. More...
 
#define PI_I2S_OPT_INT_CLK
 Use internal clock. More...
 
#define PI_I2S_OPT_EXT_CLK
 Use external clock. More...
 
#define PI_I2S_OPT_INT_WS
 Use internal word strobe. More...
 
#define PI_I2S_OPT_EXT_WS
 Use external word strobe. More...
 

Typedefs

typedef uint8_t pi_i2s_fmt_t
 
typedef uint16_t pi_i2s_opt_t
 

Enumerations

enum  pi_i2s_ioctl_cmd_e
 IOCTL command. More...
 

Functions

void pi_i2s_setup (uint32_t flags)
 Setup specific I2S aspects. More...
 
void pi_i2s_conf_init (struct pi_i2s_conf *conf)
 Initialize an I2S configuration with default values. More...
 
int pi_i2s_open (struct pi_device *device)
 Open an I2S device. More...
 
void pi_i2s_close (struct pi_device *device)
 Close an opened I2S device. More...
 
int pi_i2s_ioctl (struct pi_device *device, uint32_t cmd, void *arg)
 Dynamically change the device configuration. More...
 
int pi_i2s_read (struct pi_device *dev, void **mem_block, size_t *size)
 Read data from the RX queue. More...
 
int pi_i2s_read_async (struct pi_device *dev, pi_task_t *task)
 Read data asynchronously from the RX queue. More...
 
int pi_i2s_write (struct pi_device *dev, void *mem_block, size_t size)
 Write data to the TX queue of a channel. More...
 
int pi_i2s_write_async (struct pi_device *dev, void *mem_block, size_t size, pi_task_t *task)
 Write data asynchronously to the TX queue of a channel. More...
 
int pi_i2s_channel_read (struct pi_device *dev, int channel, void **mem_block, size_t *size)
 Read data from the RX queue of a channel in TDM mode. More...
 
int pi_i2s_channel_read_async (struct pi_device *dev, int channel, pi_task_t *task)
 Read data asynchronously from the RX queue of a channel in TDM mode. More...
 
int pi_i2s_read_status (pi_task_t *task, void **mem_block, size_t *size)
 Read the status of an asynchronous read. More...
 
int pi_i2s_channel_write (struct pi_device *dev, int channel, void *mem_block, size_t size)
 Write data to the TX queue of a channel in TDM mode. More...
 
int pi_i2s_channel_write_async (struct pi_device *dev, int channel, void *mem_block, size_t size, pi_task_t *task)
 Write data asynchronously to the TX queue of a channel in TDM mode. More...
 
int pi_i2s_write_status (pi_task_t *task)
 Read the status of an asynchronous write. More...
 

Description

The I2S API provides support for the I2S interface.

Macro Definition Documentation

#define PI_I2S_CH_FMT_DATA_ALIGN_LEFT

Left Justified.

#define PI_I2S_CH_FMT_DATA_ALIGN_RIGHT

Right Justified.

#define PI_I2S_CH_FMT_DATA_ORDER_LSB

Data bits are transferred LSB first.

#define PI_I2S_CH_FMT_DATA_ORDER_MSB

Data bits are transferred MSB first.

#define PI_I2S_CH_FMT_DATA_SIGN_EXTEND

Data are sign extended when I2S data size is inferior to memory data size. For example when I2S data are on 16 bits but are stored in a 32 bits word, MSB sign is extended.

#define PI_I2S_CH_FMT_DATA_SIGN_NO_EXTEND

Data are not sign extended when I2S data size is inferior to memory data size.

#define PI_I2S_FMT_DATA_FORMAT_I2S

Serial data is transmitted in two's complement with the MSB first. Both Word Select (WS) and Serial Data (SD) signals are sampled on the rising edge of the clock signal (SCK). The MSB is always sent one clock period after the WS changes. Left channel data are sent first indicated by WS = 0, followed by right channel data indicated by WS = 1.

   -. .-. .-. .-. .-. .-. .-. .-. .-. .-. .-. .-. .-. .-. .-. .-. .-. .-.
SCK '-' '-' '-' '-' '-' '-' '-' '-' '-' '-' '-' '-' '-' '-' '-' '-' '-' '
   -.                               .-------------------------------.
WS  '-------------------------------'                               '----
   -.---.---.---.---.---.---.---.---.---.---.---.---.---.---.---.---.---.
SD  |   |MSB|   |...|   |LSB| x |...| x |MSB|   |...|   |LSB| x |...| x |
   -'---'---'---'---'---'---'---'---'---'---'---'---'---'---'---'---'---'
        | Left channel                  | Right channel                 |
#define PI_I2S_FMT_DATA_FORMAT_PDM

Serial data is transmitted using the pulse-density modulation. Each sample is a one bit pulse, where the density of the pulses gives the amplitude of the signal. The driver will filter the input signals so that classic PCM samples are stored in the buffers. In single channel mode, the bits are transmitted on clock signal (CLK) rising edges. In dual channel mode, left chanel is transmitted on SCK rising edges and right channel on SCK falling edges. Word Select (WS) is ignored.

#define PI_I2S_OPT_DISABLED

If set, this desactivates the channel being configured (either RX or TX). Once the sampling is running, this will make sure this channel is not receiving or sending samples.

#define PI_I2S_OPT_ENABLED

If set, this activates the channel being configured (either RX or TX). Once the sampling is running, this will make sure this channel is receiving or sending samples.

#define PI_I2S_OPT_EXT_CLK

If this option is specified, no clock is generated and an external clock is used.

#define PI_I2S_OPT_EXT_WS

If this option is specified, no word strobe is generated and an external one is used.

#define PI_I2S_OPT_FULL_DUPLEX

The normal and default mode is to use a single pin for both TX and RX. In full duplex mode, RX and TX will use 2 different pins(called sdi and sdo so that samples can be received and sent at the same time).

#define PI_I2S_OPT_INT_CLK

Clock is generated internally from SOC's clock.

This is default clock source.

#define PI_I2S_OPT_INT_WS

WS signal is generated internally from SCK signal.

This is default WS source.

#define PI_I2S_OPT_IS_RX

If set, the configuration will apply to the RX channel and won't change anything for what concerns the TX channel. Note that this does not prevent from using the TX channel, they must just be configured separately.

Setting this configuration allows to receive data from microphones to memory.

#define PI_I2S_OPT_IS_TX

If set, the configuration will apply to the TX channel and won't change anything for what concerns the RX channel. Note that this does not prevent from using the RX channel, they must just be configured separately.

Setting this configuration allows to send data from memory to speakers.

#define PI_I2S_OPT_LOOPBACK

If set, this activates an internal loopback between the RX pin and TX pin. All data received on the RX will be sent to the TX pin. Note that this does not prevent from receiving data. Data received on the RX can be sent both to a memory buffer (if RX channel is enabled) and to the TX (if the loopback is enabled). The loopback must be applied on the TX channel.

#define PI_I2S_OPT_MEM_SLAB

In mem slab mode TX output or RX sampling will keep alternating between a a set of buffers given by the user. Memory slab pointed to by the mem_slab field has to be defined and initialized by the user. For I2S driver to function correctly number of memory blocks in a slab has to be at least 2 per queue. Size of the memory block should be multiple of frame_size where frame_size = (channels * word_size_bytes). As an example 16 bit word will occupy 2 bytes, 24 or 32 bit word will occupy 4 bytes.

#define PI_I2S_OPT_PINGPONG

In ping pong mode TX output or RX sampling will keep alternating between a ping buffer and a pong buffer. This is normally used in audio streams when one buffer is being populated while the other is being played (DMAed) and vice versa. So, in this mode, 2 sets of buffers fixed in size are used. These 2 buffers must be given in the configuration when the driver is opened and kept alive until the driver is closed.

#define PI_I2S_OPT_TDM

In TDM mode, the same interface is time-multiplexed to transmit data for multiple channels where each channel can have a specific configuration. As for classic I2S mode, TX and RX channels are grouped together within a slot. Each slot can send and receive 1 data per frame. In this mode each slot must be configured separately using the I2S configuration. Each slot can have an RX and a TX channel.

Typedef Documentation

typedef uint8_t pi_i2s_fmt_t
typedef uint16_t pi_i2s_opt_t

Enumeration Type Documentation

Enumerator
PI_I2S_IOCTL_START 

Start the transmission / reception of data.

This command can be used when the interface has been opened or stopped to start sampling.

PI_I2S_IOCTL_STOP 

Stop the transmission / reception of data.

Stop the transmission / reception of data at the end of the current memory block. This command can be used when the interface is sampling and is stopping the interface. When the current TX / RX block is transmitted / received the interface is stopped. Subsequent START command will resume transmission / reception where it stopped.

PI_I2S_IOCTL_CONF_SET 

Configure a channel in TDM mode.

In TDM mode, the same interface is time-multiplexed to transmit data for multiple channels, and each channel can have a specific configuration. This command can be used to give the configuration of one channel. The argument must be a pointer to a structure of type struct pi_i2s_conf containing the channel configuration.

PI_I2S_IOCTL_CONF_GET 

Get the current configuration of a channel in TDM mode.

In TDM mode, the same interface is time-multiplexed to transmit data for multiple channels, and each channel can have a specific configuration. This command can be used to get the current configuration of one channel. The argument must be a pointer to a structure of type struct pi_i2s_conf where the current channel configuration will be stored.

PI_I2S_IOCTL_CLOCK_ENABLE 

Enable clock.

Enable clock for the i2s interface. This command does not sample data, and does not save data. It allows the interface to receive clock signals from SoC and propgate it to slave devices on end line.

PI_I2S_IOCTL_CLOCK_DISABLE 

Disable clock.

Disable clock for the i2s interface.

PI_I2S_IOCTL_EN_TIMESTAMP 

Enable the timestamp.

Enable the timestamp feature for the i2s interface.

Function Documentation

int pi_i2s_channel_read ( struct pi_device *  dev,
int  channel,
void **  mem_block,
size_t *  size 
)

Data received by the I2S interface is stored in the RX queue consisting of two memory blocks preallocated by the user and given to the driver in the configuration. Calling this function will return the next available buffer to the caller, which has to use it before the sampling for this buffer starts again.

The data is read in chunks equal to the size of the memory block.

This will return data for the specified channel and must only be used in TDM mode.

If there is no data in the RX queue the function will block waiting for the next RX memory block to fill in.

Due to hardware constraints, the address of the buffer must be aligned on 4 bytes.

Parameters
devPointer to the device structure for the driver instance.
channelID of the slot, from 0 to the number of channels minus 1.
mem_blockPointer to the variable storing the address of the RX memory block containing received data.
sizePointer to the variable storing the number of bytes read.
Return values
0If successful, -1 if not.
int pi_i2s_channel_read_async ( struct pi_device *  dev,
int  channel,
pi_task_t *  task 
)

Data received by the I2S interface is stored in the RX queue consisting of two memory blocks preallocated by the user and given to the driver in the configuration. Calling this function will return the next available buffer to the caller, which has to use it before the sampling for this buffer starts again.

The data is read in chunks equal to the size of the memory block.

This will return data for the specified channel and must only be used in TDM mode.

The specified task will be pushed as soon as data is ready in the RX queue, and the information about the memory block and the size will be available in the task.

Due to hardware constraints, the address of the buffer must be aligned on 4 bytes.

Parameters
devPointer to the device structure for the driver instance.
channelID of the slot, from 0 to the number of channels minus 1.
taskThe task used to notify the end of transfer.
Return values
0If successful, -1 if not.
int pi_i2s_channel_write ( struct pi_device *  dev,
int  channel,
void *  mem_block,
size_t  size 
)

Data to be sent by the I2S interface is stored first in the TX queue consisting of memory blocks preallocated by the user with either pingpong buffers or a memory slab allocator.

In pingpong mode, the driver will automatically alternate between 2 buffers and the user code is supposed to call this function to notify the driver that the specified buffer is ready to be sent. This is used by the driver to report when an underrun or an overrun occurs.

In memory slab allocator mode, the user has to allocate buffers from the memory slab allocator and pass them to the driver by calling this function when they are ready to be sent.

This fonction will block until the specified buffer has been transfered.

This will sent data to the specified channel and must only be used in TDM mode.

Parameters
devPointer to the device structure for the driver instance.
channelID of the slot, from 0 to the number of channels minus 1.
mem_blockPointer to the TX memory block containing data to be sent.
sizeNumber of bytes to write. This value has to be equal or smaller than the size of the memory block.
Return values
0If successful.
-1An error occured.
int pi_i2s_channel_write_async ( struct pi_device *  dev,
int  channel,
void *  mem_block,
size_t  size,
pi_task_t *  task 
)

Data to be sent by the I2S interface is stored first in the TX queue consisting of memory blocks preallocated by the user with either pingpong buffers or a memory slab allocator.

In pingpong mode, the driver will automatically alternate between 2 buffers and the user code is supposed to call this function to notify the driver that the specified buffer is ready to be sent. This is used by the driver to report when an underrun or an overrun occurs.

In memory slab allocator mode, the user has to allocate buffers from the memory slab allocator and pass them to the driver by calling this function when they are ready to be sent.

This will sent data to the specified channel and must only be used in TDM mode.

The specified task will be pushed as soon as data is has been transfered.

Parameters
devPointer to the device structure for the driver instance.
channelID of the slot, from 0 to the number of channels minus 1.
mem_blockPointer to the TX memory block containing data to be sent.
sizeNumber of bytes to write. This value has to be equal or smaller than the size of the memory block.
taskThe task used to notify the end of transfer.
Return values
0If successful.
-1An error occured.
void pi_i2s_close ( struct pi_device *  device)

This function can be called to close an opened I2S device once it is not needed anymore, in order to free all allocated resources. Once this function is called, the device is not accessible anymore and must be opened again before being used. The caller is blocked until the operation is finished.

Parameters
deviceA pointer to the structure describing the device.
void pi_i2s_conf_init ( struct pi_i2s_conf conf)

This function can be called to get default values for all parameters before setting some of them. The structure containing the configuration must be kept alive until the I2S device is opened.

Parameters
confA pointer to the I2S configuration.
int pi_i2s_ioctl ( struct pi_device *  device,
uint32_t  cmd,
void *  arg 
)

This function can be called to change part of the device configuration after it has been opened or to control it.

Parameters
deviceA pointer to the structure describing the device.
cmdThe command which specifies which parameters of the driver to modify and for some of them also their values. The command must be one of those defined in pi_spi_ioctl_e.
argAn additional value which is required for some parameters when they are set.
int pi_i2s_open ( struct pi_device *  device)

This function must be called before the I2S device can be used. It will do all the needed configuration to make it usable and initialize the handle used to refer to this opened device when calling other functions. The caller is blocked until the operation is finished.

Parameters
deviceA pointer to the device structure of the device to open. This structure is allocated by the caller and must be kept alive until the device is closed.
Returns
0 if the operation is successfull, -1 if there was an error.
int pi_i2s_read ( struct pi_device *  dev,
void **  mem_block,
size_t *  size 
)

Data received by the I2S interface is stored in the RX queue consisting of two memory blocks preallocated by the user and given to the driver in the configuration. Calling this function will return the next available buffer to the caller, which has to use it before the sampling for this buffer starts again.

The data is read in chunks equal to the size of the memory block.

When using several channels, the organization of the samples for each channel in the buffer, is chip-dependent, check the chip-specific documentation to get more information.

If there is no data in the RX queue the function will block waiting for the next RX memory block to fill in.

Due to hardware constraints, the address of the buffer must be aligned on 4 bytes.

Parameters
devPointer to the device structure for the driver instance.
mem_blockPointer to the variable storing the address of the RX memory block containing received data.
sizePointer to the variable storing the number of bytes read.
Return values
0If successful, -1 if not.
int pi_i2s_read_async ( struct pi_device *  dev,
pi_task_t *  task 
)

Data received by the I2S interface is stored in the RX queue consisting of two memory blocks preallocated by the user and given to the driver in the configuration. Calling this function will return the next available buffer to the caller, which has to use it before the sampling for this buffer starts again.

The data is read in chunks equal to the size of the memory block.

When using several channels, the organization of the samples for each channel in the buffer, is chip-dependent, check the chip-specific documentation to get more information.

The specified task will be pushed as soon as data is ready in the RX queue, and the information about the memory block and the size will be available in the task.

Due to hardware constraints, the address of the buffer must be aligned on 4 bytes.

Parameters
devPointer to the device structure for the driver instance.
taskThe task used to notify the end of transfer.
Return values
0If successful, -1 if not.
int pi_i2s_read_status ( pi_task_t *  task,
void **  mem_block,
size_t *  size 
)

After pi_i2s_read_async or pi_i2s_channel_read_async is called to be notified when a read buffer is available, and the notification is received, the output information can be retrieved by calling this function.

Parameters
taskThe task used for notification.
mem_blockPointer to the variable storing the address of the RX memory block containing received data.
sizePointer to the variable storing the number of bytes read.
Return values
0If successful.
-1An error occured.
void pi_i2s_setup ( uint32_t  flags)

This function can be called to set specific I2S properties such as the number of clock generator. This is typically used by the BSP to give board specific information.

Parameters
flagsA bitfield of chip-dependant properties.
int pi_i2s_write ( struct pi_device *  dev,
void *  mem_block,
size_t  size 
)

Data to be sent by the I2S interface is stored first in the TX queue consisting of memory blocks preallocated by the user with either pingpong buffers or a memory slab allocator.

In pingpong mode, the driver will automatically alternate between 2 buffers and the user code is supposed to call this function to notify the driver that the specified buffer is ready to be sent. This is used by the driver to report when an underrun or an overrun occurs.

In memory slab allocator mode, the user has to allocate buffers from the memory slab allocator and pass them to the driver by calling this function when they are ready to be sent.

This fonction will block until the specified buffer has been transfered.

Parameters
devPointer to the device structure for the driver instance.
mem_blockPointer to the TX memory block containing data to be sent.
sizeNumber of bytes to write. This value has to be equal or smaller than the size of the memory block.
Return values
0If successful.
-1An error occured.
int pi_i2s_write_async ( struct pi_device *  dev,
void *  mem_block,
size_t  size,
pi_task_t *  task 
)

Data to be sent by the I2S interface is stored first in the TX queue consisting of memory blocks preallocated by the user with either pingpong buffers or a memory slab allocator.

In pingpong mode, the driver will automatically alternate between 2 buffers and the user code is supposed to call this function to notify the driver that the specified buffer is ready to be sent. This is used by the driver to report when an underrun or an overrun occurs.

In memory slab allocator mode, the user has to allocate buffers from the memory slab allocator and pass them to the driver by calling this function when they are ready to be sent.

The specified task will be pushed as soon as data is has been transfered.

Parameters
devPointer to the device structure for the driver instance.
mem_blockPointer to the TX memory block containing data to be sent.
sizeNumber of bytes to write. This value has to be equal or smaller than the size of the memory block.
taskThe task used to notify the end of transfer.
Return values
0If successful.
-1An error occured.
int pi_i2s_write_status ( pi_task_t *  task)

After pi_i2s_write_async or pi_i2s_channel_write_async and the notification for the end of transfer is received, return value can be retrieved by calling this function.

Parameters
taskThe task used for notification.
Return values
0If successful.
-1An error occured.