Move the LED stuff into a plugin

Moves the LED control code, along with the built-in effects into the
Keyboardio-LEDControl plugin.

Signed-off-by: Gergely Nagy <algernon@madhouse-project.org>
pull/90/head
Gergely Nagy 8 years ago
parent 867f9507ed
commit eaf3991f38

@ -24,10 +24,10 @@
const Key keymaps[][ROWS][COLS] PROGMEM = {
[0] = KEYMAP_STACKED
(
Key_LEDEffectNext, Key_1, Key_2, Key_3, Key_4, Key_5, Key_LEDEffectNext,
Key_Backtick, Key_Q, Key_W, Key_E, Key_R, Key_T, Key_Tab,
Key_PageUp, Key_A, Key_S, Key_D, Key_F, Key_G,
Key_PageDn, Key_Z, Key_X, Key_C, Key_V, Key_B, Key_Esc,
Key_NoKey, Key_1, Key_2, Key_3, Key_4, Key_5, Key_NoKey,
Key_Backtick, Key_Q, Key_W, Key_E, Key_R, Key_T, Key_Tab,
Key_PageUp, Key_A, Key_S, Key_D, Key_F, Key_G,
Key_PageDn, Key_Z, Key_X, Key_C, Key_V, Key_B, Key_Esc,
Key_LCtrl, Key_Backspace, Key_LGUI, Key_LShift,
M(M_APPSWITCH),

@ -6,6 +6,7 @@
#include "Keyboardio-MouseKeys.h"
#include "Keyboardio-Macros.h"
#include "Keyboardio-LEDControl.h"
#include "KeyboardioFirmware.h"
#include "generated/keymaps.h"
@ -50,7 +51,7 @@ const macro_t *macroAction(uint8_t macroIndex, uint8_t keyState) {
void setup() {
Keyboardio.setup(KEYMAP_SIZE);
Keyboardio.use(&LEDOff,
Keyboardio.use(&LEDControl, &LEDOff,
&solidRed, &solidOrange, &solidYellow, &solidGreen, &solidBlue, &solidIndigo, &solidViolet,
&LEDBreatheEffect, &LEDRainbowEffect, &LEDChaseEffect, &numLockEffect,

@ -13,40 +13,40 @@ TestMode_::TestMode_(void) {
void TestMode_::TestLEDs(void) {
// make all LEDs dim red
LEDControl.set_all_leds_to(50,0,0);
led_sync();
LEDControl.led_sync();
delay(LED_TEST_DELAY);
// make all LEDs dim blue
LEDControl.set_all_leds_to(0,50,0);
led_sync();
LEDControl.led_sync();
delay(LED_TEST_DELAY);
// make all LEDs dim green
LEDControl.set_all_leds_to(0,0,50);
led_sync();
LEDControl.led_sync();
delay(LED_TEST_DELAY);
// make all LEDs dim white
LEDControl.set_all_leds_to(50,50,50);
led_sync();
LEDControl.led_sync();
delay(LED_TEST_DELAY);
// make all the LEDs bright red
LEDControl.set_all_leds_to(200,0,0);
led_sync();
LEDControl.led_sync();
delay(LED_TEST_DELAY);
// make all the LEDs bright green
LEDControl.set_all_leds_to(0,200,0);
led_sync();
LEDControl.led_sync();
delay(LED_TEST_DELAY);
// make all the LEDs bright blue
LEDControl.set_all_leds_to(0,0,200);
led_sync();
LEDControl.led_sync();
delay(LED_TEST_DELAY);
// make all the LEDs bright white (1.6A)
LEDControl.set_all_leds_to(160,160,160);
led_sync();
LEDControl.led_sync();
delay(LED_TEST_DELAY);
// rainbow for 10 seconds
for(auto i=0; i<1000; i++ ) {
LEDRainbowEffect.update();
led_sync();
LEDControl.led_sync();
}
// set all the keys to red
LEDControl.set_all_leds_to(50,0,0);
@ -94,7 +94,7 @@ void TestMode_::TestMatrix () {
}
}
}
KeyboardHardware.led_sync();
LEDControl.led_sync();
}
}

@ -1,40 +0,0 @@
#include "BootAnimation.h"
#include "KeyboardConfig.h"
#include "EEPROM.h"
#define EEPROM_BOOT_ANIMATION_LOCATION 1
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);
}
void
bootAnimation (void) {
if (EEPROM.read (EEPROM_BOOT_ANIMATION_LOCATION))
return;
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);
EEPROM.update (EEPROM_BOOT_ANIMATION_LOCATION, 1);
}

@ -1,3 +0,0 @@
#pragma once
void bootAnimation(void);

@ -1,17 +1,3 @@
#include "KeyboardConfig.h"
HARDWARE_IMPLEMENTATION KeyboardHardware;
// These global proxy functions are a cheap hack to avoid
void led_set_crgb_at(uint8_t i, cRGB crgb) {
KeyboardHardware.led_set_crgb_at(i,crgb);
}
void led_set_crgb_at(byte row, byte col, cRGB color) {
KeyboardHardware.led_set_crgb_at(row,col,color);
}
cRGB led_get_crgb_at(uint8_t i) {
return KeyboardHardware.led_get_crgb_at(i);
}
void led_sync(void) {
KeyboardHardware.led_sync();
}

@ -3,16 +3,3 @@
#include "Model01.h"
// These global proxy functions are a cheap hack to avoid
// a circular dependency between the keyboard hardware class
// and the 'userspace' LED implementation. If my C++ were stronger, there woudl
// certainly be a better way -JV 2016-02-01
void led_set_crgb_at(uint8_t i, cRGB crgb);
void led_set_crgb_at(byte row, byte col, cRGB color);
cRGB led_get_crgb_at(uint8_t i);
void led_sync(void);

@ -12,7 +12,6 @@ Keyboardio_::setup(const byte keymap_count) {
delay(100);
Keyboard.begin();
KeyboardHardware.setup();
LEDControl.setup();
event_handler_hook_add (NULL);
loop_hook_add (NULL);
@ -25,7 +24,6 @@ custom_loop_t loopHooks[HOOK_MAX];
void
Keyboardio_::loop(void) {
KeyboardHardware.scan_matrix();
LEDControl.update();
for (byte i = 0; loopHooks[i] != NULL && i < HOOK_MAX; i++) {
custom_loop_t hook = loopHooks[i];
@ -39,8 +37,6 @@ Keyboardio_::loop(void) {
custom_loop_t hook = loopHooks[i];
(*hook)(true);
}
led_sync ();
}
void

@ -1,12 +0,0 @@
#include "LED-BreatheEffect.h"
LEDBreatheEffect_::LEDBreatheEffect_ (void) {
}
void
LEDBreatheEffect_::update (void) {
cRGB color = breath_compute();
LEDControl.set_all_leds_to (color);
}
LEDBreatheEffect_ LEDBreatheEffect;

@ -1,15 +0,0 @@
#pragma once
#include "LEDControl.h"
#include "LEDUtils.h"
class LEDBreatheEffect_ : LEDMode {
public:
LEDBreatheEffect_ (void);
virtual void update (void) final;
private:
};
extern LEDBreatheEffect_ LEDBreatheEffect;

@ -1,23 +0,0 @@
#include "LED-ChaseEffect.h"
LEDChaseEffect_::LEDChaseEffect_ (void) {
}
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});
}
LEDChaseEffect_ LEDChaseEffect;

