AceSegment  0.3.0
An adjustable, configurable, and extensible framework for rendering seven segment LED displays.
ModulatingDigitDriver.cpp
1 /*
2 MIT License
3 
4 Copyright (c) 2018 Brian T. Park
5 
6 Permission is hereby granted, free of charge, to any person obtaining a copy
7 of this software and associated documentation files (the "Software"), to deal
8 in the Software without restriction, including without limitation the rights
9 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 copies of the Software, and to permit persons to whom the Software is
11 furnished to do so, subject to the following conditions:
12 
13 The above copyright notice and this permission notice shall be included in all
14 copies or substantial portions of the Software.
15 
16 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 SOFTWARE.
23 */
24 
25 #include "Util.h"
26 #include "Hardware.h"
27 #include "LedMatrix.h"
28 #include "ModulatingDigitDriver.h"
29 
30 namespace ace_segment {
31 
33  if (mPreparedToSleep) return;
34 
35  bool isCurrentDigitOn;
36  DimmablePattern& dimmablePattern = mDimmablePatterns[mCurrentDigit];
37  uint8_t brightness = dimmablePattern.brightness;
38  if (mCurrentDigit != mPrevDigit) {
39  // NOTE: The following could be optimized away by wrapping it around an 'if
40  // (mIsPrevDigitOn)' statement. But I think it's safer to issue a redundant
41  // disable-digit command just in case some else (interrupts or other
42  // unpredicatble things) causes the mIsPrevDigitOn state to be wrong. We
43  // want to be absolutely sure that 2 digits cannot be turned on at the same
44  // time.
45  mLedMatrix->disableGroup(mPrevDigit);
46 
47  isCurrentDigitOn = false;
48  mCurrentSubFieldMax = ((uint16_t) mNumSubFields * brightness) / 256;
49  } else {
50  isCurrentDigitOn = mIsPrevDigitOn;
51  }
52 
53  // No matter how small the mNumSubFields, we want:
54  // * If brightness == 0, then subfield 0 should be OFF.
55  // * If birghtness == 255, then special case that to be ON.
56  if (brightness < 255 && mCurrentSubField >= mCurrentSubFieldMax) {
57  // turn off the current digit
58  if (isCurrentDigitOn) {
59  mLedMatrix->disableGroup(mCurrentDigit);
60  isCurrentDigitOn = false;
61  }
62  } else {
63  // turn on the current digit
64  if (!isCurrentDigitOn) {
65  SegmentPatternType segmentPattern = dimmablePattern.pattern;
66  if (segmentPattern != mSegmentPattern) {
67  mLedMatrix->drawElements(segmentPattern);
68  mSegmentPattern = segmentPattern;
69  }
70  mLedMatrix->enableGroup(mCurrentDigit);
71  isCurrentDigitOn = true;
72  }
73  }
74 
75  mCurrentSubField++;
77  mIsPrevDigitOn = isCurrentDigitOn;
78  if (mCurrentSubField >= mNumSubFields) {
79  Util::incrementMod(mCurrentDigit, mNumDigits);
80  mCurrentSubField = 0;
81  }
82 }
83 
84 }
uint8_t SegmentPatternType
Integer type used to store the segment bit patterns of a single digit.
Definition: Driver.h:51
uint8_t mPrevDigit
Within the displayCurrentField() method, the mPrevDigit is the digit that was displayed on the previo...
Definition: DigitDriver.h:76
static void incrementMod(T &i, T m)
Increment i modulo m, avoiding expensive % operator on some 8-bit processors like AVR...
Definition: Util.h:39
uint8_t mCurrentDigit
Within the displayCurrentField() method, mCurrentDigit is the current digit that is being drawn...
Definition: DigitDriver.h:69
bool mIsPrevDigitOn
Whether the previous digit was turned on or off.
virtual void displayCurrentField() override
Display the current field of the frame.