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
22
24
30
31#include "src/system/ext/math8.h"
32
36
37namespace lampda::modes {
38
39struct XYTy
40{
41 uint16_t x;
42 uint16_t y;
43};
44
46static constexpr uint16_t to_strip(uint16_t, uint16_t);
48static constexpr XYTy strip_to_XY(uint16_t n);
49
51{
52 float x;
53 float y;
54 float z;
55};
56
58static constexpr HelixXYZTy strip_to_helix(int16_t n);
59
62static constexpr HelixXYZTy strip_to_helix_unconstraint(const int16_t n);
64static constexpr bool is_led_index_valid(const int16_t ledIndex);
66static constexpr bool is_lamp_coordinate_out_of_bounds(const float angle_rad, const float z);
67
71static constexpr uint16_t to_led_index(const float angle_rad, const float z);
72
76static constexpr int16_t to_led_index_no_bounds(const float angle_rad, const float z);
77
78} // namespace lampda::modes
79
82
87enum class LampTypes : uint8_t
88{
89 simple,
90 cct,
91 indexable,
92};
93
94#ifdef LMBD_LAMP_TYPE__SIMPLE
95static constexpr LampTypes _lampType = LampTypes::simple;
96#endif
97
98#ifdef LMBD_LAMP_TYPE__CCT
99static constexpr LampTypes _lampType = LampTypes::cct;
100#endif
101
102#ifdef LMBD_LAMP_TYPE__INDEXABLE
103static constexpr LampTypes _lampType = LampTypes::indexable;
104#endif
105
107static constexpr LampTypes lampType = _lampType;
108
113struct LampTy
114{
115 //
116 // state managed by manager
117 //
118
121 {
124 };
125
128
129 //
130 // private constructors
131 //
132
133#ifdef LMBD_LAMP_TYPE__INDEXABLE
134private:
135 static constexpr float _fwidth = stripXCoordinates;
136 static constexpr float _fheight = stripYCoordinates;
137 static constexpr uint16_t _width = floor(_fwidth);
138 static constexpr uint16_t _height = floor(_fheight);
139 static constexpr uint16_t _ledCount = LED_COUNT;
140 static constexpr uint16_t _nbBuffers = stripNbBuffers;
141 static constexpr float _lampBodyRadius_mm = lampda::lampBodyRadius_mm;
142 static constexpr float _ledStripWidth_mm = lampda::ledStripWidth_mm;
143 static constexpr float _ledStripLength_mm = lampda::ledStripLength_mm;
144 static constexpr float _ledByMeter = lampda::ledByMeter;
145 physical::LedStrip& strip;
146
148 static constexpr uint16_t _safeBufSize = (_width + 1) * (_height + 1);
149
151 using BufferTy = std::array<uint32_t, _ledCount>;
152 // using BufferTy = std::array<uint32_t, _safeBufSize>;
153
154 LampTy() = delete;
155 LampTy(const LampTy&) = delete;
156 LampTy& operator=(const LampTy&) = delete;
157
158public:
160 LMBD_INLINE LampTy(physical::LedStrip& strip) : config {}, strip {strip}, now {0}, tick {0}, raw_frame_count {0} {}
161#else
162private:
163 // (placeholder values to avoid bad fails on misuse)
164 static constexpr float _fwidth = 23.5451;
165 static constexpr float _fheight = 22.51;
166 static constexpr uint16_t _width = 23;
167 static constexpr uint16_t _height = 22;
168 static constexpr uint16_t _ledCount = 530;
169 static constexpr uint16_t _nbBuffers = 3;
170 static constexpr float _lampBodyRadius_mm = 25.0f;
171 static constexpr float _ledStripWidth_mm = 5.2f;
172 static constexpr float _ledStripLength_mm = 25.0f;
173 static constexpr float _ledByMeter = 160.0f;
174
176 static constexpr uint16_t _safeBufSize = (_width + 1) * (_height + 1);
177
179 using BufferTy = std::array<uint32_t, _ledCount>;
180 // using BufferTy = std::array<uint32_t, _safeBufSize>;
181
182 LampTy(const LampTy&) = delete;
183 LampTy& operator=(const LampTy&) = delete;
184
185 struct LedStrip
186 {
187 BufferTy _buffers[_nbBuffers];
188 COLOR _colors[_ledCount]; // !! slighly smaller than buffers in _buffers !!
189
190 void begin();
191 void show();
192 void show_now();
193 void signal_display();
194 void setBrightness(brightness_t);
195 uint8_t getBrightness();
196 void setPixelColor(uint16_t, uint32_t);
197 uint32_t getPixelColor(uint16_t);
198 };
199 LedStrip fakeStrip;
200 LedStrip& strip;
201
202public:
204 LMBD_INLINE LampTy() : config {}, fakeStrip {}, strip {fakeStrip}, now {0}, tick {0}, raw_frame_count {0} {}
205#endif
206
207 //
208 // private API
209 //
210
212 void LMBD_INLINE refresh_tick_value()
213 {
214 uint32_t* writeable_now = const_cast<uint32_t*>(&now);
215 *writeable_now = platform::time_ms();
216
217 uint32_t* writable_tick = const_cast<uint32_t*>(&tick);
218 *writable_tick = now / frameDurationMs;
219
220 uint32_t* writable_frame_count = const_cast<uint32_t*>(&raw_frame_count);
221 *writable_frame_count += 1; // monotonous
222 }
223
234 void LMBD_INLINE startup()
235 {
236 // set output voltage for leds that will not change voltage
237 if (stripInputMinVoltage_mV == stripInputMaxVoltage_mV)
238 physical::outputPower::write_voltage(stripInputMaxVoltage_mV);
239
240 begin();
241 clear();
242 show_now();
245 }
246
255 void LMBD_INLINE begin()
256 {
257 if constexpr (flavor == LampTypes::indexable)
258 {
259 strip.begin();
260 }
261 else
262 {
263 // (this is optimized out, and is essentially no-op for other flavors)
264 assert(true);
265 }
266 }
267
276 void LMBD_INLINE show()
277 {
278 if constexpr (flavor == LampTypes::indexable)
279 {
280 strip.show();
281 }
282 else
283 {
284 // (this is optimized out, and is essentially no-op for other flavors)
285 assert(true);
286 }
287 }
288
297 void LMBD_INLINE show_now()
298 {
299 if constexpr (flavor == LampTypes::indexable)
300 {
301 strip.show_now();
302 }
303 else
304 {
305 // (this is optimized out, and is essentially no-op for other flavors)
306 assert(true);
307 }
308 }
309
318 void LMBD_INLINE signal_display()
319 {
320 if constexpr (flavor == LampTypes::indexable)
321 {
322 strip.signal_display();
323 }
324 else
325 {
326 // (this is optimized out, and is essentially no-op for other flavors)
327 assert(true);
328 }
329 }
330
331 //
332 // public constants
333 //
334
336 static constexpr LampTypes flavor = lampType;
337
339 static constexpr uint32_t frameDurationMs = MAIN_LOOP_UPDATE_PERIOD_MS;
340
341#ifndef LMBD_LAMP_TYPE__INDEXABLE_IS_HD
342 // (we have 12ms and 83.3fps values to be updated in this file)
343 static_assert(frameDurationMs == 12, "Update the documentation of .tick :)");
344#endif
345
347 static constexpr uint32_t brightnessDurationMs = frameDurationMs * 2;
348
353 static constexpr uint16_t ledCount = _ledCount;
354
366 static constexpr uint16_t maxWidth = _width;
367
369 static constexpr float maxWidthFloat = _fwidth;
370
372 static constexpr uint16_t maxOverflowWidth = maxWidth + 1;
373
387 static constexpr uint16_t maxHeight = _height;
388
390 static constexpr float maxHeightFloat = _fheight;
391
393 static constexpr uint16_t maxOverflowHeight = maxHeight + 1;
394
396 static constexpr float shiftPerTurn = _fwidth - floor(_fwidth - 0.0001);
397
399 static constexpr uint16_t shiftPeriod = 2;
400
402 static constexpr float _invShiftResidue = shiftPeriod * (_fwidth - floor(_fwidth - 0.0001));
403
405 static constexpr uint16_t shiftResidue = 100.0 / abs(100.0 * _invShiftResidue - 100.0);
406
408 static constexpr auto allResiduesY = details::computeResidues<maxOverflowHeight>(_fwidth);
409
411 static constexpr auto allDeltaResiduesY = details::computeDeltaResidues<maxOverflowHeight>(_fwidth);
412
414 static constexpr auto extraShiftResiduesY = details::computeExtraShiftResidues<maxOverflowHeight>(_fwidth);
415
417 static constexpr int extraShiftTotal = extraShiftResiduesY[maxOverflowHeight - 1];
418
420 static constexpr float lampBodyRadius_mm = _lampBodyRadius_mm;
421
423 static constexpr float ledStripWidth_mm = _ledStripWidth_mm;
425 static constexpr float ledStripLength_mm = _ledStripLength_mm;
426
428 static constexpr float ledByMeter = _ledByMeter;
429
431 static constexpr float ledSize_mm = 1000.0f / ledByMeter;
438
443 static constexpr uint8_t nbBuffers = _nbBuffers;
444
445 //
446 // public helpers
447 //
448
455 template<typename T> static constexpr LMBD_INLINE uint16_t toLedCount(T scale)
456 {
457 if constexpr (std::is_same_v<T, float>)
458 {
459 assert(scale <= 1.0 && "scale is 0-1");
460 return ledCount * scale;
461 }
462 else if constexpr (std::is_same_v<T, uint8_t>)
463 {
464 uint32_t scaled = ledCount * scale;
465 return scaled / 256;
466 }
467 else
468 {
469 static_assert(std::is_same_v<T, std::false_type>, "Invalid type, either float or uint8_t required!");
470 return 0;
471 }
472 }
473
474 //
475 // public API
476 //
477
486 void LMBD_INLINE clear()
487 {
488 if constexpr (flavor == LampTypes::indexable)
489 {
490 for (uint16_t i = 0; i < ledCount; ++i)
491 {
493 }
494 }
495 else
496 {
497 // (this is optimized out, and is essentially no-op for other flavors)
498 assert(true);
499 }
500 }
501
509 void LMBD_INLINE blip(const uint32_t duration)
510 {
511 if constexpr (flavor == LampTypes::indexable)
512 {
513 // disable strip temporarily
514 // should be reactivated by the manager
516 }
517 else
518 {
520 }
521 }
522
526 void LMBD_INLINE cancel_blip() const { return physical::outputPower::cancel_blip(); }
527
531 bool LMBD_INLINE is_bliping() const { return physical::outputPower::is_bliping(); }
532
553 void LMBD_INLINE setBrightness(const brightness_t newBrightness,
554 const bool skipCallbacks = true,
555 const bool skipUpdateBrightness = false,
556 const bool updateSavedBrightess = false)
557 {
558 assert((skipCallbacks || !skipUpdateBrightness) && "implicit callback skip!");
559
560 // invalid call, fallback to enforcing
561 if (newBrightness > ::lampda::brightness::absoluteMaximumBrightness)
562 {
564 return;
565 }
566
567 // force update if we are getting lower and lower
568 if (!skipUpdateBrightness or newBrightness > getMaxBrightness())
569 {
570 // store the new temporary
571 temporary_brightness = min<brightness_t>(newBrightness, getMaxBrightness());
572
574 if ((this->now - last) > brightnessDurationMs)
576 }
577 // if necessary, update the saved version
578 if (updateSavedBrightess)
579 {
580 saved_brightness = min<brightness_t>(static_cast<brightness_t>(temporary_brightness), getMaxBrightness());
581 }
582
583 // USE THE BRIGHTNESS VALUE AFTER THE UPDATE
584 // brightness can be limited by the system, so do not use the raw brightness
585 const auto trueNewBrightness = logic::brightness::get_brightness();
586
587 if constexpr (flavor == LampTypes::indexable)
588 {
589#ifndef LMBD_LAMP_TYPE__INDEXABLE
590 static constexpr uint8_t minimumAllowedBrightness = 5;
591#else
592 static constexpr uint8_t minimumAllowedBrightness = ::lampda::minimumAllowedBrightness_8;
593#endif
595 static curve_t brightnessCurve({curve_t::point_t {0, minimumAllowedBrightness},
596 curve_t::point_t {::lampda::brightness::absoluteMaximumBrightness, 255}});
597
599 strip.setBrightness(brightnessCurve.sample(trueNewBrightness));
600 }
601
602 if constexpr (flavor == LampTypes::simple)
603 {
604 const auto trueMaxBrightness = logic::brightness::get_max_brightness();
605
606 // This is kind of a hack to detect that the user did this call
607 // using the known user call signature
608 const bool isUserCall = skipCallbacks and skipUpdateBrightness and not updateSavedBrightess;
609
610 // display an output blip on max brightness reached
611 if (isUserCall and trueNewBrightness >= trueMaxBrightness)
612 {
613 physical::outputPower::blip(50); // blip
614 }
615
617 static curve_t brightnessCurve(
618 curve_t::point_t {0, stripInputMinVoltage_mV},
619 curve_t::point_t {::lampda::brightness::absoluteMaximumBrightness, stripInputMaxVoltage_mV},
620 1.0);
621
622 physical::outputPower::write_voltage(round(brightnessCurve.sample(trueNewBrightness)));
623 }
624 }
625
628 {
631 }
632
635 {
636 const auto maxAllowedBrightness = getMaxBrightness();
637 const brightness_t new_saved_brightness =
638 min<brightness_t>(static_cast<brightness_t>(saved_brightness), maxAllowedBrightness);
639 const brightness_t new_temporary_brightness =
640 min<brightness_t>(static_cast<brightness_t>(temporary_brightness), maxAllowedBrightness);
641
642 const bool isChanged = new_saved_brightness != saved_brightness or new_temporary_brightness != temporary_brightness;
643 if (isChanged)
644 {
645 saved_brightness = new_saved_brightness;
646 temporary_brightness = new_temporary_brightness;
647
649 }
650 }
651
656
668 void LMBD_INLINE tempBrightness(const brightness_t brightness)
669 {
670 brightness_t current = getBrightness();
671 if (current != brightness)
672 setBrightness(brightness, true, false, false);
673 }
674
686 void LMBD_INLINE jumpBrightness(const brightness_t brightness) { setBrightness(brightness, true, false, true); }
687
694 brightness_t LMBD_INLINE getBrightness(const bool readPreviousBrightness = false)
695 {
696 if (readPreviousBrightness)
697 return saved_brightness;
698 else
700 }
701
703 brightness_t LMBD_INLINE getSavedBrightness() { return getBrightness(true); }
704
706 void LMBD_INLINE restoreBrightness()
707 {
708 const brightness_t current = getBrightness();
709 const brightness_t saved = getSavedBrightness();
710
711 if (current != saved)
712 setBrightness(saved, true, false, false);
713 }
714
723 void LMBD_INLINE fadeToBlackBy(uint8_t fadeBy)
724 {
725 if constexpr (flavor == LampTypes::indexable)
726 {
727 if (fadeBy == 0)
728 return; // optimization - no scaling to apply
729
730 for (uint16_t i = 0; i < ledCount; ++i)
731 {
732 const uint32_t c = getPixelColor(i);
733 setPixelColor(i, colors::fade(c, 255 - fadeBy));
734 }
735 }
736 else
737 {
738 uint8_t brightness = getBrightness();
739 brightness = (brightness < fadeBy) ? 0 : brightness - fadeBy;
740 setBrightness(brightness);
741 }
742 }
743
753 void LMBD_INLINE blur(uint8_t blurBy)
754 {
755 if (blurBy == 0)
756 return; // optimization: 0 means "don't blur"
757 uint8_t keep = 255 - blurBy;
758 uint8_t seep = blurBy >> 1;
759
760 uint32_t carryover = 0;
761 for (unsigned i = 0; i < ledCount; i++)
762 {
763 uint32_t cur = getPixelColor(i);
764 uint32_t c = cur;
765 uint32_t part = colors::fade<false>(c, seep);
766 cur = colors::add<true>(colors::fade<false>(c, keep), carryover);
767 if (i > 0)
768 {
769 c = getPixelColor(i - 1);
770 setPixelColor(i - 1, colors::add<true>(c, part));
771 }
772 setPixelColor(i, cur);
773 carryover = part;
774 }
775 }
776
777 //
778 // public API (indexable-only)
779 //
780
786 void LMBD_INLINE fill(uint32_t color, uint16_t start, uint16_t end)
787 {
788 if constexpr (flavor == LampTypes::indexable)
789 {
790 assert(start <= ledCount && "invalid start parameter");
791 assert(end <= ledCount && "invalid end parameter");
792
793 for (uint16_t I = start; I < end; ++I)
794 {
795 setPixelColor(I, color);
796 }
797 }
798 else
799 {
800 assert(false && "unsupported");
801 }
802 }
803
809 void LMBD_INLINE fill(uint32_t color, uint16_t start, uint16_t end, const BufferTy& shouldDisplay)
810 {
811 if constexpr (flavor == LampTypes::indexable)
812 {
813 assert(start <= ledCount && "invalid start parameter");
814 assert(end <= ledCount && "invalid end parameter");
815
816 for (uint16_t I = start; I < end; ++I)
817 {
818 const uint8_t blendValue = min<uint32_t>(shouldDisplay[I], UINT8_MAX);
819 setPixelColor(I, colors::blend(0, color, blendValue));
820 }
821 }
822 else
823 {
824 assert(false && "unsupported");
825 }
826 }
827
832 void LMBD_INLINE fill(uint32_t color) { fill(color, 0, ledCount); }
833
838 void LMBD_INLINE fill(uint32_t color, const BufferTy& shouldDisplay) { fill(color, 0, ledCount, shouldDisplay); }
839
845 void LMBD_INLINE fill(const colors::PaletteTy& palette, uint16_t start, uint16_t end)
846 {
847 if constexpr (flavor == LampTypes::indexable)
848 {
849 assert(start < ledCount && "invalid start parameter");
850 assert(end <= ledCount && "invalid end parameter");
851
852 for (uint16_t I = start; I < end; ++I)
853 {
854 // map index to [0; 255]
855 const auto color = colors::from_palette<false, uint8_t>(I / static_cast<float>(ledCount) * 255, palette);
856 setPixelColor(I, color);
857 }
858 }
859 else
860 {
861 assert(false && "unsupported");
862 }
863 }
864
868 void LMBD_INLINE fill(const colors::PaletteTy& palette) { fill(palette, 0, ledCount); }
869
874 void LMBD_INLINE setPixelColor(uint16_t n, uint32_t color)
875 {
876 if constexpr (flavor == LampTypes::indexable)
877 {
879 {
880 return;
881 }
882
883 assert(n < ledCount && "invalid LED index");
884 strip.setPixelColor(n, color);
885 }
886 else
887 {
888 assert(false && "unsupported");
889 }
890 }
891
894 uint32_t LMBD_INLINE getPixelColor(uint16_t n)
895 {
896 if constexpr (flavor == LampTypes::indexable)
897 {
899 {
900 return 0;
901 }
902
903 assert(n < ledCount && "invalid LED index");
904 return strip.getPixelColor(n);
905 }
906 else
907 {
908 assert(false && "unsupported");
909 }
910 }
911
916 void LMBD_INLINE setPixelColorXY(uint16_t X, uint16_t Y, uint32_t color) { setPixelColor(to_strip(X, Y), color); }
917
922 static uint16_t LMBD_INLINE fromXYtoStripIndex(uint16_t X, uint16_t Y) { return to_strip(X, Y); }
923
928 static XYTy LMBD_INLINE fromStripIndexToXY(uint16_t N) { return strip_to_XY(N); }
929
935 template<uint8_t bufIdx = 0> BufferTy& LMBD_INLINE getTempBuffer()
936 {
937 static_assert(bufIdx < nbBuffers, "bufIdx must be lower than nbBuffers");
938 BufferTy& buffer = strip._buffers[bufIdx];
939 return buffer;
940 }
941
948 template<uint8_t dstBufIdx, uint8_t srcBufIdx> void LMBD_INLINE copyBuffer()
949 {
950 static_assert(srcBufIdx < nbBuffers, "srcBufIdx must be lower than nbBuffers");
951 static_assert(dstBufIdx < nbBuffers, "dstBufIdx must be lower than nbBuffers");
952
953 strip._buffers[dstBufIdx] = strip._buffers[srcBufIdx];
954 }
955
960 template<uint8_t bufIdx = 0, typename T> void LMBD_INLINE fillTempBuffer(const T& value)
961 {
962 getTempBuffer<bufIdx>().fill(value);
963 }
964
969 template<uint8_t bufIdx = 0> void setColorsFromBuffer()
970 {
971 static_assert(sizeof(BufferTy) == sizeof(strip._colors));
972 const BufferTy& buffer = getTempBuffer<bufIdx>();
974 {
975 uint16_t Idx = config.skipFirstLedsForAmount;
976 uint16_t Sz = sizeof(strip._colors) - Idx * sizeof(uint32_t);
977 memcpy(&strip._colors[Idx], &buffer[Idx], Sz);
978 }
979 else
980 {
981 memcpy(strip._colors, buffer.data(), sizeof(strip._colors));
982 }
983 }
984
989 template<uint8_t dstBufIdx = 0, uint8_t srcBufIdx = 1> void setColorsFromMixedBuffers(float phase)
990 {
991 static_assert(sizeof(BufferTy) == sizeof(strip._colors));
992 const BufferTy& dstBuf = getTempBuffer<dstBufIdx>();
993 const BufferTy& srcBuf = getTempBuffer<srcBufIdx>();
994
995 uint16_t start = 0, end = srcBuf.size();
997 {
999 }
1000
1001 for (uint16_t I = start; I < end; ++I)
1002 {
1003 COLOR src, dst;
1004 src.color = srcBuf[I];
1005 dst.color = dstBuf[I];
1006 strip._colors[I].color = utils::get_gradient(src.color, dst.color, phase);
1007 }
1008 }
1009
1012 template<uint8_t bufIdx = 0> void setColorsFromBufferReversed(bool skipLastLine)
1013 {
1014 static_assert(sizeof(BufferTy) == sizeof(strip._colors));
1015 const BufferTy& buffer = getTempBuffer<bufIdx>();
1016
1017 uint16_t start = 0, end = buffer.size();
1019 {
1021 }
1022
1023 if (skipLastLine)
1024 {
1025 end = maxWidth * maxHeight;
1026 }
1027
1028 for (uint16_t I = 0, J = start; I < end - start; ++I, ++J)
1029 {
1030 strip._colors[J].color = buffer[end - start - I - 1];
1031 }
1032 }
1033
1038 template<uint8_t bufIdx = 0, bool forceFullRead = false> void getColorsToBuffer()
1039 {
1040 static_assert(sizeof(BufferTy) == sizeof(strip._colors));
1041
1042 BufferTy& buffer = getTempBuffer<bufIdx>();
1043 if (!forceFullRead && config.skipFirstLedsForEffect)
1044 {
1045 uint16_t Idx = config.skipFirstLedsForAmount;
1046 uint16_t Sz = sizeof(strip._colors) - Idx * sizeof(uint32_t);
1047
1048 buffer.fill(0);
1049 memcpy(&buffer[Idx], &strip._colors[Idx], Sz);
1050 }
1051 else
1052 {
1053 memcpy(buffer.data(), strip._colors, sizeof(strip._colors));
1054 }
1055 }
1056
1061 {
1063 }
1064
1069
1075 volatile const uint32_t now;
1076
1084 volatile const uint32_t tick;
1085
1092 volatile const uint32_t raw_frame_count;
1093};
1094
1095} // namespace lampda::modes::hardware
1096
1097namespace lampda::modes {
1098
1100static constexpr uint16_t to_strip(uint16_t x, uint16_t y)
1101{
1102 // maxHeight is the last "full" row and maxOverflowHeight is truncated row
1103 // -> user max use to_strip(x, maxOverflowHeight) to set truncated row
1105 {
1107 }
1108
1109 // if row is longer (because next row gets a shift) use maxOverflowWidth
1110 if (hardware::LampTy::allDeltaResiduesY[y])
1111 {
1113 {
1115 }
1116
1117 // if row is aligned to XY maxWidth/maxHeight matrix, use maxWidth instead
1118 }
1119 else if (x >= hardware::LampTy::maxWidth)
1120 {
1122 }
1123
1124 // final result is capped by the "real" LED count of the strip
1125 uint16_t n = x + y * hardware::LampTy::maxWidth + hardware::LampTy::allResiduesY[y];
1128 return n;
1129}
1130
1132static constexpr XYTy strip_to_XY(uint16_t n)
1133{
1134 // (saturates N to ledCount)
1137
1138 uint16_t y = 0;
1139 while (y * hardware::LampTy::maxWidth + hardware::LampTy::allResiduesY[y] <= n)
1140 y += 1;
1141
1142 if (y == 0)
1143 return {0, 0};
1144 y -= 1;
1145
1146 uint16_t x = n - y * hardware::LampTy::maxWidth - hardware::LampTy::allResiduesY[y];
1147 return {x, y};
1148}
1149
1155static constexpr HelixXYZTy strip_to_helix(int16_t n)
1156{
1158 return HelixXYZTy {0.0, 0.0, 0.0};
1159
1161}
1162
1168static constexpr float to_helix_z(const int16_t n)
1169{
1171}
1172
1178static constexpr HelixXYZTy strip_to_helix_unconstraint(const int16_t n)
1179{
1182 to_helix_z(n)};
1183}
1184
1189static constexpr bool is_led_index_valid(const int16_t n) { return n >= 0 and n < hardware::LampTy::ledCount; }
1190
1197static constexpr bool is_lamp_coordinate_out_of_bounds(const float angle_rad, const float z_mm)
1198{
1199 return not is_led_index_valid(to_led_index_no_bounds(angle_rad, z_mm));
1200}
1201
1208static constexpr uint16_t to_led_index(const float angle_rad, const float z_mm)
1209{
1210 constexpr uint16_t maxZCoordinate =
1212
1213 // snip Z per possible lines
1214 uint16_t zIndex = floor(-z_mm / hardware::LampTy::ledStripWidth_mm);
1215 if (zIndex < 0.0)
1216 zIndex = 0.0;
1217 if (zIndex > maxZCoordinate)
1218 zIndex = maxZCoordinate;
1219
1220 // indexing around the led turn
1221 const float angularPosition = wrap_angle(angle_rad) / c_TWO_PI * hardware::LampTy::maxWidthFloat;
1222
1223 // convert to led index (approx)
1224 int16_t ledIndex = round(angularPosition + zIndex * hardware::LampTy::maxWidthFloat);
1225 if (ledIndex < 0)
1226 ledIndex = round(angularPosition + (zIndex + 1) * hardware::LampTy::maxWidthFloat);
1227 if (ledIndex >= hardware::LampTy::ledCount)
1228 ledIndex = round(angularPosition + (zIndex - 1) * hardware::LampTy::maxWidthFloat);
1229
1230 if (ledIndex < 0)
1231 return 0;
1232 if (ledIndex >= hardware::LampTy::ledCount)
1233 return hardware::LampTy::ledCount - 1;
1234 return ledIndex;
1235}
1236
1243static constexpr int16_t to_led_index_no_bounds(const float angle_rad, const float z_mm)
1244{
1245 // snip Z per possible lines
1246 const int16_t zIndex = floor(-z_mm / hardware::LampTy::ledStripWidth_mm);
1247 // indexing around the led turn
1248 const float angularPosition = wrap_angle(angle_rad) / c_TWO_PI * hardware::LampTy::maxWidthFloat;
1249
1250 // convert to led index (approx)
1251 return round(angularPosition + zIndex * hardware::LampTy::maxWidthFloat);
1252}
1253
1254} // namespace lampda::modes
1255
1256#endif
Define assertions helpers.
Handle the output LED strip brightness.
protected inheritence to avoid uncontroled hardware calls
Definition: strip.h:46
BufferTy _buffers[stripNbBuffers]
buffers for computations
Definition: strip.h:432
void setBrightness(uint8_t b)
Brightness is an internal counter.
Definition: strip.h:110
void show_now()
Show the current data, independant of changes.
Definition: strip.h:176
COLOR _colors[LED_COUNT]
store the display colors, with no brightness scaling
Definition: strip.h:426
void begin()
Definition: strip.h:134
Given two points and an exponent, fit an exponential function.
Definition: curves.h:121
Given a set of points, will fit multiple linear segments to it.
Definition: curves.h:36
Manipulate color representations.
Compile definitions and sanity checks.
Contains shorthand macro definitions.
Define the lamps coordinates systems.
Define curves types, that can be sampled.
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:123
static uint32_t blend(uint32_t leftColor, uint32_t rightColor, uint16_t blend, bool b16=false)
blend to two colors
Definition: utils.hpp:95
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:88
@ 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:107
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:1208
static constexpr float to_helix_z(const int16_t n)
Convert a led index to an helix height coordinate.
Definition: lamp_type.hpp:1168
static constexpr uint16_t to_strip(uint16_t, uint16_t)
convert grid coordinates to strip index
Definition: lamp_type.hpp:1100
static constexpr XYTy strip_to_XY(uint16_t n)
convert strip index to grid coordinates
Definition: lamp_type.hpp:1132
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:1243
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:1197
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:1189
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:1178
static constexpr HelixXYZTy strip_to_helix(int16_t n)
convert strip index to 3D coordinates
Definition: lamp_type.hpp:1155
SoundStruct & get_sound_characteristics()
Compute and process sound data.
Definition: sound.cpp:168
void blip(const uint32_t timing)
short interruption of output voltage
Definition: output_power.cpp:39
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
void cancel_blip()
stop an ongoing blip
Definition: output_power.cpp:41
bool is_bliping()
indicates that the gate is in a blip
Definition: output_power.cpp:43
uint32_t time_ms(void)
Returns the number of milliseconds since the Arduino board began running the current program....
Definition: time.cpp:16
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).
Interface for the physical components of the microphone.
Interface of the indexable strip object. Only used for RGB lamp type.
Definition: lamp_type.hpp:51
float x
x 3D mm coordinates
Definition: lamp_type.hpp:52
float y
y 3D mm coordinates
Definition: lamp_type.hpp:53
float z
z 3D mm coordinates
Definition: lamp_type.hpp:54
Definition: lamp_type.hpp:40
uint16_t y
y 2D led grid coordinates
Definition: lamp_type.hpp:42
uint16_t x
x 2D led grid coordinates
Definition: lamp_type.hpp:41
Store a display config.
Definition: lamp_type.hpp:121
uint16_t skipFirstLedsForAmount
Skip the first N leds.
Definition: lamp_type.hpp:123
uint16_t skipFirstLedsForEffect
Skip duration.
Definition: lamp_type.hpp:122
Main interface between the user and the hardware of the lamp.
Definition: lamp_type.hpp:114
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:786
void align_internal_to_system_brightness()
Special call to update the internal brightness values to the system brightness.
Definition: lamp_type.hpp:627
void setColorsFromMixedBuffers(float phase)
Mix two colors from a buffer.
Definition: lamp_type.hpp:989
static XYTy LMBD_INLINE fromStripIndexToXY(uint16_t N)
(indexable) Given a LED index, return a corresponding X,Y value
Definition: lamp_type.hpp:928
brightness_t LMBD_INLINE getMaxBrightness() const
Return the actual allowed maximum brightness.
Definition: lamp_type.hpp:655
static constexpr float ledByMeter
number of led per meters of strip used
Definition: lamp_type.hpp:428
void LMBD_INLINE restoreBrightness()
Reset brightness to internal saved brightness, skip callbacks.
Definition: lamp_type.hpp:706
void LMBD_INLINE blur(uint8_t blurBy)
Blur currently displayed content by blurBy units /!\ Only applied along the strip,...
Definition: lamp_type.hpp:753
static constexpr uint16_t maxHeight
(indexable) Height of "pixel space" w/ lamp taken as a LED matrix
Definition: lamp_type.hpp:387
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:809
static constexpr float lampHeight_mm
Computation of the lamp height.
Definition: lamp_type.hpp:437
void LMBD_INLINE fill(uint32_t color, const BufferTy &shouldDisplay)
(indexable) Fill lamp with target color, with a mask
Definition: lamp_type.hpp:838
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:553
void LMBD_INLINE fill(const colors::PaletteTy &palette)
(indexable) Fill lamp with target palette
Definition: lamp_type.hpp:868
static constexpr float maxHeightFloat
Height as a precise floating point number, equal to stripYCoordinates.
Definition: lamp_type.hpp:390
volatile brightness_t temporary_brightness
Define a localy consistant temporary brightness.
Definition: lamp_type.hpp:1068
void LMBD_INLINE copyBuffer()
Copy a source buffer at srcBufIdx to another buffer at dstBufIdx.
Definition: lamp_type.hpp:948
static constexpr float lampBodyCircumpherence_mm
Computation of the lamp body circumpherence.
Definition: lamp_type.hpp:433
static constexpr float maxWidthFloat
Width as a precise floating point number, equal to stripXCoordinates.
Definition: lamp_type.hpp:369
BufferTy &LMBD_INLINE getTempBuffer()
Get a reference to the bufIdx temporary buffer.
Definition: lamp_type.hpp:935
static constexpr float ledStripWidth_mm
real size of the led strip in use
Definition: lamp_type.hpp:423
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:922
static constexpr float ledPerTurns
Computation of the led count per turns.
Definition: lamp_type.hpp:435
void LMBD_INLINE tempBrightness(const brightness_t brightness)
Temporarily set brightness, without affecting brightness navigation.
Definition: lamp_type.hpp:668
void setColorsFromBufferReversed(bool skipLastLine)
(indexable) Display bufIdx temporary buffer, but reversed
Definition: lamp_type.hpp:1012
void enforce_internal_brightness_limits()
Enforce the brightness limits, if getMaxBrightness changed. Will call setBrightness.
Definition: lamp_type.hpp:634
void LMBD_INLINE jumpBrightness(const brightness_t brightness)
Jump to brightness, affecting the next brightness navigation.
Definition: lamp_type.hpp:686
LampConfig config
store a display configuration
Definition: lamp_type.hpp:127
physical::microphone::SoundStruct &LMBD_INLINE get_sound_struct()
Return the an object containing sound analysis data.
Definition: lamp_type.hpp:1060
volatile const uint32_t tick
(physical) Tick number, ever-increasing every frameDurationMs
Definition: lamp_type.hpp:1084
static constexpr float ledSize_mm
Number of leds per one turn of led strip.
Definition: lamp_type.hpp:431
volatile const uint32_t now
(physical) The "now" on milliseconds, updated just before loop.
Definition: lamp_type.hpp:1075
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:916
void LMBD_INLINE setPixelColor(uint16_t n, uint32_t color)
(indexable) Set the n-th LED color
Definition: lamp_type.hpp:874
void LMBD_INLINE fillTempBuffer(const T &value)
Fill temporary buffer bufIdx with given value.
Definition: lamp_type.hpp:960
void LMBD_INLINE clear()
Clear lamp to a clean state.
Definition: lamp_type.hpp:486
uint32_t LMBD_INLINE getPixelColor(uint16_t n)
(indexable) Get the n-th LED color
Definition: lamp_type.hpp:894
static constexpr uint16_t maxOverflowHeight
Larger height, taken as the absolute maximum Y coordinate, overflowing.
Definition: lamp_type.hpp:393
void LMBD_INLINE blip(const uint32_t duration)
blip the power gate for set time
Definition: lamp_type.hpp:509
void setColorsFromBuffer()
(indexable) Display bufIdx temporary buffer as LED colors
Definition: lamp_type.hpp:969
volatile brightness_t saved_brightness
Define a localy consistant saved brightness. Should be similar.
Definition: lamp_type.hpp:1066
bool LMBD_INLINE is_bliping() const
return true if the output is in a blip state
Definition: lamp_type.hpp:531
static constexpr float ledStripLength_mm
Copy the led strip lenght.
Definition: lamp_type.hpp:425
static constexpr float _invShiftResidue
(while shifting every shiftPeriod, we have a residue accumulating)
Definition: lamp_type.hpp:402
static constexpr LMBD_INLINE uint16_t toLedCount(T scale)
(indexable) Return a led count in 0-ledCount scaled by scale
Definition: lamp_type.hpp:455
static constexpr float lampBodyRadius_mm
real radius of the lamp body
Definition: lamp_type.hpp:420
static constexpr LampTypes flavor
Which lamp flavor is currently used by the implementation?
Definition: lamp_type.hpp:336
static constexpr uint32_t frameDurationMs
Hardward try to call .loop() every frameDurationMs (12ms for 83.3fps)
Definition: lamp_type.hpp:339
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:845
static constexpr uint16_t maxWidth
(indexable) Width of "pixel space" w/ lamp taken as a LED matrix
Definition: lamp_type.hpp:366
brightness_t LMBD_INLINE getBrightness(const bool readPreviousBrightness=false)
Get brightness of the lamp.
Definition: lamp_type.hpp:694
void LMBD_INLINE fill(uint32_t color)
(indexable) Fill lamp with target color
Definition: lamp_type.hpp:832
static constexpr uint16_t maxOverflowWidth
Larger width, taken as the absolute maximum X coordinate on all rows.
Definition: lamp_type.hpp:372
void getColorsToBuffer()
(indexable) Copy all current LEDs color to bufIdx temp. buffer
Definition: lamp_type.hpp:1038
static constexpr uint16_t ledCount
(indexable) Count of indexable LEDs on the lamp
Definition: lamp_type.hpp:353
brightness_t LMBD_INLINE getSavedBrightness()
Alias for getBrightness(true)
Definition: lamp_type.hpp:703
static constexpr uint8_t nbBuffers
(indexable) Number of color buffers available for direct access
Definition: lamp_type.hpp:443
volatile const uint32_t raw_frame_count
(physical) Raw frame count, incremented at an undefined rate
Definition: lamp_type.hpp:1092
static constexpr uint32_t brightnessDurationMs
Limit mode-requested brightness changes to one every few frames.
Definition: lamp_type.hpp:347
void LMBD_INLINE cancel_blip() const
Cancel the ongoing blip, if any.
Definition: lamp_type.hpp:526
void LMBD_INLINE fadeToBlackBy(uint8_t fadeBy)
Fade currently displayed content by fadeBy units.
Definition: lamp_type.hpp:723
Handle the analysis of a sound sample. This structure handled the FastFourrier analysis of a sound sa...
Definition: sound.h:33
Define the system hardware constants.
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.
Convertion header to use the print and debug functions from C code.
Define useful functions.