From 27109657413f8e6a947c72ff02177d9ee887f623 Mon Sep 17 00:00:00 2001 From: electron-rare Date: Sun, 14 Jun 2026 22:15:53 +0200 Subject: [PATCH] fix(plip): synchronous tones_stop (I2S arbitration), MAX_DIGITS 12, drop s_state cross-task write, pulse guard --- plip_voice/main/dialer.c | 2 +- plip_voice/main/net.c | 2 +- plip_voice/main/phone.c | 13 +++++++++---- plip_voice/main/tones.c | 20 +++++++++++++++++--- 4 files changed, 28 insertions(+), 9 deletions(-) diff --git a/plip_voice/main/dialer.c b/plip_voice/main/dialer.c index dda4c1a..2a73125 100644 --- a/plip_voice/main/dialer.c +++ b/plip_voice/main/dialer.c @@ -20,7 +20,7 @@ #define TAG "dialer" -#define MAX_DIGITS 8 +#define MAX_DIGITS 12 static char s_num[MAX_DIGITS + 1]; static int s_len; diff --git a/plip_voice/main/net.c b/plip_voice/main/net.c index c4d1dbb..1f1a20c 100644 --- a/plip_voice/main/net.c +++ b/plip_voice/main/net.c @@ -441,7 +441,7 @@ static esp_err_t handle_debug_dial(httpd_req_t *req) } int pushed = 0; - for (int i = 0; number[i] != '\0' && i < 8; i++) { + for (int i = 0; number[i] != '\0' && i < 12; i++) { if (number[i] >= '0' && number[i] <= '9') { dialer_push_digit(number[i] - '0'); pushed++; diff --git a/plip_voice/main/phone.c b/plip_voice/main/phone.c index c4b348d..984e59c 100644 --- a/plip_voice/main/phone.c +++ b/plip_voice/main/phone.c @@ -189,10 +189,15 @@ static void phone_task(void *arg) if (s_offhook && pulse_count > 0 && !in_pulse && last_close_us > 0) { int64_t gap_ms = (esp_timer_get_time() - last_close_us) / 1000; if (gap_ms > CONFIG_PLIP_DIAL_PULSE_MAX_GAP_MS) { - int digit = (pulse_count == 10) ? 0 : pulse_count; - ESP_LOGI(TAG, "rotary digit: %d pulses -> %d", pulse_count, digit); - dialer_push_digit(digit); - pulse_count = 0; + if (pulse_count > 10) { + ESP_LOGW(TAG, "bad pulse count %d, ignored", pulse_count); + pulse_count = 0; + } else { + int digit = (pulse_count == 10) ? 0 : pulse_count; + ESP_LOGI(TAG, "rotary digit: %d pulses -> %d", pulse_count, digit); + dialer_push_digit(digit); + pulse_count = 0; + } } } diff --git a/plip_voice/main/tones.c b/plip_voice/main/tones.c index 80f0604..19819d3 100644 --- a/plip_voice/main/tones.c +++ b/plip_voice/main/tones.c @@ -26,8 +26,9 @@ typedef enum { TONE_NONE, TONE_DIAL, TONE_BUSY, TONE_RINGBACK } tone_mode_t; -static volatile tone_mode_t s_mode = TONE_NONE; -static TaskHandle_t s_task = NULL; +static volatile tone_mode_t s_mode = TONE_NONE; +static volatile bool s_tone_idle = true; /* true when tone_task is NOT in i2s_channel_write */ +static TaskHandle_t s_task = NULL; #define SR 16000 /* sample rate (must match audio_init) */ #define FRAME 320 /* 20 ms @ 16 kHz */ @@ -58,6 +59,7 @@ static void tone_task(void *a) for (;;) { tone_mode_t m = s_mode; if (m == TONE_NONE) { + s_tone_idle = true; vTaskDelay(pdMS_TO_TICKS(20)); t = 0; ph = 0; @@ -81,7 +83,8 @@ static void tone_task(void *a) } size_t written = 0; - i2s_channel_write(audio_spk_handle(), buf, sizeof(buf), &written, pdMS_TO_TICKS(500)); + s_tone_idle = false; + i2s_channel_write(audio_spk_handle(), buf, sizeof(buf), &written, pdMS_TO_TICKS(50)); t += 20; /* each frame = 20 ms */ } } @@ -122,4 +125,15 @@ void tones_stop(void) { ESP_LOGI(TAG, "tones stop"); s_mode = TONE_NONE; + /* Wait until tone_task is no longer inside i2s_channel_write (I2S arbitration). + * Guard: max 200 ms so we never block indefinitely. */ + const int max_wait_ms = 200; + int waited_ms = 0; + while (!s_tone_idle && waited_ms < max_wait_ms) { + vTaskDelay(pdMS_TO_TICKS(5)); + waited_ms += 5; + } + if (waited_ms >= max_wait_ms) { + ESP_LOGW(TAG, "tones_stop: timeout waiting for tone_task idle"); + } }