diff --git a/src/Kaleidoscope-LEDControl.cpp b/src/Kaleidoscope-LEDControl.cpp index c0c1e2ce..be12b6fb 100644 --- a/src/Kaleidoscope-LEDControl.cpp +++ b/src/Kaleidoscope-LEDControl.cpp @@ -1,83 +1,77 @@ #include "Kaleidoscope-LEDControl.h" #include "Kaleidoscope-Focus.h" -LEDMode *LEDControl_::modes[LED_MAX_MODES]; -uint8_t LEDControl_::previousMode, LEDControl_::mode; -uint16_t LEDControl_::syncDelay = 16; -uint32_t LEDControl_::syncTimer; +namespace kaleidoscope { -void -LEDMode::activate(void) { - LEDControl.activate(this); +LEDMode *LEDControl::modes[LED_MAX_MODES]; +uint8_t LEDControl::mode; +uint16_t LEDControl::syncDelay = 16; +uint32_t LEDControl::syncTimer; + +void LEDMode::activate(void) { + ::LEDControl.activate(this); } -void -LEDMode::begin(void) { - Kaleidoscope.use(&LEDControl, NULL); - LEDControl.mode_add(this); +void LEDMode::begin(void) { + Kaleidoscope.use(&::LEDControl); + ::LEDControl.mode_add(this); + setup(); } -LEDControl_::LEDControl_(void) { - mode = previousMode = 0; +LEDControl::LEDControl(void) { + mode = 0; memset(modes, 0, LED_MAX_MODES * sizeof(modes[0])); } -void -LEDControl_::next_mode(void) { +void LEDControl::next_mode(void) { mode++; - if (mode >= LED_MAX_MODES) { - mode = 0; - return; + if (mode >= LED_MAX_MODES || !modes[mode]) { + return set_mode(0); } - if (modes[mode]) - return; - - mode = 0; + return set_mode(mode); } -void -LEDControl_::update(void) { - if (previousMode != mode) { - set_all_leds_to({0, 0, 0}); - if (modes[mode]) - (modes[mode]->init)(); - } - +#if 0 +void LEDControl::update(void) { if (modes[mode]) (modes[mode]->update)(); - - previousMode = mode; } -void -LEDControl_::init_mode(void) { +void LEDControl::refreshAt(byte row, byte col) { if (modes[mode]) - (modes[mode]->init)(); + modes[mode]->refreshAt(row, col); } +#endif void -LEDControl_::set_mode(uint8_t mode_) { - if (mode_ < LED_MAX_MODES) - mode = mode_; +LEDControl::set_mode(uint8_t mode_) { + if (mode_ >= LED_MAX_MODES) + return; + + set_all_leds_to({0, 0, 0}); + mode = mode_; + if (modes[mode]) + modes[mode]->onActivate(); } -uint8_t -LEDControl_::get_mode(void) { +uint8_t LEDControl::get_mode_index(void) { return mode; } -void -LEDControl_::activate(LEDMode *mode) { +LEDMode *LEDControl::get_mode(void) { + return modes[mode]; +} + +void LEDControl::activate(LEDMode *mode) { for (uint8_t i = 0; i < LED_MAX_MODES; i++) { if (modes[i] == mode) return set_mode(i); } } -int8_t -LEDControl_::mode_add(LEDMode *mode) { +int8_t LEDControl::mode_add(LEDMode *mode) { for (int i = 0; i < LED_MAX_MODES; i++) { if (modes[i]) continue; @@ -88,8 +82,7 @@ LEDControl_::mode_add(LEDMode *mode) { return -1; } -void -LEDControl_::set_all_leds_to(uint8_t r, uint8_t g, uint8_t b) { +void LEDControl::set_all_leds_to(uint8_t r, uint8_t g, uint8_t b) { cRGB color; color.r = r; color.g = g; @@ -97,35 +90,29 @@ LEDControl_::set_all_leds_to(uint8_t r, uint8_t g, uint8_t b) { set_all_leds_to(color); } -void -LEDControl_::set_all_leds_to(cRGB color) { +void LEDControl::set_all_leds_to(cRGB color) { for (uint8_t i = 0; i < LED_COUNT; i++) { setCrgbAt(i, color); } } -void -LEDControl_::setCrgbAt(uint8_t i, cRGB crgb) { +void LEDControl::setCrgbAt(uint8_t i, cRGB crgb) { KeyboardHardware.setCrgbAt(i, crgb); } -void -LEDControl_::setCrgbAt(byte row, byte col, cRGB color) { +void LEDControl::setCrgbAt(byte row, byte col, cRGB color) { KeyboardHardware.setCrgbAt(row, col, color); } -cRGB -LEDControl_::getCrgbAt(uint8_t i) { +cRGB LEDControl::getCrgbAt(uint8_t i) { return KeyboardHardware.getCrgbAt(i); } -void -LEDControl_::syncLeds(void) { +void LEDControl::syncLeds(void) { KeyboardHardware.syncLeds(); } -void -LEDControl_::begin(void) { +void LEDControl::begin(void) { set_all_leds_to({0, 0, 0}); for (uint8_t i = 0; i < LED_MAX_MODES; i++) { @@ -133,25 +120,23 @@ LEDControl_::begin(void) { (modes[i]->setup)(); } - event_handler_hook_use(eventHandler); - loop_hook_use(loopHook); + Kaleidoscope.useEventHandlerHook(eventHandler); + Kaleidoscope.useLoopHook(loopHook); syncTimer = millis() + syncDelay; } -Key -LEDControl_::eventHandler(Key mappedKey, byte row, byte col, uint8_t keyState) { +Key LEDControl::eventHandler(Key mappedKey, byte row, byte col, uint8_t keyState) { if (mappedKey.flags != (SYNTHETIC | IS_INTERNAL | LED_TOGGLE)) return mappedKey; if (keyToggledOn(keyState)) - LEDControl.next_mode(); + next_mode(); return Key_NoKey; } -void -LEDControl_::loopHook(bool postClear) { +void LEDControl::loopHook(bool postClear) { if (postClear) return; @@ -162,8 +147,7 @@ LEDControl_::loopHook(bool postClear) { update(); } -bool -LEDControl_::focusHook(const char *command) { +bool LEDControl::focusHook(const char *command) { enum { SETALL, MODE, @@ -189,9 +173,9 @@ LEDControl_::focusHook(const char *command) { uint8_t idx = Serial.parseInt(); if (Serial.peek() == '\n') { - cRGB c = LEDControl.getCrgbAt(idx); + cRGB c = getCrgbAt(idx); - Focus.printColor(c.r, c.g, c.b); + ::Focus.printColor(c.r, c.g, c.b); Serial.println(); } else { cRGB c; @@ -200,7 +184,7 @@ LEDControl_::focusHook(const char *command) { c.g = Serial.parseInt(); c.b = Serial.parseInt(); - LEDControl.setCrgbAt(idx, c); + setCrgbAt(idx, c); } break; } @@ -211,16 +195,16 @@ LEDControl_::focusHook(const char *command) { c.g = Serial.parseInt(); c.b = Serial.parseInt(); - LEDControl.set_all_leds_to(c); + set_all_leds_to(c); break; } case MODE: { char peek = Serial.peek(); if (peek == '\n') { - Serial.println(LEDControl.get_mode()); + Serial.println(get_mode_index()); } else if (peek == 'n') { - LEDControl.next_mode(); + next_mode(); Serial.read(); } else if (peek == 'p') { // TODO(algernon) @@ -228,17 +212,17 @@ LEDControl_::focusHook(const char *command) { } else { uint8_t mode = Serial.parseInt(); - LEDControl.set_mode(mode); + set_mode(mode); } break; } case THEME: { if (Serial.peek() == '\n') { for (uint8_t idx = 0; idx < LED_COUNT; idx++) { - cRGB c = LEDControl.getCrgbAt(idx); + cRGB c = getCrgbAt(idx); - Focus.printColor(c.r, c.g, c.b); - Focus.printSpace(); + ::Focus.printColor(c.r, c.g, c.b); + ::Focus.printSpace(); } Serial.println(); break; @@ -252,7 +236,7 @@ LEDControl_::focusHook(const char *command) { color.g = Serial.parseInt(); color.b = Serial.parseInt(); - LEDControl.setCrgbAt(idx, color); + setCrgbAt(idx, color); idx++; } break; @@ -262,4 +246,6 @@ LEDControl_::focusHook(const char *command) { return true; } -LEDControl_ LEDControl; +} + +kaleidoscope::LEDControl LEDControl; diff --git a/src/Kaleidoscope-LEDControl.h b/src/Kaleidoscope-LEDControl.h index 5ece0b2a..e38012a9 100644 --- a/src/Kaleidoscope-LEDControl.h +++ b/src/Kaleidoscope-LEDControl.h @@ -8,27 +8,100 @@ #define Key_LEDEffectNext (Key) { 0, KEY_FLAGS | SYNTHETIC | IS_INTERNAL | LED_TOGGLE } +namespace kaleidoscope { +/** Base class for LED modes. + * + * LED modes are a special kind of plugin, they are in charge of updating LED + * colors, setting a theme. While it is possible to have other plugins + * override the mode's colors, the LED mode is the baseline. + * + * Most of its functionality is called via @ref LEDControl, with only a few + * public methods. + * + * A LED mode **must** implement at least one of @ref onActivate or @ref + * update, and possibly @ref refreshAt too. + */ class LEDMode : public KaleidoscopePlugin { - public: - virtual void begin(void); + friend class LEDControl; + protected: + // These methods should only be called by LEDControl. + + /** One-time setup, called at keyboard boot. + * + * Any hooks that need registering, any one-time setup that needs to be + * performed, shall be done here. This is purely for preparation purposes, the + * LEDs should not be touched yet at this time. + */ virtual void setup(void) {} - virtual void init(void) {} + + /** Function to call whenever the mode is activated. + * + * Like @ref setup, this method need not touch LEDs, @ref update will be + * called right after it. The purpose of this callback is to allow a plugin to + * do some preparation whenever it is activated, instead of only on boot, or + * always at each cycle. + * + * However, unlike @ref setup, this method can change LED colors, if so + * desired. Either to provide an initial state, or a static color set. In the + * latter case, consider implementing @ref refreshAt too, because other + * plugins may override some of the colors set at activation time, and @ref + * refreshAt can be used to restore them when needed. + * + * Before the callback runs, LEDs will be blanked. + */ + virtual void onActivate(void) {} + + /** Update the LEDs once per cycle. + * + * Usually the brains of the plugin, which updates the LEDs each cycle. It is + * called after the matrix has been scanned, once per cycle. + */ virtual void update(void) {} - virtual void activate(void); + + /** Refresh the color of a given key. + * + * If we have another plugin that overrides colors set by the active LED mode + * (either at @onActivate time, or via @ref update), if that plugin wants to + * restore whatever color the mode would set the key color to, this is the + * method it will call. + * + * @param row is the row coordinate of the key to refresh the color of. + * @param col is the column coordinate of the key to refresh the color of. + */ + virtual void refreshAt(byte row, byte col) {} + + public: + /** Activate the current object as the LED mode. + */ + void activate(void); + + /** Plugin initialization. + * + * Called via `Kaleidoscope.use()`, registers the LED mode, and does the + * necessary initialization steps. Calls @ref setup at the end. + */ + void begin(void) final; }; -class LEDControl_ : public KaleidoscopePlugin { +class LEDControl : public KaleidoscopePlugin { public: - LEDControl_(void); + LEDControl(void); void begin(void) final; static void next_mode(void); static void setup(void); - static void update(void); + static void update(void) { + if (modes[mode]) + modes[mode]->update(); + } + static void refreshAt(byte row, byte col) { + if (modes[mode]) + modes[mode]->refreshAt(row, col); + } static void set_mode(uint8_t mode); - static uint8_t get_mode(); - static void init_mode(void); + static uint8_t get_mode_index(); + static LEDMode *get_mode(); static int8_t mode_add(LEDMode *mode); @@ -49,13 +122,14 @@ class LEDControl_ : public KaleidoscopePlugin { private: static uint32_t syncTimer; static LEDMode *modes[LED_MAX_MODES]; - static uint8_t previousMode, mode; + static uint8_t mode; static Key eventHandler(Key mappedKey, byte row, byte col, uint8_t keyState); static void loopHook(bool postClear); }; +} -extern LEDControl_ LEDControl; +extern kaleidoscope::LEDControl LEDControl; #define FOCUS_HOOK_LEDCONTROL FOCUS_HOOK (LEDControl.focusHook, \ "led.at\n" \ diff --git a/src/LED-Off.cpp b/src/LED-Off.cpp index 1cacc667..25a74c04 100644 --- a/src/LED-Off.cpp +++ b/src/LED-Off.cpp @@ -1,7 +1,13 @@ #include "LED-Off.h" -void LEDOff_::update(void) { - LEDControl.set_all_leds_to({0, 0, 0}); +namespace kaleidoscope { +void LEDOff::onActivate(void) { + ::LEDControl.set_all_leds_to({0, 0, 0}); } -LEDOff_ LEDOff; +void LEDOff::refreshAt(byte row, byte col) { + ::LEDControl.setCrgbAt(row, col, {0, 0, 0}); +} +} + +kaleidoscope::LEDOff LEDOff; diff --git a/src/LED-Off.h b/src/LED-Off.h index 19d65cde..1da39edf 100644 --- a/src/LED-Off.h +++ b/src/LED-Off.h @@ -2,11 +2,15 @@ #include "Kaleidoscope-LEDControl.h" -class LEDOff_ : public LEDMode { +namespace kaleidoscope { +class LEDOff : public LEDMode { public: - LEDOff_(void) { } + LEDOff(void) { } - void update(void) final; + protected: + void onActivate(void) final; + void refreshAt(byte row, byte col) final; }; +} -extern LEDOff_ LEDOff; +extern kaleidoscope::LEDOff LEDOff;