From 913a171be087a562f58a3404eba4f12e859b66ce Mon Sep 17 00:00:00 2001 From: NoSloppy <53964195+NoSloppy@users.noreply.github.com> Date: Wed, 27 Nov 2024 03:31:20 -0500 Subject: [PATCH 1/3] add StrokeType UNKNOWN_GESTURE --- props/prop_base.h | 1 + 1 file changed, 1 insertion(+) diff --git a/props/prop_base.h b/props/prop_base.h index 4f6216388..73dd33b2a 100644 --- a/props/prop_base.h +++ b/props/prop_base.h @@ -835,6 +835,7 @@ class PropBase : CommandParser, Looper, protected SaberBase, public ModeInterfac TWIST_CLOSE, TWIST_LEFT, TWIST_RIGHT, + UNKNOWN_GESTURE, SHAKE_CLOSE, SHAKE_FWD, From 4a66700108afa62b0609b203b156fc133401f867 Mon Sep 17 00:00:00 2001 From: NoSloppy <53964195+NoSloppy@users.noreply.github.com> Date: Wed, 27 Nov 2024 03:45:00 -0500 Subject: [PATCH 2/3] De-wonkify how saved_twist works. --- props/saber_BC_buttons.h | 108 ++++++++++++++++++++++----------------- 1 file changed, 60 insertions(+), 48 deletions(-) diff --git a/props/saber_BC_buttons.h b/props/saber_BC_buttons.h index 15017db21..2a8442a15 100644 --- a/props/saber_BC_buttons.h +++ b/props/saber_BC_buttons.h @@ -1107,10 +1107,6 @@ push - force push #define BUTTON_HELD_LONG_TIMEOUT 2000 #endif -#ifndef NORMAL_TWIST_TIMEOUT -#define NORMAL_TWIST_TIMEOUT 400 -#endif - #ifndef BC_MAIN_BLADE #define BC_MAIN_BLADE 1 #endif @@ -1428,7 +1424,6 @@ class SaberBCButtons : public PROP_INHERIT_PREFIX PropBase { void Loop() override { PropBase::Loop(); - DetectMenuTurn(); DetectTwist(); Vec3 mss = fusor.mss(); sound_library_.Poll(wav_player); @@ -1520,9 +1515,6 @@ class SaberBCButtons : public PROP_INHERIT_PREFIX PropBase { if (scroll_presets_beep_delay_timer_.isTimerExpired() && scroll_presets_) { SaberBase::DoEffect(EFFECT_NEWFONT, 0); } - if (twist_delay_timer_.isTimerExpired()) { - DoSavedTwist(); - } } // Loop() #ifdef SPEAK_BLADE_ID @@ -1536,39 +1528,69 @@ class SaberBCButtons : public PROP_INHERIT_PREFIX PropBase { } #endif - void DetectMenuTurn() { - float a = fusor.angle2() - current_twist_angle_; - if (isPointingUp()) return; - // Keep the rotational angle within range of - // -180 to 180 degrees in terms of radians. - if (a > M_PI) a-= M_PI * 2; - if (a < -M_PI) a+= M_PI * 2; - - if (a < -M_PI / 3) { - CheckSavedTwist(EVENT_TWIST_LEFT); - current_twist_angle_ = fusor.angle2(); - } else if (a > M_PI / 3) { - CheckSavedTwist(EVENT_TWIST_RIGHT); - current_twist_angle_ = fusor.angle2(); + // Track the last twist type and time + StrokeType saved_twist = UNKNOWN_GESTURE; + uint32_t saved_twist_start_millis = 0; + + // Call this from Loop() to detect twists. + void DetectTwist() override { + Vec3 gyro = fusor.gyro(); + bool process = false; + if (fabsf(gyro.x) > 200.0 && + fabsf(gyro.x) > 3.0f * abs(gyro.y) && + fabsf(gyro.x) > 3.0f * abs(gyro.z)) { + process = DoGesture(gyro.x > 0 ? TWIST_LEFT : TWIST_RIGHT); + } else { + process = DoGesture(TWIST_CLOSE); } - } + if (process) { + // Start timer if no saved_twist + if (saved_twist == UNKNOWN_GESTURE && + (strokes[NELEM(strokes)-1].type == TWIST_LEFT || + strokes[NELEM(strokes)-1].type == TWIST_RIGHT)) { + saved_twist = strokes[NELEM(strokes)-1].type; + saved_twist_start_millis = millis(); + return; + } - void CheckSavedTwist(uint32_t event) { - if (!saved_twist_) { - // Save the current twist and start the timer if no twist is saved - saved_twist_ = event; - twist_delay_timer_.trigger(NORMAL_TWIST_TIMEOUT); - PVLOG_DEBUG << "**** Saving twist event: " << (event == EVENT_TWIST_LEFT ? "TWIST LEFT" : "TWIST RIGHT") << ". Starting timer.\n"; + // Normal Twist Logic + if ((strokes[NELEM(strokes)-1].type == TWIST_LEFT && + strokes[NELEM(strokes)-2].type == TWIST_RIGHT) || + (strokes[NELEM(strokes)-1].type == TWIST_RIGHT && + strokes[NELEM(strokes)-2].type == TWIST_LEFT)) { + if (strokes[NELEM(strokes)-1].length() > 90UL && + strokes[NELEM(strokes)-1].length() < 300UL && + strokes[NELEM(strokes)-2].length() > 90UL && + strokes[NELEM(strokes)-2].length() < 300UL) { + uint32_t separation = + strokes[NELEM(strokes)-1].start_millis - + strokes[NELEM(strokes)-2].end_millis; + if (separation < 200UL) { + PVLOG_NORMAL << "EVENT_TWIST\n"; + // Emit normal twist event + Event(BUTTON_NONE, EVENT_TWIST); + + // Clear strokes and saved_twist state + strokes[NELEM(strokes)-1].type = UNKNOWN_GESTURE; + strokes[NELEM(strokes)-2].type = UNKNOWN_GESTURE; + saved_twist = UNKNOWN_GESTURE; + return; + } + } + } } - } - void DoSavedTwist() { - // Trigger the saved twist after timeout - PVLOG_DEBUG << (saved_twist_ == EVENT_TWIST_LEFT ? "**** Doing SAVED TWIST LEFT\n" : "Doing SAVED TWIST RIGHT\n"); - Event(BUTTON_NONE, (EVENT)saved_twist_); - // Clear the twist state and reset strokes to prevent Normal Twist after USER twist - DoGesture(TWIST_CLOSE); - saved_twist_ = 0; + // Check single twist timer + // Tested 300 as a good wait time. Shorter interferes with normal twist. + if (saved_twist != UNKNOWN_GESTURE && millis() - saved_twist_start_millis >= 300) { + // Emit single twist event + Event(BUTTON_NONE, saved_twist == TWIST_LEFT ? EVENT_TWIST_LEFT : EVENT_TWIST_RIGHT); + PVLOG_NORMAL << (saved_twist == TWIST_LEFT ? "EVENT_TWIST_LEFT" : "EVENT_TWIST_RIGHT") << "\n"; + + // Clear strokes and saved_twist state + strokes[NELEM(strokes)-1].type = UNKNOWN_GESTURE; + saved_twist = UNKNOWN_GESTURE; + } } void BeepEnterFeature() { @@ -1976,13 +1998,6 @@ class SaberBCButtons : public PROP_INHERIT_PREFIX PropBase { RefPtr wav_player; bool Event2(enum BUTTON button, EVENT event, uint32_t modifiers) override { - - if (event == EVENT_TWIST) { - PVLOG_DEBUG << "**** Detected EVENT_TWIST in Event2, stopping timer and resetting saved twist.\n"; - saved_twist_ = 0; - twist_delay_timer_.stopTimer(); - } - switch (EVENTID(button, event, modifiers)) { // storage of unused cases case EVENTID(BUTTON_AUX2, EVENT_PRESSED, MODE_ON): @@ -2513,7 +2528,7 @@ any # of buttons return true; // Toggle Scroll Presets - case EVENTID(BUTTON_POWER, EVENT_FIRST_HELD_MEDIUM, MODE_OFF): + case EVENTID(BUTTON_POWER, EVENT_FIRST_HELD_LONG, MODE_OFF): scroll_presets_ = !scroll_presets_; if (scroll_presets_) { PVLOG_NORMAL << "** Enter Scroll Presets\n"; @@ -2762,10 +2777,7 @@ any # of buttons DelayTimer mute_secondBlade_delay_timer_; DelayTimer scroll_presets_beep_delay_timer_; DelayTimer overlap_delay_timer_; - DelayTimer twist_delay_timer_; - float current_twist_angle_ = 0.0; - uint32_t saved_twist_ = 0; bool battle_mode_ = false; bool auto_lockup_on_ = false; bool auto_melt_on_ = false; From db13ed28de104a22a956e42a7e67b3b070fe3c55 Mon Sep 17 00:00:00 2001 From: NoSloppy <53964195+NoSloppy@users.noreply.github.com> Date: Wed, 27 Nov 2024 03:47:14 -0500 Subject: [PATCH 3/3] make DetectTwist() virtual --- props/prop_base.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/props/prop_base.h b/props/prop_base.h index 73dd33b2a..60342bf3b 100644 --- a/props/prop_base.h +++ b/props/prop_base.h @@ -937,7 +937,7 @@ class PropBase : CommandParser, Looper, protected SaberBase, public ModeInterfac } // The prop should call this from Loop() if it wants to detect twists. - void DetectTwist() { + virtual void DetectTwist() { Vec3 gyro = fusor.gyro(); bool process = false; if (fabsf(gyro.x) > 200.0 &&