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())
290 const uint8_t previousIndex =
316 const uint8_t previousIndex =
319 entry =
_queue[previousIndex];
538 const uint8_t previousIndex =
652 return blinkPixel(index, interval, interval, blinkCount);
666 _updateIntv1 = max(
static_cast<uint16_t
>(1), onInterval);
667 _updateIntv2 = max(
static_cast<uint16_t
>(1), offInterval);
829 return emptyDownIntv(duration / steps, maxPercent, minPercent);
960 uint16_t emptyIntv = fillIntv;
963 fillIntv = max(5, duration) / (2 * steps);
964 emptyIntv = fillIntv;
968 emptyIntv = max(5, duration - fillIntv * steps) / steps;
1048 uint16_t emptyIntv = fillIntv;
1051 fillIntv = max(5, duration) / (2 * steps);
1052 emptyIntv = fillIntv;
1056 emptyIntv = max(5, duration - fillIntv * steps) / steps;
1138 uint16_t emptyIntv = fillIntv;
1141 fillIntv = max(5, duration) / (2 * steps);
1142 emptyIntv = fillIntv;
1146 emptyIntv = max(5, duration - fillIntv * steps) / steps;
1230 uint16_t emptyIntv = fillIntv;
1233 fillIntv = max(5, duration) / (2 * steps);
1234 emptyIntv = fillIntv;
1238 emptyIntv = max(5, duration - fillIntv * steps) / steps;
1893 if (resetRuntimeState)
1903 : previousRenderLogic;
1920 if (resetRuntimeState)
1959 const uint16_t requestedCapacity =
static_cast<uint16_t
>(
_segmentCapacity) + 2U;
1962 const uint8_t randomOrderBlocks =
1964 const uint8_t workspaceBlocks = max(
_blockCapacity, randomOrderBlocks);
1965 if (workspaceBlocks > 0)
1982 for (uint8_t i = 0; i < blockCapacity; ++i)
1989 minP = constrain(minP, 0, 100);
1990 maxP = constrain(maxP, 0, 100);
2015 uint8_t minP = minPercPtr ? *minPercPtr : 0;
2016 uint8_t maxP = maxPercPtr ? *maxPercPtr : 100;
2037 return abs((half - 1) - pixel);
2041 if (minVal > maxVal)
2043 uint16_t temp = maxVal;
2047 if (minVal == maxVal)
2051 maxVal = minVal + 1;
2059 static inline uint8_t
_getMappedSignal(uint16_t sig, uint16_t minM, uint16_t maxM, uint8_t minR, uint8_t maxR)
2061 uint8_t mapped = map(sig, minM, maxM, minR, maxR);
2062 return constrain(mapped, minR, maxR);
2070 for (uint8_t i = 0; i <
_segsNum; i++)
2093 const uint8_t index =
_param1;
2094 const uint8_t blinkCount =
_param2;
2119 return blinkCount > 0 &&
_counter1 >= blinkCount;
2142 for (uint8_t i = 0; i <
_segsNum; ++i)
2153 for (uint8_t i = 0; i <
_segsNum; ++i)
2238 const uint8_t center =
_segsNum / 2;
2253 for (uint8_t i = 0; i < center; ++i)
2273 for (uint8_t i = 0; i < center; ++i)
2352#define MIN_BASE_LEVEL _param2
2353#define MIN_PEAK_LEVEL _param3
2354#define PEAK_HOLD_TIME _param4
2355#define bpmPtr _liveBpmPtr()
2356#define currentLevel _ledTracker1
2357#define peakLevel _ledTracker2
2358#define beat _updateIntv1
2359#define lastBeat _lastUpdate1
2360#define lastRandomUpdate _lastUpdate2
2361#define prevPeakUpdate _lastUpdate3
2364 static int8_t randomOffset;
2365 static bool isPeak =
false;
2400 randomOffset = random(-4, 4);
2404 finalLevel = constrain(finalLevel, 0,
_segsNum);
2423 for (uint8_t i = 0; i <
_segsNum; i++)
2443#undef MIN_BASE_LEVEL
2444#undef MIN_PEAK_LEVEL
2445#undef PEAK_HOLD_TIME
2451#undef lastRandomUpdate
2452#undef prevPeakUpdate
2454#define blockLength _param1
2455#define blockSpacing _param2
2456#define requestedNumBlocks _param3
2457#define maxBlocks _param4
2458#define emitIndex _param5
2459#define emittedBlocksCount _counter1
2460#define emitCooldown _counter2
2496 return (range - 1) - pos + (blockL - 1);
2503 int8_t closestSwp = -127;
2527 if (closestSwp == -127 || swp < closestSwp)
2531 if (closestSwp >= 0)
2532 return (emitInterval - 1) - closestSwp;
2539 const uint8_t center =
_segsNum / 2;
2581 uint16_t clamped = max(0, (int16_t)b.
position + 1);
2582 uint8_t pixelsVisible = min(
blockLength, (uint8_t)clamped);
2583 for (uint8_t j = 0; j < pixelsVisible; ++j)
2591 int8_t idx = tailOffset;
2595 int8_t mirrorIdx =
_segsNum - 1 - idx;
2601 if (mirrorIdx != idx && mirrorIdx >= 0 && mirrorIdx <
_segsNum)
2615 bool anyActive =
false;
2679 int8_t idx = tailOffset;
2706#define stackLevel _ledTracker1
2710 bool hasActive =
false;
2804 if (clearPos >= 0 && clearPos <
_segsNum)
2845 for (int8_t i = 0; i <
stackLevel - blockInterval; ++i)
2855 for (uint8_t i = 0; i <
stackLevel - blockInterval; i++)
2879#undef requestedNumBlocks
2882#undef emittedBlocksCount
2885#define smoothingFactor _param1
2921 for (uint8_t i = 0; i <
_segsNum; i++)
2965 for (uint8_t i = 0; i <
_segsNum; i++)
2971 if (pointer < avg && pointer > 0)
2974 if (pointer < avg - 2)
3031 uint8_t level2 = level1;
3035 for (uint8_t i = 0; i <
_segsNum; i++)
3047#define currentLevel _ledTracker1
3048#define peakLevel _ledTracker3
3049#define baseUpdate _updateIntv1
3050#define lastBaseUpdate _lastUpdate1
3051#define peakHoldTime _updateIntv3
3052#define lastPeakUpdate _lastUpdate3
3106 for (uint8_t i = 0; i <
_segsNum; i++)
3122#undef lastBaseUpdate
3124#undef lastPeakUpdate
3126#undef smoothingFactor
3146 for (uint8_t i = 0; i <
_segsNum; ++i)
3149 for (uint8_t i =
_segsNum - 1; i > 0; --i)
3151 uint8_t j = random(0, i + 1);
3152 uint8_t tmp = pixelOrder[i];
3153 pixelOrder[i] = pixelOrder[j];
3154 pixelOrder[j] = tmp;
3167 uint8_t retries = 0;
3171 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 & resume()
Resume animation after pause.
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 & 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)
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.
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.
SBK_BarMeterAnimations & pause()
Pause animation progression.
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 & 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.
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 the first queued animation, if any.
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 all pending queued animations without stopping the current animation.
bool _randomPixelUpdater()
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.
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