5#ifndef COMPONENT_STRIP_H
6#define COMPONENT_STRIP_H
9#ifdef LMBD_LAMP_TYPE__INDEXABLE
18#include "src/generated/hal/strip_impl.hpp"
21#include "src/system/ext/scale8.h"
22#include "src/system/ext/random8.h"
32static constexpr size_t stripNbBuffers = 3;
33static constexpr float baseCurrentConsumption = 0.4f;
34static constexpr float maxCurrentConsumption = 2.7f - baseCurrentConsumption;
35static constexpr float ampPerLed = maxCurrentConsumption / (float)LED_COUNT;
37namespace modes::hardware {
43using StripImpl_t = hal::strip::LampdaStrip<LED_COUNT, 3>;
48 using BufferTy = std::array<uint32_t, LED_COUNT>;
52 static constexpr bool useColorDithering =
true;
54 static constexpr bool useTemporalDithering =
false;
55 static constexpr uint16_t refreshFramesCount = 10;
64 for (uint16_t i = 0; i < LED_COUNT; ++i)
66 if constexpr (useTemporalDithering)
82 hasSomeChanges =
false;
85 float estimateCurrentDraw()
const
87 float estimatedCurrentDraw = 0.0;
90 const float currentPerLed = lmpd_map<float>(b, 0, 255, 0.0f, ampPerLed);
92 for (uint16_t i = 0; i < LED_COUNT; ++i)
97 const float res = max<float>(c.blue, max<float>(c.red, c.green));
103 estimatedCurrentDraw += currentPerLed;
105 return max<float>(baseCurrentConsumption, estimatedCurrentDraw);
115 void setPixelColor(uint16_t n,
COLOR c)
127 void begin() { StripImpl_t::begin(); }
138 c.color = StripImpl_t::getPixelColor(n);
149 void write_to_led_driver(
const uint8_t writeBrightness)
152 const uint8_t capedShown = shownCount % refreshFramesCount;
153 for (uint16_t i = 0; i < LED_COUNT; ++i)
155 if constexpr (useTemporalDithering)
159 StripImpl_t::setPixelColor(i, c.color);
165 StripImpl_t::setPixelColor(i, c.color);
174 brightnessAtShowTime = brightness;
175 write_to_led_driver(brightnessAtShowTime);
178 hasSomeChanges =
false;
180 auto refCount = shownCount;
181 shownCount = refCount + 1;
198 const uint16_t colorShifted = (uint16_t)colorIn << 8;
199 if (colorShifted <= brightness or brightness == 0)
202 uint8_t fullColor = (colorShifted - brightness) / brightness;
216 const uint8_t brightness,
217 const uint16_t index)
220 static constexpr std::array<uint8_t, 64> BLUE_NOISE_LUT = {
221 0, 32, 8, 40, 2, 34, 10, 42, 48, 16, 56, 24, 50, 18, 58, 26, 12, 44, 4, 36, 14, 46,
222 6, 38, 60, 28, 52, 20, 62, 30, 54, 22, 3, 35, 11, 43, 1, 33, 9, 41, 51, 19, 59, 27,
223 49, 17, 57, 25, 15, 47, 7, 39, 13, 45, 5, 37, 63, 31, 55, 23, 61, 29, 53, 21};
230 const uint16_t scaledColor = colorIn * brightness + brightness;
233 if constexpr (useColorDithering and useTemporalDithering)
235 const uint8_t allowedError = UINT8_MAX - (scaledColor & 0xFF);
236 errorIn += min<uint16_t>(allowedError, BLUE_NOISE_LUT[index % BLUE_NOISE_LUT.size()]);
240 const uint32_t fullColor = min<uint32_t>(scaledColor + errorIn, 0xFF00);
243 uint32_t finalColorRaw = fullColor >> 8;
244 const uint8_t finalError = fullColor & 0xFF;
247 if constexpr (useColorDithering and not useTemporalDithering)
249 finalColorRaw += (finalError > BLUE_NOISE_LUT[index % BLUE_NOISE_LUT.size()] ? 1 : 0);
252 const uint8_t finalColor = (finalColorRaw > 255) ? 255 : finalColorRaw;
253 return {finalColor, finalError};
265 const uint8_t brightness,
266 const uint16_t index,
270 if constexpr (not useTemporalDithering)
282 error.red = redError;
283 error.green = greenError;
284 error.blue = blueError;
288 result.green = green;
293 void setPixelColor(uint16_t n, uint8_t r, uint8_t g, uint8_t b)
303 void setPixelColor(uint16_t n, uint8_t r, uint8_t g, uint8_t b, uint8_t w)
314 void setPixelColor(uint16_t n, uint32_t c)
319 setPixelColor(n, co);
322 static uint16_t to_strip(uint16_t screenX, uint16_t screenY)
324 if (screenX > stripXCoordinates)
325 screenX = stripXCoordinates;
326 if (screenY > stripYCoordinates)
327 screenY = stripYCoordinates;
329 return lmpd_constrain<uint16_t>(screenX + screenY * stripXCoordinates, 0, LED_COUNT - 1);
332 void setPixelColorXY(uint16_t x, uint16_t y, COLOR c) { setPixelColor(LedStrip::to_strip(x, y), c); }
334 void setPixelColorXY(uint16_t x, uint16_t y, uint32_t c) { setPixelColor(LedStrip::to_strip(x, y), c); }
341 uint32_t color_wheel(uint8_t pos)
346 return ((uint32_t)(255 - pos * 3) << 16) | ((uint32_t)(0) << 8) | (pos * 3);
351 return ((uint32_t)(0) << 16) | ((uint32_t)(pos * 3) << 8) | (255 - pos * 3);
356 return ((uint32_t)(pos * 3) << 16) | ((uint32_t)(255 - pos * 3) << 8) | (0);
360 void blur(uint8_t blur_amount)
362 if (blur_amount == 0)
364 uint8_t keep = 255 - blur_amount;
365 uint8_t seep = blur_amount >> 1;
368 for (
unsigned i = 0; i < LED_COUNT; i++)
371 cur.color = getPixelColor(i);
373 COLOR part = utils::color_fade(c, seep);
374 cur = utils::color_add(utils::color_fade(c, keep), carryover,
true);
377 c.color = getPixelColor(i - 1);
378 setPixelColor(i - 1, utils::color_add(c, part,
true));
380 setPixelColor(i, cur);
385 uint32_t getPixelColor(uint16_t n)
const {
return _colors[lmpd_constrain<uint16_t>(n, 0, LED_COUNT - 1)].color; }
386 uint32_t getPixelColorXY(int16_t x, int16_t y)
const {
return getPixelColor(LedStrip::to_strip(x, y)); }
390 void addPixelColor(uint16_t n, uint32_t color,
bool fast =
false)
393 c1.color = getPixelColor(n);
397 setPixelColor(n, utils::color_add(c1, c2, fast));
400 void addPixelColorXY(uint16_t x, uint16_t y, uint32_t color,
bool fast =
false)
402 addPixelColor(LedStrip::to_strip(x, y), color, fast);
406 void signal_display() { hasSomeChanges =
true; }
408 uint32_t* get_buffer_ptr(
const uint8_t index) {
return _buffers[index].data(); }
410 void buffer_current_colors(
const uint8_t index)
412 static_assert(
sizeof(BufferTy) ==
sizeof(
_colors));
416 void fill_buffer(
const uint8_t index,
const uint32_t value)
418 memset(
_buffers[index].data(), value,
sizeof(BufferTy));
431 volatile bool hasSomeChanges;
434 volatile uint8_t brightness;
437 volatile uint8_t brightnessAtShowTime;
440 volatile uint8_t shownCount;
protected inheritence to avoid uncontroled hardware calls
Definition: strip.h:47
uint8_t getBrightness() const
Brightness is an internal flag.
Definition: strip.h:112
COLOR _colors[LED_COUNT]
store the display colors, with no brightness scaling
Definition: strip.h:422
std::array< COLOR, useTemporalDithering ? LED_COUNT :1 > _colorErrors
used for temporal dithering
Definition: strip.h:425
void setBrightness(uint8_t b)
Brightness is an internal counter.
Definition: strip.h:109
uint32_t getRawPixelColor(uint16_t n) const
Return the raw color value stored in the send buffer.
Definition: strip.h:131
BufferTy _buffers[stripNbBuffers]
buffers for computations
Definition: strip.h:428
static std::pair< uint8_t, uint8_t > get_brightness_color_and_error(const uint8_t colorIn, uint16_t errorIn, const uint8_t brightness, const uint16_t index)
Convert a color to the desired brightness level, with an error adjustment.
Definition: strip.h:214
static uint8_t restore_color_with_brightness(uint8_t colorIn, const uint8_t brightness)
Convert a color to the standard range, assuming it starts as brightness level.
Definition: strip.h:195
void begin()
Definition: strip.h:127
void show_now()
Show the current data, independant of changes.
Definition: strip.h:171
static COLOR convert_color_with_brightness(const COLOR &c, const uint8_t brightness, const uint16_t index, COLOR &error)
Convert a color to the correct brightness, with temporal dithering.
Definition: strip.h:264
This class is a lightweight port of the Adafruit_Neopixel library, with compile time buffers to have ...
Definition: strip_impl.h:30
Program scope.
Definition: control_fixed_modes.hpp:12
Implement a led strip object.
uint8_t neoPixelType
3rd arg to Adafruit_NeoPixel constructor
Definition: strip_impl.h:17
Main interface between the user and the hardware of the lamp.
Definition: lamp_type.hpp:118
Define the system hardware constants.
Use this to convert color to bytes.
Definition: utils.h:128
User defined constants, relative to specific lamp types.
Define vectors and rotation matrices, and the possibility to rotate vectors.