// sa22c props file, updated to include Battle Mode and gestures, and allow lb in Battle Mode.. // // Includes 1,2 and 3 button modes. Incorporates multi-blast, // battle mode and gesture ignitions from fett263 plus on-the-fly volume // controls and full access to all features with 1,2 or 3 button sabers // // New #define SA22C_NO_LOCKUP_HOLD // reverts to lockup being triggered only by clash + aux in 2-button mode // Also sets multi-blast to trigger while holding aux and swinging, rather than // double click and hold // // Gesture Controls // There are four gesture types: swing, stab, twist and thrust. For simplicity, // using gesture ignition will automatically skip the preon effect. // Below are the options to add to the config to enable // the various gestures // // #define SA22C_STAB_ON // #define SA22C_SWING_ON // #define SA22C_TWIST_ON // #define SA22C_THRUST_ON // #define SA22C_TWIST_OFF // #define SA22C_FORCE_PUSH // // #define SA22C_FORCE_PUSH_LENGTH 5 // Allows for adjustment to Push gesture length in millis needed to trigger Force Push // Recommended range 1 ~ 10, 1 = shortest, easiest to trigger, 10 = longest // // If you want the gesture ignition to ALSO enter battle mode automatically // on ignition, add this define // // #define GESTURE_AUTO_BATTLE_MODE // // Battle mode by fett263 // // Once you enter battle mode, button functions will be disabled for lockup // stab, melt, etc. Blaster blocks and lightning block will continue to be // triggered by button controls. Automatic lockup/clash detection works // by measuring delay of the saber blade pulling back from the clash. // If you clash the blade and it does not pull back during the delay period, // it is assumed to be a lockup and the lockup effect will show on the blade. // If you clash the blade and pull away, only the bgn/end lockup effects will show. // // You can adjust the threshold of this detection by using // #define SA22C_LOCKUP_DELAY (insert number here) // Default value is 200 // // Battle mode features automatic clash and lockup detection plus a new // force push mode that will play a force or force push sound with a controlled // pushing gesture. Automatic clash/lockup uses the pre and post lock effects // so your blade style and font MUST have those capabilities to support // battle mode. Kudos to fett263 for his very impressive additions for OS 5 // // Tightened click timings // I've shortened the timeout for short and double click detection from 500ms // to 300ms. I think it feels more responsive this way but still gives enough // timeout to ensure all button actions can be achieved consistently // I've included all button timings so they can be easily tweaked to suit // individual tastes. // // Button configs: // // 1 Button: // Activate Muted - double click and hold while OFF // Activate - short click while OFF // Play/Stop Music - double click while OFF // Turn off blade - hold and wait till blade is off while ON // Next Preset - hold and release while OFF // Prev Preset - hold and wait while OFF // Lockup - hold + hit clash while ON // Stab - thrust forward clash while ON // Lightning Block - double click and hold while ON // Melt - hold + thust forward clash while ON // Drag - hold + hit clash while ON pointing the blade tip down // Blaster Blocks - short click/double click/triple click while on // Multi-Blast - hold while swinging for one second and release // to trigger blaster block, swing saber while in multi-blast mode // to exit, hold while swinging for one second and release // Battle Mode - triple-click and hold while on // Force Effects - hold + twist the hilt while ON (while pointing up) // Color Change mode - hold + twist the hilt while ON (pointing down) // Enter Volume - Menu hold + clash while OFF // Volume UP - hold and release while in Volume Menu // Volume DOWN - click while in Volume Menu // Exit Volume Menu - Menu hold + clash while OFF // Battery Level - triple click while OFF // // // 2 Button: // POWER // Activate Muted - double click and hold while OFF // Activate - short click while OFF // Play/Stop Music - hold and release while OFF // Turn off blade - hold and wait till blade is off while ON // Force Effects - double click while ON // Volume UP - short click while OFF and in VOLUME MENU // Prev Preset - hold and wait while OFF // Color Change mode - hold + toggle AUX while ON // Lightning Block - double click and hold while ON // Melt - hold while stabbing (clash with forward motion, horizontal) // Battle Mode - triple-click and hold for half a second while on // AUX // Blaster blocks - short click/double click/triple click while ON // Multi-Blast - double-click and hold for half a second // to trigger blaster block, swing saber while in multi-blast mode // to exit, double-click and hold for half a second // Next Preset - short click while OFF // Lockup - hold while ON (unless #define SA22C_NO_LOCKUP_HOLD) // Drag - hold while ON pointing the blade tip down // Enter VOLUME MENU - long click while OFF // Volume down - short click while OFF and in VOLUME MENU // Battery level - hold while off // // 3 Button: Same as two button except for the following // // AUX2 // Lightning Block - hold while ON // Battle Mode - double-click and hold while on // Previous Preset - short click while OFF #ifndef PROPS_SABER_SA22C_BUTTONS_H #define PROPS_SABER_SA22C_BUTTONS_H #include "prop_base.h" #include "../sound/hybrid_font.h" #undef PROP_TYPE #define PROP_TYPE SaberSA22CButtons #ifndef MOTION_TIMEOUT #define MOTION_TIMEOUT 60 * 15 * 1000 #endif #ifndef SA22C_SWING_ON_SPEED #define SA22C_SWING_ON_SPEED 250 #endif #ifndef SA22C_LOCKUP_DELAY #define SA22C_LOCKUP_DELAY 200 #endif #ifndef SA22C_FORCE_PUSH_LENGTH #define SA22C_FORCE_PUSH_LENGTH 5 #endif #ifndef BUTTON_DOUBLE_CLICK_TIMEOUT #define BUTTON_DOUBLE_CLICK_TIMEOUT 300 #endif #ifndef BUTTON_SHORT_CLICK_TIMEOUT #define BUTTON_SHORT_CLICK_TIMEOUT 300 #endif #ifndef BUTTON_HELD_TIMEOUT #define BUTTON_HELD_TIMEOUT 300 #endif #ifndef BUTTON_HELD_MEDIUM_TIMEOUT #define BUTTON_HELD_MEDIUM_TIMEOUT 1000 #endif #ifndef BUTTON_HELD_LONG_TIMEOUT #define BUTTON_HELD_LONG_TIMEOUT 2000 #endif #ifdef SA22C_SWING_ON #define SWING_GESTURE #endif #ifdef SA22C_STAB_ON #define STAB_GESTURE #endif #ifdef SA22C_TWIST_ON #define TWIST_GESTURE #endif #ifdef SA22C_THRUST_ON #define THRUST_GESTURE #endif #define FORCE_PUSH_CONDITION battle_mode_ EFFECT(dim); // for EFFECT_POWERSAVE EFFECT(battery); // for EFFECT_BATTERY_LEVEL EFFECT(bmbegin); // for Begin Battle Mode EFFECT(bmend); // for End Battle Mode EFFECT(vmbegin); // for Begin Volume Menu EFFECT(vmend); // for End Volume Menu EFFECT(volup); // for increse volume EFFECT(voldown); // for decrease volume EFFECT(volmin); // for minimum volume reached EFFECT(volmax); // for maximum volume reached EFFECT(faston); // for EFFECT_FAST_ON EFFECT(blstbgn); // for Begin Multi-Blast EFFECT(blstend); // for End Multi-Blast EFFECT(push); // for Force Push gesture in Battle Mode // The Saber class implements the basic states and actions // for the saber. class SaberSA22CButtons : public virtual PropBase { public: SaberSA22CButtons() : PropBase() {} const char* name() override { return "SaberSA22CButtons"; } void Loop() override { PropBase::Loop(); DetectTwist(); Vec3 mss = fusor.mss(); if (SaberBase::IsOn()) { DetectSwing(); if (auto_lockup_on_ && !swinging_ && fusor.swing_speed() > 120 && millis() - clash_impact_millis_ > SA22C_LOCKUP_DELAY && SaberBase::Lockup()) { SaberBase::DoEndLockup(); SaberBase::SetLockup(SaberBase::LOCKUP_NONE); auto_lockup_on_ = false; } if (auto_melt_on_ && !swinging_ && fusor.swing_speed() > 60 && millis() - clash_impact_millis_ > SA22C_LOCKUP_DELAY && SaberBase::Lockup()) { SaberBase::DoEndLockup(); SaberBase::SetLockup(SaberBase::LOCKUP_NONE); auto_melt_on_ = false; } // EVENT_PUSH if (fabs(mss.x) < 3.0 && mss.y * mss.y + mss.z * mss.z > 70 && fusor.swing_speed() < 30 && fabs(fusor.gyro().x) < 10) { if (millis() - push_begin_millis_ > SA22C_FORCE_PUSH_LENGTH) { Event(BUTTON_NONE, EVENT_PUSH); push_begin_millis_ = millis(); } } else { push_begin_millis_ = millis(); } } else { // EVENT_SWING - Swing On gesture control to allow fine tuning of speed needed to ignite if (millis() - saber_off_time_ < MOTION_TIMEOUT) { SaberBase::RequestMotion(); if (swinging_ && fusor.swing_speed() < 90) { swinging_ = false; } if (!swinging_ && fusor.swing_speed() > SA22C_SWING_ON_SPEED) { swinging_ = true; Event(BUTTON_NONE, EVENT_SWING); } } // EVENT_THRUST if (mss.y * mss.y + mss.z * mss.z < 16.0 && mss.x > 14 && fusor.swing_speed() < 150) { if (millis() - thrust_begin_millis_ > 15) { Event(BUTTON_NONE, EVENT_THRUST); thrust_begin_millis_ = millis(); } } else { thrust_begin_millis_ = millis(); } } } // Fast On Gesture Ignition virtual void FastOn() { if (IsOn()) return; if (current_style() && current_style()->NoOnOff()) return; activated_ = millis(); STDOUT.println("Ignition."); MountSDCard(); EnableAmplifier(); SaberBase::RequestMotion(); // Avoid clashes a little bit while turning on. // It might be a "clicky" power button... IgnoreClash(500); SaberBase::TurnOn(); // Optional effects SaberBase::DoEffect(EFFECT_FAST_ON, 0); } // Volume Menu void VolumeUp() { STDOUT.println("Volume up"); if (dynamic_mixer.get_volume() < VOLUME) { dynamic_mixer.set_volume(std::min(VOLUME + VOLUME * 0.1, dynamic_mixer.get_volume() + VOLUME * 0.10)); if (SFX_volup) { hybrid_font.PlayCommon(&SFX_volup); } else { beeper.Beep(0.5, 2000); } STDOUT.print("Volume Up - Current Volume: "); STDOUT.println(dynamic_mixer.get_volume()); } else { // Cycle through ends of Volume Menu option #ifdef VOLUME_MENU_CYCLE if (!max_vol_reached_) { if (SFX_volmax) { hybrid_font.PlayCommon(&SFX_volmax); } else { beeper.Beep(0.5, 3000); } STDOUT.print("Maximum Volume: "); max_vol_reached_ = true; } else { dynamic_mixer.set_volume(std::max(VOLUME * 0.1, dynamic_mixer.get_volume() - VOLUME * 0.90)); if (SFX_volmin) { hybrid_font.PlayCommon(&SFX_volmin); } else { beeper.Beep(0.5, 1000); } STDOUT.print("Minimum Volume: "); max_vol_reached_ = false; } #else if (SFX_volmax) { hybrid_font.PlayCommon(&SFX_volmax); } else { beeper.Beep(0.5, 3000); } STDOUT.print("Maximum Volume: "); #endif } } void VolumeDown() { STDOUT.println("Volume Down"); if (dynamic_mixer.get_volume() > (0.10 * VOLUME)) { dynamic_mixer.set_volume(std::max(VOLUME * 0.1, dynamic_mixer.get_volume() - VOLUME * 0.10)); if (SFX_voldown) { hybrid_font.PlayCommon(&SFX_voldown); } else { beeper.Beep(0.5, 2000); } STDOUT.print("Volume Down - Current Volume: "); STDOUT.println(dynamic_mixer.get_volume()); } else { #ifdef VOLUME_MENU_CYCLE if (!min_vol_reached_) { if (SFX_volmin) { hybrid_font.PlayCommon(&SFX_volmin); } else { beeper.Beep(0.5, 1000); } STDOUT.print("Minimum Volume: "); min_vol_reached_ = true; } else { dynamic_mixer.set_volume(VOLUME); if (SFX_volmax) { hybrid_font.PlayCommon(&SFX_volmax); } else { beeper.Beep(0.5, 3000); } STDOUT.print("Maximum Volume: "); min_vol_reached_ = false; } #else if (SFX_volmin) { hybrid_font.PlayCommon(&SFX_volmin); } else { beeper.Beep(0.5, 1000); } STDOUT.print("Minimum Volume: "); #endif } } bool Event2(enum BUTTON button, EVENT event, uint32_t modifiers) override { switch (EVENTID(button, event, modifiers)) { case EVENTID(BUTTON_POWER, EVENT_PRESSED, MODE_ON): case EVENTID(BUTTON_AUX, EVENT_PRESSED, MODE_ON): case EVENTID(BUTTON_AUX2, EVENT_PRESSED, MODE_ON): if (accel_.x < -0.15) { pointing_down_ = true; } else { pointing_down_ = false; } return true; // Battle Mode #if NUM_BUTTONS == 3 case EVENTID(BUTTON_AUX2, EVENT_SECOND_HELD, MODE_ON): #else case EVENTID(BUTTON_POWER, EVENT_THIRD_HELD, MODE_ON): #endif if (!battle_mode_) { STDOUT.println("Entering Battle Mode"); battle_mode_ = true; if (SFX_bmbegin) { hybrid_font.PlayCommon(&SFX_bmbegin); } else { hybrid_font.DoEffect(EFFECT_FORCE, 0); } } else { STDOUT.println("Exiting Battle Mode"); battle_mode_ = false; if (SFX_bmend) { hybrid_font.PlayCommon(&SFX_bmend); } else { beeper.Beep(0.5, 3000); } } return true; // Auto Lockup Mode case EVENTID(BUTTON_NONE, EVENT_CLASH, MODE_ON): if (!battle_mode_) return false; clash_impact_millis_ = millis(); swing_blast_ = false; if (swinging_) return false; SaberBase::SetLockup(SaberBase::LOCKUP_NORMAL); auto_lockup_on_ = true; SaberBase::DoBeginLockup(); return true; case EVENTID(BUTTON_NONE, EVENT_STAB, MODE_ON): if (!battle_mode_) return false; clash_impact_millis_ = millis(); swing_blast_ = false; if (!swinging_) { if (fusor.angle1() < - M_PI / 4) { SaberBase::SetLockup(SaberBase::LOCKUP_DRAG); } else { SaberBase::SetLockup(SaberBase::LOCKUP_MELT); } auto_melt_on_ = true; SaberBase::DoBeginLockup(); } return true; // Gesture Controls #ifdef SA22C_SWING_ON case EVENTID(BUTTON_NONE, EVENT_SWING, MODE_OFF): // Due to motion chip startup on boot creating false ignition we delay Swing On at boot for 3000ms if (millis() > 3000) { FastOn(); #ifdef GESTURE_AUTO_BATTLE_MODE STDOUT.println("Entering Battle Mode"); battle_mode_ = true; #endif } return true; #endif #ifdef SA22C_TWIST_ON case EVENTID(BUTTON_NONE, EVENT_TWIST, MODE_OFF): // Delay twist events to prevent false trigger from over twisting if (millis() - last_twist_ > 2000 && millis() - saber_off_time_ > 1000) { FastOn(); #ifdef GESTURE_AUTO_BATTLE_MODE STDOUT.println("Entering Battle Mode"); battle_mode_ = true; #endif last_twist_ = millis(); } return true; #endif #ifdef SA22C_TWIST_OFF case EVENTID(BUTTON_NONE, EVENT_TWIST, MODE_ON): // Delay twist events to prevent false trigger from over twisting if (millis() - last_twist_ > 3000) { Off(); last_twist_ = millis(); saber_off_time_ = millis(); battle_mode_ = false; } return true; #endif #ifdef SA22C_STAB_ON case EVENTID(BUTTON_NONE, EVENT_STAB, MODE_OFF): if (millis() - saber_off_time_ > 1000) { FastOn(); #ifdef GESTURE_AUTO_BATTLE_MODE STDOUT.println("Entering Battle Mode"); battle_mode_ = true; #endif } return true; #endif #ifdef SA22C_THRUST_ON case EVENTID(BUTTON_NONE, EVENT_THRUST, MODE_OFF): if (millis() - saber_off_time_ > 1000) { FastOn(); #ifdef GESTURE_AUTO_BATTLE_MODE STDOUT.println("Entering Battle Mode"); battle_mode_ = true; #endif } return true; #endif #ifdef SA22C_FORCE_PUSH case EVENTID(BUTTON_NONE, EVENT_PUSH, MODE_ON): if (FORCE_PUSH_CONDITION && millis() - last_push_ > 2000) { if (SFX_push) { hybrid_font.PlayCommon(&SFX_push); } else { hybrid_font.DoEffect(EFFECT_FORCE, 0); } last_push_ = millis(); } return true; #endif // Saber ON AND Volume Up case EVENTID(BUTTON_POWER, EVENT_FIRST_SAVED_CLICK_SHORT, MODE_OFF): if (!mode_volume_) { On(); } else { VolumeUp(); } return true; case EVENTID(BUTTON_POWER, EVENT_FIRST_CLICK_LONG, MODE_OFF): // 1-button: Next Preset AND Volume Down #if NUM_BUTTONS == 1 if (!mode_volume_) { next_preset(); } else { VolumeDown(); } return true; #else // 2 and 3 button: Start or Stop Track StartOrStopTrack(); return true; #endif // 2 and 3 button: Next Preset and Volume Down case EVENTID(BUTTON_AUX, EVENT_FIRST_CLICK_SHORT, MODE_OFF): if (!mode_volume_) { next_preset(); } else { VolumeDown(); } return true; #if NUM_BUTTONS == 3 // 3 button: Previous Preset case EVENTID(BUTTON_AUX2, EVENT_FIRST_CLICK_SHORT, MODE_OFF): #else // 1 and 2 button: Previous Preset case EVENTID(BUTTON_POWER, EVENT_FIRST_HELD_LONG, MODE_OFF): #endif if (!mode_volume_) { previous_preset(); } return true; // Activate Muted case EVENTID(BUTTON_POWER, EVENT_SECOND_HELD, MODE_OFF): if (SetMute(true)) { unmute_on_deactivation_ = true; On(); } return true; // Turn Blade OFF #if NUM_BUTTONS > 1 // 2 and 3 button case EVENTID(BUTTON_POWER, EVENT_FIRST_HELD_MEDIUM, MODE_ON): #else // 1 button case EVENTID(BUTTON_POWER, EVENT_FIRST_HELD_LONG, MODE_ON): #endif if (!SaberBase::Lockup()) { #ifndef DISABLE_COLOR_CHANGE if (SaberBase::GetColorChangeMode() != SaberBase::COLOR_CHANGE_MODE_NONE) { // Just exit color change mode. // Don't turn saber off. ToggleColorChangeMode(); return true; } #endif if (!battle_mode_) { Off(); } } saber_off_time_ = millis(); battle_mode_ = false; swing_blast_ = false; return true; // 1 button Force and Color Change mode #if NUM_BUTTONS == 1 case EVENTID(BUTTON_NONE, EVENT_TWIST, MODE_ON | BUTTON_POWER): #ifndef DISABLE_COLOR_CHANGE if (accel_.x < -0.15) { ToggleColorChangeMode(); } else { SaberBase::DoForce(); } #else SaberBase::DoForce(); #endif return true; #else // 2 and 3 button Force effect case EVENTID(BUTTON_POWER, EVENT_SECOND_SAVED_CLICK_SHORT, MODE_ON): SaberBase::DoForce(); return true; // 2 and 3 button color change #ifndef DISABLE_COLOR_CHANGE case EVENTID(BUTTON_AUX, EVENT_FIRST_CLICK_SHORT, MODE_ON | BUTTON_POWER): ToggleColorChangeMode(); return true; #endif #endif // Blaster Deflection #if NUM_BUTTONS == 1 // 1 button case EVENTID(BUTTON_POWER, EVENT_FIRST_SAVED_CLICK_SHORT, MODE_ON): case EVENTID(BUTTON_POWER, EVENT_SECOND_SAVED_CLICK_SHORT, MODE_ON): case EVENTID(BUTTON_POWER, EVENT_THIRD_CLICK_SHORT, MODE_ON): #else // 2 and 3 button case EVENTID(BUTTON_AUX, EVENT_FIRST_SAVED_CLICK_SHORT, MODE_ON): case EVENTID(BUTTON_AUX, EVENT_SECOND_SAVED_CLICK_SHORT, MODE_ON): case EVENTID(BUTTON_AUX, EVENT_THIRD_CLICK_SHORT, MODE_ON): #endif swing_blast_ = false; SaberBase::DoBlast(); return true; // Multi-Blaster Deflection mode #if NUM_BUTTONS == 1 // 1 button case EVENTID(BUTTON_NONE, EVENT_SWING, MODE_ON | BUTTON_POWER): #else // 2 and 3 button #ifndef SA22C_NO_LOCKUP_HOLD case EVENTID(BUTTON_AUX, EVENT_SECOND_HELD, MODE_ON): #else // in SA22C_NO_LOCKUP_HOLD mode, multi-blaster is triggered by holding aux // while swinging case EVENTID(BUTTON_NONE, EVENT_SWING, MODE_ON | BUTTON_AUX): #endif #endif swing_blast_ = !swing_blast_; if (swing_blast_) { if (SFX_blstbgn) { hybrid_font.PlayCommon(&SFX_blstbgn); } else { hybrid_font.SB_Effect(EFFECT_BLAST, 0); } } else { if (SFX_blstend) { hybrid_font.PlayCommon(&SFX_blstend); } else { hybrid_font.SB_Effect(EFFECT_BLAST, 0); } } return true; case EVENTID(BUTTON_NONE, EVENT_SWING, MODE_ON): if (swing_blast_) { SaberBase::DoBlast(); } return true; // Lockup #if NUM_BUTTONS == 1 // 1 button lockup case EVENTID(BUTTON_NONE, EVENT_CLASH, MODE_ON | BUTTON_POWER): #else #ifndef SA22C_NO_LOCKUP_HOLD // 2 and 3 button lockup case EVENTID(BUTTON_AUX, EVENT_FIRST_HELD, MODE_ON): #else case EVENTID(BUTTON_NONE, EVENT_CLASH, MODE_ON | BUTTON_AUX): #endif #endif if (!SaberBase::Lockup() && !battle_mode_) { if (pointing_down_) { SaberBase::SetLockup(SaberBase::LOCKUP_DRAG); } else { SaberBase::SetLockup(SaberBase::LOCKUP_NORMAL); } swing_blast_ = false; SaberBase::DoBeginLockup(); return true; } break; // Lightning Block #if NUM_BUTTONS < 3 // 1 and 2 button case EVENTID(BUTTON_POWER, EVENT_SECOND_HELD, MODE_ON): #else // 3 button case EVENTID(BUTTON_AUX2, EVENT_FIRST_HELD, MODE_ON): #endif SaberBase::SetLockup(SaberBase::LOCKUP_LIGHTNING_BLOCK); swing_blast_ = false; SaberBase::DoBeginLockup(); return true; break; // Melt case EVENTID(BUTTON_NONE, EVENT_STAB, MODE_ON | BUTTON_POWER): if (!SaberBase::Lockup() && !battle_mode_) { SaberBase::SetLockup(SaberBase::LOCKUP_MELT); swing_blast_ = false; SaberBase::DoBeginLockup(); return true; } break; // Start or Stop Track #if NUM_BUTTONS == 1 // 1 button case EVENTID(BUTTON_POWER, EVENT_SECOND_SAVED_CLICK_SHORT, MODE_OFF): StartOrStopTrack(); return true; #endif case EVENTID(BUTTON_POWER, EVENT_PRESSED, MODE_OFF): case EVENTID(BUTTON_AUX, EVENT_PRESSED, MODE_OFF): case EVENTID(BUTTON_AUX2, EVENT_PRESSED, MODE_OFF): SaberBase::RequestMotion(); return true; // Enter Volume MENU #if NUM_BUTTONS == 1 // 1 button case EVENTID(BUTTON_NONE, EVENT_CLASH, MODE_OFF | BUTTON_POWER): #else // 2 and 3 button case EVENTID(BUTTON_AUX, EVENT_FIRST_CLICK_LONG, MODE_OFF): #endif if (!mode_volume_) { mode_volume_ = true; if (SFX_vmbegin) { hybrid_font.PlayCommon(&SFX_vmbegin); } else { beeper.Beep(0.5, 3000); } STDOUT.println("Enter Volume Menu"); } else { mode_volume_ = false; if (SFX_vmend) { hybrid_font.PlayCommon(&SFX_vmend); } else { beeper.Beep(0.5, 3000); } STDOUT.println("Exit Volume Menu"); } return true; // Battery level #if NUM_BUTTONS == 1 // 1 button case EVENTID(BUTTON_POWER, EVENT_THIRD_SAVED_CLICK_SHORT, MODE_OFF): #else // 2 and 3 button case EVENTID(BUTTON_AUX, EVENT_FIRST_HELD_LONG, MODE_OFF): #endif //talkie.Say(spBATTERYLEVEL); talkie.SayDigit((int)floorf(battery_monitor.battery())); talkie.Say(spPOINT); talkie.SayDigit(((int)floorf(battery_monitor.battery() * 10)) % 10); talkie.SayDigit(((int)floorf(battery_monitor.battery() * 100)) % 10); talkie.Say(spVOLTS); STDOUT.println(battery_monitor.battery()); return true; #ifdef BLADE_DETECT_PIN case EVENTID(BUTTON_BLADE_DETECT, EVENT_LATCH_ON, MODE_ANY_BUTTON | MODE_ON): case EVENTID(BUTTON_BLADE_DETECT, EVENT_LATCH_ON, MODE_ANY_BUTTON | MODE_OFF): // Might need to do something cleaner, but let's try this for now. blade_detected_ = true; FindBladeAgain(); SaberBase::DoBladeDetect(true); return true; case EVENTID(BUTTON_BLADE_DETECT, EVENT_LATCH_OFF, MODE_ANY_BUTTON | MODE_ON): case EVENTID(BUTTON_BLADE_DETECT, EVENT_LATCH_OFF, MODE_ANY_BUTTON | MODE_OFF): // Might need to do something cleaner, but let's try this for now. blade_detected_ = false; FindBladeAgain(); SaberBase::DoBladeDetect(false); return true; #endif // Events that needs to be handled regardless of what other buttons // are pressed. case EVENTID(BUTTON_POWER, EVENT_RELEASED, MODE_ANY_BUTTON | MODE_ON): case EVENTID(BUTTON_AUX, EVENT_RELEASED, MODE_ANY_BUTTON | MODE_ON): case EVENTID(BUTTON_AUX2, EVENT_RELEASED, MODE_ANY_BUTTON | MODE_ON): if (SaberBase::Lockup()) { SaberBase::DoEndLockup(); SaberBase::SetLockup(SaberBase::LOCKUP_NONE); return true; } } return false; } void SB_Effect(EffectType effect, float location) override { switch (effect) { case EFFECT_POWERSAVE: if (SFX_dim) { hybrid_font.PlayCommon(&SFX_dim); } else { beeper.Beep(0.5, 3000); } return; case EFFECT_BATTERY_LEVEL: if (SFX_battery) { hybrid_font.PlayCommon(&SFX_battery); } else { beeper.Beep(0.5, 3000); } return; case EFFECT_FAST_ON: if (SFX_faston) { hybrid_font.PlayCommon(&SFX_faston); } return; default: break; // avoids compiler warning } } private: bool pointing_down_ = false; bool swing_blast_ = false; bool mode_volume_ = false; bool auto_lockup_on_ = false; bool auto_melt_on_ = false; bool battle_mode_ = false; bool max_vol_reached_ = false; bool min_vol_reached_ = false; uint32_t thrust_begin_millis_ = millis(); uint32_t push_begin_millis_ = millis(); uint32_t clash_impact_millis_ = millis(); uint32_t last_twist_ = millis(); uint32_t last_push_ = millis(); uint32_t saber_off_time_ = millis(); }; #endif