Загрузка данных


#define SAMPLE_FREQUENCY    16000
#define NUMBER_OF_CHANNELS  1
#define SAMPLE_BIT_WIDTH    16
#define BYTES_PER_SAMPLE    2

/* 20 ms - оптимальный интервал для VoIP (16000 * 0.02 = 320 семплов) */
#define SAMPLES_PER_BLOCK   ((SAMPLE_FREQUENCY / 50) * NUMBER_OF_CHANNELS)
#define ZEPHYR_AUDIO_BLOCK_SIZE  (BYTES_PER_SAMPLE * SAMPLES_PER_BLOCK)

/* 6 блоков по 20мс = 120мс буферизации на каждое направление */
#define ZEPHYR_AUDIO_BLOCK_COUNT 6

typedef void I2S_Stream;

/* Создаем раздельные пулы памяти для RX и TX в быстрой секции DTCM */
K_MEM_SLAB_DEFINE_IN_SECT_STATIC(mem_slab_rx, __dtcm_noinit_section, 
                                 ZEPHYR_AUDIO_BLOCK_SIZE, ZEPHYR_AUDIO_BLOCK_COUNT, 4);

K_MEM_SLAB_DEFINE_IN_SECT_STATIC(mem_slab_tx, __dtcm_noinit_section, 
                                 ZEPHYR_AUDIO_BLOCK_SIZE, ZEPHYR_AUDIO_BLOCK_COUNT, 4);

int zephyr_i2s_audio_init(void)
{
    struct i2s_config config_rx;
    struct i2s_config config_tx;

#if DT_NODE_HAS_STATUS(DT_NODELABEL(audio_codec), okay)
    const struct device *const codec_dev = DEVICE_DT_GET(DT_NODELABEL(audio_codec));
    struct audio_codec_cfg audio_cfg;

    audio_cfg.dai_route = AUDIO_ROUTE_PLAYBACK_CAPTURE;
    audio_cfg.dai_type = AUDIO_DAI_TYPE_I2S;
    audio_cfg.dai_cfg.i2s.word_size = SAMPLE_BIT_WIDTH;
    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_FRAME_CLK_MASTER;
    audio_cfg.dai_cfg.i2s.frame_clk_freq = SAMPLE_FREQUENCY;
    /* Кодеку отдаем любой, он использует его для общих параметров DAI */
    audio_cfg.dai_cfg.i2s.mem_slab = &mem_slab_tx; 
    audio_cfg.dai_cfg.i2s.block_size = ZEPHYR_AUDIO_BLOCK_SIZE;

    audio_codec_configure(codec_dev, &audio_cfg);
    k_msleep(100); // 1000мс многовато, 100мс обычно хватает для стабилизации
#else
    printk("Error: No audio_codec in DTS!\n");
    return -1;
#endif

    if (!device_is_ready(i2s_dev_rx) || !device_is_ready(i2s_dev_tx)) {
        printk("I2S devices not ready\n");
        return -1;
    }

    /* Настройка RX (Capture) */
    config_rx.word_size = SAMPLE_BIT_WIDTH;
    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.frame_clk_freq = SAMPLE_FREQUENCY;
    config_rx.mem_slab = &mem_slab_rx; // Свой пул
    config_rx.block_size = ZEPHYR_AUDIO_BLOCK_SIZE;
    config_rx.timeout = TIMEOUT;

    /* Настройка TX (Playback) */
    config_tx = config_rx;
    config_tx.mem_slab = &mem_slab_tx; // Свой пул

    if (i2s_configure(i2s_dev_rx, I2S_DIR_RX, &config_rx) < 0) {
        printk("Failed to configure RX stream\n");
        return -1;
    }

    if (i2s_configure(i2s_dev_tx, I2S_DIR_TX, &config_tx) < 0) {
        printk("Failed to configure TX stream\n");
        return -1;
    }

    return 0;
}