39#ifndef SBK_BARDRIVE_QUEUE_CAPACITY
40#define SBK_BARDRIVE_QUEUE_CAPACITY 4
43#if SBK_BARDRIVE_QUEUE_CAPACITY < 1 || SBK_BARDRIVE_QUEUE_CAPACITY > 255
44#error "SBK_BARDRIVE_QUEUE_CAPACITY must be between 1 and 255"
57template <
typename BarMeterT>
93 bool update(uint32_t syncTime = millis())
310 const uint8_t previousIndex =
336 const uint8_t previousIndex =
339 entry =
_queue[previousIndex];
578 const uint8_t previousIndex =
692 return blinkPixel(index, interval, interval, blinkCount);
869 return emptyDownIntv(duration / steps, maxPercent, minPercent);
1000 uint16_t emptyIntv = fillIntv;
1003 fillIntv =
_maxValue(5, duration) / (2 * steps);
1004 emptyIntv = fillIntv;
1008 emptyIntv =
_maxValue(5, duration - fillIntv * steps) / steps;
1088 uint16_t emptyIntv = fillIntv;
1091 fillIntv =
_maxValue(5, duration) / (2 * steps);
1092 emptyIntv = fillIntv;
1096 emptyIntv =
_maxValue(5, duration - fillIntv * steps) / steps;
1178 uint16_t emptyIntv = fillIntv;
1181 fillIntv =
_maxValue(5, duration) / (2 * steps);
1182 emptyIntv = fillIntv;
1186 emptyIntv =
_maxValue(5, duration - fillIntv * steps) / steps;
1270 uint16_t emptyIntv = fillIntv;
1273 fillIntv =
_maxValue(5, duration) / (2 * steps);
1274 emptyIntv = fillIntv;
1278 emptyIntv =
_maxValue(5, duration - fillIntv * steps) / steps;
1938 if (resetRuntimeState)
1948 : previousRenderLogic;
1965 if (resetRuntimeState)
2011 const uint16_t requestedCapacity =
static_cast<uint16_t
>(
_segmentCapacity) + 2U;
2014 const uint8_t randomOrderBlocks =
2017 if (workspaceBlocks > 0)
2034 for (uint8_t i = 0; i < blockCapacity; ++i)
2041 template <
typename A,
typename B>
2042 static auto _minValue(A a, B b) ->
decltype(
true ? A() : B())
2044 return a < b ? a : b;
2047 template <
typename A,
typename B>
2048 static auto _maxValue(A a, B b) ->
decltype(
true ? A() : B())
2050 return a > b ? a : b;
2055 minP = constrain(minP, 0, 100);
2056 maxP = constrain(maxP, 0, 100);
2081 uint8_t minP = minPercPtr ? *minPercPtr : 0;
2082 uint8_t maxP = maxPercPtr ? *maxPercPtr : 100;
2103 return abs((half - 1) - pixel);
2107 if (minVal > maxVal)
2109 uint16_t temp = maxVal;
2113 if (minVal == maxVal)
2117 maxVal = minVal + 1;
2125 static inline uint8_t
_getMappedSignal(uint16_t sig, uint16_t minM, uint16_t maxM, uint8_t minR, uint8_t maxR)
2127 uint8_t mapped = map(sig, minM, maxM, minR, maxR);
2128 return constrain(mapped, minR, maxR);
2136 for (uint8_t i = 0; i <
_segsNum; i++)
2159 const uint8_t index =
_param1;
2160 const uint8_t blinkCount =
_param2;
2185 return blinkCount > 0 &&
_counter1 >= blinkCount;
2208 for (uint8_t i = 0; i <
_segsNum; ++i)
2219 for (uint8_t i = 0; i <
_segsNum; ++i)
2304 const uint8_t center =
_segsNum / 2;
2319 for (uint8_t i = 0; i < center; ++i)
2339 for (uint8_t i = 0; i < center; ++i)
2430#define MIN_BASE_LEVEL _param2
2431#define MIN_PEAK_LEVEL _param3
2432#define PEAK_HOLD_TIME _param4
2433#define bpmPtr _liveBpmPtr()
2434#define currentLevel _ledTracker1
2435#define peakLevel _ledTracker2
2436#define beat _updateIntv1
2437#define lastBeat _lastUpdate1
2438#define lastRandomUpdate _lastUpdate2
2439#define prevPeakUpdate _lastUpdate3
2442 static int8_t randomOffset;
2443 static bool isPeak =
false;
2478 randomOffset = random(-4, 4);
2482 finalLevel = constrain(finalLevel, 0,
_segsNum);
2501 for (uint8_t i = 0; i <
_segsNum; i++)
2521#undef MIN_BASE_LEVEL
2522#undef MIN_PEAK_LEVEL
2523#undef PEAK_HOLD_TIME
2529#undef lastRandomUpdate
2530#undef prevPeakUpdate
2532#define blockLength _param1
2533#define blockSpacing _param2
2534#define requestedNumBlocks _param3
2535#define maxBlocks _param4
2536#define emitIndex _param5
2537#define emittedBlocksCount _counter1
2538#define emitCooldown _counter2
2574 return (range - 1) - pos + (blockL - 1);
2581 int8_t closestSwp = -127;
2605 if (closestSwp == -127 || swp < closestSwp)
2609 if (closestSwp >= 0)
2610 return (emitInterval - 1) - closestSwp;
2617 const uint8_t center =
_segsNum / 2;
2661 for (uint8_t j = 0; j < pixelsVisible; ++j)
2669 int8_t idx = tailOffset;
2673 int8_t mirrorIdx =
_segsNum - 1 - idx;
2679 if (mirrorIdx != idx && mirrorIdx >= 0 && mirrorIdx <
_segsNum)
2693 bool anyActive =
false;
2757 int8_t idx = tailOffset;
2784#define stackLevel _ledTracker1
2788 bool hasActive =
false;
2882 if (clearPos >= 0 && clearPos <
_segsNum)
2923 for (int8_t i = 0; i <
stackLevel - blockInterval; ++i)
2933 for (uint8_t i = 0; i <
stackLevel - blockInterval; i++)
2957#undef requestedNumBlocks
2960#undef emittedBlocksCount
2963#define smoothingFactor _param1
2999 for (uint8_t i = 0; i <
_segsNum; i++)
3043 for (uint8_t i = 0; i <
_segsNum; i++)
3049 if (pointer < avg && pointer > 0)
3052 if (pointer < avg - 2)
3109 uint8_t level2 = level1;
3113 for (uint8_t i = 0; i <
_segsNum; i++)
3125#define currentLevel _ledTracker1
3126#define peakLevel _ledTracker3
3127#define baseUpdate _updateIntv1
3128#define lastBaseUpdate _lastUpdate1
3129#define peakHoldTime _updateIntv3
3130#define lastPeakUpdate _lastUpdate3
3184 for (uint8_t i = 0; i <
_segsNum; i++)
3200#undef lastBaseUpdate
3202#undef lastPeakUpdate
3204#undef smoothingFactor
3224 for (uint8_t i = 0; i <
_segsNum; ++i)
3227 for (uint8_t i =
_segsNum - 1; i > 0; --i)
3229 uint8_t j = random(0, i + 1);
3230 uint8_t tmp = pixelOrder[i];
3231 pixelOrder[i] = pixelOrder[j];
3232 pixelOrder[j] = tmp;
3245 uint8_t retries = 0;
3249 bool currentState =
_barMeter.getPixelState(seg);
#define emittedBlocksCount
#define SBK_BARDRIVE_QUEUE_CAPACITY
#define requestedNumBlocks
bool isNonInvertingLogicAnim()
Return true if the current animation does not support logic inversion.
SBK_BarMeterAnimations & fillUpIntv(uint16_t updateIntv, const uint8_t *maxPercentPtr, const uint8_t *minPercentPtr=nullptr)
Start animation that fills the bar upwards at a fixed interval with live percent tracking.
bool _followDualSignalCenterMirror()
SBK_BarMeterAnimations & beatPulse(uint8_t bpm=116)
Start a beat pulse animation synchronized to a constant BPM.
uint32_t _animationDuration
SBK_BarMeterAnimations & bounceFillUpIntv(uint16_t fillIntv, uint16_t emptyIntv, const uint8_t *maxPercentPtr, const uint8_t *minPercentPtr=nullptr)
Start animation that fills/empties (bounces) bar upward with live range.
SBK_BarMeterAnimations & fillDownDur(uint16_t duration, uint8_t maxPercent=100, uint8_t minPercent=0)
Start animation that fills the bar downwards over a specified duration.
SBK_BarMeterAnimations & fillUpIntv(uint16_t updateIntv, uint8_t maxPercent=100, uint8_t minPercent=0)
Start animation that fills the bar upwards at a fixed interval.
void _emitBlock(int8_t pos)
bool _prevAnimRenderLogic
SBK_BarMeterAnimations & emptyUpIntv(uint16_t updateIntv, const uint8_t *maxPercentPtr, const uint8_t *minPercentPtr=nullptr)
Start animation that empties the bar from bottom to top at fixed intervals with live range.
SBK_BarMeterAnimations & loop()
Set animation to automatically loop when complete.
uint8_t currentQueueIndex() const
Return the physical queue slot currently playing, or NO_QUEUE_INDEX.
SBK_BarMeterAnimations & bounceFillFromEdgesDur(uint16_t duration, uint8_t maxPercent=100, uint8_t minPercent=0, uint16_t fillIntv=0)
Bounce fill from both edges inward with fixed range.
static int8_t _calculateSwitchPosition(int8_t pos, uint8_t blockL, uint8_t range)
SBK_BarMeterAnimations & setDir(bool newDirection)
Explicitly set the animation rendering direction.
void _initializeStorage()
SBK_BarMeterAnimations & bounceFillUpDur(uint16_t duration, uint8_t maxPercent=100, uint8_t minPercent=0, uint16_t fillIntv=0)
Start animation that fills/empties (bounces) bar upward with fixed range.
SBK_BarMeterAnimations & beatPulse(uint8_t *bpmPtr)
Start a beat pulse animation synchronized to a live BPM value.
SBK_BarMeterAnimations(BarMeterT &barMeter)
Construct an animation controller linked to a bar meter.
SBK_BarMeterAnimations & fillDownIntv(uint16_t updateIntv, uint8_t maxPercent=100, uint8_t minPercent=0)
Start animation that fills the bar downwards at a fixed interval.
SBK_BarMeterAnimations & toggleLogic()
Toggle rendering logic (inverted vs normal), example fill logic become empty logic.
bool _followSignalFloatingPeak()
SBK_BarMeterAnimations & loopQueue()
Repeat the entire queue after its final entry completes.
SBK_BarMeterAnimations & followSignalWithPointer(const uint16_t *sigPtr, uint16_t updateIntv=100, uint16_t minMap=0, uint16_t maxMap=1023, uint8_t smoothingFactor=30, uint16_t samplingIntv=5)
Follow signal with smoothing and display a pointer.
SBK_BarMeterAnimations & toggleDir()
Toggle the current animation rendering direction.
SBK_BarMeterAnimations & emptyDownIntv(uint16_t updateIntv, uint8_t maxPercent=100, uint8_t minPercent=0)
Start animation that empties the bar from top to bottom at fixed intervals.
void _loadQueueEntry(const QueueEntry &entry, bool forceReset=false)
const uint16_t * _signalPtr1() const
SBK_BarMeterAnimations & reverseDir()
Reverse the rendering direction compared to the original one.
void _mapMinMaxTracker(uint8_t minP, uint8_t maxP, uint8_t minR, uint8_t maxR)
SBK_BarMeterAnimations & pause(uint32_t syncTime=millis())
Freeze animation progression and all queue/animation timers.
void _mapMinMaxTrackerFromPtr(const uint8_t *minPercPtr, const uint8_t *maxPercPtr, int8_t minR, uint8_t maxR)
SBK_BarMeterAnimations & bounceFillDownDur(uint16_t duration, uint8_t maxPercent=100, uint8_t minPercent=0, uint16_t fillIntv=0)
Start animation that fills/empties (bounces) bar downward.
SBK_BarMeterAnimations & setUpdateInterval(uint16_t interval)
Change the primary update interval without restarting the animation.
SBK_BarMeterAnimations & followSignalSmooth(const uint16_t *sigPtr, uint16_t updateIntv=100, uint16_t minMap=0, uint16_t maxMap=1023, uint8_t smoothingFactor=30, uint16_t samplingIntv=5)
Follow analog signal with smoothing for fill animation.
static constexpr uint8_t MAX_BLOCK_CAPACITY
const uint8_t * _liveBpmPtr() const
SBK_BarMeterAnimations & followSignalFloatingPeak(const uint16_t *sigPtr, uint8_t peakHoldTime=20, uint16_t updateIntv=100, uint16_t minMap=0, uint16_t maxMap=1023, uint8_t smoothingFactor=30, uint16_t samplingIntv=5)
Follow an analog signal with smoothing and floating peak indicator.
static auto _minValue(A a, B b) -> decltype(true ? A() :B())
bool _animRenderLogicIsInverted
const uint16_t * _signalPtr2() const
SBK_BarMeterAnimations & setAll(bool onff)
Set all pixels to the specified state.
SBK_BarMeterAnimations & downStackingBlocks(uint16_t intv=50, uint8_t blockLength=1, uint8_t blockSpacing=0)
Drop blocks from top and stack from bottom up.
bool _isNonInvertingLogicAnim
void _resetBlocks(uint8_t &blockCapacity)
uint8_t _corrPixelToDirForHalfRange(uint8_t pixel)
const uint8_t * _percentMaxPtr() const
SBK_BarMeterAnimations & emptyDownDur(uint16_t duration, uint8_t maxPercent=100, uint8_t minPercent=0)
Start animation that empties the bar from top to bottom over a duration.
bool _queueEntryTimingPending
SBK_BarMeterAnimations & blinkPixel(uint8_t index, uint16_t interval=500, uint8_t blinkCount=0)
Blink one pixel with equal ON and OFF intervals.
bool queueOverflowed() const
Return true if an enqueue operation exceeded the configured capacity.
static constexpr uint8_t QUEUE_CAPACITY
SBK_BarMeterAnimations & setLogic(bool newLogic)
Set rendering logic (true = inverted logic, false = normal logic), example fill logic become empty lo...
SBK_BarMeterAnimations & downUnstackingBlocks(uint16_t intv=50, uint8_t blockLength=1, uint8_t blockSpacing=0)
Drop blocks from top and unstack from bottom up.
bool isQueueRunning() const
Return true while an animation queue is being processed.
void _startNextQueuedAnimation(bool forceReset=false)
SBK_BarMeterAnimations & resetDir()
Reset direction to the original setting.
SBK_BarMeterAnimations & setAllOff()
Set all pixels OFF.
SBK_BarMeterAnimations & animInit()
Mark animation as ready to reinitialize in next update cycle.
bool _emittingBlocksEnabled
SBK_BarMeterAnimations & randomEmpty(uint16_t interval=30)
Randomly turn off pixels until the bar is empty.
bool isQueueIndexPlaying(uint8_t index) const
Return true when the requested physical queue slot is currently playing.
SBK_BarMeterAnimations & stopBlockEmission()
Stop emitting new blocks during compatible block animations.
SBK_BarMeterAnimations & blinkPixel(uint8_t index, uint16_t onInterval, uint16_t offInterval, uint8_t blinkCount)
Blink one pixel with independent ON and OFF intervals.
uint32_t _queueEntryStartedAt
SBK_BarMeterAnimations & upStackingBlocks(uint16_t intv=50, uint8_t blockLength=1, uint8_t blockSpacing=0)
Launch blocks from bottom and stack at the top.
bool isLogicInverted()
Returns true if current logic is different from original logic.
SBK_BarMeterAnimations & enqueue()
Add the currently configured animation to the fixed-capacity queue.
SBK_BarMeterAnimations & enqueueReverseAnim()
Queue a state-preserving logic reversal of the preceding entry.
SBK_BarMeterAnimations & followDualSignalFromCenter(const uint16_t *sig1Ptr, uint16_t updateIntv=100, const uint16_t *sig2Ptr=nullptr, uint16_t minMap=0, uint16_t maxMap=1023, uint8_t smoothingFactor=30, uint16_t samplingIntv=5)
Smoothly fills the lower half and upper half of the bar meter independently from center,...
SBK_BarMeterAnimations & explodingBlocks(uint16_t intv=50, uint8_t blockLength=2, uint8_t blockSpacing=1, uint8_t numBlocks=0)
Emit mirrored blocks from center outward.
uint32_t _blockEmissionStopAfter
bool animPendingLoop()
Detect whether animation has completed and is about to loop.
void _captureQueueEntry(QueueEntry &entry, bool resetRuntimeState, uint32_t duration)
static void _correctSwapOrEqualMinMax(uint16_t &minVal, uint16_t &maxVal)
bool isBlockEmissionEnabled() const
Query if block emission is enabled.
SBK_BarMeterAnimations & noLoop()
Disable auto-looping.
SBK_BarMeterAnimations & emptyDownIntv(uint16_t updateIntv, const uint8_t *maxPercentPtr, const uint8_t *minPercentPtr=nullptr)
Start animation that empties the bar from top to bottom at fixed intervals with live range.
SBK_BarMeterAnimations & stop()
Terminate the animation, loop, and queue, then clear mapped pixels.
int8_t _calculateSwitchedEmitTickCounter(uint8_t range)
SBK_BarMeterAnimations & upUnstackingBlocks(uint16_t intv=50, uint8_t blockLength=1, uint8_t blockSpacing=0)
Launch blocks upward and unstack from top.
SBK_BarMeterAnimations & wait(uint16_t duration)
Wait without blocking or changing pixel states; waits never loop.
uint8_t _corrPixelToDir(uint8_t pixel)
SBK_BarMeterAnimations & bounceFillFromCenterIntv(uint16_t fillIntv=25, uint16_t emptyIntv=25, uint8_t maxPercent=100, uint8_t minPercent=0)
Bounce fill from center outward with fixed range.
bool _fillFromOrEmptyToCenter()
SBK_BarMeterAnimations & bounceFillFromCenterIntv(uint16_t fillIntv, uint16_t emptyIntv, const uint8_t *maxPercentPtr, const uint8_t *minPercentPtr=nullptr)
Bounce fill from center outward with live percent range tracking.
bool _followSignalWithPointer()
const uint8_t * _percentMinPtr() const
bool update(uint32_t syncTime=millis())
Advance the animation logic based on the current millis().
SBK_BarMeterAnimations & collidingBlocks(uint16_t intv=50, uint8_t blockLength=2, uint8_t blockSpacing=1, uint8_t numBlocks=0)
Emit mirrored blocks from edge to center.
uint8_t _currentQueueIndex
~SBK_BarMeterAnimations()
bool _AnimInitLogicIsInverted
QueueEntry _queue[QUEUE_CAPACITY]
SBK_BarMeterAnimations & noLoopQueue()
Disable repetition; finish the current queue pass before stopping.
SBK_BarMeterAnimations & emptyUpDur(uint16_t duration, uint8_t maxPercent=100, uint8_t minPercent=0)
Start animation that empties the bar from bottom to top over a duration.
uint8_t _queueStoredCount
SBK_BarMeterAnimations & resetLogic()
Reset logic to initial (default) value.
bool isLoopEnabled() const
Query if animation loop is enabled.
void setSegsNum(uint8_t n)
Set the total number of segments the animation logic should handle.
SBK_BarMeterAnimations & startQueue()
Start queued playback using the current queue-loop setting.
static void _normalizePercentRange(uint8_t &minP, uint8_t &maxP)
SBK_BarMeterAnimations & setAllOn()
Set all pixels ON.
SBK_BarMeterAnimations & stopBlockEmissionAfter(uint32_t duration)
Stop new block emission after an animation has run for a duration.
bool(SBK_BarMeterAnimations::*)() AnimUpdateFn
AnimUpdateFn _currentFunc
bool isRunning() const
Query if animation is currently active.
SBK_BarMeterAnimations & bounceFillDownIntv(uint16_t fillIntv=10, uint16_t emptyIntv=10, uint8_t maxPercent=100, uint8_t minPercent=0)
Start downwardfill/empty (bounce) with fixed percent range.
SBK_BarMeterAnimations & invertLogic()
Reverse logic compared to initial state Logic refer to behavior, example : fill/empty,...
bool _bounceFillHalfRangeMirrorCenter()
SBK_BarMeterAnimations & scrollingDownBlocks(uint16_t intv=50, uint8_t blockLength=2, uint8_t blockSpacing=1, uint8_t numBlocks=0)
Scroll blocks downward.
uint32_t _activeBlockEmissionStopAfter
SBK_BarMeterAnimations & emptyUpIntv(uint16_t updateIntv, uint8_t maxPercent=100, uint8_t minPercent=0)
Start animation that empties the bar from bottom to top at fixed intervals.
SBK_BarMeterAnimations & bounceFillDownIntv(uint16_t fillIntv, uint16_t emptyIntv, const uint8_t *maxPercentPtr, const uint8_t *minPercentPtr=nullptr)
Start downward fill/empty (bounce) with live percent range tracking.
SBK_BarMeterAnimations & forTime(uint32_t duration)
Limit a direct or queued animation to a maximum run time.
SBK_BarMeterAnimations & bounceFillFromCenterDur(uint16_t duration, uint8_t maxPercent=100, uint8_t minPercent=0, uint16_t fillIntv=0)
Bounce fill from center outward with fixed range.
SBK_BarMeterAnimations & skipCurrent()
Abandon the active animation and immediately start the next queue entry.
Block * _animationWorkspace
SBK_BarMeterAnimations & fillDownIntv(uint16_t updateIntv, const uint8_t *maxPercentPtr, const uint8_t *minPercentPtr=nullptr)
Start animation that fills the bar downwards at a fixed interval with live percent tracking.
static uint8_t _getMappedSignal(uint16_t sig, uint16_t minM, uint16_t maxM, uint8_t minR, uint8_t maxR)
bool _AnimInitDirIsReversed
SBK_BarMeterAnimations & resumeBlockEmission()
Resume emitting new blocks during compatible block animations.
SBK_BarMeterAnimations & clearQueue()
Discard the queue and disable queue looping without stopping the current animation.
bool _randomPixelUpdater()
static auto _maxValue(A a, B b) -> decltype(true ? A() :B())
SBK_BarMeterAnimations & randomFill(uint16_t interval=30)
Randomly light up pixels until the bar is full.
uint8_t queuedAnimations() const
Return the number of animations waiting behind the active one.
SBK_BarMeterAnimations & bounceFillUpIntv(uint16_t fillIntv=10, uint16_t emptyIntv=10, uint8_t maxPercent=100, uint8_t minPercent=0)
Start animation that fills/empties (bounces) bar upward with fixed range.
SBK_BarMeterAnimations & fillUpDur(uint16_t duration, uint8_t maxPercent=100, uint8_t minPercent=0)
Start animation that fills the bar upwards over a specified duration.
SBK_BarMeterAnimations & bounceFillFromEdgesIntv(uint16_t fillIntv, uint16_t emptyIntv, const uint8_t *maxPercentPtr, const uint8_t *minPercentPtr=nullptr)
Bounce fill from both edges inward with live percent range tracking.
static constexpr uint8_t NO_QUEUE_INDEX
SBK_BarMeterAnimations & scrollingUpBlocks(uint16_t intv=50, uint8_t blockLength=2, uint8_t blockSpacing=1, uint8_t numBlocks=0)
Scroll blocks upward.
SBK_BarMeterAnimations & resume(uint32_t syncTime=millis())
Resume with the same playback time remaining as when paused.
bool _followSignalSmooth()
SBK_BarMeterAnimations & enqueueFor(uint32_t duration)
Queue the configured animation for a fixed amount of time.
SBK_BarMeterAnimations & followDualSignalFromEdges(const uint16_t *sig1Ptr, uint16_t updateIntv=100, const uint16_t *sig2Ptr=nullptr, uint16_t minMap=0, uint16_t maxMap=1023, uint8_t smoothingFactor=30, uint16_t samplingIntv=5)
Smoothly fills the lower half and upper half of the bar meter independently from center,...
bool _animRenderDirIsReversed
bool isDirectionReversed()
Returns true if direction is reversed compared to the original.
uint32_t _queueEntryDuration
SBK_BarMeterAnimations & bounceFillFromEdgesIntv(uint16_t fillIntv=25, uint16_t emptyIntv=25, uint8_t maxPercent=100, uint8_t minPercent=0)
Bounce fill from both edges inward with fix range.
bool isPaused() const
Query if animation is paused.
bool animInitLogicIsInverted
bool isNonInvertingLogicAnim
uint32_t blockEmissionStopAfter
bool animInitDirIsReversed
bool animRenderDirIsReversed
bool animRenderLogicIsInverted
bool emittingBlocksEnabled