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


static bool configure_streams(const struct device *i2s_dev_rx,
                              const struct device *i2s_dev_tx,
                              const struct i2s_config *base_config)
{
    int ret;
    struct i2s_config config = *base_config;

    config.mem_slab = &mem_slab_rx;
    ret = i2s_configure(i2s_dev_rx, I2S_DIR_RX, &config);
    if (ret < 0) {
        printf("Failed to configure RX: %d\n", ret);
        return false;
    }

    config.mem_slab = &mem_slab_tx;
    ret = i2s_configure(i2s_dev_tx, I2S_DIR_TX, &config);
    if (ret < 0) {
        printf("Failed to configure TX: %d\n", ret);
        return false;
    }

    return true;
}

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;
        ret = k_mem_slab_alloc(&mem_slab_tx, &mem_block, K_NO_WAIT);
        if (ret < 0) {
            printf("Failed to allocate TX block %d: %d\n", i, ret);
            return false;
        }
        memset(mem_block, 0, current_audio_block_size);
        ret = i2s_write(i2s_dev_tx, mem_block, current_audio_block_size);
        if (ret < 0) {
            printf("Failed to write block %d: %d\n", i, ret);
            return false;
        }
    }
    return true;
}

static bool trigger_command(const struct device *i2s_dev_rx,
                            const struct device *i2s_dev_tx,
                            enum i2s_trigger_cmd cmd)
{
    int ret;
    if (i2s_dev_rx == i2s_dev_tx) {
        ret = i2s_trigger(i2s_dev_rx, I2S_DIR_BOTH, cmd);
        if (ret == 0) return true;
        if (ret != -ENOSYS) {
            printf("Failed to trigger command %d: %d\n", cmd, ret);
            return false;
        }
    }
    ret = i2s_trigger(i2s_dev_rx, I2S_DIR_RX, cmd);
    if (ret < 0) {
        printf("Failed to trigger command %d on RX: %d\n", cmd, ret);
        return false;
    }
    ret = i2s_trigger(i2s_dev_tx, I2S_DIR_TX, cmd);
    if (ret < 0) {
        printf("Failed to trigger command %d on TX: %d\n", cmd, ret);
        return false;
    }
    return true;
}

int zephyr_i2s_start(uint8_t audio_in)
{
    printf("%s(%d) audio_in=%d\n",__FUNCTION__,__LINE__, audio_in);
    if (start_stream) {
        return 0;
    }
    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;
}

int zephyr_i2s_stop(uint8_t audio_in)
{
    printf("%s(%d) start_stream=%d\n",__FUNCTION__,__LINE__, start_stream);
    if(start_stream) {
        start_stream = 0;
        if (!trigger_command(i2s_dev_rx, i2s_dev_tx, I2S_TRIGGER_DROP)) {
            return -1;
        }
    }
    return 0;
}

int zephyr_i2s_open_stream(I2S_Stream **stream, uint8_t *buf, uint8_t audio_in)
{
    struct i2s_strm *i2s_stream;
    struct i2s_config config;
    int ret = 0;
    uint32_t dynamic_block_size = ((current_sample_rate / ZEPHYR_AUDIO_DIV_SIZE) * NUMBER_OF_CHANNELS * BYTES_PER_SAMPLE);
    current_audio_block_size = dynamic_block_size;

    printf("%s(%d) Set sample_rate=%u block_size=%u\n",__FUNCTION__,__LINE__,current_sample_rate,dynamic_block_size);

    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 = current_sample_rate;
    audio_cfg.dai_cfg.i2s.mem_slab = &mem_slab_tx;
    audio_cfg.dai_cfg.i2s.block_size = dynamic_block_size;
    audio_cfg.mclk_freq = AUDIO_MCLK_FREQ;
    audio_codec_configure(codec_dev, &audio_cfg);

    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 = current_sample_rate;
    config.block_size = dynamic_block_size;
    config.timeout = TIMEOUT;
    if (!configure_streams(i2s_dev_rx, i2s_dev_tx, &config)) {
        printf("Failed to reconfigure streams for %u Hz\n", current_sample_rate);
        return -1;
    }
    /* 2. Стандартная аллокация потока */
    i2s_stream = i2s_str_alloc();
    if (!i2s_stream) {
        printf("Cannot allocate i2s_strm\n");
        return -1;
    }
    i2s_stream->devid = (audio_in) ? 1 : 2;
    i2s_stream->i2s_buf = buf;
    i2s_stream->state = I2S_STREAM_RUNNING;
    i2s_stream->block_size = dynamic_block_size;
    *stream = i2s_stream;
    pthread_attr_init(&i2s_stream->threadAttr);
#ifndef USE_DTCM
    pthread_attr_setstacksize(&i2s_stream->threadAttr, 1024);
#else
    if (audio_in) {
        ret = pthread_attr_setstack(&i2s_stream->threadAttr, i2s_dev_in_dtcm_stack, 1024);
    } else {
        ret = pthread_attr_setstack(&i2s_stream->threadAttr, i2s_dev_out_dtcm_stack, 1024);
    }
    if (ret != 0) {
        printf("[POSIX_STACK] ERROR: Failed to assign DTCM memory to thread attributes: %d\n", ret);
        return -1;
    }
#endif
    ret = pthread_create(&i2s_stream->i2s_thread, &i2s_stream->threadAttr,
    audio_in ? i2s_thread_in : i2s_thread_out, i2s_stream);
    if (ret != 0) {
        printf("i2s pthread_create failed ret=%d\n", ret);
        return -1;
    }
    pthread_setschedprio(i2s_stream->i2s_thread, I2S_THREAD_PRIORITY);
    if(audio_in)
        pthread_setname_np(i2s_stream->i2s_thread, "i2s_thread_in");
    else
        pthread_setname_np(i2s_stream->i2s_thread, "i2s_thread_out");
    return 0;
}

int zephyr_i2s_close_stream(I2S_Stream *stream)
{
    struct i2s_strm *i2s_stream = (struct i2s_strm *)stream;

    i2s_thread_wakeup(i2s_stream, I2S_STREAM_CLOSED);
    pthread_join(i2s_stream->i2s_thread, NULL);
    pthread_attr_destroy(&i2s_stream->threadAttr);
    i2s_str_free(i2s_stream);
    return 0; // paNoError
}

надо написать код reconfigure, при start_stream - ничего не делаем, выдаём busy, если start_stream - не установлен, переконфигурируем всё на новый PATH