diff --git a/include/config.h b/include/config.h index d8267b5..6265259 100644 --- a/include/config.h +++ b/include/config.h @@ -13,7 +13,11 @@ // Examples, assuming EDGES_PER_PART == 3: // Example: Nodes arranged in a circle: {1, 2, 2, 2, 2} // Example: Nodes arranged in a line: {1, 2, 1, 2, 1, 2} -#define NODE_COUNT 3 -#define LAYOUT {2, 1} +#define NODE_COUNT 5 +#define LAYOUT {2, 1, 1, 2} -#define LED_COUNT NODE_COUNT * CORNERS_PER_PART * LEDS_PER_CORNER \ No newline at end of file +#define LED_COUNT NODE_COUNT * CORNERS_PER_PART * LEDS_PER_CORNER + +#define SPEEDUP 1 + +//#define TEST_MODE \ No newline at end of file diff --git a/include/corner.h b/include/corner.h index 4fc9c80..a4a4efc 100644 --- a/include/corner.h +++ b/include/corner.h @@ -1,5 +1,5 @@ #pragma once -#include +#include "my_fastled.h" #include #include #include "edge.h" @@ -18,12 +18,18 @@ class Corner { bool effect_running = false; uint8_t color_blend_state = 255; uint16_t effect_id; - bool loop(); + uint8_t effect_speed; + //bool loop(); void draw(); - void blend_to(CRGB color, uint16_t effect_id=0); + void blend_to(CRGB color, uint16_t effect_id=0, uint8_t effect_speed=0); void add_led(uint16_t led_id); void merge_leds(Corner* c); + void step(); + void infect(uint8_t short_level, uint8_t long_level); + bool is_finished(); + void set_color(CRGB color); + bool reached_level(uint8_t level); private: - void infect(std::vector* neighbours); + void _infect(std::vector* neighbours); }; \ No newline at end of file diff --git a/include/my_fastled.h b/include/my_fastled.h new file mode 100644 index 0000000..915ca7a --- /dev/null +++ b/include/my_fastled.h @@ -0,0 +1,4 @@ +#pragma once + +#define FASTLED_INTERNAL +#include \ No newline at end of file diff --git a/include/node.h b/include/node.h index 047f7cb..269a6cb 100644 --- a/include/node.h +++ b/include/node.h @@ -13,4 +13,10 @@ class Node { Corner* _corners[CORNERS_PER_PART]; Node(uint16_t number); Node* create_neighbour(uint8_t edge); + + void blend_to(CRGB color, uint16_t effect_id=0, uint8_t effect_speed=0); + void set_color(CRGB color); + void infect(uint8_t level); + void step(); + void draw(); }; \ No newline at end of file diff --git a/include/prototypes.h b/include/prototypes.h index 675dd1f..c8ce41a 100644 --- a/include/prototypes.h +++ b/include/prototypes.h @@ -1,5 +1,5 @@ #pragma once -#include +#include "my_fastled.h" #include #include #include "config.h" @@ -8,8 +8,13 @@ #include "corner.h" -extern std::list nodes; +extern std::vector nodes; extern std::list edges; extern std::vector corners; -extern CRGB leds[LED_COUNT]; \ No newline at end of file +extern CRGB leds[LED_COUNT]; + +enum AnimationMode { + AM_CORNERS, + AM_NODES +}; \ No newline at end of file diff --git a/include/tools.h b/include/tools.h index b2d6d3b..d0b247d 100644 --- a/include/tools.h +++ b/include/tools.h @@ -1,5 +1,5 @@ #pragma once -#include +#include "my_fastled.h" #define LOG(...) Serial.printf(__VA_ARGS__) #define LOGln(...) Serial.printf(__VA_ARGS__); Serial.println() diff --git a/src/corner.cpp b/src/corner.cpp index ae45e1c..337fbe7 100644 --- a/src/corner.cpp +++ b/src/corner.cpp @@ -12,59 +12,66 @@ void Corner::draw() { } } -void Corner::infect(std::vector* neighbours) { +void Corner::_infect(std::vector* neighbours) { for(Corner* c : *neighbours) { if (c==nullptr) continue; - c->blend_to(this->target_color, this->effect_id); + c->blend_to(this->target_color, this->effect_id, effect_speed); } } -bool Corner::loop() { +void Corner::step() { if (this->color_blend_state < 255) { this->color = blend(this->source_color, this->target_color, color_blend_state); - color_blend_state++; + this->color_blend_state = (this->color_blend_state + effect_speed > 255) ? 255 : this->color_blend_state + effect_speed; + if (this->color_blend_state==255) { + this->color = this->target_color; + } + } +} - if (color_blend_state == 200) { +void Corner::infect(uint8_t infect_short_level, uint8_t infect_long_level) { + if (reached_level(infect_short_level)) { + _infect(&_short_neighbours); + } + if (reached_level(infect_long_level)) { + _infect(&_long_neighbours); + } +} + +bool Corner::reached_level(uint8_t level) { + uint8_t old_cbs = color_blend_state >= effect_speed ? color_blend_state - effect_speed : 0; + return (old_cbs < level && color_blend_state >= level); +} + +/*bool Corner::loop() { + if (this->color_blend_state < 255) { + this->color = blend(this->source_color, this->target_color, color_blend_state); + if (255 - color_blend_state >= effect_speed) { + color_blend_state += effect_speed; + } else { + color_blend_state = 255; + } + + if (color_blend_state >= 200 && color_blend_state-effect_speed<200) { infect(&_long_neighbours); } - if (color_blend_state==75) { + if (color_blend_state>=75 && color_blend_state-effect_speed<75) { infect(&_short_neighbours); } if (color_blend_state==255) { this->color = this->target_color; } - /* LOGln("I am %p and have %d long neighbours:", this, _long_neighbours.size()); - for(Corner* c1 : _long_neighbours) { - if (c1==nullptr) continue; - c1->blend_to(this->target_color, this->effect_id); - - LOGln("c1: cbs:%d, target_color.r:%d", c1->color_blend_state, c1->target_color.r); - } - LOGln("long neighbours done."); - //LOGln("Address of my short neighbours: %p", &_short_neighbours); - //delay(10); - LOGln("I am %p and have %d short neighbours:", this, _short_neighbours.size()); - for(Corner* c2 : _short_neighbours) { - if (c2==nullptr) continue; - LOGln("c2: %p", c2); - c2->blend_to(this->target_color, this->effect_id); - - LOGln("c2: cbs:%d, target_color.r:%d", c2->color_blend_state, c2->target_color.r); - } - LOGln("short neighbours done."); - - }*/ } this->draw(); return color_blend_state < 255; -} +}*/ -void Corner::blend_to(CRGB target, uint16_t eid) { - LOGln("blendTo called. Corner: %p, target: %d,%d,%d, eid: %d, 'old' effect_id: %d", this, target.r, target.g, target.b, eid, effect_id); +void Corner::blend_to(CRGB target, uint16_t eid, uint8_t effect_speed) { + LOGln("blendTo called. Corner: %p, target: %d,%d,%d, eid: %d, 'old' effect_id: %d, speed: %d", this, target.r, target.g, target.b, eid, effect_id, effect_speed); if (eid==0) { this->effect_id = random16(); LOGln("Set effect_id to %d", this->effect_id); @@ -75,6 +82,11 @@ void Corner::blend_to(CRGB target, uint16_t eid) { } this->effect_id = eid; } + + if (effect_speed==0) { + effect_speed = random8(3) + 1; + } + this->effect_speed = effect_speed; this->source_color = this->color; this->target_color = target; @@ -89,4 +101,13 @@ void Corner::merge_leds(Corner* c) { for(uint16_t led : c->_leds) { _leds.push_back(led); } +} + +bool Corner::is_finished() { + return color_blend_state < 255; +} + +void Corner::set_color(CRGB color) { + this->color = color; + this->color_blend_state = 255; } \ No newline at end of file diff --git a/src/main.cpp b/src/main.cpp index b5c8c70..2271903 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,5 +1,6 @@ #include -#include +#include +#include "my_fastled.h" #include "config.h" #include "tools.h" #include "node.h" @@ -7,12 +8,18 @@ #include "corner.h" #include "prototypes.h" -std::list nodes; +std::vector nodes; std::list edges; std::vector corners; CRGB leds[LED_COUNT]; +AnimationMode mode = AM_CORNERS; + +#ifdef TEST_MODE + uint8_t base_hue = 0; +#endif + bool looping; void setup_layout() { @@ -33,12 +40,10 @@ void setup_layout() { edges.push_back(edge); } } - /*for(Corner* corner: node->corners) { - auto c = std::find(corners.begin(), corners.end(), corner); - if (c == corners.end()) { - corners.push_back(corner); - } - }*/ + LOGln("Node %p:", node); + for(Node* n : node->neighbours) { + LOGln(" %p", n); + } } for(Corner* corner: corners) { @@ -64,35 +69,80 @@ void setup_fastled() { FastLED.addLeds(leds, LEDS_PER_CORNER * CORNERS_PER_PART * NODE_COUNT).setCorrection(TypicalLEDStrip); LOGln("LEDs: %3d", LED_COUNT); FastLED.setBrightness(255); + FastLED.setDither(DISABLE_DITHER); set_all_leds(CRGB::Black); } +void setup_wifi() { + LOGln("Starting WiFi scan for RNG initialization..."); + WiFi.mode(WIFI_STA); + WiFi.disconnect(); + uint16_t seed = 0; + int n = WiFi.scanNetworks(); + LOGln("%d WiFi networks found", n); + for(int i=0; iloop() || looping; + #ifdef TEST_MODE + EVERY_N_MILLISECONDS(20) { + int i=0; + for(Node* node : nodes) { + CHSV color(base_hue + 150*i, 255, 255); + for(int j=0; jblend_to(CHSV(random8(), 255, 255)); - }*/ - if (random8()==42) { - corners[random16(corners.size())]->blend_to(CHSV(random8(), 255, 255)); + if (mode == AM_CORNERS) { + for(Corner* corner: corners) { + corner->step(); + corner->infect(75, 200); + looping |= !corner->is_finished(); + corner->draw(); + } + + if (random8(128)==0) { + corners[random16(corners.size())]->blend_to(CHSV(random8(), 255, 255)); + } + } else if (mode == AM_NODES) { + for(Node* node : nodes) { + node->step(); + node->infect(128); + node->draw(); + } + + if (random8(128)==0) { + nodes[random8(nodes.size())]->blend_to(CHSV(random8(), 255, 255)); + } + } } - } + #endif + + FastLED.show(); } \ No newline at end of file diff --git a/src/node.cpp b/src/node.cpp index 03f1969..7e703a1 100644 --- a/src/node.cpp +++ b/src/node.cpp @@ -1,5 +1,6 @@ #include "node.h" #include "prototypes.h" +#include "tools.h" Node::Node(uint16_t number) { _number = number; @@ -53,4 +54,40 @@ Node* Node::create_neighbour(uint8_t edge) { node->corners[CORNERS_PER_PART-1] = c; */ return node; +} + +void Node::blend_to(CRGB color, uint16_t effect_id, uint8_t effect_speed) { + LOGln("Node::blend_to called. this:%p", this); + if (effect_speed == 0) effect_speed = random8(2)+1; + if (effect_id == 0) effect_id = random16(); + for(Corner* corner : this->_corners) { + corner->blend_to(color, effect_id, effect_speed); + } +} + +void Node::step() { + for (Corner* corner : this->_corners) { + corner->step(); + } +} + +void Node::draw() { + for (Corner* corner : this->_corners) { + corner->draw(); + } +} + +void Node::set_color(CRGB color) { + for(Corner* corner : this->_corners) { + corner->set_color(color); + } +} + +void Node::infect(uint8_t level) { + if (this->_corners[0]->reached_level(level)) { + for (Node* neighbour : neighbours) { + if (neighbour == nullptr) continue; + neighbour->blend_to(_corners[0]->target_color, _corners[0]->effect_id, _corners[0]->effect_speed); + } + } } \ No newline at end of file