62#ifndef SBK_BARDRIVE_WITH_ANIM
63#pragma message(" ⚠️ SBK_BARDRIVE_WITH_ANIM is not defined. SBK BarDrive Built-in animations are disabled and cannot be accessed, saving memory if they are not needed. If you do need the animations library, define SBK_BARDRIVE_WITH_ANIM before including SBK_BarDrive.h.")
68#if !defined(SBK_MAX72xx_IS_DEFINED) && !defined(SBK_HT16K33_IS_DEFINED)
69#pragma message(" ⚠️ SBK BarDrive library note: Include an SBK_MAX72xx or SBK_HT16K33 driver header and declare a driver before creating a bar meter instance.")
73#ifdef SBK_BARDRIVE_WITH_ANIM
124template <
typename DriverT>
145 uint8_t rowOffset = 0,
146 uint8_t colOffset = 0)
148 _devIdx(constrain(devIdx, 0, 7)),
149 _matrixPreset(matrixPreset),
150 _direction(direction)
152 _isMatrixMapped =
true;
153 if (_devIdx > (driver->devsNum() - 1))
155 _initializePresetMapping(MatrixPreset::NONE);
164 _initializePresetMapping(matrixPreset);
165 _rowOffset = constrain(rowOffset, 0, _driver->maxRows(_devIdx) - 1);
166 _colOffset = constrain(colOffset, 0, _driver->maxColumns() - 1);
194 uint8_t rowOffset = 0,
195 uint8_t colOffset = 0)
197 _devIdx(constrain(devIdx, 0, 7)),
198 _direction(direction)
200 _isMatrixMapped =
true;
201 if (_devIdx > (driver->devsNum() - 1))
211 _rowsNum = constrain(rowsNum, 1, 255);
212 _colsNum = constrain(colsNum, 1, driver->maxColumns());
213 _rowOffset = constrain(rowOffset, 0, _driver->maxRows(_devIdx) - 1);
214 _colOffset = constrain(colOffset, 0, _driver->maxColumns() - 1);
239 uint8_t segOffset = 0)
241 _devIdx(constrain(devIdx, 0, 7)),
242 _direction(direction),
245 _isMatrixMapped =
false;
246 if (_devIdx > (driver->devsNum() - 1))
255 _rowsNum = _driver->maxRows(_devIdx);
256 _colsNum = _driver->maxColumns();
257 _segOffset = constrain(segOffset, 0, _driver->maxSegments(_devIdx) - 1);
284 const uint8_t (&mapping)[N][3],
286 bool progmem =
false,
287 uint8_t rowOffset = 0,
288 uint8_t colOffset = 0)
290 _devIdx(constrain(devIdx, 0, 7)),
291 _customMapping(mapping),
292 _direction(direction),
293 _userMappingIsProgmem(progmem)
295 _isMatrixMapped =
true;
296 if (_devIdx > (driver->devsNum() - 1))
307 _rowsNum = _driver->maxRows(_devIdx);
308 _colsNum = _driver->maxColumns();
309 _rowOffset = constrain(rowOffset, 0, _driver->maxRows(_devIdx) - 1);
310 _colOffset = constrain(colOffset, 0, _driver->maxColumns() - 1);
325 void show() { _driver->show(); }
332 for (uint8_t i = 0; i < _segsNum; ++i)
369 for (uint8_t i = 0; i < _segsNum; ++i)
371 uint8_t devIdx = _devIdx;
372 uint8_t rowIdx, colIdx;
373 _getMappedDevRowCol(i, &devIdx, &rowIdx, &colIdx);
374 stream.print(F(
"Segment "));
376 stream.print(F(
" → Device "));
377 stream.print(devIdx);
378 stream.print(F(
", Row "));
379 stream.print(rowIdx);
380 stream.print(F(
", Col "));
381 stream.println(colIdx);
398 if (segment >= _segsNum || !_driver)
401 uint8_t devIdx = _devIdx;
402 uint8_t rowIdx, colIdx;
403 _getMappedDevRowCol(segment, &devIdx, &rowIdx, &colIdx);
404 _driver->setLed(devIdx, rowIdx, colIdx, state != 0);
421 if (segment >= _segsNum || !_driver)
424 uint8_t devIdx = _devIdx;
425 uint8_t rowIdx, colIdx;
427 _getMappedDevRowCol(segment, &devIdx, &rowIdx, &colIdx);
428 return _driver->getLed(devIdx, rowIdx, colIdx);
458 _rowOffset = rowOffset;
459 _colOffset = colOffset;
464 void _initializePresetMapping(
MatrixPreset matrixPreset)
472 switch (matrixPreset)
475 _rowsNum = _driver->maxRows(_devIdx);
476 _colsNum = _driver->maxColumns();
477 _segsNum = _rowsNum * _colsNum;
478 _isMatrixMapped =
false;
484 _isMatrixMapped =
true;
490 _isMatrixMapped =
true;
493 _rowsNum = _driver->maxRows(_devIdx);
494 _colsNum = _driver->maxColumns();
495 _segsNum = _rowsNum * _colsNum;
496 _isMatrixMapped =
false;
501 void _getMappedDevRowCol(uint8_t seg, uint8_t *devIdx, uint8_t *rowIdx, uint8_t *colIdx)
const
505 ? (_segsNum - 1 - seg)
509 mappedSeg += (_isMatrixMapped ? 0 : _segOffset);
514 if (_userMappingIsProgmem)
516 *devIdx = pgm_read_byte(&_customMapping[mappedSeg][0]);
517 *rowIdx = pgm_read_byte(&_customMapping[mappedSeg][1]);
518 *colIdx = pgm_read_byte(&_customMapping[mappedSeg][2]);
522 *devIdx = _customMapping[mappedSeg][0];
523 *rowIdx = _customMapping[mappedSeg][1] + _rowOffset;
524 *colIdx = _customMapping[mappedSeg][2] + _colOffset;
531 const uint8_t segPerDev = _driver->maxRows(*devIdx) * _driver->maxColumns();
532 const uint8_t baseDevIdx = *devIdx + (mappedSeg / segPerDev);
533 const uint8_t localIdx = mappedSeg % segPerDev;
538 uint8_t baseRowIdx = localIdx % _rowsNum;
539 uint8_t baseColIdx = localIdx / _rowsNum;
541 *devIdx = baseDevIdx;
542 *rowIdx = baseRowIdx + _rowOffset;
543 *colIdx = baseColIdx + _colOffset;
548 uint8_t baseRowIdx = localIdx / _driver->maxColumns();
549 uint8_t baseColIdx = localIdx % _driver->maxColumns();
551 *devIdx = baseDevIdx;
552 *rowIdx = baseRowIdx;
553 *colIdx = baseColIdx;
558 const uint8_t _devIdx;
560 const uint8_t (*_customMapping)[3] =
nullptr;
562 uint8_t _segOffset = 0;
563 uint8_t _rowOffset = 0;
564 uint8_t _colOffset = 0;
565 bool _isMatrixMapped =
false;
567 uint8_t _rowsNum = 0;
568 uint8_t _colsNum = 0;
569 bool _userMappingIsProgmem =
false;
588template <
typename DriverT>
609 uint8_t rowOffset = 0,
610 uint8_t colOffset = 0)
611 : _barMeter(driver, devIdx, matrixPreset, direction, rowOffset, colOffset)
612#ifdef SBK_BARDRIVE_WITH_ANIM
614 _barAnimations(_barMeter)
617#ifdef SBK_BARDRIVE_WITH_ANIM
618 _barAnimations.setSegsNum(_barMeter.getSegsNum());
646 uint8_t rowOffset = 0,
647 uint8_t colOffset = 0)
648 : _barMeter(driver, devIdx, rowsNum, colsNum, direction, rowOffset, colOffset)
649#ifdef SBK_BARDRIVE_WITH_ANIM
651 _barAnimations(_barMeter)
654#ifdef SBK_BARDRIVE_WITH_ANIM
655 _barAnimations.setSegsNum(_barMeter.getSegsNum());
680 uint8_t segOffset = 0)
681 : _barMeter(driver, devIdx, segsNum, direction, segOffset)
682#ifdef SBK_BARDRIVE_WITH_ANIM
684 _barAnimations(_barMeter)
687#ifdef SBK_BARDRIVE_WITH_ANIM
688 _barAnimations.setSegsNum(_barMeter.getSegsNum());
715 const uint8_t (&mapping)[N][3],
717 bool progmem =
false,
718 uint8_t rowOffset = 0,
719 uint8_t colOffset = 0)
720 : _barMeter(driver, devIdx, mapping, direction, progmem, rowOffset, colOffset)
721#ifdef SBK_BARDRIVE_WITH_ANIM
723 _barAnimations(_barMeter)
726#ifdef SBK_BARDRIVE_WITH_ANIM
727 _barAnimations.setSegsNum(_barMeter.getSegsNum());
738#ifdef SBK_BARDRIVE_WITH_ANIM
755 void show() { _barMeter.show(); }
805 void setPixel(uint8_t segment, uint8_t state) { _barMeter.setPixel(segment, state); }
819 uint8_t
getPixelState(uint8_t segment) {
return _barMeter.getPixelState(segment); }
854#ifdef SBK_BARDRIVE_WITH_ANIM
MatrixPreset
Enables built-in animation support for SBK_BarDrive.
@ SBK_BarMeter_SA28
Alias for SBK BarMeter SA28, uses the BL28_3005SA preset internally.
@ BL28_3005SK
Native mapping for BL28-3005SK (4 anodes × 7 cathodes), common cathode.
@ SBK_BarMeter_SK28
Alias for SBK BarMeter SK28, uses the BL28_3005SK preset internally.
@ NONE
No preset selected; manual segment mapping is required.
@ BL28_3005SA
Native mapping for BL28-3005SA (7 anodes × 4 cathodes), common anode.
BarDirection
Direction of bar fill or animation progression.
@ REVERSE
From last segment to first.
@ FORWARD
From first segment to last.
Built-in animation engine for SBK_BarMeter-based LED displays.
SBK_BarDrive(DriverT *driver, uint8_t devIdx, const uint8_t(&mapping)[N][3], BarDirection direction=BarDirection::FORWARD, bool progmem=false, uint8_t rowOffset=0, uint8_t colOffset=0)
Construct a SBK_BarDrive using a custom pixel mapping array.
void clear()
Clear all bar segments.
uint8_t getPixelState(uint8_t segment)
Get the current state of a bar segment (pixel).
uint8_t getSegsNum()
Get the total number of segments in the bar.
void show()
Push the current LED state buffer to the physical display.
void setDirection(BarDirection dir)
Set the bar fill direction.
SBK_BarDrive(DriverT *driver, uint8_t devIdx, MatrixPreset matrixPreset, BarDirection direction=BarDirection::FORWARD, uint8_t rowOffset=0, uint8_t colOffset=0)
Construct a SBK_BarDrive using a predefined matrix-style layout.
void setPixel(uint8_t segment, uint8_t state)
Set the on/off state of a logical segment (LED).
SBK_BarDrive & setSegmentOffset(uint8_t offset)
Apply a segment-wise offset (shifts segment index before mapping to row/col).
SBK_BarDrive & setMatrixOffset(uint8_t rowOffset, uint8_t colOffset)
Apply a matrix-style physical offset for row/column positioning.
SBK_BarDrive(DriverT *driver, uint8_t devIdx, uint8_t segsNum, BarDirection direction=BarDirection::FORWARD, uint8_t segOffset=0)
Construct a SBK_BarDrive with a fixed number of vertical segments (non-matrix layout).
void debugSegmentMapping(Stream &stream=Serial)
Print the segment-to-device mapping for debugging purposes.
SBK_BarDrive(DriverT *driver, uint8_t devIdx, uint8_t rowsNum, uint8_t colsNum, BarDirection direction=BarDirection::FORWARD, uint8_t rowOffset=0, uint8_t colOffset=0)
Construct a SBK_BarDrive with a custom matrix size (rows × columns layout).
BarDirection getDirection()
Get the current bar fill direction.
SBK_BarMeterAnimations< SBK_BarMeter< DriverT > > & animations()
Get the animation controller instance (if enabled).
SBK_BarMeter< DriverT > & barmeter()
Get the underlying SBK_BarMeter instance.
Templated animation controller for SBK_BarMeter<T>.
Template class for controlling segment-based LED bar meters using row/column mappings.
SBK_BarMeter & setMatrixOffset(uint8_t rowOffset, uint8_t colOffset)
Apply a matrix-style physical offset for row/column positioning.
void debugSegmentMapping(Stream &stream=Serial)
Print the segment-to-device mapping for debugging purposes.
void clear()
Clear all bar segments.
SBK_BarMeter(DriverT *driver, uint8_t devIdx, uint8_t rowsNum, uint8_t colsNum, BarDirection direction=BarDirection::FORWARD, uint8_t rowOffset=0, uint8_t colOffset=0)
Construct a SBK_BarMeter with a custom matrix size (rows × columns layout).
void show()
Push the current LED state buffer to the physical display.
SBK_BarMeter(DriverT *driver, uint8_t devIdx, const uint8_t(&mapping)[N][3], BarDirection direction=BarDirection::FORWARD, bool progmem=false, uint8_t rowOffset=0, uint8_t colOffset=0)
Construct a SBK_BarMeter using a custom pixel mapping array.
SBK_BarMeter(DriverT *driver, uint8_t devIdx, MatrixPreset matrixPreset=MatrixPreset::BL28_3005SK, BarDirection direction=BarDirection::FORWARD, uint8_t rowOffset=0, uint8_t colOffset=0)
Construct a SBK_BarMeter using a predefined matrix-style layout.
void setDirection(BarDirection dir)
Set the bar fill direction.
BarDirection getDirection() const
Get the current bar fill direction.
SBK_BarMeter & setSegmentOffset(uint8_t offset)
Apply a segment-wise offset (shifts segment index before mapping to row/col).
void setPixel(uint8_t segment, uint8_t state)
Set the on/off state of a logical segment (LED).
uint8_t getPixelState(uint8_t segment) const
Get the current state of a bar segment (pixel).
SBK_BarMeter(DriverT *driver, uint8_t devIdx, uint8_t segsNum, BarDirection direction=BarDirection::FORWARD, uint8_t segOffset=0)
Construct a SBK_BarMeter with a fixed number of vertical segments (non-matrix layout).
uint8_t getSegsNum() const
Get the total number of segments in the bar.