feat(control-plane): add configurable Wi-Fi reset button
This commit is contained in:
@@ -14,6 +14,7 @@ idf_component_register(
|
|||||||
"src/runtime/control_plane_fortune_service.c"
|
"src/runtime/control_plane_fortune_service.c"
|
||||||
"src/runtime/control_plane_system_events.c"
|
"src/runtime/control_plane_system_events.c"
|
||||||
"src/runtime/control_plane_key_input.c"
|
"src/runtime/control_plane_key_input.c"
|
||||||
|
"src/runtime/control_plane_reset_service.c"
|
||||||
"src/runtime/control_plane_remote_log_service.c"
|
"src/runtime/control_plane_remote_log_service.c"
|
||||||
"src/runtime/control_plane_runtime_workers.c"
|
"src/runtime/control_plane_runtime_workers.c"
|
||||||
"src/runtime/control_plane_ota.c"
|
"src/runtime/control_plane_ota.c"
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ typedef enum {
|
|||||||
CONTROL_PLANE_KEY_ID_PTT = 0,
|
CONTROL_PLANE_KEY_ID_PTT = 0,
|
||||||
CONTROL_PLANE_KEY_ID_SW1,
|
CONTROL_PLANE_KEY_ID_SW1,
|
||||||
CONTROL_PLANE_KEY_ID_SW2,
|
CONTROL_PLANE_KEY_ID_SW2,
|
||||||
|
CONTROL_PLANE_KEY_ID_RESET,
|
||||||
} control_plane_key_id_t;
|
} control_plane_key_id_t;
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
@@ -54,4 +55,3 @@ typedef struct {
|
|||||||
control_plane_key_event_t key;
|
control_plane_key_event_t key;
|
||||||
} data;
|
} data;
|
||||||
} control_plane_system_event_t;
|
} control_plane_system_event_t;
|
||||||
|
|
||||||
|
|||||||
@@ -158,6 +158,7 @@ const char *control_plane_key_event_type_name(control_plane_key_event_type_t typ
|
|||||||
|
|
||||||
esp_err_t control_plane_start_key_input_task(void);
|
esp_err_t control_plane_start_key_input_task(void);
|
||||||
void control_plane_stop_key_input_task(void);
|
void control_plane_stop_key_input_task(void);
|
||||||
|
void control_plane_reset_wifi_provisioning_and_restart(void);
|
||||||
esp_err_t control_plane_schedule_websocket_wait_task(void);
|
esp_err_t control_plane_schedule_websocket_wait_task(void);
|
||||||
void control_plane_set_ptt_active(bool active);
|
void control_plane_set_ptt_active(bool active);
|
||||||
esp_err_t control_plane_enter_mini_program_reprovisioning(const char *reason);
|
esp_err_t control_plane_enter_mini_program_reprovisioning(const char *reason);
|
||||||
|
|||||||
@@ -94,6 +94,18 @@
|
|||||||
#define CONFIG_TQ_CALIBRATION_SWITCH_PULLDOWN 0
|
#define CONFIG_TQ_CALIBRATION_SWITCH_PULLDOWN 0
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef CONFIG_TQ_RESET_BUTTON_ENABLE
|
||||||
|
#define CONFIG_TQ_RESET_BUTTON_ENABLE 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef CONFIG_TQ_RESET_BUTTON_PULLUP
|
||||||
|
#define CONFIG_TQ_RESET_BUTTON_PULLUP 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef CONFIG_TQ_RESET_BUTTON_PULLDOWN
|
||||||
|
#define CONFIG_TQ_RESET_BUTTON_PULLDOWN 0
|
||||||
|
#endif
|
||||||
|
|
||||||
static const char *TAG = "cp_key_input";
|
static const char *TAG = "cp_key_input";
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
@@ -181,6 +193,22 @@ static const control_plane_key_config_t s_key_configs[] = {
|
|||||||
.enable_long_press = true,
|
.enable_long_press = true,
|
||||||
.enable_double_click = true,
|
.enable_double_click = true,
|
||||||
},
|
},
|
||||||
|
#if CONFIG_TQ_RESET_BUTTON_ENABLE
|
||||||
|
{
|
||||||
|
.key_id = CONTROL_PLANE_KEY_ID_RESET,
|
||||||
|
.gpio_num = CONFIG_TQ_RESET_BUTTON_GPIO,
|
||||||
|
.active_level = CONFIG_TQ_RESET_BUTTON_ACTIVE_LEVEL,
|
||||||
|
.pullup_enabled = CONFIG_TQ_RESET_BUTTON_PULLUP,
|
||||||
|
.pulldown_enabled = CONFIG_TQ_RESET_BUTTON_PULLDOWN,
|
||||||
|
.debounce_ms = CONFIG_TQ_KEY_DEBOUNCE_INTERVAL_MS,
|
||||||
|
.long_press_ms = CONFIG_TQ_RESET_BUTTON_LONG_PRESS_MS,
|
||||||
|
.double_click_ms = 0,
|
||||||
|
.emit_press_release = false,
|
||||||
|
.enable_short_press = false,
|
||||||
|
.enable_long_press = true,
|
||||||
|
.enable_double_click = false,
|
||||||
|
},
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
static QueueHandle_t s_gpio_irq_queue;
|
static QueueHandle_t s_gpio_irq_queue;
|
||||||
@@ -262,6 +290,31 @@ static esp_err_t control_plane_configure_key_gpio(const control_plane_key_config
|
|||||||
return gpio_intr_enable(config->gpio_num);
|
return gpio_intr_enable(config->gpio_num);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static esp_err_t control_plane_validate_key_configs(void)
|
||||||
|
{
|
||||||
|
for (size_t i = 0; i < sizeof(s_key_configs) / sizeof(s_key_configs[0]); ++i) {
|
||||||
|
const control_plane_key_config_t *config = &s_key_configs[i];
|
||||||
|
if (config->pullup_enabled && config->pulldown_enabled) {
|
||||||
|
ESP_LOGE(TAG,
|
||||||
|
"key=%s gpio=%d cannot enable pull-up and pull-down together",
|
||||||
|
control_plane_key_id_name(config->key_id),
|
||||||
|
(int)config->gpio_num);
|
||||||
|
return ESP_ERR_INVALID_ARG;
|
||||||
|
}
|
||||||
|
for (size_t j = 0; j < i; ++j) {
|
||||||
|
if (s_key_configs[j].gpio_num == config->gpio_num) {
|
||||||
|
ESP_LOGE(TAG,
|
||||||
|
"key GPIO conflict: key=%s and key=%s both use gpio=%d",
|
||||||
|
control_plane_key_id_name(s_key_configs[j].key_id),
|
||||||
|
control_plane_key_id_name(config->key_id),
|
||||||
|
(int)config->gpio_num);
|
||||||
|
return ESP_ERR_INVALID_ARG;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ESP_OK;
|
||||||
|
}
|
||||||
|
|
||||||
static void control_plane_emit_key_event(const control_plane_key_config_t *config,
|
static void control_plane_emit_key_event(const control_plane_key_config_t *config,
|
||||||
control_plane_key_event_type_t type,
|
control_plane_key_event_type_t type,
|
||||||
int level,
|
int level,
|
||||||
@@ -469,6 +522,12 @@ static void control_plane_key_input_task(void *arg)
|
|||||||
|
|
||||||
esp_err_t setup_err = ESP_OK;
|
esp_err_t setup_err = ESP_OK;
|
||||||
memset(s_key_states, 0, sizeof(s_key_states));
|
memset(s_key_states, 0, sizeof(s_key_states));
|
||||||
|
setup_err = control_plane_validate_key_configs();
|
||||||
|
if (setup_err != ESP_OK) {
|
||||||
|
s_key_input_task = NULL;
|
||||||
|
vTaskDelete(NULL);
|
||||||
|
return;
|
||||||
|
}
|
||||||
for (size_t i = 0; i < sizeof(s_key_configs) / sizeof(s_key_configs[0]); ++i) {
|
for (size_t i = 0; i < sizeof(s_key_configs) / sizeof(s_key_configs[0]); ++i) {
|
||||||
const control_plane_key_config_t *config = &s_key_configs[i];
|
const control_plane_key_config_t *config = &s_key_configs[i];
|
||||||
s_key_states[i].initialized = true;
|
s_key_states[i].initialized = true;
|
||||||
|
|||||||
@@ -0,0 +1,27 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2024-2026 Espressif Systems (Shanghai) CO LTD
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "control_plane_internal.h"
|
||||||
|
|
||||||
|
#include "esp_log.h"
|
||||||
|
|
||||||
|
static const char *TAG = "cp_reset";
|
||||||
|
|
||||||
|
void control_plane_reset_wifi_provisioning_and_restart(void)
|
||||||
|
{
|
||||||
|
ESP_LOGW(TAG, "Wi-Fi reset requested; clearing saved credentials");
|
||||||
|
|
||||||
|
esp_err_t err = domain_runtime_wifi_portal_clear_saved_credentials();
|
||||||
|
if (err != ESP_OK) {
|
||||||
|
ESP_LOGE(TAG,
|
||||||
|
"Wi-Fi credential reset failed; device will not restart: %s",
|
||||||
|
esp_err_to_name(err));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ESP_LOGW(TAG, "Saved Wi-Fi credentials cleared; restarting device");
|
||||||
|
domain_runtime_restart();
|
||||||
|
}
|
||||||
@@ -84,6 +84,8 @@ const char *control_plane_key_id_name(control_plane_key_id_t key_id)
|
|||||||
return "SW1";
|
return "SW1";
|
||||||
case CONTROL_PLANE_KEY_ID_SW2:
|
case CONTROL_PLANE_KEY_ID_SW2:
|
||||||
return "SW2";
|
return "SW2";
|
||||||
|
case CONTROL_PLANE_KEY_ID_RESET:
|
||||||
|
return "RESET";
|
||||||
default:
|
default:
|
||||||
return "UNKNOWN";
|
return "UNKNOWN";
|
||||||
}
|
}
|
||||||
@@ -128,6 +130,13 @@ static void control_plane_dispatch_key_event(const control_plane_key_event_t *ev
|
|||||||
event->press_duration_ms,
|
event->press_duration_ms,
|
||||||
event->click_count);
|
event->click_count);
|
||||||
|
|
||||||
|
if (event->key_id == CONTROL_PLANE_KEY_ID_RESET) {
|
||||||
|
if (event->type == CONTROL_PLANE_KEY_EVENT_LONG_PRESS_START) {
|
||||||
|
control_plane_reset_wifi_provisioning_and_restart();
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (event->key_id == CONTROL_PLANE_KEY_ID_SW2) {
|
if (event->key_id == CONTROL_PLANE_KEY_ID_SW2) {
|
||||||
if (event->type == CONTROL_PLANE_KEY_EVENT_SHORT_PRESS) {
|
if (event->type == CONTROL_PLANE_KEY_EVENT_SHORT_PRESS) {
|
||||||
esp_err_t request_err = control_plane_request_cloud_chouqian();
|
esp_err_t request_err = control_plane_request_cloud_chouqian();
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ the ESP32-S3 MCU perspective.
|
|||||||
| 11 | `CONFIG_MULTIMODAL_AUDIO_PA_GPIO` | Output | Audio amplifier | PA enable | Managed by codec GPIO interface |
|
| 11 | `CONFIG_MULTIMODAL_AUDIO_PA_GPIO` | Output | Audio amplifier | PA enable | Managed by codec GPIO interface |
|
||||||
| 12 | `CONFIG_TQ_CALIBRATION_SWITCH_GPIO` | Input | Turntable calibration | Button 1 / SW1 direction calibration | Active-low, external and internal pull-up |
|
| 12 | `CONFIG_TQ_CALIBRATION_SWITCH_GPIO` | Input | Turntable calibration | Button 1 / SW1 direction calibration | Active-low, external and internal pull-up |
|
||||||
| 13 | `CONFIG_MULTIMODAL_PTT_BUTTON_GPIO` | Input | Keys / multimodal | Button 2 / K2 push-to-talk | Active-low, external and internal pull-up |
|
| 13 | `CONFIG_MULTIMODAL_PTT_BUTTON_GPIO` | Input | Keys / multimodal | Button 2 / K2 push-to-talk | Active-low, external and internal pull-up |
|
||||||
|
| 14 | `CONFIG_TQ_RESET_BUTTON_GPIO` | Input when enabled | Optional reset key | Hold to clear saved Wi-Fi credentials and restart | Disabled by default; active-low with internal pull-up when enabled |
|
||||||
| 15 | `CONFIG_TQ_SCREEN_SPI_CS_GPIO` | Output | LCD | ST7789P3 SPI chip select | SPI2 host |
|
| 15 | `CONFIG_TQ_SCREEN_SPI_CS_GPIO` | Output | LCD | ST7789P3 SPI chip select | SPI2 host |
|
||||||
| 16 | `CONFIG_TQ_SCREEN_DC_GPIO` | Output | LCD | ST7789P3 data/command select | Initialized low |
|
| 16 | `CONFIG_TQ_SCREEN_DC_GPIO` | Output | LCD | ST7789P3 data/command select | Initialized low |
|
||||||
| 17 | `CONFIG_TQ_SCREEN_RESET_PIN` | Output | LCD | ST7789P3 panel reset | Active-low reset; `-1` disables hardware reset |
|
| 17 | `CONFIG_TQ_SCREEN_RESET_PIN` | Output | LCD | ST7789P3 panel reset | Active-low reset; `-1` disables hardware reset |
|
||||||
|
|||||||
+1
-1
@@ -30,7 +30,7 @@ hold net; that assignment is not valid for the current board.
|
|||||||
| 19 | GPIO11 | PA_CTRL | Output | Audio power-amplifier enable | Amplifier control |
|
| 19 | GPIO11 | PA_CTRL | Output | Audio power-amplifier enable | Amplifier control |
|
||||||
| 20 | GPIO12 | SW1 | Input | Button 1 / turntable calibration switch | External 10 kOhm pull-up; active low |
|
| 20 | GPIO12 | SW1 | Input | Button 1 / turntable calibration switch | External 10 kOhm pull-up; active low |
|
||||||
| 21 | GPIO13 | SW2 | Input | Button 2 / K2 push-to-talk input | External 10 kOhm pull-up; active low |
|
| 21 | GPIO13 | SW2 | Input | Button 2 / K2 push-to-talk input | External 10 kOhm pull-up; active low |
|
||||||
| 22 | GPIO14 | UNASSIGNED | N/A | No connection assigned | Reserved; no signal assigned |
|
| 22 | GPIO14 | UNASSIGNED / RESET_KEY | Optional input | Configurable Wi-Fi reset button | Unassigned and disabled by default; active-low with internal pull-up when enabled |
|
||||||
| 23 | GPIO21 | IN4 | Output | ULN2003 IN4 | Stepper motor phase control |
|
| 23 | GPIO21 | IN4 | Output | ULN2003 IN4 | Stepper motor phase control |
|
||||||
| 24 | GPIO47 | IN3 | Output | ULN2003 IN3 | Stepper motor phase control |
|
| 24 | GPIO47 | IN3 | Output | ULN2003 IN3 | Stepper motor phase control |
|
||||||
| 25 | GPIO48 | IN2 | Output | ULN2003 IN2 | Stepper motor phase control |
|
| 25 | GPIO48 | IN2 | Output | ULN2003 IN2 | Stepper motor phase control |
|
||||||
|
|||||||
+52
-2
@@ -389,8 +389,9 @@ menu "Example Configuration"
|
|||||||
default y
|
default y
|
||||||
help
|
help
|
||||||
Start the staged GPIO interrupt key input task for PTT, SW1,
|
Start the staged GPIO interrupt key input task for PTT, SW1,
|
||||||
and SW2. SW1 remains the turntable calibration input and is
|
SW2, and the optional Wi-Fi reset button. SW1 remains the
|
||||||
also reported for post-boot button diagnostics.
|
turntable calibration input and is also reported for post-boot
|
||||||
|
button diagnostics.
|
||||||
|
|
||||||
config TQ_KEY_INPUT_TASK_STACK
|
config TQ_KEY_INPUT_TASK_STACK
|
||||||
int "Key input task stack size"
|
int "Key input task stack size"
|
||||||
@@ -448,6 +449,55 @@ menu "Example Configuration"
|
|||||||
help
|
help
|
||||||
Ignore raw GPIO chatter briefly after a double-click has been emitted.
|
Ignore raw GPIO chatter briefly after a double-click has been emitted.
|
||||||
|
|
||||||
|
config TQ_RESET_BUTTON_ENABLE
|
||||||
|
bool "Enable Wi-Fi reset button"
|
||||||
|
default n
|
||||||
|
depends on TQ_KEY_INPUT_ENABLE
|
||||||
|
help
|
||||||
|
Enable a dedicated reset button. Holding the button for the
|
||||||
|
configured duration clears saved Wi-Fi credentials and then
|
||||||
|
restarts the device. Other persisted data is not changed.
|
||||||
|
|
||||||
|
config TQ_RESET_BUTTON_GPIO
|
||||||
|
int "Wi-Fi reset button GPIO"
|
||||||
|
default 14
|
||||||
|
range 0 48
|
||||||
|
depends on TQ_RESET_BUTTON_ENABLE
|
||||||
|
help
|
||||||
|
GPIO used for the dedicated Wi-Fi reset button when enabled.
|
||||||
|
GPIO14 is unassigned on the current board revision.
|
||||||
|
|
||||||
|
config TQ_RESET_BUTTON_ACTIVE_LEVEL
|
||||||
|
int "Wi-Fi reset button active level"
|
||||||
|
default 0
|
||||||
|
range 0 1
|
||||||
|
depends on TQ_RESET_BUTTON_ENABLE
|
||||||
|
help
|
||||||
|
Logic level that means the Wi-Fi reset button is pressed.
|
||||||
|
|
||||||
|
config TQ_RESET_BUTTON_PULLUP
|
||||||
|
bool "Enable Wi-Fi reset button pull-up"
|
||||||
|
default y
|
||||||
|
depends on TQ_RESET_BUTTON_ENABLE
|
||||||
|
help
|
||||||
|
Enable the internal pull-up for active-low wiring.
|
||||||
|
|
||||||
|
config TQ_RESET_BUTTON_PULLDOWN
|
||||||
|
bool "Enable Wi-Fi reset button pull-down"
|
||||||
|
default n
|
||||||
|
depends on TQ_RESET_BUTTON_ENABLE
|
||||||
|
help
|
||||||
|
Enable the internal pull-down for active-high wiring.
|
||||||
|
|
||||||
|
config TQ_RESET_BUTTON_LONG_PRESS_MS
|
||||||
|
int "Wi-Fi reset button hold duration (ms)"
|
||||||
|
default 5000
|
||||||
|
range 1000 15000
|
||||||
|
depends on TQ_RESET_BUTTON_ENABLE
|
||||||
|
help
|
||||||
|
Continuous press duration required before saved Wi-Fi
|
||||||
|
credentials are cleared and the device restarts.
|
||||||
|
|
||||||
choice TQ_PTT_INTERACTION_MODE
|
choice TQ_PTT_INTERACTION_MODE
|
||||||
prompt "PTT interaction mode"
|
prompt "PTT interaction mode"
|
||||||
default TQ_PTT_MODE_CLICK_TO_TALK
|
default TQ_PTT_MODE_CLICK_TO_TALK
|
||||||
|
|||||||
@@ -181,6 +181,7 @@ CONFIG_MULTIMODAL_PTT_BUTTON_GPIO=13
|
|||||||
CONFIG_MULTIMODAL_PTT_BUTTON_ACTIVE_LEVEL=0
|
CONFIG_MULTIMODAL_PTT_BUTTON_ACTIVE_LEVEL=0
|
||||||
CONFIG_MULTIMODAL_PTT_BUTTON_PULLUP=y
|
CONFIG_MULTIMODAL_PTT_BUTTON_PULLUP=y
|
||||||
# CONFIG_MULTIMODAL_PTT_BUTTON_PULLDOWN is not set
|
# CONFIG_MULTIMODAL_PTT_BUTTON_PULLDOWN is not set
|
||||||
|
# CONFIG_TQ_RESET_BUTTON_ENABLE is not set
|
||||||
# CONFIG_MULTIMODAL_AUDIO_CHANNEL_PROBE_ON_INIT is not set
|
# CONFIG_MULTIMODAL_AUDIO_CHANNEL_PROBE_ON_INIT is not set
|
||||||
CONFIG_MULTIMODAL_HEARTBEAT_INTERVAL_MS=50000
|
CONFIG_MULTIMODAL_HEARTBEAT_INTERVAL_MS=50000
|
||||||
CONFIG_MULTIMODAL_NO_RESPONSE_TIMEOUT_MS=60000
|
CONFIG_MULTIMODAL_NO_RESPONSE_TIMEOUT_MS=60000
|
||||||
|
|||||||
Reference in New Issue
Block a user