Lamp-Da 0.1
A compact lantern project
Loading...
Searching...
No Matches
lamp_type.hpp
Go to the documentation of this file.
1
5#ifndef MODES_HARDWARE_LAMP_TYPE_HPP
6#define MODES_HARDWARE_LAMP_TYPE_HPP
7
8#include <cstdint>
9#include <cstring>
10
11#include "src/compile.h"
12#include "src/user/constants.h"
13
16
17#ifdef LMBD_LAMP_TYPE__INDEXABLE
19#endif
20
21#include "src/system/hal/time.h"
22
24
26
30
32
33#include "src/system/ext/math8.h"
34
37
40
41namespace lampda::modes {
42
43struct XYTy
44{
45 uint16_t x;
46 uint16_t y;
47};
48
50static constexpr uint16_t to_strip(uint16_t, uint16_t);
52static constexpr XYTy strip_to_XY(uint16_t n);
53
55{
56 float x;
57 float y;
58 float z;
59};
60
62static constexpr HelixXYZTy strip_to_helix(int16_t n);
63
66static constexpr HelixXYZTy strip_to_helix_unconstraint(const int16_t n);
68static constexpr bool is_led_index_valid(const int16_t ledIndex);
70static constexpr bool is_lamp_coordinate_out_of_bounds(const float angle_rad, const float z);
71
75static constexpr uint16_t to_led_index(const float angle_rad, const float z);
76
80static constexpr int16_t to_led_index_no_bounds(const float angle_rad, const float z);
81
82} // namespace lampda::modes
83
86
91enum class LampTypes : uint8_t
92{
93 simple,
94 cct,
95 indexable,
96};
97
98#ifdef LMBD_LAMP_TYPE__SIMPLE
99static constexpr LampTypes _lampType = LampTypes::simple;
100#endif
101
102#ifdef LMBD_LAMP_TYPE__CCT
103static constexpr LampTypes _lampType = LampTypes::cct;
104#endif
105
106#ifdef LMBD_LAMP_TYPE__INDEXABLE
107static constexpr LampTypes _lampType = LampTypes::indexable;
108#endif
109
111static constexpr LampTypes lampType = _lampType;
112
117struct LampTy
118{
119 //
120 // state managed by manager
121 //
122
125 {
128 };
129
132
133 //
134 // private constructors
135 //
136
137#ifdef LMBD_LAMP_TYPE__INDEXABLE
138private:
139 static constexpr float _fwidth = stripXCoordinates;
140 static constexpr float _fheight = stripYCoordinates;
141 static constexpr uint16_t _width = floor(_fwidth);
142 static constexpr uint16_t _height = floor(_fheight);
143 static constexpr uint16_t _ledCount = LED_COUNT;
144 static constexpr uint16_t _nbBuffers = stripNbBuffers;
145 static constexpr float _lampBodyRadius_mm = lampda::lampBodyRadius_mm;
146 static constexpr float _ledStripWidth_mm = lampda::ledStripWidth_mm;
147 static constexpr float _ledStripLength_mm = lampda::ledStripLength_mm;
148 static constexpr float _ledByMeter = lampda::ledByMeter;
149 component::LedStrip& strip;
150
152 static constexpr uint16_t _safeBufSize = (_width + 1) * (_height + 1);
153
155 using BufferTy = std::array<uint32_t, _ledCount>;
156 // using BufferTy = std::array<uint32_t, _safeBufSize>;
157
158 LampTy() = delete;
159 LampTy(const LampTy&) = delete;
160 LampTy& operator=(const LampTy&) = delete;
161
162public:
164 LMBD_INLINE LampTy(component::LedStrip& strip) : config {}, strip {strip}, now {0}, tick {0}, raw_frame_count {0} {}
165#else
166private:
167 // (placeholder values to avoid bad fails on misuse)
168 static constexpr float _fwidth = 23.5451;
169 static constexpr float _fheight = 22.51;
170 static constexpr uint16_t _width = 23;
171 static constexpr uint16_t _height = 22;
172 static constexpr uint16_t _ledCount = 530;
173 static constexpr uint16_t _nbBuffers = 3;
174 static constexpr float _lampBodyRadius_mm = 25.0f;
175 static constexpr float _ledStripWidth_mm = 5.2f;
176 static constexpr float _ledStripLength_mm = 25.0f;
177 static constexpr float _ledByMeter = 160.0f;
178
180 static constexpr uint16_t _safeBufSize = (_width + 1) * (_height + 1);
181
183 using BufferTy = std::array<uint32_t, _ledCount>;
184 // using BufferTy = std::array<uint32_t, _safeBufSize>;
185
186 LampTy(const LampTy&) = delete;
187 LampTy& operator=(const LampTy&) = delete;
188
189 struct LedStrip
190 {
191 BufferTy _buffers[_nbBuffers];
192 COLOR _colors[_ledCount]; // !! slighly smaller than buffers in _buffers !!
193
194 void begin();
195 void show();
196 void show_now();
197 void signal_display();
198 void setBrightness(brightness_t);
199 uint8_t getBrightness();
200 void setPixelColor(uint16_t, uint32_t);
201 uint32_t getPixelColor(uint16_t);
202 };
203 LedStrip fakeStrip;
204 LedStrip& strip;
205
206public:
208 LMBD_INLINE LampTy() : config {}, fakeStrip {}, strip {fakeStrip}, now {0}, tick {0}, raw_frame_count {0} {}
209#endif
210
211 //
212 // private API
213 //
214
216 void LMBD_INLINE refresh_tick_value()
217 {
218 uint32_t* writeable_now = const_cast<uint32_t*>(&now);
219 *writeable_now = hal::time_ms();
220
221 uint32_t* writable_tick = const_cast<uint32_t*>(&tick);
222 *writable_tick = now / frameDurationMs;
223
224 uint32_t* writable_frame_count = const_cast<uint32_t*>(&raw_frame_count);
225 *writable_frame_count += 1; // monotonous
226 }
227
238 void LMBD_INLINE startup()
239 {
240 // set output voltage for leds that will not change voltage
241 if (stripInputMinVoltage_mV == stripInputMaxVoltage_mV)
242 component::outputPower::write_voltage(stripInputMaxVoltage_mV);
243
244 begin();
245 clear();
246 show_now();
249 }
250
259 void LMBD_INLINE begin()
260 {
261 if constexpr (flavor == LampTypes::indexable)
262 {
263 strip.begin();
264 }
265 else
266 {
267 // (this is optimized out, and is essentially no-op for other flavors)
268 assert(true);
269 }
270 }
271
280 void LMBD_INLINE show()
281 {
282 if constexpr (flavor == LampTypes::indexable)
283 {
284 strip.show();
285 }
286 else
287 {
288 // (this is optimized out, and is essentially no-op for other flavors)
289 assert(true);
290 }
291 }
292
301 void LMBD_INLINE show_now()
302 {
303 if constexpr (flavor == LampTypes::indexable)
304 {
305 strip.show_now();
306 }
307 else
308 {
309 // (this is optimized out, and is essentially no-op for other flavors)
310 assert(true);
311 }
312 }
313
322 void LMBD_INLINE signal_display()
323 {
324 if constexpr (flavor == LampTypes::indexable)
325 {
326 strip.signal_display();
327 }
328 else
329 {
330 // (this is optimized out, and is essentially no-op for other flavors)
331 assert(true);
332 }
333 }
334
335 //
336 // public constants
337 //
338
340 static constexpr LampTypes flavor = lampType;
341
343 static constexpr uint32_t frameDurationMs = MAIN_LOOP_UPDATE_PERIOD_MS;
344
345#ifndef LMBD_LAMP_TYPE__INDEXABLE_IS_HD
346 // (we have 12ms and 83.3fps values to be updated in this file)
347 static_assert(frameDurationMs == 12, "Update the documentation of .tick :)");
348#endif
349
351 static constexpr uint32_t brightnessDurationMs = frameDurationMs * 2;
352
357 static constexpr uint16_t ledCount = _ledCount;
358
370 static constexpr uint16_t maxWidth = _width;
371
373 static constexpr float maxWidthFloat = _fwidth;
374
376 static constexpr uint16_t maxOverflowWidth = maxWidth + 1;
377
391 static constexpr uint16_t maxHeight = _height;
392
394 static constexpr float maxHeightFloat = _fheight;
395
397 static constexpr uint16_t maxOverflowHeight = maxHeight + 1;
398
400 static constexpr float shiftPerTurn = _fwidth - floor(_fwidth - 0.0001);
401
403 static constexpr uint16_t shiftPeriod = 2;
404
406 static constexpr float _invShiftResidue = shiftPeriod * (_fwidth - floor(_fwidth - 0.0001));
407
409 static constexpr uint16_t shiftResidue = 100.0 / abs(100.0 * _invShiftResidue - 100.0);
410
412 static constexpr auto allResiduesY = details::computeResidues<maxOverflowHeight>(_fwidth);
413
415 static constexpr auto allDeltaResiduesY = details::computeDeltaResidues<maxOverflowHeight>(_fwidth);
416
418 static constexpr auto extraShiftResiduesY = details::computeExtraShiftResidues<maxOverflowHeight>(_fwidth);
419
421 static constexpr int extraShiftTotal = extraShiftResiduesY[maxOverflowHeight - 1];
422
424 static constexpr float lampBodyRadius_mm = _lampBodyRadius_mm;
425
427 static constexpr float ledStripWidth_mm = _ledStripWidth_mm;
429 static constexpr float ledStripLength_mm = _ledStripLength_mm;
430
432 static constexpr float ledByMeter = _ledByMeter;
433
435 static constexpr float ledSize_mm = 1000.0f / ledByMeter;
442
447 static constexpr uint8_t nbBuffers = _nbBuffers;
448
449 //
450 // public helpers
451 //
452
459 template<typename T> static constexpr LMBD_INLINE uint16_t toLedCount(T scale)
460 {
461 if constexpr (std::is_same_v<T, float>)
462 {
463 assert(scale <= 1.0 && "scale is 0-1");
464 return ledCount * scale;
465 }
466 else if constexpr (std::is_same_v<T, uint8_t>)
467 {
468 uint32_t scaled = ledCount * scale;
469 return scaled / 256;
470 }
471 else
472 {
473 static_assert(std::is_same_v<T, std::false_type>, "Invalid type, either float or uint8_t required!");
474 return 0;
475 }
476 }
477
478 //
479 // public API
480 //
481
490 void LMBD_INLINE clear()
491 {
492 if constexpr (flavor == LampTypes::indexable)
493 {
494 for (uint16_t i = 0; i < ledCount; ++i)
495 {
497 }
498 }
499 else
500 {
501 // (this is optimized out, and is essentially no-op for other flavors)
502 assert(true);
503 }
504 }
505
513 void LMBD_INLINE blip(const uint32_t duration)
514 {
515 if constexpr (flavor == LampTypes::indexable)
516 {
517 // disable strip temporarily
518 // should be reactivated by the manager
520 }
521 else
522 {
524 }
525 }
526
530 void LMBD_INLINE cancel_blip() const { return component::outputPower::cancel_blip(); }
531
535 bool LMBD_INLINE is_bliping() const { return component::outputPower::is_bliping(); }
536
557 void LMBD_INLINE setBrightness(const brightness_t newBrightness,
558 const bool skipCallbacks = true,
559 const bool skipUpdateBrightness = false,
560 const bool updateSavedBrightess = false)
561 {
562 assert((skipCallbacks || !skipUpdateBrightness) && "implicit callback skip!");
563
564 // invalid call, fallback to enforcing
565 if (newBrightness > ::lampda::brightness::absoluteMaximumBrightness)
566 {
568 return;
569 }
570
571 // force update if we are getting lower and lower
572 if (!skipUpdateBrightness or newBrightness > getMaxBrightness())
573 {
574 // store the new temporary
575 temporary_brightness = min<brightness_t>(newBrightness, getMaxBrightness());
576
578 if ((this->now - last) > brightnessDurationMs)
580 }
581 // if necessary, update the saved version
582 if (updateSavedBrightess)
583 {
584 saved_brightness = min<brightness_t>(static_cast<brightness_t>(temporary_brightness), getMaxBrightness());
585 }
586
587 // USE THE BRIGHTNESS VALUE AFTER THE UPDATE
588 // brightness can be limited by the system, so do not use the raw brightness
589 const auto trueNewBrightness = logic::brightness::get_brightness();
590
591 if constexpr (flavor == LampTypes::indexable)
592 {
593#ifndef LMBD_LAMP_TYPE__INDEXABLE
594 static constexpr uint8_t minimumAllowedBrightness = 5;
595#else
596 static constexpr uint8_t minimumAllowedBrightness = ::lampda::minimumAllowedBrightness_8;
597#endif
599 static curve_t brightnessCurve({curve_t::point_t {0, minimumAllowedBrightness},
600 curve_t::point_t {::lampda::brightness::absoluteMaximumBrightness, 255}});
601
603 strip.setBrightness(brightnessCurve.sample(trueNewBrightness));
604 }
605
606 if constexpr (flavor == LampTypes::simple)
607 {
608 const auto trueMaxBrightness = logic::brightness::get_max_brightness();
609
610 // This is kind of a hack to detect that the user did this call
611 // using the known user call signature
612 const bool isUserCall = skipCallbacks and skipUpdateBrightness and not updateSavedBrightess;
613
614 // display an output blip on max brightness reached
615 if (isUserCall and trueNewBrightness >= trueMaxBrightness)
616 {
618 }
619
621 static curve_t brightnessCurve(
622 curve_t::point_t {0, stripInputMinVoltage_mV},
623 curve_t::point_t {::lampda::brightness::absoluteMaximumBrightness, stripInputMaxVoltage_mV},
624 1.0);
625
626 component::outputPower::write_voltage(round(brightnessCurve.sample(trueNewBrightness)));
627 }
628 }
629
632 {
635 }
636
639 {
640 const auto maxAllowedBrightness = getMaxBrightness();
641 const brightness_t new_saved_brightness =
642 min<brightness_t>(static_cast<brightness_t>(saved_brightness), maxAllowedBrightness);
643 const brightness_t new_temporary_brightness =
644 min<brightness_t>(static_cast<brightness_t>(temporary_brightness), maxAllowedBrightness);
645
646 const bool isChanged = new_saved_brightness != saved_brightness or new_temporary_brightness != temporary_brightness;
647 if (isChanged)
648 {
649 saved_brightness = new_saved_brightness;
650 temporary_brightness = new_temporary_brightness;
651
653 }
654 }
655
660
672 void LMBD_INLINE tempBrightness(const brightness_t brightness)
673 {
674 brightness_t current = getBrightness();
675 if (current != brightness)
676 setBrightness(brightness, true, false, false);
677 }
678
690 void LMBD_INLINE jumpBrightness(const brightness_t brightness) { setBrightness(brightness, true, false, true); }
691
698 brightness_t LMBD_INLINE getBrightness(const bool readPreviousBrightness = false)
699 {
700 if (readPreviousBrightness)
701 return saved_brightness;
702 else
704 }
705
707 brightness_t LMBD_INLINE getSavedBrightness() { return getBrightness(true); }
708
710 void LMBD_INLINE restoreBrightness()
711 {
712 const brightness_t current = getBrightness();
713 const brightness_t saved = getSavedBrightness();
714
715 if (current != saved)
716 setBrightness(saved, true, false, false);
717 }
718
727 void LMBD_INLINE fadeToBlackBy(uint8_t fadeBy)
728 {
729 if constexpr (flavor == LampTypes::indexable)
730 {
731 if (fadeBy == 0)
732 return; // optimization - no scaling to apply
733
734 for (uint16_t i = 0; i < ledCount; ++i)
735 {
736 const uint32_t c = getPixelColor(i);
737 setPixelColor(i, colors::fade(c, 255 - fadeBy));
738 }
739 }
740 else
741 {
742 uint8_t brightness = getBrightness();
743 brightness = (brightness < fadeBy) ? 0 : brightness - fadeBy;
744 setBrightness(brightness);
745 }
746 }
747
757 void LMBD_INLINE blur(uint8_t blurBy)
758 {
759 if (blurBy == 0)
760 return; // optimization: 0 means "don't blur"
761 uint8_t keep = 255 - blurBy;
762 uint8_t seep = blurBy >> 1;
763
764 uint32_t carryover = 0;
765 for (unsigned i = 0; i < ledCount; i++)
766 {
767 uint32_t cur = getPixelColor(i);
768 uint32_t c = cur;
769 uint32_t part = colors::fade<false>(c, seep);
770 cur = colors::add<true>(colors::fade<false>(c, keep), carryover);
771 if (i > 0)
772 {
773 c = getPixelColor(i - 1);
774 setPixelColor(i - 1, colors::add<true>(c, part));
775 }
776 setPixelColor(i, cur);
777 carryover = part;
778 }
779 }
780
781 //
782 // public API (indexable-only)
783 //
784
790 void LMBD_INLINE fill(uint32_t color, uint16_t start, uint16_t end)
791 {
792 if constexpr (flavor == LampTypes::indexable)
793 {
794 assert(start <= ledCount && "invalid start parameter");
795 assert(end <= ledCount && "invalid end parameter");
796
797 for (uint16_t I = start; I < end; ++I)
798 {
799 setPixelColor(I, color);
800 }
801 }
802 else
803 {
804 assert(false && "unsupported");
805 }
806 }
807
813 void LMBD_INLINE fill(uint32_t color, uint16_t start, uint16_t end, const BufferTy& shouldDisplay)
814 {
815 if constexpr (flavor == LampTypes::indexable)
816 {
817 assert(start <= ledCount && "invalid start parameter");
818 assert(end <= ledCount && "invalid end parameter");
819
820 for (uint16_t I = start; I < end; ++I)
821 {
822 const uint8_t blendValue = min<uint32_t>(shouldDisplay[I], UINT8_MAX);
823 setPixelColor(I, colors::blend<uint8_t>(0, color, blendValue));
824 }
825 }
826 else
827 {
828 assert(false && "unsupported");
829 }
830 }
831
836 void LMBD_INLINE fill(uint32_t color) { fill(color, 0, ledCount); }
837
842 void LMBD_INLINE fill(uint32_t color, const BufferTy& shouldDisplay) { fill(color, 0, ledCount, shouldDisplay); }
843
849 void LMBD_INLINE fill(const colors::PaletteTy& palette, uint16_t start, uint16_t end)
850 {
851 if constexpr (flavor == LampTypes::indexable)
852 {
853 assert(start < ledCount && "invalid start parameter");
854 assert(end <= ledCount && "invalid end parameter");
855
856 for (uint16_t I = start; I < end; ++I)
857 {
858 // map index to [0; 255]
859 const auto color = colors::from_palette<false, uint8_t>(I / static_cast<float>(ledCount) * 255, palette);
860 setPixelColor(I, color);
861 }
862 }
863 else
864 {
865 assert(false && "unsupported");
866 }
867 }
868
872 void LMBD_INLINE fill(const colors::PaletteTy& palette) { fill(palette, 0, ledCount); }
873
878 void LMBD_INLINE setPixelColor(uint16_t n, uint32_t color)
879 {
880 if constexpr (flavor == LampTypes::indexable)
881 {
883 {
884 return;
885 }
886
887 assert(n < ledCount && "invalid LED index");
888 strip.setPixelColor(n, color);
889 }
890 else
891 {
892 assert(false && "unsupported");
893 }
894 }
895
898 uint32_t LMBD_INLINE getPixelColor(uint16_t n)
899 {
900 if constexpr (flavor == LampTypes::indexable)
901 {
903 {
904 return 0;
905 }
906
907 assert(n < ledCount && "invalid LED index");
908 return strip.getPixelColor(n);
909 }
910 else
911 {
912 assert(false && "unsupported");
913 }
914 }
915
920 void LMBD_INLINE setPixelColorXY(uint16_t X, uint16_t Y, uint32_t color) { setPixelColor(to_strip(X, Y), color); }
921
926 static uint16_t LMBD_INLINE fromXYtoStripIndex(uint16_t X, uint16_t Y) { return to_strip(X, Y); }
927
932 static XYTy LMBD_INLINE fromStripIndexToXY(uint16_t N) { return strip_to_XY(N); }
933
939 template<uint8_t bufIdx = 0> BufferTy& LMBD_INLINE getTempBuffer()
940 {
941 static_assert(bufIdx < nbBuffers, "bufIdx must be lower than nbBuffers");
942 BufferTy& buffer = strip._buffers[bufIdx];
943 return buffer;
944 }
945
952 template<uint8_t dstBufIdx, uint8_t srcBufIdx> void LMBD_INLINE copyBuffer()
953 {
954 static_assert(srcBufIdx < nbBuffers, "srcBufIdx must be lower than nbBuffers");
955 static_assert(dstBufIdx < nbBuffers, "dstBufIdx must be lower than nbBuffers");
956
957 strip._buffers[dstBufIdx] = strip._buffers[srcBufIdx];
958 }
959
964 template<uint8_t bufIdx = 0, typename T> void LMBD_INLINE fillTempBuffer(const T& value)
965 {
966 getTempBuffer<bufIdx>().fill(value);
967 }
968
973 template<uint8_t bufIdx = 0> void setColorsFromBuffer()
974 {
975 static_assert(sizeof(BufferTy) == sizeof(strip._colors));
976 const BufferTy& buffer = getTempBuffer<bufIdx>();
978 {
979 uint16_t Idx = config.skipFirstLedsForAmount;
980 uint16_t Sz = sizeof(strip._colors) - Idx * sizeof(uint32_t);
981 memcpy(&strip._colors[Idx], &buffer[Idx], Sz);
982 }
983 else
984 {
985 memcpy(strip._colors, buffer.data(), sizeof(strip._colors));
986 }
987 }
988
993 template<uint8_t dstBufIdx = 0, uint8_t srcBufIdx = 1> void setColorsFromMixedBuffers(float phase)
994 {
995 static_assert(sizeof(BufferTy) == sizeof(strip._colors));
996 const BufferTy& dstBuf = getTempBuffer<dstBufIdx>();
997 const BufferTy& srcBuf = getTempBuffer<srcBufIdx>();
998
999 uint16_t start = 0, end = srcBuf.size();
1001 {
1003 }
1004
1005 for (uint16_t I = start; I < end; ++I)
1006 {
1007 COLOR src, dst;
1008 src.color = srcBuf[I];
1009 dst.color = dstBuf[I];
1010 strip._colors[I].color = utils::get_gradient(src.color, dst.color, phase);
1011 }
1012 }
1013
1016 template<uint8_t bufIdx = 0> void setColorsFromBufferReversed(bool skipLastLine)
1017 {
1018 static_assert(sizeof(BufferTy) == sizeof(strip._colors));
1019 const BufferTy& buffer = getTempBuffer<bufIdx>();
1020
1021 uint16_t start = 0, end = buffer.size();
1023 {
1025 }
1026
1027 if (skipLastLine)
1028 {
1029 end = maxWidth * maxHeight;
1030 }
1031
1032 for (uint16_t I = 0, J = start; I < end - start; ++I, ++J)
1033 {
1034 strip._colors[J].color = buffer[end - start - I - 1];
1035 }
1036 }
1037
1042 template<uint8_t bufIdx = 0, bool forceFullRead = false> void getColorsToBuffer()
1043 {
1044 static_assert(sizeof(BufferTy) == sizeof(strip._colors));
1045
1046 BufferTy& buffer = getTempBuffer<bufIdx>();
1047 if (!forceFullRead && config.skipFirstLedsForEffect)
1048 {
1049 uint16_t Idx = config.skipFirstLedsForAmount;
1050 uint16_t Sz = sizeof(strip._colors) - Idx * sizeof(uint32_t);
1051
1052 buffer.fill(0);
1053 memcpy(&buffer[Idx], &strip._colors[Idx], Sz);
1054 }
1055 else
1056 {
1057 memcpy(buffer.data(), strip._colors, sizeof(strip._colors));
1058 }
1059 }
1060
1065 {
1067 }
1068
1073
1079 volatile const uint32_t now;
1080
1088 volatile const uint32_t tick;
1089
1096 volatile const uint32_t raw_frame_count;
1097};
1098
1099} // namespace lampda::modes::hardware
1100
1101namespace lampda::modes {
1102
1104static constexpr uint16_t to_strip(uint16_t x, uint16_t y)
1105{
1106 // maxHeight is the last "full" row and maxOverflowHeight is truncated row
1107 // -> user max use to_strip(x, maxOverflowHeight) to set truncated row
1109 {
1111 }
1112
1113 // if row is longer (because next row gets a shift) use maxOverflowWidth
1114 if (hardware::LampTy::allDeltaResiduesY[y])
1115 {
1117 {
1119 }
1120
1121 // if row is aligned to XY maxWidth/maxHeight matrix, use maxWidth instead
1122 }
1123 else if (x >= hardware::LampTy::maxWidth)
1124 {
1126 }
1127
1128 // final result is capped by the "real" LED count of the strip
1129 uint16_t n = x + y * hardware::LampTy::maxWidth + hardware::LampTy::allResiduesY[y];
1132 return n;
1133}
1134
1136static constexpr XYTy strip_to_XY(uint16_t n)
1137{
1138 // (saturates N to ledCount)
1141
1142 uint16_t y = 0;
1143 while (y * hardware::LampTy::maxWidth + hardware::LampTy::allResiduesY[y] <= n)
1144 y += 1;
1145
1146 if (y == 0)
1147 return {0, 0};
1148 y -= 1;
1149
1150 uint16_t x = n - y * hardware::LampTy::maxWidth - hardware::LampTy::allResiduesY[y];
1151 return {x, y};
1152}
1153
1159static constexpr HelixXYZTy strip_to_helix(int16_t n)
1160{
1162 return HelixXYZTy {0.0, 0.0, 0.0};
1163
1165}
1166
1172static constexpr float to_helix_z(const int16_t n)
1173{
1175}
1176
1182static constexpr HelixXYZTy strip_to_helix_unconstraint(const int16_t n)
1183{
1186 to_helix_z(n)};
1187}
1188
1193static constexpr bool is_led_index_valid(const int16_t n) { return n >= 0 and n < hardware::LampTy::ledCount; }
1194
1201static constexpr bool is_lamp_coordinate_out_of_bounds(const float angle_rad, const float z_mm)
1202{
1203 return not is_led_index_valid(to_led_index_no_bounds(angle_rad, z_mm));
1204}
1205
1212static constexpr uint16_t to_led_index(const float angle_rad, const float z_mm)
1213{
1214 constexpr uint16_t maxZCoordinate =
1216
1217 // snip Z per possible lines
1218 uint16_t zIndex = floor(-z_mm / hardware::LampTy::ledStripWidth_mm);
1219 if (zIndex < 0.0)
1220 zIndex = 0.0;
1221 if (zIndex > maxZCoordinate)
1222 zIndex = maxZCoordinate;
1223
1224 // indexing around the led turn
1225 const float angularPosition = wrap_angle(angle_rad) / c_TWO_PI * hardware::LampTy::maxWidthFloat;
1226
1227 // convert to led index (approx)
1228 int16_t ledIndex = round(angularPosition + zIndex * hardware::LampTy::maxWidthFloat);
1229 if (ledIndex < 0)
1230 ledIndex = round(angularPosition + (zIndex + 1) * hardware::LampTy::maxWidthFloat);
1231 if (ledIndex >= hardware::LampTy::ledCount)
1232 ledIndex = round(angularPosition + (zIndex - 1) * hardware::LampTy::maxWidthFloat);
1233
1234 if (ledIndex < 0)
1235 return 0;
1236 if (ledIndex >= hardware::LampTy::ledCount)
1237 return hardware::LampTy::ledCount - 1;
1238 return ledIndex;
1239}
1240
1247static constexpr int16_t to_led_index_no_bounds(const float angle_rad, const float z_mm)
1248{
1249 // snip Z per possible lines
1250 const int16_t zIndex = floor(-z_mm / hardware::LampTy::ledStripWidth_mm);
1251 // indexing around the led turn
1252 const float angularPosition = wrap_angle(angle_rad) / c_TWO_PI * hardware::LampTy::maxWidthFloat;
1253
1254 // convert to led index (approx)
1255 return round(angularPosition + zIndex * hardware::LampTy::maxWidthFloat);
1256}
1257
1258} // namespace lampda::modes
1259
1260#endif
Define assertions helpers.
Handle the output LED strip brightness.
Given two points and an exponent, fit an exponential function.
Definition: curves.h:120
Given a set of points, will fit multiple linear segments to it.
Definition: curves.h:35
protected inheritence to avoid uncontroled hardware calls
Definition: strip.h:49
COLOR _colors[LED_COUNT]
store the display colors, with no brightness scaling
Definition: strip.h:424
void setBrightness(uint8_t b)
Brightness is an internal counter.
Definition: strip.h:111
BufferTy _buffers[stripNbBuffers]
buffers for computations
Definition: strip.h:430
void begin()
Definition: strip.h:129
void show_now()
Show the current data, independant of changes.
Definition: strip.h:173
Manipulate color representations.
Compile definitions and sanity checks.
Contains shorthand macro definitions.
Define the lamps coordinates systems.
Define curves types, that can be sampled.
SoundStruct & get_sound_characteristics()
Compute and process sound data.
Definition: sound.cpp:169
void cancel_blip()
stop an ongoing blip
Definition: output_power.cpp:41
void write_voltage(const uint16_t voltage_mv)
Write a voltage to the output (will only write it in output mode)
Definition: output_power.cpp:19
bool is_bliping()
indicates that the gate is in a blip
Definition: output_power.cpp:43
void blip(const uint32_t timing)
short interruption of output voltage
Definition: output_power.cpp:39
uint32_t time_ms(void)
Returns the number of milliseconds since the Arduino board began running the current program....
Definition: time.cpp:18
brightness_t get_brightness()
Return the current brightness value (in range 0 - brightness::absoluteMaximumBrightness)....
Definition: brightness_handle.cpp:39
uint32_t when_last_update_brightness()
Get time in milliseconds when brightness was last updated.
Definition: brightness_handle.cpp:94
void update_brightness(const brightness_t newBrightness, const bool shouldCallUserBrightnessCallback)
update the internal brightness values
Definition: brightness_handle.cpp:66
brightness_t get_saved_brightness()
Return the saved brightness level. This shoudl be the prefered option in all computations.
Definition: brightness_handle.cpp:64
brightness_t get_max_user_brightness()
Return the maximum allowed brightness for the user modes.
Definition: brightness_handle.cpp:43
brightness_t get_max_brightness()
Return the maximum allowed brightness.
Definition: brightness_handle.cpp:41
static uint32_t fade(uint32_t inputColor, uint8_t fadeAmount)
fade the color toward black
Definition: utils.hpp:121
std::array< uint32_t, 16 > PaletteTy
Palette types.
Definition: palettes.hpp:18
@ Black
Definition: palettes.hpp:96
Provide interface to the physical hardware and other facilities.
Definition: coordinates.hpp:10
LampTypes
Enumeration to write code working with all lamp types.
Definition: lamp_type.hpp:92
@ indexable
Equivalent to LMBD_LAMP_TYPE__INDEXABLE.
@ simple
Equivalent to LMBD_LAMP_TYPE__SIMPLE.
@ cct
Equivalent to LMBD_LAMP_TYPE__CCT.
static constexpr LampTypes lampType
Currently implemented lamp type, defined at compile-time by the user.
Definition: lamp_type.hpp:111
Contains basic interface types to implement custom user modes.
Definition: control_fixed_modes.hpp:12
static constexpr uint16_t to_led_index(const float angle_rad, const float z)
convert a lamp coordinate to a led index
Definition: lamp_type.hpp:1212
static constexpr float to_helix_z(const int16_t n)
Convert a led index to an helix height coordinate.
Definition: lamp_type.hpp:1172
static constexpr uint16_t to_strip(uint16_t, uint16_t)
convert grid coordinates to strip index
Definition: lamp_type.hpp:1104
static constexpr XYTy strip_to_XY(uint16_t n)
convert strip index to grid coordinates
Definition: lamp_type.hpp:1136
static constexpr int16_t to_led_index_no_bounds(const float angle_rad, const float z)
convert a lamp coordinate to a led index, the result can be an index out of the lamp body
Definition: lamp_type.hpp:1247
static constexpr bool is_lamp_coordinate_out_of_bounds(const float angle_rad, const float z)
True if the given led index is out of bounds.
Definition: lamp_type.hpp:1201
static constexpr bool is_led_index_valid(const int16_t ledIndex)
True if the given strip index is a valid one.
Definition: lamp_type.hpp:1193
static constexpr HelixXYZTy strip_to_helix_unconstraint(const int16_t n)
convert strip index to 3D coordinates, without checks on led index. This allows to use 3D coordinates...
Definition: lamp_type.hpp:1182
static constexpr HelixXYZTy strip_to_helix(int16_t n)
convert strip index to 3D coordinates
Definition: lamp_type.hpp:1159
uint32_t get_gradient(const uint32_t colorStart, const uint32_t colorEnd, const float level)
Return the color gradient between colorStart to colorEnd.
Definition: utils.cpp:60
static constexpr float wrap_angle(const float angle_rad)
Wrap an angle in radians between 0 and 2*PI.
Definition: utils.h:115
static constexpr N abs(const N a)
absolute of a number
Definition: utils.h:46
static constexpr float c_TWO_PI
2*PI constant
Definition: constants.h:21
uint16_t brightness_t
Define the type of the brightness parameters.
Definition: constants.h:147
Interface for the physical components of the main power output (eg: LED strip output).
Define some useful color palettes, and tools to use them.
Interface for the physical components of the microphone.
Interface of the indexable strip object. Only used for RGB lamp type.
Handle the analysis of a sound sample. This structure handled the FastFourrier analysis of a sound sa...
Definition: sound.h:34
Definition: lamp_type.hpp:55
float x
x 3D mm coordinates
Definition: lamp_type.hpp:56
float y
y 3D mm coordinates
Definition: lamp_type.hpp:57
float z
z 3D mm coordinates
Definition: lamp_type.hpp:58
Definition: lamp_type.hpp:44
uint16_t y
y 2D led grid coordinates
Definition: lamp_type.hpp:46
uint16_t x
x 2D led grid coordinates
Definition: lamp_type.hpp:45
Store a display config.
Definition: lamp_type.hpp:125
uint16_t skipFirstLedsForAmount
Skip the first N leds.
Definition: lamp_type.hpp:127
uint16_t skipFirstLedsForEffect
Skip duration.
Definition: lamp_type.hpp:126
Main interface between the user and the hardware of the lamp.
Definition: lamp_type.hpp:118
void LMBD_INLINE fill(uint32_t color, uint16_t start, uint16_t end)
(indexable) Fill lamp with target color, from start to end
Definition: lamp_type.hpp:790
void align_internal_to_system_brightness()
Special call to update the internal brightness values to the system brightness.
Definition: lamp_type.hpp:631
void setColorsFromMixedBuffers(float phase)
Mix two colors from a buffer.
Definition: lamp_type.hpp:993
static XYTy LMBD_INLINE fromStripIndexToXY(uint16_t N)
(indexable) Given a LED index, return a corresponding X,Y value
Definition: lamp_type.hpp:932
brightness_t LMBD_INLINE getMaxBrightness() const
Return the actual allowed maximum brightness.
Definition: lamp_type.hpp:659
static constexpr float ledByMeter
number of led per meters of strip used
Definition: lamp_type.hpp:432
void LMBD_INLINE restoreBrightness()
Reset brightness to internal saved brightness, skip callbacks.
Definition: lamp_type.hpp:710
void LMBD_INLINE blur(uint8_t blurBy)
Blur currently displayed content by blurBy units /!\ Only applied along the strip,...
Definition: lamp_type.hpp:757
static constexpr uint16_t maxHeight
(indexable) Height of "pixel space" w/ lamp taken as a LED matrix
Definition: lamp_type.hpp:391
void LMBD_INLINE fill(uint32_t color, uint16_t start, uint16_t end, const BufferTy &shouldDisplay)
(indexable) Fill lamp with target color, from start to end. Apply a mask to display leds
Definition: lamp_type.hpp:813
static constexpr float lampHeight_mm
Computation of the lamp height.
Definition: lamp_type.hpp:441
void LMBD_INLINE fill(uint32_t color, const BufferTy &shouldDisplay)
(indexable) Fill lamp with target color, with a mask
Definition: lamp_type.hpp:842
void LMBD_INLINE setBrightness(const brightness_t newBrightness, const bool skipCallbacks=true, const bool skipUpdateBrightness=false, const bool updateSavedBrightess=false)
Set brightness of the lamp.
Definition: lamp_type.hpp:557
void LMBD_INLINE fill(const colors::PaletteTy &palette)
(indexable) Fill lamp with target palette
Definition: lamp_type.hpp:872
static constexpr float maxHeightFloat
Height as a precise floating point number, equal to stripYCoordinates.
Definition: lamp_type.hpp:394
volatile brightness_t temporary_brightness
Define a localy consistant temporary brightness.
Definition: lamp_type.hpp:1072
void LMBD_INLINE copyBuffer()
Copy a source buffer at srcBufIdx to another buffer at dstBufIdx.
Definition: lamp_type.hpp:952
static constexpr float lampBodyCircumpherence_mm
Computation of the lamp body circumpherence.
Definition: lamp_type.hpp:437
static constexpr float maxWidthFloat
Width as a precise floating point number, equal to stripXCoordinates.
Definition: lamp_type.hpp:373
BufferTy &LMBD_INLINE getTempBuffer()
Get a reference to the bufIdx temporary buffer.
Definition: lamp_type.hpp:939
static constexpr float ledStripWidth_mm
real size of the led strip in use
Definition: lamp_type.hpp:427
static uint16_t LMBD_INLINE fromXYtoStripIndex(uint16_t X, uint16_t Y)
(indexable) Given X,Y coordinate, return a corresponding LED index
Definition: lamp_type.hpp:926
static constexpr float ledPerTurns
Computation of the led count per turns.
Definition: lamp_type.hpp:439
void LMBD_INLINE tempBrightness(const brightness_t brightness)
Temporarily set brightness, without affecting brightness navigation.
Definition: lamp_type.hpp:672
void setColorsFromBufferReversed(bool skipLastLine)
(indexable) Display bufIdx temporary buffer, but reversed
Definition: lamp_type.hpp:1016
void enforce_internal_brightness_limits()
Enforce the brightness limits, if getMaxBrightness changed. Will call setBrightness.
Definition: lamp_type.hpp:638
void LMBD_INLINE jumpBrightness(const brightness_t brightness)
Jump to brightness, affecting the next brightness navigation.
Definition: lamp_type.hpp:690
LampConfig config
store a display configuration
Definition: lamp_type.hpp:131
volatile const uint32_t tick
(physical) Tick number, ever-increasing every frameDurationMs
Definition: lamp_type.hpp:1088
static constexpr float ledSize_mm
Number of leds per one turn of led strip.
Definition: lamp_type.hpp:435
volatile const uint32_t now
(physical) The "now" on milliseconds, updated just before loop.
Definition: lamp_type.hpp:1079
void LMBD_INLINE setPixelColorXY(uint16_t X, uint16_t Y, uint32_t color)
(indexable) Set the X,Y-th LED color
Definition: lamp_type.hpp:920
void LMBD_INLINE setPixelColor(uint16_t n, uint32_t color)
(indexable) Set the n-th LED color
Definition: lamp_type.hpp:878
void LMBD_INLINE fillTempBuffer(const T &value)
Fill temporary buffer bufIdx with given value.
Definition: lamp_type.hpp:964
void LMBD_INLINE clear()
Clear lamp to a clean state.
Definition: lamp_type.hpp:490
uint32_t LMBD_INLINE getPixelColor(uint16_t n)
(indexable) Get the n-th LED color
Definition: lamp_type.hpp:898
static constexpr uint16_t maxOverflowHeight
Larger height, taken as the absolute maximum Y coordinate, overflowing.
Definition: lamp_type.hpp:397
void LMBD_INLINE blip(const uint32_t duration)
blip the power gate for set time
Definition: lamp_type.hpp:513
void setColorsFromBuffer()
(indexable) Display bufIdx temporary buffer as LED colors
Definition: lamp_type.hpp:973
volatile brightness_t saved_brightness
Define a localy consistant saved brightness. Should be similar.
Definition: lamp_type.hpp:1070
bool LMBD_INLINE is_bliping() const
return true if the output is in a blip state
Definition: lamp_type.hpp:535
static constexpr float ledStripLength_mm
Copy the led strip lenght.
Definition: lamp_type.hpp:429
static constexpr float _invShiftResidue
(while shifting every shiftPeriod, we have a residue accumulating)
Definition: lamp_type.hpp:406
static constexpr LMBD_INLINE uint16_t toLedCount(T scale)
(indexable) Return a led count in 0-ledCount scaled by scale
Definition: lamp_type.hpp:459
component::microphone::SoundStruct &LMBD_INLINE get_sound_struct()
Return the an object containing sound analysis data.
Definition: lamp_type.hpp:1064
static constexpr float lampBodyRadius_mm
real radius of the lamp body
Definition: lamp_type.hpp:424
static constexpr LampTypes flavor
Which lamp flavor is currently used by the implementation?
Definition: lamp_type.hpp:340
static constexpr uint32_t frameDurationMs
Hardward try to call .loop() every frameDurationMs (12ms for 83.3fps)
Definition: lamp_type.hpp:343
void LMBD_INLINE fill(const colors::PaletteTy &palette, uint16_t start, uint16_t end)
(indexable) Fill lamp with target palette, from start to end
Definition: lamp_type.hpp:849
static constexpr uint16_t maxWidth
(indexable) Width of "pixel space" w/ lamp taken as a LED matrix
Definition: lamp_type.hpp:370
brightness_t LMBD_INLINE getBrightness(const bool readPreviousBrightness=false)
Get brightness of the lamp.
Definition: lamp_type.hpp:698
void LMBD_INLINE fill(uint32_t color)
(indexable) Fill lamp with target color
Definition: lamp_type.hpp:836
static constexpr uint16_t maxOverflowWidth
Larger width, taken as the absolute maximum X coordinate on all rows.
Definition: lamp_type.hpp:376
void getColorsToBuffer()
(indexable) Copy all current LEDs color to bufIdx temp. buffer
Definition: lamp_type.hpp:1042
static constexpr uint16_t ledCount
(indexable) Count of indexable LEDs on the lamp
Definition: lamp_type.hpp:357
brightness_t LMBD_INLINE getSavedBrightness()
Alias for getBrightness(true)
Definition: lamp_type.hpp:707
static constexpr uint8_t nbBuffers
(indexable) Number of color buffers available for direct access
Definition: lamp_type.hpp:447
volatile const uint32_t raw_frame_count
(physical) Raw frame count, incremented at an undefined rate
Definition: lamp_type.hpp:1096
static constexpr uint32_t brightnessDurationMs
Limit mode-requested brightness changes to one every few frames.
Definition: lamp_type.hpp:351
void LMBD_INLINE cancel_blip() const
Cancel the ongoing blip, if any.
Definition: lamp_type.hpp:530
void LMBD_INLINE fadeToBlackBy(uint8_t fadeBy)
Fade currently displayed content by fadeBy units.
Definition: lamp_type.hpp:727
Define the system hardware constants.
Convertion header to use the text out functions from C code.
Define all time related platform functions.
Use this to convert color to bytes.
Definition: utils.h:128
User defined constants, relative to specific lamp types.
Define useful functions.