1+ /* !
2+ * @file src/components/display/drivers/dispDrv7Seg.h
3+ *
4+ * Driver for 7-Segment LED Backpack displays.
5+ *
6+ * Adafruit invests time and resources providing this open source code,
7+ * please support Adafruit and open-source hardware by purchasing
8+ * products from Adafruit!
9+ *
10+ * Copyright (c) Brent Rubell 2025 for Adafruit Industries.
11+ *
12+ * BSD license, all text here must be included in any redistribution.
13+ *
14+ */
15+ #ifndef WS_DISP_DRV_7Seg
16+ #define WS_DISP_DRV_7Seg
17+
18+ #include " dispDrvBase.h"
19+ #include < Adafruit_LEDBackpack.h>
20+
21+ #define LED_BACKPACK_ALIGNMENT_UNSPECIFIED 0 // /< Unspecified alignment
22+ #define LED_BACKPACK_ALIGNMENT_LEFT 1 // /< Left alignment
23+ #define LED_BACKPACK_ALIGNMENT_RIGHT 2 // /< Right alignment
24+ #define LED_BACKPACK_ALIGNMENT_DEFAULT \
25+ LED_BACKPACK_ALIGNMENT_LEFT // /< Default alignment
26+ #define LED_MAX_CHARS \
27+ 5 // /< Maximum characters for 7-segment display, including ':'
28+ #define LED_BACKPACK_DEGREE_SYMBOL \
29+ 0b01100011 // /< Degree symbol for 7-segment display
30+
31+ /* !
32+ @brief Driver for 7-segment LED backpack displays.
33+ */
34+ class dispDrv7Seg : public dispDrvBase {
35+ public:
36+ /* !
37+ @brief Constructor for the 7-segment LED matrix.
38+ */
39+ dispDrv7Seg (TwoWire *i2c, uint16_t sensorAddress)
40+ : dispDrvBase(i2c, sensorAddress), _matrix(nullptr ) {
41+ _alignment = LED_BACKPACK_ALIGNMENT_DEFAULT;
42+ }
43+
44+ /* !
45+ @brief Destructor for the 7-segment LED backpack driver.
46+ */
47+ ~dispDrv7Seg () {
48+ if (_matrix) {
49+ delete _matrix;
50+ _matrix = nullptr ;
51+ }
52+ }
53+
54+ /* !
55+ @brief Attempts to initialize the 7-segment LED backpack driver.
56+ @return True if the matrix was initialized successfully, false otherwise.
57+ */
58+ bool begin () override {
59+ _matrix = new Adafruit_7segment ();
60+ return _matrix->begin (_sensorAddress, _i2c);
61+ }
62+
63+ /* !
64+ @brief Sets the text alignment for the matrix.
65+ @param alignment
66+ The desired alignment to set (LEFT or RIGHT).
67+ */
68+ void setAlignment (uint32_t alignment) override {
69+ if (alignment == LED_BACKPACK_ALIGNMENT_RIGHT) {
70+ _alignment = LED_BACKPACK_ALIGNMENT_RIGHT;
71+ } else {
72+ _alignment = LED_BACKPACK_ALIGNMENT_DEFAULT;
73+ }
74+ }
75+
76+ /* !
77+ @brief Writes the first four characters of a message to the Adafruit
78+ 7-segment LED matrix.
79+ @param message
80+ The message to be displayed.
81+ */
82+ void writeMessage (const char *message) override {
83+ if (_matrix == nullptr || message == nullptr ) {
84+ return ;
85+ }
86+
87+ // Clear before writing
88+ _matrix->clear ();
89+
90+ // Calculate the number of characters to display
91+ size_t len_display = min (strlen (message), (size_t )LED_MAX_CHARS);
92+
93+ // Set the starting position based on alignment
94+ int pos_start;
95+ if (_alignment == LED_BACKPACK_ALIGNMENT_LEFT) {
96+ pos_start = 0 ; // start at the leftmost position of the display
97+ } else {
98+ // Exclude decimal points from the character count because those get
99+ // displayed on a "special" segment of the LED display
100+ int seg_chars = 0 ;
101+ for (size_t i = 0 ; i < len_display; i++) {
102+ if (message[i] != ' .' ) {
103+ seg_chars++;
104+ }
105+ }
106+ // start at the rightmost position of the display
107+ switch (seg_chars) {
108+ case 4 :
109+ pos_start = 0 ;
110+ break ;
111+ case 3 :
112+ pos_start = 1 ;
113+ break ;
114+ case 2 :
115+ pos_start = 3 ; // if 2 characters, start at position 3 is required
116+ // because ':' is position 2 and we need to skip it
117+ break ;
118+ case 1 :
119+ pos_start = 4 ;
120+ break ;
121+ default :
122+ pos_start = 0 ; // if no characters or overflow, start at position 0
123+ break ;
124+ }
125+ }
126+
127+ // Write to the display's buffer
128+ int cur_idx = pos_start;
129+ for (size_t i = 0 ; i < len_display; i++) {
130+
131+ // skip position 2
132+ if (cur_idx == 2 ) {
133+ cur_idx++;
134+ }
135+ // Save the character because if there's a decimal, we need to skip it in
136+ // the buffer
137+ char ch = message[i];
138+
139+ // Look-ahead for a decimal point to attach to the current character
140+ bool display_dot = false ;
141+ if (i + 1 < len_display && message[i + 1 ] == ' .' ) {
142+ display_dot = true ;
143+ i++;
144+ len_display++;
145+ } else if (message[i] == 0xC2 && message[i + 1 ] == 0xB0 &&
146+ i + 1 < strlen (message)) {
147+ // Write degree symbol
148+ _matrix->writeDigitRaw (cur_idx, LED_BACKPACK_DEGREE_SYMBOL);
149+ i++;
150+ cur_idx++;
151+ continue ; // skip to next character
152+ }
153+ // Write the character to the display buffer
154+ _matrix->writeDigitAscii (cur_idx, ch, display_dot);
155+ cur_idx++;
156+ }
157+ // Issue the buffered data in RAM to the display
158+ _matrix->writeDisplay ();
159+ }
160+
161+ private:
162+ Adafruit_7segment *_matrix;
163+ };
164+
165+ #endif // WS_DISP_DRV_7Seg
0 commit comments