26 #include "StyledDigit.h" 33 #define ACE_SEGMENT_USE_INVERSE_PULSE_FRAMES 1 38 uint16_t nowMicros = mHardware->
micros();
49 mLastRenderFieldMicros = nowMicros;
55 mFramesPerBlinkSlow = (uint32_t) mFramesPerSecond
56 * mBlinkSlowDurationMillis / 1000;
57 mCurrentBlinkSlowFrame = 0;
60 mFramesPerBlinkFast = (uint32_t) mFramesPerSecond
61 * mBlinkFastDurationMillis / 1000;
62 mCurrentBlinkFastFrame = 0;
65 mFramesPerPulseSlow = (uint32_t) mFramesPerSecond
66 * mPulseSlowDurationMillis / 1000;
67 mFramesPerPulseSlowInverse = (uint32_t) 65536 * 1000
68 / mFramesPerSecond / mPulseSlowDurationMillis;
69 mCurrentPulseSlowFrame = 0;
72 mFramesPerPulseFast = (uint32_t) mFramesPerSecond
73 * mPulseFastDurationMillis / 1000;
74 mFramesPerPulseFastInverse = (uint32_t) 65536 * 1000
75 / mFramesPerSecond / mPulseFastDurationMillis;
76 mCurrentPulseFastFrame = 0;
80 if (digit >= mNumDigits)
return;
82 styledDigit.pattern = pattern;
83 styledDigit.style = style;
87 if (digit >= mNumDigits)
return;
89 styledDigit.pattern = pattern;
93 if (digit >= mNumDigits)
return;
95 styledDigit.style = style;
99 if (digit >= mNumDigits)
return;
102 styledDigit.setDecimalPoint();
104 styledDigit.clearDecimalPoint();
109 uint16_t now = mHardware->
micros();
110 uint16_t elapsedMicros = now - mLastRenderFieldMicros;
111 if (elapsedMicros >= mMicrosPerField) {
113 mLastRenderFieldMicros = now;
118 uint16_t now = mHardware->
micros();
119 if (mCurrentField == 0) {
125 uint16_t duration = mHardware->
micros() - now;
126 mStats.update(duration);
132 if (mStatsResetInterval > 0 &&
133 mStats.
getCount() >= mStatsResetInterval) {
146 for (uint8_t digit = 0; digit < mNumDigits; digit++) {
148 StyledDigit::StyleType style = styledDigit.style;
150 mBlinkSlowState, mBlinkFastState, mIsPulseEnabled,
151 mPulseSlowFraction, mPulseFastFraction);
152 mDriver->
setPattern(digit, styledDigit.pattern, brightness);
157 uint8_t blinkSlowState, uint8_t blinkFastState,
bool isPulseEnabled,
158 uint8_t pulseSlowFraction, uint8_t pulseFastFraction) {
161 case StyledDigit::kStyleNormal:
163 case StyledDigit::kStyleBlinkSlow:
164 return (blinkSlowState == kBlinkStateOff) ? 0 : brightness;
165 case StyledDigit::kStyleBlinkFast:
166 return (blinkFastState == kBlinkStateOff) ? 0 : brightness;
167 case StyledDigit::kStylePulseSlow:
168 if (isPulseEnabled) {
169 return ((uint16_t) pulseSlowFraction * brightness) / 256;
173 case StyledDigit::kStylePulseFast:
174 if (isPulseEnabled) {
175 return ((uint16_t) pulseFastFraction * brightness) / 256;
190 if (mIsPulseEnabled) {
191 #if ACE_SEGMENT_USE_INVERSE_PULSE_FRAMES == 1 193 mFramesPerPulseSlow, mCurrentPulseSlowFrame, mPulseSlowFraction);
195 mFramesPerPulseFast, mCurrentPulseFastFrame, mPulseFastFraction);
206 uint16_t& currentFrame, uint8_t& blinkState) {
207 uint16_t middleOfBlink = framesPerBlink / 2;
208 if (currentFrame < middleOfBlink) {
209 blinkState = kBlinkStateOn;
211 blinkState = kBlinkStateOff;
217 uint16_t& currentFrame, uint8_t& pulseFraction) {
218 uint16_t middleOfPulse = framesPerPulse / 2;
220 if (currentFrame < middleOfPulse) {
222 fraction = 256 * (uint32_t) currentFrame / middleOfPulse;
223 }
else if (currentFrame < framesPerPulse) {
224 uint16_t reverse = (framesPerPulse - currentFrame - 1);
226 fraction = 256 * (uint32_t) reverse / middleOfPulse;
230 if (fraction > 255) fraction = 255;
231 pulseFraction = fraction;
236 uint16_t framesPerPulseInverse, uint16_t framesPerPulse,
237 uint16_t& currentFrame, uint8_t& pulseFraction) {
238 uint16_t middleOfPulse = framesPerPulse / 2;
240 if (currentFrame < middleOfPulse) {
241 fraction = (uint32_t) framesPerPulseInverse * currentFrame / (256/2);
242 }
else if (currentFrame < framesPerPulse) {
243 uint16_t reverse = (framesPerPulse - currentFrame - 1);
244 fraction = (uint32_t) framesPerPulseInverse * reverse / (256/2);
248 if (fraction > 255) fraction = 255;
249 pulseFraction = fraction;
void renderFieldWhenReady()
Display one field of a frame when the time is right.
TimingStats getTimingStats()
Return stats.
virtual void displayCurrentField()=0
Display the current field of the frame.
Data structure that keeps track of the state of each digit (its segment bit pattern and its style)...
void writePatternAt(uint8_t digit, uint8_t pattern, uint8_t style)
Write the pattern and style for a given digit.
void renderField()
Render the current field immediately.
static void calcPulseFractionForFrameUsingInverse(uint16_t framesPerPulseInverse, uint16_t framesPerPulse, uint16_t ¤tFrame, uint8_t &pulseFraction)
Calculate the pulse fraction using the reciprocal of the framesPerPulse, which avoid a long division...
void writeStyleAt(uint8_t digit, uint8_t style)
Write the style for a given digit, leaving pattern unchanged.
virtual unsigned long micros()
Get the current micros.
virtual void configure()
Configure the driver with the parameters given by the various setXxx() methods.
virtual bool isBrightnessSupported()=0
Returns true if the driver supports brightness.
void updateFrame()
Perform things that need to be done each frame.
void setPattern(uint8_t digit, SegmentPatternType pattern, uint8_t brightness=DimmingDigit::kOn)
Set the pattern for a given digit.
void calcBlinkAndPulseForFrame()
Calculate the blink and pulse states for current frame.
void renderStyledDigits()
Translate the StyledDigits to DimmingDigits for the Driver.
static void calcPulseFractionForFrame(uint16_t framesPerPulse, uint16_t ¤tFrame, uint8_t &pulseFraction)
Calculate the pulse fraction.
uint16_t getCount()
Number of times update() was called since last reset.
uint16_t getFieldsPerSecond()
Return the fields per second.
void writeDecimalPointAt(uint8_t digit, bool state=true)
Write the decimal point for the digit.
static uint8_t calcBrightness(uint8_t style, uint8_t brightness, uint8_t blinkSlowState, uint8_t blinkFastState, bool isPulseEnabled, uint8_t pulseSlowFraction, uint8_t pulseFastFraction)
Calculate the effective brightness of a digit with the given style.
static void calcBlinkStateForFrame(uint16_t framesPerBlink, uint16_t ¤tFrame, uint8_t &blinkState)
Calculate the blink state.
static void incrementMod(T &i, T m)
Increment i modulo m, avoiding expensive % operator on some 8-bit processors like AVR...
virtual uint16_t getFieldsPerFrame()=0
Return number of fields per frame.