forked from Makuna/NeoPixelBus
Seven segment (#293)
This commit is contained in:
36
examples/sevensegment/NeoSegmentBus/NeoSegmentBus.ino
Normal file
36
examples/sevensegment/NeoSegmentBus/NeoSegmentBus.ino
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
// NeoSegmentBus
|
||||||
|
// This example will demonstrate using the NeoSegmentBus which provides support for a
|
||||||
|
// seven segment LED digit driven by three WS2811; connected in series with other digits
|
||||||
|
//
|
||||||
|
// See https://shop.idlehandsdev.com/products/addressable-7-segment-display for a hardware example
|
||||||
|
//
|
||||||
|
// This example will print the string "3.14" and then rotate it through the available digits
|
||||||
|
//
|
||||||
|
|
||||||
|
#include <NeoPixelSegmentBus.h>
|
||||||
|
|
||||||
|
const uint16_t DigitCount = 4; // Max Digits, not segments, not pixels
|
||||||
|
const uint8_t BusPin = 2; // make sure to set this to the correct pin, ignored for Esp8266
|
||||||
|
|
||||||
|
#define brightness 128
|
||||||
|
|
||||||
|
NeoPixelSegmentBus<SevenSegmentFeature, Neo800KbpsMethod> strip(DigitCount, BusPin);
|
||||||
|
|
||||||
|
void setup()
|
||||||
|
{
|
||||||
|
strip.Begin();
|
||||||
|
strip.Show(); // clears all digits by default
|
||||||
|
|
||||||
|
delay(500);
|
||||||
|
strip.SetString(0, "3.14", brightness);
|
||||||
|
strip.Show();
|
||||||
|
}
|
||||||
|
|
||||||
|
void loop()
|
||||||
|
{
|
||||||
|
delay(2000);
|
||||||
|
|
||||||
|
strip.RotateLeft(1);
|
||||||
|
strip.Show();
|
||||||
|
}
|
||||||
|
|
144
examples/sevensegment/NeoSegmentFade/NeoSegmentFade.ino
Normal file
144
examples/sevensegment/NeoSegmentFade/NeoSegmentFade.ino
Normal file
@@ -0,0 +1,144 @@
|
|||||||
|
// NeoSegmentBus
|
||||||
|
// This example will demonstrate using the NeoSegmentBus which provides support for a
|
||||||
|
// seven segment LED digit driven by three WS2811; connected in series with other digits
|
||||||
|
//
|
||||||
|
// See https://shop.idlehandsdev.com/products/addressable-7-segment-display for a hardware example
|
||||||
|
//
|
||||||
|
// This example will print current seconds since start of the Arduino
|
||||||
|
// with a digit animating a circling path for each second
|
||||||
|
//
|
||||||
|
|
||||||
|
#include <NeoPixelSegmentBus.h>
|
||||||
|
#include <NeoPixelAnimator.h>
|
||||||
|
|
||||||
|
const uint16_t DigitCount = 5; // Max Digits, not segments, not pixels
|
||||||
|
const uint8_t BusPin = 2; // make sure to set this to the correct pin, ignored for Esp8266
|
||||||
|
const uint16_t CycleDigit = 0;
|
||||||
|
const uint16_t SecondsDigit = 1;
|
||||||
|
|
||||||
|
#define brightness 128
|
||||||
|
|
||||||
|
NeoPixelSegmentBus<SevenSegmentFeature, Neo800KbpsMethod> strip(DigitCount, BusPin);
|
||||||
|
|
||||||
|
enum Animation
|
||||||
|
{
|
||||||
|
Animation_Cycle, // animation for the cycle indicator
|
||||||
|
Animation_Fade, // animation for fade of seconds
|
||||||
|
Animation_COUNT
|
||||||
|
};
|
||||||
|
|
||||||
|
NeoPixelAnimator animations(Animation_COUNT);
|
||||||
|
|
||||||
|
void CycleAnimation(const AnimationParam& param)
|
||||||
|
{
|
||||||
|
// calculate which segment should be on using the animation progress
|
||||||
|
uint8_t bitfield = 1 << (uint8_t)(param.progress * LedSegment_F);
|
||||||
|
// instant a digit with that segment on
|
||||||
|
SevenSegDigit digit(bitfield, brightness);
|
||||||
|
// apply it to the strip
|
||||||
|
strip.SetPixelColor(CycleDigit, digit);
|
||||||
|
}
|
||||||
|
|
||||||
|
// for the animation of fading the new number in, we use
|
||||||
|
// two digit DIBs (Device Independant Bitmaps) of SevenSegDigit to blend with;
|
||||||
|
// each sized one less than the strip due to the first is a used for the cycle
|
||||||
|
// animation.
|
||||||
|
typedef NeoDib<SevenSegDigit> SevenSegDib;
|
||||||
|
|
||||||
|
SevenSegDib StartingDigits(DigitCount - 1);
|
||||||
|
SevenSegDib EndingDigits(DigitCount - 1);
|
||||||
|
|
||||||
|
// shader class that will do the "string" blending
|
||||||
|
//
|
||||||
|
class DigitBlendShader
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
// this shader always renders and doesn't track a dirty state
|
||||||
|
bool IsDirty() const
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ResetDirty()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
SevenSegDigit Apply(uint16_t indexDigit, SevenSegDigit digit)
|
||||||
|
{
|
||||||
|
// since we call EndingDigits.Render below, the digit argument is
|
||||||
|
// from the EndingDigits so no need to call GetPixelColor to get it
|
||||||
|
// create a digit that is a blend between the last seconds
|
||||||
|
// value and the next seconds value using the BlendAmount
|
||||||
|
SevenSegDigit blendDigit = SevenSegDigit::LinearBlend(
|
||||||
|
StartingDigits.GetPixelColor(indexDigit),
|
||||||
|
digit,
|
||||||
|
BlendAmount);
|
||||||
|
|
||||||
|
return blendDigit;
|
||||||
|
}
|
||||||
|
|
||||||
|
float BlendAmount;
|
||||||
|
};
|
||||||
|
|
||||||
|
// the instance of our shader class
|
||||||
|
DigitBlendShader blendShader;
|
||||||
|
|
||||||
|
void FadeAnimation(const AnimationParam& param)
|
||||||
|
{
|
||||||
|
// set the shader property BlendAmount to the animation progress
|
||||||
|
blendShader.BlendAmount = param.progress;
|
||||||
|
// apply it to the strip at the SecondsDigit location
|
||||||
|
EndingDigits.Render<SevenSegmentFeature, DigitBlendShader>(strip,
|
||||||
|
blendShader,
|
||||||
|
SecondsDigit);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t lastSeconds;
|
||||||
|
|
||||||
|
void setup()
|
||||||
|
{
|
||||||
|
lastSeconds = millis() / 1000;
|
||||||
|
|
||||||
|
strip.Begin();
|
||||||
|
strip.Show();
|
||||||
|
|
||||||
|
// init animation Dibs as cleared
|
||||||
|
StartingDigits.ClearTo(0);
|
||||||
|
EndingDigits.ClearTo(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void loop()
|
||||||
|
{
|
||||||
|
uint32_t seconds = millis() / 1000;
|
||||||
|
|
||||||
|
// when the seconds change, start animations for the update
|
||||||
|
//
|
||||||
|
if (seconds != lastSeconds)
|
||||||
|
{
|
||||||
|
// copy last animation ending digits as starting digits
|
||||||
|
StartingDigits = EndingDigits;
|
||||||
|
|
||||||
|
// format and display new value in ending digits dib
|
||||||
|
String display(seconds);
|
||||||
|
SevenSegDigit::SetString<SevenSegDib>(EndingDigits,
|
||||||
|
0,
|
||||||
|
display.c_str(),
|
||||||
|
brightness);
|
||||||
|
|
||||||
|
// start the seconds fade animation
|
||||||
|
animations.StartAnimation(Animation_Fade, 1000, FadeAnimation);
|
||||||
|
|
||||||
|
// start the cycle animation for the next second
|
||||||
|
animations.StartAnimation(Animation_Cycle, 1000, CycleAnimation);
|
||||||
|
|
||||||
|
lastSeconds = seconds;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (animations.IsAnimating())
|
||||||
|
{
|
||||||
|
// the normal loop just needs these two to run the active animations
|
||||||
|
animations.UpdateAnimations();
|
||||||
|
strip.Show();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@@ -153,7 +153,6 @@ private:
|
|||||||
_duration = duration;
|
_duration = duration;
|
||||||
_remaining = duration;
|
_remaining = duration;
|
||||||
_fnCallback = animUpdate;
|
_fnCallback = animUpdate;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void StopAnimation()
|
void StopAnimation()
|
||||||
|
@@ -43,10 +43,12 @@ License along with NeoPixel. If not, see
|
|||||||
#include "internal/HsbColor.h"
|
#include "internal/HsbColor.h"
|
||||||
#include "internal/HtmlColor.h"
|
#include "internal/HtmlColor.h"
|
||||||
#include "internal/RgbwColor.h"
|
#include "internal/RgbwColor.h"
|
||||||
|
#include "internal/SegmentDigit.h"
|
||||||
|
|
||||||
#include "internal/NeoColorFeatures.h"
|
#include "internal/NeoColorFeatures.h"
|
||||||
#include "internal/DotStarColorFeatures.h"
|
#include "internal/DotStarColorFeatures.h"
|
||||||
#include "internal/Lpd8806ColorFeatures.h"
|
#include "internal/Lpd8806ColorFeatures.h"
|
||||||
|
#include "internal/NeoSegmentFeatures.h"
|
||||||
|
|
||||||
#include "internal/Layouts.h"
|
#include "internal/Layouts.h"
|
||||||
#include "internal/NeoTopology.h"
|
#include "internal/NeoTopology.h"
|
||||||
|
67
src/NeoPixelSegmentBus.h
Normal file
67
src/NeoPixelSegmentBus.h
Normal file
@@ -0,0 +1,67 @@
|
|||||||
|
/*-------------------------------------------------------------------------
|
||||||
|
NeoPixelBus library wrapper template class that provides enhanced methods
|
||||||
|
for writing to segment based strips
|
||||||
|
|
||||||
|
Written by Michael C. Miller.
|
||||||
|
|
||||||
|
I invest time and resources providing this open source code,
|
||||||
|
please support me by dontating (see https://github.com/Makuna/NeoPixelBus)
|
||||||
|
|
||||||
|
-------------------------------------------------------------------------
|
||||||
|
This file is part of the Makuna/NeoPixelBus library.
|
||||||
|
|
||||||
|
NeoPixelBus is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU Lesser General Public License as
|
||||||
|
published by the Free Software Foundation, either version 3 of
|
||||||
|
the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
NeoPixelBus is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU Lesser General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public
|
||||||
|
License along with NeoPixel. If not, see
|
||||||
|
<http://www.gnu.org/licenses/>.
|
||||||
|
-------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "NeoPixelBus.h"
|
||||||
|
|
||||||
|
template<typename T_COLOR_FEATURE, typename T_METHOD> class NeoPixelSegmentBus :
|
||||||
|
public NeoPixelBus<T_COLOR_FEATURE, T_METHOD>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
NeoPixelSegmentBus(uint16_t countPixels, uint8_t pin) :
|
||||||
|
NeoPixelBus<T_COLOR_FEATURE, T_METHOD>(countPixels, pin)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
NeoPixelSegmentBus(uint16_t countPixels) :
|
||||||
|
NeoPixelBus<T_COLOR_FEATURE, T_METHOD>(countPixels)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetString(uint16_t indexDigit,
|
||||||
|
const char* str,
|
||||||
|
uint8_t brightness,
|
||||||
|
uint8_t defaultBrightness = 0)
|
||||||
|
{
|
||||||
|
T_COLOR_FEATURE::ColorObject::SetString(*this,
|
||||||
|
indexDigit,
|
||||||
|
str,
|
||||||
|
brightness,
|
||||||
|
defaultBrightness);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetString(uint16_t indexDigit,
|
||||||
|
const String& str,
|
||||||
|
uint8_t brightness,
|
||||||
|
uint8_t defaultBrightness = 0)
|
||||||
|
{
|
||||||
|
SetString(indexDigit, str.c_str(), brightness, defaultBrightness);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
@@ -45,9 +45,10 @@ public:
|
|||||||
uint8_t* pEnd = pPixelDest + (count * PixelSize);
|
uint8_t* pEnd = pPixelDest + (count * PixelSize);
|
||||||
while (pPixelDest < pEnd)
|
while (pPixelDest < pEnd)
|
||||||
{
|
{
|
||||||
*pPixelDest++ = pPixelSrc[0];
|
for (uint8_t iElement = 0; iElement < PixelSize; iElement++)
|
||||||
*pPixelDest++ = pPixelSrc[1];
|
{
|
||||||
*pPixelDest++ = pPixelSrc[2];
|
*pPixelDest++ = pPixelSrc[iElement];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -57,8 +58,6 @@ public:
|
|||||||
while (pPixelDest < pEnd)
|
while (pPixelDest < pEnd)
|
||||||
{
|
{
|
||||||
*pPixelDest++ = *pPixelSrc++;
|
*pPixelDest++ = *pPixelSrc++;
|
||||||
*pPixelDest++ = *pPixelSrc++;
|
|
||||||
*pPixelDest++ = *pPixelSrc++;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -69,8 +68,6 @@ public:
|
|||||||
while (pPixelDest < pEnd)
|
while (pPixelDest < pEnd)
|
||||||
{
|
{
|
||||||
*pPixelDest++ = pgm_read_byte(pSrc++);
|
*pPixelDest++ = pgm_read_byte(pSrc++);
|
||||||
*pPixelDest++ = pgm_read_byte(pSrc++);
|
|
||||||
*pPixelDest++ = pgm_read_byte(pSrc++);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -81,8 +78,6 @@ public:
|
|||||||
while (pDestBack > pPixelDest)
|
while (pDestBack > pPixelDest)
|
||||||
{
|
{
|
||||||
*--pDestBack = *--pSrcBack;
|
*--pDestBack = *--pSrcBack;
|
||||||
*--pDestBack = *--pSrcBack;
|
|
||||||
*--pDestBack = *--pSrcBack;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -94,6 +94,25 @@ public:
|
|||||||
free((uint8_t*)_pixels);
|
free((uint8_t*)_pixels);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NeoDib& operator=(const NeoDib& other)
|
||||||
|
{
|
||||||
|
// check for self-assignment
|
||||||
|
if (&other == this)
|
||||||
|
{
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t copyCount = other.PixelCount() < PixelCount() ? other.PixelCount() : PixelCount();
|
||||||
|
|
||||||
|
for (uint16_t pixel = 0; pixel < copyCount; pixel++)
|
||||||
|
{
|
||||||
|
_pixels[pixel] = other.Pixels()[pixel];
|
||||||
|
}
|
||||||
|
|
||||||
|
Dirty();
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
T_COLOR_OBJECT* Pixels() const
|
T_COLOR_OBJECT* Pixels() const
|
||||||
{
|
{
|
||||||
return _pixels;
|
return _pixels;
|
||||||
@@ -144,8 +163,8 @@ public:
|
|||||||
Dirty();
|
Dirty();
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename T_COLOR_FEATURE, typename T_SHADER> void Render(NeoBufferContext<T_COLOR_FEATURE> destBuffer,
|
template <typename T_COLOR_FEATURE, typename T_SHADER>
|
||||||
T_SHADER& shader)
|
void Render(NeoBufferContext<T_COLOR_FEATURE> destBuffer, T_SHADER& shader, uint16_t destIndexPixel = 0)
|
||||||
{
|
{
|
||||||
if (IsDirty() || shader.IsDirty())
|
if (IsDirty() || shader.IsDirty())
|
||||||
{
|
{
|
||||||
@@ -159,7 +178,7 @@ public:
|
|||||||
for (uint16_t indexPixel = 0; indexPixel < countPixels; indexPixel++)
|
for (uint16_t indexPixel = 0; indexPixel < countPixels; indexPixel++)
|
||||||
{
|
{
|
||||||
T_COLOR_OBJECT color = shader.Apply(indexPixel, _pixels[indexPixel]);
|
T_COLOR_OBJECT color = shader.Apply(indexPixel, _pixels[indexPixel]);
|
||||||
T_COLOR_FEATURE::applyPixelColor(destBuffer.Pixels, indexPixel, color);
|
T_COLOR_FEATURE::applyPixelColor(destBuffer.Pixels, destIndexPixel + indexPixel, color);
|
||||||
}
|
}
|
||||||
|
|
||||||
shader.ResetDirty();
|
shader.ResetDirty();
|
||||||
|
130
src/internal/NeoSegmentFeatures.h
Normal file
130
src/internal/NeoSegmentFeatures.h
Normal file
@@ -0,0 +1,130 @@
|
|||||||
|
/*-------------------------------------------------------------------------
|
||||||
|
NeoSegmentFeatures provides feature classes to describe seven segment display
|
||||||
|
elements for NeoPixelBus template class
|
||||||
|
|
||||||
|
Written by Michael C. Miller.
|
||||||
|
|
||||||
|
I invest time and resources providing this open source code,
|
||||||
|
please support me by dontating (see https://github.com/Makuna/NeoPixelBus)
|
||||||
|
|
||||||
|
-------------------------------------------------------------------------
|
||||||
|
This file is part of the Makuna/NeoPixelBus library.
|
||||||
|
|
||||||
|
NeoPixelBus is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU Lesser General Public License as
|
||||||
|
published by the Free Software Foundation, either version 3 of
|
||||||
|
the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
NeoPixelBus is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU Lesser General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public
|
||||||
|
License along with NeoPixel. If not, see
|
||||||
|
<http://www.gnu.org/licenses/>.
|
||||||
|
-------------------------------------------------------------------------*/
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
class Neo9Elements
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
static const size_t PixelSize = 9; // three 3 element
|
||||||
|
|
||||||
|
static uint8_t* getPixelAddress(uint8_t* pPixels, uint16_t indexPixel)
|
||||||
|
{
|
||||||
|
return pPixels + indexPixel * PixelSize;
|
||||||
|
}
|
||||||
|
static const uint8_t* getPixelAddress(const uint8_t* pPixels, uint16_t indexPixel)
|
||||||
|
{
|
||||||
|
return pPixels + indexPixel * PixelSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void replicatePixel(uint8_t* pPixelDest, const uint8_t* pPixelSrc, uint16_t count)
|
||||||
|
{
|
||||||
|
uint8_t* pEnd = pPixelDest + (count * PixelSize);
|
||||||
|
while (pPixelDest < pEnd)
|
||||||
|
{
|
||||||
|
for (uint8_t iElement = 0; iElement < PixelSize; iElement++)
|
||||||
|
{
|
||||||
|
*pPixelDest++ = pPixelSrc[iElement];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void movePixelsInc(uint8_t* pPixelDest, const uint8_t* pPixelSrc, uint16_t count)
|
||||||
|
{
|
||||||
|
uint8_t* pEnd = pPixelDest + (count * PixelSize);
|
||||||
|
while (pPixelDest < pEnd)
|
||||||
|
{
|
||||||
|
*pPixelDest++ = *pPixelSrc++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void movePixelsInc_P(uint8_t* pPixelDest, PGM_VOID_P pPixelSrc, uint16_t count)
|
||||||
|
{
|
||||||
|
uint8_t* pEnd = pPixelDest + (count * PixelSize);
|
||||||
|
const uint8_t* pSrc = (const uint8_t*)pPixelSrc;
|
||||||
|
while (pPixelDest < pEnd)
|
||||||
|
{
|
||||||
|
*pPixelDest++ = pgm_read_byte(pSrc++);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void movePixelsDec(uint8_t* pPixelDest, const uint8_t* pPixelSrc, uint16_t count)
|
||||||
|
{
|
||||||
|
uint8_t* pDestBack = pPixelDest + (count * PixelSize);
|
||||||
|
const uint8_t* pSrcBack = pPixelSrc + (count * PixelSize);
|
||||||
|
while (pDestBack > pPixelDest)
|
||||||
|
{
|
||||||
|
*--pDestBack = *--pSrcBack;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef SevenSegDigit ColorObject;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Abcdefg byte order
|
||||||
|
class NeoAbcdefgSegmentFeature : public Neo9Elements
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
static void applyPixelColor(uint8_t* pPixels, uint16_t indexPixel, ColorObject color)
|
||||||
|
{
|
||||||
|
uint8_t* p = getPixelAddress(pPixels, indexPixel);
|
||||||
|
uint8_t commonSize = (PixelSize < color.SegmentCount) ? PixelSize : color.SegmentCount;
|
||||||
|
for (uint8_t iSegment = 0; iSegment < commonSize; iSegment++)
|
||||||
|
{
|
||||||
|
*p++ = color.Segment[iSegment];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static ColorObject retrievePixelColor(uint8_t* pPixels, uint16_t indexPixel)
|
||||||
|
{
|
||||||
|
ColorObject color;
|
||||||
|
uint8_t* p = getPixelAddress(pPixels, indexPixel);
|
||||||
|
uint8_t commonSize = (PixelSize < color.SegmentCount) ? PixelSize : color.SegmentCount;
|
||||||
|
|
||||||
|
for (uint8_t iSegment = 0; iSegment < commonSize; iSegment++)
|
||||||
|
{
|
||||||
|
color.Segment[iSegment] = *p++;
|
||||||
|
}
|
||||||
|
return color;
|
||||||
|
}
|
||||||
|
|
||||||
|
static ColorObject retrievePixelColor_P(PGM_VOID_P pPixels, uint16_t indexPixel)
|
||||||
|
{
|
||||||
|
ColorObject color;
|
||||||
|
const uint8_t* p = getPixelAddress((const uint8_t*)pPixels, indexPixel);
|
||||||
|
uint8_t commonSize = (PixelSize < color.SegmentCount) ? PixelSize : color.SegmentCount;
|
||||||
|
|
||||||
|
for (uint8_t iSegment = 0; iSegment < commonSize; iSegment++)
|
||||||
|
{
|
||||||
|
color.Segment[iSegment] = pgm_read_byte(p++);
|
||||||
|
}
|
||||||
|
|
||||||
|
return color;
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef NeoAbcdefgSegmentFeature SevenSegmentFeature; // Abcdefg order is default
|
153
src/internal/SegmentDigit.cpp
Normal file
153
src/internal/SegmentDigit.cpp
Normal file
@@ -0,0 +1,153 @@
|
|||||||
|
/*-------------------------------------------------------------------------
|
||||||
|
SegmentDigit provides a color object that can be directly consumed by NeoPixelBus
|
||||||
|
|
||||||
|
Written by Michael C. Miller.
|
||||||
|
|
||||||
|
I invest time and resources providing this open source code,
|
||||||
|
please support me by dontating (see https://github.com/Makuna/NeoPixelBus)
|
||||||
|
|
||||||
|
-------------------------------------------------------------------------
|
||||||
|
This file is part of the Makuna/NeoPixelBus library.
|
||||||
|
|
||||||
|
NeoPixelBus is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU Lesser General Public License as
|
||||||
|
published by the Free Software Foundation, either version 3 of
|
||||||
|
the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
NeoPixelBus is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU Lesser General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public
|
||||||
|
License along with NeoPixel. If not, see
|
||||||
|
<http://www.gnu.org/licenses/>.
|
||||||
|
-------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
#include "SegmentDigit.h"
|
||||||
|
|
||||||
|
//
|
||||||
|
// https://en.wikichip.org/wiki/seven-segment_display/representing_letters
|
||||||
|
//
|
||||||
|
const uint8_t SevenSegDigit::DecodeNumbers[] = {
|
||||||
|
// 0 1 2 3 4 5 6 7 8 9
|
||||||
|
0x3F, 0x06, 0x5B, 0x4F, 0x66, 0x6D, 0x7D, 0x07, 0x7F, 0x6F };
|
||||||
|
|
||||||
|
const uint8_t SevenSegDigit::DecodeAlphaCaps[] = {
|
||||||
|
// A B C D E F G
|
||||||
|
0x77, 0x00, 0x39, 0x00, 0x79, 0x71, 0x3D,
|
||||||
|
// H I J K L M N
|
||||||
|
0x76, 0x30, 0x1E, 0x00, 0x38, 0x00, 0x00,
|
||||||
|
// O P Q R S
|
||||||
|
0x3F, 0x73, 0x00, 0x00, 0x6D,
|
||||||
|
// T U V W X Y Z
|
||||||
|
0x00, 0x3E, 0x00, 0x00, 0x00, 0x00, 0x00 };
|
||||||
|
|
||||||
|
const uint8_t SevenSegDigit::DecodeAlpha[] = {
|
||||||
|
// a b c d e f g
|
||||||
|
0x00, 0x7C, 0x58, 0x5E, 0x00, 0x00, 0x00,
|
||||||
|
// h i j k l m n
|
||||||
|
0x74, 0x00, 0x00, 0x00, 0x00, 0x00, 0x54,
|
||||||
|
// o p q r s
|
||||||
|
0x5C, 0x00, 0x67, 0x50, 0x00,
|
||||||
|
// t u v w x y z
|
||||||
|
0x78, 0x1C, 0x00, 0x00, 0x00, 0x6E, 0x00 };
|
||||||
|
|
||||||
|
const uint8_t SevenSegDigit::DecodeSpecial[] = {
|
||||||
|
// , - . /
|
||||||
|
0x80, 0x40, 0x80, 0x40 };
|
||||||
|
|
||||||
|
void SevenSegDigit::init(uint8_t bitmask, uint8_t brightness, uint8_t defaultBrightness)
|
||||||
|
{
|
||||||
|
for (uint8_t iSegment = 0; iSegment < SegmentCount; iSegment++)
|
||||||
|
{
|
||||||
|
Segment[iSegment] = (bitmask & 0x01) ? brightness : defaultBrightness;
|
||||||
|
bitmask >>= 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SevenSegDigit::SevenSegDigit(uint8_t bitmask, uint8_t brightness, uint8_t defaultBrightness)
|
||||||
|
{
|
||||||
|
init(bitmask, brightness, defaultBrightness);
|
||||||
|
};
|
||||||
|
|
||||||
|
SevenSegDigit::SevenSegDigit(char letter, uint8_t brightness, uint8_t defaultBrightness)
|
||||||
|
{
|
||||||
|
if (letter >= '0' && letter <= '9')
|
||||||
|
{
|
||||||
|
init(DecodeNumbers[letter - '0'], brightness, defaultBrightness);
|
||||||
|
}
|
||||||
|
else if (letter >= 'a' && letter <= 'z')
|
||||||
|
{
|
||||||
|
init(DecodeAlpha[letter - 'a'], brightness, defaultBrightness);
|
||||||
|
}
|
||||||
|
else if (letter >= 'A' && letter <= 'Z')
|
||||||
|
{
|
||||||
|
init(DecodeAlphaCaps[letter - 'A'], brightness, defaultBrightness);
|
||||||
|
}
|
||||||
|
else if (letter >= ',' && letter <= '/')
|
||||||
|
{
|
||||||
|
init(DecodeSpecial[letter - ','], brightness, defaultBrightness);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
memset(Segment, defaultBrightness, sizeof(Segment));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
uint8_t SevenSegDigit::CalculateBrightness() const
|
||||||
|
{
|
||||||
|
uint16_t sum = 0;
|
||||||
|
|
||||||
|
for (uint8_t iSegment = 0; iSegment < SegmentCount; iSegment++)
|
||||||
|
{
|
||||||
|
sum += Segment[iSegment];
|
||||||
|
}
|
||||||
|
|
||||||
|
return (uint8_t)(sum / SegmentCount);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SevenSegDigit::Darken(uint8_t delta)
|
||||||
|
{
|
||||||
|
for (uint8_t iSegment = 0; iSegment < SegmentCount; iSegment++)
|
||||||
|
{
|
||||||
|
uint8_t element = Segment[iSegment];
|
||||||
|
if (element > delta)
|
||||||
|
{
|
||||||
|
element -= delta;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
element = 0;
|
||||||
|
}
|
||||||
|
Segment[iSegment] = element;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SevenSegDigit::Lighten(uint8_t delta)
|
||||||
|
{
|
||||||
|
for (uint8_t iSegment = 0; iSegment < SegmentCount; iSegment++)
|
||||||
|
{
|
||||||
|
uint8_t element = Segment[iSegment];
|
||||||
|
if (element < 255 - delta)
|
||||||
|
{
|
||||||
|
element += delta;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
element = 255;
|
||||||
|
}
|
||||||
|
Segment[iSegment] = element;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SevenSegDigit SevenSegDigit::LinearBlend(const SevenSegDigit& left, const SevenSegDigit& right, float progress)
|
||||||
|
{
|
||||||
|
SevenSegDigit result;
|
||||||
|
|
||||||
|
for (uint8_t iSegment = 0; iSegment < SegmentCount; iSegment++)
|
||||||
|
{
|
||||||
|
result.Segment[iSegment] = left.Segment[iSegment] + ((right.Segment[iSegment] - left.Segment[iSegment]) * progress);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
202
src/internal/SegmentDigit.h
Normal file
202
src/internal/SegmentDigit.h
Normal file
@@ -0,0 +1,202 @@
|
|||||||
|
/*-------------------------------------------------------------------------
|
||||||
|
SegmentDigit provides a color object that can be directly consumed by NeoPixelBus
|
||||||
|
|
||||||
|
Written by Michael C. Miller.
|
||||||
|
|
||||||
|
I invest time and resources providing this open source code,
|
||||||
|
please support me by dontating (see https://github.com/Makuna/NeoPixelBus)
|
||||||
|
|
||||||
|
-------------------------------------------------------------------------
|
||||||
|
This file is part of the Makuna/NeoPixelBus library.
|
||||||
|
|
||||||
|
NeoPixelBus is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU Lesser General Public License as
|
||||||
|
published by the Free Software Foundation, either version 3 of
|
||||||
|
the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
NeoPixelBus is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU Lesser General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public
|
||||||
|
License along with NeoPixel. If not, see
|
||||||
|
<http://www.gnu.org/licenses/>.
|
||||||
|
-------------------------------------------------------------------------*/
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <Arduino.h>
|
||||||
|
|
||||||
|
enum LedSegment
|
||||||
|
{
|
||||||
|
LedSegment_A,
|
||||||
|
LedSegment_B,
|
||||||
|
LedSegment_C,
|
||||||
|
LedSegment_D,
|
||||||
|
LedSegment_E,
|
||||||
|
LedSegment_F,
|
||||||
|
LedSegment_G,
|
||||||
|
LedSegment_Decimal,
|
||||||
|
LedSegment_COUNT
|
||||||
|
};
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
// SevenSegDigit represents a color object that is represented by the segments
|
||||||
|
// of a 7 segment LED display digit. It contains helpful routines to manipulate
|
||||||
|
// and set the elements.
|
||||||
|
//
|
||||||
|
// The order represents the physical LED location starting at A, through to G, then
|
||||||
|
// ending at the decimal point
|
||||||
|
// "abcdefg."
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
struct SevenSegDigit
|
||||||
|
{
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
// Construct a SevenSegDigit using
|
||||||
|
// the default brightness to apply to all segments
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
SevenSegDigit(uint8_t defaultBrightness)
|
||||||
|
{
|
||||||
|
memset(Segment, defaultBrightness, sizeof(Segment));
|
||||||
|
}
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
// Construct a SevenSegDigit using
|
||||||
|
// a bitmask for the segment (bit order is ".gfedcba")
|
||||||
|
// the brightness to apply to them, (0-255)
|
||||||
|
// the default brightness to apply to those not set in the bitmask (0-255)
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
SevenSegDigit(uint8_t bitmask, uint8_t brightness, uint8_t defaultBrightness = 0);
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
// Construct a SevenSegDigit using
|
||||||
|
// a char that will get mapped to the segments,
|
||||||
|
// the brightness to apply to them, (0-255)
|
||||||
|
// the default brightness to apply to those not set in the bitmask (0-255)
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
SevenSegDigit(char letter, uint8_t brightness, uint8_t defaultBrightness = 0);
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
// Construct a SevenSegDigit that will have its values set in latter operations
|
||||||
|
// CAUTION: The members are not initialized and may not be consistent
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
SevenSegDigit()
|
||||||
|
{
|
||||||
|
};
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
// Comparison operators
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
bool operator==(const SevenSegDigit& other) const
|
||||||
|
{
|
||||||
|
for (uint8_t iSegment = 0; iSegment < SegmentCount; iSegment++)
|
||||||
|
{
|
||||||
|
if (Segment[iSegment] != other.Segment[iSegment])
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
|
||||||
|
bool operator!=(const SevenSegDigit& other) const
|
||||||
|
{
|
||||||
|
return !(*this == other);
|
||||||
|
};
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
// CalculateBrightness will calculate the overall brightness
|
||||||
|
// NOTE: This is a simple linear brightness
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
uint8_t CalculateBrightness() const;
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
// Darken will adjust the color by the given delta toward black
|
||||||
|
// NOTE: This is a simple linear change
|
||||||
|
// delta - (0-255) the amount to dim the segment
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
void Darken(uint8_t delta);
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
// Lighten will adjust the color by the given delta toward white
|
||||||
|
// NOTE: This is a simple linear change
|
||||||
|
// delta - (0-255) the amount to lighten the segment
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
void Lighten(uint8_t delta);
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
// LinearBlend between two colors by the amount defined by progress variable
|
||||||
|
// left - the segment to start the blend at
|
||||||
|
// right - the segment to end the blend at
|
||||||
|
// progress - (0.0 - 1.0) value where 0 will return left and 1.0 will return right
|
||||||
|
// and a value between will blend the brightness of each element
|
||||||
|
// weighted linearly between them
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
static SevenSegDigit LinearBlend(const SevenSegDigit& left, const SevenSegDigit& right, float progress);
|
||||||
|
|
||||||
|
template <typename T_SET_TARGET>
|
||||||
|
static void SetString(T_SET_TARGET& target, uint16_t indexDigit, const char* str, uint8_t brightness, uint8_t defaultBrightness = 0)
|
||||||
|
{
|
||||||
|
if (str == nullptr)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* pFirst = str;
|
||||||
|
const char* pIter = str;
|
||||||
|
|
||||||
|
// digits are right to left
|
||||||
|
// so find the end
|
||||||
|
while (*pIter != '\0')
|
||||||
|
{
|
||||||
|
pIter++;
|
||||||
|
}
|
||||||
|
pIter--;
|
||||||
|
|
||||||
|
|
||||||
|
while (pIter >= pFirst)
|
||||||
|
{
|
||||||
|
bool decimal = false;
|
||||||
|
char value = *pIter;
|
||||||
|
|
||||||
|
// check if merging a decimal is required
|
||||||
|
if (pIter > pFirst && (*pIter == '.' || *pIter == ','))
|
||||||
|
{
|
||||||
|
// merge a decimal as long as they aren't the same
|
||||||
|
if (*(pIter - 1) != *pIter)
|
||||||
|
{
|
||||||
|
decimal = true;
|
||||||
|
pIter--;
|
||||||
|
value = *pIter; // use the next char
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SevenSegDigit digit(value, brightness, defaultBrightness);
|
||||||
|
if (decimal)
|
||||||
|
{
|
||||||
|
digit.Segment[LedSegment_Decimal] = brightness;
|
||||||
|
}
|
||||||
|
target.SetPixelColor(indexDigit, digit);
|
||||||
|
indexDigit++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
// segment members (0-255) where each represents the segment location
|
||||||
|
// and the value defines the brightnes (0) is off and (255) is full brightness
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
static const uint8_t SegmentCount = 9;
|
||||||
|
uint8_t Segment[SegmentCount];
|
||||||
|
|
||||||
|
|
||||||
|
// segment decode maps from ascii relative first char in map to a bitmask of segments
|
||||||
|
//
|
||||||
|
static const uint8_t DecodeNumbers[10]; // 0-9
|
||||||
|
static const uint8_t DecodeAlphaCaps[26]; // A-Z
|
||||||
|
static const uint8_t DecodeAlpha[26]; // a-z
|
||||||
|
static const uint8_t DecodeSpecial[4]; // , - . /
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void init(uint8_t bitmask, uint8_t brightness, uint8_t defaultBrightness);
|
||||||
|
};
|
||||||
|
|
Reference in New Issue
Block a user