segment-display
Arduino library to drive a multiplexed segment display
segment_display.h
1 #ifndef _SEGMENT_DISPLAY
2 #define _SEGMENT_DISPLAY
3 
4 #include <avr/pgmspace.h>
5 
6 #include "std/initializer_list.h"
7 
8 namespace SegmentDisplay {
9 
10 // Simple seven segment decimal decoder
11 const PROGMEM uint8_t DECODER[] = {
12  //.gfedcba
13  0b00111111, // 0
14  0b00000110, // 1
15  0b01011011, // 2
16  0b01001111, // 3
17  0b01100110, // 4
18  0b01101101, // 5
19  0b01111101, // 6
20  0b00000111, // 7
21  0b01111111, // 8
22  0b01101111, // 9
23  0b00000000, // *
24  0b00000000, // *
25  0b00000000, // *
26  0b00000000, // *
27  0b00000000, // *
28  0b00000000, // *
29  0b00000000, // EMPTY
30  0b01000000, // DASH
31 };
32 
51 template<size_t NUM_DIGITS>
52 class Driver {
53  public:
55  const static size_t EMPTY = 16;
57  const static size_t DASH = 17;
58 
64  Driver(std::initializer_list<uint8_t> digit_pins, std::initializer_list<uint8_t> segment_pins) {
65  size_t i = 0;
66  for(auto pin : digit_pins) {
67  if(i >= NUM_DIGITS) break;
68  this->digit_pins[i++] = pin;
69  pinMode(pin, OUTPUT);
70  }
71  i = 0;
72  for(auto pin : segment_pins) {
73  if(i >= 8) break;
74  this->segment_pins[i++] = pin;
75  pinMode(pin, OUTPUT);
76  }
77 
78  for(i = 0; i < NUM_DIGITS; ++i) {
79  setDigit(i, EMPTY);
80  }
81  }
82 
87  void setDigits(std::initializer_list<uint8_t> digits) {
88  size_t i = 0;
89  for(auto digit : digits) {
90  setDigit(i++, digit);
91  }
92  }
93 
101  void setDigit(size_t num, uint8_t digit) {
102  if(num >= NUM_DIGITS || digit > 17) return;
103  this->state[num] = pgm_read_byte_near(DECODER + digit);
104  }
105 
113  void setSegments(size_t num, uint8_t segments) {
114  if(num >= NUM_DIGITS) return;
115  this->state[num] = segments;
116  }
117 
126  void refresh(unsigned int light_time = 0) {
127  size_t i = 0;
128  for(auto segment : segment_pins) {
129  // If only 7 segments were specified
130  if(segment < 0) continue;
131 
132  digitalWrite(segment, HIGH);
133 
134  size_t j = 0;
135  for(auto digitState : state) {
136  digitalWrite(digit_pins[j++],(digitState & 1 << i) == 0);
137  }
138 
139  // Give the segment some time to light up
140  delayMicroseconds(light_time);
141 
142  j = 0;
143  for(auto digitState : state) {
144  digitalWrite(digit_pins[j++], HIGH);
145  }
146 
147  digitalWrite(segment, LOW);
148  i += 1;
149  }
150  }
151 
152  private:
153  uint8_t segment_pins[8] = {-1, -1, -1, -1, -1, -1, -1, -1};
154  uint8_t digit_pins[NUM_DIGITS];
155 
156  uint8_t state[NUM_DIGITS];
157 };
158 
159 } // namespace SegmentDisplay
160 
161 #endif // _SEGMENT_DISPLAY
Driver(std::initializer_list< uint8_t > digit_pins, std::initializer_list< uint8_t > segment_pins)
Create a new driver instance using the given pins.
static const size_t EMPTY
Turn all segments off.
void refresh(unsigned int light_time=0)
Refresh on the display.
void setSegments(size_t num, uint8_t segments)
Change the digit at index num to the given segments.
Driver for a multiplexed segment display.
void setDigit(size_t num, uint8_t digit)
Change the digit at index num to the given one.
void setDigits(std::initializer_list< uint8_t > digits)
Change the digits to the given ones.
static const size_t DASH
Only enable the segment in the middle (G).