kopia lustrzana https://github.com/espressif/esp-idf
113 wiersze
4.1 KiB
C
113 wiersze
4.1 KiB
C
/*
|
|
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
|
|
*
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
*/
|
|
|
|
#include <inttypes.h>
|
|
#include "soc/soc_caps.h"
|
|
#include "stdatomic.h"
|
|
#if SOC_LP_VAD_SUPPORTED
|
|
#include "esp_check.h"
|
|
#include "esp_err.h"
|
|
#include "driver/lp_i2s_vad.h"
|
|
#include "esp_heap_caps.h"
|
|
#include "hal/lp_i2s_ll.h"
|
|
#include "hal/lp_i2s_hal.h"
|
|
#include "esp_private/lp_i2s_private.h"
|
|
|
|
#define LP_VAD_MEM_ALLOC_CAPS (MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT)
|
|
|
|
static const char *LP_VAD_TAG = "LP_VAD";
|
|
|
|
typedef enum {
|
|
VAD_FSM_INIT,
|
|
VAD_FSM_ENABLE,
|
|
} vad_fsm_t;
|
|
|
|
typedef struct vad_unit_ctx_t {
|
|
lp_i2s_soc_handle_t hw;
|
|
lp_vad_t vad_id;
|
|
vad_fsm_t fsm;
|
|
} vad_unit_ctx_t;
|
|
|
|
static atomic_bool s_vad_id_claimed[SOC_ADC_PERIPH_NUM] = {ATOMIC_VAR_INIT(false)};
|
|
|
|
static bool s_vad_claim(lp_vad_t vad_id)
|
|
{
|
|
bool false_var = false;
|
|
return atomic_compare_exchange_strong(&s_vad_id_claimed[vad_id], &false_var, true);
|
|
}
|
|
|
|
static bool s_vad_free(lp_vad_t vad_id)
|
|
{
|
|
bool true_var = true;
|
|
return atomic_compare_exchange_strong(&s_vad_id_claimed[vad_id], &true_var, false);
|
|
}
|
|
|
|
esp_err_t lp_i2s_vad_new_unit(lp_vad_t vad_id, const lp_vad_init_config_t *init_config, vad_unit_handle_t *ret_unit)
|
|
{
|
|
esp_err_t ret = ESP_OK;
|
|
ESP_RETURN_ON_FALSE(init_config, ESP_ERR_INVALID_ARG, LP_VAD_TAG, "invalid arg");
|
|
ESP_RETURN_ON_FALSE(init_config->lp_i2s_chan, ESP_ERR_INVALID_ARG, LP_VAD_TAG, "LP I2S not initialised");
|
|
ESP_RETURN_ON_FALSE(init_config->vad_config.init_frame_num >= LP_VAD_LL_INIT_FRAME_MIN && init_config->vad_config.init_frame_num <= LP_VAD_LL_INIT_FRAME_MAX, ESP_ERR_INVALID_ARG, LP_VAD_TAG, "invalid init frame num");
|
|
|
|
bool success_claim = s_vad_claim(vad_id);
|
|
ESP_RETURN_ON_FALSE(success_claim, ESP_ERR_NOT_FOUND, LP_VAD_TAG, "vad%"PRId32" is already in use", vad_id);
|
|
|
|
vad_unit_ctx_t *unit = heap_caps_calloc(1, sizeof(vad_unit_ctx_t), LP_VAD_MEM_ALLOC_CAPS);
|
|
ESP_GOTO_ON_FALSE(unit, ESP_ERR_NO_MEM, err, LP_VAD_TAG, "no mem for unit");
|
|
|
|
unit->hw = lp_i2s_get_soc_handle(init_config->lp_i2s_chan);
|
|
ESP_LOGD(LP_VAD_TAG, "unit->hw: %p", unit->hw);
|
|
lp_vad_ll_set_init_frame_num(unit->hw, init_config->vad_config.init_frame_num);
|
|
lp_vad_ll_set_init_min_energy(unit->hw, init_config->vad_config.min_energy_thresh);
|
|
lp_vad_ll_set_speak_activity_thresh(unit->hw, init_config->vad_config.speak_activity_thresh);
|
|
lp_vad_ll_set_non_speak_activity_thresh(unit->hw, init_config->vad_config.non_speak_activity_thresh);
|
|
lp_vad_ll_set_min_speak_activity_thresh(unit->hw, init_config->vad_config.min_speak_activity_thresh);
|
|
lp_vad_ll_set_max_speak_activity_thresh(unit->hw, init_config->vad_config.max_speak_activity_thresh);
|
|
lp_vad_ll_skip_band_energy(unit->hw, init_config->vad_config.skip_band_energy_thresh);
|
|
unit->fsm = VAD_FSM_INIT;
|
|
*ret_unit = unit;
|
|
|
|
return ESP_OK;
|
|
err:
|
|
bool success_free = s_vad_free(vad_id);
|
|
assert(success_free);
|
|
|
|
return ret;
|
|
}
|
|
|
|
esp_err_t lp_i2s_vad_enable(vad_unit_handle_t unit)
|
|
{
|
|
ESP_RETURN_ON_FALSE(unit, ESP_ERR_INVALID_ARG, LP_VAD_TAG, "invalid arg");
|
|
ESP_RETURN_ON_FALSE(unit->fsm == VAD_FSM_INIT, ESP_ERR_INVALID_STATE, LP_VAD_TAG, "The driver is enabled already");
|
|
|
|
lp_vad_ll_enable(unit->hw, true);
|
|
unit->fsm = VAD_FSM_ENABLE;
|
|
return ESP_OK;
|
|
}
|
|
|
|
esp_err_t lp_i2s_vad_disable(vad_unit_handle_t unit)
|
|
{
|
|
ESP_RETURN_ON_FALSE(unit, ESP_ERR_INVALID_ARG, LP_VAD_TAG, "invalid arg");
|
|
ESP_RETURN_ON_FALSE(unit->fsm == VAD_FSM_ENABLE, ESP_ERR_INVALID_STATE, LP_VAD_TAG, "The driver is not enabled yet");
|
|
|
|
lp_vad_ll_enable(unit->hw, false);
|
|
unit->fsm = VAD_FSM_INIT;
|
|
return ESP_OK;
|
|
}
|
|
|
|
esp_err_t lp_i2s_vad_del_unit(vad_unit_handle_t unit)
|
|
{
|
|
ESP_RETURN_ON_FALSE(unit, ESP_ERR_INVALID_ARG, LP_VAD_TAG, "invalid arg");
|
|
ESP_RETURN_ON_FALSE(unit->fsm == VAD_FSM_INIT, ESP_ERR_INVALID_STATE, LP_VAD_TAG, "The driver is still in enabled state");
|
|
|
|
bool success_free = s_vad_free(unit->vad_id);
|
|
ESP_RETURN_ON_FALSE(success_free, ESP_ERR_NOT_FOUND, LP_VAD_TAG, "vad%"PRId32" isn't in use", unit->vad_id);
|
|
|
|
free(unit);
|
|
return ESP_OK;
|
|
}
|
|
#endif /* SOC_LP_VAD_SUPPORTED */
|