Загрузка данных
int main(void)
{
const struct device *const i2s_dev_rx = DEVICE_DT_GET(I2S_RX_NODE);
const struct device *const i2s_dev_tx = DEVICE_DT_GET(I2S_TX_NODE);
struct i2s_config config_rx;
struct i2s_config config_tx;
bool streaming = false;
printk("I2S asynchronous Audio: SGTL5000 (RX) & TFA9882 (TX)\n");
const struct device *const rx_dev = DEVICE_DT_GET(DT_NODELABEL(rx_audio_codec));
const struct device *const tx_dev = DEVICE_DT_GET(DT_NODELABEL(tx_audio_codec));
struct audio_codec_cfg audio_cfg;
if (!device_is_ready(rx_dev) || !device_is_ready(tx_dev)) {
printk("Audio codecs are not ready\n");
return 0;
}
/* 1. RX Capture Config */
audio_cfg.dai_route = AUDIO_ROUTE_CAPTURE;
audio_cfg.dai_type = AUDIO_DAI_TYPE_I2S;
audio_cfg.dai_cfg.i2s.word_size = SAMPLE_BIT_WIDTH_RX;
audio_cfg.dai_cfg.i2s.channels = NUMBER_OF_CHANNELS;
audio_cfg.dai_cfg.i2s.format = I2S_FMT_DATA_FORMAT_I2S;
audio_cfg.dai_cfg.i2s.options = I2S_OPT_BIT_CLK_SLAVE | I2S_OPT_FRAME_CLK_SLAVE;
audio_cfg.dai_cfg.i2s.frame_clk_freq = SAMPLE_FREQ_RX;
#if 0
audio_cfg.dai_cfg.i2s.mem_slab = &mem_slab_rx;
#else
audio_cfg.dai_cfg.i2s.mem_slab = &mem_slab;
#endif
audio_cfg.dai_cfg.i2s.block_size = BLOCK_SIZE_RX;
audio_cfg.mclk_freq = AUDIO_MCLK_FREQ;
audio_codec_configure(rx_dev, &audio_cfg);
/* 2. TX Playback Config */
audio_cfg.dai_route = AUDIO_ROUTE_PLAYBACK;
audio_cfg.dai_cfg.i2s.word_size = SAMPLE_BIT_WIDTH_TX;
audio_cfg.dai_cfg.i2s.frame_clk_freq = SAMPLE_FREQ_TX;
#if 0
audio_cfg.dai_cfg.i2s.mem_slab = &mem_slab_tx;
#else
audio_cfg.dai_cfg.i2s.mem_slab = &mem_slab;
#endif
audio_cfg.dai_cfg.i2s.block_size = BLOCK_SIZE_TX;
audio_codec_configure(tx_dev, &audio_cfg);
k_msleep(500);
if (!init_buttons()) return 0;
if (!device_is_ready(i2s_dev_rx) || !device_is_ready(i2s_dev_tx)) {
printk("SAI2 Devices are not ready\n");
return 0;
}
/* 3. Setings for I2S/SAI */
config_rx.word_size = SAMPLE_BIT_WIDTH_RX;
config_rx.channels = NUMBER_OF_CHANNELS;
config_rx.format = I2S_FMT_DATA_FORMAT_I2S;
config_rx.options = I2S_OPT_BIT_CLK_MASTER | I2S_OPT_FRAME_CLK_MASTER;
config_rx.timeout = TIMEOUT;
/* RX I2S config */
config_rx.frame_clk_freq = SAMPLE_FREQ_RX;
#if 0
config_rx.mem_slab = &mem_slab_rx;
#else
config_rx.mem_slab = &mem_slab;
#endif
config_rx.block_size = BLOCK_SIZE_RX;
i2s_configure(i2s_dev_rx, I2S_DIR_RX, &config_rx);
/* TX I2S config */
config_tx = config_rx;
config_tx.word_size = SAMPLE_BIT_WIDTH_TX;
config_tx.frame_clk_freq = SAMPLE_FREQ_TX;
#if 0
config_tx.mem_slab = &mem_slab_tx;
#else
config_tx.mem_slab = &mem_slab;
#endif
config_tx.block_size = BLOCK_SIZE_TX;
i2s_configure(i2s_dev_tx, I2S_DIR_TX, &config_tx);
#ifndef MY_CODE
/* 1. Set explicit volume to safe maximum level (100%) */
audio_property_value_t vol_val = { .vol = 100 };
audio_codec_set_property(tx_dev, AUDIO_PROPERTY_OUTPUT_VOLUME, AUDIO_CHANNEL_ALL, vol_val);
audio_codec_set_property(rx_dev, AUDIO_PROPERTY_INPUT_VOLUME, AUDIO_CHANNEL_ALL, vol_val);
/* 2. Explicitly disable output channel mutes */
audio_property_value_t mute_val = { .mute = false };
audio_codec_set_property(tx_dev, AUDIO_PROPERTY_OUTPUT_MUTE, AUDIO_CHANNEL_ALL, mute_val);
audio_codec_set_property(rx_dev, AUDIO_PROPERTY_INPUT_MUTE, AUDIO_CHANNEL_ALL, mute_val);
audio_codec_start_output(rx_dev);
#endif
if (!streaming) {
if (!prepare_transfer(i2s_dev_rx, i2s_dev_tx)) {
printk("Failed to prepare TX buffers\n");
}
if (!trigger_command(i2s_dev_rx, i2s_dev_tx, I2S_TRIGGER_START)) {
}
streaming = true;
printk("Stream started\n");
} else {
if (!trigger_command(i2s_dev_rx, i2s_dev_tx, I2S_TRIGGER_DROP)) {
}
streaming = false;
printk("Stream stopped\n");
}
/* 4. Main cycle */
while (streaming) {
void *rx_block = NULL;
void *tx_block = NULL;
size_t rx_size;
int ret;
/* Read RX (16 kHz) */
ret = i2s_read(i2s_dev_rx, &rx_block, &rx_size);
if (ret < 0) {
printk("i2s_read failed: %d\n", ret);
break;
}
/* Proccess rx data */
process_block_data(rx_block, SAMPLES_PER_BLOCK_RX);
#if 0
/* Allocate TX block(32 kHz) */
ret = k_mem_slab_alloc(&mem_slab_tx, &tx_block, K_NO_WAIT);
if (ret < 0) {
printk("Failed to allocate TX block: %d\n", ret);
k_mem_slab_free(&mem_slab_rx, rx_block);
break;
}
/* Upsample to 32kHz */
audio_upsample_to_32k((const int16_t *)rx_block, (int32_t *)tx_block,
NUMBER_OF_CHANNELS, SAMPLE_FREQ_RX);
k_mem_slab_free(&mem_slab_rx, rx_block);
/* Send to TX (32 kHz) */
ret = i2s_write(i2s_dev_tx, tx_block, BLOCK_SIZE_TX);
if (ret < 0) {
printk("i2s_write failed: %d\n", ret);
k_mem_slab_free(&mem_slab_tx, tx_block);
break;
}
#else
#if 0//ndef MY_CODE
int16_t *mas = rx_block;
for(int i=0; i<rx_size; i++)
{
if(mas[i] != 0)
printk("data[%d]=0x%X\n",i,mas[i]);
}
#endif
#if 0
ret = i2s_write(i2s_dev_tx, rx_block, rx_size);
if (ret < 0) {
printk("i2s_write failed: %d\n", ret);
//k_mem_slab_free(&mem_slab_tx, tx_block);
break;
}
#else
void *mem_block;
uint32_t block_size = 0;
/* If not using DMIC, play a sine wave 440Hz */
mem_block = (void *)&__16kHz16bit_stereo_sine_pcm;
block_size = __16kHz16bit_stereo_sine_pcm_len;
ret = i2s_buf_write(i2s_dev_tx, mem_block, block_size);
#endif
#endif
}
return 0;
}
Логи работы:
*** Booting Zephyr OS build 3ae962fd364a ***
I2S asynchronous Audio: SGTL5000 (RX) & TFA9882 (TX)
[00:00:00.055,000] <inf> wolfson_wm8960: Codec protocol: 0x2
wm8960_audio_fmt_config(175) mclk=12288750 sample_rate=16000 divider=768
SAI_GetCommonConfig(364) config=0x80006700 saiChannelMask=0x1
i2s_mcux_config(560) frame_clk_slave=0 bit_clk_slave=0
SAI_RxSetConfig(1339) syncMode=0
SAI_GetCommonConfig(364) config=0x80006700 saiChannelMask=0x1
i2s_mcux_config(560) frame_clk_slave=0 bit_clk_slave=0
SAI_TxSetConfig(1222) syncMode=0
reg[0x0] = 0xA011
reg[0x2] = 0x72
reg[0x4] = 0x11
reg[0x6] = 0x130
reg[0xA] = 0x10
reg[0xE] = 0x3200
reg[0x10] = 0x3C3C
reg[0x14] = 0x15F
reg[0x20] = 0xCC
reg[0x22] = 0x1818
reg[0x24] = 0x136
reg[0x26] = 0x20
reg[0x28] = 0x1F1
reg[0x2A] = 0x273
reg[0x2C] = 0x304
reg[0x2E] = 0x1F1F
reg[0x30] = 0x4062
reg[0x32] = 0x5000
reg[0x34] = 0x0
reg[0x36] = 0x17
reg[0x3A] = 0x4000
reg[0x3C] = 0x0
reg[0x100] = 0x11
reg[0x102] = 0x0
reg[0x104] = 0x40
reg[0x106] = 0x51F
reg[0x108] = 0x3
reg[0x10A] = 0x40
reg[0x10C] = 0x0
reg[0x10E] = 0x0
reg[0x110] = 0x0
reg[0x116] = 0x2F
reg[0x118] = 0x2F
reg[0x11A] = 0x2F
reg[0x11C] = 0x2F
reg[0x11E] = 0x2F
reg[0x120] = 0x8000
reg[0x122] = 0x0
reg[0x124] = 0x5100
reg[0x126] = 0x1473
reg[0x128] = 0x28
reg[0x12A] = 0x50
reg[0x12C] = 0x0
reg[0x12E] = 0x0
reg[0x130] = 0x0
reg[0x132] = 0x0
reg[0x134] = 0x0
reg[0x136] = 0x0
reg[0x138] = 0x0
reg[0x13A] = 0x0
[00:00:00.596,000] <inf> nxp_sgtl5000: Streaming started: Unmuting DAC
Stream started
[00:00:01.001,000] <wrn> dev_i2s_mcux: TX input queue empty!
[00:00:01.001,000] <wrn> dev_i2s_mcux: TX is paused.
[00:00:01.002,000] <err> dev_i2s_mcux: buffer alloc from slab 0x8000241c err -12
[00:00:01.003,000] <wrn> dev_i2s_mcux: TX is resumed
[00:00:01.103,000] <wrn> dev_i2s_mcux: TX input queue empty!
[00:00:01.103,000] <wrn> dev_i2s_mcux: TX is paused.
[00:00:01.105,000] <wrn> dev_i2s_mcux: TX is resumed
[00:00:01.204,000] <wrn> dev_i2s_mcux: TX input queue empty!
[00:00:01.204,000] <wrn> dev_i2s_mcux: TX is paused.
i2s_read failed: -5