# 功能特性 ## I2S 接口特性 ### 数据格式 * 支持 `标准 I2S`、`左对齐 (Left Justified)`、`右对齐 (Right Justified)` 和 ` TDM(64、128、256)` 四种数据格式。 * 可参考结构体 \ref GX_I2S_DATA_FORMAT。 ### BCLK * 支持 `32fs(I2S)`、`64fs(I2S/TDM)`、`128fs(TDM)` 和 `256fs(TMD)` 四种 BCLK 时钟选择。 * 可参考结构体 \ref GX_I2S_BCLK_SEL。 ### MCLK * 支持 `64fs`、`128fs`、`192fs`、`256fs`、`384fs`、`512fs`、`768fs`、`1024fs`、`1536fs`、`2048fs` 等几种 MCLK 时钟选择。 * 可参考结构体 \ref GX_I2S_MCLK_SEL。 :::{important} MCLK 选择需要是 BCLK 的至少四倍及以上。 ::: ### 时钟模式 * 支持 `Master`、`Slave 普通模式` 和 `Slave 精简模式` 三种时钟模式。 * 可参考结构体 \ref GX_I2S_CLK_MODE。 :::{important} 如果是 slave 精简模式时,MCLK 时钟必须来源于芯片内部;BCLK 和 LRCLK 时钟必须来源于芯片外部。且 MCLK 给定频率需要比实际配置的 MCLK 频率稍微高一点(如1.5倍)。 ::: ### 采样率 * 支持 `8kHz`、`11.025kHz`、`12kHz`、`16kHz`、`22.05kHz`、`24kHz`、`32kHz`、`44.1kHz`、`48kHz`、`64kHz`、`96kHz`、`192kHz`、`384kHz` 采样率输入。 * 可参考结构体 \ref GX_I2S_SAMPLE_RATE。 ### 传输有效位 * 支持 `16bit`、`20bit`、`24bit`、`32bit`(包括 32bit 全部有效、32bit 内 8 到 23bit 有效、32bit 内 16 到 31bit 有效、32bit 内 0 到 15bit 有效、32bit 内 8 到 31bit 有效、32bit 内 0 到 23bit 有效)传输。 * TDM 模式下支持`长帧同步`和`短帧同步`两种格式。 * 可参考结构体 \ref GX_I2S_PCM_LENGTH。 :::{note} 32bit 传输中除了 32bit 全有效外,其余只在 TDM 模式下支持。 ::: ## 数据的输入、输出特性 ### 存储位宽 * 支持 `16bit`、`24bit`、`32bit` 存储。 * 对于 `I2S TX` ,对应 SRAM 中的数据存储位宽,为保证输出的数据的正确性符合预期,需要对应配置 * 对于 `I2S RX` ,描述存储至 SRAM 的数据位宽 * 可参考结构体 \ref GX_I2S_BIT_SIZE。 ### 最大支持声道数 * `I2S RX` 最大支持 4 声道输入(PCM 通路在选择声道(\ref GX_I2S_RX_PCM 结构体中的 channel 成员中的 channel_sel)时,最大选择 4) * `I2S TX` 最大支持 4 声道输出。可选择的数据来源参考 \ref GX_I2S_TX_CH_SEL。 ### 交织与非交织 - 对于 `I2S TX` ,支持从内存中读取交织和非交织数据。 - 交织只支持两声道存储,非交织支持所有声道存储 - 对于 `I2S RX` ,仅支持向内存中写入非交织数据。 ### Route PCM - 单个 buffer 的大小,描述 pcm buffer 的长度,单位字节。 - 单个 buffer 大小必须为 64 的倍数 - 非交织形式时,此 buffer 为一个声道数据存放的空间,每个通路的 buffer 大小一致 - 交织形式时,此 buffer 大小为两声道所有数据存放的空间 - 一帧单个声道的 pcm 样点数(中断上报 pcm 样点数) - 一帧的样点数建议是 64 的倍数,非 64 的倍数中断时间间隔会存在较小误差 - 对于 `I2S RX` ,pcm buffer 循环写模式,buffer 大小必须大于等于两帧 - 对于 `I2S TX` ,建议一帧样点数大于等于 512 - 每个 buffer 的起始地址 (物理地址) - buffer 的起始地址必须 8 字节对齐 ## I2S IN(I2S RX)配置 - 可以通过 \ref gx_i2s_rx_config 接口配置 I2S RX 模块。配置结构体参考 \ref GX_I2S_RX。 - 示例代码: ```c gx_i2s_init(); GX_I2S_RX_PARAM rx = { .frequence = 12288000, //i2s mclk频率 .clk_mode = GX_I2S_CLK_MODE_MASTER, //时钟模式 master 模式 .data_format = GX_I2S_DATA_FORMAT_I2S, //数据格式标准 i2s .sample_rate = GX_I2S_SAMPLE_RATE_16KHZ, //采样率 16k .pcm_length = GX_I2S_PCM_LENGTH_16BIT, //传输位宽 16bit .bclk_sel = GX_I2S_BCLK_SEL_64FS, //bclk 配置 64fs .fsync_mode = GX_I2S_FSYNC_MODE_LONG_FRAME, //同步帧格式长帧同步,该配置在 TDM 模式下才会生效 }; gx_i2s_rx_config(&rx); GX_I2S_RX_PCM pcm = { .bit_size = GX_I2S_BIT_SIZE_32BIT, //存储位宽 32bit .buffer_size = 1024, //数据存储 buffer 大小,实际使用按需配置 .frame_samples = 128, //一帧的样点数,实际使用按需配置 //其他成员实际使用时按需配置 }; unsigned int buffer_num = 2; //PCM buffer 数量,实际使用按需配置 for (int i = 0; i < buffer_num; ++i) { pcm.channel[i].endian = GX_I2S_PCM_ENDIAN_LITTLE_16BIT; //数据存储大小端配置 16bit 小端存储 pcm.channel[i].channel_sel = i; //数据来源声道选择,实际使用按需配置 pcm.channel[i].buffer_saddr = 0x20000000; //数据存储 buffer 起始地址,实际使用按需配置 pcm.channel[i].work_enable = 1; } gx_i2s_rx_start(&pcm) ``` ## I2S OUT(I2S TX)配置 - 可以通过 \ref gx_i2s_tx_config 接口配置 I2S RX 模块。配置结构体参考 \ref GX_I2S_TX。 - 示例代码: ```c gx_i2s_init(); GX_I2S_TX_PARAM tx = { .frequence = 12288000, //i2s mclk频率 .clk_mode = GX_I2S_CLK_MODE_MASTER, //时钟模式 master 模式 .data_format = GX_I2S_DATA_FORMAT_I2S, //数据格式标准 i2s .sample_rate = GX_I2S_SAMPLE_RATE_16KHZ, //采样率 16k .pcm_length = GX_I2S_PCM_LENGTH_16BIT, //传输位宽 16bit .bclk_sel = GX_I2S_BCLK_SEL_64FS, //bclk 配置 64fs .fsync_mode = GX_I2S_FSYNC_MODE_SHORT_FRAME, //同步帧格式短帧同步,该配置在 TDM 模式下才会生效 .ch_sel[0] = GX_I2S_TX_CH_SEL_I2S_TX_PCM_0, //声道数据来源选择 I2S OUT PCM0 .ch_sel[1] = GX_I2S_TX_CH_SEL_NULL, //声道数据来源选择静音 .ch_sel[2] = GX_I2S_TX_CH_SEL_NULL, .ch_sel[3] = GX_I2S_TX_CH_SEL_NULL, //该芯片最大可用 4 个声道,其余声道配置无效,且若来源选择不是来自于 I2S PCM buffer 后续 PCM 相关配置可以不用配置 }; gx_i2s_tx_config(&tx); GX_I2S_TX_PCM pcm = { .bit_size = GX_I2S_BIT_SIZE_16BIT, //存储位宽 16bit .interleave_en = 0, //数据交织与非交织配置;配置 0 为非交织,1 为交织 .endian = GX_I2S_PCM_ENDIAN_LITTLE_16BIT; //数据存储大小端配置 .channel_num = 2, //最大 4 .buffer_size = 1024, //数据存储 buffer 大小,实际使用按需配置 //其他成员按需配置 }; for (int i = 0; i < pcm.channel_num; ++i) { pcm.buffer_saddr[i] = 0x20000000; //数据存储 buffer 起始地址,实际使用按需配置 } gx_i2s_tx_start(&pcm); GX_I2S_TX_FRAME frame = { .frame_saddr = 0, //新的一帧的起始地址(相对地址),实际使用时按需配置 .frame_samples = 1024, //新的一帧样点数,实际使用按需配置 }; gx_i2s_tx_push_frame(&frame);//配置新的一帧,这里只推了新的一帧,如果需要连续推帧,可在配置新的一帧pcm申请中断的中断回调函数里进行 ``` ## 中断类型 ### I2S IN * 一帧数据录制完成中断。 * 通过 \ref gx_i2s_rx_start 配置 \ref GX_I2S_RX_PCM 的 callback_func 即可实现中断注册。 * 写通路 AHB 出错中断。 ### I2S OUT * 配置新的一帧数据申请中断。 * 通过 \ref gx_i2s_tx_start 配置 \ref GX_I2S_TX_PCM 的 callback_func 即可实现中断。 * 读通路 AHB 出错中断。 * I2S OUT SLAVE 精简模式 MCLK 配置出错中断。 :::{note} 当有报该错误中断时,将 MCLK 时钟微调频率变高即可解决。 ::: * I2S OUT 模式内部 FIFO 上溢下溢出错中断。 :::{note} 当有报该错误中断时,说明数据来源的采样率和播放的采样时钟不一致。 ::: ### ERROR - 错误中断类型见 \ref GX_I2S_ERR_CB_MODE 结构体。 - 通过 \ref gx_i2s_init 配置 \ref GX_I2S_CFG 的 err_cb 实现中断,中断错误处理函数: \ref GX_I2S_ERR_CB ## 接口时序说明 ### 标准 I2S 格式 - 在 BCLK 的下降沿,LRCLK 信号先于 DATA 信号一个 BCLK 时钟周期开始变化,即 LRCLK 信号从当前通道数据的第一个位之前的一个时钟开始有效,并在当前通道数据发送结束前一个 BCLK 时钟周期变化。DATA 信号线首先传输音频数据的最高有效位。 ![](../../../../gximage/gximage51_i2s.drawio.svg) ### I2S 左对齐 - 左声道的数据 MSB 在 LRCLK 上升沿之后 BCLK 的第一个上升沿有效;右声道的数据 MSB 在 LRCLK 下降沿之后 BCLK 第一个上升沿有效。 ### I2S 右对齐 - 标准右对齐,也叫 `日本格式` 或 `SONY 格式`,右对齐格式左声道的数据 LSB 在 LRCLK 下降沿的前一个 BCLK 上升沿有效,右声道的数据 LSB 在 LRCLK 上升沿的前一个 BCLK 上升沿有效。 ![](../../../../gximage/gximage52_i2s_justified.drawio.svg) ### TDM 格式 - 根据 DATA 相对于同步时钟 FSYNC 的位置,TDM 分两种基本模式: - `长帧同步模式(long frame sync mode)`:数据在 FSYNC 有效后,BCLK 的第 1 个上升沿有效 - `短帧同步模式(short frame sync mode)`:数据在 FSYNC 有效后,BCLK 的第 2 个上升沿有效 ![](../../../../gximage/gximage53_i2s_tdm.drawio.svg) :::{note} TDM 中 FSYNC 信号对应于 I2S 下 LRCLK。 :::