diff --git a/examples/KeyboardioFirmware/KeyboardioFirmware.ino b/examples/KeyboardioFirmware/KeyboardioFirmware.ino index 274f4243..9f342368 100644 --- a/examples/KeyboardioFirmware/KeyboardioFirmware.ino +++ b/examples/KeyboardioFirmware/KeyboardioFirmware.ino @@ -7,6 +7,13 @@ #include "KeyboardioFirmware.h" #include "generated/keymaps.h" +#include "LED-BootAnimation.h" +#include "LED-SolidColor.h" +#include "LED-Numlock.h" +#include "LED-BreatheEffect.h" +#include "LED-ChaseEffect.h" +#include "LED-RainbowEffect.h" + uint8_t primary_keymap = 0; uint8_t temporary_keymap = 0; @@ -16,13 +23,27 @@ uint8_t temporary_keymap = 0; const Key keymaps[][ROWS][COLS] PROGMEM = { KEYMAP_LIST }; +static LEDBootAnimation bootAnimation; +static LEDSolidColor solidRed (100, 0, 0); +static LEDSolidColor solidOrange (100, 30, 0); +static LEDSolidColor solidYellow (90, 70, 0); +static LEDSolidColor solidGreen (0, 200, 0); +static LEDSolidColor solidBlue (0, 30, 200); +static LEDSolidColor solidIndigo (0, 0, 200); +static LEDSolidColor solidViolet (100, 0, 120); + +static LEDBreatheEffect breatheEffect; +static LEDRainbowEffect rainbowEffect; +static LEDRainbowWaveEffect rainbowWaveEffect; +static LEDChaseEffect chaseEffect; + +static LEDNumlock numLockEffect (NUMPAD_KEYMAP); + void setup() { - Keyboardio.setup(KEYMAPS, NUMPAD_KEYMAP); + Keyboardio.setup(KEYMAPS); } void loop() { Keyboardio.loop(); } - - diff --git a/src/KeyboardioFirmware.cpp b/src/KeyboardioFirmware.cpp index 6909c0df..7193d4e4 100644 --- a/src/KeyboardioFirmware.cpp +++ b/src/KeyboardioFirmware.cpp @@ -1,12 +1,10 @@ #include "KeyboardioFirmware.h" -byte NUMPAD_KEYMAP = 0; - Keyboardio_::Keyboardio_(void) { } void -Keyboardio_::setup(const byte keymap_count, const byte numpad_layer) { +Keyboardio_::setup(const byte keymap_count) { event_handler_hook_add (handle_key_event_default); wdt_disable(); delay(100); @@ -14,9 +12,8 @@ Keyboardio_::setup(const byte keymap_count, const byte numpad_layer) { Mouse.begin(); AbsoluteMouse.begin(); KeyboardHardware.setup(); - LEDControl.boot_animation(); + LEDControl.setup(); - NUMPAD_KEYMAP = numpad_layer; temporary_keymap = primary_keymap = Storage.load_primary_keymap(keymap_count); } @@ -30,7 +27,7 @@ Keyboardio_::loop(void) { } KeyboardHardware.scan_matrix(); - LEDControl.update(temporary_keymap); + LEDControl.update(); Keyboard.sendReport(); Keyboard.releaseAll(); } diff --git a/src/KeyboardioFirmware.h b/src/KeyboardioFirmware.h index 3cbe9de4..e476fe03 100644 --- a/src/KeyboardioFirmware.h +++ b/src/KeyboardioFirmware.h @@ -37,7 +37,7 @@ class Keyboardio_ { public: Keyboardio_(void); - void setup(const byte keymap_count, const byte numpad_layer); + void setup(const byte keymap_count); void loop(void); }; diff --git a/src/LED-BootAnimation.cpp b/src/LED-BootAnimation.cpp new file mode 100644 index 00000000..728c4eb1 --- /dev/null +++ b/src/LED-BootAnimation.cpp @@ -0,0 +1,35 @@ +#include "LED-BootAnimation.h" + +static void +type_letter(uint8_t letter) { + led_set_crgb_at(letter, {255, 0, 0}); + led_sync(); + delay(250); + led_set_crgb_at(letter, {0, 0, 0}); + led_sync(); + delay(10); +} + +LEDBootAnimation::LEDBootAnimation (void) { + LEDControl.mode_add (this); +} + +void +LEDBootAnimation::setup (void) { + LEDControl.set_all_leds_to(0, 0, 0); + + type_letter(LED_K); + type_letter(LED_E); + type_letter(LED_Y); + type_letter(LED_B); + type_letter(LED_O); + type_letter(LED_A); + type_letter(LED_R); + type_letter(LED_D); + type_letter(LED_I); + type_letter(LED_O); + type_letter(LED_SPACE); + type_letter(LED_0); + type_letter(LED_PERIOD); + type_letter(LED_9); +} diff --git a/src/LED-BootAnimation.h b/src/LED-BootAnimation.h new file mode 100644 index 00000000..dcd4f616 --- /dev/null +++ b/src/LED-BootAnimation.h @@ -0,0 +1,10 @@ +#pragma once + +#include "LEDControl.h" + +class LEDBootAnimation : LEDMode { + public: + LEDBootAnimation (void); + + virtual void setup (void) final; +}; diff --git a/src/LED-BreatheEffect.cpp b/src/LED-BreatheEffect.cpp new file mode 100644 index 00000000..69928d77 --- /dev/null +++ b/src/LED-BreatheEffect.cpp @@ -0,0 +1,14 @@ +#include "LED-BreatheEffect.h" + +LEDBreatheEffect::LEDBreatheEffect (void) { + state.brightness = 0; + state.fadeAmount = 1; + + LEDControl.mode_add (this); +} + +void +LEDBreatheEffect::update (void) { + cRGB color = breath_compute (&state); + LEDControl.set_all_leds_to (color); +} diff --git a/src/LED-BreatheEffect.h b/src/LED-BreatheEffect.h new file mode 100644 index 00000000..67b0c48c --- /dev/null +++ b/src/LED-BreatheEffect.h @@ -0,0 +1,14 @@ +#pragma once + +#include "LEDControl.h" +#include "LEDUtils.h" + +class LEDBreatheEffect : LEDMode { + public: + LEDBreatheEffect (void); + + virtual void update (void) final; + + private: + BreathState state; +}; diff --git a/src/LED-ChaseEffect.cpp b/src/LED-ChaseEffect.cpp new file mode 100644 index 00000000..8a212e37 --- /dev/null +++ b/src/LED-ChaseEffect.cpp @@ -0,0 +1,22 @@ +#include "LED-ChaseEffect.h" + +LEDChaseEffect::LEDChaseEffect (void) { + LEDControl.mode_add (this); +} + +void +LEDChaseEffect::update (void) { + if (current_chase_counter++ < chase_threshold) { + return; + } + current_chase_counter = 0; + led_set_crgb_at(pos - (chase_sign* chase_pixels), {0, 0, 0}); + led_set_crgb_at(pos, {0, 0, 0}); + + pos += chase_sign; + if (pos >= LED_COUNT || pos <= 0) { + chase_sign = -chase_sign; + } + led_set_crgb_at(pos, {0, 0, 255}); + led_set_crgb_at(pos - (chase_sign * chase_pixels), {255, 0, 0}); +} diff --git a/src/LED-ChaseEffect.h b/src/LED-ChaseEffect.h new file mode 100644 index 00000000..54f81a08 --- /dev/null +++ b/src/LED-ChaseEffect.h @@ -0,0 +1,18 @@ +#pragma once + +#include "LEDControl.h" +#include "LEDUtils.h" + +class LEDChaseEffect : LEDMode { + public: + LEDChaseEffect (void); + + virtual void update (void) final; + + private: + uint8_t pos = 0; + int8_t chase_sign = 1; //negative values when it's going backwar + uint8_t chase_pixels = 5; + uint8_t current_chase_counter = 0; + static const uint8_t chase_threshold = 20; +}; diff --git a/src/LED-Numlock.cpp b/src/LED-Numlock.cpp new file mode 100644 index 00000000..78c110c6 --- /dev/null +++ b/src/LED-Numlock.cpp @@ -0,0 +1,50 @@ +#include "LED-Numlock.h" +#include "LEDUtils.h" + +static uint8_t numpadIndex; +static uint8_t storedLEDMode; +static uint8_t us; + +LEDNumlock::LEDNumlock (uint8_t numpadIdx) { + numpadIndex = numpadIdx; + us = LEDControl.mode_add (this); + loop_hook_add (this->loopHook); + + breathState.brightness = 0; + breathState.fadeAmount = 1; +} + +void +LEDNumlock::setup (void) { + if (temporary_keymap != numpadIndex) { + LEDControl.next_mode (); + } +} + +void +LEDNumlock::update (void) { + for (uint8_t i = 0; i < 44; i++) { + led_set_crgb_at(i, {0, 0, 0}); + } + for (uint8_t i = 44; i < LED_COUNT; i++) { + led_set_crgb_at(i, {255, 0, 0}); + } + + cRGB color = breath_compute (&breathState); + led_set_crgb_at (60, color); +} + +void +LEDNumlock::loopHook (void) { + if (temporary_keymap == numpadIndex) { + if (storedLEDMode != us) { + storedLEDMode = LEDControl.get_mode (); + } + LEDControl.set_mode (us); + } + + if (temporary_keymap != numpadIndex && + LEDControl.get_mode () == us) { + LEDControl.set_mode (storedLEDMode); + } +} diff --git a/src/LED-Numlock.h b/src/LED-Numlock.h new file mode 100644 index 00000000..29826924 --- /dev/null +++ b/src/LED-Numlock.h @@ -0,0 +1,17 @@ +#pragma once + +#include "LEDControl.h" +#include "LEDUtils.h" + +class LEDNumlock : LEDMode { + public: + LEDNumlock (uint8_t numpadIndex); + + virtual void update (void) final; + virtual void setup (void) final; + + private: + static void loopHook (void); + + BreathState breathState; +}; diff --git a/src/LED-RainbowEffect.cpp b/src/LED-RainbowEffect.cpp new file mode 100644 index 00000000..5b5653ae --- /dev/null +++ b/src/LED-RainbowEffect.cpp @@ -0,0 +1,50 @@ +#include "LED-RainbowEffect.h" + +LEDRainbowEffect::LEDRainbowEffect (void) { + LEDControl.mode_add (this); +} + +void +LEDRainbowEffect::update (void) { + if (rainbow_current_ticks++ < rainbow_ticks) { + return; + } else { + rainbow_current_ticks = 0; + } + + cRGB rainbow = hsv_to_rgb(rainbow_hue, rainbow_saturation, rainbow_value); + + rainbow_hue += rainbow_steps; + if (rainbow_hue >= 255) { + rainbow_hue -= 255; + } + LEDControl.set_all_leds_to(rainbow); +} + +// --------- + +LEDRainbowWaveEffect::LEDRainbowWaveEffect (void) { + LEDControl.mode_add (this); +} + +void +LEDRainbowWaveEffect::update (void) { + if (rainbow_current_ticks++ < rainbow_wave_ticks) { + return; + } else { + rainbow_current_ticks = 0; + } + + for (uint8_t i = 0; i < LED_COUNT; i++) { + uint16_t key_hue = rainbow_hue +16*(i/4); + if (key_hue >= 255) { + key_hue -= 255; + } + cRGB rainbow = hsv_to_rgb(key_hue, rainbow_saturation, rainbow_value); + led_set_crgb_at (i, rainbow); + } + rainbow_hue += rainbow_wave_steps; + if (rainbow_hue >= 255) { + rainbow_hue -= 255; + } +} diff --git a/src/LED-RainbowEffect.h b/src/LED-RainbowEffect.h new file mode 100644 index 00000000..ae02d5b6 --- /dev/null +++ b/src/LED-RainbowEffect.h @@ -0,0 +1,39 @@ +#pragma once + +#include "LEDControl.h" +#include "LEDUtils.h" + +class LEDRainbowEffect : LEDMode { + public: + LEDRainbowEffect (void); + + virtual void update (void) final; + + private: + uint16_t rainbow_hue = 0; //stores 0 to 614 + + static const uint8_t rainbow_steps = 1; //number of hues we skip in a 360 range per update + long rainbow_current_ticks = 0; + static const long rainbow_ticks = 10; //delays between update + + static const byte rainbow_saturation = 255; + static const byte rainbow_value = 50; + +}; + +class LEDRainbowWaveEffect : LEDMode { + public: + LEDRainbowWaveEffect (void); + + virtual void update (void) final; + + private: + uint16_t rainbow_hue = 0; //stores 0 to 614 + + static const uint8_t rainbow_wave_steps = 1; //number of hues we skip in a 360 range per update + long rainbow_current_ticks = 0; + static const long rainbow_wave_ticks = 10; //delays between update + + static const byte rainbow_saturation = 255; + static const byte rainbow_value = 50; +}; diff --git a/src/LED-SolidColor.cpp b/src/LED-SolidColor.cpp new file mode 100644 index 00000000..84a57126 --- /dev/null +++ b/src/LED-SolidColor.cpp @@ -0,0 +1,13 @@ +#include "LED-SolidColor.h" + +LEDSolidColor::LEDSolidColor (uint8_t r, uint8_t g, uint8_t b) { + this->r = r; + this->g = g; + this->b = b; + LEDControl.mode_add (this); +} + +void +LEDSolidColor::init (void) { + LEDControl.set_all_leds_to (r, g, b); +} diff --git a/src/LED-SolidColor.h b/src/LED-SolidColor.h new file mode 100644 index 00000000..562a02d1 --- /dev/null +++ b/src/LED-SolidColor.h @@ -0,0 +1,13 @@ +#pragma once + +#include "LEDControl.h" + +class LEDSolidColor : LEDMode { + public: + LEDSolidColor (uint8_t r, uint8_t g, uint8_t b); + + virtual void init (void) final; + + private: + uint8_t r, g, b; +}; diff --git a/src/LEDControl.cpp b/src/LEDControl.cpp index b0321a3e..cdc2f650 100644 --- a/src/LEDControl.cpp +++ b/src/LEDControl.cpp @@ -1,322 +1,85 @@ #include "LEDControl.h" - - LEDControl_::LEDControl_(void) { - led_off.r = 0; - led_off.g = 0; - led_off.b = 0; - led_steady.r = 0; - led_steady.g = 255; - led_steady.b = 0; - led_blue.r = 0; - led_blue.g = 0; - led_blue.b = 255; - led_dark_blue.r = 0; - led_dark_blue.g = 0; - led_dark_blue.b = 127; - led_red.r = 255; - led_red.g = 0; - led_red.b = 0; - led_dark_red.r = 127; - led_dark_red.g = 0; - led_dark_red.b = 0; - -} - - -void LEDControl_::initialize_led_mode(uint8_t mode) { - set_all_leds_to(led_off); - - switch (mode) { - - case LED_MODE_RED: - set_all_leds_to(100,0,0) ; - break; - case LED_MODE_ORANGE: - set_all_leds_to(100,30,0) ; - break; - case LED_MODE_YELLOW: - set_all_leds_to(90,70,0) ; - break; - - case LED_MODE_GREEN: - set_all_leds_to(0,200,0) ; - break; - - case LED_MODE_BLUE: - set_all_leds_to(0,30,160) ; - break; - case LED_MODE_INDIGO: - set_all_leds_to(0,0,200) ; - break; - case LED_MODE_VIOLET: - set_all_leds_to(100,0,120) ; - break; - case LED_MODE_OFF: - break; - case LED_MODE_BREATHE: - break; - - case LED_MODE_RAINBOW: - break; - case LED_MODE_RAINBOW_WAVE: - break; - case LED_MODE_CHASE: - break; - default: - break; - } + memset (modes, 0, LED_MAX_MODES * sizeof (modes[0])); } -void LEDControl_::set_all_leds_to(uint8_t r, uint8_t g, uint8_t b) { - cRGB color; - color.r=r; - color.g=g; - color.b=b; - set_all_leds_to(color); -} -void LEDControl_::set_all_leds_to(cRGB color) { - for (uint8_t i = 0; i < LED_COUNT; i++) { - led_set_crgb_at(i, color); - } -} - - -void LEDControl_::next_mode() { - if (led_mode++ >= LED_MODES) { - led_mode = 0; - } -} - -void LEDControl_::set_mode(uint8_t mode) { - led_mode = mode; -} - - - - -void LEDControl_::update(uint8_t current_keymap) { - if (current_keymap == NUMPAD_KEYMAP) { - if (led_mode != LED_SPECIAL_MODE_NUMLOCK) { - stored_led_mode = led_mode; - } - led_mode = LED_SPECIAL_MODE_NUMLOCK; - } - if (current_keymap != NUMPAD_KEYMAP && - led_mode == LED_SPECIAL_MODE_NUMLOCK - ) { - led_mode = stored_led_mode; - } - +void +LEDControl_::next_mode (void) { + mode++; - if (led_mode != last_led_mode) { - initialize_led_mode(led_mode); - } - switch (led_mode) { + if (mode >= LED_MAX_MODES) { + mode = 0; + return; + } - case LED_MODE_OFF: - break; - case LED_MODE_BREATHE: - effect_breathe_update(); - break; - case LED_MODE_RAINBOW: - effect_rainbow_update(); - break; - case LED_MODE_RAINBOW_WAVE: - effect_rainbow_wave_update(); - break; - case LED_MODE_CHASE: - effect_chase_update(); - break; - case LED_SPECIAL_MODE_NUMLOCK: - effect_numlock_update(); - break; - default: - break; - } + if (modes[mode]) + return; - led_sync(); - last_led_mode = led_mode; + mode = 0; } +void +LEDControl_::setup (void) { + set_all_leds_to ({0, 0, 0}); - -void LEDControl_::effect_numlock_update() { - for (uint8_t i = 0; i < 44; i++) { - led_set_crgb_at(i, led_off); - } - for (uint8_t i = 44; i < LED_COUNT; i++) { - led_set_crgb_at(i, led_red); - } - led_compute_breath(); - led_set_crgb_at(60, led_breathe); // make numlock breathe + for (uint8_t i = 0; i < LED_MAX_MODES; i++) { + if (modes[i]) + (modes[i]->setup) (); + } } +void +LEDControl_::update (void) { + if (previousMode != mode) { + set_all_leds_to ({0, 0, 0}); + (modes[mode]->init) (); + } -void LEDControl_::led_compute_breath() { - // algorithm from http://sean.voisen.org/blog/2011/10/breathing-led-with-arduino/ - breathe_brightness = (exp(sin(millis()/2000.0*PI)) - 0.36787944)*108.0; - // change the brightness for next time through the loop: - //breathe_brightness = breathe_brightness + breathe_fadeAmount; + (modes[mode]->update) (); - // reverse the direction of the fading at the ends of the fade: - if (breathe_brightness == 0 || breathe_brightness == 150) { - breathe_fadeAmount = -breathe_fadeAmount ; - } + led_sync (); - - hsv_to_rgb(&led_breathe,200, 255, breathe_brightness); + previousMode = mode; } -void LEDControl_::effect_breathe_update() { - led_compute_breath(); - set_all_leds_to(led_breathe); +void +LEDControl_::set_mode (uint8_t mode) { + if (mode < LED_MAX_MODES) + this->mode = mode; } -void LEDControl_::effect_chase_update() { - if (current_chase_counter++ < chase_threshold) { - return; - } - current_chase_counter = 0; - led_set_crgb_at(pos - (chase_sign* chase_pixels), led_off); - led_set_crgb_at(pos, led_off); - - pos += chase_sign; - if (pos >= LED_COUNT || pos <= 0) { - chase_sign = -chase_sign; - } - led_set_crgb_at(pos, led_blue); - led_set_crgb_at(pos - (chase_sign * chase_pixels), led_red); +uint8_t +LEDControl_::get_mode (void) { + return mode; } -void LEDControl_::effect_rainbow_update() { - if (rainbow_current_ticks++ < rainbow_ticks) { - return; - } else { - rainbow_current_ticks = 0; - } - hsv_to_rgb( &rainbow, rainbow_hue, rainbow_saturation, rainbow_value); - rainbow_hue += rainbow_steps; - if (rainbow_hue >= 255) { - rainbow_hue -= 255; - } - set_all_leds_to(rainbow); -} - -void LEDControl_::effect_rainbow_wave_update() { - if (rainbow_current_ticks++ < rainbow_wave_ticks) { - return; - } else { - rainbow_current_ticks = 0; - } - - for (uint8_t i = 0; i < LED_COUNT; i++) { - uint16_t key_hue = rainbow_hue +16*(i/4); - if (key_hue >= 255) { - key_hue -= 255; - } - hsv_to_rgb(&rainbow, key_hue, rainbow_saturation, rainbow_value); - led_set_crgb_at(i,rainbow); - } - rainbow_hue += rainbow_wave_steps; - if (rainbow_hue >= 255) { - rainbow_hue -= 255; - } -} - -void LEDControl_::boot_animation() { - set_all_leds_to(led_off); - - type_letter(LED_K); - type_letter(LED_E); - type_letter(LED_Y); - type_letter(LED_B); - type_letter(LED_O); - type_letter(LED_A); - type_letter(LED_R); - type_letter(LED_D); - type_letter(LED_I); - type_letter(LED_O); - type_letter(LED_SPACE); - type_letter(LED_0); - type_letter(LED_PERIOD); - type_letter(LED_9); - led_mode = LED_MODE_RAINBOW; - +int8_t +LEDControl_::mode_add (LEDMode *mode) { + for (int i = 0; i < LED_MAX_MODES; i++) { + if (modes[i]) + continue; + modes[i] = mode; + return i; + } + return -1; } -void LEDControl_::type_letter(uint8_t letter) { - led_set_crgb_at(letter,led_red); - led_sync(); - delay(250); - led_set_crgb_at(letter,led_off); - led_sync(); - delay(10); - +void +LEDControl_::set_all_leds_to(uint8_t r, uint8_t g, uint8_t b) { + cRGB color; + color.r=r; + color.g=g; + color.b=b; + set_all_leds_to(color); } - -// From http://web.mit.edu/storborg/Public/hsvtorgb.c - talk to Scott about licensing -void LEDControl_::hsv_to_rgb(cRGB *cRGB, uint16_t h, uint16_t s, uint16_t v) { - /* HSV to RGB conversion function with only integer - * math */ - uint16_t region, fpart, p, q, t; - - if(s == 0) { - /* color is grayscale */ - cRGB->r = cRGB->g = cRGB->b = v; - return; - } - - /* make hue 0-5 */ - region = (h *6) >> 8; - /* find remainder part, make it from 0-255 */ - fpart = (h*6) - (region <<8); - - /* calculate temp vars, doing integer multiplication */ - p = (v * (255 - s)) >> 8; - q = (v * (255 - ((s * fpart) >> 8))) >> 8; - t = (v * (255 - ((s * (255 - fpart)) >> 8))) >> 8; - - /* assign temp vars based on color cone region */ - switch(region) { - case 0: - cRGB->r = v; - cRGB->g = t; - cRGB->b = p; - break; - case 1: - cRGB->r = q; - cRGB->g = v; - cRGB->b = p; - break; - case 2: - cRGB->r = p; - cRGB->g = v; - cRGB->b = t; - break; - case 3: - cRGB->r = p; - cRGB->g = q; - cRGB->b = v; - break; - case 4: - cRGB->r = t; - cRGB->g = p; - cRGB->b = v; - break; - default: - cRGB->r = v; - cRGB->g = p; - cRGB->b = q; - break; - } - - return; +void +LEDControl_::set_all_leds_to(cRGB color) { + for (uint8_t i = 0; i < LED_COUNT; i++) { + led_set_crgb_at(i, color); + } } - - LEDControl_ LEDControl; diff --git a/src/LEDControl.h b/src/LEDControl.h index bea7be8d..c18cc045 100644 --- a/src/LEDControl.h +++ b/src/LEDControl.h @@ -3,93 +3,32 @@ #include #include "KeyboardConfig.h" +#define LED_MAX_MODES 24 -#define LED_MODES 12 -#define LED_MODE_OFF 0 - -#define LED_MODE_RED 1 -#define LED_MODE_ORANGE 2 -#define LED_MODE_YELLOW 3 -#define LED_MODE_GREEN 4 -#define LED_MODE_BLUE 5 -#define LED_MODE_INDIGO 6 -#define LED_MODE_VIOLET 7 - - -#define LED_MODE_BREATHE 8 -#define LED_MODE_RAINBOW 9 -#define LED_MODE_RAINBOW_WAVE 10 -#define LED_MODE_CHASE 11 - - - - -#define LED_SPECIAL_MODE_NUMLOCK 100 - +class LEDMode { + public: + virtual void setup (void) {}; + virtual void init (void) {}; + virtual void update (void) {}; +}; class LEDControl_ { public: LEDControl_(void); - void next_mode(); - void boot_animation(); - void update(uint8_t current_keymap); - void type_letter(uint8_t letter); + void next_mode(void); + void setup(void); + void update(void); void set_mode(uint8_t mode); - void set_all_leds_to(uint8_t r, uint8_t g, uint8_t b); - void effect_rainbow_update(); + uint8_t get_mode(); - private: - uint8_t led_mode = 0; - uint8_t last_led_mode = 0; - uint8_t stored_led_mode = 0; - uint8_t pos = 0; - void hsv_to_rgb(cRGB *cRGB, uint16_t h, uint16_t s, uint16_t v); + int8_t mode_add (LEDMode *mode); - cRGB led_off; - cRGB led_steady; - cRGB led_blue; - cRGB led_dark_blue; - cRGB led_red; - cRGB led_dark_red; - cRGB led_breathe; - cRGB rainbow; - - uint16_t rainbow_hue = 0; //stores 0 to 614 - - static const uint8_t rainbow_steps = 1; //number of hues we skip in a 360 range per update - static const uint8_t rainbow_wave_steps=1; //number of hues we skip in a 360 range per update - - static const byte rainbow_saturation = 255; - static const byte rainbow_value = 50; - - static const long rainbow_wave_ticks = 10; //delays between update - static const long rainbow_ticks = 10; //delays between update - long rainbow_current_ticks=0; - - uint8_t breathe_brightness = 0; // how bright the LED is - int8_t breathe_fadeAmount=1; // how many points to fade the LED by (can be negative) - int8_t chase_sign =1; //negative values when it's going backwar - uint8_t chase_pixels=5; - uint8_t current_chase_counter = 0; - static const uint8_t chase_threshold = 20; -// End RGB stuff - void led_compute_breath(); - void effect_breathe_init(); - void effect_rainbow_init(); - void effect_chase_init(); - void effect_steady_init(); - void effect_heatmap_init(); - - void effect_breathe_update(); - void effect_rainbow_wave_update(); - void effect_chase_update(); - void effect_steady_update(); - void effect_heatmap_update(); - void effect_numlock_update(); + void set_all_leds_to(uint8_t r, uint8_t g, uint8_t b); void set_all_leds_to(cRGB color); - void initialize_led_mode(uint8_t mode); + + private: + LEDMode *modes[LED_MAX_MODES]; + uint8_t previousMode, mode; }; extern LEDControl_ LEDControl; - -extern byte NUMPAD_KEYMAP; diff --git a/src/LEDUtils.cpp b/src/LEDUtils.cpp new file mode 100644 index 00000000..458c8705 --- /dev/null +++ b/src/LEDUtils.cpp @@ -0,0 +1,78 @@ +#include "LEDUtils.h" + +cRGB +breath_compute (BreathState *state) { + // algorithm from http://sean.voisen.org/blog/2011/10/breathing-led-with-arduino/ + state->brightness = (exp(sin(millis()/2000.0*PI)) - 0.36787944)*108.0; + // change the brightness for next time through the loop: + //state->brightness = state->brightness + state->fadeAmount; + + // reverse the direction of the fading at the ends of the fade: + if (state->brightness == 0 || state->brightness == 150) { + state->fadeAmount = -state->fadeAmount ; + } + + return hsv_to_rgb(200, 255, state->brightness); +} + +// From http://web.mit.edu/storborg/Public/hsvtorgb.c - talk to Scott about licensing +cRGB +hsv_to_rgb(uint16_t h, uint16_t s, uint16_t v) { + cRGB color; + + /* HSV to RGB conversion function with only integer + * math */ + uint16_t region, fpart, p, q, t; + + if(s == 0) { + /* color is grayscale */ + color.r = color.g = color.b = v; + return color; + } + + /* make hue 0-5 */ + region = (h *6) >> 8; + /* find remainder part, make it from 0-255 */ + fpart = (h*6) - (region <<8); + + /* calculate temp vars, doing integer multiplication */ + p = (v * (255 - s)) >> 8; + q = (v * (255 - ((s * fpart) >> 8))) >> 8; + t = (v * (255 - ((s * (255 - fpart)) >> 8))) >> 8; + + /* assign temp vars based on color cone region */ + switch(region) { + case 0: + color.r = v; + color.g = t; + color.b = p; + break; + case 1: + color.r = q; + color.g = v; + color.b = p; + break; + case 2: + color.r = p; + color.g = v; + color.b = t; + break; + case 3: + color.r = p; + color.g = q; + color.b = v; + break; + case 4: + color.r = t; + color.g = p; + color.b = v; + break; + default: + color.r = v; + color.g = p; + color.b = q; + break; + } + + return color; +} diff --git a/src/LEDUtils.h b/src/LEDUtils.h new file mode 100644 index 00000000..184388f6 --- /dev/null +++ b/src/LEDUtils.h @@ -0,0 +1,11 @@ +#pragma once + +#include "KeyboardConfig.h" + +typedef struct BreathState { + uint8_t brightness = 0; // how bright the LED is + int8_t fadeAmount = 1; // how many points to fade the LED by (can be negative) +}; + +cRGB breath_compute (BreathState *state); +cRGB hsv_to_rgb(uint16_t h, uint16_t s, uint16_t v); diff --git a/src/TestMode.cpp b/src/TestMode.cpp index 4edc0239..1de2c6c1 100644 --- a/src/TestMode.cpp +++ b/src/TestMode.cpp @@ -1,5 +1,8 @@ #include "KeyboardioFirmware.h" #include "TestMode.h" +#include "LED-RainbowEffect.h" + +static LEDRainbowEffect testRainbowEffect; TestMode_::TestMode_(void) { } @@ -39,7 +42,7 @@ void TestMode_::TestLEDs(void) { delay(1000); // rainbow for 10 seconds for(auto i=0; i<10000; i++ ) { - LEDControl.effect_rainbow_update(); + testRainbowEffect.update(); led_sync(); delay(1); }