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


/* Исправленная функция подготовки трансфера: блоки берем СТРОГО из пула TX */
static bool prepare_transfer(const struct device *i2s_dev_tx)
{
    int ret;

    for (int i = 0; i < ZEPHYR_AUDIO_INITIAL_BLOCKS; ++i)
    {
        void *mem_block;

        /* ОШИБКА ИСПРАВЛЕНА: используем mem_slab_tx */
        ret = k_mem_slab_alloc(&mem_slab_tx, &mem_block, K_NO_WAIT);
        if (ret < 0)
        {
            printk("Failed to allocate TX block from mem_slab_tx: %d\n", ret);
            return false;
        }

        memset(mem_block, 0, ZEPHYR_AUDIO_BLOCK_SIZE);

        ret = i2s_write(i2s_dev_tx, mem_block, ZEPHYR_AUDIO_BLOCK_SIZE);
        if (ret < 0)
        {
            printk("Failed to write block %d: %d\n", i, ret);
            return false;
        }
    }

    return true;
}

/* Исправленная функция старта: учитываем дуплекс SAI */
int zephyr_i2s_start(uint8_t audio_in)
{
    printf("%s(%d) audio_in=%d\n", __FUNCTION__, __LINE__, audio_in);
    
    /* Если один из потоков уже запустил устройство, выходим */
    if (start_stream) {
        return 0;
    }

    /* Пре-фил очереди нужен только для воспроизведения (TX) */
    if (!prepare_transfer(i2s_dev_tx))
    {
        return -1;
    }

    /* Запускаем оба плеча одновременно для синхронизации */
    if (!trigger_command(i2s_dev_rx, i2s_dev_tx, I2S_TRIGGER_START))
    {
        return -1;
    }
    
    start_stream = 1;
    return 0;
}

/* Исправленная инициализация: настройка кодека и SAI с разными Slab */
int zephyr_i2s_audio_init(void)
{
    struct i2s_config config;

#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;
    /* Кодеку указываем любой пул (обычно используется только для валидации) */
    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); 
#else
    printk("No audio_codec found 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;
    }

    /* Общие параметры SAI */
    config.word_size = SAMPLE_BIT_WIDTH;
    config.channels = NUMBER_OF_CHANNELS;
    config.format = I2S_FMT_DATA_FORMAT_I2S;
    config.options = I2S_OPT_BIT_CLK_MASTER | I2S_OPT_FRAME_CLK_MASTER;
    config.frame_clk_freq = SAMPLE_FREQUENCY;
    config.block_size = ZEPHYR_AUDIO_BLOCK_SIZE;
    config.timeout = TIMEOUT;

    /* ИСПРАВЛЕНО: Теперь вызываем функцию, которая разделяет mem_slab_rx и mem_slab_tx */
    if (!configure_streams(i2s_dev_rx, i2s_dev_tx, &config))
    {
        return -1;
    }
    return 0;
}