9#ifdef LMBD_LAMP_TYPE__INDEXABLE
15#ifndef LMBD_SIMULATION
21#include "src/system/ext/scale8.h"
23#include "src/system/ext/random8.h"
33static constexpr size_t stripNbBuffers = 3;
34static constexpr float baseCurrentConsumption = 0.4f;
35static constexpr float maxCurrentConsumption = 2.7f - baseCurrentConsumption;
36static constexpr float ampPerLed = maxCurrentConsumption / (float)LED_COUNT;
38namespace modes::hardware {
47 using BufferTy = std::array<uint32_t, LED_COUNT>;
51 static constexpr bool useColorDithering =
true;
53 static constexpr bool useTemporalDithering =
false;
54 static constexpr uint16_t refreshFramesCount = 10;
57 LedStrip(int16_t pin, neoPixelType type = NEO_RGB + NEO_KHZ800) :
65 for (uint16_t i = 0; i < LED_COUNT; ++i)
67 if constexpr (useTemporalDithering)
83 hasSomeChanges =
false;
86 float estimateCurrentDraw()
88 float estimatedCurrentDraw = 0.0;
91 const float currentPerLed = lmpd_map<float>(b, 0, 255, 0.0f, ampPerLed);
93 for (uint16_t i = 0; i < LED_COUNT; ++i)
98 const float res = max<float>(c.blue, max<float>(c.red, c.green));
104 estimatedCurrentDraw += currentPerLed;
106 return max<float>(baseCurrentConsumption, estimatedCurrentDraw);
116 assert(Adafruit_NeoPixel::getBrightness() == 255);
122 void setPixelColor(uint16_t n,
COLOR c)
136 Adafruit_NeoPixel::begin();
150 c.color = Adafruit_NeoPixel::getPixelColor(n);
161 void write_to_led_driver(
const uint8_t writeBrightness)
164 for (uint16_t i = 0; i < LED_COUNT; ++i)
168 i + shownCount % refreshFramesCount,
171 Adafruit_NeoPixel::setPixelColor(i, c.color);
179 brightnessAtShowTime = brightness;
180 write_to_led_driver(brightnessAtShowTime);
183 hasSomeChanges =
false;
202 const uint16_t colorShifted = (uint16_t)colorIn << 8;
203 if (colorShifted <= brightness or brightness == 0)
206 uint8_t fullColor = (colorShifted - brightness) / brightness;
220 const uint8_t brightness,
221 const uint16_t index)
224 static constexpr std::array<uint8_t, 64> BLUE_NOISE_LUT = {
225 0, 32, 8, 40, 2, 34, 10, 42, 48, 16, 56, 24, 50, 18, 58, 26, 12, 44, 4, 36, 14, 46,
226 6, 38, 60, 28, 52, 20, 62, 30, 54, 22, 3, 35, 11, 43, 1, 33, 9, 41, 51, 19, 59, 27,
227 49, 17, 57, 25, 15, 47, 7, 39, 13, 45, 5, 37, 63, 31, 55, 23, 61, 29, 53, 21};
234 const uint16_t scaledColor = colorIn * brightness + brightness;
237 if constexpr (useColorDithering and useTemporalDithering)
239 const uint8_t allowedError = UINT8_MAX - (scaledColor & 0xFF);
240 errorIn += min<uint16_t>(allowedError, BLUE_NOISE_LUT[index % BLUE_NOISE_LUT.size()]);
244 const uint32_t fullColor = min<uint32_t>(scaledColor + errorIn, 0xFF00);
247 uint32_t finalColorRaw = fullColor >> 8;
248 const uint8_t finalError = fullColor & 0xFF;
251 if constexpr (useColorDithering and not useTemporalDithering)
253 finalColorRaw += (finalError > BLUE_NOISE_LUT[index % BLUE_NOISE_LUT.size()] ? 1 : 0);
256 const uint8_t finalColor = (finalColorRaw > 255) ? 255 : finalColorRaw;
257 return {finalColor, finalError};
269 const uint8_t brightness,
270 const uint16_t index,
274 if constexpr (not useTemporalDithering)
286 error.red = redError;
287 error.green = greenError;
288 error.blue = blueError;
292 result.green = green;
297 void setPixelColor(uint16_t n, uint8_t r, uint8_t g, uint8_t b)
307 void setPixelColor(uint16_t n, uint8_t r, uint8_t g, uint8_t b, uint8_t w)
318 void setPixelColor(uint16_t n, uint32_t c)
323 setPixelColor(n, co);
326 static uint16_t to_strip(uint16_t screenX, uint16_t screenY)
328 if (screenX > stripXCoordinates)
329 screenX = stripXCoordinates;
330 if (screenY > stripYCoordinates)
331 screenY = stripYCoordinates;
333 return lmpd_constrain<uint16_t>(screenX + screenY * stripXCoordinates, 0, LED_COUNT - 1);
336 void setPixelColorXY(uint16_t x, uint16_t y, COLOR c) { setPixelColor(LedStrip::to_strip(x, y), c); }
338 void setPixelColorXY(uint16_t x, uint16_t y, uint32_t c) { setPixelColor(LedStrip::to_strip(x, y), c); }
345 uint32_t color_wheel(uint8_t pos)
350 return ((uint32_t)(255 - pos * 3) << 16) | ((uint32_t)(0) << 8) | (pos * 3);
355 return ((uint32_t)(0) << 16) | ((uint32_t)(pos * 3) << 8) | (255 - pos * 3);
360 return ((uint32_t)(pos * 3) << 16) | ((uint32_t)(255 - pos * 3) << 8) | (0);
364 void blur(uint8_t blur_amount)
366 if (blur_amount == 0)
368 uint8_t keep = 255 - blur_amount;
369 uint8_t seep = blur_amount >> 1;
372 for (
unsigned i = 0; i < LED_COUNT; i++)
375 cur.color = getPixelColor(i);
377 COLOR part = utils::color_fade(c, seep);
378 cur = utils::color_add(utils::color_fade(c, keep), carryover,
true);
381 c.color = getPixelColor(i - 1);
382 setPixelColor(i - 1, utils::color_add(c, part,
true));
384 setPixelColor(i, cur);
389 uint32_t getPixelColor(uint16_t n)
const {
return _colors[lmpd_constrain<uint16_t>(n, 0, LED_COUNT - 1)].color; }
390 uint32_t getPixelColorXY(int16_t x, int16_t y)
const {
return getPixelColor(LedStrip::to_strip(x, y)); }
394 void addPixelColor(uint16_t n, uint32_t color,
bool fast =
false)
397 c1.color = getPixelColor(n);
401 setPixelColor(n, utils::color_add(c1, c2, fast));
404 void addPixelColorXY(uint16_t x, uint16_t y, uint32_t color,
bool fast =
false)
406 addPixelColor(LedStrip::to_strip(x, y), color, fast);
410 void signal_display() { hasSomeChanges =
true; }
412 uint32_t* get_buffer_ptr(
const uint8_t index) {
return _buffers[index].data(); }
414 void buffer_current_colors(
const uint8_t index)
416 static_assert(
sizeof(BufferTy) ==
sizeof(
_colors));
420 void fill_buffer(
const uint8_t index,
const uint32_t value)
422 memset(
_buffers[index].data(), value,
sizeof(BufferTy));
435 volatile bool hasSomeChanges;
438 volatile uint8_t brightness;
441 volatile uint8_t brightnessAtShowTime;
444 volatile uint8_t shownCount;
Mock of the Adafruit NeoPixel library.
Definition: Adafruit_NeoPixel.h:27
void setBrightness(uint8_t b)
Implementation similar to Adafruit led strip.
Definition: Adafruit_NeoPixel.h:47
void show()
Definition: Adafruit_NeoPixel.h:39
protected inheritence to avoid uncontroled hardware calls
Definition: strip.h:46
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:199
BufferTy _buffers[stripNbBuffers]
buffers for computations
Definition: strip.h:432
void setBrightness(uint8_t b)
Brightness is an internal counter.
Definition: strip.h:110
uint8_t getBrightness() const
Brightness is an internal flag.
Definition: strip.h:113
void show_now()
Show the current data, independant of changes.
Definition: strip.h:176
std::array< COLOR, useTemporalDithering ? LED_COUNT :1 > _colorErrors
used for temporal dithering
Definition: strip.h:429
COLOR _colors[LED_COUNT]
store the display colors, with no brightness scaling
Definition: strip.h:426
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:268
uint32_t getRawPixelColor(uint16_t n) const
Return the raw color value stored in the send buffer.
Definition: strip.h:143
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:218
void begin()
Definition: strip.h:134
Program scope.
Definition: control_fixed_modes.hpp:12
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.