diff --git a/components/control_plane/src/runtime/control_plane_key_input.c b/components/control_plane/src/runtime/control_plane_key_input.c index cf15e04..e45c8c5 100644 --- a/components/control_plane/src/runtime/control_plane_key_input.c +++ b/components/control_plane/src/runtime/control_plane_key_input.c @@ -62,10 +62,6 @@ #define CONFIG_MULTIMODAL_PTT_BUTTON_PULLDOWN 0 #endif -#ifndef CONFIG_TQ_CALIBRATION_SWITCH_PULLDOWN -#define CONFIG_TQ_CALIBRATION_SWITCH_PULLDOWN 0 -#endif - #ifndef CONFIG_TQ_SLOT_SWITCH_PULLDOWN #define CONFIG_TQ_SLOT_SWITCH_PULLDOWN 0 #endif @@ -120,20 +116,6 @@ static const control_plane_key_config_t s_key_configs[] = { .enable_long_press = false, .enable_double_click = false, }, - { - .key_id = CONTROL_PLANE_KEY_ID_SW1, - .gpio_num = CONFIG_TQ_CALIBRATION_SWITCH_GPIO, - .active_level = CONFIG_TQ_CALIBRATION_SWITCH_ACTIVE_LEVEL, - .pullup_enabled = CONFIG_TQ_CALIBRATION_SWITCH_PULLUP, - .pulldown_enabled = CONFIG_TQ_CALIBRATION_SWITCH_PULLDOWN, - .debounce_ms = CONFIG_TQ_KEY_DEBOUNCE_INTERVAL_MS, - .long_press_ms = CONFIG_TQ_KEY_LONG_PRESS_MS, - .double_click_ms = CONFIG_TQ_KEY_DOUBLE_CLICK_MS, - .emit_press_release = true, - .enable_short_press = true, - .enable_long_press = true, - .enable_double_click = true, - }, { .key_id = CONTROL_PLANE_KEY_ID_SW2, .gpio_num = CONFIG_TQ_SLOT_SWITCH_GPIO, diff --git a/components/domain/src/calibration/domain_calibration_service.c b/components/domain/src/calibration/domain_calibration_service.c index 8db8640..d1db786 100644 --- a/components/domain/src/calibration/domain_calibration_service.c +++ b/components/domain/src/calibration/domain_calibration_service.c @@ -16,7 +16,9 @@ static const char *TAG = "domain_cal"; #define DOMAIN_CALIBRATION_TIMEOUT_MS 20000 #define DOMAIN_CALIBRATION_STEP_TIMEOUT_MS 1500 -#define DOMAIN_CALIBRATION_RELEASE_SWEEP_DEG 45.0f +#define DOMAIN_TURNTABLE_LIMIT_SEARCH_MAX_DEG 330.0f +#define DOMAIN_TURNTABLE_LIMIT_TO_HOME_DEG 180.0f +#define DOMAIN_TURNTABLE_HOME_ANGLE_DEG 0.0f static float clamp_positive_default(float value, float default_value) { @@ -108,51 +110,6 @@ static esp_err_t calibration_rotate_and_track(float delta, int rotate_speed_us, return domain_apply_rotation_delta(delta); } -static esp_err_t calibration_release_active_switch(const domain_direction_calibration_t *calibration, - float step_angle, - float search_direction, - int rotate_speed_us, - TickType_t start_tick, - TickType_t timeout_ticks) -{ - float release_sweep_limit = clamp_positive_default(DOMAIN_CALIBRATION_RELEASE_SWEEP_DEG, - step_angle); - float released_sweep = 0.0f; - float release_delta = -search_direction * step_angle; - - while (released_sweep < release_sweep_limit) { - if (!is_calibration_switch_active(calibration)) { - ESP_LOGI(TAG, "Calibration switch released after %.1f deg", released_sweep); - return ESP_OK; - } - - if (calibration_timeout_reached(start_tick, timeout_ticks)) { - return ESP_ERR_TIMEOUT; - } - - int step_timeout_ms = calibration_step_timeout_ms(start_tick, timeout_ticks); - esp_err_t err = calibration_rotate_and_track(release_delta, rotate_speed_us, step_timeout_ms); - if (err != ESP_OK) { - return err; - } - - released_sweep += step_angle; - if (!calibration_settle(calibration, start_tick, timeout_ticks)) { - return ESP_ERR_TIMEOUT; - } - } - - if (is_calibration_switch_active(calibration)) { - ESP_LOGW(TAG, - "Calibration switch stayed active after %.1f deg release sweep", - released_sweep); - return ESP_ERR_INVALID_STATE; - } - - ESP_LOGI(TAG, "Calibration switch released after %.1f deg", released_sweep); - return ESP_OK; -} - esp_err_t domain_calibrate_with_timeout(const domain_direction_calibration_t *config, int timeout_ms) { int effective_timeout_ms = timeout_ms > 0 ? timeout_ms : DOMAIN_CALIBRATION_TIMEOUT_MS; @@ -190,37 +147,44 @@ esp_err_t domain_calibrate_with_timeout(const domain_direction_calibration_t *co } float step_angle = clamp_positive_default(calibration.step_angle_deg, 5.0f); - float max_sweep = clamp_positive_default(calibration.max_sweep_deg, 360.0f); + float configured_max_sweep = clamp_positive_default(calibration.max_sweep_deg, + DOMAIN_TURNTABLE_LIMIT_SEARCH_MAX_DEG); + float max_sweep = configured_max_sweep > DOMAIN_TURNTABLE_LIMIT_SEARCH_MAX_DEG ? + DOMAIN_TURNTABLE_LIMIT_SEARCH_MAX_DEG : + configured_max_sweep; float total_sweep = 0.0f; float direction = calibration.search_clockwise ? 1.0f : -1.0f; int rotate_speed_us = domain_get_rotate_speed_us(); ESP_LOGI(TAG, - "Calibration start step=%.1f sweep=%.1f search=%s", + "Limit calibration start step=%.1f sweep=%.1f search=%s", step_angle, max_sweep, calibration.search_clockwise ? "clockwise" : "counterclockwise"); if (is_calibration_switch_active(&calibration)) { - ESP_LOGI(TAG, "Calibration switch active at start, releasing before homing"); - err = calibration_release_active_switch(&calibration, - step_angle, - direction, - rotate_speed_us, - start_tick, - timeout_ticks); + ESP_LOGI(TAG, "Limit switch active at start; treating current position as 6 o'clock"); + int return_timeout_ms = calibration_step_timeout_ms(start_tick, timeout_ticks); + err = calibration_rotate_and_track(-direction * DOMAIN_TURNTABLE_LIMIT_TO_HOME_DEG, + rotate_speed_us, + return_timeout_ms); if (err != ESP_OK) { domain_runtime_stepper_power_off(); domain_direction_unlock_state(); return err; } + domain_set_current_angle(DOMAIN_TURNTABLE_HOME_ANGLE_DEG); + domain_runtime_stepper_power_off(); + domain_direction_unlock_state(); + ESP_LOGI(TAG, "Turntable home reached from active limit switch"); + return ESP_OK; } while (total_sweep < max_sweep) { if (calibration_timeout_reached(start_tick, timeout_ticks)) { domain_runtime_stepper_power_off(); domain_direction_unlock_state(); - ESP_LOGW(TAG, "Calibration timed out after %.1f deg search", total_sweep); + ESP_LOGW(TAG, "Limit calibration timed out after %.1f deg search", total_sweep); return ESP_ERR_TIMEOUT; } @@ -237,21 +201,31 @@ esp_err_t domain_calibrate_with_timeout(const domain_direction_calibration_t *co if (!calibration_settle(&calibration, start_tick, timeout_ticks)) { domain_runtime_stepper_power_off(); domain_direction_unlock_state(); - ESP_LOGW(TAG, "Calibration timed out during settle after %.1f deg search", total_sweep); + ESP_LOGW(TAG, "Limit calibration timed out during settle after %.1f deg search", total_sweep); return ESP_ERR_TIMEOUT; } if (is_calibration_switch_active(&calibration)) { - domain_set_current_angle(calibration.calibration_angle); + ESP_LOGI(TAG, "Limit switch detected after %.1f deg; current position is 6 o'clock", total_sweep); + int return_timeout_ms = calibration_step_timeout_ms(start_tick, timeout_ticks); + err = calibration_rotate_and_track(-direction * DOMAIN_TURNTABLE_LIMIT_TO_HOME_DEG, + rotate_speed_us, + return_timeout_ms); + if (err != ESP_OK) { + domain_runtime_stepper_power_off(); + domain_direction_unlock_state(); + return err; + } + domain_set_current_angle(DOMAIN_TURNTABLE_HOME_ANGLE_DEG); domain_runtime_stepper_power_off(); domain_direction_unlock_state(); - ESP_LOGI(TAG, "Calibration switch detected after %.1f deg", total_sweep); + ESP_LOGI(TAG, "Turntable home reached after limit calibration"); return ESP_OK; } } domain_runtime_stepper_power_off(); domain_direction_unlock_state(); - ESP_LOGW(TAG, "Calibration sweep exhausted after %.1f deg", total_sweep); + ESP_LOGW(TAG, "Limit switch not found after %.1f deg search", total_sweep); return ESP_ERR_TIMEOUT; } diff --git a/components/domain/src/direction/domain_direction_service.c b/components/domain/src/direction/domain_direction_service.c index 4eed564..82bf86b 100644 --- a/components/domain/src/direction/domain_direction_service.c +++ b/components/domain/src/direction/domain_direction_service.c @@ -19,9 +19,9 @@ static const char *TAG = "domain"; #define DOMAIN_ROTATE_TIMEOUT_MS 8000 #define DOMAIN_STATE_LOCK_TIMEOUT_MS 2000 #define DOMAIN_DEFAULT_CALIBRATION_ENABLED 1 -#define DOMAIN_DEFAULT_CALIBRATION_ANGLE_DEG 180.0f +#define DOMAIN_DEFAULT_CALIBRATION_ANGLE_DEG 0.0f #define DOMAIN_DEFAULT_CALIBRATION_STEP_ANGLE_DEG 5.0f -#define DOMAIN_DEFAULT_CALIBRATION_MAX_SWEEP_DEG 360.0f +#define DOMAIN_DEFAULT_CALIBRATION_MAX_SWEEP_DEG 330.0f #define DOMAIN_DEFAULT_CALIBRATION_SEARCH_CLOCKWISE 1 #define DOMAIN_DEFAULT_CALIBRATION_SETTLE_DELAY_MS 10 diff --git a/components/platform/src/platform_stepper_driver.c b/components/platform/src/platform_stepper_driver.c index 8936b51..4006966 100644 --- a/components/platform/src/platform_stepper_driver.c +++ b/components/platform/src/platform_stepper_driver.c @@ -9,6 +9,7 @@ #include #include "driver/gpio.h" +#include "esp_log.h" #include "esp_timer.h" #include "esp_rom_sys.h" #include "freertos/FreeRTOS.h" @@ -39,9 +40,11 @@ #define PLATFORM_STEPPER_DECEL_STEPS 48 #define PLATFORM_STEPPER_STEPS_PER_REV 4128.0f #define PLATFORM_STEPPER_POWER_OFF_WAIT_MS 1000 +#define PLATFORM_STEPPER_MAX_ROTATION_DEG 330.0f #define PLATFORM_GPIO_LOW_BANK_MAX_PIN 31 #define PLATFORM_GPIO_HIGH_BANK_OFFSET 32 +static const char *TAG = "platform_stepper"; static portMUX_TYPE s_stepper_mux = portMUX_INITIALIZER_UNLOCKED; static SemaphoreHandle_t s_stepper_motion_mutex; #if ( configSUPPORT_STATIC_ALLOCATION == 1 ) @@ -331,6 +334,13 @@ esp_err_t platform_stepper_driver_rotate_angle_with_accel(float angle, if (!ensure_stepper_motion_mutex()) { return ESP_ERR_INVALID_STATE; } + if (fabsf(angle) > PLATFORM_STEPPER_MAX_ROTATION_DEG) { + ESP_LOGE(TAG, + "rotation rejected: angle %.1f exceeds %.1f deg limit", + angle, + PLATFORM_STEPPER_MAX_ROTATION_DEG); + return ESP_ERR_INVALID_ARG; + } int64_t start_ms = esp_timer_get_time() / 1000; TickType_t lock_ticks = (timeout_ms > 0) ? pdMS_TO_TICKS(timeout_ms) : portMAX_DELAY; diff --git a/main/Kconfig.projbuild b/main/Kconfig.projbuild index 53f64b3..804d340 100644 --- a/main/Kconfig.projbuild +++ b/main/Kconfig.projbuild @@ -136,7 +136,9 @@ menu "Example Configuration" bool "Enable interrupt-driven key input task" default y help - Start the staged GPIO interrupt key input task for PTT, SW1, and SW2. + Start the staged GPIO interrupt key input task for PTT and SW2. + SW1 is reserved as the turntable limit switch and is not + emitted as a normal key event. config TQ_KEY_INPUT_TASK_STACK int "Key input task stack size" @@ -358,9 +360,11 @@ menu "Example Configuration" config TQ_BOOT_TURNTABLE_CALIBRATION_ENABLE bool "Run turntable calibration at boot" - default y + default n help - Disable when the turntable calibration mechanism is not present. + Keep disabled for staged module verification. The calibration + API remains available for key, voice, console, or system-event + triggers after boot. config TQ_STEPPER_IN1_GPIO int "Turntable stepper IN1 GPIO" diff --git a/sdkconfig.defaults b/sdkconfig.defaults index 8c66d57..0d52f8f 100644 --- a/sdkconfig.defaults +++ b/sdkconfig.defaults @@ -195,6 +195,7 @@ CONFIG_TQ_SLOT_SWITCH_GPIO=45 CONFIG_TQ_SLOT_SWITCH_ACTIVE_LEVEL=0 CONFIG_TQ_SLOT_SWITCH_PULLUP=y # CONFIG_TQ_SLOT_SWITCH_PULLDOWN is not set +CONFIG_TQ_BOOT_TURNTABLE_CALIBRATION_ENABLE=n CONFIG_TQ_STEPPER_IN1_GPIO=13 CONFIG_TQ_STEPPER_IN2_GPIO=14 CONFIG_TQ_STEPPER_IN3_GPIO=21