Skip to content

Commit 9b5da3d

Browse files
committed
Add driver for quadalphanum
1 parent f601d4d commit 9b5da3d

File tree

3 files changed

+178
-5
lines changed

3 files changed

+178
-5
lines changed
Lines changed: 161 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,161 @@
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

src/components/display/hardware.cpp

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -364,7 +364,8 @@ bool DisplayHardware::beginOled(
364364
sizeof(i2c_config->i2c.i2c_device_name)) <
365365
sizeof(i2c_config->i2c.i2c_device_name) &&
366366
strcmp(i2c_config->i2c.i2c_device_name, "SH1107") == 0) {
367-
_drvDisp = new dispDrvSh1107(WS._i2cPort0->getBus(), i2c_config->i2c.i2c_device_address);
367+
_drvDisp = new dispDrvSh1107(WS._i2cPort0->getBus(),
368+
i2c_config->i2c.i2c_device_address);
368369
} else {
369370
WS_DEBUG_PRINTLN("[display] Unsupported OLED driver!");
370371
return false;
@@ -402,7 +403,9 @@ bool DisplayHardware::beginOled(
402403
Pointer to the I2C configuration structure.
403404
@return True if configuration was successful, False otherwise.
404405
*/
405-
bool DisplayHardware::beginLedBackpack(wippersnapper_display_v1_LEDBackpackConfig *config, wippersnapper_display_v1_I2cConfig *i2c_config) {
406+
bool DisplayHardware::beginLedBackpack(
407+
wippersnapper_display_v1_LEDBackpackConfig *config,
408+
wippersnapper_display_v1_I2cConfig *i2c_config) {
406409
// Validate pointers
407410
if (config == nullptr || i2c_config == nullptr || !i2c_config->has_i2c)
408411
return false;
@@ -419,7 +422,14 @@ bool DisplayHardware::beginLedBackpack(wippersnapper_display_v1_LEDBackpackConfi
419422
sizeof(i2c_config->i2c.i2c_device_name)) <
420423
sizeof(i2c_config->i2c.i2c_device_name) &&
421424
strcmp(i2c_config->i2c.i2c_device_name, "7seg") == 0) {
422-
_drvDisp = new dispDrv7Seg(WS._i2cPort0->getBus(), i2c_config->i2c.i2c_device_address);
425+
_drvDisp = new dispDrv7Seg(WS._i2cPort0->getBus(),
426+
i2c_config->i2c.i2c_device_address);
427+
} else if (strnlen(i2c_config->i2c.i2c_device_name,
428+
sizeof(i2c_config->i2c.i2c_device_name)) <
429+
sizeof(i2c_config->i2c.i2c_device_name) &&
430+
strcmp(i2c_config->i2c.i2c_device_name, "quadalphanum") == 0) {
431+
_drvDisp = new dispDrvQuadAlphaNum(WS._i2cPort0->getBus(),
432+
i2c_config->i2c.i2c_device_address);
423433
} else {
424434
WS_DEBUG_PRINTLN("[display] Unsupported OLED driver!");
425435
return false;

src/components/display/hardware.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,13 +15,14 @@
1515
#ifndef WS_DISPLAY_HARDWARE_H
1616
#define WS_DISPLAY_HARDWARE_H
1717
#include "Wippersnapper.h"
18+
#include "drivers/dispDrv7Seg.h"
1819
#include "drivers/dispDrvBase.h"
20+
#include "drivers/dispDrvQuadAlphaNum.h"
1921
#include "drivers/dispDrvSh1107.h"
2022
#include "drivers/dispDrvSsd1306.h"
2123
#include "drivers/dispDrvSt7789.h"
2224
#include "drivers/dispDrvThinkInkGrayscale4Eaamfgn.h"
2325
#include "drivers/dispDrvThinkInkGrayscale4T5.h"
24-
#include "drivers/dispDrv7Seg.h"
2526
#include <functional>
2627
#include <map>
2728

@@ -48,7 +49,8 @@ class DisplayHardware {
4849
wippersnapper_display_v1_SpiConfig *spi_config);
4950
bool beginOled(wippersnapper_display_v1_OledConfig *config,
5051
wippersnapper_display_v1_I2cConfig *i2c_config);
51-
bool beginLedBackpack(wippersnapper_display_v1_LEDBackpackConfig *config, wippersnapper_display_v1_I2cConfig *i2c_config);
52+
bool beginLedBackpack(wippersnapper_display_v1_LEDBackpackConfig *config,
53+
wippersnapper_display_v1_I2cConfig *i2c_config);
5254

5355
//
5456
// API for Adafruit_GFX that abstracts hardware functionality

0 commit comments

Comments
 (0)