Split out LED effects into smaller "plugins"

Recreate LEDControl as a class with pluggable parts, similar in vein to
the event handler and loop hooks. Except in this case, only the current
effect runs at any one time, the current one.

All existing effects were separated out into plugins, and the default
firmware example was updated too. All of them were pretty trivial, save
the special NumLock effect: that one also installs a loop hook, and
switches the LED mode if need be. Its setup function also skips to the
next effect, if the mode was selected manually.

Behaviour should be the same as before, but LED effects are now
pluggable, at the cost of some code and data size increase.

Signed-off-by: Gergely Nagy <algernon@madhouse-project.org>
pull/44/head
Gergely Nagy 8 years ago
parent 9fff7d8519
commit 4b7354a342

@ -7,6 +7,13 @@
#include "KeyboardioFirmware.h" #include "KeyboardioFirmware.h"
#include "generated/keymaps.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 primary_keymap = 0;
uint8_t temporary_keymap = 0; uint8_t temporary_keymap = 0;
@ -16,13 +23,27 @@ uint8_t temporary_keymap = 0;
const Key keymaps[][ROWS][COLS] PROGMEM = { KEYMAP_LIST }; 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() { void setup() {
Keyboardio.setup(KEYMAPS, NUMPAD_KEYMAP); Keyboardio.setup(KEYMAPS);
} }
void loop() { void loop() {
Keyboardio.loop(); Keyboardio.loop();
} }

@ -1,12 +1,10 @@
#include "KeyboardioFirmware.h" #include "KeyboardioFirmware.h"
byte NUMPAD_KEYMAP = 0;
Keyboardio_::Keyboardio_(void) { Keyboardio_::Keyboardio_(void) {
} }
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); event_handler_hook_add (handle_key_event_default);
wdt_disable(); wdt_disable();
delay(100); delay(100);
@ -14,9 +12,8 @@ Keyboardio_::setup(const byte keymap_count, const byte numpad_layer) {
Mouse.begin(); Mouse.begin();
AbsoluteMouse.begin(); AbsoluteMouse.begin();
KeyboardHardware.setup(); KeyboardHardware.setup();
LEDControl.boot_animation(); LEDControl.setup();
NUMPAD_KEYMAP = numpad_layer;
temporary_keymap = primary_keymap = Storage.load_primary_keymap(keymap_count); temporary_keymap = primary_keymap = Storage.load_primary_keymap(keymap_count);
} }
@ -30,7 +27,7 @@ Keyboardio_::loop(void) {
} }
KeyboardHardware.scan_matrix(); KeyboardHardware.scan_matrix();
LEDControl.update(temporary_keymap); LEDControl.update();
Keyboard.sendReport(); Keyboard.sendReport();
Keyboard.releaseAll(); Keyboard.releaseAll();
} }

@ -37,7 +37,7 @@ class Keyboardio_ {
public: public:
Keyboardio_(void); Keyboardio_(void);
void setup(const byte keymap_count, const byte numpad_layer); void setup(const byte keymap_count);
void loop(void); void loop(void);
}; };

@ -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);
}

@ -0,0 +1,10 @@
#pragma once
#include "LEDControl.h"
class LEDBootAnimation : LEDMode {
public:
LEDBootAnimation (void);
virtual void setup (void) final;
};

@ -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);
}

@ -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;
};

@ -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});
}

@ -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;
};

@ -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);
}
}

@ -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;
};

@ -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;
}
}

@ -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;
};

@ -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);
}

@ -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;
};

