1+ /* !
2+ * @file src/components/display/drivers/dispDrvQuadAlphaNum.h
3+ *
4+ * Driver for Quad Alphanumeric 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_QUADALPHANUM
16+ #define WS_DISP_DRV_QUADALPHANUM
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+ 4 // /< Maximum number of characters to display on the alphanumeric display
28+ #define ALPHANUM_DEGREE_SYMBOL \
29+ 0b0000000011100011 // /< Degree symbol for alphanumeric display
30+
31+ /* !
32+ @brief Driver for Quad Alphanumeric LED matrixes.
33+ */
34+ class dispDrvQuadAlphaNum : public dispDrvBase {
35+ public:
36+ /* !
37+ @brief Constructor for Quad Alphanumeric LED matrixes.
38+ @param i2c
39+ The I2C hardware interface, default is Wire.
40+ @param sensorAddress
41+ The I2C sensor's unique address.
42+ */
43+ dispDrvQuadAlphaNum (TwoWire *i2c, uint16_t sensorAddress)
44+ : dispDrvBase(i2c, sensorAddress), _alpha4(nullptr ) {
45+ _alignment = LED_BACKPACK_ALIGNMENT_DEFAULT;
46+ }
47+
48+ /* !
49+ @brief Destructor for the 7-segment LED backpack driver.
50+ */
51+ ~dispDrvQuadAlphaNum () {
52+ if (_alpha4) {
53+ delete _alpha4;
54+ _alpha4 = nullptr ;
55+ }
56+ }
57+
58+ /* !
59+ @brief Initializes the drvOutQuadAlphaNum component and begins I2C.
60+ @returns True if initialized successfully, False otherwise.
61+ */
62+ bool begin () override {
63+ _alpha4 = new Adafruit_AlphaNum4 ();
64+ bool did_begin = _alpha4->begin (_sensorAddress, _i2c);
65+ _alpha4->setBrightness (_brightness);
66+ return did_begin;
67+ }
68+
69+ /* !
70+ @brief Sets the brightness of the LED backpack.
71+ @param b
72+ The brightness value, from 0 (off) to 15 (full brightness).
73+ */
74+ void setBrightness (int32_t brightness) override {
75+ if (_alpha4 == nullptr ) {
76+ return ;
77+ }
78+ _alpha4->setBrightness (brightness);
79+ }
80+
81+ /* !
82+ @brief Sets the alignment of the displayed text.
83+ @param alignment
84+ The alignment value, either LED_BACKPACK_ALIGNMENT_LEFT or
85+ LED_BACKPACK_ALIGNMENT_RIGHT.
86+ */
87+ void setAlignment (uint32_t alignment) override {
88+ if (alignment == LED_BACKPACK_ALIGNMENT_RIGHT) {
89+ _alignment = LED_BACKPACK_ALIGNMENT_RIGHT;
90+ } else {
91+ _alignment = LED_BACKPACK_ALIGNMENT_DEFAULT;
92+ }
93+ }
94+
95+ /* !
96+ @brief Writes the first four characters of a message to the quad
97+ alphanumeric display.
98+ @param message
99+ The message to be displayed.
100+ */
101+ void writeMessage (const char *message) override {
102+ if (_alpha4 == nullptr || message == nullptr ) {
103+ return ;
104+ }
105+ // Clear before writing
106+ _alpha4->clear ();
107+
108+ // Calculate the number of characters to display
109+ size_t len_display = min (strlen (message), (size_t )LED_MAX_CHARS);
110+
111+ // Set the starting position based on alignment
112+ int pos_start;
113+ if (_alignment == LED_BACKPACK_ALIGNMENT_LEFT) {
114+ pos_start = 0 ; // start at the leftmost position of the display
115+ } else {
116+ // Exclude decimal points from the character count because those get
117+ // displayed on a "special" segment of the LED display
118+ int seg_chars = 0 ;
119+ for (size_t i = 0 ; i < len_display; i++) {
120+ if (message[i] != ' .' ) {
121+ seg_chars++;
122+ }
123+ }
124+ // start at the rightmost position of the display
125+ pos_start = LED_MAX_CHARS - seg_chars;
126+ }
127+
128+ // Write to the display's buffer
129+ int cur_idx = pos_start;
130+ for (size_t i = 0 ; i < len_display; i++) {
131+ // Save the character because if there's a decimal, we need to skip it in
132+ // the buffer
133+ char ch = message[i];
134+
135+ // Look-ahead for a decimal point to attach to the current character
136+ bool display_dot = false ;
137+ if (i + 1 < len_display && message[i + 1 ] == ' .' ) {
138+ display_dot = true ;
139+ i++;
140+ len_display++;
141+ } else if (message[i] == 0xC2 && message[i + 1 ] == 0xB0 &&
142+ i + 1 < strlen (message)) {
143+ // Write the degree symbol
144+ _alpha4->writeDigitRaw (cur_idx, ALPHANUM_DEGREE_SYMBOL);
145+ i++;
146+ cur_idx++;
147+ continue ;
148+ }
149+ // Write the character to the display buffer
150+ _alpha4->writeDigitAscii (cur_idx, ch, display_dot);
151+ cur_idx++;
152+ }
153+ // Issue the buffered data in RAM to the display
154+ _alpha4->writeDisplay ();
155+ }
156+
157+ private:
158+ Adafruit_AlphaNum4 *_alpha4; // /< Pointer to an Adafruit AlphaNum4 object
159+ };
160+
161+ #endif // WS_DISP_DRV_QUADALPHANUM
0 commit comments