@ -1,20 +0,0 @@
#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;
};
extern LEDChaseEffect_ LEDChaseEffect;

@ -1,55 +0,0 @@
#include "LED-Numlock.h"
#include "LEDUtils.h"
#include "layers.h"
static uint8_t numpadIndex;
static uint8_t storedLEDMode;
static uint8_t us;
LEDNumlock::LEDNumlock (uint8_t numpadIdx) {
numpadIndex = numpadIdx;
}
void
LEDNumlock::begin (void) {
us = LEDControl.mode_add (this);
loop_hook_add (this->loopHook);
}
void
LEDNumlock::setup (void) {
if (!Layer.isOn (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 ();
led_set_crgb_at (60, color);
}
void
LEDNumlock::loopHook (bool postClear) {
if (!postClear)
return;
if (Layer.isOn (numpadIndex)) {
if (storedLEDMode != us) {
storedLEDMode = LEDControl.get_mode ();
}
LEDControl.set_mode (us);
}
if (!Layer.isOn (numpadIndex) &&
LEDControl.get_mode () == us) {
LEDControl.set_mode (storedLEDMode);
}
}

@ -1,17 +0,0 @@
#pragma once
#include "LEDControl.h"
#include "LEDUtils.h"
class LEDNumlock : LEDMode {
public:
LEDNumlock (uint8_t numpadIndex);
virtual void begin (void) final;
virtual void update (void) final;
virtual void setup (void) final;
private:
static void loopHook (bool postClear);
};

@ -1,3 +0,0 @@
#include "LED-Off.h"
LEDOff_ LEDOff;

@ -1,10 +0,0 @@
#pragma once
#include "LEDControl.h"
class LEDOff_ : public LEDMode {
public:
LEDOff_ (void) { };
};
extern LEDOff_ LEDOff;

@ -1,52 +0,0 @@
#include "LED-RainbowEffect.h"
LEDRainbowEffect_::LEDRainbowEffect_ (void) {
}
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);
}
LEDRainbowEffect_ LEDRainbowEffect;
// ---------
LEDRainbowWaveEffect_::LEDRainbowWaveEffect_ (void) {
}
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;
}
}
LEDRainbowWaveEffect_ LEDRainbowWaveEffect;

@ -1,43 +0,0 @@
#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;
};
extern LEDRainbowEffect_ LEDRainbowEffect;
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;
};
extern LEDRainbowWaveEffect_ LEDRainbowWaveEffect;

