Skip to content

Commit

Permalink
Add HardStripes (#672)
Browse files Browse the repository at this point in the history
  • Loading branch information
NoSloppy authored Jul 31, 2024
1 parent 2054e95 commit 66df399
Showing 1 changed file with 68 additions and 7 deletions.
75 changes: 68 additions & 7 deletions styles/stripes.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
#define STYLES_STRIPES_H

#include "../functions/int.h"
#include "../common/range.h"

// Usage: Stripes<WIDTH, SPEED, COLOR1, COLOR2, ... >
// or: Usage: StripesX<WIDTH_CLASS, SPEED, COLOR1, COLOR2, ... >
Expand All @@ -14,19 +15,27 @@
// WIDTH determines width of stripes
// SPEED determines movement speed

// Usage: HardStripes<WIDTH, SPEED, COLOR1, COLOR2, ... >
// or: Usage: HardStripesX<WIDTH_CLASS, SPEED, COLOR1, COLOR2, ... >
// Works like Stripes, but with no gradient between color segments..
// * Note * Regular Stripes is recommended for very slow speeds.
// Without a 1 pixel gradient smoothing the changing pixel color,
// the animation can seem a little "choppy". At faster speeds, this is not apparent.

// If you have a ring of LEDs and you want the stripes to line up,
// you'll need to set WIDTH using the following formula:
// WIDTH = 50000 * NUM_LEDS_IN_RING / (NUM_COLORS * REPETITIONS * 341)

template<class... A>
class StripesHelper {};

template<>
class StripesHelper<> {
public:
static const size_t size = 0;
void run(BladeBase* blade) {}
void get(int led, int p, SimpleColor* c) {}
void hardGet(const Range& pixel, int led, int p, uint32_t mod, SimpleColor* c) {}
};

template<class A, class... B>
Expand All @@ -47,6 +56,25 @@ class StripesHelper<A, B...> {
}
b_.get(led, p - 341, ret);
}

void hardGet(const Range& pixel, int led, int p, uint32_t mod, SimpleColor* ret) {
int segment_size = 341;
uint32_t weight = pixel.intersect_with_stripes(Range(p, p + segment_size), mod);
if (weight) {
OverDriveColor tmp = a_.getColor(led);
if (weight == pixel.size()) {
ret->c = tmp.c;
return;
} else {
weight = weight * 16384 / pixel.size();
ret->c.r = clampi32(ret->c.r + ((tmp.c.r * weight) >> 14), 0, 65535);
ret->c.g = clampi32(ret->c.g + ((tmp.c.g * weight) >> 14), 0, 65535);
ret->c.b = clampi32(ret->c.b + ((tmp.c.b * weight) >> 14), 0, 65535);
}
}
b_.hardGet(pixel, led, p + segment_size, mod, ret);
}

A a_;
StripesHelper<B...> b_;
};
Expand All @@ -62,31 +90,45 @@ class StripesBase {
public:
void run(BladeBase* base, int width, int speed) {
colors_.run(base);

uint32_t now_micros = micros();
int32_t delta_micros = now_micros - last_micros_;
last_micros_ = now_micros;

m = MOD(m + delta_micros * speed / 333, colors_.size * 341*1024);
mult_ = (50000*1024 / width);
m = MOD(m + delta_micros * speed / 333, colors_.size * 341 * 1024);
mult_ = (50000 * 1024 / width);
}
SimpleColor getColor(int led) {
// p = 0..341*len(colors)
int p = ((m + led * mult_) >> 10) % (colors_.size * 341);

SimpleColor ret;
ret.c = Color16(0,0,0);
ret.c = Color16(0, 0, 0);
colors_.get(led, p, &ret);
colors_.get(led, p + 341 * colors_.size, &ret);
return ret;
}
private:
protected:
StripesHelper<COLORS...> colors_;
uint32_t mult_;
uint32_t last_micros_;
int32_t m;
};

template<class... COLORS>
class HardStripesBase : public StripesBase<COLORS...> {
public:
SimpleColor getColor(int led) {
// p = 0..341*len(colors)
int p = ((this->m + led * this->mult_) >> 10) % (this->colors_.size * 341);

SimpleColor ret;
ret.c = Color16(0, 0, 0);
this->colors_.hardGet(Range(0, this->mult_ >> 10), led, p, this->colors_.size * 341, &ret);
return ret;
}
};

template<class WIDTH, class SPEED, class... COLORS>
class StripesX : public StripesBase<COLORS...> {
public:
Expand All @@ -102,6 +144,25 @@ class StripesX : public StripesBase<COLORS...> {
PONUA SVFWrapper<SPEED> speed_;
};

template<class WIDTH, class SPEED, class... COLORS>
class HardStripesX : public HardStripesBase<COLORS...> {
public:
void run(BladeBase* base) {
// Width cannot be zero.
static_assert(!is_same_type<WIDTH, Int<0>>::value, "HardStripes cannot have a zero WIDTH");
this->width_.run(base);
this->speed_.run(base);
HardStripesBase<COLORS...>::run(base, this->width_.calculate(base), this->speed_.calculate(base));
}
private:
PONUA SVFWrapper<WIDTH> width_;
PONUA SVFWrapper<SPEED> speed_;
};

template<int WIDTH, int SPEED, class... COLORS>
using Stripes = StripesX<Int<WIDTH>, Int<SPEED>, COLORS...>;

template<int WIDTH, int SPEED, class... COLORS>
using HardStripes = HardStripesX<Int<WIDTH>, Int<SPEED>, COLORS...>;

#endif

0 comments on commit 66df399

Please sign in to comment.