From cfe429d88573388d78754867e747b8f39c89de4f Mon Sep 17 00:00:00 2001 From: clement Date: Wed, 17 Jun 2026 19:47:55 +0200 Subject: [PATCH] fix(plip): debounce hook hangup against flicker The marginal A1S cradle contact flickers open mid-call; treating a brief open as a hangup dropped the live conversation. Raise the prolonged-open hangup threshold to 2.5 s and make the resync asymmetric: a PICKUP is confirmed fast (600 ms, calls answer promptly) while a HANGUP needs the line to stay open 2.5 s. Brief flickers no longer end the call; a real hangup still fires ~2.5 s later. --- plip_voice/main/phone.c | 33 ++++++++++++++++++++------------- 1 file changed, 20 insertions(+), 13 deletions(-) diff --git a/plip_voice/main/phone.c b/plip_voice/main/phone.c index 31a28a3..8891eb4 100644 --- a/plip_voice/main/phone.c +++ b/plip_voice/main/phone.c @@ -34,20 +34,23 @@ #define TAG "phone" #define DEBOUNCE_MS 30 -#define HANGUP_THRESHOLD_MS 1500 /* open > this → real hangup, not a pulse. - * Raised from 500 ms: the A1S cradle contact - * is marginal and produces ~500 ms spurious - * opens that were resetting the call before - * the NPC greeting. A real hangup holds the - * line open indefinitely, so it still fires - * (~1.5 s later). Rotary pulses (~60 ms) and - * closed inter-digit gaps are unaffected. */ +#define HANGUP_THRESHOLD_MS 2500 /* open > this → real hangup, not a pulse/flicker. + * HOOK DEBOUNCE: the A1S cradle contact is + * marginal and flickers open for up to ~2 s + * mid-call; treating those as a hangup dropped + * the live conversation. Requiring the line to + * stay open ≥ 2.5 s before hanging up rides + * through the flickers. A real hangup holds the + * line open indefinitely so it still fires + * (~2.5 s later). Rotary pulses (~60 ms) and a + * closed line are unaffected. */ #define TASK_STACK 4096 #define TASK_PRIO 5 -#define RESYNC_STABLE_MS 600 /* if the raw hook level stably disagrees with - * s_offhook for this long (no pulse), the edge - * detection missed/flapped a transition → - * self-correct s_offhook to the physical level */ +#define RESYNC_PICKUP_MS 600 /* off-hook (pickup) self-correct: fast, so an + * incoming call answers promptly. */ +#define RESYNC_HANGUP_MS HANGUP_THRESHOLD_MS /* on-hook (hangup) self-correct: + * same long debounce as the prolonged-open path + * so a flickering contact never drops the call. */ /* Rotary pulse hardening (CONFIG_PLIP_DIAL_PULSE) */ #define PULSE_MIN_WIDTH_MS 20 /* ignore opens shorter than this (glitch filter) */ @@ -316,7 +319,11 @@ poll_sleep: bool phys_off = (gpio_get_level(hook_gpio) == HOOK_OFFHOOK_LEVEL); if (!pulse_active && phys_off != s_offhook) { resync_ms += 10; - if (resync_ms >= RESYNC_STABLE_MS) { + /* Hook debounce: a PICKUP (→off-hook) is confirmed fast so calls + * answer promptly; a HANGUP (→on-hook) needs the long debounce so + * a flickering cradle contact can't drop a live call. */ + int need = phys_off ? RESYNC_PICKUP_MS : RESYNC_HANGUP_MS; + if (resync_ms >= need) { ESP_LOGW(TAG, "hook resync: physical=%s but s_offhook=%d — correcting", phys_off ? "off-hook" : "on-hook", (int)s_offhook); s_offhook = phys_off; -- 2.52.0