PMSIS API
|
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... | |
The I2S API provides support for the I2S interface.
#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 uint8_t pi_i2s_fmt_t |
typedef uint16_t pi_i2s_opt_t |
enum pi_i2s_ioctl_cmd_e |
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. |
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.
dev | Pointer to the device structure for the driver instance. |
channel | ID of the slot, from 0 to the number of channels minus 1. |
mem_block | Pointer to the variable storing the address of the RX memory block containing received data. |
size | Pointer to the variable storing the number of bytes read. |
0 | If 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.
dev | Pointer to the device structure for the driver instance. |
channel | ID of the slot, from 0 to the number of channels minus 1. |
task | The task used to notify the end of transfer. |
0 | If 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.
dev | Pointer to the device structure for the driver instance. |
channel | ID of the slot, from 0 to the number of channels minus 1. |
mem_block | Pointer to the TX memory block containing data to be sent. |
size | Number of bytes to write. This value has to be equal or smaller than the size of the memory block. |
0 | If successful. |
-1 | An 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.
dev | Pointer to the device structure for the driver instance. |
channel | ID of the slot, from 0 to the number of channels minus 1. |
mem_block | Pointer to the TX memory block containing data to be sent. |
size | Number of bytes to write. This value has to be equal or smaller than the size of the memory block. |
task | The task used to notify the end of transfer. |
0 | If successful. |
-1 | An 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.
device | A 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.
conf | A 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.
device | A pointer to the structure describing the device. |
cmd | The 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. |
arg | An 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.
device | A 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. |
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.
dev | Pointer to the device structure for the driver instance. |
mem_block | Pointer to the variable storing the address of the RX memory block containing received data. |
size | Pointer to the variable storing the number of bytes read. |
0 | If 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.
dev | Pointer to the device structure for the driver instance. |
task | The task used to notify the end of transfer. |
0 | If 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.
task | The task used for notification. |
mem_block | Pointer to the variable storing the address of the RX memory block containing received data. |
size | Pointer to the variable storing the number of bytes read. |
0 | If successful. |
-1 | An 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.
flags | A 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.
dev | Pointer to the device structure for the driver instance. |
mem_block | Pointer to the TX memory block containing data to be sent. |
size | Number of bytes to write. This value has to be equal or smaller than the size of the memory block. |
0 | If successful. |
-1 | An 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.
dev | Pointer to the device structure for the driver instance. |
mem_block | Pointer to the TX memory block containing data to be sent. |
size | Number of bytes to write. This value has to be equal or smaller than the size of the memory block. |
task | The task used to notify the end of transfer. |
0 | If successful. |
-1 | An 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.
task | The task used for notification. |
0 | If successful. |
-1 | An error occured. |