@ -1,13 +0,0 @@
#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);
}

@ -1,13 +0,0 @@
#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,104 +0,0 @@
#include "LEDControl.h"
void
LEDMode::activate (void) {
LEDControl.activate (this);
}
void
LEDMode::begin(void) {
LEDControl.mode_add(this);
}
LEDControl_::LEDControl_(void) {
mode = previousMode = 0;
memset (modes, 0, LED_MAX_MODES * sizeof (modes[0]));
}
void
LEDControl_::next_mode (void) {
mode++;
if (mode >= LED_MAX_MODES) {
mode = 0;
return;
}
if (modes[mode])
return;
mode = 0;
}
void
LEDControl_::setup (void) {
set_all_leds_to ({0, 0, 0});
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});
if (modes[mode])
(modes[mode]->init) ();
}
if (modes[mode])
(modes[mode]->update) ();
previousMode = mode;
}
void
LEDControl_::set_mode (uint8_t mode_) {
if (mode_ < LED_MAX_MODES)
mode = mode_;
}
uint8_t
LEDControl_::get_mode (void) {
return 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) {
for (int i = 0; i < LED_MAX_MODES; i++) {
if (modes[i])
continue;
modes[i] = mode;
return i;
}
return -1;
}
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);
}
}
LEDControl_ LEDControl;

@ -1,39 +0,0 @@
#pragma once
#include <Arduino.h>
#include "KeyboardConfig.h"
#include "plugin.h"
#define LED_MAX_MODES 24
class LEDMode : public KeyboardioPlugin {
public:
virtual void begin (void);
virtual void setup (void) {};
virtual void init (void) {};
virtual void update (void) {};
virtual void activate (void);
};
class LEDControl_ {
public:
LEDControl_(void);
void next_mode(void);
void setup(void);
void update(void);
void set_mode(uint8_t mode);
uint8_t get_mode();
int8_t mode_add (LEDMode *mode);
void set_all_leds_to(uint8_t r, uint8_t g, uint8_t b);
void set_all_leds_to(cRGB color);
void activate (LEDMode *mode);
private:
LEDMode *modes[LED_MAX_MODES];
uint8_t previousMode, mode;
};
extern LEDControl_ LEDControl;

@ -1,86 +0,0 @@
#include "LEDUtils.h"
cRGB
breath_compute () {
// This code is adapted from FastLED lib8tion.h as of dd5d96c6b289cb6b4b891748a4aeef3ddceaf0e6
// Eventually, we should consider just using FastLED
uint8_t i = (uint16_t)millis()/12;
if( i & 0x80) {
i = 255 - i;
}
i = i << 1;
uint8_t ii = (i*i)>>8;
uint8_t iii = (ii*i)>>8;
i = (( (3 * (uint16_t)(ii)) - ( 2 * (uint16_t)(iii))) / 2) + 2;
return hsv_to_rgb(200, 255, i);
}
// 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;
}

@ -1,6 +0,0 @@
#pragma once
#include "KeyboardConfig.h"
cRGB breath_compute (void);
cRGB hsv_to_rgb(uint16_t h, uint16_t s, uint16_t v);

@ -49,11 +49,6 @@ typedef union Key_ {
#define MOMENTARY_OFFSET 42
// IS_INTERNAL key table:
#define LED_TOGGLE B00000001 // Synthetic, internal
#define KEYMAP_0 0
#define KEYMAP_1 1
#define KEYMAP_2 2
@ -266,8 +261,3 @@ typedef union Key_ {
#define Key_KeymapNext_Momentary (Key) {KEY_FLAGS | SYNTHETIC | SWITCH_TO_KEYMAP, KEYMAP_NEXT + MOMENTARY_OFFSET }
#define Key_KeymapPrevious_Momentary (Key) {KEY_FLAGS | SYNTHETIC | SWITCH_TO_KEYMAP, KEYMAP_PREVIOUS + MOMENTARY_OFFSET }
#define Key_LEDEffectNext (Key) { 0, KEY_FLAGS | SYNTHETIC | IS_INTERNAL | LED_TOGGLE }

@ -12,11 +12,7 @@ static bool handle_synthetic_key_event(Key mappedKey, uint8_t keyState) {
return true;
if (mappedKey.flags & IS_INTERNAL) {
if (mappedKey.flags & LED_TOGGLE) {
LEDControl.next_mode();
} else {
return false;
}
return false;
} else if (mappedKey.flags & IS_CONSUMER) {
ConsumerControl.press(mappedKey.keyCode);
} else if (mappedKey.flags & IS_SYSCTL) {

@ -4,7 +4,6 @@
#include "key_defs.h"
#include "keyswitch_state.h"
#include "LEDControl.h"
#include "Storage.h"
#include "keymap_metadata.h"
#include "hooks.h"

Loading…
Cancel
Save