@@ -28,25 +28,12 @@ static const std::map<std::string, FnCreateDispDrv> FactoryDrvDisp = {
2828 int16_t busy) -> dispDrvBase * {
2929 return new drvDispThinkInkGrayscale4Eaamfgn (dc, rst, cs, sram_cs, busy);
3030 }},
31- {" thinkink-magtag-2025" ,
32- [](int16_t dc, int16_t rst, int16_t cs, int16_t sram_cs,
33- int16_t busy) -> dispDrvBase * {
34- return new drvDispThinkInkGrayscale4Eaamfgn (dc, rst, cs, sram_cs, busy);
35- }},
3631 {" thinkink-gs4-t5" ,
3732 [](int16_t dc, int16_t rst, int16_t cs, int16_t sram_cs,
3833 int16_t busy) -> dispDrvBase * {
3934 return new dispDrvThinkInkGrayscale4T5 (dc, rst, cs, sram_cs, busy);
40- }},
41- {" thinkink-magtag-pre-2025" ,
42- [](int16_t dc, int16_t rst, int16_t cs, int16_t sram_cs,
43- int16_t busy) -> dispDrvBase * {
44- return new dispDrvThinkInkGrayscale4T5 (dc, rst, cs, sram_cs, busy);
45- }}
46- };
35+ }}};
4736
48-
49-
5037/* !
5138 @brief Creates a new display driver instance based on the driver name.
5239 @param driver_name
@@ -169,6 +156,19 @@ bool DisplayHardware::beginEPD(
169156
170157 // TODO: Configure SPI bus selection (UNUSED AS OF RIGHT NOW)
171158
159+ // For "magtag" component name, attempt to autodetect the driver
160+ if (strncmp (_name, " magtag" , 6 ) == 0 ) {
161+ if (detect_ssd1680 (cs, dc, rst)) {
162+ // Detected SSD1680, use EAAMFGN driver
163+ strncpy (_name, " thinkink-gs4-eaamfgn" , sizeof (_name) - 1 );
164+ _name[sizeof (_name) - 1 ] = ' \0 ' ;
165+ } else {
166+ // Did not detect SSD1680, use T5 driver
167+ strncpy (_name, " thinkink-gs4-t5" , sizeof (_name) - 1 );
168+ _name[sizeof (_name) - 1 ] = ' \0 ' ;
169+ }
170+ }
171+
172172 // Create display driver object using the factory function
173173 _drvDisp = CreateDrvDisp (_name, dc, rst, cs, srcs, busy);
174174 if (!_drvDisp) {
@@ -210,4 +210,71 @@ void DisplayHardware::writeMessage(const char *message) {
210210 } else {
211211 WS_DEBUG_PRINTLN (" [display] No display driver initialized!" );
212212 }
213+ }
214+
215+ /* !
216+ @brief Detects if an SSD1680 EPD is connected using bit-banged SPI.
217+ @param cs
218+ Chip Select pin number.
219+ @param dc
220+ Data/Command pin number.
221+ @param rst
222+ Reset pin number.
223+ @return True if an SSD1680 is detected, False otherwise (IL0373 or different
224+ EPD).
225+ */
226+ bool DisplayHardware::detect_ssd1680 (uint8_t cs, uint8_t dc, uint8_t rst) {
227+ // note: for a complete implementation reference, see
228+ // https://github.com/adafruit/circuitpython/commit/f4316cb2491c815b128acca47f1bb75519fe306e
229+ // Configure SPI pins to bit-bang
230+ pinMode (MOSI, OUTPUT);
231+ pinMode (SCK, OUTPUT);
232+ pinMode (cs, OUTPUT);
233+ pinMode (dc, OUTPUT);
234+ pinMode (rst, OUTPUT);
235+
236+ // Begin transaction by pulling cs and dc LOW
237+ digitalWrite (cs, LOW);
238+ digitalWrite (dc, LOW);
239+ digitalWrite (SCK, LOW);
240+ digitalWrite (rst, HIGH);
241+
242+ // Write to read register 0x71
243+ uint8_t cmd = 0x71 ;
244+ for (int i = 0 ; i < 8 ; i++) {
245+ digitalWrite (MOSI, (cmd & (1 << (7 - i))) != 0 );
246+ digitalWrite (SCK, HIGH);
247+ digitalWrite (SCK, LOW);
248+ }
249+
250+ // Set DC high to indicate data and switch MOSI to input with PUR in case
251+ // SSD1680 does not send data back
252+ digitalWrite (dc, HIGH);
253+ delayMicroseconds (1 );
254+ pinMode (MOSI, INPUT_PULLUP);
255+ delayMicroseconds (1 );
256+
257+ // Read response from register
258+ uint8_t status = 0 ;
259+ for (int i = 0 ; i < 8 ; i++) {
260+ status <<= 1 ;
261+ if (digitalRead (MOSI)) {
262+ status |= 1 ;
263+ }
264+ digitalWrite (SCK, HIGH);
265+ delayMicroseconds (1 );
266+ digitalWrite (SCK, LOW);
267+ delayMicroseconds (1 );
268+ }
269+
270+ // End transaction by pulling CS high
271+ digitalWrite (cs, HIGH);
272+
273+ // Put back MOSI pin as an output
274+ pinMode (MOSI, OUTPUT);
275+
276+ WS_DEBUG_PRINT (" [display] Bitbang read 0x71: 0x" );
277+ WS_DEBUG_PRINTLN (status, HEX);
278+
279+ return status == 0xFF ;
213280}
0 commit comments