1+ /* !
2+ * @file src/components/display/drivers/dispDrvSh1107.h
3+ *
4+ * Device driver for a SH1107 OLED Display
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) Tyeth Gundry for Adafruit Industries 2025
11+ *
12+ * MIT license, all text here must be included in any redistribution.
13+ *
14+ */
15+ #ifndef WS_DISP_DRV_SH1107_H
16+ #define WS_DISP_DRV_SH1107_H
17+
18+ #include " dispDrvBase.h"
19+ #include < Adafruit_SH110X.h>
20+
21+ #define WS_SH1107_DEFAULT_WIDTH \
22+ 128 // /< Default width for a sh1107 128x64 display
23+ #define WS_SH1107_DEFAULT_HEIGHT \
24+ 64 // /< Default height for a sh1107 128x64 display
25+
26+ #define OLED_128X64_WING_WIDTH 128 // /< Width of the 128x64 OLED FeatherWing
27+ #define OLED_128X64_WING_HEIGHT 64 // /< Height of the 128x64 OLED FeatherWing
28+ #define OLED_128X64_WING_ROTATION_90 1 // /< Rotation of OLED FeatherWing 0-3
29+
30+ /* !
31+ @brief Class that provides a driver interface for a SH1107
32+ OLED Display
33+ */
34+ class dispDrvSh1107 : public dispDrvBase {
35+ public:
36+ /* !
37+ @brief Constructor for the SH1107 display driver.
38+ */
39+ dispDrvSh1107 (TwoWire *i2c, uint16_t sensorAddress)
40+ : dispDrvBase(i2c, sensorAddress), _display(nullptr ) {
41+ _i2c = i2c;
42+ _sensorAddress = sensorAddress;
43+ _width = WS_SH1107_DEFAULT_WIDTH;
44+ _height = WS_SH1107_DEFAULT_HEIGHT;
45+ }
46+
47+ /* !
48+ @brief Destructor for a SH1107 display driver.
49+ */
50+ ~dispDrvSh1107 () {
51+ if (_display != nullptr ) {
52+ _display->clearDisplay ();
53+ _display->display ();
54+ _display->oled_command (SH110X_DISPLAYOFF);
55+ delete _display;
56+ _display = nullptr ;
57+ }
58+ }
59+
60+ /* !
61+ @brief Attempts to initialize the SSD1306 display driver.
62+ @return True if the display was initialized successfully, false otherwise.
63+ */
64+ bool begin () override {
65+ if (!_i2c)
66+ return false ;
67+
68+ // Attempt to create and allocate a SH1107 obj.
69+ if (_width == OLED_128X64_WING_WIDTH &&
70+ _height == OLED_128X64_WING_HEIGHT &&
71+ _rotation == OLED_128X64_WING_ROTATION_90) {
72+ // FeatherWing needs to be rotated 90deg and swap w/h ctor args
73+ _display = new Adafruit_SH1107 (_height, _width, _i2c);
74+ } else {
75+ _display = new Adafruit_SH1107 (_width, _height, _i2c);
76+ }
77+ if (!_display->begin (_sensorAddress, true ))
78+ return false ;
79+
80+ // Clear the buffer.
81+ _display->clearDisplay ();
82+ _display->display ();
83+ _display->setRotation (_rotation); // 0-3, not degrees for SH1107
84+
85+ // Configure the text size and color
86+ _display->setTextSize (_text_sz);
87+ _display->setTextColor (SH110X_WHITE);
88+ _display->setCursor (0 , 0 );
89+ // Clear the buffer
90+ _display->clearDisplay ();
91+ _display->display ();
92+ return true ;
93+ }
94+
95+ /* !
96+ @brief Sets the text size for the display.
97+ @param s
98+ The text size to set.
99+ @note This method overrides the base class method to provide specific
100+ functionality for the SSD1306 driver.
101+ */
102+ void setTextSize (uint8_t s) override {
103+ if (!_display)
104+ return ;
105+ _text_sz = s;
106+ _display->setTextSize (s);
107+ }
108+
109+ void setRotation (uint8_t r) override {
110+ if (!_display)
111+ return ;
112+ _rotation = r % 90 ; // constrain to 0-3
113+ _display->setRotation (r);
114+ }
115+
116+ /* !
117+ @brief Writes a message to the display.
118+ @param message
119+ The message to write to the display.
120+ @note This method overrides the base class method to provide specific
121+ functionality for the SSD1306 driver.
122+ */
123+ virtual void writeMessage (const char *message) override {
124+ if (_display == nullptr )
125+ return ;
126+ // Start with a fresh display buffer
127+ // and settings
128+ int16_t y_idx = 0 ;
129+ _display->clearDisplay ();
130+ _display->setTextSize (_text_sz);
131+ _display->setTextColor (SH110X_WHITE);
132+ _display->setCursor (0 , y_idx);
133+ _display->display ();
134+
135+ // Calculate the line height based on the text size (NOTE: base height is
136+ // 8px)
137+ int16_t line_height = 8 * _text_sz;
138+ uint16_t c_idx = 0 ;
139+ size_t msg_size = strlen (message);
140+ for (size_t i = 0 ; i < msg_size && c_idx < msg_size; i++) {
141+ if (message[i] == ' \\ ' && i + 1 < msg_size &&
142+ (message[i + 1 ] == ' n' || message[i + 1 ] == ' r' )) {
143+ // Handle \r\n sequence as a single newline
144+ if (message[i + 1 ] == ' r' && i + 3 < msg_size &&
145+ message[i + 2 ] == ' \\ ' && message[i + 3 ] == ' n' ) {
146+ // Skip to the next line
147+ y_idx += line_height;
148+ _display->setCursor (0 , y_idx);
149+ i += 3 ;
150+ } else if (message[i + 1 ] == ' n' ) {
151+ // Skip to the next line
152+ y_idx += line_height;
153+ _display->setCursor (0 , y_idx);
154+ i++;
155+ }
156+ } else if (message[i] == 0xC2 && message[i + 1 ] == 0xB0 ) {
157+ _display->write (char (248 ));
158+ _display->display ();
159+ i++;
160+ } else {
161+ _display->print (message[i]);
162+ _display->display ();
163+ }
164+ }
165+ }
166+
167+ private:
168+ Adafruit_SH1107 *_display;
169+ };
170+
171+ #endif // WS_DISP_DRV_SSD1306
0 commit comments