@ -1,322 +1,85 @@
#include "LEDControl.h" #include "LEDControl.h"
LEDControl_::LEDControl_(void) { LEDControl_::LEDControl_(void) {
led_off.r = 0; memset (modes, 0, LED_MAX_MODES * sizeof (modes[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;
}
} }
void LEDControl_::set_all_leds_to(uint8_t r, uint8_t g, uint8_t b) { void
cRGB color; LEDControl_::next_mode (void) {
color.r=r; mode++;
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;
}
if (led_mode != last_led_mode) { if (mode >= LED_MAX_MODES) {
initialize_led_mode(led_mode); mode = 0;
} return;
switch (led_mode) { }
case LED_MODE_OFF: if (modes[mode])
break; return;
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;
}
led_sync(); mode = 0;
last_led_mode = led_mode;
} }
void
LEDControl_::setup (void) {
set_all_leds_to ({0, 0, 0});
for (uint8_t i = 0; i < LED_MAX_MODES; i++) {
void LEDControl_::effect_numlock_update() { if (modes[i])
for (uint8_t i = 0; i < 44; i++) { (modes[i]->setup) ();
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
} }
void
LEDControl_::update (void) {
if (previousMode != mode) {
set_all_leds_to ({0, 0, 0});
(modes[mode]->init) ();
}
void LEDControl_::led_compute_breath() { (modes[mode]->update) ();
// 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;
// reverse the direction of the fading at the ends of the fade: led_sync ();
if (breathe_brightness == 0 || breathe_brightness == 150) {
breathe_fadeAmount = -breathe_fadeAmount ;
}
previousMode = mode;
hsv_to_rgb(&led_breathe,200, 255, breathe_brightness);
} }
void LEDControl_::effect_breathe_update() { void
led_compute_breath(); LEDControl_::set_mode (uint8_t mode) {
set_all_leds_to(led_breathe); if (mode < LED_MAX_MODES)
this->mode = mode;
} }
void LEDControl_::effect_chase_update() { uint8_t
if (current_chase_counter++ < chase_threshold) { LEDControl_::get_mode (void) {
return; return mode;
}
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);
} }
void LEDControl_::effect_rainbow_update() { int8_t
if (rainbow_current_ticks++ < rainbow_ticks) { LEDControl_::mode_add (LEDMode *mode) {
return; for (int i = 0; i < LED_MAX_MODES; i++) {
} else { if (modes[i])
rainbow_current_ticks = 0; continue;
}
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;
modes[i] = mode;
return i;
}
return -1;
} }
void LEDControl_::type_letter(uint8_t letter) { void
led_set_crgb_at(letter,led_red); LEDControl_::set_all_leds_to(uint8_t r, uint8_t g, uint8_t b) {
led_sync(); cRGB color;
delay(250); color.r=r;
led_set_crgb_at(letter,led_off); color.g=g;
led_sync(); color.b=b;
delay(10); set_all_leds_to(color);
} }
void
// From http://web.mit.edu/storborg/Public/hsvtorgb.c - talk to Scott about licensing LEDControl_::set_all_leds_to(cRGB color) {
void LEDControl_::hsv_to_rgb(cRGB *cRGB, uint16_t h, uint16_t s, uint16_t v) { for (uint8_t i = 0; i < LED_COUNT; i++) {
/* HSV to RGB conversion function with only integer led_set_crgb_at(i, color);
* 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;
} }
LEDControl_ LEDControl; LEDControl_ LEDControl;

@ -3,93 +3,32 @@
#include <Arduino.h> #include <Arduino.h>
#include "KeyboardConfig.h" #include "KeyboardConfig.h"
#define LED_MAX_MODES 24
#define LED_MODES 12 class LEDMode {
#define LED_MODE_OFF 0 public:
virtual void setup (void) {};
#define LED_MODE_RED 1 virtual void init (void) {};
#define LED_MODE_ORANGE 2 virtual void update (void) {};
#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 LEDControl_ { class LEDControl_ {
public: public:
LEDControl_(void); LEDControl_(void);
void next_mode(); void next_mode(void);
void boot_animation(); void setup(void);
void update(uint8_t current_keymap); void update(void);
void type_letter(uint8_t letter);
void set_mode(uint8_t mode); void set_mode(uint8_t mode);
void set_all_leds_to(uint8_t r, uint8_t g, uint8_t b); uint8_t get_mode();
void effect_rainbow_update();
private: int8_t mode_add (LEDMode *mode);
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);
cRGB led_off; void set_all_leds_to(uint8_t r, uint8_t g, uint8_t b);
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(cRGB color); 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 LEDControl_ LEDControl;
extern byte NUMPAD_KEYMAP;

@ -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;
}

@ -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);

@ -1,5 +1,8 @@
#include "KeyboardioFirmware.h" #include "KeyboardioFirmware.h"
#include "TestMode.h" #include "TestMode.h"
#include "LED-RainbowEffect.h"
static LEDRainbowEffect testRainbowEffect;
TestMode_::TestMode_(void) { TestMode_::TestMode_(void) {
} }
@ -39,7 +42,7 @@ void TestMode_::TestLEDs(void) {
delay(1000); delay(1000);
// rainbow for 10 seconds // rainbow for 10 seconds
for(auto i=0; i<10000; i++ ) { for(auto i=0; i<10000; i++ ) {
LEDControl.effect_rainbow_update(); testRainbowEffect.update();
led_sync(); led_sync();
delay(1); delay(1);
} }

Loading…
Cancel
Save