基本功能正常,需要解决首次双击没有效果,首次对话没有反应
This commit is contained in:
@@ -130,6 +130,17 @@ static esp_err_t app_composition_run_plan_a_boot_sequence(void)
|
||||
return err;
|
||||
}
|
||||
|
||||
#if CONFIG_TQ_SCREEN_ENABLE
|
||||
if (lcd_ready) {
|
||||
esp_err_t expression_err = control_plane_request_boot_expression();
|
||||
if (expression_err != ESP_OK) {
|
||||
ESP_LOGW(TAG,
|
||||
"Boot LCD expression request failed: %s",
|
||||
esp_err_to_name(expression_err));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#if CONFIG_TQ_BOOT_TURNTABLE_CALIBRATION_ENABLE
|
||||
app_composition_log_stage(APP_COMPOSITION_BOOT_STAGE_TURNTABLE_CALIBRATION,
|
||||
"turntable_calibration",
|
||||
|
||||
@@ -82,6 +82,7 @@
|
||||
#define CONTROL_PLANE_LOCAL_RESPONDING_EVENT_TASK_STACK_BYTES 4096U
|
||||
#define CONTROL_PLANE_LOCAL_RESPONDING_EVENT_TASK_PRIORITY 5U
|
||||
#define CONTROL_PLANE_LOCAL_RESPONDING_EVENT_QUEUE_LEN 4U
|
||||
#define CONTROL_PLANE_LOCAL_RESPONDING_EVENT_IDLE_EXIT_MS 5000U
|
||||
#define CONTROL_PLANE_MULTIMODAL_BINARY_SUMMARY_INTERVAL 200U
|
||||
#define CONTROL_PLANE_UPLINK_READY_WAIT_MS 6000U
|
||||
#define CONTROL_PLANE_UPLINK_READY_POLL_MS 20U
|
||||
@@ -446,8 +447,14 @@ static void local_responding_event_worker(void *arg)
|
||||
|
||||
local_responding_event_msg_t msg = {0};
|
||||
while (true) {
|
||||
if (xQueueReceive(s_local_responding_event_queue, &msg, portMAX_DELAY) != pdTRUE) {
|
||||
continue;
|
||||
TickType_t idle_ticks = pdMS_TO_TICKS(CONTROL_PLANE_LOCAL_RESPONDING_EVENT_IDLE_EXIT_MS);
|
||||
if (idle_ticks == 0) {
|
||||
idle_ticks = 1;
|
||||
}
|
||||
if (xQueueReceive(s_local_responding_event_queue, &msg, idle_ticks) != pdTRUE) {
|
||||
s_local_responding_event_task = NULL;
|
||||
vTaskDelete(NULL);
|
||||
return;
|
||||
}
|
||||
|
||||
bool should_send = false;
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
#define CONTROL_PLANE_MODEL_CMD_TASK_STACK_SIZE (1024 * 4)
|
||||
#define CONTROL_PLANE_DIRECTION_TASK_STACK_SIZE (1024 * 4)
|
||||
#define CONTROL_PLANE_LCD_RENDER_LOOP_TASK_STACK_SIZE (1024 * 12)
|
||||
#define CONTROL_PLANE_WIFI_STATE_TASK_STACK_SIZE (1024 * 6)
|
||||
#define CONTROL_PLANE_WIFI_STATE_TASK_STACK_SIZE (1024 * 12)
|
||||
#define CONTROL_PLANE_TASK_MONITOR_TASK_STACK_SIZE (1024 * 6)
|
||||
#define CONTROL_PLANE_MODEL_CMD_QUEUE_LEN 4
|
||||
#define CONTROL_PLANE_MODEL_CMD_RECV_TIMEOUT_MS 200
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
#include "esp_err.h"
|
||||
#include "esp_heap_caps.h"
|
||||
#include "esp_log.h"
|
||||
#include "esp_timer.h"
|
||||
#include "esp_opus_dec.h"
|
||||
#include "esp_opus_enc.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
@@ -232,7 +233,6 @@
|
||||
#define MULTIMODAL_PCM_SAMPLE_BYTES 2U
|
||||
#define MULTIMODAL_MIN_DECODER_PCM_BUFFER_BYTES 2048U
|
||||
#define MULTIMODAL_DECODER_BUFFER_GUARD_BYTES 512U
|
||||
#define MULTIMODAL_AUDIO_DOWNSTREAM_IDLE_MUTE_TASK_STACK_BYTES 4096U
|
||||
#define MULTIMODAL_AUDIO_DOWNSTREAM_TX_BOUNCE_BYTES 3200U
|
||||
#define MULTIMODAL_AUDIO_DEFAULT_MIC_CHANNEL ((uint8_t)CONFIG_MULTIMODAL_AUDIO_MIC_CHANNEL)
|
||||
|
||||
@@ -273,7 +273,6 @@ typedef struct {
|
||||
uint8_t *downstream_tx_bounce_buf;
|
||||
size_t downstream_tx_bounce_buf_bytes;
|
||||
uint32_t downstream_playback_generation;
|
||||
uint32_t downstream_audio_activity_generation;
|
||||
volatile bool downstream_decoder_reset_pending;
|
||||
bool downstream_playback_in_progress;
|
||||
bool downstream_output_muted;
|
||||
@@ -281,8 +280,7 @@ typedef struct {
|
||||
bool downstream_output_primed;
|
||||
bool downstream_response_active;
|
||||
bool downstream_response_end_received;
|
||||
TaskHandle_t downstream_idle_mute_task;
|
||||
bool downstream_idle_mute_stop_requested;
|
||||
esp_timer_handle_t downstream_idle_mute_timer;
|
||||
QueueHandle_t downstream_playback_queue;
|
||||
bool downstream_playback_queue_with_caps;
|
||||
TaskHandle_t downstream_playback_task;
|
||||
|
||||
@@ -206,46 +206,24 @@ static void audio_set_uplink_send_task(multimodal_audio_ctx_t *ctx, TaskHandle_t
|
||||
portEXIT_CRITICAL(&s_audio_runtime_lock);
|
||||
}
|
||||
|
||||
static bool audio_get_downstream_idle_mute_stop_requested(const multimodal_audio_ctx_t *ctx)
|
||||
static esp_timer_handle_t audio_get_downstream_idle_mute_timer(const multimodal_audio_ctx_t *ctx)
|
||||
{
|
||||
bool stop_requested = true;
|
||||
esp_timer_handle_t timer = NULL;
|
||||
|
||||
portENTER_CRITICAL(&s_audio_runtime_lock);
|
||||
if (ctx != NULL) {
|
||||
stop_requested = ctx->downstream_idle_mute_stop_requested;
|
||||
timer = ctx->downstream_idle_mute_timer;
|
||||
}
|
||||
portEXIT_CRITICAL(&s_audio_runtime_lock);
|
||||
|
||||
return stop_requested;
|
||||
return timer;
|
||||
}
|
||||
|
||||
static void audio_set_downstream_idle_mute_stop_requested(multimodal_audio_ctx_t *ctx, bool stop_requested)
|
||||
static void audio_set_downstream_idle_mute_timer(multimodal_audio_ctx_t *ctx, esp_timer_handle_t timer)
|
||||
{
|
||||
portENTER_CRITICAL(&s_audio_runtime_lock);
|
||||
if (ctx != NULL) {
|
||||
ctx->downstream_idle_mute_stop_requested = stop_requested;
|
||||
}
|
||||
portEXIT_CRITICAL(&s_audio_runtime_lock);
|
||||
}
|
||||
|
||||
static TaskHandle_t audio_get_downstream_idle_mute_task(const multimodal_audio_ctx_t *ctx)
|
||||
{
|
||||
TaskHandle_t task = NULL;
|
||||
|
||||
portENTER_CRITICAL(&s_audio_runtime_lock);
|
||||
if (ctx != NULL) {
|
||||
task = ctx->downstream_idle_mute_task;
|
||||
}
|
||||
portEXIT_CRITICAL(&s_audio_runtime_lock);
|
||||
|
||||
return task;
|
||||
}
|
||||
|
||||
static void audio_set_downstream_idle_mute_task(multimodal_audio_ctx_t *ctx, TaskHandle_t task)
|
||||
{
|
||||
portENTER_CRITICAL(&s_audio_runtime_lock);
|
||||
if (ctx != NULL) {
|
||||
ctx->downstream_idle_mute_task = task;
|
||||
ctx->downstream_idle_mute_timer = timer;
|
||||
}
|
||||
portEXIT_CRITICAL(&s_audio_runtime_lock);
|
||||
}
|
||||
@@ -1118,32 +1096,6 @@ static bool clear_downstream_decoder_reset_pending(uint32_t expected_generation)
|
||||
return cleared;
|
||||
}
|
||||
|
||||
static uint32_t snapshot_downstream_audio_activity_generation(void)
|
||||
{
|
||||
uint32_t generation = 0U;
|
||||
|
||||
portENTER_CRITICAL(&s_audio_runtime_lock);
|
||||
generation = s_audio.downstream_audio_activity_generation;
|
||||
portEXIT_CRITICAL(&s_audio_runtime_lock);
|
||||
|
||||
return generation;
|
||||
}
|
||||
|
||||
static uint32_t advance_downstream_audio_activity_generation(void)
|
||||
{
|
||||
uint32_t generation = 0U;
|
||||
|
||||
portENTER_CRITICAL(&s_audio_runtime_lock);
|
||||
s_audio.downstream_audio_activity_generation++;
|
||||
if (s_audio.downstream_audio_activity_generation == 0U) {
|
||||
s_audio.downstream_audio_activity_generation = 1U;
|
||||
}
|
||||
generation = s_audio.downstream_audio_activity_generation;
|
||||
portEXIT_CRITICAL(&s_audio_runtime_lock);
|
||||
|
||||
return generation;
|
||||
}
|
||||
|
||||
static void snapshot_downstream_output_mute_state(bool *out_known, bool *out_muted)
|
||||
{
|
||||
if (out_known == NULL || out_muted == NULL) {
|
||||
@@ -1337,71 +1289,30 @@ static esp_err_t set_downstream_output_mute_if_needed(multimodal_audio_ctx_t *ct
|
||||
return (esp_err_t)ret;
|
||||
}
|
||||
|
||||
static TickType_t get_downstream_idle_mute_timeout_ticks(void)
|
||||
static uint32_t get_downstream_idle_mute_timeout_ms(void)
|
||||
{
|
||||
uint32_t timeout_ms = (uint32_t)CONFIG_MULTIMODAL_AUDIO_DOWNSTREAM_IDLE_MUTE_MS;
|
||||
if (timeout_ms < 50U) {
|
||||
timeout_ms = 50U;
|
||||
}
|
||||
|
||||
TickType_t ticks = pdMS_TO_TICKS(timeout_ms);
|
||||
return ticks == 0 ? 1 : ticks;
|
||||
return timeout_ms;
|
||||
}
|
||||
|
||||
static void downstream_idle_mute_task(void *arg)
|
||||
static void downstream_idle_mute_timer_cb(void *arg)
|
||||
{
|
||||
multimodal_audio_ctx_t *ctx = (multimodal_audio_ctx_t *)arg;
|
||||
TickType_t idle_timeout_ticks = get_downstream_idle_mute_timeout_ticks();
|
||||
if (ctx == NULL || snapshot_downstream_response_active()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (ctx->initialized && ctx->codec_dev != NULL) {
|
||||
(void)set_downstream_output_mute_if_needed(ctx, true, "Idle mute");
|
||||
}
|
||||
ESP_LOGI(TAG,
|
||||
"Downstream idle mute task started (timeout=%ums)",
|
||||
(unsigned)CONFIG_MULTIMODAL_AUDIO_DOWNSTREAM_IDLE_MUTE_MS);
|
||||
|
||||
while (ctx != NULL && !audio_get_downstream_idle_mute_stop_requested(ctx)) {
|
||||
(void)ulTaskNotifyTake(pdTRUE, portMAX_DELAY);
|
||||
if (audio_get_downstream_idle_mute_stop_requested(ctx)) {
|
||||
break;
|
||||
}
|
||||
|
||||
uint32_t observed_generation = snapshot_downstream_audio_activity_generation();
|
||||
while (!audio_get_downstream_idle_mute_stop_requested(ctx)) {
|
||||
uint32_t notify_count = ulTaskNotifyTake(pdTRUE, idle_timeout_ticks);
|
||||
if (audio_get_downstream_idle_mute_stop_requested(ctx)) {
|
||||
break;
|
||||
}
|
||||
if (notify_count > 0U) {
|
||||
observed_generation = snapshot_downstream_audio_activity_generation();
|
||||
continue;
|
||||
}
|
||||
|
||||
uint32_t current_generation = snapshot_downstream_audio_activity_generation();
|
||||
if (current_generation != observed_generation) {
|
||||
observed_generation = current_generation;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (snapshot_downstream_response_active()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (ctx->initialized && ctx->codec_dev != NULL) {
|
||||
(void)set_downstream_output_mute_if_needed(ctx, true, "Idle mute");
|
||||
}
|
||||
ESP_LOGI(TAG,
|
||||
"Downstream idle mute after %ums (response_active=%d)",
|
||||
(unsigned)CONFIG_MULTIMODAL_AUDIO_DOWNSTREAM_IDLE_MUTE_MS,
|
||||
snapshot_downstream_response_active() ? 1 : 0);
|
||||
maybe_notify_downstream_playback_completed_after_drain("idle");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (ctx != NULL) {
|
||||
audio_set_downstream_idle_mute_task(ctx, NULL);
|
||||
audio_set_downstream_idle_mute_stop_requested(ctx, false);
|
||||
}
|
||||
ESP_LOGI(TAG, "Downstream idle mute task stopped");
|
||||
delete_audio_task_with_caps(NULL);
|
||||
"Downstream idle mute after %ums (response_active=%d)",
|
||||
(unsigned)get_downstream_idle_mute_timeout_ms(),
|
||||
snapshot_downstream_response_active() ? 1 : 0);
|
||||
maybe_notify_downstream_playback_completed_after_drain("idle");
|
||||
}
|
||||
|
||||
static esp_err_t ensure_downstream_idle_mute_task(multimodal_audio_ctx_t *ctx)
|
||||
@@ -1409,38 +1320,39 @@ static esp_err_t ensure_downstream_idle_mute_task(multimodal_audio_ctx_t *ctx)
|
||||
if (ctx == NULL) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
if (audio_get_downstream_idle_mute_task(ctx) != NULL) {
|
||||
if (audio_get_downstream_idle_mute_timer(ctx) != NULL) {
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
audio_set_downstream_idle_mute_stop_requested(ctx, false);
|
||||
TaskHandle_t task = NULL;
|
||||
BaseType_t created = create_audio_task_with_caps(downstream_idle_mute_task,
|
||||
"mm_audio_idle_mute",
|
||||
MULTIMODAL_AUDIO_DOWNSTREAM_IDLE_MUTE_TASK_STACK_BYTES,
|
||||
ctx,
|
||||
4,
|
||||
&task,
|
||||
false,
|
||||
MULTIMODAL_AUDIO_CORE_ID);
|
||||
if (created != pdPASS) {
|
||||
audio_set_downstream_idle_mute_task(ctx, NULL);
|
||||
return ESP_ERR_NO_MEM;
|
||||
const esp_timer_create_args_t timer_args = {
|
||||
.callback = downstream_idle_mute_timer_cb,
|
||||
.arg = ctx,
|
||||
.dispatch_method = ESP_TIMER_TASK,
|
||||
.name = "mm_audio_idle_mute",
|
||||
.skip_unhandled_events = true,
|
||||
};
|
||||
esp_timer_handle_t timer = NULL;
|
||||
esp_err_t err = esp_timer_create(&timer_args, &timer);
|
||||
if (err != ESP_OK) {
|
||||
return err;
|
||||
}
|
||||
audio_set_downstream_idle_mute_task(ctx, task);
|
||||
audio_set_downstream_idle_mute_timer(ctx, timer);
|
||||
ESP_LOGI(TAG,
|
||||
"Downstream idle mute timer ready (timeout=%ums)",
|
||||
(unsigned)get_downstream_idle_mute_timeout_ms());
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static void notify_downstream_audio_active(multimodal_audio_ctx_t *ctx)
|
||||
{
|
||||
TaskHandle_t task = audio_get_downstream_idle_mute_task(ctx);
|
||||
if (ctx == NULL || task == NULL) {
|
||||
esp_timer_handle_t timer = audio_get_downstream_idle_mute_timer(ctx);
|
||||
if (ctx == NULL || timer == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
(void)advance_downstream_audio_activity_generation();
|
||||
xTaskNotifyGive(task);
|
||||
(void)esp_timer_stop(timer);
|
||||
(void)esp_timer_start_once(timer, (uint64_t)get_downstream_idle_mute_timeout_ms() * 1000ULL);
|
||||
}
|
||||
|
||||
static esp_err_t ensure_downstream_tx_bounce_buffer(multimodal_audio_ctx_t *ctx)
|
||||
@@ -1566,6 +1478,7 @@ static esp_err_t prime_downstream_output_path(multimodal_audio_ctx_t *ctx)
|
||||
|
||||
static esp_err_t stop_downstream_idle_mute_task(multimodal_audio_ctx_t *ctx, int timeout_ms)
|
||||
{
|
||||
(void)timeout_ms;
|
||||
if (timeout_ms < 0) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
@@ -1574,34 +1487,22 @@ static esp_err_t stop_downstream_idle_mute_task(multimodal_audio_ctx_t *ctx, int
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
TaskHandle_t task = audio_get_downstream_idle_mute_task(ctx);
|
||||
if (task == NULL) {
|
||||
audio_set_downstream_idle_mute_stop_requested(ctx, false);
|
||||
esp_timer_handle_t timer = audio_get_downstream_idle_mute_timer(ctx);
|
||||
if (timer == NULL) {
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
audio_set_downstream_idle_mute_stop_requested(ctx, true);
|
||||
xTaskNotifyGive(task);
|
||||
if (timeout_ms == 0) {
|
||||
return ESP_OK;
|
||||
esp_err_t stop_err = esp_timer_stop(timer);
|
||||
if (stop_err != ESP_OK && stop_err != ESP_ERR_INVALID_STATE) {
|
||||
ESP_LOGW(TAG, "Downstream idle mute timer stop failed: %s", esp_err_to_name(stop_err));
|
||||
}
|
||||
|
||||
int effective_timeout_ms = timeout_ms;
|
||||
int waited_ms = 0;
|
||||
while (audio_get_downstream_idle_mute_task(ctx) != NULL && waited_ms < effective_timeout_ms) {
|
||||
vTaskDelay(pdMS_TO_TICKS(20));
|
||||
waited_ms += 20;
|
||||
esp_err_t delete_err = esp_timer_delete(timer);
|
||||
if (delete_err != ESP_OK) {
|
||||
ESP_LOGW(TAG, "Downstream idle mute timer delete failed: %s", esp_err_to_name(delete_err));
|
||||
return delete_err;
|
||||
}
|
||||
esp_err_t result = ESP_OK;
|
||||
task = audio_get_downstream_idle_mute_task(ctx);
|
||||
if (task != NULL) {
|
||||
ESP_LOGW(TAG, "Downstream idle mute task stop timeout, force delete");
|
||||
delete_audio_task_with_caps(task);
|
||||
audio_set_downstream_idle_mute_task(ctx, NULL);
|
||||
result = ESP_ERR_TIMEOUT;
|
||||
}
|
||||
audio_set_downstream_idle_mute_stop_requested(ctx, false);
|
||||
return result;
|
||||
audio_set_downstream_idle_mute_timer(ctx, NULL);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static void downstream_playback_task(void *arg)
|
||||
|
||||
@@ -173,16 +173,11 @@ static void seed_default_credentials(const char *ssid, const char *password)
|
||||
return;
|
||||
}
|
||||
|
||||
if (saved_count > 0U) {
|
||||
ESP_LOGI(TAG,
|
||||
"Configured Wi-Fi SSID \"%s\" overrides %u saved credential candidate(s)",
|
||||
ssid,
|
||||
(unsigned)saved_count);
|
||||
manager.Clear();
|
||||
}
|
||||
|
||||
manager.AddSsid(ssid, password != NULL ? password : "");
|
||||
ESP_LOGI(TAG, "Configured Wi-Fi credentials for SSID \"%s\"", ssid);
|
||||
ESP_LOGI(TAG,
|
||||
"Ensured configured Wi-Fi credentials for SSID \"%s\" with %u previous candidate(s)",
|
||||
ssid,
|
||||
(unsigned)saved_count);
|
||||
}
|
||||
|
||||
static int normalize_connect_timeout_ms(int timeout_ms)
|
||||
|
||||
Reference in New Issue
Block a user