From b0f6e350d38558c7228f1bda0dc4c0c319337e75 Mon Sep 17 00:00:00 2001 From: Selene Scriven Date: Fri, 4 Aug 2017 23:34:55 -0600 Subject: [PATCH] Early working version of wavepool effect... is buggy. --- README.md | 28 +- .../LED-Wavepool.ino} | 12 +- library.properties | 8 +- ...-Stalker.h => Kaleidoscope-LED-Wavepool.h} | 6 +- src/Kaleidoscope/LED-Stalker.cpp | 140 --------- src/Kaleidoscope/LED-Wavepool.cpp | 287 ++++++++++++++++++ .../{LED-Stalker.h => LED-Wavepool.h} | 34 ++- 7 files changed, 338 insertions(+), 177 deletions(-) rename examples/{LED-Stalker/LED-Stalker.ino => LED-Wavepool/LED-Wavepool.ino} (84%) rename src/{Kaleidoscope-LED-Stalker.h => Kaleidoscope-LED-Wavepool.h} (79%) delete mode 100644 src/Kaleidoscope/LED-Stalker.cpp create mode 100644 src/Kaleidoscope/LED-Wavepool.cpp rename src/Kaleidoscope/{LED-Stalker.h => LED-Wavepool.h} (65%) diff --git a/README.md b/README.md index 6ffdec09..1c97f4d7 100644 --- a/README.md +++ b/README.md @@ -1,15 +1,15 @@ -# Kaleidoscope-LED-Stalker +# Kaleidoscope-LED-Wavepool ![status][st:experimental] [![Build Status][travis:image]][travis:status] - [travis:image]: https://travis-ci.org/keyboardio/Kaleidoscope-LED-Stalker.svg?branch=master - [travis:status]: https://travis-ci.org/keyboardio/Kaleidoscope-LED-Stalker + [travis:image]: https://travis-ci.org/keyboardio/Kaleidoscope-LED-Wavepool.svg?branch=master + [travis:status]: https://travis-ci.org/keyboardio/Kaleidoscope-LED-Wavepool [st:stable]: https://img.shields.io/badge/stable-✔-black.svg?style=flat&colorA=44cc11&colorB=494e52 [st:broken]: https://img.shields.io/badge/broken-X-black.svg?style=flat&colorA=e05d44&colorB=494e52 [st:experimental]: https://img.shields.io/badge/experimental----black.svg?style=flat&colorA=dfb317&colorB=494e52 -The `StalkerEffect` plugin provides an interesting new typing experience: the +The `WavepoolEffect` plugin provides an interesting new typing experience: the LEDs light up as you tap keys and play one of the selected effects: a haunting trail of ghostly white lights, or a blazing trail of fire. @@ -19,32 +19,32 @@ To use the plugin, one needs to include the header and select the effect. ```c++ #include -#include +#include void setup (){ - Kaleidoscope.use(&StalkerEffect); + Kaleidoscope.use(&WavepoolEffect); Kaleidoscope.setup(); - StalkerEffect.variant = STALKER(Haunt, (CRGB(0, 128, 0))); - StalkerEffect.activate(); + WavepoolEffect.variant = WAVEPOOL(Haunt, (CRGB(0, 128, 0))); + WavepoolEffect.activate(); } ``` It is recommended to place the activation of the plugin (the `USE_PLUGINS` call) as early as possible, so the plugin can catch all relevant key presses. The -configuration can happen at any time and should use the `STALKER` macro to do so. +configuration can happen at any time and should use the `WAVEPOOL` macro to do so. ## Plugin methods -The plugin provides the `StalkerEffect` object, which has the following +The plugin provides the `WavepoolEffect` object, which has the following properties: ### `.variant` > Set the effect to use with the plugin. See below for a list. > -> It is recommended to use the `STALKER` macro to declare the effect itself. +> It is recommended to use the `WAVEPOOL` macro to declare the effect itself. ### `.stepLength` @@ -55,10 +55,10 @@ properties: ## Plugin helpers -### `STALKER(effect, params)` +### `WAVEPOOL(effect, params)` > Returns an effect, to be used to assign a value the `.variant` property of the -> `StalkerEffect` object. Any arguments given to the macro are passed on +> `WavepoolEffect` object. Any arguments given to the macro are passed on > to the effect. If the effect takes no arguments, use an empty `params` list. ## Plugin effects @@ -84,4 +84,4 @@ The plugin provides the following effects: Starting from the [example][plugin:example] is the recommended way of getting started with the plugin. - [plugin:example]: https://github.com/keyboardio/Kaleidoscope-LED-Stalker/blob/master/examples/LED-Stalker/LED-Stalker.ino + [plugin:example]: https://github.com/keyboardio/Kaleidoscope-LED-Wavepool/blob/master/examples/LED-Wavepool/LED-Wavepool.ino diff --git a/examples/LED-Stalker/LED-Stalker.ino b/examples/LED-Wavepool/LED-Wavepool.ino similarity index 84% rename from examples/LED-Stalker/LED-Stalker.ino rename to examples/LED-Wavepool/LED-Wavepool.ino index bbab98f8..e257a2e9 100644 --- a/examples/LED-Stalker/LED-Stalker.ino +++ b/examples/LED-Wavepool/LED-Wavepool.ino @@ -1,6 +1,6 @@ /* -*- mode: c++ -*- - * Kaleidoscope-LED-Stalker -- Stalk keys pressed by lighting up and fading back the LED under them - * Copyright (C) 2017 Gergely Nagy + * Kaleidoscope-LED-Wavepool + * Copyright (C) 2017 Selene Scriven * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -17,7 +17,7 @@ */ #include -#include +#include #include "LED-Off.h" const Key keymaps[][ROWS][COLS] PROGMEM = { @@ -41,12 +41,12 @@ const Key keymaps[][ROWS][COLS] PROGMEM = { }; void setup() { - Kaleidoscope.use(&LEDOff, &StalkerEffect); + Kaleidoscope.use(&LEDOff, &WavepoolEffect); Kaleidoscope.setup(); - StalkerEffect.variant = STALKER(BlazingTrail); - StalkerEffect.activate(); + WavepoolEffect.variant = WAVEPOOL(BlazingTrail); + WavepoolEffect.activate(); } void loop() { diff --git a/library.properties b/library.properties index 8c121e5d..02674a0b 100644 --- a/library.properties +++ b/library.properties @@ -1,10 +1,10 @@ -name=Kaleidoscope-LED-Stalker +name=Kaleidoscope-LED-Wavepool version=0.0.0 author=Gergely Nagy maintainer=Gergely Nagy -sentence=Stalk keys pressed by lighting up and fading back the LED under them. -paragraph=Stalk keys pressed by lighting up and fading back the LED under them. +sentence=Splash water on each keypress. +paragraph=Splash water on each keypress. category=Communication -url=https://github.com/keyboardio/Kaleidoscope-LED-Stalker +url=https://github.com/keyboardio/Kaleidoscope-LED-Wavepool architectures=avr dot_a_linkage=true diff --git a/src/Kaleidoscope-LED-Stalker.h b/src/Kaleidoscope-LED-Wavepool.h similarity index 79% rename from src/Kaleidoscope-LED-Stalker.h rename to src/Kaleidoscope-LED-Wavepool.h index e9c84797..6cce33e5 100644 --- a/src/Kaleidoscope-LED-Stalker.h +++ b/src/Kaleidoscope-LED-Wavepool.h @@ -1,6 +1,6 @@ /* -*- mode: c++ -*- - * Kaleidoscope-LED-Stalker -- Stalk keys pressed by lighting up and fading back the LED under them - * Copyright (C) 2017 Gergely Nagy + * Kaleidoscope-LED-Wavepool + * Copyright (C) 2017 Selene Scriven * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -18,4 +18,4 @@ #pragma once -#include +#include diff --git a/src/Kaleidoscope/LED-Stalker.cpp b/src/Kaleidoscope/LED-Stalker.cpp deleted file mode 100644 index b3d40029..00000000 --- a/src/Kaleidoscope/LED-Stalker.cpp +++ /dev/null @@ -1,140 +0,0 @@ -/* -*- mode: c++ -*- - * Kaleidoscope-LED-Stalker -- Stalk keys pressed by lighting up and fading back the LED under them - * Copyright (C) 2017 Gergely Nagy - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include -#include - -namespace kaleidoscope { - -uint8_t StalkerEffect::map_[ROWS][COLS]; -StalkerEffect::ColorComputer *StalkerEffect::variant; -uint16_t StalkerEffect::step_length = 50; -uint32_t StalkerEffect::step_end_time_; - -StalkerEffect::StalkerEffect(void) { -} - -void StalkerEffect::begin(void) { - event_handler_hook_use(eventHandlerHook); - LEDMode::begin(); -} - -void StalkerEffect::init(void) { - memset(map_, 0, sizeof(map_)); -} - -Key StalkerEffect::eventHandlerHook(Key mapped_key, byte row, byte col, uint8_t key_state) { - if (row >= ROWS || col >= COLS) - return mapped_key; - - if (keyIsPressed(key_state)) { - map_[row][col] = 0xff; - } - - return mapped_key; -} - -void StalkerEffect::update(void) { - if (!variant) - return; - - bool time_out = millis() >= step_end_time_; - - for (byte r = 0; r < ROWS; r++) { - for (byte c = 0; c < COLS; c++) { - uint8_t step = map_[r][c]; - if (step) { - LEDControl.setCrgbAt(r, c, variant->compute(&step)); - } - - bool was_zero = (map_[r][c] == 0); - - if (time_out) { - map_[r][c] = step; - } - - if (!was_zero && !map_[r][c]) - LEDControl.setCrgbAt(r, c, (cRGB) { - 0, 0, 0 - }); - } - } - - if (time_out) - step_end_time_ = millis() + step_length; -} - -namespace stalker { - -cRGB Haunt::highlight_color_; - -// Haunt -Haunt::Haunt(const cRGB highlight_color) { - highlight_color_ = highlight_color; -} - -cRGB Haunt::compute(uint8_t *step) { - cRGB color = CRGB((uint8_t)min(*step * highlight_color_.r / 255, 255), - (uint8_t)min(*step * highlight_color_.g / 255, 255), - (uint8_t)min(*step * highlight_color_.b / 255, 255)); - - if (*step >= 0xf0) - *step -= 1; - else if (*step >= 0x40) - *step -= 16; - else if (*step >= 32) - *step -= 32; - else - *step = 0; - - return color; -} - -// BlazingTrail -BlazingTrail::BlazingTrail(void) { -} - -cRGB BlazingTrail::compute(uint8_t *step) { - cRGB color; - - if (*step >= 0xff - 30) { - color = hsvToRgb(0xff - *step, 255, 255); - } else { - color = hsvToRgb(30, 255, 255); - - color.r = min(*step * color.r / 255, 255); - color.g = min(*step * color.g / 255, 255); - } - - if (*step >= 0xf0 - 30) - *step -= 1; - else if (*step >= 0x40) - *step -= 16; - else if (*step >= 32) - *step -= 32; - else - *step = 0; - - return color; -} - -} - -} - -kaleidoscope::StalkerEffect StalkerEffect; diff --git a/src/Kaleidoscope/LED-Wavepool.cpp b/src/Kaleidoscope/LED-Wavepool.cpp new file mode 100644 index 00000000..9793c0b9 --- /dev/null +++ b/src/Kaleidoscope/LED-Wavepool.cpp @@ -0,0 +1,287 @@ +/* -*- mode: c++ -*- + * Kaleidoscope-LED-Wavepool + * Copyright (C) 2017 Selene Scriven + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include +#include + +namespace kaleidoscope { + +int8_t WavepoolEffect::map_[2][WP_WID*WP_HGT]; +uint8_t WavepoolEffect::page = 0; +WavepoolEffect::ColorComputer *WavepoolEffect::variant; +uint16_t WavepoolEffect::step_length = 50; +uint32_t WavepoolEffect::step_end_time_; +uint8_t WavepoolEffect::frames_since_event = 0; +uint8_t WavepoolEffect::positions[WP_HGT*WP_WID] = { + 0, 1, 2, 3, 4, 5, 6, 9, 10, 11, 12, 13, 14, 15, + 16, 17, 18, 19, 20, 21, 64, 64, 26, 27, 28, 29, 30, 31, + 32, 33, 34, 35, 36, 37, 22, 25, 42, 43, 44, 45, 46, 47, + 48, 49, 50, 51, 52, 53, 37, 40, 58, 59, 60, 61, 62, 63, + 64, 64, 7, 23, 39, 55, 54, 57, 56, 40, 24, 8, 64, 64, +}; +uint8_t WavepoolEffect::rc2pos[ROWS*COLS] = { + 0, 1, 2, 3, 4, 5, 6, 58, 67, 7, 8, 9, 10, 11, 12, 13, + 14, 15, 16, 17, 18, 19, 34, 59, 66, 35, 22, 23, 24, 25, 26, 27, + 28, 29, 30, 31, 32, 33, 48, 60, 65, 49, 36, 37, 38, 39, 40, 41, + 42, 43, 44, 45, 46, 47, 62,61,63,64, 50, 51, 52, 53, 54, 55, +}; + +WavepoolEffect::WavepoolEffect(void) { +} + +void WavepoolEffect::begin(void) { + event_handler_hook_use(eventHandlerHook); + LEDMode::begin(); +} + +void WavepoolEffect::init(void) { + memset(map_, 0, sizeof(map_)); +} + +Key WavepoolEffect::eventHandlerHook(Key mapped_key, byte row, byte col, uint8_t key_state) { + if (row >= ROWS || col >= COLS) + return mapped_key; + + if (keyIsPressed(key_state)) { + uint8_t offset = (row*COLS)+col; + map_[page][rc2pos[offset]] = 0x7f; + frames_since_event = 0; + } + + return mapped_key; +} + +void WavepoolEffect::update(void) { + + // limit the frame rate; one frame every 64 ms + static uint8_t prev_time = 0; + uint8_t now = (millis()>>6) % 0xff; + if (now != prev_time) { + prev_time = now; + } else { + return; + } + + // rotate the colors over time + // (side note: it's weird that this is a 16-bit int instead of 8-bit, + // but that's what the library function wants) + //static uint16_t current_hue = 0; + //current_hue ++; + //current_hue &= 0xff; + static uint8_t current_hue = 0; + current_hue ++; + + frames_since_event ++; + + // needs two pages of height map to do the calculations + int8_t *newpg = &map_[page^1][0]; + int8_t *oldpg = &map_[page][0]; + + // rain a bit while idle + if ((frames_since_event & 0x1f) == 0x1f) { + uint8_t x = rand() % WP_WID; + uint8_t y = rand() % WP_HGT; + uint8_t rainspot = (y*WP_WID) + x; + oldpg[rainspot] = 0x7f; + if (y > 0) oldpg[rainspot-WP_WID] = 0x50; + if (y < (WP_HGT-1)) oldpg[rainspot+WP_WID] = 0x50; + if (x > 0) oldpg[rainspot-1] = 0x50; + if (x < (WP_WID-1)) oldpg[rainspot+1] = 0x50; + } + + // calculate water movement + //for (uint8_t y = 1; y < WP_HGT-1; y++) { + // for (uint8_t x = 1; x < WP_WID-1; x++) { + for (uint8_t y = 0; y < WP_HGT; y++) { + for (uint8_t x = 0; x < WP_WID; x++) { + uint8_t offset = (y*WP_WID) + x; + + /* + int8_t value; + int8_t offsets[] = { -WP_WID, WP_WID, -1, 1, }; + if (y==0) offsets[0] = 0; + else if (y==WP_HGT-1) offsets[1] = 0; + if (x==0) offsets[2] = 0; + else if (x==WP_WID-1) offsets[3] = 0; + + value = ((oldpg[offset + offsets[0]] + +oldpg[offset + offsets[1]] + +oldpg[offset + offsets[2]] + +oldpg[offset + offsets[3]] + ) >> 1) + - newpg[offset]; + */ + + int16_t value; + int8_t offsets[] = { -WP_WID, WP_WID, -1, 1, + -WP_WID-1, -WP_WID+1, + WP_WID-1, WP_WID+1 + }; + if (y==0) { + offsets[0] = 0; + offsets[4] = 0; + offsets[5] = 0; + } + else if (y==WP_HGT-1) { + offsets[1] = 0; + offsets[6] = 0; + offsets[7] = 0; + } + if (x==0) { + offsets[2] = 0; + offsets[4] = 0; + offsets[6] = 0; + } + else if (x==WP_WID-1) { + offsets[3] = 0; + offsets[5] = 0; + offsets[7] = 0; + } + + value = ((oldpg[offset + offsets[0]] + +oldpg[offset + offsets[1]] + +oldpg[offset + offsets[2]] + +oldpg[offset + offsets[3]] + +oldpg[offset + offsets[4]] + +oldpg[offset + offsets[5]] + +oldpg[offset + offsets[6]] + +oldpg[offset + offsets[7]] + ) >> 2) + - newpg[offset]; + + //value = oldpg[offset]; + //if (value > 0) value --; + //oldpg[offset] = value; + //newpg[offset] = value; + newpg[offset] = value - (value >> 3); + } + } + + for (byte r = 0; r < ROWS; r++) { + for (byte c = 0; c < COLS; c++) { + uint8_t offset = (r*COLS) + c; + int8_t value = oldpg[rc2pos[offset]]; + uint8_t step; + /* + if (value < 0) step = 0; + else step = value; + step <<= 1; + */ + //step = value; + //LEDControl.setCrgbAt(r, c, CRGB(step,step,step)); + + cRGB color; + + uint16_t intensity; + if (value >= 0) intensity = value * 2; + else intensity = (-value) * 2; + color = hsvToRgb(current_hue + (uint16_t)value + (uint16_t)value, + 0xff - intensity, + (intensity*5)/3); + + LEDControl.setCrgbAt(r, c, color); + //LEDControl.setCrgbAt(r, c, variant->compute(&step)); + /* + if (offset == (now & 63)) { + LEDControl.setCrgbAt(r, c, CRGB(100,100,100)); + } else { + LEDControl.setCrgbAt(r, c, CRGB(0,0,0)); + } + */ + } + } + + page ^= 1; + +} + +namespace wavepool { + +cRGB Haunt::highlight_color_; + +// Haunt +Haunt::Haunt(const cRGB highlight_color) { + highlight_color_ = highlight_color; +} + +cRGB Haunt::compute(uint8_t *step) { + cRGB color = CRGB((uint8_t)min(*step * highlight_color_.r / 255, 255), + (uint8_t)min(*step * highlight_color_.g / 255, 255), + (uint8_t)min(*step * highlight_color_.b / 255, 255)); + + if (*step >= 0xf0) + *step -= 1; + else if (*step >= 0x40) + *step -= 16; + else if (*step >= 32) + *step -= 32; + else + *step = 0; + + return color; +} + +// BlazingTrail +BlazingTrail::BlazingTrail(void) { +} + +cRGB BlazingTrail::compute(uint8_t *step) { + cRGB color; + + if (*step >= 0xff - 30) { + color = hsvToRgb(0xff - *step, 255, 255); + } else { + color = hsvToRgb(30, 255, 255); + + color.r = min(*step * color.r / 255, 255); + color.g = min(*step * color.g / 255, 255); + } + + if (*step >= 0xf0 - 30) + *step -= 1; + else if (*step >= 0x40) + *step -= 16; + else if (*step >= 32) + *step -= 32; + else + *step = 0; + + return color; +} + +// Rainbow +Rainbow::Rainbow(void) { +} + +cRGB Rainbow::compute(uint8_t *step) { + cRGB color; + + uint8_t intensity; + if ((*step) <= 127) intensity = (*step) * 2; + else intensity = (255 - (*step)) * 2; + color = hsvToRgb(intensity, + 0xff - intensity, + intensity); + + return color; +} +} + +} + +kaleidoscope::WavepoolEffect WavepoolEffect; diff --git a/src/Kaleidoscope/LED-Stalker.h b/src/Kaleidoscope/LED-Wavepool.h similarity index 65% rename from src/Kaleidoscope/LED-Stalker.h rename to src/Kaleidoscope/LED-Wavepool.h index f4764b11..b0133ecc 100644 --- a/src/Kaleidoscope/LED-Stalker.h +++ b/src/Kaleidoscope/LED-Wavepool.h @@ -1,6 +1,6 @@ /* -*- mode: c++ -*- - * Kaleidoscope-LED-Stalker -- Stalk keys pressed by lighting up and fading back the LED under them - * Copyright (C) 2017 Gergely Nagy + * Kaleidoscope-LED-Wavepool + * Copyright (C) 2017 Selene Scriven * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -21,17 +21,20 @@ #include #include -#define STALKER(v, ...) ({static kaleidoscope::stalker::v _effect __VA_ARGS__; &_effect;}) +#define WAVEPOOL(v, ...) ({static kaleidoscope::wavepool::v _effect __VA_ARGS__; &_effect;}) + +#define WP_WID 14 +#define WP_HGT 5 namespace kaleidoscope { -class StalkerEffect : public LEDMode { +class WavepoolEffect : public LEDMode { public: class ColorComputer { public: virtual cRGB compute(uint8_t *step) = 0; }; - StalkerEffect(void); + WavepoolEffect(void); void begin(void) final; void init(void) final; @@ -41,15 +44,19 @@ class StalkerEffect : public LEDMode { static uint16_t step_length; private: + static uint8_t frames_since_event; static uint32_t step_end_time_; - static uint8_t map_[ROWS][COLS]; + static int8_t map_[2][WP_WID*WP_HGT]; + static uint8_t page; + static uint8_t positions[WP_HGT*WP_WID]; + static uint8_t rc2pos[ROWS*COLS]; static Key eventHandlerHook(Key mapped_key, byte row, byte col, uint8_t key_state); }; -namespace stalker { +namespace wavepool { -class Haunt : public StalkerEffect::ColorComputer { +class Haunt : public WavepoolEffect::ColorComputer { public: explicit Haunt(const cRGB highlight_color); Haunt(void) : Haunt(CRGB(0x40, 0x80, 0x80)) {} @@ -59,14 +66,21 @@ class Haunt : public StalkerEffect::ColorComputer { static cRGB highlight_color_; }; -class BlazingTrail : public StalkerEffect::ColorComputer { +class BlazingTrail : public WavepoolEffect::ColorComputer { public: BlazingTrail(void); cRGB compute(uint8_t *step) final; }; +class Rainbow : public WavepoolEffect::ColorComputer { + public: + Rainbow(void); + + cRGB compute(uint8_t *step) final; +}; + } } -extern kaleidoscope::StalkerEffect StalkerEffect; +extern kaleidoscope::WavepoolEffect WavepoolEffect;