9#ifdef LMBD_LAMP_TYPE__INDEXABLE
17#ifndef LMBD_SIMULATION
23#include "src/system/ext/scale8.h"
24#include "src/system/ext/random8.h"
34static constexpr size_t stripNbBuffers = 3;
35static constexpr float baseCurrentConsumption = 0.4f;
36static constexpr float maxCurrentConsumption = 2.7f - baseCurrentConsumption;
37static constexpr float ampPerLed = maxCurrentConsumption / (float)LED_COUNT;
39namespace modes::hardware {
45using StripImpl_t = platform::strip::LampdaStrip<LED_COUNT, 3>;
50 using BufferTy = std::array<uint32_t, LED_COUNT>;
54 static constexpr bool useColorDithering =
true;
56 static constexpr bool useTemporalDithering =
false;
57 static constexpr uint16_t refreshFramesCount = 10;
66 for (uint16_t i = 0; i < LED_COUNT; ++i)
68 if constexpr (useTemporalDithering)
84 hasSomeChanges =
false;
87 float estimateCurrentDraw()
const
89 float estimatedCurrentDraw = 0.0;
92 const float currentPerLed = lmpd_map<float>(b, 0, 255, 0.0f, ampPerLed);
94 for (uint16_t i = 0; i < LED_COUNT; ++i)
99 const float res = max<float>(c.blue, max<float>(c.red, c.green));
105 estimatedCurrentDraw += currentPerLed;
107 return max<float>(baseCurrentConsumption, estimatedCurrentDraw);
117 void setPixelColor(uint16_t n,
COLOR c)
129 void begin() { StripImpl_t::begin(); }
140 c.color = StripImpl_t::getPixelColor(n);
151 void write_to_led_driver(
const uint8_t writeBrightness)
154 const uint8_t capedShown = shownCount % refreshFramesCount;
155 for (uint16_t i = 0; i < LED_COUNT; ++i)
157 if constexpr (useTemporalDithering)
161 StripImpl_t::setPixelColor(i, c.color);
167 StripImpl_t::setPixelColor(i, c.color);
176 brightnessAtShowTime = brightness;
177 write_to_led_driver(brightnessAtShowTime);
180 hasSomeChanges =
false;
182 auto refCount = shownCount;
183 shownCount = refCount + 1;
200 const uint16_t colorShifted = (uint16_t)colorIn << 8;
201 if (colorShifted <= brightness or brightness == 0)
204 uint8_t fullColor = (colorShifted - brightness) / brightness;
218 const uint8_t brightness,
219 const uint16_t index)
222 static constexpr std::array<uint8_t, 64> BLUE_NOISE_LUT = {
223 0, 32, 8, 40, 2, 34, 10, 42, 48, 16, 56, 24, 50, 18, 58, 26, 12, 44, 4, 36, 14, 46,
224 6, 38, 60, 28, 52, 20, 62, 30, 54, 22, 3, 35, 11, 43, 1, 33, 9, 41, 51, 19, 59, 27,
225 49, 17, 57, 25, 15, 47, 7, 39, 13, 45, 5, 37, 63, 31, 55, 23, 61, 29, 53, 21};
232 const uint16_t scaledColor = colorIn * brightness + brightness;
235 if constexpr (useColorDithering and useTemporalDithering)
237 const uint8_t allowedError = UINT8_MAX - (scaledColor & 0xFF);
238 errorIn += min<uint16_t>(allowedError, BLUE_NOISE_LUT[index % BLUE_NOISE_LUT.size()]);
242 const uint32_t fullColor = min<uint32_t>(scaledColor + errorIn, 0xFF00);
245 uint32_t finalColorRaw = fullColor >> 8;
246 const uint8_t finalError = fullColor & 0xFF;
249 if constexpr (useColorDithering and not useTemporalDithering)
251 finalColorRaw += (finalError > BLUE_NOISE_LUT[index % BLUE_NOISE_LUT.size()] ? 1 : 0);
254 const uint8_t finalColor = (finalColorRaw > 255) ? 255 : finalColorRaw;
255 return {finalColor, finalError};
267 const uint8_t brightness,
268 const uint16_t index,
272 if constexpr (not useTemporalDithering)
284 error.red = redError;
285 error.green = greenError;
286 error.blue = blueError;
290 result.green = green;
295 void setPixelColor(uint16_t n, uint8_t r, uint8_t g, uint8_t b)
305 void setPixelColor(uint16_t n, uint8_t r, uint8_t g, uint8_t b, uint8_t w)
316 void setPixelColor(uint16_t n, uint32_t c)
321 setPixelColor(n, co);
324 static uint16_t to_strip(uint16_t screenX, uint16_t screenY)
326 if (screenX > stripXCoordinates)
327 screenX = stripXCoordinates;
328 if (screenY > stripYCoordinates)
329 screenY = stripYCoordinates;
331 return lmpd_constrain<uint16_t>(screenX + screenY * stripXCoordinates, 0, LED_COUNT - 1);
334 void setPixelColorXY(uint16_t x, uint16_t y, COLOR c) { setPixelColor(LedStrip::to_strip(x, y), c); }
336 void setPixelColorXY(uint16_t x, uint16_t y, uint32_t c) { setPixelColor(LedStrip::to_strip(x, y), c); }
343 uint32_t color_wheel(uint8_t pos)
348 return ((uint32_t)(255 - pos * 3) << 16) | ((uint32_t)(0) << 8) | (pos * 3);
353 return ((uint32_t)(0) << 16) | ((uint32_t)(pos * 3) << 8) | (255 - pos * 3);
358 return ((uint32_t)(pos * 3) << 16) | ((uint32_t)(255 - pos * 3) << 8) | (0);
362 void blur(uint8_t blur_amount)
364 if (blur_amount == 0)
366 uint8_t keep = 255 - blur_amount;
367 uint8_t seep = blur_amount >> 1;
370 for (
unsigned i = 0; i < LED_COUNT; i++)
373 cur.color = getPixelColor(i);
375 COLOR part = utils::color_fade(c, seep);
376 cur = utils::color_add(utils::color_fade(c, keep), carryover,
true);
379 c.color = getPixelColor(i - 1);
380 setPixelColor(i - 1, utils::color_add(c, part,
true));
382 setPixelColor(i, cur);
387 uint32_t getPixelColor(uint16_t n)
const {
return _colors[lmpd_constrain<uint16_t>(n, 0, LED_COUNT - 1)].color; }
388 uint32_t getPixelColorXY(int16_t x, int16_t y)
const {
return getPixelColor(LedStrip::to_strip(x, y)); }
392 void addPixelColor(uint16_t n, uint32_t color,
bool fast =
false)
395 c1.color = getPixelColor(n);
399 setPixelColor(n, utils::color_add(c1, c2, fast));
402 void addPixelColorXY(uint16_t x, uint16_t y, uint32_t color,
bool fast =
false)
404 addPixelColor(LedStrip::to_strip(x, y), color, fast);
408 void signal_display() { hasSomeChanges =
true; }
410 uint32_t* get_buffer_ptr(
const uint8_t index) {
return _buffers[index].data(); }
412 void buffer_current_colors(
const uint8_t index)
414 static_assert(
sizeof(BufferTy) ==
sizeof(
_colors));
418 void fill_buffer(
const uint8_t index,
const uint32_t value)
420 memset(
_buffers[index].data(), value,
sizeof(BufferTy));
433 volatile bool hasSomeChanges;
436 volatile uint8_t brightness;
439 volatile uint8_t brightnessAtShowTime;
442 volatile uint8_t shownCount;
protected inheritence to avoid uncontroled hardware calls
Definition: strip.h:49
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:197
BufferTy _buffers[stripNbBuffers]
buffers for computations
Definition: strip.h:430
void setBrightness(uint8_t b)
Brightness is an internal counter.
Definition: strip.h:111
uint8_t getBrightness() const
Brightness is an internal flag.
Definition: strip.h:114
void show_now()
Show the current data, independant of changes.
Definition: strip.h:173
std::array< COLOR, useTemporalDithering ? LED_COUNT :1 > _colorErrors
used for temporal dithering
Definition: strip.h:427
COLOR _colors[LED_COUNT]
store the display colors, with no brightness scaling
Definition: strip.h:424
static COLOR convert_color_with_brigthness(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:266
uint32_t getRawPixelColor(uint16_t n) const
Return the raw color value stored in the send buffer.
Definition: strip.h:133
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:216
void begin()
Definition: strip.h:129
Program scope.
Definition: control_fixed_modes.hpp:12
Mock of the indexable strip library.
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:114
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.