85 bool update(uint32_t syncTime = millis())
87 _currentTime = syncTime;
89 if (!_isRunning || _isPaused || !_currentFunc)
92 if ((this->*_currentFunc)())
97 _isLoopingNow =
false;
100 _isLoopingNow =
true;
106 _isLoopingNow =
false;
108 _currentFunc =
nullptr;
140 _skipPending =
false;
141 _currentFunc =
nullptr;
142 _animLogicSet =
false;
163 _animRenderDirIsReversed = newDirection;
171 _animRenderDirIsReversed = !_animRenderDirIsReversed;
179 _animRenderDirIsReversed = !_AnimInitDirIsReversed;
187 _animRenderDirIsReversed = _AnimInitDirIsReversed;
198 if (_isNonInvertingLogicAnim)
200 _animRenderLogicIsInverted = newLogic;
201 _animLogicSet =
true;
212 if (_isNonInvertingLogicAnim)
214 _animRenderLogicIsInverted = !_animRenderLogicIsInverted;
215 _animLogicSet =
true;
226 if (_isNonInvertingLogicAnim)
228 _animRenderLogicIsInverted = !_AnimInitLogicIsInverted;
229 _animLogicSet =
true;
240 if (_isNonInvertingLogicAnim)
242 _animRenderLogicIsInverted = _AnimInitLogicIsInverted;
243 _animLogicSet =
false;
250 _emittingBlocksEnabled =
false;
257 _emittingBlocksEnabled =
true;
273 if (_skipPending ==
true)
274 _skipPending =
false;
279 _isLoopingNow =
false;
289 if (_AnimInitLogicIsInverted != _animRenderLogicIsInverted)
301 if (_AnimInitDirIsReversed != _animRenderDirIsReversed)
322 _currentFunc = &SBK_BarMeterAnimations::_setAllOn;
333 _currentFunc = &SBK_BarMeterAnimations::_setAllOff;
348 _isNonInvertingLogicAnim =
false;
349 _animRenderDirIsReversed =
false;
350 _AnimInitLogicIsInverted =
false;
354 _mapMinMaxTracker(minPercent, maxPercent, 0, _segsNum - 1);
356 uint8_t steps = max(1, _maxTracker - _minTracker + 1);
357 _updateIntv1 = max(5, duration / steps);
358 _currentFunc = &SBK_BarMeterAnimations::_fillOrEmpty;
371 _isNonInvertingLogicAnim =
false;
372 _animRenderDirIsReversed =
false;
373 _AnimInitLogicIsInverted =
false;
375 _sigPtr2 = maxPercentPtr;
376 _sigPtr1 = minPercentPtr;
377 _mapMinMaxTrackerFromPtr(_sigPtr1, _sigPtr2, 0, _segsNum - 1);
379 _updateIntv1 = max(5, updateIntv);
380 _currentFunc = &SBK_BarMeterAnimations::_fillOrEmpty;
393 _isNonInvertingLogicAnim =
false;
394 _animRenderDirIsReversed =
false;
395 _AnimInitLogicIsInverted =
false;
399 _mapMinMaxTracker(minPercent, maxPercent, 0, _segsNum - 1);
401 _updateIntv1 = max(5, updateIntv);
402 _currentFunc = &SBK_BarMeterAnimations::_fillOrEmpty;
415 _isNonInvertingLogicAnim =
false;
416 _animRenderDirIsReversed =
true;
417 _AnimInitLogicIsInverted =
false;
421 _mapMinMaxTracker(minPercent, maxPercent, 0, _segsNum - 1);
423 uint8_t steps = max(1, _maxTracker - _minTracker + 1);
424 _updateIntv1 = max(5, duration / steps);
425 _currentFunc = &SBK_BarMeterAnimations::_fillOrEmpty;
438 _isNonInvertingLogicAnim =
false;
439 _animRenderDirIsReversed =
true;
440 _AnimInitLogicIsInverted =
false;
442 _sigPtr2 = maxPercentPtr;
443 _sigPtr1 = minPercentPtr;
444 _mapMinMaxTrackerFromPtr(_sigPtr1, _sigPtr2, 0, _segsNum - 1);
446 uint8_t steps = max(1, _maxTracker - _minTracker + 1);
447 _updateIntv1 = max(5, updateIntv);
448 _currentFunc = &SBK_BarMeterAnimations::_fillOrEmpty;
461 _isNonInvertingLogicAnim =
false;
462 _animRenderDirIsReversed =
true;
463 _AnimInitLogicIsInverted =
false;
467 _mapMinMaxTracker(minPercent, maxPercent, 0, _segsNum - 1);
469 _updateIntv1 = max(5, updateIntv);
470 _currentFunc = &SBK_BarMeterAnimations::_fillOrEmpty;
483 _isNonInvertingLogicAnim =
false;
484 _animRenderDirIsReversed =
false;
485 _AnimInitLogicIsInverted =
true;
489 _mapMinMaxTracker(minPercent, maxPercent, 0, _segsNum - 1);
491 uint8_t steps = max(1, _maxTracker - _minTracker + 1);
492 return emptyDownIntv(duration / steps, maxPercent, minPercent);
504 _isNonInvertingLogicAnim =
false;
505 _animRenderDirIsReversed =
false;
506 _AnimInitLogicIsInverted =
true;
508 _sigPtr2 = maxPercentPtr;
509 _sigPtr1 = minPercentPtr;
510 _mapMinMaxTrackerFromPtr(_sigPtr1, _sigPtr2, 0, _segsNum - 1);
512 _updateIntv1 = max(5, updateIntv);
513 _currentFunc = &SBK_BarMeterAnimations::_fillOrEmpty;
526 _isNonInvertingLogicAnim =
false;
527 _animRenderDirIsReversed =
false;
528 _AnimInitLogicIsInverted =
true;
532 _mapMinMaxTracker(minPercent, maxPercent, 0, _segsNum - 1);
534 _updateIntv1 = max(5, updateIntv);
535 _currentFunc = &SBK_BarMeterAnimations::_fillOrEmpty;
548 _isNonInvertingLogicAnim =
false;
549 _animRenderDirIsReversed =
true;
550 _AnimInitLogicIsInverted =
true;
554 _mapMinMaxTracker(minPercent, maxPercent, 0, _segsNum - 1);
556 uint8_t steps = max(1, _maxTracker - _minTracker + 1);
557 _updateIntv1 = max(5, duration / steps);
558 _currentFunc = &SBK_BarMeterAnimations::_fillOrEmpty;
571 _isNonInvertingLogicAnim =
false;
572 _animRenderDirIsReversed =
true;
573 _AnimInitLogicIsInverted =
true;
575 _sigPtr2 = maxPercentPtr;
576 _sigPtr1 = minPercentPtr;
577 _mapMinMaxTrackerFromPtr(_sigPtr1, _sigPtr2, 0, _segsNum - 1);
579 _updateIntv1 = max(5, updateIntv);
580 _currentFunc = &SBK_BarMeterAnimations::_fillOrEmpty;
593 _isNonInvertingLogicAnim =
false;
594 _animRenderDirIsReversed =
true;
595 _AnimInitLogicIsInverted =
true;
599 _mapMinMaxTracker(minPercent, maxPercent, 0, _segsNum - 1);
601 _updateIntv1 = max(5, updateIntv);
602 _currentFunc = &SBK_BarMeterAnimations::_fillOrEmpty;
616 _isNonInvertingLogicAnim =
true;
617 _animRenderDirIsReversed =
false;
621 _mapMinMaxTracker(minPercent, maxPercent, 0, _segsNum - 1);
622 uint8_t steps = max(1, _maxTracker - _minTracker + 1);
623 uint16_t emptyIntv = fillIntv;
626 fillIntv = round(max(5, duration) / (2 * steps));
627 emptyIntv = fillIntv;
631 emptyIntv = round(max(5, duration - fillIntv * steps) / (steps));
633 _updateIntv1 = fillIntv;
634 _updateIntv2 = _updateIntv1;
635 _updateIntv3 = emptyIntv;
638 _currentFunc = &SBK_BarMeterAnimations::_bounceFill;
652 _isNonInvertingLogicAnim =
true;
653 _animRenderDirIsReversed =
false;
654 _sigPtr2 = maxPercentPtr;
655 _sigPtr1 = minPercentPtr;
657 _mapMinMaxTrackerFromPtr(_sigPtr1, _sigPtr2, 0, _segsNum - 1);
658 _updateIntv1 = max(5, fillIntv);
659 _updateIntv2 = _updateIntv1;
660 _updateIntv3 = max(5, emptyIntv);
663 _currentFunc = &SBK_BarMeterAnimations::_bounceFill;
677 _isNonInvertingLogicAnim =
true;
678 _animRenderDirIsReversed =
false;
679 _AnimInitLogicIsInverted =
false;
683 _mapMinMaxTracker(minPercent, maxPercent, 0, _segsNum - 1);
684 _updateIntv1 = max(5, fillIntv);
685 _updateIntv2 = _updateIntv1;
686 _updateIntv3 = max(5, emptyIntv);
689 _currentFunc = &SBK_BarMeterAnimations::_bounceFill;
703 _isNonInvertingLogicAnim =
true;
704 _animRenderDirIsReversed =
true;
705 _AnimInitLogicIsInverted =
false;
709 _mapMinMaxTracker(minPercent, maxPercent, 0, _segsNum - 1);
710 uint8_t steps = max(1, _maxTracker - _minTracker + 1);
711 uint16_t emptyIntv = fillIntv;
714 fillIntv = round(max(5, duration) / (2 * steps));
715 emptyIntv = fillIntv;
719 emptyIntv = round(max(5, duration - fillIntv * steps) / (steps));
721 _updateIntv1 = fillIntv;
722 _updateIntv2 = _updateIntv1;
723 _updateIntv3 = emptyIntv;
726 _currentFunc = &SBK_BarMeterAnimations::_bounceFill;
740 _isNonInvertingLogicAnim =
true;
741 _animRenderDirIsReversed =
true;
742 _AnimInitLogicIsInverted =
false;
743 _sigPtr2 = maxPercentPtr;
744 _sigPtr1 = minPercentPtr;
746 _mapMinMaxTrackerFromPtr(_sigPtr1, _sigPtr2, 0, _segsNum - 1);
747 _updateIntv1 = max(5, fillIntv);
748 _updateIntv2 = _updateIntv1;
749 _updateIntv3 = max(5, emptyIntv);
752 _currentFunc = &SBK_BarMeterAnimations::_bounceFill;
766 _isNonInvertingLogicAnim =
true;
767 _animRenderDirIsReversed =
true;
768 _AnimInitLogicIsInverted =
false;
772 _mapMinMaxTracker(minPercent, maxPercent, 0, _segsNum - 1);
773 _updateIntv1 = max(5, fillIntv);
774 _updateIntv2 = _updateIntv1;
775 _updateIntv3 = max(5, emptyIntv);
778 _currentFunc = &SBK_BarMeterAnimations::_bounceFill;
792 _isNonInvertingLogicAnim =
true;
793 _AnimInitLogicIsInverted =
false;
794 _animRenderDirIsReversed =
false;
795 _mirrorHalfRangeDir =
false;
799 _mapMinMaxTracker(minPercent, maxPercent, (_segsNum / 2) - 1, 0);
800 uint8_t steps = max(1, _maxTracker - _minTracker + 1);
801 uint16_t emptyIntv = fillIntv;
804 fillIntv = round(max(5, duration) / (2 * steps));
805 emptyIntv = fillIntv;
809 emptyIntv = round(max(5, duration - fillIntv * steps) / (steps));
811 _updateIntv1 = fillIntv;
812 _updateIntv2 = _updateIntv1;
813 _updateIntv3 = emptyIntv;
816 _currentFunc = &SBK_BarMeterAnimations::_bounceFillHalfRangeMirrorCenter;
830 _isNonInvertingLogicAnim =
true;
831 _AnimInitLogicIsInverted =
false;
832 _animRenderDirIsReversed =
false;
833 _mirrorHalfRangeDir =
false;
834 _sigPtr2 = maxPercentPtr;
835 _sigPtr1 = minPercentPtr;
837 _mapMinMaxTrackerFromPtr(minPercentPtr, maxPercentPtr, (_segsNum / 2) - 1, 0);
838 _updateIntv1 = fillIntv;
839 _updateIntv2 = _updateIntv1;
840 _updateIntv3 = emptyIntv;
843 _currentFunc = &SBK_BarMeterAnimations::_bounceFillHalfRangeMirrorCenter;
857 _isNonInvertingLogicAnim =
true;
858 _AnimInitLogicIsInverted =
false;
859 _animRenderDirIsReversed =
false;
860 _mirrorHalfRangeDir =
false;
864 _mapMinMaxTracker(minPercent, maxPercent, (_segsNum / 2) - 1, 0);
865 _updateIntv1 = fillIntv;
866 _updateIntv2 = _updateIntv1;
867 _updateIntv3 = emptyIntv;
870 _currentFunc = &SBK_BarMeterAnimations::_bounceFillHalfRangeMirrorCenter;
884 _isNonInvertingLogicAnim =
true;
885 _AnimInitLogicIsInverted =
false;
886 _animRenderDirIsReversed =
false;
887 _mirrorHalfRangeDir =
true;
891 _mapMinMaxTracker(minPercent, maxPercent, (_segsNum / 2) - 1, 0);
892 uint8_t steps = max(1, _maxTracker - _minTracker + 1);
893 uint16_t emptyIntv = fillIntv;
896 fillIntv = round(max(5, duration) / (2 * steps));
897 emptyIntv = fillIntv;
901 emptyIntv = round(max(5, duration - fillIntv * steps) / (steps));
903 _updateIntv1 = fillIntv;
904 _updateIntv2 = _updateIntv1;
905 _updateIntv3 = emptyIntv;
908 _currentFunc = &SBK_BarMeterAnimations::_bounceFillHalfRangeMirrorCenter;
922 _isNonInvertingLogicAnim =
true;
923 _AnimInitLogicIsInverted =
false;
924 _animRenderDirIsReversed =
false;
925 _mirrorHalfRangeDir =
true;
926 _sigPtr2 = maxPercentPtr;
927 _sigPtr1 = minPercentPtr;
929 _mapMinMaxTrackerFromPtr(minPercentPtr, maxPercentPtr, (_segsNum / 2) - 1, 0);
930 _updateIntv1 = fillIntv;
931 _updateIntv2 = _updateIntv1;
932 _updateIntv3 = emptyIntv;
935 _currentFunc = &SBK_BarMeterAnimations::_bounceFillHalfRangeMirrorCenter;
949 _isNonInvertingLogicAnim =
true;
950 _AnimInitLogicIsInverted =
false;
951 _animRenderDirIsReversed =
false;
952 _mirrorHalfRangeDir =
true;
956 _mapMinMaxTracker(minPercent, maxPercent, (_segsNum / 2) - 1, 0);
957 _updateIntv1 = fillIntv;
958 _updateIntv2 = _updateIntv1;
959 _updateIntv3 = emptyIntv;
962 _currentFunc = &SBK_BarMeterAnimations::_bounceFillHalfRangeMirrorCenter;
974 _param2 = min(35 * (_segsNum - 1) / 100, 255);
975 _param2 = min(67 * (_segsNum - 1) / 100, 255);
978 _isNonInvertingLogicAnim =
true;
979 _AnimInitLogicIsInverted =
false;
980 _animRenderDirIsReversed =
false;
983 _currentFunc = &SBK_BarMeterAnimations::_beatPulse;
995 _param1 = max(1, bpm);
996 _param2 = min(35 * (_segsNum - 1) / 100, 255);
997 _param3 = min(67 * (_segsNum - 1) / 100, 255);
1001 _isNonInvertingLogicAnim =
true;
1002 _AnimInitLogicIsInverted =
false;
1003 _animRenderDirIsReversed =
false;
1006 _currentFunc = &SBK_BarMeterAnimations::_beatPulse;
1021 _updateIntv1 = max(5, intv);
1022 _param1 = blockLength;
1023 _param2 = blockSpacing;
1024 _param3 = numBlocks;
1025 _param4 = ((_segsNum / 2) / (blockLength + blockSpacing)) + 2;
1026 _param4 = constrain(_param4, 2, 32);
1028 _isNonInvertingLogicAnim =
false;
1029 _animRenderDirIsReversed =
false;
1030 _AnimInitLogicIsInverted =
true;
1032 _currentFunc = &SBK_BarMeterAnimations::_mirrorBlocks;
1047 _updateIntv1 = max(5, intv);
1048 _param1 = blockLength;
1049 _param2 = blockSpacing;
1050 _param3 = numBlocks;
1051 _param4 = ((_segsNum / 2) / (blockLength + blockSpacing)) + 2;
1052 _param4 = constrain(_param4, 2, 32);
1054 _isNonInvertingLogicAnim =
false;
1055 _animRenderDirIsReversed =
false;
1056 _AnimInitLogicIsInverted =
false;
1058 _currentFunc = &SBK_BarMeterAnimations::_mirrorBlocks;
1072 _updateIntv1 = max(5, intv);
1073 _param1 = blockLength;
1074 _param2 = blockSpacing;
1075 _param3 = numBlocks;
1076 _param4 = (_segsNum / (blockLength + blockSpacing)) + 2;
1077 _param4 = constrain(_param4, 2, 64);
1079 _isNonInvertingLogicAnim =
false;
1080 _animRenderDirIsReversed =
false;
1081 _AnimInitLogicIsInverted =
false;
1083 _currentFunc = &SBK_BarMeterAnimations::_scrollingBlocks;
1097 _updateIntv1 = max(5, intv);
1098 _param1 = blockLength;
1099 _param2 = blockSpacing;
1100 _param3 = numBlocks;
1101 _param4 = (_segsNum / (blockLength + blockSpacing)) + 2;
1102 _param4 = constrain(_param4, 2, 64);
1104 _isNonInvertingLogicAnim =
false;
1105 _animRenderDirIsReversed =
false;
1106 _AnimInitLogicIsInverted =
true;
1108 _currentFunc = &SBK_BarMeterAnimations::_scrollingBlocks;
1121 _isNonInvertingLogicAnim =
false;
1122 _animRenderDirIsReversed =
false;
1123 _AnimInitLogicIsInverted =
false;
1124 _updateIntv1 = max(5, intv);
1125 _param1 = blockLength;
1126 _param2 = blockSpacing;
1130 _emittingBlocksEnabled =
true;
1132 _currentFunc = &SBK_BarMeterAnimations::_stackingBlocks;
1145 _isNonInvertingLogicAnim =
false;
1146 _animRenderDirIsReversed =
false;
1147 _AnimInitLogicIsInverted =
true;
1148 _updateIntv1 = max(5, intv);
1149 _param1 = blockLength;
1150 _param2 = blockSpacing;
1154 _emittingBlocksEnabled =
true;
1156 _currentFunc = &SBK_BarMeterAnimations::_stackingBlocks;
1169 _isNonInvertingLogicAnim =
false;
1170 _animRenderDirIsReversed =
true;
1171 _AnimInitLogicIsInverted =
false;
1172 _updateIntv1 = max(5, intv);
1173 _param1 = blockLength;
1174 _param2 = blockSpacing;
1178 _emittingBlocksEnabled =
true;
1180 _currentFunc = &SBK_BarMeterAnimations::_stackingBlocks;
1193 _isNonInvertingLogicAnim =
false;
1194 _animRenderDirIsReversed =
true;
1195 _AnimInitLogicIsInverted =
true;
1196 _updateIntv1 = max(5, intv);
1197 _param1 = blockLength;
1198 _param2 = blockSpacing;
1202 _emittingBlocksEnabled =
true;
1204 _currentFunc = &SBK_BarMeterAnimations::_stackingBlocks;
1222 _updateIntv1 = max(10, updateIntv);
1223 _minMap = max(0, minMap);
1224 _maxMap = max(0, maxMap);
1225 _correctSwapOrEqualMinMax(_minMap, _maxMap);
1226 _param1 = constrain(smoothingFactor, 0, 100);
1227 _updateIntv2 = samplingIntv;
1229 _isNonInvertingLogicAnim =
true;
1230 _animRenderDirIsReversed =
false;
1231 _AnimInitLogicIsInverted =
false;
1234 _currentFunc = &SBK_BarMeterAnimations::_followSignalSmooth;
1251 _updateIntv1 = max(10, updateIntv);
1252 _minMap = max(0, minMap);
1253 _maxMap = max(0, maxMap);
1254 _correctSwapOrEqualMinMax(_minMap, _maxMap);
1255 _param1 = constrain(smoothingFactor, 0, 100);
1256 _updateIntv2 = samplingIntv;
1258 _isNonInvertingLogicAnim =
true;
1259 _animRenderDirIsReversed =
false;
1260 _AnimInitLogicIsInverted =
false;
1263 _currentFunc = &SBK_BarMeterAnimations::_followSignalWithPointer;
1282 _updateIntv1 = max(10, updateIntv);
1283 _sigPtr2 = sig2Ptr ? sig2Ptr : sig1Ptr;
1284 _minMap = max(0, minMap);
1285 _maxMap = max(0, maxMap);
1286 _correctSwapOrEqualMinMax(_minMap, _maxMap);
1287 _param1 = constrain(smoothingFactor, 0, 100);
1288 _updateIntv2 = samplingIntv;
1290 _isNonInvertingLogicAnim =
false;
1291 _animRenderDirIsReversed =
false;
1292 _AnimInitLogicIsInverted =
false;
1296 _currentFunc = &SBK_BarMeterAnimations::_followDualSignalCenterMirror;
1318 _updateIntv1 = max(10, updateIntv);
1319 _sigPtr2 = sig2Ptr ? sig2Ptr : sig1Ptr;
1320 _minMap = max(0, minMap);
1321 _maxMap = max(0, maxMap);
1322 _correctSwapOrEqualMinMax(_minMap, _maxMap);
1323 _param1 = constrain(smoothingFactor, 0, 100);
1324 _updateIntv2 = samplingIntv;
1326 _isNonInvertingLogicAnim =
false;
1327 _animRenderDirIsReversed =
true;
1328 _AnimInitLogicIsInverted =
false;
1332 _currentFunc = &SBK_BarMeterAnimations::_followDualSignalCenterMirror;
1355 _updateIntv3 = max(20, peakHoldTime);
1356 _updateIntv1 = max(10, updateIntv);
1357 _minMap = max(0, minMap);
1358 _maxMap = max(0, maxMap);
1359 _correctSwapOrEqualMinMax(_minMap, _maxMap);
1360 _param1 = constrain(smoothingFactor, 0, 100);
1361 _updateIntv2 = samplingIntv;
1363 _isNonInvertingLogicAnim =
true;
1364 _animRenderDirIsReversed =
false;
1365 _AnimInitLogicIsInverted =
false;
1368 _currentFunc = &SBK_BarMeterAnimations::_followSignalFloatingPeak;
1379 _updateIntv1 = interval;
1381 _isNonInvertingLogicAnim =
false;
1382 _animRenderDirIsReversed =
false;
1383 _AnimInitLogicIsInverted =
false;
1385 _currentFunc = &SBK_BarMeterAnimations::_randomPixelUpdater;
1397 _updateIntv1 = interval;
1399 _isNonInvertingLogicAnim =
false;
1400 _animRenderDirIsReversed =
false;
1401 _AnimInitLogicIsInverted =
true;
1403 _currentFunc = &SBK_BarMeterAnimations::_randomPixelUpdater;
1409 BarMeterT &_barMeter;
1410 uint8_t _segsNum = 0;
1414 AnimUpdateFn _currentFunc =
nullptr;
1418 bool _isRunning =
false;
1419 bool _isPaused =
false;
1421 bool _isLoopingNow =
false;
1422 bool _AnimInitLogicIsInverted =
false;
1423 bool _animRenderLogicIsInverted =
false;
1424 bool _prevAnimRenderLogic =
false;
1425 bool _isNonInvertingLogicAnim =
false;
1426 bool _mirrorHalfRangeDir =
false;
1427 bool _animLogicSet =
false;
1428 bool _skipPending =
false;
1429 bool _animRenderDirIsReversed =
false;
1430 bool _AnimInitDirIsReversed =
false;
1431 bool _animDirSet =
false;
1432 bool _usePtr =
false;
1433 bool _emittingBlocksEnabled =
true;
1436 uint32_t _currentTime = 0;
1437 uint32_t _lastUpdate1 = 0, _lastUpdate2 = 0, _lastUpdate3 = 0;
1440 uint16_t _updateIntv1 = 10, _updateIntv2 = 10, _updateIntv3 = 10;
1443 uint8_t _sequenceState = 0;
1444 int8_t _ledTracker1 = 0, _ledTracker2 = 0, _ledTracker3 = 0;
1445 int8_t _minTracker = 0, _maxTracker = 1;
1446 uint8_t _param1 = 0, _param2 = 0, _param3 = 0, _param4 = 0, _param5 = 0;
1447 uint16_t _smoothedValue1 = 0, _smoothedValue2 = 0;
1448 uint16_t _minMap = 0, _maxMap = 1023;
1449 uint8_t _counter1 = 0, _counter2 = 0;
1451 const uint16_t *_sigPtr1 =
nullptr, *_sigPtr2 =
nullptr;
1455 Block() : position(-1), active(
false) {}
1459 Block *_blocks =
nullptr;
1462 static inline void _normalizePercentRange(uint8_t &minP, uint8_t &maxP)
1464 minP = constrain(minP, 0, 100);
1465 maxP = constrain(maxP, 0, 100);
1480 inline void _mapMinMaxTrackerFromPtr(uint16_t *minPercPtr, uint16_t *maxPercPtr, int8_t minR, uint8_t maxR)
1484 uint8_t minP = minPercPtr ? *minPercPtr : 0;
1485 uint8_t maxP = maxPercPtr ? *maxPercPtr : 100;
1486 _normalizePercentRange(minP, maxP);
1487 _minTracker = map(minP, 0, 100, minR, maxR);
1488 _maxTracker = map(maxP, 0, 100, minR, maxR);
1490 inline void _mapMinMaxTracker(uint8_t minP, uint8_t maxP, uint8_t minR, uint8_t maxR)
1492 _normalizePercentRange(minP, maxP);
1493 _minTracker = map(minP, 0, 100, minR, maxR);
1494 _maxTracker = map(maxP, 0, 100, minR, maxR);
1496 inline uint8_t _corrPixelToDir(uint8_t pixel)
1498 return _animRenderDirIsReversed ? (_segsNum - 1) - pixel : pixel;
1500 inline uint8_t _corrPixelToDirForHalfRange(uint8_t pixel)
1502 if (!_mirrorHalfRangeDir)
1505 const uint8_t half = _segsNum / 2;
1506 return abs((half - 1) - pixel);
1508 static inline void _correctSwapOrEqualMinMax(uint16_t &minVal, uint16_t &maxVal)
1510 if (minVal > maxVal)
1512 uint16_t temp = maxVal;
1516 if (minVal == maxVal)
1517 if (maxVal < 65, 535)
1518 maxVal = minVal + 1;
1522 static inline uint8_t _getMappedSignal(uint16_t sig, uint16_t minM, uint16_t maxM, uint8_t minR, uint8_t maxR)
1524 uint8_t mapped = map(sig, minM, maxM, minR, maxR);
1525 return constrain(mapped, minR, maxR);
1533 for (uint8_t i = 0; i < _segsNum; i++)
1534 _barMeter.setPixel(i,
true);
1546 _mapMinMaxTrackerFromPtr(_sigPtr1, _sigPtr2, 0, _segsNum - 1);
1553 _prevAnimRenderLogic = _animRenderLogicIsInverted = _AnimInitLogicIsInverted;
1556 if (_animRenderLogicIsInverted)
1558 _ledTracker1 = _maxTracker;
1559 for (uint8_t i = 0; i < _segsNum; ++i)
1561 if (i <= _maxTracker)
1562 _barMeter.setPixel(_corrPixelToDir(i),
true);
1564 _barMeter.setPixel(_corrPixelToDir(i),
false);
1569 _ledTracker1 = _minTracker;
1570 for (uint8_t i = 0; i < _segsNum; ++i)
1572 if (i <= _minTracker)
1573 _barMeter.setPixel(_corrPixelToDir(i),
true);
1575 _barMeter.setPixel(_corrPixelToDir(i),
false);
1581 if (_animRenderLogicIsInverted != _prevAnimRenderLogic)
1583 _prevAnimRenderLogic = _animRenderLogicIsInverted;
1586 if (_animRenderLogicIsInverted && _ledTracker1 > _maxTracker)
1587 _ledTracker1 = _maxTracker;
1590 if (!_animRenderLogicIsInverted && _ledTracker1 < _minTracker)
1591 _ledTracker1 = _minTracker;
1594 if (_currentTime - _lastUpdate1 >= _updateIntv1)
1596 _lastUpdate1 = _currentTime;
1598 if (_animRenderLogicIsInverted)
1600 if (_ledTracker1 >= _minTracker && _ledTracker1 >= _minTracker)
1602 _barMeter.setPixel(_corrPixelToDir(_ledTracker1),
false);
1610 if (_ledTracker1 <= _maxTracker && _ledTracker1 < _segsNum)
1612 _barMeter.setPixel(_corrPixelToDir(_ledTracker1),
true);
1624 switch (_sequenceState)
1628 _skipPending =
false;
1631 _animRenderLogicIsInverted = !_AnimInitLogicIsInverted;
1633 _updateIntv1 = _updateIntv3;
1639 _skipPending =
true;
1642 _animRenderLogicIsInverted = _AnimInitLogicIsInverted;
1644 _updateIntv1 = _updateIntv2;
1653 bool _fillFromOrEmptyToCenter()
1655 const uint8_t center = _segsNum / 2;
1656 _mapMinMaxTrackerFromPtr(_sigPtr1, _sigPtr2, center - 1, 0);
1663 _prevAnimRenderLogic = _animRenderLogicIsInverted = _AnimInitLogicIsInverted;
1665 if (_animRenderLogicIsInverted)
1667 _ledTracker1 = _maxTracker;
1670 for (uint8_t i = 0; i < center; ++i)
1672 if (i >= _maxTracker)
1674 _barMeter.setPixel(_corrPixelToDirForHalfRange(i),
true);
1675 _barMeter.setPixel((_segsNum - 1) - _corrPixelToDirForHalfRange(i),
true);
1679 _barMeter.setPixel(_corrPixelToDirForHalfRange(i),
false);
1680 _barMeter.setPixel((_segsNum - 1) - _corrPixelToDirForHalfRange(i),
false);
1687 _ledTracker1 = _minTracker;
1690 for (uint8_t i = 0; i < center; ++i)
1692 if (i > _minTracker)
1694 _barMeter.setPixel(_corrPixelToDirForHalfRange(i),
true);
1695 _barMeter.setPixel((_segsNum - 1) - _corrPixelToDirForHalfRange(i),
true);
1699 _barMeter.setPixel(_corrPixelToDirForHalfRange(i),
false);
1700 _barMeter.setPixel((_segsNum - 1) - _corrPixelToDirForHalfRange(i),
false);
1707 if (_currentTime - _lastUpdate1 >= _updateIntv1)
1709 _lastUpdate1 = _currentTime;
1710 if (!_animRenderLogicIsInverted)
1712 if (_ledTracker1 >= _maxTracker && _ledTracker1 >= 0)
1714 _barMeter.setPixel(_corrPixelToDirForHalfRange(_ledTracker1),
true);
1715 _barMeter.setPixel((_segsNum - 1) - _corrPixelToDirForHalfRange(_ledTracker1),
true);
1723 if (_ledTracker1 <= _minTracker && _ledTracker1 < center)
1725 _barMeter.setPixel(_corrPixelToDirForHalfRange(_ledTracker1),
false);
1726 _barMeter.setPixel((_segsNum - 1) - _corrPixelToDirForHalfRange(_ledTracker1),
false);
1737 bool _bounceFillHalfRangeMirrorCenter()
1739 switch (_sequenceState)
1743 _skipPending =
true;
1744 if (_fillFromOrEmptyToCenter())
1746 _animRenderLogicIsInverted = !_AnimInitLogicIsInverted;
1747 _updateIntv1 = _updateIntv3;
1754 _skipPending =
false;
1755 if (_fillFromOrEmptyToCenter())
1757 _animRenderLogicIsInverted = _AnimInitLogicIsInverted;
1758 _updateIntv1 = _updateIntv2;
1769#define MIN_BASE_LEVEL _param2
1770#define MIN_PEAK_LEVEL _param3
1771#define PEAK_HOLD_TIME _param4
1772#define bpmPtr _sigPtr1
1773#define currentLevel _ledTracker1
1774#define peakLevel _ledTracker2
1775#define beat _updateIntv1
1776#define lastBeat _lastUpdate1
1777#define lastRandomUpdate _lastUpdate2
1778#define prevPeakUpdate _lastUpdate3
1781 static int8_t randomOffset;
1782 static bool isPeak =
false;
1789 _prevAnimRenderLogic = _animRenderLogicIsInverted = _AnimInitLogicIsInverted;
1792 currentLevel = MIN_BASE_LEVEL;
1793 peakLevel = MIN_PEAK_LEVEL;
1799 bpm = bpmPtr ? max(1, *bpmPtr) : 116;
1804 if (_currentTime - lastBeat >= beat)
1806 lastBeat = _currentTime;
1811 if (isPeak && currentLevel <= MIN_PEAK_LEVEL)
1813 currentLevel += random(3, 5);
1815 else if (!isPeak && currentLevel >= MIN_BASE_LEVEL)
1817 currentLevel -= random(0, 4);
1821 if (_currentTime - lastRandomUpdate >= uint16_t(random(50, 300)))
1823 lastRandomUpdate = _currentTime;
1824 randomOffset = random(-4, 4);
1827 uint8_t finalLevel = currentLevel + randomOffset;
1828 finalLevel = constrain(finalLevel, 0, _segsNum);
1829 if (finalLevel > _segsNum)
1830 finalLevel = _segsNum;
1835 if (finalLevel > peakLevel)
1837 peakLevel = min(finalLevel, _segsNum - 1);
1838 prevPeakUpdate = _currentTime;
1840 else if (_currentTime - prevPeakUpdate >= PEAK_HOLD_TIME && peakLevel > finalLevel)
1843 prevPeakUpdate = _currentTime;
1847 for (uint8_t i = 0; i < _segsNum; i++)
1849 _barMeter.setPixel(_corrPixelToDir(i), (i < finalLevel));
1853 if (peakLevel < _segsNum)
1855 _barMeter.setPixel(_corrPixelToDir(peakLevel),
true);
1860#undef MIN_BASE_LEVEL
1861#undef MIN_PEAK_LEVEL
1862#undef PEAK_HOLD_TIME
1868#undef lastRandomUpdate
1869#undef prevPeakUpdate
1871#define blockLength _param1
1872#define blockSpacing _param2
1873#define requestedNumBlocks _param3
1874#define maxBlocks _param4
1875#define emitIndex _param5
1876#define emittedBlocksCount _counter1
1877#define emitCooldown _counter2
1878 void _emitBlock(int8_t pos)
1880 if (!_blocks || maxBlocks < 1)
1883 if (emitCooldown > 0)
1889 if (requestedNumBlocks > 0 && emittedBlocksCount >= requestedNumBlocks)
1892 for (uint8_t i = 0; i < maxBlocks; ++i)
1894 uint8_t idx = (emitIndex + i) % maxBlocks;
1895 Block &b = _blocks[idx];
1901 emittedBlocksCount++;
1903 emitCooldown = blockLength + blockSpacing - 1;
1904 emitIndex = (emitIndex + 1) % maxBlocks;
1910 static inline int8_t _calculateSwtichPostion(int8_t pos, uint8_t bockL, uint8_t range)
1913 return (range - 1) - pos + (bockL - 1);
1916 int8_t _calculateSwitchedEmitTickCounter(uint8_t range)
1918 const int8_t emitInterval = blockLength + blockSpacing;
1920 int8_t closestSwp = -127;
1922 for (uint8_t i = 0; i < maxBlocks; ++i)
1924 Block &b = _blocks[i];
1929 int8_t p = b.position;
1932 int8_t swp = _calculateSwtichPostion(p, blockLength, range);
1944 if (closestSwp == -127 || swp < closestSwp)
1948 if (closestSwp >= 0)
1949 return (emitInterval - 1) - closestSwp;
1954 bool _mirrorBlocks()
1956 const uint8_t center = _segsNum / 2;
1961 _emittingBlocksEnabled =
true;
1963 emittedBlocksCount = 0;
1967 _prevAnimRenderLogic = _animRenderLogicIsInverted = _AnimInitLogicIsInverted;
1974 _blocks =
new Block[maxBlocks]{};
1978 if (_prevAnimRenderLogic != _animRenderLogicIsInverted)
1980 emitCooldown = _calculateSwitchedEmitTickCounter(_segsNum / 2);
1981 emittedBlocksCount = requestedNumBlocks ;
1982 _prevAnimRenderLogic = _animRenderLogicIsInverted;
1985 if (_currentTime - _lastUpdate1 >= _updateIntv1)
1987 _lastUpdate1 = _currentTime;
1991 if ((requestedNumBlocks == 0 || emittedBlocksCount < requestedNumBlocks) && _emittingBlocksEnabled)
1994 for (uint8_t i = 0; i < maxBlocks; ++i)
1996 Block &b = _blocks[i];
2003 uint16_t clamped = max(0, (int16_t)b.position + 1);
2004 uint8_t pixelsVisible = min(blockLength, (uint8_t)clamped);
2005 for (uint8_t j = 0; j < pixelsVisible; ++j)
2007 int8_t pos = _animRenderLogicIsInverted ? center - 1 - b.position : b.position;
2008 int8_t tailOffset = _animRenderLogicIsInverted ? pos + j : pos - j;
2013 int8_t idx = tailOffset;
2017 int8_t mirrorIdx = _segsNum - 1 - idx;
2019 if (idx >= 0 && idx < _segsNum)
2021 _barMeter.setPixel(idx,
true);
2023 if (mirrorIdx != idx && mirrorIdx >= 0 && mirrorIdx < _segsNum)
2025 _barMeter.setPixel(mirrorIdx,
true);
2030 if (b.position >= center - 1 + blockLength)
2035 if ((requestedNumBlocks > 0 && emittedBlocksCount >= requestedNumBlocks) || !_emittingBlocksEnabled)
2037 bool anyActive =
false;
2038 for (uint8_t i = 0; i < maxBlocks; ++i)
2040 if (_blocks[i].active)
2053 bool _scrollingBlocks()
2058 _emittingBlocksEnabled =
true;
2060 emittedBlocksCount = 0;
2064 _prevAnimRenderLogic = _animRenderLogicIsInverted = _AnimInitLogicIsInverted;
2071 _blocks =
new Block[maxBlocks]{};
2075 if (_prevAnimRenderLogic != _animRenderLogicIsInverted)
2077 emitCooldown = _calculateSwitchedEmitTickCounter(_segsNum);
2078 emittedBlocksCount = requestedNumBlocks ;
2079 _prevAnimRenderLogic = _animRenderLogicIsInverted;
2083 if (_currentTime - _lastUpdate1 >= _updateIntv1)
2085 _lastUpdate1 = _currentTime;
2088 if ((requestedNumBlocks == 0 || emittedBlocksCount < requestedNumBlocks) && _emittingBlocksEnabled)
2091 for (uint8_t i = 0; i < maxBlocks; ++i)
2093 Block &b = _blocks[i];
2099 for (uint8_t j = 0; j < blockLength; ++j)
2101 int8_t pos = _animRenderLogicIsInverted ? (_segsNum - 1) - b.position : b.position;
2102 int8_t tailOffset = _animRenderLogicIsInverted ? pos + j : pos - j;
2107 int8_t idx = tailOffset;
2108 if (idx >= _segsNum)
2111 if (idx >= 0 && idx < _segsNum)
2112 _barMeter.setPixel(_corrPixelToDir(idx),
true);
2116 if (b.position >= (_segsNum - 1) + blockLength)
2121 if ((requestedNumBlocks > 0 && emittedBlocksCount >= requestedNumBlocks) || !_emittingBlocksEnabled)
2123 for (uint8_t i = 0; i < maxBlocks; ++i)
2125 if (_blocks[i].active)
2134#define stackLevel _ledTracker1
2135 bool _stackingBlocks()
2137 const uint8_t blockInterval = blockLength + blockSpacing;
2138 bool hasActive =
false;
2145 _prevAnimRenderLogic = _animRenderLogicIsInverted = _AnimInitLogicIsInverted;
2153 _blocks =
new Block[maxBlocks]{};
2159 if (!_animRenderLogicIsInverted)
2168 while (stackLevel < _segsNum)
2169 stackLevel += blockInterval;
2170 for (uint8_t i = 0; i < stackLevel; i++)
2172 if ((i % blockInterval) < blockLength)
2173 _barMeter.setPixel(_corrPixelToDir(i),
true);
2175 _barMeter.setPixel(_corrPixelToDir(i),
false);
2182 if (_animRenderLogicIsInverted != _prevAnimRenderLogic)
2184 _prevAnimRenderLogic = _animRenderLogicIsInverted;
2185 if (_animRenderLogicIsInverted)
2186 stackLevel += blockInterval;
2188 stackLevel -= blockInterval;
2191 if (_currentTime - _lastUpdate1 >= _updateIntv1)
2193 _lastUpdate1 = _currentTime;
2196 for (uint8_t i = 0; i < maxBlocks; ++i)
2198 Block &b = _blocks[i];
2202 for (uint8_t j = 0; j < blockLength; ++j)
2204 int8_t seg = b.position + j;
2205 if (seg >= 0 && seg < _segsNum)
2206 _barMeter.setPixel(_corrPixelToDir(seg),
false);
2211 for (uint8_t i = 0; i < maxBlocks; ++i)
2213 if (_blocks[i].active)
2222 if (!_animRenderLogicIsInverted && stackLevel <= _segsNum)
2223 _emitBlock(_segsNum);
2224 else if (_animRenderLogicIsInverted && stackLevel >= 0)
2225 _emitBlock(stackLevel - blockInterval);
2229 for (uint8_t i = 0; i < maxBlocks; ++i)
2231 Block &b = _blocks[i];
2236 int8_t clearPos = b.position;
2237 if (clearPos >= 0 && clearPos < _segsNum)
2238 _barMeter.setPixel(_corrPixelToDir(clearPos),
false);
2241 if (!_animRenderLogicIsInverted)
2246 for (uint8_t j = 0; j < blockLength; ++j)
2248 int8_t seg = b.position + j;
2249 if (seg >= 0 && seg < _segsNum)
2250 _barMeter.setPixel(_corrPixelToDir(seg),
true);
2253 if (!_animRenderLogicIsInverted)
2255 if (b.position <= stackLevel)
2257 stackLevel += blockInterval;
2263 if (b.position >= _segsNum)
2265 stackLevel -= blockInterval;
2272 if (stackLevel == 0)
2274 _barMeter.setPixel(_corrPixelToDir(0),
false);
2276 if (!_animRenderLogicIsInverted)
2278 for (int8_t i = 0; i < stackLevel - blockInterval; ++i)
2280 if ((i % blockInterval) < blockLength)
2281 _barMeter.setPixel(_corrPixelToDir(i),
true);
2283 _barMeter.setPixel(_corrPixelToDir(i),
false);
2288 for (uint8_t i = 0; i < stackLevel - blockInterval; i++)
2290 if ((i % blockInterval) < blockLength)
2291 _barMeter.setPixel(_corrPixelToDir(i),
true);
2293 _barMeter.setPixel(_corrPixelToDir(i),
false);
2296 if (!_animRenderLogicIsInverted)
2298 if (stackLevel >= _segsNum - 1 && !hasActive)
2303 if (stackLevel <= 0 && !hasActive)
2312#undef requestedNumBlocks
2315#undef emittedBlocksCount
2318#define smoothingFactor _param1
2319 bool _followSignalSmooth()
2332 _prevAnimRenderLogic = _animRenderLogicIsInverted = _AnimInitLogicIsInverted;
2334 _smoothedValue1 = *_sigPtr1;
2335 _lastUpdate1 = _currentTime;
2341 if (_currentTime - _lastUpdate2 >= _updateIntv2)
2343 uint16_t raw = *_sigPtr1;
2344 _smoothedValue1 = (raw * smoothingFactor + _smoothedValue1 * (100 - smoothingFactor)) / 100;
2345 _lastUpdate2 = _currentTime;
2348 if (_currentTime - _lastUpdate1 >= _updateIntv1)
2350 _lastUpdate1 = _currentTime;
2352 uint8_t level = _getMappedSignal(_smoothedValue1, _minMap, _maxMap, 0, _segsNum);
2354 for (uint8_t i = 0; i < _segsNum; i++)
2356 _barMeter.setPixel(_corrPixelToDir(i), i < level);
2361 bool _followSignalWithPointer()
2374 _prevAnimRenderLogic = _animRenderLogicIsInverted = _AnimInitLogicIsInverted;
2376 _smoothedValue1 = *_sigPtr1;
2377 _lastUpdate1 = _currentTime;
2383 if (_currentTime - _lastUpdate2 >= _updateIntv2)
2385 uint16_t raw = *_sigPtr1;
2386 _smoothedValue1 = (raw * smoothingFactor + _smoothedValue1 * (100 - smoothingFactor)) / 100;
2387 _lastUpdate2 = _currentTime;
2390 if (_currentTime - _lastUpdate1 >= _updateIntv1)
2392 _lastUpdate1 = _currentTime;
2394 uint8_t avg = _getMappedSignal(_smoothedValue1, _minMap, _maxMap, 0, _segsNum);
2395 uint8_t pointer = _getMappedSignal(*_sigPtr1, _minMap, _maxMap, 0, _segsNum);
2398 for (uint8_t i = 0; i < _segsNum; i++)
2400 _barMeter.setPixel(_corrPixelToDir(i), i < avg);
2404 if (pointer < avg && pointer > 0)
2405 _barMeter.setPixel(_corrPixelToDir(pointer - 1),
false);
2407 if (pointer < avg - 2)
2408 _barMeter.setPixel(_corrPixelToDir(pointer + 1),
false);
2411 _barMeter.setPixel(_corrPixelToDir(pointer),
true);
2415 bool _followDualSignalCenterMirror()
2417 if (!_sigPtr1 && !_sigPtr2)
2428 _mirrorHalfRangeDir = _prevAnimRenderLogic = _animRenderLogicIsInverted = _AnimInitLogicIsInverted;
2430 _smoothedValue1 = *_sigPtr1;
2432 _smoothedValue2 = *_sigPtr2;
2433 _lastUpdate1 = _currentTime;
2438 if (_animRenderLogicIsInverted != _prevAnimRenderLogic)
2439 _prevAnimRenderLogic = _animRenderLogicIsInverted;
2442 if (_currentTime - _lastUpdate2 >= _updateIntv2)
2444 _lastUpdate2 = _currentTime;
2446 uint16_t raw1 = *_sigPtr1;
2447 _smoothedValue1 = (uint16_t)(((uint32_t)smoothingFactor * raw1 + (uint32_t)(100 - smoothingFactor) * _smoothedValue1) / 100);
2451 uint16_t raw2 = *_sigPtr2;
2452 _smoothedValue2 = (uint16_t)(((uint32_t)smoothingFactor * raw2 + (uint32_t)(100 - smoothingFactor) * _smoothedValue2) / 100);
2456 if (_currentTime - _lastUpdate1 >= _updateIntv1)
2458 _lastUpdate1 = _currentTime;
2460 uint16_t raw1 = *_sigPtr1;
2461 _smoothedValue1 = (uint16_t)(((uint32_t)smoothingFactor * raw1 + (uint32_t)(100 - smoothingFactor) * _smoothedValue1) / 100);
2462 uint8_t level1 = _getMappedSignal(_smoothedValue1, _minMap, _maxMap, 0, _segsNum / 2);
2464 uint8_t level2 = level1;
2466 level2 = _getMappedSignal(_smoothedValue2, _minMap, _maxMap, 0, _segsNum / 2);
2468 for (uint8_t i = 0; i < _segsNum; i++)
2471 if (_animRenderLogicIsInverted)
2472 _barMeter.setPixel(i, i < (_segsNum / 2 - 1) - level1 || i > ((_segsNum / 2) + level2));
2474 _barMeter.setPixel(i, i >= (_segsNum / 2 - 1) - level1 && i <= ((_segsNum / 2) + level2));
2480#define currentLevel _ledTracker1
2481#define peakLevel _ledTracker3
2482#define baseUpdate _updateIntv1
2483#define lastBaseUpdate _lastUpdate1
2484#define peakHoldTime _updateIntv3
2485#define lastPeakUpdate _lastUpdate3
2486 bool _followSignalFloatingPeak()
2500 _prevAnimRenderLogic = _animRenderLogicIsInverted = _AnimInitLogicIsInverted;
2503 _smoothedValue1 = *_sigPtr1;
2504 lastBaseUpdate = _currentTime;
2505 lastPeakUpdate = _currentTime;
2512 if (_currentTime - _lastUpdate2 >= _updateIntv2)
2514 _lastUpdate2 = _currentTime;
2516 uint16_t raw = *_sigPtr1;
2517 _smoothedValue1 = (raw * smoothingFactor + _smoothedValue1 * (100 - smoothingFactor)) / 100;
2518 currentLevel = _getMappedSignal(_smoothedValue1, _minMap, _maxMap, 0, _segsNum);
2522 if (_currentTime - _lastUpdate1 >= _updateIntv1)
2524 _lastUpdate1 = _currentTime;
2527 if (currentLevel > peakLevel)
2529 peakLevel = min(currentLevel, _segsNum - 1);
2530 lastPeakUpdate = _currentTime;
2532 else if (_currentTime - lastPeakUpdate >= peakHoldTime && peakLevel > currentLevel)
2535 lastPeakUpdate = _currentTime;
2539 for (uint8_t i = 0; i < _segsNum; i++)
2541 _barMeter.setPixel(_corrPixelToDir(i), (i <= currentLevel));
2545 if (peakLevel < _segsNum)
2547 _barMeter.setPixel(_corrPixelToDir(peakLevel),
true);
2555#undef lastBaseUpdate
2557#undef lastPeakUpdate
2559#undef smoothingFactor
2561#define cursor _ledTracker1
2562 bool _randomPixelUpdater()
2565 static uint8_t *pixelOrder =
nullptr;
2572 _prevAnimRenderLogic = _animRenderLogicIsInverted = _AnimInitLogicIsInverted;
2574 if (_animRenderLogicIsInverted)
2581 delete[] pixelOrder;
2582 pixelOrder =
nullptr;
2585 pixelOrder =
new uint8_t[_segsNum];
2586 for (uint8_t i = 0; i < _segsNum; ++i)
2589 for (uint8_t i = _segsNum - 1; i > 0; --i)
2591 uint8_t j = random(0, i + 1);
2592 uint8_t tmp = pixelOrder[i];
2593 pixelOrder[i] = pixelOrder[j];
2594 pixelOrder[j] = tmp;
2598 _lastUpdate1 = _currentTime;
2603 if (_currentTime - _lastUpdate1 >= _updateIntv1)
2605 _lastUpdate1 = _currentTime;
2607 uint8_t retries = 0;
2608 while (cursor < _segsNum && retries++ < _segsNum - 1)
2610 uint8_t seg = pixelOrder[cursor];
2611 bool currentState = _barMeter.getPixelState(seg);
2612 bool shouldChange = (!_AnimInitLogicIsInverted && !currentState) || (_AnimInitLogicIsInverted && currentState);
2616 _barMeter.setPixel(seg, !_AnimInitLogicIsInverted);
2626 if (cursor >= _segsNum)
2628 delete[] pixelOrder;
2629 pixelOrder =
nullptr;