Version
- ProffieOS v8.10 (commit
3c991a7)
- Prop:
props/saber_fett263_buttons.h
- Board: Proffieboard V3.9, 2-button setup
Summary
The FETT263_SWING_CLASH_DELAY guard on the swing-driven Battle Mode and Multi-Blast toggles has its comparison inverted (> where it should be <). As a result the toggle is blocked during normal use and only fires within the short window right after a clash — the exact opposite of the documented intent.
The code
The same guard appears on both swing toggles:
saber_fett263_buttons.h:6137 — Battle Mode toggle (Hold AUX + Swing, active when FETT263_HOLD_BUTTON_LOCKUP is defined):
#if defined(FETT263_HOLD_BUTTON_LOCKUP) && !defined(FETT263_DISABLE_BM_TOGGLE)
case EVENTID(BUTTON_NONE, EVENT_SWING, MODE_ON | BUTTON_AUX):
if (menu_ || CheckShowColorCC() || millis() - last_clash_ > FETT263_SWING_CLASH_DELAY) return true;
ToggleBattleMode();
return true;
#endif
saber_fett263_buttons.h:5811 — Multi-Blast toggle (Hold PWR + Swing). Note that this
occurrence sits inside the #if NUM_BUTTONS == 1 block (lines 5514–5905), so it only
affects 1-button builds; on 2-button builds Multi-Blast is toggled by Long Click AUX
(line 6297), which has no such guard:
case EVENTID(BUTTON_NONE, EVENT_SWING, MODE_ON | BUTTON_POWER):
if (menu_ || CheckShowColorCC() || millis() - last_clash_ > FETT263_SWING_CLASH_DELAY) return true;
ToggleMultiBlast();
return true;
Why it is inverted
The documented purpose of the define (saber_fett263_buttons.h:537):
FETT263_SWING_CLASH_DELAY — Set delay timing in MILLIS for Button/Swing Events if a Clash is detected. Prevent trigger for Multi-Blast/Battle Mode where a button hold and swing are used but a Clash was detected, i.e. Lockup trigger. Default is 150.
So the toggle should be suppressed while a clash was recently detected (a clash produces an incidental swing), and allowed otherwise.
last_clash_ (props/prop_base.h:121) starts at 0 and is set to millis() on every clash. Therefore millis() - last_clash_ is:
- large during normal use (no recent clash),
- small (
< FETT263_SWING_CLASH_DELAY) only for ~150 ms after a clash.
return true consumes the event without toggling, so ToggleBattleMode() / ToggleMultiBlast() runs only when the condition is false:
- Normal deliberate swing →
millis() - last_clash_ > 150 is true → event consumed → toggle never happens.
- Swing within 150 ms of a clash → condition false → toggle fires.
That is exactly backwards from the intent.
The correct idiom for "recently clashed" is already used elsewhere in the same tree — props/prop_base.h:204:
uint32_t time_since_last_clash = now - last_clash_;
if (time_since_last_clash < clash_timeout_) { ... }
i.e. <, not >.
Proposed fix
Change > to < on both lines (5811 and 6137). Line 6137 is the one that hits 2-button
builds; line 5811 has the same defect in the 1-button branch:
if (menu_ || CheckShowColorCC() || millis() - last_clash_ < FETT263_SWING_CLASH_DELAY) return true;
Observed symptoms (2-button build with FETT263_HOLD_BUTTON_LOCKUP defined — line 6137)
- Battle Mode cannot be toggled off.
Hold AUX + Swing never registers, because a deliberate toggle has no preceding clash, so the inverted guard always consumes it.
- A clash while holding AUX silently toggles Battle Mode. The clash-induced swing lands inside the 150 ms window and passes the guard. Because most fonts have no
bmbegin.wav, ToggleBattleMode() (saber_fett263_buttons.h:5244) falls back to hybrid_font.DoEffect(EFFECT_FORCE, 0) and plays a force/*.wav quote — which presents to the user as a random quote firing on clash.
Workaround
Removing FETT263_HOLD_BUTTON_LOCKUP moves the Battle Mode toggle to the EVENTID(BUTTON_AUX, EVENT_HELD_LONG, MODE_ON) handler (saber_fett263_buttons.h:6130), which has no SWING_CLASH_DELAY guard, so Hold AUX toggles reliably. (Trade-off: lockup returns to Hold PWR + Clash.) Alternatively FETT263_DISABLE_BM_TOGGLE compiles the broken branch out entirely.
Version
3c991a7)props/saber_fett263_buttons.hSummary
The
FETT263_SWING_CLASH_DELAYguard on the swing-driven Battle Mode and Multi-Blast toggles has its comparison inverted (>where it should be<). As a result the toggle is blocked during normal use and only fires within the short window right after a clash — the exact opposite of the documented intent.The code
The same guard appears on both swing toggles:
saber_fett263_buttons.h:6137— Battle Mode toggle (Hold AUX + Swing, active whenFETT263_HOLD_BUTTON_LOCKUPis defined):saber_fett263_buttons.h:5811— Multi-Blast toggle (Hold PWR + Swing). Note that thisoccurrence sits inside the
#if NUM_BUTTONS == 1block (lines 5514–5905), so it onlyaffects 1-button builds; on 2-button builds Multi-Blast is toggled by
Long Click AUX(line 6297), which has no such guard:
Why it is inverted
The documented purpose of the define (
saber_fett263_buttons.h:537):So the toggle should be suppressed while a clash was recently detected (a clash produces an incidental swing), and allowed otherwise.
last_clash_(props/prop_base.h:121) starts at0and is set tomillis()on every clash. Thereforemillis() - last_clash_is:< FETT263_SWING_CLASH_DELAY) only for ~150 ms after a clash.return trueconsumes the event without toggling, soToggleBattleMode()/ToggleMultiBlast()runs only when the condition is false:millis() - last_clash_ > 150is true → event consumed → toggle never happens.That is exactly backwards from the intent.
The correct idiom for "recently clashed" is already used elsewhere in the same tree —
props/prop_base.h:204:i.e.
<, not>.Proposed fix
Change
>to<on both lines (5811 and 6137). Line 6137 is the one that hits 2-buttonbuilds; line 5811 has the same defect in the 1-button branch:
Observed symptoms (2-button build with
FETT263_HOLD_BUTTON_LOCKUPdefined — line 6137)Hold AUX + Swingnever registers, because a deliberate toggle has no preceding clash, so the inverted guard always consumes it.bmbegin.wav,ToggleBattleMode()(saber_fett263_buttons.h:5244) falls back tohybrid_font.DoEffect(EFFECT_FORCE, 0)and plays aforce/*.wavquote — which presents to the user as a random quote firing on clash.Workaround
Removing
FETT263_HOLD_BUTTON_LOCKUPmoves the Battle Mode toggle to theEVENTID(BUTTON_AUX, EVENT_HELD_LONG, MODE_ON)handler (saber_fett263_buttons.h:6130), which has noSWING_CLASH_DELAYguard, soHold AUXtoggles reliably. (Trade-off: lockup returns toHold PWR + Clash.) AlternativelyFETT263_DISABLE_BM_TOGGLEcompiles the broken branch out entirely.