AceSegmentWriter  0.4
Write decimal numbers, hex numbers, temperature, clock digits, characters, and strings to seven segment LED modules
NumberWriter.h
1 /*
2 MIT License
3 
4 Copyright (c) 2021 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 #ifndef ACE_SEGMENT_WRITER_NUMBER_WRITER_H
26 #define ACE_SEGMENT_WRITER_NUMBER_WRITER_H
27 
28 #include <stdint.h>
29 #include <AceCommon.h> // decToBcd()
30 #include "PatternWriter.h"
31 
32 namespace ace_segment {
33 
35 const uint8_t kNumDigitPatterns = 18;
36 
38 extern const uint8_t kDigitPatterns[kNumDigitPatterns];
39 
54 typedef uint8_t digit_t;
55 
57 const digit_t kDigitSpace = 16;
58 
60 const digit_t kDigitMinus = 17;
61 
71 template <typename T_LED_MODULE>
72 class NumberWriter {
73  public:
76  mPatternWriter(patternWriter)
77  {}
78 
80  T_LED_MODULE& ledModule() { return mPatternWriter.ledModule(); }
81 
83  PatternWriter<T_LED_MODULE>& patternWriter() { return mPatternWriter; }
84 
86  void home() { mPatternWriter.home(); }
87 
93  void writeDigit(digit_t c) {
94  write(((uint8_t) c < kNumDigitPatterns) ? c : kDigitSpace);
95  }
96 
98  void writeDigits(const digit_t s[], uint8_t len) {
99  for (uint8_t i = 0; i < len; ++i) {
100  writeDigit(s[i]);
101  }
102  }
103 
113  void writeDec2(uint8_t d, uint8_t padPattern = kPattern0) {
114  if (d >= 100) {
115  mPatternWriter.writePattern(kPatternSpace);
116  mPatternWriter.writePattern(kPatternSpace);
117  } else {
118  uint8_t tens = d / 10;
119  uint8_t ones = d - 10 * tens;
120  if (tens == 0) {
121  mPatternWriter.writePattern(padPattern);
122  } else {
123  writeDigit(tens);
124  }
125  writeDigit(ones);
126  }
127  }
128 
134  void writeDec4(uint16_t dd, uint8_t padPattern = kPattern0) {
135  if (dd >= 10000) {
136  mPatternWriter.writePattern(kPatternSpace);
137  mPatternWriter.writePattern(kPatternSpace);
138  mPatternWriter.writePattern(kPatternSpace);
139  mPatternWriter.writePattern(kPatternSpace);
140  } else {
141  uint8_t high = dd / 100;
142  uint8_t low = dd - high * 100;
143  if (high == 0) {
144  mPatternWriter.writePattern(padPattern);
145  mPatternWriter.writePattern(padPattern);
146  writeDec2(low, padPattern);
147  } else {
148  writeDec2(high, padPattern);
149  writeDec2(low, kPattern0);
150  }
151  }
152  }
153 
159  void writeBcd(uint8_t bcd) {
160  uint8_t high = (bcd & 0xF0) >> 4;
161  uint8_t low = (bcd & 0x0F);
162  if (high > 9) high = kDigitSpace;
163  if (low > 9) low = kDigitSpace;
164  writeDigit(high);
165  writeDigit(low);
166  }
167 
169  void writeHexByte(uint8_t b) {
170  uint8_t low = (b & 0x0F);
171  uint8_t high = ((b >> 4) & 0x0F);
172  write(high);
173  write(low);
174  }
175 
177  void writeHexWord(uint16_t w) {
178  uint8_t low = (w & 0xFF);
179  uint8_t high = (w >> 8) & 0xFF;
180  writeHexByte(high);
181  writeHexByte(low);
182  }
183 
199  uint8_t writeUnsignedDecimal(uint16_t num, int8_t boxSize = 0) {
200  const uint8_t bufSize = 5;
201  digit_t buf[bufSize];
202  uint8_t start = toDecimal(num, buf, bufSize);
203 
204  return writeDigitsInsideBox(&buf[start], bufSize - start, boxSize);
205  }
206 
208  uint8_t writeSignedDecimal(int16_t num, int8_t boxSize = 0) {
209  // Even -32768 turns into +32768, which is exactly what we want
210  bool negative = num < 0;
211  uint16_t absNum = negative ? -num : num;
212 
213  const uint8_t bufSize = 6;
214  digit_t buf[bufSize];
215  uint8_t start = toDecimal(absNum, buf, bufSize);
216  if (negative) {
217  buf[--start] = kDigitMinus;
218  }
219 
220  return writeDigitsInsideBox(&buf[start], bufSize - start, boxSize);
221  }
222 
227  void setDecimalPointAt(uint8_t pos, bool state = true) {
228  mPatternWriter.setDecimalPointAt(pos, state);
229  }
230 
232  void clear() { mPatternWriter.clear(); }
233 
239  void clearToEnd() { mPatternWriter.clearToEnd(); }
240 
241  private:
242  // disable copy-constructor and assignment operator
243  NumberWriter(const NumberWriter&) = delete;
244  NumberWriter& operator=(const NumberWriter&) = delete;
245 
247  void write(digit_t c) {
248  uint8_t pattern = pgm_read_byte(&kDigitPatterns[(uint8_t) c]);
249  mPatternWriter.writePattern(pattern);
250  }
251 
253  void writeInternalDigits(const digit_t s[], uint8_t len) {
254  for (uint8_t i = 0; i < len; ++i) {
255  write(s[i]);
256  }
257  }
258 
266  uint8_t writeDigitsInsideBox(
267  const digit_t s[], uint8_t len, int8_t boxSize) {
268 
269  uint8_t absBoxSize = (boxSize < 0) ? -boxSize : boxSize;
270 
271  // if the box is too small, print normally
272  if (len >= absBoxSize) {
273  writeInternalDigits(s, len);
274  return len;
275  }
276 
277  // Print either left justified or right justified inside box
278  uint8_t padSize = absBoxSize - len;
279  if (boxSize < 0) {
280  // left justified
281  writeInternalDigits(s, len);
282  while (padSize--) write(kDigitSpace);
283  } else {
284  // right justified
285  while (padSize--) write(kDigitSpace);
286  writeInternalDigits(s, len);
287  }
288 
289  return absBoxSize;
290  }
291 
305  static uint8_t toDecimal(uint16_t num, digit_t buf[], uint8_t bufSize) {
306  uint8_t pos = bufSize;
307  while (true) {
308  if (num < 10) {
309  buf[--pos] = num;
310  break;
311  }
312  uint16_t quot = num / 10;
313  buf[--pos] = num - quot * 10;
314  num = quot;
315  }
316  return pos;
317  }
318 
319  private:
320  PatternWriter<T_LED_MODULE> &mPatternWriter;
321 };
322 
323 }
324 
325 #endif
The NumberWriter supports converting decimal and hexadecimal numbers to segment patterns expected by ...
Definition: NumberWriter.h:72
void setDecimalPointAt(uint8_t pos, bool state=true)
Write the decimal point for the pos.
Definition: NumberWriter.h:227
void writeDec2(uint8_t d, uint8_t padPattern=kPattern0)
Write a 2-digit decimal number at position digit, right justified with the given padPattern (default ...
Definition: NumberWriter.h:113
void writeDigits(const digit_t s[], uint8_t len)
Write the len hex characters given by s at LED pos.
Definition: NumberWriter.h:98
PatternWriter< T_LED_MODULE > & patternWriter()
Get the underlying PatternWriter.
Definition: NumberWriter.h:83
void clearToEnd()
Clear the display from the current position to the end.
Definition: NumberWriter.h:239
uint8_t writeSignedDecimal(int16_t num, int8_t boxSize=0)
Same as writeUnsignedDecimal() but prepends a '-' sign if negative.
Definition: NumberWriter.h:208
uint8_t writeUnsignedDecimal(uint16_t num, int8_t boxSize=0)
Write the 16-bit unsigned number num as a decimal number at pos.
Definition: NumberWriter.h:199
void clear()
Clear the entire display.
Definition: NumberWriter.h:232
NumberWriter(PatternWriter< T_LED_MODULE > &patternWriter)
Constructor.
Definition: NumberWriter.h:75
T_LED_MODULE & ledModule()
Get the underlying LedModule.
Definition: NumberWriter.h:80
void writeHexWord(uint16_t w)
Write the 4 digit (16-bit) hexadecimal word at pos.
Definition: NumberWriter.h:177
void writeDigit(digit_t c)
Write the digit c at position pos.
Definition: NumberWriter.h:93
void writeHexByte(uint8_t b)
Write the 2-digit (8-bit) hexadecimal byte 'b' at pos.
Definition: NumberWriter.h:169
void writeDec4(uint16_t dd, uint8_t padPattern=kPattern0)
Write the 4 digit decimal number dd at pos, right justified, padded with a the padPattern (default kP...
Definition: NumberWriter.h:134
void home()
Reset cursor to home.
Definition: NumberWriter.h:86
void writeBcd(uint8_t bcd)
Write a 2-digit BCD number at position, which involves just printing the number as a hexadecimal numb...
Definition: NumberWriter.h:159
Write LED segment patterns to the underlying LedModule.