AceSegment  0.7.0
A framework for rendering seven segment LED displays using the TM1637, MAX7219, HT16K33, or 74HC595 controller chips
NumberWriter.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 <Arduino.h>
26 #include "NumberWriter.h"
27 
28 namespace ace_segment {
29 
30 // Bit patterns for Hex characters (0x00 - 0x0F) plus a few symbols.
31 // Adapted from https://github.com/dmadison/LED-Segment-ASCII.
32 //
33 // 7-segment map:
34 // AAA 000
35 // F B 5 1
36 // F B 5 1
37 // GGG 666
38 // E C 4 2
39 // E C 4 2
40 // DDD DP 333 77
41 //
42 // Segment: DP G F E D C B A
43 // Bits: 7 6 5 4 3 2 1 0
44 //
45 const uint8_t NumberWriter::kHexCharPatterns[kNumHexChars] PROGMEM = {
46  0b00111111, /* 0 */
47  0b00000110, /* 1 */
48  0b01011011, /* 2 */
49  0b01001111, /* 3 */
50  0b01100110, /* 4 */
51  0b01101101, /* 5 */
52  0b01111101, /* 6 */
53  0b00000111, /* 7 */
54  0b01111111, /* 8 */
55  0b01101111, /* 9 */
56  0b01110111, /* A */
57  0b01111100, /* b */
58  0b00111001, /* C */
59  0b01011110, /* d */
60  0b01111001, /* E */
61  0b01110001, /* F */
62  0b00000000, /* (space) */
63  0b01000000, /* - */
64 };
65 
66 void NumberWriter::writeInternalHexCharAt(uint8_t pos, hexchar_t c) {
67  uint8_t pattern = pgm_read_byte(&kHexCharPatterns[(uint8_t) c]);
68  mPatternWriter.writePatternAt(pos, pattern);
69 }
70 
72  uint8_t pos,
73  uint16_t num,
74  int8_t boxSize) {
75 
76  const uint8_t bufSize = 5;
77  hexchar_t buf[bufSize];
78  uint8_t start = toDecimal(num, buf, bufSize);
79 
80  return writeHexCharsInsideBoxAt(
81  pos, &buf[start], bufSize - start, boxSize);
82 }
83 
85  uint8_t pos,
86  int16_t num,
87  int8_t boxSize) {
88 
89  // Even -32768 turns into +32768, which is exactly what we want
90  bool negative = num < 0;
91  uint16_t absNum = negative ? -num : num;
92 
93  const uint8_t bufSize = 6;
94  hexchar_t buf[bufSize];
95  uint8_t start = toDecimal(absNum, buf, bufSize);
96  if (negative) {
97  buf[--start] = kCharMinus;
98  }
99 
100  return writeHexCharsInsideBoxAt(
101  pos, &buf[start], bufSize - start, boxSize);
102 }
103 
104 uint8_t NumberWriter::writeHexCharsInsideBoxAt(
105  uint8_t pos,
106  const hexchar_t s[],
107  uint8_t len,
108  int8_t boxSize) {
109 
110  uint8_t absBoxSize = (boxSize < 0) ? -boxSize : boxSize;
111 
112  // if the box is too small, print normally
113  if (len >= absBoxSize) {
114  writeInternalHexCharsAt(pos, s, len);
115  return len;
116  }
117 
118  // Print either left justified or right justified inside box
119  uint8_t padSize = absBoxSize - len;
120  if (boxSize < 0) {
121  // left justified
122  writeInternalHexCharsAt(pos, s, len);
123  pos += len;
124  while (padSize--) writeInternalHexCharAt(pos++, kCharSpace);
125  } else {
126  // right justified
127  while (padSize--) writeInternalHexCharAt(pos++, kCharSpace);
128  writeInternalHexCharsAt(pos, s, len);
129  }
130 
131  return absBoxSize;
132 }
133 
134 void NumberWriter::writeUnsignedDecimal2At(uint8_t pos, uint8_t num) {
135  if (num >= 100) {
136  writeHexCharAt(pos++, 9);
137  writeHexCharAt(pos++, 9);
138  } else {
139  uint8_t high = num / 10;
140  uint8_t low = num - high * 10;
141  writeHexCharAt(pos++, (high == 0) ? kCharSpace : high);
142  writeHexCharAt(pos++, low);
143  }
144 }
145 
146 } // ace_segment
ace_segment::NumberWriter::writeHexCharAt
void writeHexCharAt(uint8_t pos, hexchar_t c)
Write the hex character c at position pos.
Definition: NumberWriter.h:83
ace_segment::NumberWriter::writeUnsignedDecimalAt
uint8_t writeUnsignedDecimalAt(uint8_t pos, uint16_t num, int8_t boxSize=0)
Write the 16-bit unsigned number num as a decimal number at pos.
Definition: NumberWriter.cpp:71
ace_segment::PatternWriter::writePatternAt
void writePatternAt(uint8_t pos, uint8_t pattern)
Write the pattern for a given pos.
Definition: PatternWriter.h:61
ace_segment::NumberWriter::writeSignedDecimalAt
uint8_t writeSignedDecimalAt(uint8_t pos, int16_t num, int8_t boxSize=0)
Same as writeUnsignedDecimalAt() but prepends a '-' sign if negative.
Definition: NumberWriter.cpp:84
ace_segment::NumberWriter::hexchar_t
uint8_t hexchar_t
The type of the character set supported by many methods in this class, usually containing the string ...
Definition: NumberWriter.h:56
ace_segment::NumberWriter::kCharMinus
static const hexchar_t kCharMinus
A minus character.
Definition: NumberWriter.h:65
ace_segment::NumberWriter::kCharSpace
static const hexchar_t kCharSpace
A space character.
Definition: NumberWriter.h:62
ace_segment::NumberWriter::writeUnsignedDecimal2At
void writeUnsignedDecimal2At(uint8_t pos, uint8_t num)
Write the 2 digit decimal number at pos.
Definition: NumberWriter.cpp:134