From 250bf6742defc9b95d59fba572f06338c07af4d6 Mon Sep 17 00:00:00 2001 From: profezzorn Date: Sun, 26 Apr 2020 12:15:09 -0700 Subject: [PATCH 01/24] blade id fix --- 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 1923c38c5..99592f5ca 100644 --- a/props/prop_base.h +++ b/props/prop_base.h @@ -367,7 +367,7 @@ class PropBase : CommandParser, Looper, protected SaberBase { if (NELEM(blades) > 1) { float resistor = id(); - float best_err = 1000000.0; + float best_err = 100000000.0; for (size_t i = 0; i < NELEM(blades); i++) { float err = fabsf(resistor - blades[i].ohm); if (err < best_err) { From f94c655a8d2cbe5507fe762d2efb0995dca77c6a Mon Sep 17 00:00:00 2001 From: profezzorn Date: Tue, 28 Apr 2020 20:51:18 -0700 Subject: [PATCH 02/24] spiled --- blades/spiled_pin.h | 85 +++++++++++++++++++++++++++++++++++++++++++ blades/ws2811_blade.h | 1 + 2 files changed, 86 insertions(+) create mode 100644 blades/spiled_pin.h diff --git a/blades/spiled_pin.h b/blades/spiled_pin.h new file mode 100644 index 000000000..5f381156b --- /dev/null +++ b/blades/spiled_pin.h @@ -0,0 +1,85 @@ +#ifndef BLADES_SPILEDPIN_H +#define BLADES_SPILEDPIN_H + +template +class SpiLedPin : public Looper { +public: + SpiLedPin(int pin, + int num_leds, + Color8::Byteorder byteorder, + int frequency, + int reset_us, + int t0h_us = 294, + int t1h_us = 862) : + pin_(pin), + num_leds_(num_leds), + frequency_(frequency), + byteorder_(byteorder) { + pinMode(CLOCK_PIN, OUTPUT); + digitalWrite(CLOCK_PIN, HIGH); + pinMode(pin, OUTPUT); + digitalWrite(pin, HIGH); + } + + bool IsReadyForBeginFrame() { return true; } + bool IsReadyForEndFrame() { return true; } + + static inline void delay_nanos(uint32_t nanos) { +#ifdef TEENSYDUINO + uint32_t scale = F_CPU / 1000000; +#else + uint32_t scale = SystemCoreClock / 1000000; +#endif + uint32_t n = (nanos * scale + 2) / 3000; + + __asm__ __volatile__( + "1: subs %0, #1 \n" + " bne 1b \n" + : "+r" (n)); + } + + void OutByte(uint8_t output) { + for (int bit = 0; bit < 8; bit++) { + digitalWrite(CLOCK_PIN, LOW); + digitalWrite(pin_, output & 0x80); + delay_nanos(500000000 / frequency_); + output <<= 8; + digitalWrite(CLOCK_PIN, HIGH); + delay_nanos(500000000 / frequency_); + } + } + + void BeginFrame() { + for (int i = Color8::num_bytes(byteorder_); i >= 0; i--) OutByte(0); + } + void EndFrame() { + for (int i = Color8::num_bytes(byteorder_); i >= 0; i--) OutByte(0xff); + } + + void Set(int led, Color16 color) { + uint8_t *output = ((uint8_t *)displayMemory) + (led + 1) * (1 + Color8::num_bytes(byteorder_)); + int MAX = std::max(color.r, std::max(color.g, color.b)); + int output_level = (MAX + 2114) / 2115; + int mult = output_level == 0 ? 0 : 31 * 256 / output_level; + OutByte(0xE0 | output_level); + for (int i = Color8::num_bytes(byteorder_) - 1; i >= 0; i--) { + OutByte(color.getShort(byteorder_, i) * mult >> 16); + } + } + + void Set(int led, Color8 color) { + Set(led, Color16(color)); + } + + int num_leds() const { return num_leds_; } + Color8::Byteorder get_byteorder() const { return byteorder_; } + uint8_t pin() const { return pin_; } + +private: + uint8_t pin_; + uint32_t num_leds_; + uint32_t frequency_; + Color8::Byteorder byteorder_; +}; + +#endif diff --git a/blades/ws2811_blade.h b/blades/ws2811_blade.h index db5aaa3d8..e4d445a8d 100644 --- a/blades/ws2811_blade.h +++ b/blades/ws2811_blade.h @@ -16,6 +16,7 @@ DMAMEM int displayMemory[maxLedsPerStrip * 24 / 4 + 1]; #include "ws2811_serial.h" #define DefaultPinClass MonopodWSPin #endif +#include "spiled_pin.h" Color16 color_buffer[maxLedsPerStrip]; BladeBase* current_blade = NULL; From 70018b08db7d9bc50dd32fac3496d883efccd764 Mon Sep 17 00:00:00 2001 From: profezzorn Date: Wed, 29 Apr 2020 16:56:35 -0700 Subject: [PATCH 03/24] fix spiled output --- blades/spiled_pin.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/blades/spiled_pin.h b/blades/spiled_pin.h index 5f381156b..2e46bd47b 100644 --- a/blades/spiled_pin.h +++ b/blades/spiled_pin.h @@ -59,8 +59,8 @@ class SpiLedPin : public Looper { void Set(int led, Color16 color) { uint8_t *output = ((uint8_t *)displayMemory) + (led + 1) * (1 + Color8::num_bytes(byteorder_)); int MAX = std::max(color.r, std::max(color.g, color.b)); - int output_level = (MAX + 2114) / 2115; - int mult = output_level == 0 ? 0 : 31 * 256 / output_level; + int output_level = (MAX + 2113) / 2117; + int mult = output_level == 0 ? 0 : 7930 / output_level; OutByte(0xE0 | output_level); for (int i = Color8::num_bytes(byteorder_) - 1; i >= 0; i--) { OutByte(color.getShort(byteorder_, i) * mult >> 16); From 00bc84d0d0ffefd4b2743ab9298370e91f97fd83 Mon Sep 17 00:00:00 2001 From: profezzorn Date: Wed, 29 Apr 2020 17:30:16 -0700 Subject: [PATCH 04/24] fix spiled output --- blades/spiled_pin.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/blades/spiled_pin.h b/blades/spiled_pin.h index 2e46bd47b..427f662e6 100644 --- a/blades/spiled_pin.h +++ b/blades/spiled_pin.h @@ -43,7 +43,7 @@ class SpiLedPin : public Looper { digitalWrite(CLOCK_PIN, LOW); digitalWrite(pin_, output & 0x80); delay_nanos(500000000 / frequency_); - output <<= 8; + output <<= 1; digitalWrite(CLOCK_PIN, HIGH); delay_nanos(500000000 / frequency_); } From 253596c0068905af6dee066338aa0434a1cdb9db Mon Sep 17 00:00:00 2001 From: fdarosa2663 Date: Fri, 1 May 2020 03:19:50 -0400 Subject: [PATCH 05/24] Responsive style update (#56) --- styles/responsive_styles.h | 56 +++++++++++++++++++------------------- 1 file changed, 28 insertions(+), 28 deletions(-) diff --git a/styles/responsive_styles.h b/styles/responsive_styles.h index 7e34e56ff..ae7fd0995 100644 --- a/styles/responsive_styles.h +++ b/styles/responsive_styles.h @@ -15,11 +15,11 @@ template + class TOP = Scale,Int<4000>,Int<28000>>, + class BOTTOM = Int<6000>, + class SIZE = Scale,Int<9000>,Int<14000>>> using ResponsiveLockupL = - LockupTrL,Int,Int>,Int>>, + LockupTrL,TOP,BOTTOM>,SIZE>>, TR1, TR2, SaberBase::LOCKUP_NORMAL>; @@ -31,10 +31,10 @@ using ResponsiveLockupL = template + class SIZE1 = Int<2000>, + class SIZE2 = Int<10000>> using ResponsiveDragL = - LockupTrL,Scale,Int,Int>>>, + LockupTrL,Scale,SIZE1,SIZE2>>>, TR1, TR2, SaberBase::LOCKUP_DRAG>; @@ -47,10 +47,10 @@ using ResponsiveDragL = template,OrangeRed,Red>, class TR1 = TrWipeIn<600>, class TR2 = TrWipe<600>, - int SIZE1 = 4000, - int SIZE2 = 10000> + class SIZE1 = Int<4000>, + class SIZE2 = Int<10000>> using ResponsiveMeltL = - LockupTrL,Scale,Int,Int>>>, + LockupTrL,Scale,SIZE1,SIZE2>>>, TR1, TR2, SaberBase::LOCKUP_MELT>; @@ -81,12 +81,12 @@ using ResponsiveLightningBlockL = template, - int TOP = 26000, - int BOTTOM = 4000, - int SIZE = 10000> + class TOP = Scale,Int<4000>,Int<28000>>, + class BOTTOM = Int<6000>, + class SIZE = Int<10000>> using ResponsiveClashL = TransitionEffectL,Int,Int>,Int>>, + AlphaL,TOP,BOTTOM>,SIZE>>, TR2>, EFFECT_CLASH>; @@ -102,15 +102,15 @@ template, class SIZE = Int<100>, class SPEED = Int<400>, - int TOP = 28000, - int BOTTOM = 8000, + class TOP = Int<28000>, + class BOTTOM = Int<8000>, BladeEffectType EFFECT = EFFECT_BLAST> using ResponsiveBlastL = AlphaL< MultiTransitionEffectL< - TrWaveX, Int, Int>>, + TrWaveX, TOP, BOTTOM>>, EFFECT>, - Bump,Int,Int>,Int<24000>>>; + Bump,TOP,BOTTOM>,Int<24000>>>; // ResponsiveBlastWaveL // Implements Blast effect that will move based on angle of the blade instead of random location Blast will impact and split up and down the length of the blade from original position @@ -124,15 +124,15 @@ template, class SIZE = Int<100>, class SPEED = Int<400>, - int TOP = 28000, - int BOTTOM = 8000, + class TOP = Int<28000>, + class BOTTOM = Int<8000>, BladeEffectType EFFECT = EFFECT_BLAST> using ResponsiveBlastWaveL = MultiTransitionEffectL< TrWaveX, - Int, - Int>>, + TOP, + BOTTOM>>, EFFECT>; // ResponsiveBlastFadeL @@ -145,13 +145,13 @@ using ResponsiveBlastWaveL = template, class FADE = Int<400>, - int TOP = 28000, - int BOTTOM = 8000, + class TOP = Int<28000>, + class BOTTOM = Int<8000>, BladeEffectType EFFECT = EFFECT_BLAST> using ResponsiveBlastFadeL = MultiTransitionEffectL< TrConcat, Int, Int>, SIZE>>, + AlphaL, TOP, BOTTOM>, SIZE>>, TrFadeX>, EFFECT>; @@ -163,11 +163,11 @@ using ResponsiveBlastFadeL = template, class TR2 = TrWipe<600>, - int SIZE1 = 14000, - int SIZE2 = 8000> + class SIZE1 = Int<14000>, + class SIZE2 = Int<8000>> using ResponsiveStabL = TransitionEffectL,Scale,Int,Int>>>, + AlphaL,Scale,SIZE1,SIZE2>>>, TR2>, EFFECT_STAB>; From 0e581b69fdcd728b0189045b4642718e9f3d9b19 Mon Sep 17 00:00:00 2001 From: fdarosa2663 Date: Sat, 2 May 2020 18:01:29 -0400 Subject: [PATCH 06/24] adding Fett263 buttons (#57) --- props/saber_fett263_buttons.h | 281 ++++++++++++++++++++++++++++++++++ 1 file changed, 281 insertions(+) create mode 100644 props/saber_fett263_buttons.h diff --git a/props/saber_fett263_buttons.h b/props/saber_fett263_buttons.h new file mode 100644 index 000000000..8562bcde5 --- /dev/null +++ b/props/saber_fett263_buttons.h @@ -0,0 +1,281 @@ +// Fett263 Buttons +// Includes "Multi-Blast" Mode to enable Swing Blast control and SA22C volume menu +// +// 2 Button Controls (PWR and AUX): +// Ignite (ON) - click PWR while OFF +// Muted Ignition (ON) - double click PWR while OFF +// Retract (OFF) - click PWR while ON (not swinging) +// Play Music Track - hold and release PWR while OFF +// Blast - click AUX while ON +// Multi-Blast Mode - hold and release AUX while ON to enter mode, Swing to initiate Blasts, click Aux to exit mode +// Clash - clash blade while ON +// Stab - thrust forward and clash blade while ON +// Lockup - hold AUX and clash while ON +// Drag - hold AUX and clash pointing down while ON +// Lightning Block - hold PWR and click AUX while ON +// Melt - hold PWR (or AUX) and thrust forward and clash while ON +// Force - hold and release PWR while ON +// Color Change - hold AUX and click PWR while ON to enter CCWheel, +// turn hilt to rotate through colors, click PWR to select/exit +// if using COLOR_CHANGE_DIRECT each button press advances one Color at a time +// Next Preset - click AUX while OFF +// Previous Preset - hold AUX and click PWR while OFF +// Enter SA22C Volume Menu - hold and release AUX while OFF +// Volume Up (10% increment, 100% max) - click PWR while in Volume Menu while OFF +// Volume Down (10% increment) - click AUX while in Volume Menu while OFF +// Exit Volume Menu - hold and release AUX while in Volume Menu while OFF + +#ifndef PROPS_SABER_FETT263_BUTTONS_H +#define PROPS_SABER_FETT263_BUTTONS_H + +#include "prop_base.h" +#include "../sound/hybrid_font.h" + +#undef PROP_TYPE +#define PROP_TYPE SaberFett263Buttons + +// The Saber class implements the basic states and actions +// for the saber. +class SaberFett263Buttons : public PropBase { +public: + SaberFett263Buttons() : PropBase() {} + const char* name() override { return "SaberFett263Buttons"; } + +// EVENT_SWING + bool swinging_ = false; + void Loop() override { + PropBase::Loop(); + if (!swinging_ && fusor.swing_speed() > 250) { + swinging_ = true; + Event(BUTTON_NONE, EVENT_SWING); + } + if (swinging_ && fusor.swing_speed() < 100) { + swinging_ = false; + } + } + +// SA22C 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)); + beeper.Beep(0.5, 2000); + STDOUT.print("Current Volume: "); + STDOUT.println(dynamic_mixer.get_volume()); + } + else { + beeper.Beep(0.5, 3000); + } +} + 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)); + beeper.Beep(0.5, 2000); + STDOUT.print("Current Volume: "); + STDOUT.println(dynamic_mixer.get_volume()); + } + else{ + beeper.Beep(0.5, 1000); + } + } + + 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): + if (accel_.x < -0.15) { + pointing_down_ = true; + } else { + pointing_down_ = false; + } + return true; + + case EVENTID(BUTTON_POWER, EVENT_LATCH_ON, MODE_OFF): + case EVENTID(BUTTON_AUX, EVENT_LATCH_ON, MODE_OFF): + case EVENTID(BUTTON_AUX2, EVENT_LATCH_ON, MODE_OFF): + case EVENTID(BUTTON_POWER, EVENT_CLICK_SHORT, MODE_OFF): + if (mode_volume_) { + VolumeUp(); + } else { + On(); + } + 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 + + + case EVENTID(BUTTON_AUX, EVENT_CLICK_SHORT, MODE_OFF): + if (mode_volume_) { + VolumeDown(); + } else { + next_preset(); + } + return true; + + // Handle double-click with preon + case EVENTID(BUTTON_POWER, EVENT_DOUBLE_CLICK, MODE_OFF): + if (on_pending_) { + if (SetMute(true)) { + unmute_on_deactivation_ = true; + } + return true; + } + return false; + + case EVENTID(BUTTON_POWER, EVENT_DOUBLE_CLICK, MODE_ON): + if (millis() - activated_ < 500) { + if (SetMute(true)) { + unmute_on_deactivation_ = true; + } + } + return true; + + case EVENTID(BUTTON_POWER, EVENT_CLICK_SHORT, MODE_ON): + case EVENTID(BUTTON_POWER, EVENT_LATCH_OFF, MODE_ON): + case EVENTID(BUTTON_AUX, EVENT_LATCH_OFF, MODE_ON): + case EVENTID(BUTTON_AUX2, EVENT_LATCH_OFF, MODE_ON): + +#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 (!swinging_) { + swing_blast_ = false; + Off(); + } + return true; + + case EVENTID(BUTTON_POWER, EVENT_CLICK_LONG, MODE_ON): + SaberBase::DoForce(); + return true; + + case EVENTID(BUTTON_AUX, EVENT_CLICK_SHORT, MODE_ON): + case EVENTID(BUTTON_AUX, EVENT_DOUBLE_CLICK, MODE_ON): + // Avoid the base and the very tip. + // TODO: Make blast only appear on one blade! + swing_blast_ = false; + SaberBase::DoBlast(); + return true; + + case EVENTID(BUTTON_AUX, EVENT_CLICK_LONG, MODE_ON): + swing_blast_ = true; + hybrid_font.SB_Blast(); + return true; + + case EVENTID(BUTTON_NONE, EVENT_SWING, MODE_ON): + if (swing_blast_) { + SaberBase::DoBlast(); + } + return true; + +#ifndef DISABLE_COLOR_CHANGE + case EVENTID(BUTTON_POWER, EVENT_CLICK_SHORT, MODE_ON | BUTTON_AUX): + ToggleColorChangeMode(); + break; +#endif + + // Lockup + case EVENTID(BUTTON_NONE, EVENT_CLASH, MODE_ON | BUTTON_POWER): + case EVENTID(BUTTON_NONE, EVENT_CLASH, MODE_ON | BUTTON_AUX): + if (!SaberBase::Lockup()) { + if (pointing_down_) { + SaberBase::SetLockup(SaberBase::LOCKUP_DRAG); + } else { + SaberBase::SetLockup(SaberBase::LOCKUP_NORMAL); + } + swing_blast_ = false; + SaberBase::DoBeginLockup(); + return true; + } + break; + + case EVENTID(BUTTON_AUX, EVENT_CLICK_SHORT, MODE_ON | BUTTON_POWER): + SaberBase::SetLockup(SaberBase::LOCKUP_LIGHTNING_BLOCK); + swing_blast_ = false; + SaberBase::DoBeginLockup(); + return true; + + case EVENTID(BUTTON_NONE, EVENT_STAB, MODE_ON | BUTTON_POWER): + case EVENTID(BUTTON_NONE, EVENT_STAB, MODE_ON | BUTTON_AUX): + if (!SaberBase::Lockup()) { + SaberBase::SetLockup(SaberBase::LOCKUP_MELT); + swing_blast_ = false; + SaberBase::DoBeginLockup(); + return true; + } + break; + + // Off functions + case EVENTID(BUTTON_POWER, EVENT_CLICK_LONG, MODE_OFF): + StartOrStopTrack(); + return true; + + case EVENTID(BUTTON_POWER, EVENT_PRESSED, MODE_OFF): + SaberBase::RequestMotion(); + return true; + + case EVENTID(BUTTON_AUX, EVENT_CLICK_LONG, MODE_OFF): + if (mode_volume_) { + mode_volume_ = false; + hybrid_font.SB_Change(EXIT_COLOR_CHANGE); + // beeper.Beep(0.5, 3000); + STDOUT.println("Exit Volume Menu"); + } else { + mode_volume_ = true; + hybrid_font.SB_Change(ENTER_COLOR_CHANGE); + // beeper.Beep(0.5, 3000); + STDOUT.println("Enter Volume Menu"); + } + return true; + + case EVENTID(BUTTON_NONE, EVENT_CLASH, MODE_OFF | BUTTON_POWER): + next_preset(); + return true; + + case EVENTID(BUTTON_POWER, EVENT_CLICK_SHORT, MODE_OFF | BUTTON_AUX): + previous_preset(); + return true; + + // 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): + if (SaberBase::Lockup()) { + SaberBase::DoEndLockup(); + SaberBase::SetLockup(SaberBase::LOCKUP_NONE); + return true; + } + } + return false; + } +private: + bool pointing_down_ = false; + bool swing_blast_ = false; + bool mode_volume_ = false; + +}; + +#endif From 7bbb06af83d3a0708c595f203f253406e82ed3ad Mon Sep 17 00:00:00 2001 From: profezzorn Date: Sat, 2 May 2020 15:06:12 -0700 Subject: [PATCH 07/24] fix indentation --- props/saber_fett263_buttons.h | 168 +++++++++++++++++----------------- 1 file changed, 83 insertions(+), 85 deletions(-) diff --git a/props/saber_fett263_buttons.h b/props/saber_fett263_buttons.h index 8562bcde5..72c20ee8f 100644 --- a/props/saber_fett263_buttons.h +++ b/props/saber_fett263_buttons.h @@ -15,8 +15,8 @@ // Lightning Block - hold PWR and click AUX while ON // Melt - hold PWR (or AUX) and thrust forward and clash while ON // Force - hold and release PWR while ON -// Color Change - hold AUX and click PWR while ON to enter CCWheel, -// turn hilt to rotate through colors, click PWR to select/exit +// Color Change - hold AUX and click PWR while ON to enter CCWheel, +// turn hilt to rotate through colors, click PWR to select/exit // if using COLOR_CHANGE_DIRECT each button press advances one Color at a time // Next Preset - click AUX while OFF // Previous Preset - hold AUX and click PWR while OFF @@ -38,49 +38,49 @@ // for the saber. class SaberFett263Buttons : public PropBase { public: - SaberFett263Buttons() : PropBase() {} +SaberFett263Buttons() : PropBase() {} const char* name() override { return "SaberFett263Buttons"; } -// EVENT_SWING - bool swinging_ = false; - void Loop() override { - PropBase::Loop(); - if (!swinging_ && fusor.swing_speed() > 250) { - swinging_ = true; - Event(BUTTON_NONE, EVENT_SWING); - } - if (swinging_ && fusor.swing_speed() < 100) { - swinging_ = false; - } - } + // EVENT_SWING + bool swinging_ = false; + void Loop() override { + PropBase::Loop(); + if (!swinging_ && fusor.swing_speed() > 250) { + swinging_ = true; + Event(BUTTON_NONE, EVENT_SWING); + } + if (swinging_ && fusor.swing_speed() < 100) { + swinging_ = false; + } + } -// SA22C Volume Menu + // SA22C 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)); - beeper.Beep(0.5, 2000); - STDOUT.print("Current Volume: "); - STDOUT.println(dynamic_mixer.get_volume()); - } - else { - beeper.Beep(0.5, 3000); - } -} - 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)); - beeper.Beep(0.5, 2000); - STDOUT.print("Current Volume: "); - STDOUT.println(dynamic_mixer.get_volume()); - } - else{ - beeper.Beep(0.5, 1000); - } + 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)); + beeper.Beep(0.5, 2000); + STDOUT.print("Current Volume: "); + STDOUT.println(dynamic_mixer.get_volume()); } + else { + beeper.Beep(0.5, 3000); + } + } + 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)); + beeper.Beep(0.5, 2000); + STDOUT.print("Current Volume: "); + STDOUT.println(dynamic_mixer.get_volume()); + } + else{ + beeper.Beep(0.5, 1000); + } + } bool Event2(enum BUTTON button, EVENT event, uint32_t modifiers) override { switch (EVENTID(button, event, modifiers)) { @@ -92,7 +92,7 @@ class SaberFett263Buttons : public PropBase { pointing_down_ = false; } return true; - + case EVENTID(BUTTON_POWER, EVENT_LATCH_ON, MODE_OFF): case EVENTID(BUTTON_AUX, EVENT_LATCH_ON, MODE_OFF): case EVENTID(BUTTON_AUX2, EVENT_LATCH_ON, MODE_OFF): @@ -103,7 +103,7 @@ class SaberFett263Buttons : public PropBase { On(); } 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): @@ -112,7 +112,7 @@ class SaberFett263Buttons : public PropBase { 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. @@ -121,26 +121,25 @@ class SaberFett263Buttons : public PropBase { SaberBase::DoBladeDetect(false); return true; #endif - - + case EVENTID(BUTTON_AUX, EVENT_CLICK_SHORT, MODE_OFF): - if (mode_volume_) { - VolumeDown(); + if (mode_volume_) { + VolumeDown(); } else { - next_preset(); + next_preset(); } return true; - - // Handle double-click with preon + + // Handle double-click with preon case EVENTID(BUTTON_POWER, EVENT_DOUBLE_CLICK, MODE_OFF): - if (on_pending_) { + if (on_pending_) { if (SetMute(true)) { unmute_on_deactivation_ = true; } - return true; - } - return false; - + return true; + } + return false; + case EVENTID(BUTTON_POWER, EVENT_DOUBLE_CLICK, MODE_ON): if (millis() - activated_ < 500) { if (SetMute(true)) { @@ -148,12 +147,12 @@ class SaberFett263Buttons : public PropBase { } } return true; - + case EVENTID(BUTTON_POWER, EVENT_CLICK_SHORT, MODE_ON): case EVENTID(BUTTON_POWER, EVENT_LATCH_OFF, MODE_ON): case EVENTID(BUTTON_AUX, EVENT_LATCH_OFF, MODE_ON): case EVENTID(BUTTON_AUX2, EVENT_LATCH_OFF, MODE_ON): - + #ifndef DISABLE_COLOR_CHANGE if (SaberBase::GetColorChangeMode() != SaberBase::COLOR_CHANGE_MODE_NONE) { // Just exit color change mode. @@ -163,15 +162,15 @@ class SaberFett263Buttons : public PropBase { } #endif if (!swinging_) { - swing_blast_ = false; + swing_blast_ = false; Off(); - } + } return true; - + case EVENTID(BUTTON_POWER, EVENT_CLICK_LONG, MODE_ON): SaberBase::DoForce(); return true; - + case EVENTID(BUTTON_AUX, EVENT_CLICK_SHORT, MODE_ON): case EVENTID(BUTTON_AUX, EVENT_DOUBLE_CLICK, MODE_ON): // Avoid the base and the very tip. @@ -179,24 +178,24 @@ class SaberFett263Buttons : public PropBase { swing_blast_ = false; SaberBase::DoBlast(); return true; - + case EVENTID(BUTTON_AUX, EVENT_CLICK_LONG, MODE_ON): swing_blast_ = true; hybrid_font.SB_Blast(); return true; - - case EVENTID(BUTTON_NONE, EVENT_SWING, MODE_ON): - if (swing_blast_) { - SaberBase::DoBlast(); - } - return true; - + + case EVENTID(BUTTON_NONE, EVENT_SWING, MODE_ON): + if (swing_blast_) { + SaberBase::DoBlast(); + } + return true; + #ifndef DISABLE_COLOR_CHANGE case EVENTID(BUTTON_POWER, EVENT_CLICK_SHORT, MODE_ON | BUTTON_AUX): ToggleColorChangeMode(); break; #endif - + // Lockup case EVENTID(BUTTON_NONE, EVENT_CLASH, MODE_ON | BUTTON_POWER): case EVENTID(BUTTON_NONE, EVENT_CLASH, MODE_ON | BUTTON_AUX): @@ -211,13 +210,13 @@ class SaberFett263Buttons : public PropBase { return true; } break; - + case EVENTID(BUTTON_AUX, EVENT_CLICK_SHORT, MODE_ON | BUTTON_POWER): - SaberBase::SetLockup(SaberBase::LOCKUP_LIGHTNING_BLOCK); - swing_blast_ = false; - SaberBase::DoBeginLockup(); - return true; - + SaberBase::SetLockup(SaberBase::LOCKUP_LIGHTNING_BLOCK); + swing_blast_ = false; + SaberBase::DoBeginLockup(); + return true; + case EVENTID(BUTTON_NONE, EVENT_STAB, MODE_ON | BUTTON_POWER): case EVENTID(BUTTON_NONE, EVENT_STAB, MODE_ON | BUTTON_AUX): if (!SaberBase::Lockup()) { @@ -227,16 +226,16 @@ class SaberFett263Buttons : public PropBase { return true; } break; - + // Off functions case EVENTID(BUTTON_POWER, EVENT_CLICK_LONG, MODE_OFF): StartOrStopTrack(); return true; - + case EVENTID(BUTTON_POWER, EVENT_PRESSED, MODE_OFF): SaberBase::RequestMotion(); return true; - + case EVENTID(BUTTON_AUX, EVENT_CLICK_LONG, MODE_OFF): if (mode_volume_) { mode_volume_ = false; @@ -248,17 +247,17 @@ class SaberFett263Buttons : public PropBase { hybrid_font.SB_Change(ENTER_COLOR_CHANGE); // beeper.Beep(0.5, 3000); STDOUT.println("Enter Volume Menu"); - } - return true; - + } + return true; + case EVENTID(BUTTON_NONE, EVENT_CLASH, MODE_OFF | BUTTON_POWER): next_preset(); return true; - + case EVENTID(BUTTON_POWER, EVENT_CLICK_SHORT, MODE_OFF | BUTTON_AUX): previous_preset(); return true; - + // Events that needs to be handled regardless of what other buttons // are pressed. case EVENTID(BUTTON_POWER, EVENT_RELEASED, MODE_ANY_BUTTON | MODE_ON): @@ -275,7 +274,6 @@ class SaberFett263Buttons : public PropBase { bool pointing_down_ = false; bool swing_blast_ = false; bool mode_volume_ = false; - }; #endif From 469fb3b9968d805a506fb48fab976fa9e862e0c4 Mon Sep 17 00:00:00 2001 From: profezzorn Date: Sat, 2 May 2020 15:21:37 -0700 Subject: [PATCH 08/24] update with LB, Melt and mult-blast --- props/saber_shtok_buttons.h | 197 ++++++++++++++++++++++++++---------- 1 file changed, 143 insertions(+), 54 deletions(-) diff --git a/props/saber_shtok_buttons.h b/props/saber_shtok_buttons.h index 25d30860d..d8d3ab465 100644 --- a/props/saber_shtok_buttons.h +++ b/props/saber_shtok_buttons.h @@ -8,9 +8,13 @@ // Lockup - hold + hit clash while ON // Drag - hold + hit clash while ON pointing the blade tip down // Blaster Blocks - short click while ON -// Force Effects - twist the hilt + press and hold the button while ON (while pointing up) -// Enter Color Change mode - twist the hilt + press and hold the button while ON (pointing down) +// Force Effects - twist the hilt + press and hold the button while ON (while pointing blade up) +// Enter Color Change mode - twist the hilt + press and hold the button while ON (pointing blade down) // Confirm selected color in Color Change mode - hold the button until confirmation sound +// Melt - hold the button + stab while ON +// Lightning Block - fast double click + hold the button while ON +// Enter Multi-Block mode - swing + hold the button for 1 second and release while ON (now swing the saber, blaster blocks will trigger automatically) +// Exit Multi-Block mode - short click while ON // // 2 Buttons: // Activate Muted - fast double click Activation button while OFF @@ -25,6 +29,10 @@ // Force Effects - short click Activation button while ON // Enter Color Change mode - hold AUX and click Activation button while ON // Confirm selected color in Color Change mode - hold the button until confirmation sound +// Melt - hold AUX (or Activation) button + perform stab action while ON +// Lightning Block - hold Activation button + short click AUX button while ON +// Enter Multi-Block mode - swing + hold the button for 1 second and release while ON (now swing the saber, blaster blocks will trigger automatically) +// Exit Multi-Block mode - short click AUX button while ON #ifndef PROPS_SABER_SHTOK_BUTTONS_H #define PROPS_SABER_SHTOK_BUTTONS_H @@ -34,13 +42,25 @@ #undef PROP_TYPE #define PROP_TYPE SaberShtokButtons -// The Saber class implements the basic states and actions -// for the saber. +// The Saber class implements the basic states and actions for the saber. class SaberShtokButtons : public PropBase { public: - SaberShtokButtons() : PropBase() {} +SaberShtokButtons() : PropBase() {} const char* name() override { return "SaberShtokButtons"; } +// EVENT_SWING + bool swinging_ = false; + void Loop() override { + PropBase::Loop(); + if (!swinging_ && fusor.swing_speed() > 250) { + swinging_ = true; + Event(BUTTON_NONE, EVENT_SWING); + } + if (swinging_ && fusor.swing_speed() < 100) { + swinging_ = false; + } + } + bool Event2(enum BUTTON button, EVENT event, uint32_t modifiers) override { switch (EVENTID(button, event, modifiers)) { case EVENTID(BUTTON_POWER, EVENT_PRESSED, MODE_ON): @@ -50,7 +70,7 @@ class SaberShtokButtons : public PropBase { } else { pointing_down_ = false; } - return true; + return true; // 1-button code @@ -63,7 +83,7 @@ class SaberShtokButtons : public PropBase { case EVENTID(BUTTON_POWER, EVENT_CLICK_SHORT, MODE_OFF): aux_on_ = false; On(); - return true; + return true; // Next Preset case EVENTID(BUTTON_POWER, EVENT_CLICK_LONG, MODE_OFF): @@ -73,7 +93,7 @@ class SaberShtokButtons : public PropBase { #else next_preset(); #endif - return true; + return true; // Previous Preset case EVENTID(BUTTON_POWER, EVENT_HELD_LONG, MODE_OFF): @@ -83,20 +103,20 @@ class SaberShtokButtons : public PropBase { #else previous_preset(); #endif - return true; + return true; // Activate Muted case EVENTID(BUTTON_POWER, EVENT_DOUBLE_CLICK, MODE_ON): - if (millis() - activated_ < 500) { - if (SetMute(true)) { - unmute_on_deactivation_ = true; - } - } - return true; - -// Turn Blade OFF + if (millis() - activated_ < 500) { + if (SetMute(true)) { + unmute_on_deactivation_ = true; + } + } + return true; + +// Turn Blade OFF case EVENTID(BUTTON_POWER, EVENT_HELD_LONG, MODE_ON): - if (!SaberBase::Lockup()) { + if (!SaberBase::Lockup()) { #ifndef DISABLE_COLOR_CHANGE if (SaberBase::GetColorChangeMode() != SaberBase::COLOR_CHANGE_MODE_NONE) { // Just exit color change mode. @@ -105,8 +125,9 @@ class SaberShtokButtons : public PropBase { return true; } #endif - Off(); - } + Off(); + } + swing_blast_ = false; return true; // Force and Color Change mode @@ -120,12 +141,25 @@ class SaberShtokButtons : public PropBase { #else SaberBase::DoForce(); #endif - return true; + return true; // Blaster Deflection case EVENTID(BUTTON_POWER, EVENT_CLICK_SHORT, MODE_ON): + swing_blast_ = false; SaberBase::DoBlast(); - return true; + return true; + +// Multi-Blaster Deflection mode + case EVENTID(BUTTON_NONE, EVENT_SWING, MODE_ON | BUTTON_POWER): + swing_blast_ = true; + hybrid_font.SB_Blast(); + return true; + + case EVENTID(BUTTON_NONE, EVENT_SWING, MODE_ON): + if (swing_blast_) { + SaberBase::DoBlast(); + } + return true; // Lockup case EVENTID(BUTTON_NONE, EVENT_CLASH, MODE_ON | BUTTON_POWER): @@ -136,19 +170,39 @@ class SaberShtokButtons : public PropBase { } else { SaberBase::SetLockup(SaberBase::LOCKUP_NORMAL); } + swing_blast_ = false; + SaberBase::DoBeginLockup(); + return true; + } + break; + +// Lightning Block + case EVENTID(BUTTON_POWER, EVENT_SECOND_HELD, MODE_ON): + SaberBase::SetLockup(SaberBase::LOCKUP_LIGHTNING_BLOCK); + swing_blast_ = false; + SaberBase::DoBeginLockup(); + return true; + +// Melt + case EVENTID(BUTTON_NONE, EVENT_STAB, MODE_ON | BUTTON_POWER): + case EVENTID(BUTTON_NONE, EVENT_STAB, MODE_ON | BUTTON_AUX): + if (!SaberBase::Lockup()) { + SaberBase::SetLockup(SaberBase::LOCKUP_MELT); + swing_blast_ = false; SaberBase::DoBeginLockup(); - return true; + return true; } break; // Start or Stop Track case EVENTID(BUTTON_POWER, EVENT_CLICK_LONG, MODE_ON): StartOrStopTrack(); - return true; + return true; case EVENTID(BUTTON_POWER, EVENT_PRESSED, MODE_OFF): SaberBase::RequestMotion(); - return true; + return true; + // 2-button code @@ -161,7 +215,7 @@ class SaberShtokButtons : public PropBase { case EVENTID(BUTTON_POWER, EVENT_CLICK_SHORT, MODE_OFF): aux_on_ = false; On(); - return true; + return true; // Next Preset case EVENTID(BUTTON_AUX, EVENT_CLICK_SHORT, MODE_OFF): @@ -171,22 +225,22 @@ class SaberShtokButtons : public PropBase { #else next_preset(); #endif - return true; + return true; // Activate Muted case EVENTID(BUTTON_POWER, EVENT_DOUBLE_CLICK, MODE_ON): - if (millis() - activated_ < 500) { - if (SetMute(true)) { - unmute_on_deactivation_ = true; - } - } - return true; - -// Turn Blade OFF + if (millis() - activated_ < 500) { + if (SetMute(true)) { + unmute_on_deactivation_ = true; + } + } + return true; + +// Turn Blade OFF case EVENTID(BUTTON_POWER, EVENT_HELD_LONG, MODE_ON): case EVENTID(BUTTON_AUX, EVENT_LATCH_OFF, MODE_ON): case EVENTID(BUTTON_AUX2, EVENT_LATCH_OFF, MODE_ON): - if (!SaberBase::Lockup()) { + if (!SaberBase::Lockup()) { #ifndef DISABLE_COLOR_CHANGE if (SaberBase::GetColorChangeMode() != SaberBase::COLOR_CHANGE_MODE_NONE) { // Just exit color change mode. @@ -195,38 +249,70 @@ class SaberShtokButtons : public PropBase { return true; } #endif - Off(); - } + Off(); + } + swing_blast_ = false; return true; // Force case EVENTID(BUTTON_POWER, EVENT_CLICK_SHORT, MODE_ON): SaberBase::DoForce(); - return true; + return true; // Color Change mode #ifndef DISABLE_COLOR_CHANGE case EVENTID(BUTTON_POWER, EVENT_CLICK_SHORT, MODE_ON | BUTTON_AUX): - ToggleColorChangeMode(); - break; + ToggleColorChangeMode(); + break; #endif // Blaster Deflection case EVENTID(BUTTON_AUX, EVENT_CLICK_SHORT, MODE_ON): + swing_blast_ = false; SaberBase::DoBlast(); - return true; + return true; + +// Multi-Blaster Deflection mode + case EVENTID(BUTTON_NONE, EVENT_SWING, MODE_ON | BUTTON_POWER): + swing_blast_ = true; + hybrid_font.SB_Blast(); + return true; + + case EVENTID(BUTTON_NONE, EVENT_SWING, MODE_ON): + if (swing_blast_) { + SaberBase::DoBlast(); + } + return true; // Lockup case EVENTID(BUTTON_AUX, EVENT_HELD, MODE_ON): - case EVENTID(BUTTON_NONE, EVENT_CLASH, MODE_ON | BUTTON_AUX): if (!SaberBase::Lockup()) { if (pointing_down_) { SaberBase::SetLockup(SaberBase::LOCKUP_DRAG); } else { SaberBase::SetLockup(SaberBase::LOCKUP_NORMAL); } + swing_blast_ = false; + SaberBase::DoBeginLockup(); + return true; + } + break; + +// Lightning Block + case EVENTID(BUTTON_AUX, EVENT_CLICK_SHORT, MODE_ON | BUTTON_POWER): + SaberBase::SetLockup(SaberBase::LOCKUP_LIGHTNING_BLOCK); + swing_blast_ = false; + SaberBase::DoBeginLockup(); + return true; + +// Melt + case EVENTID(BUTTON_NONE, EVENT_STAB, MODE_ON | BUTTON_POWER): + case EVENTID(BUTTON_NONE, EVENT_STAB, MODE_ON | BUTTON_AUX): + if (!SaberBase::Lockup()) { + SaberBase::SetLockup(SaberBase::LOCKUP_MELT); + swing_blast_ = false; SaberBase::DoBeginLockup(); - return true; + return true; } break; @@ -234,21 +320,21 @@ class SaberShtokButtons : public PropBase { case EVENTID(BUTTON_POWER, EVENT_CLICK_LONG, MODE_OFF): case EVENTID(BUTTON_POWER, EVENT_CLICK_LONG, MODE_ON): StartOrStopTrack(); - return true; + return true; case EVENTID(BUTTON_POWER, EVENT_PRESSED, MODE_OFF): SaberBase::RequestMotion(); - return true; + return true; case EVENTID(BUTTON_NONE, EVENT_CLASH, MODE_OFF | BUTTON_POWER): next_preset(); - return true; + return true; // Previous Preset case EVENTID(BUTTON_POWER, EVENT_CLICK_SHORT, MODE_OFF | BUTTON_AUX): previous_preset(); - return true; + return true; #else #error only 1 and 2 buttons are supported by this mod @@ -278,22 +364,25 @@ class SaberShtokButtons : public PropBase { #else previous_preset(); #endif - return true; + return true; // 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): - if (SaberBase::Lockup()) { - SaberBase::DoEndLockup(); - SaberBase::SetLockup(SaberBase::LOCKUP_NONE); - return true; - } + if (SaberBase::Lockup()) { + SaberBase::DoEndLockup(); + SaberBase::SetLockup(SaberBase::LOCKUP_NONE); + swing_blast_ = false; + return true; + } } return false; } + private: bool aux_on_ = true; bool pointing_down_ = false; + bool swing_blast_ = false; }; #endif From 9906b915ba73e23cad5d8009eafb54fcf05457a6 Mon Sep 17 00:00:00 2001 From: profezzorn Date: Sat, 2 May 2020 16:22:49 -0700 Subject: [PATCH 09/24] write out when saving fails --- common/current_preset.h | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/common/current_preset.h b/common/current_preset.h index 3525129d0..3f58ff98b 100644 --- a/common/current_preset.h +++ b/common/current_preset.h @@ -243,7 +243,10 @@ class CurrentPreset { FileReader f, out; if (!OpenPresets(&f, "presets.ini")) { if (!UpdateINI()) CreateINI(); - OpenPresets(&f, "presets.ini"); + if (!OpenPresets(&f, "presets.ini")) { + STDOUT << "SAVING FAILED!!!!\n"; + return; + } } PathHelper tmp_fn(GetSaveDir(), "presets.tmp"); LSFS::Remove(tmp_fn); From 9a51cfda85a58b8574b07f8964bdfd7c7cf21b90 Mon Sep 17 00:00:00 2001 From: profezzorn Date: Sat, 2 May 2020 16:23:25 -0700 Subject: [PATCH 10/24] make black turn off the blade --- styles/rgb.h | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/styles/rgb.h b/styles/rgb.h index c58cea0ce..e60623b02 100644 --- a/styles/rgb.h +++ b/styles/rgb.h @@ -40,7 +40,10 @@ template class Rgb16 { public: static Color16 color() { return Color16(R, G, B); } - void run(BladeBase* base) {} + bool run(BladeBase* base) { + if (R == 0 && G == 0 && B == 0) return false; // allow disable + return true; + } OverDriveColor getColor(int led) { OverDriveColor ret; ret.c = color(); From fbc086d7df4b48117c56f89154cdbe24bc838d11 Mon Sep 17 00:00:00 2001 From: profezzorn Date: Sun, 3 May 2020 15:22:06 -0700 Subject: [PATCH 11/24] PlayInCurrentDir --- sound/buffered_wav_player.h | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/sound/buffered_wav_player.h b/sound/buffered_wav_player.h index 0ef4fad98..14671b435 100644 --- a/sound/buffered_wav_player.h +++ b/sound/buffered_wav_player.h @@ -25,6 +25,23 @@ class BufferedWavPlayer : public VolumeOverlay > { pause_ = false; } + bool PlayInCurrentDir(const char* name) { + for (const char* dir = current_directory; dir; dir = next_current_directory(dir)) { + PathHelper full_name(dir, name); + LOCK_SD(true); + bool exists = LSFS::Exists(full_name); + LOCK_SD(false); + // Fill up audio buffers before we lock the SD again + AudioStreamWork::scheduleFillBuffer(); + if (exists) { + Play(full_name); + return true; + } + } + return false; + } + + void PlayOnce(Effect* effect, float start = 0.0) { MountSDCard(); EnableAmplifier(); From f418f5b956d40ed9a1c5111cbd559c56d8a35086 Mon Sep 17 00:00:00 2001 From: profezzorn Date: Sun, 3 May 2020 15:22:28 -0700 Subject: [PATCH 12/24] make play search current directory --- props/prop_base.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/props/prop_base.h b/props/prop_base.h index 99592f5ca..5f895e1a8 100644 --- a/props/prop_base.h +++ b/props/prop_base.h @@ -1035,7 +1035,8 @@ class PropBase : CommandParser, Looper, protected SaberBase { if (player) { STDOUT.print("Playing "); STDOUT.println(arg); - player->Play(arg); + if (!player->PlayInCurrentDir(arg)) + player->Play(arg); } else { STDOUT.println("No available WAV players."); } From ba0da9c8f9709b676f05a7670a00a5a0e0636d36 Mon Sep 17 00:00:00 2001 From: profezzorn Date: Sun, 3 May 2020 16:09:01 -0700 Subject: [PATCH 13/24] improve blade off logic for layers and convert InOutHelperX and InOutTr to layers --- functions/ifon.h | 22 ++++++++++++ functions/int.h | 8 ++++- styles/alpha.h | 11 ++++-- styles/blade_style.h | 36 ++++++++++++++++++++ styles/inout_helper.h | 70 ++++++++++++++------------------------ styles/layers.h | 15 ++++++-- styles/transition_effect.h | 7 +++- 7 files changed, 117 insertions(+), 52 deletions(-) diff --git a/functions/ifon.h b/functions/ifon.h index 1a498e5b4..8c59baedf 100644 --- a/functions/ifon.h +++ b/functions/ifon.h @@ -69,6 +69,28 @@ class InOutFuncX { int ret_; }; + +template +class InOutHelperF { +public: + LayerRunResult run(BladeBase* blade) __attribute__((warn_unused_result)) { + extension_.run(blade); + thres = (extension_.getInteger(0) * blade->num_leds()); + + if (ALLOW_DISABLE && thres == 0) + return LayerRunResult::OPAQUE_BLACK_UNTIL_IGNITION; + return LayerRunResult::UNKNOWN; + } + int getInteger(int led) { + return clampi32(thres - led * 32768, 0, 32768); + } +private: + EXTENSION extension_; + int thres = 0; +}; + + + #include "trigger.h" #include "scale.h" diff --git a/functions/int.h b/functions/int.h index b40b420c5..7e4e68e17 100644 --- a/functions/int.h +++ b/functions/int.h @@ -9,7 +9,13 @@ template class Int { public: - void run(BladeBase* base) {} + LayerRunResult run(BladeBase* base) { + switch (N) { + case 0: return LayerRunResult::TRANSPARENT_UNTIL_IGNITION; + case 32768: return LayerRunResult::OPAQUE_BLACK_UNTIL_IGNITION; + default: return LayerRunResult::UNKNOWN; + } + } int getInteger(int led) { return N; } }; diff --git a/styles/alpha.h b/styles/alpha.h index 3386d2a77..c5b1473d0 100644 --- a/styles/alpha.h +++ b/styles/alpha.h @@ -14,9 +14,14 @@ template class AlphaL { public: - void run(BladeBase* blade) { - color_.run(blade); - alpha_.run(blade); + LayerRunResult run(BladeBase* blade) { + bool base_run_result = RunStyle(&color_, blade); + LayerRunResult ret = RunLayer(&alpha_, blade); + if (ret == LayerRunResult::OPAQUE_BLACK_UNTIL_IGNITION && + base_run_result == true) { + return LayerRunResult::UNKNOWN; + } + return ret; } private: diff --git a/styles/blade_style.h b/styles/blade_style.h index 8d76b9aa2..db765f585 100644 --- a/styles/blade_style.h +++ b/styles/blade_style.h @@ -44,6 +44,12 @@ class StyleFactoryImpl : public StyleFactory { } }; +enum class LayerRunResult { + UNKNOWN, + OPAQUE_BLACK_UNTIL_IGNITION, + TRANSPARENT_UNTIL_IGNITION, +}; + template struct RunStyleHelper { static bool run(T* style, BladeBase* blade) { return style->run(blade); @@ -57,6 +63,12 @@ template struct RunStyleHelper { } }; +template struct RunStyleHelper { + static bool run(T* style, BladeBase* blade) { + return style->run(blade) == LayerRunResult::OPAQUE_BLACK_UNTIL_IGNITION; + } +}; + // Helper function for running the run() function in a style and // returning a bool. // Since some run() functions return void, we need some template @@ -66,4 +78,28 @@ inline bool RunStyle(T* style, BladeBase* blade) { return RunStyleHelperrun(blade))>::run(style, blade); } +template struct RunLayerHelper { + static LayerRunResult run(T* style, BladeBase* blade) { + style->run(blade); + return LayerRunResult::UNKNOWN; + } +}; + +template struct RunLayerHelper { + static LayerRunResult run(T* style, BladeBase* blade) { + return style->run(blade); + } +}; + +template struct RunLayerHelper { + static LayerRunResult run(T* style, BladeBase* blade) { + return style->run(blade) ? LayerRunResult::UNKNOWN : LayerRunResult::OPAQUE_BLACK_UNTIL_IGNITION; + } +}; + +template +inline LayerRunResult RunLayer(T* style, BladeBase* blade) { + return RunLayerHelperrun(blade))>::run(style, blade); +}; + #endif diff --git a/styles/inout_helper.h b/styles/inout_helper.h index 025e07d1c..edac74e6b 100644 --- a/styles/inout_helper.h +++ b/styles/inout_helper.h @@ -1,6 +1,11 @@ #ifndef STYLES_INOUT_HELPER_H #define STYLES_INOUT_HELPER_H +#include "alpha.h" +#include "layers.h" +#include "../functions/ifon.h" + + // InOutHelperX // BASE, OFF_COLOR: COLOR // EXTENSION: FUNCTION @@ -10,32 +15,11 @@ // is determined by EXTENSION. If EXTENSION returns 32768, the blade is fully // extended. If it returns zero, it is not extended. +template, bool ALLOW_DISABLE=1 > + using InOutHelperL = AlphaL>; + template, bool ALLOW_DISABLE=1 > -class InOutHelperX { -public: - bool run(BladeBase* blade) __attribute__((warn_unused_result)) { - base_.run(blade); - off_color_.run(blade); - extension_.run(blade); - thres = (extension_.getInteger(0) * blade->num_leds()) >> 7; - - if (ALLOW_DISABLE && is_same_type >::value && thres == 0) - return false; - return true; - } - OverDriveColor getColor(int led) { - int black_mix = clampi32(thres - led * 256, 0, 256); - OverDriveColor ret = base_.getColor(led); - OverDriveColor off_color = off_color_.getColor(led); - ret.c = off_color.c.mix(ret.c, black_mix); - return ret; - } -private: - T base_; - OFF_COLOR off_color_; - EXTENSION extension_; - int thres = 0; -}; + using InOutHelperX = Layers>; // Usage: InOutHelper // or: InOutHelper @@ -48,8 +32,6 @@ class InOutHelperX { // in BASE at the base of the saber. After OUT_MILLIS milliseconds, it // will be displaying the BASE color on the entire blade. -#include "../functions/ifon.h" - template > using InOutHelper = InOutHelperX, OFF_COLOR>; @@ -57,19 +39,17 @@ template, OFF_COLOR>; - // InOutTr // BASE, OFF_COLOR: COLOR // OUT_TRANSITION, IN_TRANSITION: TRANSITION // return value: COLOR // Similar to InOutHelper<>, but uses configuratble transitions // to go to and from the BASE to the OFF_COLOR. -template, bool ALLOW_DISABLE=1 > -class InOutTr { +template, bool ALLOW_DISABLE=1 > +class InOutTrL { public: - bool run(BladeBase* blade) __attribute__((warn_unused_result)) { - on_color_.run(blade); - off_color_.run(blade); + LayerRunResult run(BladeBase* blade) __attribute__((warn_unused_result)) { + LayerRunResult can_turn_off = RunLayer(&off_color_, blade); if (on_ != blade->is_on()) { if ((on_ = blade->is_on())) { @@ -89,21 +69,20 @@ class InOutTr { in_tr_.run(blade); if (in_tr_.done()) in_active_ = false; } - if (ALLOW_DISABLE && is_same_type >::value && - !on_ && !out_active_ && !in_active_) - return false; - return true; + if (ALLOW_DISABLE && !on_ && !out_active_ && !in_active_) + return can_turn_off; + return LayerRunResult::UNKNOWN; } - OverDriveColor runIn(OverDriveColor a, OverDriveColor b, int led) { + RGBA runIn(RGBA a, RGBA b, int led) { if (in_active_) { return in_tr_.getColor(a, b, led); } else { return b; } } - OverDriveColor runOut(OverDriveColor a, OverDriveColor b, int led) { + RGBA runOut(RGBA a, RGBA b, int led) { if (out_active_) { return out_tr_.getColor(a, b, led); } else { @@ -111,16 +90,16 @@ class InOutTr { } } - OverDriveColor getColor(int led) { + RGBA getColor(int led) { if (!out_active_ && !in_active_) { if (on_) { - return on_color_.getColor(led); + return RGBA_um::Transparent(); } else { return off_color_.getColor(led); } } else { - OverDriveColor on_color = on_color_.getColor(led); - OverDriveColor off_color = off_color_.getColor(led); + RGBA on_color = RGBA_um::Transparent(); + RGBA off_color = off_color_.getColor(led); if (on_) { return runOut(runIn(on_color, off_color, led), on_color, led); } else { @@ -132,10 +111,13 @@ class InOutTr { bool on_ = false; bool out_active_ = false; bool in_active_ = false; - ON on_color_; OFF off_color_; OutTr out_tr_; InTr in_tr_; }; +template, bool ALLOW_DISABLE=1 > + using InOutTr = Layers>; + + #endif diff --git a/styles/layers.h b/styles/layers.h index 34415c1e1..cc086937a 100644 --- a/styles/layers.h +++ b/styles/layers.h @@ -17,9 +17,18 @@ template class Layers {}; template class Layers { public: - bool run(BladeBase* blade) { - layer_.run(blade); - return RunStyle(&base_, blade); + LayerRunResult run(BladeBase* blade) { + LayerRunResult base_run_result = RunLayer(&base_, blade); + LayerRunResult layer_run_result = RunLayer(&layer_, blade); + switch (layer_run_result) { + case LayerRunResult::OPAQUE_BLACK_UNTIL_IGNITION: + return LayerRunResult::OPAQUE_BLACK_UNTIL_IGNITION; + case LayerRunResult::TRANSPARENT_UNTIL_IGNITION: + return base_run_result; + case LayerRunResult::UNKNOWN: + break; + } + return LayerRunResult::UNKNOWN; } private: BASE base_; diff --git a/styles/transition_effect.h b/styles/transition_effect.h index b03caf4b1..a6ddce5a6 100644 --- a/styles/transition_effect.h +++ b/styles/transition_effect.h @@ -16,7 +16,7 @@ template class TransitionEffectL { public: - void run(BladeBase* blade) { + LayerRunResult run(BladeBase* blade) { if (effect_.Detect(blade)) { transition_.begin(); run_ = true; @@ -24,7 +24,12 @@ class TransitionEffectL { if (run_) { transition_.run(blade); if (transition_.done()) run_ = false; + } else { + if (EFFECT == EFFECT_BOOT) { + return LayerRunResult::TRANSPARENT_UNTIL_IGNITION; + } } + return LayerRunResult::UNKNOWN; } private: From ed14913954b6cb1e5ea3c856c6de178c1d9d8a85 Mon Sep 17 00:00:00 2001 From: profezzorn Date: Sun, 3 May 2020 16:33:10 -0700 Subject: [PATCH 14/24] InOutHelper bugfix --- functions/ifon.h | 2 +- styles/Makefile | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/functions/ifon.h b/functions/ifon.h index 8c59baedf..c3721b6e5 100644 --- a/functions/ifon.h +++ b/functions/ifon.h @@ -82,7 +82,7 @@ class InOutHelperF { return LayerRunResult::UNKNOWN; } int getInteger(int led) { - return clampi32(thres - led * 32768, 0, 32768); + return 32768 - clampi32(thres - led * 32768, 0, 32768); } private: EXTENSION extension_; diff --git a/styles/Makefile b/styles/Makefile index df8105ead..62dcf2a9e 100644 --- a/styles/Makefile +++ b/styles/Makefile @@ -1,6 +1,6 @@ test: tests ./tests -tests: tests.cpp cylon.h style_ptr.h inout_helper.h +tests: tests.cpp cylon.h style_ptr.h inout_helper.h ../functions/ifon.h g++ -O -g -std=c++11 -o tests tests.cpp -lm From ed0f2832ced6898e8fc8dd84c4d58a36c89eb01a Mon Sep 17 00:00:00 2001 From: profezzorn Date: Sun, 3 May 2020 17:28:57 -0700 Subject: [PATCH 15/24] additional poweroff fixes --- styles/transition_effect.h | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/styles/transition_effect.h b/styles/transition_effect.h index a6ddce5a6..f30cdef50 100644 --- a/styles/transition_effect.h +++ b/styles/transition_effect.h @@ -25,8 +25,18 @@ class TransitionEffectL { transition_.run(blade); if (transition_.done()) run_ = false; } else { - if (EFFECT == EFFECT_BOOT) { - return LayerRunResult::TRANSPARENT_UNTIL_IGNITION; + switch (EFFECT) { + // This a list of effects that cannot occur after retraction is done. + case EFFECT_BOOT: + case EFFECT_PREON: + case EFFECT_IGNITION: + case EFFECT_RETRACTION: + + // NEWFONT is a special case, it CAN occur after retraction is done, but + // we also power the blade on at that time, so it's fine. + case EFFECT_NEWFONT: + return LayerRunResult::TRANSPARENT_UNTIL_IGNITION; + default: break; } } return LayerRunResult::UNKNOWN; From 4e7b28f2d77cce184b3348e775ebd75f5eb3f844 Mon Sep 17 00:00:00 2001 From: profezzorn Date: Mon, 4 May 2020 10:13:14 -0700 Subject: [PATCH 16/24] fix double-click mute --- props/saber.h | 2 +- props/saber_fett263_buttons.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/props/saber.h b/props/saber.h index 24e72259f..65d8dd982 100644 --- a/props/saber.h +++ b/props/saber.h @@ -85,7 +85,7 @@ class Saber : public PropBase { } return true; - case EVENTID(BUTTON_POWER, EVENT_CLICK_SHORT, MODE_ON): + case EVENTID(BUTTON_POWER, EVENT_FIRST_CLICK_SHORT, MODE_ON): case EVENTID(BUTTON_POWER, EVENT_LATCH_OFF, MODE_ON): case EVENTID(BUTTON_AUX, EVENT_LATCH_OFF, MODE_ON): case EVENTID(BUTTON_AUX2, EVENT_LATCH_OFF, MODE_ON): diff --git a/props/saber_fett263_buttons.h b/props/saber_fett263_buttons.h index 72c20ee8f..676b2defa 100644 --- a/props/saber_fett263_buttons.h +++ b/props/saber_fett263_buttons.h @@ -148,7 +148,7 @@ SaberFett263Buttons() : PropBase() {} } return true; - case EVENTID(BUTTON_POWER, EVENT_CLICK_SHORT, MODE_ON): + case EVENTID(BUTTON_POWER, EVENT_FIRST_CLICK_SHORT, MODE_ON): case EVENTID(BUTTON_POWER, EVENT_LATCH_OFF, MODE_ON): case EVENTID(BUTTON_AUX, EVENT_LATCH_OFF, MODE_ON): case EVENTID(BUTTON_AUX2, EVENT_LATCH_OFF, MODE_ON): From 1fc3d0608c9eb05da295557dfb645735bd08fcdc Mon Sep 17 00:00:00 2001 From: profezzorn Date: Mon, 4 May 2020 14:33:37 -0700 Subject: [PATCH 17/24] fix InOutHelper --- functions/ifon.h | 20 +++++++----- functions/int.h | 8 ++--- styles/Makefile | 2 +- styles/alpha.h | 13 ++++---- styles/blade_style.h | 39 ++++++++++++++++++++++- styles/tests.cpp | 74 ++++++++++++++++++++++++++++++++++++++++---- 6 files changed, 131 insertions(+), 25 deletions(-) diff --git a/functions/ifon.h b/functions/ifon.h index c3721b6e5..e0066fc42 100644 --- a/functions/ifon.h +++ b/functions/ifon.h @@ -38,7 +38,7 @@ class Ifon { template class InOutFuncX { public: - void run(BladeBase* blade) { + FunctionRunResult run(BladeBase* blade) { out_millis_.run(blade); in_millis_.run(blade); uint32_t now = micros(); @@ -58,6 +58,8 @@ class InOutFuncX { extension = std::max(extension, 0.0f); } ret_ = extension * 32768.0; + if (!blade->is_on() && ret_ == 0) return FunctionRunResult::ZERO_UNTIL_IGNITION; + return FunctionRunResult::UNKNOWN; } int getInteger(int led) { return ret_; } @@ -73,13 +75,17 @@ class InOutFuncX { template class InOutHelperF { public: - LayerRunResult run(BladeBase* blade) __attribute__((warn_unused_result)) { - extension_.run(blade); + FunctionRunResult run(BladeBase* blade) __attribute__((warn_unused_result)) { + FunctionRunResult ret = RunFunction(&extension_, blade); thres = (extension_.getInteger(0) * blade->num_leds()); - - if (ALLOW_DISABLE && thres == 0) - return LayerRunResult::OPAQUE_BLACK_UNTIL_IGNITION; - return LayerRunResult::UNKNOWN; + if (ALLOW_DISABLE) { + switch (ret) { + case FunctionRunResult::ZERO_UNTIL_IGNITION: return FunctionRunResult::ONE_UNTIL_IGNITION; + case FunctionRunResult::ONE_UNTIL_IGNITION: return FunctionRunResult::ZERO_UNTIL_IGNITION; + case FunctionRunResult::UNKNOWN: break; + } + } + return FunctionRunResult::UNKNOWN; } int getInteger(int led) { return 32768 - clampi32(thres - led * 32768, 0, 32768); diff --git a/functions/int.h b/functions/int.h index 7e4e68e17..b54102094 100644 --- a/functions/int.h +++ b/functions/int.h @@ -9,11 +9,11 @@ template class Int { public: - LayerRunResult run(BladeBase* base) { + FunctionRunResult run(BladeBase* base) { switch (N) { - case 0: return LayerRunResult::TRANSPARENT_UNTIL_IGNITION; - case 32768: return LayerRunResult::OPAQUE_BLACK_UNTIL_IGNITION; - default: return LayerRunResult::UNKNOWN; + case 0: return FunctionRunResult::ZERO_UNTIL_IGNITION; + case 32768: return FunctionRunResult::ONE_UNTIL_IGNITION; + default: return FunctionRunResult::UNKNOWN; } } int getInteger(int led) { return N; } diff --git a/styles/Makefile b/styles/Makefile index 62dcf2a9e..e98b1e8e6 100644 --- a/styles/Makefile +++ b/styles/Makefile @@ -1,6 +1,6 @@ test: tests ./tests -tests: tests.cpp cylon.h style_ptr.h inout_helper.h ../functions/ifon.h +tests: tests.cpp cylon.h style_ptr.h inout_helper.h ../functions/ifon.h alpha.h blade_style.h g++ -O -g -std=c++11 -o tests tests.cpp -lm diff --git a/styles/alpha.h b/styles/alpha.h index c5b1473d0..dbced5efd 100644 --- a/styles/alpha.h +++ b/styles/alpha.h @@ -15,13 +15,14 @@ template class AlphaL { public: LayerRunResult run(BladeBase* blade) { - bool base_run_result = RunStyle(&color_, blade); - LayerRunResult ret = RunLayer(&alpha_, blade); - if (ret == LayerRunResult::OPAQUE_BLACK_UNTIL_IGNITION && - base_run_result == true) { - return LayerRunResult::UNKNOWN; + LayerRunResult base_run_result = RunLayer(&color_, blade); + FunctionRunResult ret = RunFunction(&alpha_, blade); + switch (ret) { + case FunctionRunResult::ONE_UNTIL_IGNITION: return base_run_result; + case FunctionRunResult::ZERO_UNTIL_IGNITION: return LayerRunResult::TRANSPARENT_UNTIL_IGNITION; + case FunctionRunResult::UNKNOWN: break; } - return ret; + return LayerRunResult::UNKNOWN; } private: diff --git a/styles/blade_style.h b/styles/blade_style.h index db765f585..f648ed225 100644 --- a/styles/blade_style.h +++ b/styles/blade_style.h @@ -50,6 +50,12 @@ enum class LayerRunResult { TRANSPARENT_UNTIL_IGNITION, }; +enum class FunctionRunResult { + UNKNOWN, + ZERO_UNTIL_IGNITION, + ONE_UNTIL_IGNITION +}; + template struct RunStyleHelper { static bool run(T* style, BladeBase* blade) { return style->run(blade); @@ -65,7 +71,7 @@ template struct RunStyleHelper { template struct RunStyleHelper { static bool run(T* style, BladeBase* blade) { - return style->run(blade) == LayerRunResult::OPAQUE_BLACK_UNTIL_IGNITION; + return style->run(blade) != LayerRunResult::OPAQUE_BLACK_UNTIL_IGNITION; } }; @@ -102,4 +108,35 @@ inline LayerRunResult RunLayer(T* style, BladeBase* blade) { return RunLayerHelperrun(blade))>::run(style, blade); }; + +template struct RunFunctionHelper { + static FunctionRunResult run(T* style, BladeBase* blade) { + return style->ThisIsAnError(); + } +}; + +template struct RunFunctionHelper { + static FunctionRunResult run(T* style, BladeBase* blade) { + return style->run(blade); + } +}; + +template struct RunFunctionHelper { + static FunctionRunResult run(T* style, BladeBase* blade) { + style->run(blade); + return FunctionRunResult::UNKNOWN; + } +}; + +template struct RunFunctionHelper { + static FunctionRunResult run(T* style, BladeBase* blade) { + return style->ThisIsAnError(); + } +}; + +template +inline FunctionRunResult RunFunction(T* style, BladeBase* blade) { + return RunFunctionHelperrun(blade))>::run(style, blade); +}; + #endif diff --git a/styles/tests.cpp b/styles/tests.cpp index f792323ad..c68910a8e 100644 --- a/styles/tests.cpp +++ b/styles/tests.cpp @@ -65,6 +65,7 @@ struct Print { #include "inout_helper.h" bool on_ = true; +bool allow_disable_ = false; class MockBlade : public BladeBase { public: @@ -83,7 +84,9 @@ class MockBlade : public BladeBase { size_t GetEffects(BladeEffect** blade_effects) override { return 0; } - void allow_disable() override { } + void allow_disable() override { + allow_disable_ = true; + } void Activate() override { fprintf(stderr, "NOT IMPLEMENTED\n"); exit(1); @@ -170,27 +173,86 @@ void test_cylon() { } +#define STEP() do { \ + micros_ += 1000; \ + /* fprintf(stderr, "micros = %d on_ = %d\n", micros_, on_); */ \ + allow_disable_ = false; \ + t1.run(&mock_blade); \ +} while(0) + void test_inouthelper() { Style, 100, 100, Rgb16<0,0,0>>> t1; MockBlade mock_blade; mock_blade.colors.resize(1); on_ = false; micros_ = 0; - t1.run(&mock_blade); + STEP(); + + if (!allow_disable_) { + fprintf(stderr, "Should be able to turn off after first run.\n"); + exit(1); + } if (mock_blade.colors[0].r != 0) { fprintf(stderr, "InOutHelper fails to make blade completely black.\n"); exit(1); } on_ = true; - for (int i = 0; i < 200; i++) { - micros_ = i * 1000; - t1.run(&mock_blade); + int last = 0; + + STEP(); + if (allow_disable_) { + fprintf(stderr, "Should not be able to turn off when on.\n"); + exit(1); + } + + for (int i = 0; i < 90; i++) { + STEP(); + if (allow_disable_) { + fprintf(stderr, "Should not be able to turn off when extending.\n"); + exit(1); + } + if (mock_blade.colors[0].r <= last || mock_blade.colors[0].r == 65536) { + fprintf(stderr, "InOutHelper failed to brighten blade at t = %d red = %d last = %d\n", micros_, last, mock_blade.colors[0].r); + exit(1); + } + last = mock_blade.colors[0].r; + } + for (int i = 0; i < 110; i++) { + STEP(); + if (allow_disable_) { + fprintf(stderr, "Should not be able to turn off when on.\n"); + exit(1); + } } - t1.run(&mock_blade); if (mock_blade.colors[0].r != 65535) { fprintf(stderr, "InOutHelper fails to make blade completely white: %d != %d\n", mock_blade.colors[0].r, 65535); exit(1); } + last = 65535; + on_ = false; + for (int i = 0; i < 90; i++) { + STEP(); + if (allow_disable_) { + fprintf(stderr, "Should not be able to turn off when retracting.\n"); + exit(1); + } + if (mock_blade.colors[0].r >= last || mock_blade.colors[0].r == 0) { + fprintf(stderr, "InOutHelper failed to dim blade at t = %d\n", micros_); + exit(1); + } + last = mock_blade.colors[0].r; + } + for (int i = 0; i < 110; i++) { + STEP(); + } + if (!allow_disable_) { + fprintf(stderr, "Should be able to turn off when retracted.\n"); + exit(1); + } + if (mock_blade.colors[0].r != 0) { + fprintf(stderr, "InOutHelper fails to make blade completely black.\n"); + exit(1); + } } int main() { From f97f3658b5a74b2a964f57149468c78d840c7794 Mon Sep 17 00:00:00 2001 From: profezzorn Date: Mon, 4 May 2020 15:31:06 -0700 Subject: [PATCH 18/24] more tests... --- functions/blast.h | 2 +- styles/tests.cpp | 23 +++++++++++++++++++---- 2 files changed, 20 insertions(+), 5 deletions(-) diff --git a/functions/blast.h b/functions/blast.h index 3ff63f978..badec4c5c 100644 --- a/functions/blast.h +++ b/functions/blast.h @@ -126,7 +126,7 @@ class OriginalBlastF { mix += std::max(0.0, 2.0 * sinf(x / (t*t)) / x); } } - return std::min(mix, 1.0) * 32768; + return std::min(mix, 1.0) * 32768; } private: int num_leds_; diff --git a/styles/tests.cpp b/styles/tests.cpp index c68910a8e..e43516cd9 100644 --- a/styles/tests.cpp +++ b/styles/tests.cpp @@ -18,6 +18,7 @@ float fract(float x) { return x - floor(x); } uint32_t micros_ = 0; uint32_t micros() { return micros_; } +uint32_t millis() { return micros_ / 1000; } int32_t clampi32(int32_t x, int32_t a, int32_t b) { if (x < a) return a; if (x > b) return b; @@ -63,6 +64,10 @@ struct Print { #include "style_ptr.h" #include "colors.h" #include "inout_helper.h" +#include "blast.h" +#include "../transitions/base.h" +#include "../transitions/join.h" +#include "../transitions/wipe.h" bool on_ = true; bool allow_disable_ = false; @@ -177,11 +182,10 @@ void test_cylon() { micros_ += 1000; \ /* fprintf(stderr, "micros = %d on_ = %d\n", micros_, on_); */ \ allow_disable_ = false; \ - t1.run(&mock_blade); \ + style->run(&mock_blade); \ } while(0) -void test_inouthelper() { - Style, 100, 100, Rgb16<0,0,0>>> t1; +void test_inouthelper(BladeStyle* style) { MockBlade mock_blade; mock_blade.colors.resize(1); on_ = false; @@ -230,6 +234,7 @@ void test_inouthelper() { } last = 65535; on_ = false; + STEP(); for (int i = 0; i < 90; i++) { STEP(); if (allow_disable_) { @@ -237,7 +242,8 @@ void test_inouthelper() { exit(1); } if (mock_blade.colors[0].r >= last || mock_blade.colors[0].r == 0) { - fprintf(stderr, "InOutHelper failed to dim blade at t = %d\n", micros_); + fprintf(stderr, "InOutHelper failed to dim blade at t = %d r = %d last = %d\n", micros_, + mock_blade.colors[0].r, last); exit(1); } last = mock_blade.colors[0].r; @@ -255,6 +261,15 @@ void test_inouthelper() { } } +void test_inouthelper() { + fprintf(stderr, "Testing InOutHelper...\n"); + Style, 100, 100, Rgb16<0,0,0>>> t1; + test_inouthelper(&t1); + fprintf(stderr, "Testing InOutTr...\n"); + Style, TrWipe<100>, TrWipeIn<100>, Rgb16<0,0,0>>> t2; + test_inouthelper(&t2); +} + int main() { test_cylon(); test_inouthelper(); From 7936756f31908c4d294a63a8df5a7ab3479b0aaf Mon Sep 17 00:00:00 2001 From: profezzorn Date: Mon, 4 May 2020 15:56:24 -0700 Subject: [PATCH 19/24] more powerdown fixes --- styles/Makefile | 2 +- styles/rgb.h | 11 +++++++---- styles/tests.cpp | 17 +++++++++++++++++ styles/transition_effect.h | 3 ++- 4 files changed, 27 insertions(+), 6 deletions(-) diff --git a/styles/Makefile b/styles/Makefile index e98b1e8e6..a8b23075f 100644 --- a/styles/Makefile +++ b/styles/Makefile @@ -1,6 +1,6 @@ test: tests ./tests -tests: tests.cpp cylon.h style_ptr.h inout_helper.h ../functions/ifon.h alpha.h blade_style.h +tests: tests.cpp cylon.h style_ptr.h inout_helper.h ../functions/ifon.h alpha.h blade_style.h transition_effect.h layers.h *.h g++ -O -g -std=c++11 -o tests tests.cpp -lm diff --git a/styles/rgb.h b/styles/rgb.h index e60623b02..65e3a58de 100644 --- a/styles/rgb.h +++ b/styles/rgb.h @@ -26,7 +26,10 @@ template class Rgb { public: static Color16 color() { return Color16(Color8(R,G,B)); } - void run(BladeBase* base) {} + LayerRunResult run(BladeBase* base) { + if (R == 0 && G == 0 && B == 0) return LayerRunResult::OPAQUE_BLACK_UNTIL_IGNITION; + return LayerRunResult::UNKNOWN; + } OverDriveColor getColor(int led) { OverDriveColor ret; ret.c = color(); @@ -40,9 +43,9 @@ template class Rgb16 { public: static Color16 color() { return Color16(R, G, B); } - bool run(BladeBase* base) { - if (R == 0 && G == 0 && B == 0) return false; // allow disable - return true; + LayerRunResult run(BladeBase* base) { + if (R == 0 && G == 0 && B == 0) return LayerRunResult::OPAQUE_BLACK_UNTIL_IGNITION; + return LayerRunResult::UNKNOWN; } OverDriveColor getColor(int led) { OverDriveColor ret; diff --git a/styles/tests.cpp b/styles/tests.cpp index e43516cd9..bc8818f52 100644 --- a/styles/tests.cpp +++ b/styles/tests.cpp @@ -5,6 +5,7 @@ #include // cruft +#define NELEM(X) (sizeof(X)/sizeof((X)[0])) #define SCOPED_PROFILER() do { } while(0) template constexpr auto min(A&& a, B&& b) -> decltype(a < b ? std::forward(a) : std::forward(b)) { @@ -25,6 +26,7 @@ int32_t clampi32(int32_t x, int32_t a, int32_t b) { return x; } +int random(int x) { return (random(x) & 0x7fffff) % x; } class Looper { public: static void DoHFLoop() {} @@ -65,9 +67,15 @@ struct Print { #include "colors.h" #include "inout_helper.h" #include "blast.h" +#include "transition_effect.h" #include "../transitions/base.h" #include "../transitions/join.h" #include "../transitions/wipe.h" +#include "../transitions/delay.h" +#include "../transitions/concat.h" +#include "../transitions/fade.h" +#include "../transitions/instant.h" +#include "../functions/bump.h" bool on_ = true; bool allow_disable_ = false; @@ -268,6 +276,15 @@ void test_inouthelper() { fprintf(stderr, "Testing InOutTr...\n"); Style, TrWipe<100>, TrWipeIn<100>, Rgb16<0,0,0>>> t2; test_inouthelper(&t2); + fprintf(stderr, "Testing InOutTr #2...\n"); + Style, + TrWipe<100>, + TrWipeIn<100>, + Layers, Black, TrFade<1000>, AlphaL, Int<6000>>>,TrFade<3000>>, EFFECT_BOOT>, + TransitionEffectL, Int<6000>>>,TrFade<3000>>,EFFECT_NEWFONT>> + >> t3; + test_inouthelper(&t3); } int main() { diff --git a/styles/transition_effect.h b/styles/transition_effect.h index f30cdef50..8ec7c6565 100644 --- a/styles/transition_effect.h +++ b/styles/transition_effect.h @@ -24,7 +24,8 @@ class TransitionEffectL { if (run_) { transition_.run(blade); if (transition_.done()) run_ = false; - } else { + } + if (!run_) { switch (EFFECT) { // This a list of effects that cannot occur after retraction is done. case EFFECT_BOOT: From a70efa6906af8eb7b416c2dbdd95011adadd4555 Mon Sep 17 00:00:00 2001 From: profezzorn Date: Tue, 5 May 2020 10:47:18 -0700 Subject: [PATCH 20/24] button event fix --- buttons/button_base.h | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/buttons/button_base.h b/buttons/button_base.h index 2a1d15785..d3efd93d7 100644 --- a/buttons/button_base.h +++ b/buttons/button_base.h @@ -48,8 +48,10 @@ class ButtonBase : public Looper, // may double-presses there has been. The count starts at FIRST, that way // the first event can be distinguished from the rest. void Send(uint32_t event) { - prop.Event(button_, (EVENT)event); - prop.Event(button_, (EVENT)(event + (EVENT_SECOND_PRESSED - EVENT_FIRST_PRESSED) * press_count_)); + if (!prop.Event(button_, (EVENT)(event + (EVENT_SECOND_PRESSED - EVENT_FIRST_PRESSED) * press_count_))) { + // Only send the second event if the first event didn't trigger a response. + prop.Event(button_, (EVENT)event); + } } // We send the click immediately, but we also hold a "saved" event From e3bda5ea75e8bfd892ed86b916c64049d47bbfc2 Mon Sep 17 00:00:00 2001 From: profezzorn Date: Tue, 5 May 2020 17:29:42 -0700 Subject: [PATCH 21/24] turn blade on in SB_PreOn if it uses EFFECT_PREON --- blades/blade_base.h | 5 +++++ blades/fastled_blade.h | 9 +++++++++ blades/simple_blade.h | 9 +++++++++ blades/ws2811_blade.h | 9 +++++++++ 4 files changed, 32 insertions(+) diff --git a/blades/blade_base.h b/blades/blade_base.h index 1a57515b5..e06096457 100644 --- a/blades/blade_base.h +++ b/blades/blade_base.h @@ -53,6 +53,7 @@ DEFINE_ALL_EFFECTS(); HANDLED_FEATURE_DRAG = 1 << 3, HANDLED_FEATURE_MELT = 1 << 4, HANDLED_FEATURE_LIGHTNING_BLOCK = 1 << 5, + HANDLED_FEATURE_PREON = 1 << 6, }; #include "../styles/blade_style.h" @@ -135,6 +136,10 @@ class OneshotEffectDetector { switch (effect) { case EFFECT_STAB: BladeBase::HandleFeature(HANDLED_FEATURE_STAB); + break; + case EFFECT_PREON: + BladeBase::HandleFeature(HANDLED_FEATURE_PREON); + break; default: break; } diff --git a/blades/fastled_blade.h b/blades/fastled_blade.h index 52f31075c..3c0935eaf 100644 --- a/blades/fastled_blade.h +++ b/blades/fastled_blade.h @@ -101,6 +101,15 @@ class FASTLED_Blade : public AbstractBlade, CommandParser, Looper { delay(10); on_ = true; } + void SB_PreOn(float* d) override { + AbstractBlade::SB_PreOn(d); + // This blade uses EFFECT_PREON, so we need to turn the power on now. + if (IsHandled(HANDLED_FEATURE_PREON)) { + Power(true); + delay(10); + on_ = true; + } + } void SB_Off(OffType off_type) override { AbstractBlade::SB_Off(off_type); on_ = false; diff --git a/blades/simple_blade.h b/blades/simple_blade.h index aeda509c3..da2c96279 100644 --- a/blades/simple_blade.h +++ b/blades/simple_blade.h @@ -211,6 +211,15 @@ class Simple_Blade : public AbstractBlade, CommandParser, Looper { on_ = true; Power(true); } + void SB_PreOn(float* delay) override { + AbstractBlade::SB_PreOn(delay); + // This blade uses EFFECT_PREON, so we need to turn the power on now. + if (IsHandled(HANDLED_FEATURE_PREON)) { + battery_monitor.SetLoad(true); + on_ = true; + Power(true); + } + } void SB_Off(OffType off_type) override { AbstractBlade::SB_Off(off_type); battery_monitor.SetLoad(false); diff --git a/blades/ws2811_blade.h b/blades/ws2811_blade.h index e4d445a8d..a9a19b1d0 100644 --- a/blades/ws2811_blade.h +++ b/blades/ws2811_blade.h @@ -131,6 +131,15 @@ class WS2811_Blade : public AbstractBlade, CommandParser, Looper { on_ = true; power_off_requested_ = false; } + void SB_PreOn(float* delay) override { + AbstractBlade::SB_PreOn(delay); + // This blade uses EFFECT_PREON, so we need to turn the power on now. + if (IsHandled(HANDLED_FEATURE_PREON)) { + Power(true); + on_ = true; + power_off_requested_ = false; + } + } void SB_Off(OffType off_type) override { TRACE("SB_Off"); AbstractBlade::SB_Off(off_type); From db354822b3597653e8700a90489441fab65d039c Mon Sep 17 00:00:00 2001 From: profezzorn Date: Wed, 6 May 2020 09:48:38 -0700 Subject: [PATCH 22/24] preon does not imply "on" --- blades/fastled_blade.h | 1 - blades/simple_blade.h | 1 - blades/ws2811_blade.h | 1 - 3 files changed, 3 deletions(-) diff --git a/blades/fastled_blade.h b/blades/fastled_blade.h index 3c0935eaf..655b046f6 100644 --- a/blades/fastled_blade.h +++ b/blades/fastled_blade.h @@ -107,7 +107,6 @@ class FASTLED_Blade : public AbstractBlade, CommandParser, Looper { if (IsHandled(HANDLED_FEATURE_PREON)) { Power(true); delay(10); - on_ = true; } } void SB_Off(OffType off_type) override { diff --git a/blades/simple_blade.h b/blades/simple_blade.h index da2c96279..5071063c9 100644 --- a/blades/simple_blade.h +++ b/blades/simple_blade.h @@ -216,7 +216,6 @@ class Simple_Blade : public AbstractBlade, CommandParser, Looper { // This blade uses EFFECT_PREON, so we need to turn the power on now. if (IsHandled(HANDLED_FEATURE_PREON)) { battery_monitor.SetLoad(true); - on_ = true; Power(true); } } diff --git a/blades/ws2811_blade.h b/blades/ws2811_blade.h index a9a19b1d0..8c7fcdb88 100644 --- a/blades/ws2811_blade.h +++ b/blades/ws2811_blade.h @@ -136,7 +136,6 @@ class WS2811_Blade : public AbstractBlade, CommandParser, Looper { // This blade uses EFFECT_PREON, so we need to turn the power on now. if (IsHandled(HANDLED_FEATURE_PREON)) { Power(true); - on_ = true; power_off_requested_ = false; } } From 20c38b596439a8fdab9f10efab45cb57d019972d Mon Sep 17 00:00:00 2001 From: fdarosa2663 Date: Wed, 6 May 2020 18:49:12 -0400 Subject: [PATCH 23/24] Fix "blast" effect on ColorChange (#58) I found a missing "return true;" in the prop file what was triggering a blast effect on ToggleColorChangeMode() --- props/saber_fett263_buttons.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/props/saber_fett263_buttons.h b/props/saber_fett263_buttons.h index 676b2defa..b1e7cfafa 100644 --- a/props/saber_fett263_buttons.h +++ b/props/saber_fett263_buttons.h @@ -193,7 +193,7 @@ SaberFett263Buttons() : PropBase() {} #ifndef DISABLE_COLOR_CHANGE case EVENTID(BUTTON_POWER, EVENT_CLICK_SHORT, MODE_ON | BUTTON_AUX): ToggleColorChangeMode(); - break; + return true; #endif // Lockup From 98f3a69f5281d43793c17fe655b9263c8a5992d3 Mon Sep 17 00:00:00 2001 From: profezzorn Date: Wed, 6 May 2020 22:24:23 -0700 Subject: [PATCH 24/24] fix indentation and a missing "return true" --- props/saber.h | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/props/saber.h b/props/saber.h index 65d8dd982..3225a960a 100644 --- a/props/saber.h +++ b/props/saber.h @@ -67,16 +67,16 @@ class Saber : public PropBase { #endif return true; - // Handle double-click with preon + // Handle double-click with preon case EVENTID(BUTTON_POWER, EVENT_DOUBLE_CLICK, MODE_OFF): - if (on_pending_) { + if (on_pending_) { if (SetMute(true)) { unmute_on_deactivation_ = true; } - return true; - } - return false; - + return true; + } + return false; + case EVENTID(BUTTON_POWER, EVENT_DOUBLE_CLICK, MODE_ON): if (millis() - activated_ < 500) { if (SetMute(true)) { @@ -120,7 +120,7 @@ class Saber : public PropBase { #ifndef DISABLE_COLOR_CHANGE case EVENTID(BUTTON_POWER, EVENT_CLICK_SHORT, MODE_ON | BUTTON_AUX): ToggleColorChangeMode(); - break; + return true; #endif // Lockup @@ -138,9 +138,9 @@ class Saber : public PropBase { break; case EVENTID(BUTTON_AUX, EVENT_CLICK_SHORT, MODE_ON | BUTTON_POWER): - SaberBase::SetLockup(SaberBase::LOCKUP_LIGHTNING_BLOCK); - SaberBase::DoBeginLockup(); - return true; + SaberBase::SetLockup(SaberBase::LOCKUP_LIGHTNING_BLOCK); + SaberBase::DoBeginLockup(); + return true; case EVENTID(BUTTON_NONE, EVENT_STAB, MODE_ON | BUTTON_POWER): case EVENTID(BUTTON_NONE, EVENT_STAB, MODE_ON | BUTTON_AUX):