From 918d05e9a9861397cd131af83049d361e2347a00 Mon Sep 17 00:00:00 2001 From: Ton Huisman Date: Tue, 21 Jul 2026 22:53:12 +0200 Subject: [PATCH 1/5] [P073] Correct wrong content shown on 74HC595 displays --- src/_P073_7DGT.ino | 1 + src/src/PluginStructs/P073_data_struct.cpp | 15 --------------- src/src/PluginStructs/P073_data_struct.h | 1 - 3 files changed, 1 insertion(+), 16 deletions(-) diff --git a/src/_P073_7DGT.ino b/src/_P073_7DGT.ino index 8775baa2ec..2eec59bef1 100644 --- a/src/_P073_7DGT.ino +++ b/src/_P073_7DGT.ino @@ -42,6 +42,7 @@ // /** History + * 2026-07-21 tonhuisman: Fix wrong content displayed on 74HC595 displays (multiple fixes) * 2026-01-17 tonhuisman: Revert to using 'regular' Arduino GPIO functions for TM1637 displays on ESP8266 * 2026-01-12 tonhuisman: Fix initialization of number of digits when upgrading to 20260108 build, * formatted source with new Uncrustify config diff --git a/src/src/PluginStructs/P073_data_struct.cpp b/src/src/PluginStructs/P073_data_struct.cpp index 4f45136c21..06970e1c79 100644 --- a/src/src/PluginStructs/P073_data_struct.cpp +++ b/src/src/PluginStructs/P073_data_struct.cpp @@ -413,16 +413,6 @@ void P073_data_struct::hc595_ToOutputBuffer() { } } -void P073_data_struct::hc595_AdjustBuffer() { - if (digits < 8) { - const uint8_t delta = 8 - digits; - - for (uint8_t i = 0; i < digits; ++i) { - showbuffer[i] = showbuffer[i + delta]; - } - } -} - void P073_data_struct::hc595_InitDisplay() { pinMode(pin1, OUTPUT); pinMode(pin2, OUTPUT); @@ -904,7 +894,6 @@ bool P073_data_struct::plugin_once_a_second(struct EventStruct *event) { break; # if P073_USE_74HC595 case P073_74HC595_2_8DGT: - hc595_AdjustBuffer(); hc595_ToOutputBuffer(); if (hc595_Sequential()) { // Sequential displays don't need continuous refreshing @@ -1208,7 +1197,6 @@ bool P073_data_struct::plugin_write_7dn(struct EventStruct *event, break; # if P073_USE_74HC595 case P073_74HC595_2_8DGT: - hc595_AdjustBuffer(); hc595_ToOutputBuffer(); if (hc595_Sequential()) { // Sequential displays don't need continuous refreshing @@ -1289,7 +1277,6 @@ bool P073_data_struct::plugin_write_7dt(const String& text) { break; # if P073_USE_74HC595 case P073_74HC595_2_8DGT: - hc595_AdjustBuffer(); hc595_ToOutputBuffer(); if (hc595_Sequential()) { // Sequential displays don't need continuous refreshing @@ -1447,7 +1434,6 @@ bool P073_data_struct::plugin_write_7dst(struct EventStruct *event) { break; # if P073_USE_74HC595 case P073_74HC595_2_8DGT: - hc595_AdjustBuffer(); hc595_ToOutputBuffer(); if (hc595_Sequential()) { // Sequential displays don't need continuous refreshing @@ -1492,7 +1478,6 @@ bool P073_data_struct::plugin_write_7dsd(struct EventStruct *event) { break; # if P073_USE_74HC595 case P073_74HC595_2_8DGT: - hc595_AdjustBuffer(); hc595_ToOutputBuffer(); if (hc595_Sequential()) { // Sequential displays don't need continuous refreshing diff --git a/src/src/PluginStructs/P073_data_struct.h b/src/src/PluginStructs/P073_data_struct.h index 97bbbdba0d..43bcaedb75 100644 --- a/src/src/PluginStructs/P073_data_struct.h +++ b/src/src/PluginStructs/P073_data_struct.h @@ -403,7 +403,6 @@ struct P073_data_struct : public PluginTaskData_base { void hc595_InitDisplay(); void hc595_ShowBuffer(); void hc595_ToOutputBuffer(); - void hc595_AdjustBuffer(); bool hc595_Sequential() { return P073_HC595_SEQUENTIAL; } From ad18e5f679d2d23e5cc07a5edb0f62ab46f2c49a Mon Sep 17 00:00:00 2001 From: Ton Huisman Date: Fri, 24 Jul 2026 23:02:29 +0200 Subject: [PATCH 2/5] [P073] Improve update speed for 74HC595 using DIREct-GPIO Fix 7dn and 7dt content for 74HC595 displays Also use DIRECT_GPIO for remaining GPIO functions of TM1637 and MAX7219 --- src/_P073_7DGT.ino | 6 +- src/src/PluginStructs/P073_data_struct.cpp | 89 ++++++++++++++-------- src/src/PluginStructs/P073_data_struct.h | 17 +++-- 3 files changed, 73 insertions(+), 39 deletions(-) diff --git a/src/_P073_7DGT.ino b/src/_P073_7DGT.ino index 2eec59bef1..86e34f7262 100644 --- a/src/_P073_7DGT.ino +++ b/src/_P073_7DGT.ino @@ -42,6 +42,8 @@ // /** History + * 2026-07-24 tonhuisman: Fix 7dn and 7dt commands for 74HC595 to show data correctly for display setups with less than 8 digits + * Improve update speed for 74HC595 by using DIRECT_GPIO library for all GPIO commands (also for TM1637 and MAX7219) * 2026-07-21 tonhuisman: Fix wrong content displayed on 74HC595 displays (multiple fixes) * 2026-01-17 tonhuisman: Revert to using 'regular' Arduino GPIO functions for TM1637 displays on ESP8266 * 2026-01-12 tonhuisman: Fix initialization of number of digits when upgrading to 20260108 build, @@ -318,7 +320,7 @@ boolean Plugin_073(uint8_t function, struct EventStruct *event, String& string) # if P073_USE_74HC595 - if (P073_data->is74HC595Matrix()) { + if (P073_data->is74HC595Multiplex()) { Scheduler.setPluginTaskTimer(10, event->TaskIndex, 0); } # endif // if P073_USE_74HC595 @@ -376,7 +378,7 @@ boolean Plugin_073(uint8_t function, struct EventStruct *event, String& string) success = P073_data->plugin_fifty_per_second(event); if (success) { - Scheduler.setPluginTaskTimer(0, event->TaskIndex, 0); + Scheduler.setPluginTaskTimer(5, event->TaskIndex, 0); } // success = false; // Don't send out to (not configurable) Controllers or Rules diff --git a/src/src/PluginStructs/P073_data_struct.cpp b/src/src/PluginStructs/P073_data_struct.cpp index 06970e1c79..8ffd601421 100644 --- a/src/src/PluginStructs/P073_data_struct.cpp +++ b/src/src/PluginStructs/P073_data_struct.cpp @@ -303,16 +303,14 @@ bool P073_data_struct::plugin_fifty_per_second(struct EventStruct *event) { counter50++; # endif // ifdef P073_DEBUG - if (P073_74HC595_2_8DGT == displayModel) { - if (P073_HC595_MULTIPLEX) { - hc595_ShowBuffer(); - } + if (is74HC595Multiplex()) { + hc595_ShowBuffer(); return true; } return false; } -bool P073_data_struct::is74HC595Matrix() { return P073_74HC595_2_8DGT == displayModel && P073_HC595_MULTIPLEX; } +bool P073_data_struct::is74HC595Multiplex() { return P073_74HC595_2_8DGT == displayModel && P073_HC595_MULTIPLEX; } // ==================================== // ---- 74HC595 specific functions ---- @@ -353,7 +351,7 @@ void P073_data_struct::hc595_ShowBuffer() { # endif // if P073_USE_74HCMULTIPLEX for (; i != stop && i >= 0; i += incr) { - shiftOut(pin1, pin2, MSBFIRST, outputbuffer[i]); // Digit data out + DIRECT_shiftOut(pin1, pin2, MSBFIRST, outputbuffer[i]); // Digit data out // 2, 3 and some 4 digit modules use sequential digit values (in reversed order) // 4, 6 and 8 digit modules use multiplexing in LTR order @@ -373,13 +371,13 @@ void P073_data_struct::hc595_ShowBuffer() { } if (digit != 0xFF) { // Select multiplexer digit, 0xFF is invalid - shiftOut(pin1, pin2, MSBFIRST, digit); + DIRECT_shiftOut(pin1, pin2, MSBFIRST, digit); } # endif // if P073_USE_74HCMULTIPLEX if ((P073_HC595_SEQUENTIAL && (0 == i)) || P073_HC595_MULTIPLEX) { - digitalWrite(pin3, LOW); // Clock data - digitalWrite(pin3, HIGH); + DIRECT_pinWrite(pin3, LOW); // Clock data + DIRECT_pinWrite(pin3, HIGH); } } @@ -413,11 +411,21 @@ void P073_data_struct::hc595_ToOutputBuffer() { } } +void P073_data_struct::hc595_ShiftinView() { + if (digits < 8) { + uint8_t n = 0; + + for (uint8_t i = 8 - digits; i < 8; ++i, ++n) { + showbuffer[n] = showbuffer[i]; + } + } +} + void P073_data_struct::hc595_InitDisplay() { - pinMode(pin1, OUTPUT); - pinMode(pin2, OUTPUT); - pinMode(pin3, OUTPUT); - digitalWrite(pin3, HIGH); + DIRECT_PINMODE_OUTPUT(pin1); + DIRECT_PINMODE_OUTPUT(pin2); + DIRECT_PINMODE_OUTPUT(pin3); + DIRECT_pinWrite(pin3, HIGH); } # endif // if P073_USE_74HC595 @@ -1197,6 +1205,7 @@ bool P073_data_struct::plugin_write_7dn(struct EventStruct *event, break; # if P073_USE_74HC595 case P073_74HC595_2_8DGT: + hc595_ShiftinView(); hc595_ToOutputBuffer(); if (hc595_Sequential()) { // Sequential displays don't need continuous refreshing @@ -1277,6 +1286,7 @@ bool P073_data_struct::plugin_write_7dt(const String& text) { break; # if P073_USE_74HC595 case P073_74HC595_2_8DGT: + hc595_ShiftinView(); hc595_ToOutputBuffer(); if (hc595_Sequential()) { // Sequential displays don't need continuous refreshing @@ -1633,12 +1643,12 @@ bool P073_data_struct::plugin_write_7dbin(const String& text) { // ---- TM1637 specific functions ---- // =================================== -# define CLK_HIGH() DIRECT_pinWrite(this->pin1, HIGH) -# define CLK_LOW() DIRECT_pinWrite(this->pin1, LOW) -# define DIO_HIGH() DIRECT_pinWrite(this->pin2, HIGH) -# define DIO_LOW() DIRECT_PINMODE_OUTPUT(this->pin2); DIRECT_pinWrite(this->pin2, LOW) -# define DIO_INPUT() DIRECT_PINMODE_INPUT(this->pin2) -# define DIO_OUTPUT() DIRECT_PINMODE_OUTPUT(this->pin2) +# define CLK_HIGH() DIRECT_pinWrite(this->pin1, HIGH) +# define CLK_LOW() DIRECT_pinWrite(this->pin1, LOW) +# define DIO_HIGH() DIRECT_pinWrite(this->pin2, HIGH) +# define DIO_LOW() DIRECT_PINMODE_OUTPUT(this->pin2); DIRECT_pinWrite(this->pin2, LOW) +# define DIO_INPUT() DIRECT_PINMODE_INPUT(this->pin2) +# define DIO_OUTPUT() DIRECT_PINMODE_OUTPUT(this->pin2) void P073_data_struct::tm1637_i2cStart() { # if defined(P073_DEBUG) && !defined(BUILD_NO_DEBUG) @@ -1767,11 +1777,11 @@ void P073_data_struct::tm1637_SetPowerBrightness(uint8_t brightlvl, } void P073_data_struct::tm1637_InitDisplay() { - pinMode(this->pin1, OUTPUT); - pinMode(this->pin2, OUTPUT); + DIRECT_PINMODE_OUTPUT(this->pin1); + DIRECT_PINMODE_OUTPUT(this->pin2); - digitalWrite(this->pin1, HIGH); - digitalWrite(this->pin2, HIGH); + DIRECT_pinWrite(this->pin1, HIGH); + DIRECT_pinWrite(this->pin2, HIGH); delayMicroseconds(TM1637_CLOCKDELAY); uint8_t bytesToPrint[]{ 0x40 }; @@ -1897,10 +1907,10 @@ void P073_data_struct::max7219_spiTransfer(ESPEASY_VOLATILE(uint8_t) opcode, ESPEASY_VOLATILE(uint8_t) data) { spidata[1] = opcode; spidata[0] = data; - digitalWrite(pin3, LOW); - shiftOut(pin1, pin2, MSBFIRST, spidata[1]); - shiftOut(pin1, pin2, MSBFIRST, spidata[0]); - digitalWrite(pin3, HIGH); + DIRECT_pinWrite(pin3, LOW); + DIRECT_shiftOut(pin1, pin2, MSBFIRST, spidata[1]); + DIRECT_shiftOut(pin1, pin2, MSBFIRST, spidata[0]); + DIRECT_pinWrite(pin3, HIGH); } void P073_data_struct::max7219_ClearDisplay() { @@ -1935,10 +1945,10 @@ void P073_data_struct::max7219_SetDigit(int dgtpos, } void P073_data_struct::max7219_InitDisplay() { - pinMode(pin1, OUTPUT); - pinMode(pin2, OUTPUT); - pinMode(pin3, OUTPUT); - digitalWrite(pin3, HIGH); + DIRECT_PINMODE_OUTPUT(pin1); + DIRECT_PINMODE_OUTPUT(pin2); + DIRECT_PINMODE_OUTPUT(pin3); + DIRECT_pinWrite(pin3, HIGH); max7219_spiTransfer(OP_DISPLAYTEST, 0); max7219_spiTransfer(OP_SCANLIMIT, 7); // scanlimit setup to max at Init max7219_spiTransfer(OP_DECODEMODE, 0); @@ -2006,4 +2016,21 @@ void P073_data_struct::max7219_ShowBuffer() { } } +// Borrowed from wiring_shift.c, using DIRECT_GPIO +void P073_data_struct::DIRECT_shiftOut(uint8_t dataPin, + uint8_t clockPin, + uint8_t bitOrder, + uint8_t val) { + for (uint8_t i = 0; i < 8; i++) { + if (bitOrder == LSBFIRST) { + DIRECT_pinWrite(dataPin, !!(val & (1 << i))); + } else { + DIRECT_pinWrite(dataPin, !!(val & (1 << (7 - i)))); + } + + DIRECT_pinWrite(clockPin, HIGH); + DIRECT_pinWrite(clockPin, LOW); + } +} + #endif // ifdef USES_P073 diff --git a/src/src/PluginStructs/P073_data_struct.h b/src/src/PluginStructs/P073_data_struct.h index 43bcaedb75..5e4a91d4a2 100644 --- a/src/src/PluginStructs/P073_data_struct.h +++ b/src/src/PluginStructs/P073_data_struct.h @@ -105,7 +105,7 @@ # define TM1637_POWER_ON 0b10001000 # define TM1637_POWER_OFF 0b10000000 -# define TM1637_CLOCKDELAY 10 // FIXME TD-er: Maybe lower this as we can get as low as 2 usec to remain below the max 250 kHz +# define TM1637_CLOCKDELAY 10 // FIXME TD-er: Maybe lower this as we can get as low as 2 usec to remain below the max 250 kHz # define TM1637_4DIGIT 4 # define TM1637_6DIGIT 2 @@ -238,7 +238,7 @@ struct P073_data_struct : public PluginTaskData_base { # if P073_USE_74HC595 bool plugin_fifty_per_second(struct EventStruct *event); - bool is74HC595Matrix(); + bool is74HC595Multiplex(); # endif // if P073_USE_74HC595 void FillBufferWithTime(bool sevendgt_now, uint8_t sevendgt_hours, @@ -290,10 +290,10 @@ struct P073_data_struct : public PluginTaskData_base { uint8_t tm1637_getFontChar(uint8_t index, uint8_t fontset); - int dotpos = -1; - uint8_t showbuffer[8] = { 0 }; - bool showperiods[8] = { 0 }; - uint8_t spidata[2] = { 0 }; + int dotpos = -1; + uint8_t showbuffer[8]{}; + bool showperiods[8]{}; + uint8_t spidata[2]{}; uint8_t pin1 = 0xFF; uint8_t pin2 = 0xFF; uint8_t pin3 = 0xFF; @@ -402,12 +402,17 @@ struct P073_data_struct : public PluginTaskData_base { # if P073_USE_74HC595 void hc595_InitDisplay(); void hc595_ShowBuffer(); + void hc595_ShiftinView(); void hc595_ToOutputBuffer(); bool hc595_Sequential() { return P073_HC595_SEQUENTIAL; } uint8_t outputbuffer[8]{}; # endif // if P073_USE_74HC595 + void DIRECT_shiftOut(uint8_t dataPin, + uint8_t clockPin, + uint8_t bitOrder, + uint8_t val); }; From 01a216db98a2b479339e7a4fa46523772a9d8c97 Mon Sep 17 00:00:00 2001 From: Ton Huisman Date: Sat, 25 Jul 2026 16:18:45 +0200 Subject: [PATCH 3/5] [P073] Fix initialization for GPIO pins, allow some more space for temperature values --- src/_P073_7DGT.ino | 1 + src/src/PluginStructs/P073_data_struct.cpp | 22 +++++++++++----------- 2 files changed, 12 insertions(+), 11 deletions(-) diff --git a/src/_P073_7DGT.ino b/src/_P073_7DGT.ino index 86e34f7262..81e563296c 100644 --- a/src/_P073_7DGT.ino +++ b/src/_P073_7DGT.ino @@ -42,6 +42,7 @@ // /** History + * 2026-07-25 tonhuisman: Use Arduino pin initialization as some ESPs don't properly set up their pins with DIRECT_GPIO_OUTPUT * 2026-07-24 tonhuisman: Fix 7dn and 7dt commands for 74HC595 to show data correctly for display setups with less than 8 digits * Improve update speed for 74HC595 by using DIRECT_GPIO library for all GPIO commands (also for TM1637 and MAX7219) * 2026-07-21 tonhuisman: Fix wrong content displayed on 74HC595 displays (multiple fixes) diff --git a/src/src/PluginStructs/P073_data_struct.cpp b/src/src/PluginStructs/P073_data_struct.cpp index 8ffd601421..25a6e491ad 100644 --- a/src/src/PluginStructs/P073_data_struct.cpp +++ b/src/src/PluginStructs/P073_data_struct.cpp @@ -422,9 +422,9 @@ void P073_data_struct::hc595_ShiftinView() { } void P073_data_struct::hc595_InitDisplay() { - DIRECT_PINMODE_OUTPUT(pin1); - DIRECT_PINMODE_OUTPUT(pin2); - DIRECT_PINMODE_OUTPUT(pin3); + pinMode(pin1, OUTPUT); // Use Arduino pin initialization as some ESPs don't properly set up their pins with DIRECT_GPIO_OUTPUT + pinMode(pin2, OUTPUT); + pinMode(pin3, OUTPUT); DIRECT_pinWrite(pin3, HIGH); } @@ -539,9 +539,9 @@ void P073_data_struct::FillBufferWithTemp(int temperature) { String format; if (hideDegree) { - format = (between10and0 ? F(" %02d") : (between0andMinus10 ? F(" %03d") : F("%8d"))); + format = (between10and0 ? F(" %03d") : (between0andMinus10 ? F(" %04d") : F("%8d"))); } else { - format = (between10and0 ? F(" %02d") : (between0andMinus10 ? F(" %03d") : F("%7d"))); + format = (between10and0 ? F(" %03d") : (between0andMinus10 ? F(" %04d") : F("%7d"))); } sprintf_P(p073_digit, format.c_str(), temperature); const size_t p073_numlenght = strlen(p073_digit); @@ -1777,8 +1777,8 @@ void P073_data_struct::tm1637_SetPowerBrightness(uint8_t brightlvl, } void P073_data_struct::tm1637_InitDisplay() { - DIRECT_PINMODE_OUTPUT(this->pin1); - DIRECT_PINMODE_OUTPUT(this->pin2); + pinMode(this->pin1, OUTPUT); // Use Arduino pin initialization as some ESPs don't properly set up their pins with DIRECT_GPIO_OUTPUT + pinMode(this->pin2, OUTPUT); DIRECT_pinWrite(this->pin1, HIGH); DIRECT_pinWrite(this->pin2, HIGH); @@ -1827,7 +1827,7 @@ void P073_data_struct::tm1637_ShowTemp6(bool sep) { bytesToPrint[0] = 0xC0; bytesToPrint[1] = tm1637_separator(tm1637_getFontChar(showbuffer[5], fontset), sep); bytesToPrint[2] = tm1637_getFontChar(showbuffer[4], fontset); - bytesToPrint[3] = tm1637_getFontChar(10, fontset); + bytesToPrint[3] = tm1637_getFontChar(showbuffer[3], fontset); // Fill first digit of display too bytesToPrint[4] = tm1637_getFontChar(10, fontset); bytesToPrint[5] = tm1637_getFontChar(showbuffer[7], fontset); bytesToPrint[6] = tm1637_getFontChar(showbuffer[6], fontset); @@ -1945,9 +1945,9 @@ void P073_data_struct::max7219_SetDigit(int dgtpos, } void P073_data_struct::max7219_InitDisplay() { - DIRECT_PINMODE_OUTPUT(pin1); - DIRECT_PINMODE_OUTPUT(pin2); - DIRECT_PINMODE_OUTPUT(pin3); + pinMode(pin1, OUTPUT); // Use Arduino pin initialization as some ESPs don't properly set up their pins with DIRECT_GPIO_OUTPUT + pinMode(pin2, OUTPUT); + pinMode(pin3, OUTPUT); DIRECT_pinWrite(pin3, HIGH); max7219_spiTransfer(OP_DISPLAYTEST, 0); max7219_spiTransfer(OP_SCANLIMIT, 7); // scanlimit setup to max at Init From c48d8302d4e1606eccf87e1061691a5683243e81 Mon Sep 17 00:00:00 2001 From: Ton Huisman Date: Mon, 27 Jul 2026 22:59:31 +0200 Subject: [PATCH 4/5] [P073] Restructure code per display in separate files --- src/_P073_7DGT.ino | 2 + src/src/PluginStructs/P073_data_struct.cpp | 568 +----------------- src/src/PluginStructs/P073_data_struct.h | 22 +- .../PluginStructs/P073_display_74HC595.cpp | 131 ++++ .../PluginStructs/P073_display_MAX7219.cpp | 129 ++++ src/src/PluginStructs/P073_display_TM1637.cpp | 260 ++++++++ 6 files changed, 549 insertions(+), 563 deletions(-) create mode 100644 src/src/PluginStructs/P073_display_74HC595.cpp create mode 100644 src/src/PluginStructs/P073_display_MAX7219.cpp create mode 100644 src/src/PluginStructs/P073_display_TM1637.cpp diff --git a/src/_P073_7DGT.ino b/src/_P073_7DGT.ino index 81e563296c..1d71d4b327 100644 --- a/src/_P073_7DGT.ino +++ b/src/_P073_7DGT.ino @@ -42,6 +42,8 @@ // /** History + * 2026-07-27 tonhuisman: Restructure plugin_struct source into separate files per supported display model for maintainability + * Some minor code optimization for 74HC595 displays * 2026-07-25 tonhuisman: Use Arduino pin initialization as some ESPs don't properly set up their pins with DIRECT_GPIO_OUTPUT * 2026-07-24 tonhuisman: Fix 7dn and 7dt commands for 74HC595 to show data correctly for display setups with less than 8 digits * Improve update speed for 74HC595 by using DIRECT_GPIO library for all GPIO commands (also for TM1637 and MAX7219) diff --git a/src/src/PluginStructs/P073_data_struct.cpp b/src/src/PluginStructs/P073_data_struct.cpp index 25a6e491ad..7ca97ac19a 100644 --- a/src/src/PluginStructs/P073_data_struct.cpp +++ b/src/src/PluginStructs/P073_data_struct.cpp @@ -286,150 +286,12 @@ void P073_data_struct::init(struct EventStruct *event) if (output == P073_DISP_MANUAL) { ClearBuffer(); hc595_ToOutputBuffer(); - - if (hc595_Sequential()) { // Sequential displays don't need continuous refreshing - hc595_ShowBuffer(); - } } break; # endif // if P073_USE_74HC595 } } -# if P073_USE_74HC595 - -bool P073_data_struct::plugin_fifty_per_second(struct EventStruct *event) { - # ifdef P073_DEBUG - counter50++; - # endif // ifdef P073_DEBUG - - if (is74HC595Multiplex()) { - hc595_ShowBuffer(); - return true; - } - return false; -} - -bool P073_data_struct::is74HC595Multiplex() { return P073_74HC595_2_8DGT == displayModel && P073_HC595_MULTIPLEX; } - -// ==================================== -// ---- 74HC595 specific functions ---- -// ==================================== - -void P073_data_struct::hc595_ShowBuffer() { - # if P073_USE_74HCMULTIPLEX - const uint8_t hc595digit4[] = { - 0b00001000, // left segment - 0b00000100, - 0b00000010, - 0b00000001, // right segment - }; - - const uint8_t hc595digit8[] = { - 0b00010000, // left segment - 0b00100000, - 0b01000000, - 0b10000000, - 0b00000001, - 0b00000010, - 0b00000100, - 0b00001000, // right segment - }; - # endif // if P073_USE_74HCMULTIPLEX - - int8_t i = digits - 1; - int8_t stop = -1; - int8_t incr = -1; - - # if P073_USE_74HCMULTIPLEX - - if (P073_HC595_MULTIPLEX) { - i = dspDgt; - stop = dspDgt + 1; - incr = 1; - } - # endif // if P073_USE_74HCMULTIPLEX - - for (; i != stop && i >= 0; i += incr) { - DIRECT_shiftOut(pin1, pin2, MSBFIRST, outputbuffer[i]); // Digit data out - - // 2, 3 and some 4 digit modules use sequential digit values (in reversed order) - // 4, 6 and 8 digit modules use multiplexing in LTR order - # if P073_USE_74HCMULTIPLEX - uint8_t digit = 0xFF; - - if (P073_HC595_MULTIPLEX) { - if (4 == digits) { - digit = hc595digit4[i]; - } else - if (6 == digits) { - digit = hc595digit8[i + (i > 2 ? 1 : 0)]; - } else - if (8 == digits) { - digit = hc595digit8[i]; - } - } - - if (digit != 0xFF) { // Select multiplexer digit, 0xFF is invalid - DIRECT_shiftOut(pin1, pin2, MSBFIRST, digit); - } - # endif // if P073_USE_74HCMULTIPLEX - - if ((P073_HC595_SEQUENTIAL && (0 == i)) || P073_HC595_MULTIPLEX) { - DIRECT_pinWrite(pin3, LOW); // Clock data - DIRECT_pinWrite(pin3, HIGH); - } - } - - if (i >= digits) { - dspDgt = 0; - } else { - dspDgt = i; - } - - # ifdef P073_DEBUG - - // TODO disable log - // if ((counter50 % 200 == 0) || P073_HC595_SEQUENTIAL) { - // addLog(LOG_LEVEL_INFO, strformat(F("P073: hc595_ShowBuffer (end) dgt:%d i:%d stop:%d incr:%d pin1: %d pin2: %d pin3: %d"), - // digits, i, stop, incr, pin1, pin2, pin3)); - // } - # endif // ifdef P073_DEBUG -} - -void P073_data_struct::hc595_ToOutputBuffer() { - for (uint8_t i = 0; i < 8; ++i) { - uint8_t value; - - // 74HC595 uses inverted data, compared to MAX7219/TM1637 - value = ~P073_getFontChar(showbuffer[i], fontset); - - if (showperiods[i]) { - value &= 0x7F; - } - outputbuffer[i] = P073_revert7bits(value); // Rotate bits 6..0 - } -} - -void P073_data_struct::hc595_ShiftinView() { - if (digits < 8) { - uint8_t n = 0; - - for (uint8_t i = 8 - digits; i < 8; ++i, ++n) { - showbuffer[n] = showbuffer[i]; - } - } -} - -void P073_data_struct::hc595_InitDisplay() { - pinMode(pin1, OUTPUT); // Use Arduino pin initialization as some ESPs don't properly set up their pins with DIRECT_GPIO_OUTPUT - pinMode(pin2, OUTPUT); - pinMode(pin3, OUTPUT); - DIRECT_pinWrite(pin3, HIGH); -} - -# endif // if P073_USE_74HC595 - void P073_data_struct::FillBufferWithTime(bool sevendgt_now, uint8_t sevendgt_hours, uint8_t sevendgt_minutes, @@ -903,10 +765,6 @@ bool P073_data_struct::plugin_once_a_second(struct EventStruct *event) { # if P073_USE_74HC595 case P073_74HC595_2_8DGT: hc595_ToOutputBuffer(); - - if (hc595_Sequential()) { // Sequential displays don't need continuous refreshing - hc595_ShowBuffer(); - } break; # endif // if P073_USE_74HC595 } @@ -953,10 +811,6 @@ bool P073_data_struct::plugin_ten_per_second(struct EventStruct *event) { case P073_74HC595_2_8DGT: { hc595_ToOutputBuffer(); - - if (hc595_Sequential()) { // Sequential displays don't need continuous refreshing - hc595_ShowBuffer(); - } break; } # endif // if P073_USE_74HC595 @@ -967,6 +821,22 @@ bool P073_data_struct::plugin_ten_per_second(struct EventStruct *event) { # endif // if P073_SCROLL_TEXT +# if P073_USE_74HC595 + +bool P073_data_struct::plugin_fifty_per_second(struct EventStruct *event) { + # ifdef P073_DEBUG + counter50++; + # endif // ifdef P073_DEBUG + + if (is74HC595Multiplex()) { + hc595_ShowBuffer(); + return true; + } + return false; +} + +# endif // if P073_USE_74HC595 + const char p073_commands[] PROGMEM = "7dn|7dt|" # if P073_7DDT_COMMAND @@ -1207,10 +1077,6 @@ bool P073_data_struct::plugin_write_7dn(struct EventStruct *event, case P073_74HC595_2_8DGT: hc595_ShiftinView(); hc595_ToOutputBuffer(); - - if (hc595_Sequential()) { // Sequential displays don't need continuous refreshing - hc595_ShowBuffer(); - } break; # endif // if P073_USE_74HC595 } @@ -1288,10 +1154,6 @@ bool P073_data_struct::plugin_write_7dt(const String& text) { case P073_74HC595_2_8DGT: hc595_ShiftinView(); hc595_ToOutputBuffer(); - - if (hc595_Sequential()) { // Sequential displays don't need continuous refreshing - hc595_ShowBuffer(); - } break; # endif // if P073_USE_74HC595 } @@ -1386,16 +1248,11 @@ bool P073_data_struct::plugin_write_7ddt(const String& text) { # if P073_USE_74HC595 } else - // if (P073_74HC595_2_8DGT == P073_data->displayModel) { if (digits < 8) { FillBufferWithDash(); } hc595_ToOutputBuffer(); - - if (hc595_Sequential()) { // Sequential displays don't need continuous refreshing - hc595_ShowBuffer(); - } # endif // if P073_USE_74HC595 } @@ -1445,10 +1302,6 @@ bool P073_data_struct::plugin_write_7dst(struct EventStruct *event) { # if P073_USE_74HC595 case P073_74HC595_2_8DGT: hc595_ToOutputBuffer(); - - if (hc595_Sequential()) { // Sequential displays don't need continuous refreshing - hc595_ShowBuffer(); - } break; # endif // if P073_USE_74HC595 } @@ -1489,10 +1342,6 @@ bool P073_data_struct::plugin_write_7dsd(struct EventStruct *event) { # if P073_USE_74HC595 case P073_74HC595_2_8DGT: hc595_ToOutputBuffer(); - - if (hc595_Sequential()) { // Sequential displays don't need continuous refreshing - hc595_ShowBuffer(); - } break; # endif // if P073_USE_74HC595 } @@ -1538,10 +1387,6 @@ bool P073_data_struct::plugin_write_7dtext(const String& text) { # if P073_USE_74HC595 case P073_74HC595_2_8DGT: hc595_ToOutputBuffer(); - - if (hc595_Sequential()) { // Sequential displays don't need continuous refreshing - hc595_ShowBuffer(); - } break; # endif // if P073_USE_74HC595 } @@ -1623,10 +1468,6 @@ bool P073_data_struct::plugin_write_7dbin(const String& text) { # if P073_USE_74HC595 case P073_74HC595_2_8DGT: hc595_ToOutputBuffer(); - - if (hc595_Sequential()) { // Sequential displays don't need continuous refreshing - hc595_ShowBuffer(); - } break; # endif // if P073_USE_74HC595 } @@ -1639,383 +1480,6 @@ bool P073_data_struct::plugin_write_7dbin(const String& text) { # endif // if P073_7DBIN_COMMAND -// =================================== -// ---- TM1637 specific functions ---- -// =================================== - -# define CLK_HIGH() DIRECT_pinWrite(this->pin1, HIGH) -# define CLK_LOW() DIRECT_pinWrite(this->pin1, LOW) -# define DIO_HIGH() DIRECT_pinWrite(this->pin2, HIGH) -# define DIO_LOW() DIRECT_PINMODE_OUTPUT(this->pin2); DIRECT_pinWrite(this->pin2, LOW) -# define DIO_INPUT() DIRECT_PINMODE_INPUT(this->pin2) -# define DIO_OUTPUT() DIRECT_PINMODE_OUTPUT(this->pin2) - -void P073_data_struct::tm1637_i2cStart() { - # if defined(P073_DEBUG) && !defined(BUILD_NO_DEBUG) - addLog(LOG_LEVEL_DEBUG, F("7DGT : Comm Start")); - # endif // if defined(P073_DEBUG) && !defined(BUILD_NO_DEBUG) - DIO_LOW(); - delayMicroseconds(TM1637_CLOCKDELAY); -} - -void P073_data_struct::tm1637_i2cStop() { - # if defined(P073_DEBUG) && !defined(BUILD_NO_DEBUG) - addLog(LOG_LEVEL_DEBUG, F("7DGT : Comm Stop")); - # endif // if defined(P073_DEBUG) && !defined(BUILD_NO_DEBUG) - DIO_LOW(); - delayMicroseconds(TM1637_CLOCKDELAY); - CLK_HIGH(); - delayMicroseconds(TM1637_CLOCKDELAY); - DIO_HIGH(); - delayMicroseconds(TM1637_CLOCKDELAY); -} - -bool P073_data_struct::tm1637_i2cAck() { - CLK_LOW(); - DIO_INPUT(); - - delayMicroseconds(TM1637_CLOCKDELAY); - CLK_HIGH(); - const uint32_t start_wait = micros(); - - const bool acknowledged = -1 != - DIRECT_measureWaitForPinState_ISR(this->pin2, start_wait, TM1637_CLOCKDELAY, 0); - - const int32_t timePassed = usecPassedSince_fast(start_wait); - - if (timePassed < TM1637_CLOCKDELAY) { - delayMicroseconds(TM1637_CLOCKDELAY - timePassed); - } - - # if defined(P073_DEBUG) && !defined(BUILD_NO_DEBUG) - - if (loglevelActiveFor(LOG_LEVEL_DEBUG)) { - String log = F("7DGT : Comm ACK="); - - if (acknowledged) { - log += F("TRUE"); - } else { - log += F("FALSE"); - } - addLogMove(LOG_LEVEL_DEBUG, log); - } - # endif // if defined(P073_DEBUG) && !defined(BUILD_NO_DEBUG) - CLK_HIGH(); - - delayMicroseconds(TM1637_CLOCKDELAY); - CLK_LOW(); - delayMicroseconds(TM1637_CLOCKDELAY); - DIO_OUTPUT(); - - return acknowledged; -} - -void P073_data_struct::tm1637_i2cWrite_ack(uint8_t bytesToPrint[], - uint8_t length) { - # ifdef P073_DEBUG - - if (loglevelActiveFor(LOG_LEVEL_INFO)) { - addLog(LOG_LEVEL_INFO, concat(F("7DGT : TM1637 databuffer: 0x"), formatToHex_array(bytesToPrint, length))); - } - # endif // ifdef P073_DEBUG - tm1637_i2cStart(); - - for (uint8_t i = 0; i < length; ++i) { - tm1637_i2cWriteByte_ack(bytesToPrint[i]); - } - tm1637_i2cStop(); -} - -void P073_data_struct::tm1637_i2cWriteByte_ack(uint8_t bytetoprint) { - tm1637_i2cWrite(bytetoprint); - tm1637_i2cAck(); -} - -void P073_data_struct::tm1637_i2cWrite(uint8_t bytetoprint) { - # if defined(P073_DEBUG) && !defined(BUILD_NO_DEBUG) - addLog(LOG_LEVEL_DEBUG, F("7DGT : WriteByte")); - # endif // if defined(P073_DEBUG) && !defined(BUILD_NO_DEBUG) - - for (uint8_t i = 0; i < 8; ++i) { - CLK_LOW(); - delayMicroseconds(TM1637_CLOCKDELAY >> 1); - - if (bytetoprint & 0b00000001) { - DIO_HIGH(); - } else { - DIO_LOW(); - } - delayMicroseconds(TM1637_CLOCKDELAY >> 1); - bytetoprint = bytetoprint >> 1; - CLK_HIGH(); - delayMicroseconds(TM1637_CLOCKDELAY); - } -} - -void P073_data_struct::tm1637_ClearDisplay() { - uint8_t bytesToPrint[7]{}; - - bytesToPrint[0] = 0xC0; - tm1637_i2cWrite_ack(bytesToPrint, 7); -} - -void P073_data_struct::tm1637_SetPowerBrightness(uint8_t brightlvl, - bool poweron) { - # ifdef P073_DEBUG - addLog(LOG_LEVEL_INFO, F("7DGT : Set BRIGHT")); - # endif // ifdef P073_DEBUG - brightlvl &= 0b111; - - if (poweron) { - brightlvl |= TM1637_POWER_ON; - } else { - brightlvl |= TM1637_POWER_OFF; - } - - uint8_t bytesToPrint[]{ brightlvl }; - tm1637_i2cWrite_ack(bytesToPrint, NR_ELEMENTS(bytesToPrint)); -} - -void P073_data_struct::tm1637_InitDisplay() { - pinMode(this->pin1, OUTPUT); // Use Arduino pin initialization as some ESPs don't properly set up their pins with DIRECT_GPIO_OUTPUT - pinMode(this->pin2, OUTPUT); - - DIRECT_pinWrite(this->pin1, HIGH); - DIRECT_pinWrite(this->pin2, HIGH); - - delayMicroseconds(TM1637_CLOCKDELAY); - uint8_t bytesToPrint[]{ 0x40 }; - tm1637_i2cWrite_ack(bytesToPrint, NR_ELEMENTS(bytesToPrint)); - tm1637_ClearDisplay(); -} - -uint8_t P073_data_struct::tm1637_separator(uint8_t value, - bool sep) { - if (sep) { - value |= 0b10000000; - } - return value; -} - -void P073_data_struct::tm1637_ShowTime6() { - tm1637_ShowDate6(true); // deduplicated -} - -void P073_data_struct::tm1637_ShowDate6(bool showTime) { - uint8_t bytesToPrint[7]{}; - - bytesToPrint[0] = 0xC0; - bytesToPrint[1] = tm1637_getFontChar(showbuffer[2], fontset); - bytesToPrint[2] = tm1637_separator(tm1637_getFontChar(showbuffer[1], fontset), timesep); - bytesToPrint[3] = tm1637_getFontChar(showbuffer[0], fontset); - - if (showTime) { - bytesToPrint[4] = tm1637_getFontChar(showbuffer[5], fontset); - bytesToPrint[5] = tm1637_getFontChar(showbuffer[4], fontset); - } else { - bytesToPrint[4] = tm1637_getFontChar(showbuffer[7], fontset); - bytesToPrint[5] = tm1637_getFontChar(showbuffer[6], fontset); - } - bytesToPrint[6] = tm1637_separator(tm1637_getFontChar(showbuffer[3], fontset), timesep); - - tm1637_i2cWrite_ack(bytesToPrint, 7); -} - -void P073_data_struct::tm1637_ShowTemp6(bool sep) { - uint8_t bytesToPrint[7]{}; - - bytesToPrint[0] = 0xC0; - bytesToPrint[1] = tm1637_separator(tm1637_getFontChar(showbuffer[5], fontset), sep); - bytesToPrint[2] = tm1637_getFontChar(showbuffer[4], fontset); - bytesToPrint[3] = tm1637_getFontChar(showbuffer[3], fontset); // Fill first digit of display too - bytesToPrint[4] = tm1637_getFontChar(10, fontset); - bytesToPrint[5] = tm1637_getFontChar(showbuffer[7], fontset); - bytesToPrint[6] = tm1637_getFontChar(showbuffer[6], fontset); - - tm1637_i2cWrite_ack(bytesToPrint, 7); -} - -void P073_data_struct::tm1637_ShowTimeTemp4(bool sep, - uint8_t bufoffset) { - uint8_t bytesToPrint[5]{}; - - bytesToPrint[0] = 0xC0; - bytesToPrint[1] = tm1637_getFontChar(showbuffer[0 + bufoffset], fontset); - bytesToPrint[2] = tm1637_separator(tm1637_getFontChar(showbuffer[1 + bufoffset], fontset), sep); - bytesToPrint[3] = tm1637_getFontChar(showbuffer[2 + bufoffset], fontset); - bytesToPrint[4] = tm1637_getFontChar(showbuffer[3 + bufoffset], fontset); - - tm1637_i2cWrite_ack(bytesToPrint, 5); -} - -void P073_data_struct::tm1637_SwapDigitInBuffer(uint8_t startPos) { - std::swap(showbuffer[2 + startPos], showbuffer[0 + startPos]); - std::swap(showbuffer[3 + startPos], showbuffer[5 + startPos]); - - std::swap(showperiods[2 + startPos], showperiods[0 + startPos]); - std::swap(showperiods[3 + startPos], showperiods[5 + startPos]); - - if (dotpos > -1) { - const uint8_t dotPositionSwap[] = { 0, 1, 4, 3, 2, 7, 6, 5, 8 }; - - dotpos = dotPositionSwap[dotpos]; - } -} - -void P073_data_struct::tm1637_ShowBuffer(uint8_t firstPos, - uint8_t lastPos, - bool useBinaryData) { - uint8_t bytesToPrint[8]{}; - - bytesToPrint[0] = 0xC0; - uint8_t length = 1; - - if (dotpos > -1) { - showperiods[dotpos] = true; - } - - uint8_t p073_datashowpos1; - - for (int i = firstPos; i < lastPos; ++i) { - if (useBinaryData) { - bytesToPrint[length] = showbuffer[i]; - } else { - p073_datashowpos1 = tm1637_separator( - tm1637_getFontChar(showbuffer[i], fontset), - showperiods[i]); - bytesToPrint[length] = p073_datashowpos1; - } - length++; - } - # ifdef P073_DEBUG - addLog(LOG_LEVEL_INFO, strformat(F("TM1673: Write bytes: %d buffer %d to %d"), length, firstPos, lastPos)); - # endif // ifdef P073_DEBUG - tm1637_i2cWrite_ack(bytesToPrint, length); -} - -// ==================================== -// ---- MAX7219 specific functions ---- -// ==================================== - -# define OP_DECODEMODE 9 -# define OP_INTENSITY 10 -# define OP_SCANLIMIT 11 -# define OP_SHUTDOWN 12 -# define OP_DISPLAYTEST 15 - -void P073_data_struct::max7219_spiTransfer(ESPEASY_VOLATILE(uint8_t) opcode, - ESPEASY_VOLATILE(uint8_t) data) { - spidata[1] = opcode; - spidata[0] = data; - DIRECT_pinWrite(pin3, LOW); - DIRECT_shiftOut(pin1, pin2, MSBFIRST, spidata[1]); - DIRECT_shiftOut(pin1, pin2, MSBFIRST, spidata[0]); - DIRECT_pinWrite(pin3, HIGH); -} - -void P073_data_struct::max7219_ClearDisplay() { - for (int i = 0; i < 8; i++) { - max7219_spiTransfer(i + 1, 0); - } -} - -void P073_data_struct::max7219_SetPowerBrightness(uint8_t brightlvl, - bool poweron) { - max7219_spiTransfer(OP_INTENSITY, brightlvl); - max7219_spiTransfer(OP_SHUTDOWN, poweron ? 1 : 0); -} - -void P073_data_struct::max7219_SetDigit(int dgtpos, - uint8_t dgtvalue, - bool showdot, - bool binaryData) { - uint8_t p073_tempvalue; - - if (binaryData) { - p073_tempvalue = dgtvalue; // Overwrite if binary data - } else - { - p073_tempvalue = P073_getFontChar(dgtvalue, fontset); - - if (showdot) { - p073_tempvalue |= 0b10000000; - } - } - max7219_spiTransfer(dgtpos + 1, p073_tempvalue); -} - -void P073_data_struct::max7219_InitDisplay() { - pinMode(pin1, OUTPUT); // Use Arduino pin initialization as some ESPs don't properly set up their pins with DIRECT_GPIO_OUTPUT - pinMode(pin2, OUTPUT); - pinMode(pin3, OUTPUT); - DIRECT_pinWrite(pin3, HIGH); - max7219_spiTransfer(OP_DISPLAYTEST, 0); - max7219_spiTransfer(OP_SCANLIMIT, 7); // scanlimit setup to max at Init - max7219_spiTransfer(OP_DECODEMODE, 0); - max7219_ClearDisplay(); - max7219_SetPowerBrightness(0, false); -} - -void P073_data_struct::max7219_ShowTime(bool sep) { - const uint8_t idx_list[] = { 7, 6, 4, 3, 1, 0 }; // Digits in reversed order, as the loop is backward - - for (int8_t i = 5; i >= 0; --i) { - max7219_SetDigit(idx_list[i], showbuffer[i], false); - } - - const uint8_t sepChar = P073_mapCharToFontPosition(sep ? '-' : ' ', fontset); - - max7219_SetDigit(2, sepChar, false); - max7219_SetDigit(5, sepChar, false); -} - -void P073_data_struct::max7219_ShowTemp(int8_t firstDot, - int8_t secondDot) { - max7219_SetDigit(0, 10, false); - - if (firstDot > -1) { showperiods[firstDot] = true; } - - if (secondDot > -1) { showperiods[secondDot] = true; } - - const int alignRight = rightAlignTempMAX7219 ? 0 : 1; - - for (int i = alignRight; i < 8; ++i) { - const int bufIndex = (7 + alignRight) - i; - - if (bufIndex < 8) { - max7219_SetDigit(i, - showbuffer[bufIndex], - showperiods[bufIndex]); - } - } -} - -void P073_data_struct::max7219_ShowDate() { - const uint8_t dotflags[8] = { false, true, false, true, false, false, false, false }; - - for (int i = 0; i < 8; ++i) { - max7219_SetDigit(i, - showbuffer[7 - i], - dotflags[7 - i]); - } -} - -void P073_data_struct::max7219_ShowBuffer() { - if (dotpos > -1) { - showperiods[dotpos] = true; - } - - for (int i = 0; i < 8; i++) { - max7219_SetDigit(i, - showbuffer[7 - i], - showperiods[7 - i] - # if P073_7DBIN_COMMAND - , binaryData - # endif // if P073_7DBIN_COMMAND - ); - } -} - // Borrowed from wiring_shift.c, using DIRECT_GPIO void P073_data_struct::DIRECT_shiftOut(uint8_t dataPin, uint8_t clockPin, diff --git a/src/src/PluginStructs/P073_data_struct.h b/src/src/PluginStructs/P073_data_struct.h index 5e4a91d4a2..c41e863af9 100644 --- a/src/src/PluginStructs/P073_data_struct.h +++ b/src/src/PluginStructs/P073_data_struct.h @@ -393,19 +393,19 @@ struct P073_data_struct : public PluginTaskData_base { uint8_t dgtvalue, bool showdot, bool binaryData = false); - void max7219_InitDisplay(); - void max7219_ShowTime(bool sep); - void max7219_ShowTemp(int8_t firstDot, - int8_t secondDot); - void max7219_ShowDate(); - void max7219_ShowBuffer(); + void max7219_InitDisplay(); + void max7219_ShowTime(bool sep); + void max7219_ShowTemp(int8_t firstDot, + int8_t secondDot); + void max7219_ShowDate(); + void max7219_ShowBuffer(); # if P073_USE_74HC595 - void hc595_InitDisplay(); - void hc595_ShowBuffer(); - void hc595_ShiftinView(); - void hc595_ToOutputBuffer(); + void hc595_InitDisplay(); + void hc595_ShowBuffer(); + void hc595_ShiftinView(); + void hc595_ToOutputBuffer(); - bool hc595_Sequential() { return P073_HC595_SEQUENTIAL; } + inline bool hc595_Sequential() { return P073_HC595_SEQUENTIAL; } uint8_t outputbuffer[8]{}; # endif // if P073_USE_74HC595 diff --git a/src/src/PluginStructs/P073_display_74HC595.cpp b/src/src/PluginStructs/P073_display_74HC595.cpp new file mode 100644 index 0000000000..6c179c8cea --- /dev/null +++ b/src/src/PluginStructs/P073_display_74HC595.cpp @@ -0,0 +1,131 @@ +#include "../PluginStructs/P073_data_struct.h" + +#ifdef USES_P073 +# if P073_USE_74HC595 +# include + +bool P073_data_struct::is74HC595Multiplex() { return P073_74HC595_2_8DGT == displayModel && P073_HC595_MULTIPLEX; } + +// ==================================== +// ---- 74HC595 specific functions ---- +// ==================================== + +void P073_data_struct::hc595_ShowBuffer() { + # if P073_USE_74HCMULTIPLEX + const uint8_t hc595digit4[] = { + 0b00001000, // left segment + 0b00000100, + 0b00000010, + 0b00000001, // right segment + }; + + const uint8_t hc595digit8[] = { + 0b00010000, // left segment + 0b00100000, + 0b01000000, + 0b10000000, + 0b00000001, + 0b00000010, + 0b00000100, + 0b00001000, // right segment + }; + # endif // if P073_USE_74HCMULTIPLEX + + int8_t i = digits - 1; + int8_t stop = -1; + int8_t incr = -1; + + # if P073_USE_74HCMULTIPLEX + + if (P073_HC595_MULTIPLEX) { + i = dspDgt; + stop = dspDgt + 1; + incr = 1; + } + # endif // if P073_USE_74HCMULTIPLEX + + for (; i != stop && i >= 0; i += incr) { + DIRECT_shiftOut(pin1, pin2, MSBFIRST, outputbuffer[i]); // Digit data out + + // 2, 3 and some 4 digit modules use sequential digit values (in reversed order) + // 4, 6 and 8 digit modules use multiplexing in LTR order + # if P073_USE_74HCMULTIPLEX + uint8_t digit = 0xFF; + + if (P073_HC595_MULTIPLEX) { + if (4 == digits) { + digit = hc595digit4[i]; + } else + if (6 == digits) { + digit = hc595digit8[i + (i > 2 ? 1 : 0)]; + } else + if (8 == digits) { + digit = hc595digit8[i]; + } + } + + if (digit != 0xFF) { // Select multiplexer digit, 0xFF is invalid + DIRECT_shiftOut(pin1, pin2, MSBFIRST, digit); + } + # endif // if P073_USE_74HCMULTIPLEX + + if ((P073_HC595_SEQUENTIAL && (0 == i)) || P073_HC595_MULTIPLEX) { + DIRECT_pinWrite(pin3, LOW); // Clock data + DIRECT_pinWrite(pin3, HIGH); + } + } + + if (i >= digits) { + dspDgt = 0; + } else { + dspDgt = i; + } + + # ifdef P073_DEBUG + + // TODO disable log + // if ((counter50 % 200 == 0) || P073_HC595_SEQUENTIAL) { + // addLog(LOG_LEVEL_INFO, strformat(F("P073: hc595_ShowBuffer (end) dgt:%d i:%d stop:%d incr:%d pin1: %d pin2: %d pin3: %d"), + // digits, i, stop, incr, pin1, pin2, pin3)); + // } + # endif // ifdef P073_DEBUG +} + +void P073_data_struct::hc595_ToOutputBuffer() { + for (uint8_t i = 0; i < 8; ++i) { + uint8_t value; + + // 74HC595 uses inverted data, compared to MAX7219/TM1637 + value = ~P073_getFontChar(showbuffer[i], fontset); + + if (showperiods[i]) { + value &= 0x7F; + } + outputbuffer[i] = P073_revert7bits(value); // Rotate bits 6..0 + } + + if (hc595_Sequential()) { // Sequential displays don't need continuous refreshing + hc595_ShowBuffer(); + } +} + +void P073_data_struct::hc595_ShiftinView() { + if (digits < 8) { + uint8_t n = 0; + + for (uint8_t i = 8 - digits; i < 8; ++i, ++n) { + showbuffer[n] = showbuffer[i]; + } + } +} + +void P073_data_struct::hc595_InitDisplay() { + pinMode(pin1, OUTPUT); // Use Arduino pin initialization as some ESPs don't properly set up their pins with DIRECT_GPIO_OUTPUT + pinMode(pin2, OUTPUT); + pinMode(pin3, OUTPUT); + DIRECT_pinWrite(pin3, HIGH); +} + +# endif // if P073_USE_74HC595 + +#endif // ifdef USES_P073 diff --git a/src/src/PluginStructs/P073_display_MAX7219.cpp b/src/src/PluginStructs/P073_display_MAX7219.cpp new file mode 100644 index 0000000000..e2d908ff2d --- /dev/null +++ b/src/src/PluginStructs/P073_display_MAX7219.cpp @@ -0,0 +1,129 @@ +#include "../PluginStructs/P073_data_struct.h" + +#ifdef USES_P073 +# include + +// ==================================== +// ---- MAX7219 specific functions ---- +// ==================================== + +# define OP_DECODEMODE 9 +# define OP_INTENSITY 10 +# define OP_SCANLIMIT 11 +# define OP_SHUTDOWN 12 +# define OP_DISPLAYTEST 15 + +void P073_data_struct::max7219_spiTransfer(ESPEASY_VOLATILE(uint8_t) opcode, + ESPEASY_VOLATILE(uint8_t) data) { + spidata[1] = opcode; + spidata[0] = data; + DIRECT_pinWrite(pin3, LOW); + DIRECT_shiftOut(pin1, pin2, MSBFIRST, spidata[1]); + DIRECT_shiftOut(pin1, pin2, MSBFIRST, spidata[0]); + DIRECT_pinWrite(pin3, HIGH); +} + +void P073_data_struct::max7219_ClearDisplay() { + for (int i = 0; i < 8; i++) { + max7219_spiTransfer(i + 1, 0); + } +} + +void P073_data_struct::max7219_SetPowerBrightness(uint8_t brightlvl, + bool poweron) { + max7219_spiTransfer(OP_INTENSITY, brightlvl); + max7219_spiTransfer(OP_SHUTDOWN, poweron ? 1 : 0); +} + +void P073_data_struct::max7219_SetDigit(int dgtpos, + uint8_t dgtvalue, + bool showdot, + bool binaryData) { + uint8_t p073_tempvalue; + + if (binaryData) { + p073_tempvalue = dgtvalue; // Overwrite if binary data + } else + { + p073_tempvalue = P073_getFontChar(dgtvalue, fontset); + + if (showdot) { + p073_tempvalue |= 0b10000000; + } + } + max7219_spiTransfer(dgtpos + 1, p073_tempvalue); +} + +void P073_data_struct::max7219_InitDisplay() { + pinMode(pin1, OUTPUT); // Use Arduino pin initialization as some ESPs don't properly set up their pins with DIRECT_GPIO_OUTPUT + pinMode(pin2, OUTPUT); + pinMode(pin3, OUTPUT); + DIRECT_pinWrite(pin3, HIGH); + max7219_spiTransfer(OP_DISPLAYTEST, 0); + max7219_spiTransfer(OP_SCANLIMIT, 7); // scanlimit setup to max at Init + max7219_spiTransfer(OP_DECODEMODE, 0); + max7219_ClearDisplay(); + max7219_SetPowerBrightness(0, false); +} + +void P073_data_struct::max7219_ShowTime(bool sep) { + const uint8_t idx_list[] = { 7, 6, 4, 3, 1, 0 }; // Digits in reversed order, as the loop is backward + + for (int8_t i = 5; i >= 0; --i) { + max7219_SetDigit(idx_list[i], showbuffer[i], false); + } + + const uint8_t sepChar = P073_mapCharToFontPosition(sep ? '-' : ' ', fontset); + + max7219_SetDigit(2, sepChar, false); + max7219_SetDigit(5, sepChar, false); +} + +void P073_data_struct::max7219_ShowTemp(int8_t firstDot, + int8_t secondDot) { + max7219_SetDigit(0, 10, false); + + if (firstDot > -1) { showperiods[firstDot] = true; } + + if (secondDot > -1) { showperiods[secondDot] = true; } + + const int alignRight = rightAlignTempMAX7219 ? 0 : 1; + + for (int i = alignRight; i < 8; ++i) { + const int bufIndex = (7 + alignRight) - i; + + if (bufIndex < 8) { + max7219_SetDigit(i, + showbuffer[bufIndex], + showperiods[bufIndex]); + } + } +} + +void P073_data_struct::max7219_ShowDate() { + const uint8_t dotflags[8] = { false, true, false, true, false, false, false, false }; + + for (int i = 0; i < 8; ++i) { + max7219_SetDigit(i, + showbuffer[7 - i], + dotflags[7 - i]); + } +} + +void P073_data_struct::max7219_ShowBuffer() { + if (dotpos > -1) { + showperiods[dotpos] = true; + } + + for (int i = 0; i < 8; i++) { + max7219_SetDigit(i, + showbuffer[7 - i], + showperiods[7 - i] + # if P073_7DBIN_COMMAND + , binaryData + # endif // if P073_7DBIN_COMMAND + ); + } +} + +#endif // ifdef USES_P073 diff --git a/src/src/PluginStructs/P073_display_TM1637.cpp b/src/src/PluginStructs/P073_display_TM1637.cpp new file mode 100644 index 0000000000..2c0995370e --- /dev/null +++ b/src/src/PluginStructs/P073_display_TM1637.cpp @@ -0,0 +1,260 @@ +#include "../PluginStructs/P073_data_struct.h" + +#ifdef USES_P073 +# include + +// =================================== +// ---- TM1637 specific functions ---- +// =================================== + +# define CLK_HIGH() DIRECT_pinWrite(this->pin1, HIGH) +# define CLK_LOW() DIRECT_pinWrite(this->pin1, LOW) +# define DIO_HIGH() DIRECT_pinWrite(this->pin2, HIGH) +# define DIO_LOW() DIRECT_PINMODE_OUTPUT(this->pin2); DIRECT_pinWrite(this->pin2, LOW) +# define DIO_INPUT() DIRECT_PINMODE_INPUT(this->pin2) +# define DIO_OUTPUT() DIRECT_PINMODE_OUTPUT(this->pin2) + +void P073_data_struct::tm1637_i2cStart() { + # if defined(P073_DEBUG) && !defined(BUILD_NO_DEBUG) + addLog(LOG_LEVEL_DEBUG, F("7DGT : Comm Start")); + # endif // if defined(P073_DEBUG) && !defined(BUILD_NO_DEBUG) + DIO_LOW(); + delayMicroseconds(TM1637_CLOCKDELAY); +} + +void P073_data_struct::tm1637_i2cStop() { + # if defined(P073_DEBUG) && !defined(BUILD_NO_DEBUG) + addLog(LOG_LEVEL_DEBUG, F("7DGT : Comm Stop")); + # endif // if defined(P073_DEBUG) && !defined(BUILD_NO_DEBUG) + DIO_LOW(); + delayMicroseconds(TM1637_CLOCKDELAY); + CLK_HIGH(); + delayMicroseconds(TM1637_CLOCKDELAY); + DIO_HIGH(); + delayMicroseconds(TM1637_CLOCKDELAY); +} + +bool P073_data_struct::tm1637_i2cAck() { + CLK_LOW(); + DIO_INPUT(); + + delayMicroseconds(TM1637_CLOCKDELAY); + CLK_HIGH(); + const uint32_t start_wait = micros(); + + const bool acknowledged = -1 != + DIRECT_measureWaitForPinState_ISR(this->pin2, start_wait, TM1637_CLOCKDELAY, 0); + + const int32_t timePassed = usecPassedSince_fast(start_wait); + + if (timePassed < TM1637_CLOCKDELAY) { + delayMicroseconds(TM1637_CLOCKDELAY - timePassed); + } + + # if defined(P073_DEBUG) && !defined(BUILD_NO_DEBUG) + + if (loglevelActiveFor(LOG_LEVEL_DEBUG)) { + String log = F("7DGT : Comm ACK="); + + if (acknowledged) { + log += F("TRUE"); + } else { + log += F("FALSE"); + } + addLogMove(LOG_LEVEL_DEBUG, log); + } + # endif // if defined(P073_DEBUG) && !defined(BUILD_NO_DEBUG) + CLK_HIGH(); + + delayMicroseconds(TM1637_CLOCKDELAY); + CLK_LOW(); + delayMicroseconds(TM1637_CLOCKDELAY); + DIO_OUTPUT(); + + return acknowledged; +} + +void P073_data_struct::tm1637_i2cWrite_ack(uint8_t bytesToPrint[], + uint8_t length) { + # ifdef P073_DEBUG + + if (loglevelActiveFor(LOG_LEVEL_INFO)) { + addLog(LOG_LEVEL_INFO, concat(F("7DGT : TM1637 databuffer: 0x"), formatToHex_array(bytesToPrint, length))); + } + # endif // ifdef P073_DEBUG + tm1637_i2cStart(); + + for (uint8_t i = 0; i < length; ++i) { + tm1637_i2cWriteByte_ack(bytesToPrint[i]); + } + tm1637_i2cStop(); +} + +void P073_data_struct::tm1637_i2cWriteByte_ack(uint8_t bytetoprint) { + tm1637_i2cWrite(bytetoprint); + tm1637_i2cAck(); +} + +void P073_data_struct::tm1637_i2cWrite(uint8_t bytetoprint) { + # if defined(P073_DEBUG) && !defined(BUILD_NO_DEBUG) + addLog(LOG_LEVEL_DEBUG, F("7DGT : WriteByte")); + # endif // if defined(P073_DEBUG) && !defined(BUILD_NO_DEBUG) + + for (uint8_t i = 0; i < 8; ++i) { + CLK_LOW(); + delayMicroseconds(TM1637_CLOCKDELAY >> 1); + + if (bytetoprint & 0b00000001) { + DIO_HIGH(); + } else { + DIO_LOW(); + } + delayMicroseconds(TM1637_CLOCKDELAY >> 1); + bytetoprint = bytetoprint >> 1; + CLK_HIGH(); + delayMicroseconds(TM1637_CLOCKDELAY); + } +} + +void P073_data_struct::tm1637_ClearDisplay() { + uint8_t bytesToPrint[7]{}; + + bytesToPrint[0] = 0xC0; + tm1637_i2cWrite_ack(bytesToPrint, 7); +} + +void P073_data_struct::tm1637_SetPowerBrightness(uint8_t brightlvl, + bool poweron) { + # ifdef P073_DEBUG + addLog(LOG_LEVEL_INFO, F("7DGT : Set BRIGHT")); + # endif // ifdef P073_DEBUG + brightlvl &= 0b111; + + if (poweron) { + brightlvl |= TM1637_POWER_ON; + } else { + brightlvl |= TM1637_POWER_OFF; + } + + uint8_t bytesToPrint[]{ brightlvl }; + tm1637_i2cWrite_ack(bytesToPrint, NR_ELEMENTS(bytesToPrint)); +} + +void P073_data_struct::tm1637_InitDisplay() { + pinMode(this->pin1, OUTPUT); // Use Arduino pin initialization as some ESPs don't properly set up their pins with DIRECT_GPIO_OUTPUT + pinMode(this->pin2, OUTPUT); + + DIRECT_pinWrite(this->pin1, HIGH); + DIRECT_pinWrite(this->pin2, HIGH); + + delayMicroseconds(TM1637_CLOCKDELAY); + uint8_t bytesToPrint[]{ 0x40 }; + tm1637_i2cWrite_ack(bytesToPrint, NR_ELEMENTS(bytesToPrint)); + tm1637_ClearDisplay(); +} + +uint8_t P073_data_struct::tm1637_separator(uint8_t value, + bool sep) { + if (sep) { + value |= 0b10000000; + } + return value; +} + +void P073_data_struct::tm1637_ShowTime6() { + tm1637_ShowDate6(true); // deduplicated +} + +void P073_data_struct::tm1637_ShowDate6(bool showTime) { + uint8_t bytesToPrint[7]{}; + + bytesToPrint[0] = 0xC0; + bytesToPrint[1] = tm1637_getFontChar(showbuffer[2], fontset); + bytesToPrint[2] = tm1637_separator(tm1637_getFontChar(showbuffer[1], fontset), timesep); + bytesToPrint[3] = tm1637_getFontChar(showbuffer[0], fontset); + + if (showTime) { + bytesToPrint[4] = tm1637_getFontChar(showbuffer[5], fontset); + bytesToPrint[5] = tm1637_getFontChar(showbuffer[4], fontset); + } else { + bytesToPrint[4] = tm1637_getFontChar(showbuffer[7], fontset); + bytesToPrint[5] = tm1637_getFontChar(showbuffer[6], fontset); + } + bytesToPrint[6] = tm1637_separator(tm1637_getFontChar(showbuffer[3], fontset), timesep); + + tm1637_i2cWrite_ack(bytesToPrint, 7); +} + +void P073_data_struct::tm1637_ShowTemp6(bool sep) { + uint8_t bytesToPrint[7]{}; + + bytesToPrint[0] = 0xC0; + bytesToPrint[1] = tm1637_separator(tm1637_getFontChar(showbuffer[5], fontset), sep); + bytesToPrint[2] = tm1637_getFontChar(showbuffer[4], fontset); + bytesToPrint[3] = tm1637_getFontChar(showbuffer[3], fontset); // Fill first digit of display too + bytesToPrint[4] = tm1637_getFontChar(10, fontset); + bytesToPrint[5] = tm1637_getFontChar(showbuffer[7], fontset); + bytesToPrint[6] = tm1637_getFontChar(showbuffer[6], fontset); + + tm1637_i2cWrite_ack(bytesToPrint, 7); +} + +void P073_data_struct::tm1637_ShowTimeTemp4(bool sep, + uint8_t bufoffset) { + uint8_t bytesToPrint[5]{}; + + bytesToPrint[0] = 0xC0; + bytesToPrint[1] = tm1637_getFontChar(showbuffer[0 + bufoffset], fontset); + bytesToPrint[2] = tm1637_separator(tm1637_getFontChar(showbuffer[1 + bufoffset], fontset), sep); + bytesToPrint[3] = tm1637_getFontChar(showbuffer[2 + bufoffset], fontset); + bytesToPrint[4] = tm1637_getFontChar(showbuffer[3 + bufoffset], fontset); + + tm1637_i2cWrite_ack(bytesToPrint, 5); +} + +void P073_data_struct::tm1637_SwapDigitInBuffer(uint8_t startPos) { + std::swap(showbuffer[2 + startPos], showbuffer[0 + startPos]); + std::swap(showbuffer[3 + startPos], showbuffer[5 + startPos]); + + std::swap(showperiods[2 + startPos], showperiods[0 + startPos]); + std::swap(showperiods[3 + startPos], showperiods[5 + startPos]); + + if (dotpos > -1) { + const uint8_t dotPositionSwap[] = { 0, 1, 4, 3, 2, 7, 6, 5, 8 }; + + dotpos = dotPositionSwap[dotpos]; + } +} + +void P073_data_struct::tm1637_ShowBuffer(uint8_t firstPos, + uint8_t lastPos, + bool useBinaryData) { + uint8_t bytesToPrint[8]{}; + + bytesToPrint[0] = 0xC0; + uint8_t length = 1; + + if (dotpos > -1) { + showperiods[dotpos] = true; + } + + uint8_t p073_datashowpos1; + + for (int i = firstPos; i < lastPos; ++i) { + if (useBinaryData) { + bytesToPrint[length] = showbuffer[i]; + } else { + p073_datashowpos1 = tm1637_separator( + tm1637_getFontChar(showbuffer[i], fontset), + showperiods[i]); + bytesToPrint[length] = p073_datashowpos1; + } + length++; + } + # ifdef P073_DEBUG + addLog(LOG_LEVEL_INFO, strformat(F("TM1673: Write bytes: %d buffer %d to %d"), length, firstPos, lastPos)); + # endif // ifdef P073_DEBUG + tm1637_i2cWrite_ack(bytesToPrint, length); +} + +#endif // ifdef USES_P073 From 21d28a06e754c0601636942d2046ca94989d734f Mon Sep 17 00:00:00 2001 From: Ton Huisman Date: Fri, 7 Aug 2026 15:45:55 +0200 Subject: [PATCH 5/5] [P073] Refactor in separate structs (classes) for code deduplication --- src/_P073_7DGT.ino | 30 +- src/src/PluginStructs/P073_data_struct.cpp | 326 +++--------------- src/src/PluginStructs/P073_data_struct.h | 197 +++++++---- .../PluginStructs/P073_display_74HC595.cpp | 82 ++++- .../PluginStructs/P073_display_MAX7219.cpp | 132 ++++--- src/src/PluginStructs/P073_display_TM1637.cpp | 136 ++++++-- 6 files changed, 448 insertions(+), 455 deletions(-) diff --git a/src/_P073_7DGT.ino b/src/_P073_7DGT.ino index 1d71d4b327..f567f5a47f 100644 --- a/src/_P073_7DGT.ino +++ b/src/_P073_7DGT.ino @@ -42,6 +42,7 @@ // /** History + * 2026-08-06 tonhuisman: Move display specific code in separate derived structs from P073_data_struct, and deduplicate code where possible * 2026-07-27 tonhuisman: Restructure plugin_struct source into separate files per supported display model for maintainability * Some minor code optimization for 74HC595 displays * 2026-07-25 tonhuisman: Use Arduino pin initialization as some ESPs don't properly set up their pins with DIRECT_GPIO_OUTPUT @@ -314,21 +315,28 @@ boolean Plugin_073(uint8_t function, struct EventStruct *event, String& string) case PLUGIN_INIT: { - initPluginTaskData(event->TaskIndex, new (std::nothrow) P073_data_struct()); - P073_data_struct *P073_data = - static_cast(getPluginTaskData(event->TaskIndex)); - - if (nullptr != P073_data) { - P073_data->init(event); + P073_data_struct *P073_data = nullptr; + switch (P073_CFG_DISPLAYTYPE) + { + case P073_TM1637_4DGTCOLON: + case P073_TM1637_4DGTDOTS: + case P073_TM1637_6DGT: + P073_data = new (std::nothrow) P073_TM1637(event); + break; + case P073_MAX7219_8DGT: + P073_data = new (std::nothrow) P073_MAX7219(event); + break; # if P073_USE_74HC595 - - if (P073_data->is74HC595Multiplex()) { - Scheduler.setPluginTaskTimer(10, event->TaskIndex, 0); - } + case P073_74HC595_2_8DGT: + P073_data = new (std::nothrow) P073_74HC595(event); + break; # endif // if P073_USE_74HC595 + } - success = true; + if (nullptr != P073_data) { + initPluginTaskData(event->TaskIndex, P073_data); + success = P073_data->init(event); } break; } diff --git a/src/src/PluginStructs/P073_data_struct.cpp b/src/src/PluginStructs/P073_data_struct.cpp index 7ca97ac19a..a78e77b14c 100644 --- a/src/src/PluginStructs/P073_data_struct.cpp +++ b/src/src/PluginStructs/P073_data_struct.cpp @@ -197,7 +197,7 @@ uint8_t P073_revert7bits(uint8_t character) { return b | dpBit; // Restore dot-bit } -void P073_data_struct::init(struct EventStruct *event) +P073_data_struct::P073_data_struct(struct EventStruct *event) { ClearBuffer(); pin1 = CONFIG_PIN1; @@ -223,29 +223,10 @@ void P073_data_struct::init(struct EventStruct *event) fontset = P073_CFG_FONTSET; # endif // if P073_EXTRA_FONTS digits = P073_CFG_DIGITS; - # if P073_USE_74HC595 - if ((digits > 0) && ((digits < 4) || (5 == digits) || (7 == digits) || (9 == digits) || (10 == digits) || (11 == digits))) { - isSequential = true; - - if (1 == digits) { // 2+2 - digits = 4; - } else - if (9 == digits) { // 4 sequential - digits = 4; - } else - if (10 == digits) { // 4+4 sequential - digits = 8; - } else - if (7 == digits) { // 3+3 - digits = 6; - } else - if (11 == digits) { // 3+4/4+3 sequential - digits = 7; - } - } - # endif // if P073_USE_74HC595 +} +bool P073_data_struct::init(struct EventStruct *event) { if (0 == digits) { digits = P073_getDefaultDigits(P073_CFG_DISPLAYTYPE); } @@ -255,41 +236,10 @@ void P073_data_struct::init(struct EventStruct *event) } if (loglevelActiveFor(LOG_LEVEL_INFO)) { - addLog(LOG_LEVEL_INFO, strformat(F("P073 : Digits: %d, model: %d, pins: %d, %d, %d"), digits, displayModel, pin1, pin2, pin3)); - } - - switch (displayModel) - { - case P073_TM1637_4DGTCOLON: - case P073_TM1637_4DGTDOTS: - case P073_TM1637_6DGT: - tm1637_InitDisplay(); - tm1637_SetPowerBrightness(brightness / 2, true); - - if (output == P073_DISP_MANUAL) { - tm1637_ClearDisplay(); - } - break; - case P073_MAX7219_8DGT: - max7219_InitDisplay(); - delay(10); // small poweroff/poweron delay - max7219_SetPowerBrightness(brightness, true); - - if (output == P073_DISP_MANUAL) { - max7219_ClearDisplay(); - } - break; - # if P073_USE_74HC595 - case P073_74HC595_2_8DGT: - hc595_InitDisplay(); - - if (output == P073_DISP_MANUAL) { - ClearBuffer(); - hc595_ToOutputBuffer(); - } - break; - # endif // if P073_USE_74HC595 + addLog(LOG_LEVEL_INFO, strformat(F("P073 : Digits: %d, model: %d, output: %d, pins: %d, %d, %d"), + digits, displayModel, output, pin1, pin2, pin3)); } + return true; } void P073_data_struct::FillBufferWithTime(bool sevendgt_now, @@ -378,13 +328,11 @@ void P073_data_struct::FillBufferWithNumber(const String& number) { } int8_t p073_index = 7; - dotpos = -1; // -1 means no dot to display - for (int i = number.length() - 1; i >= 0 && p073_index >= 0; --i) { const char p073_tmpchar = number.charAt(i); if (p073_tmpchar == '.') { // dot - dotpos = p073_index; + showperiods[p073_index] = true; } else { showbuffer[p073_index] = P073_mapCharToFontPosition(p073_tmpchar, fontset); p073_index--; @@ -421,7 +369,7 @@ void P073_data_struct::FillBufferWithTemp(int temperature) { /** * FillBufferWithDualTemp() - * leftTemperature or rightTempareature < -100.0 then shows dashes + * leftTemperature or rightTemperature < -100.0 then shows dashes */ void P073_data_struct::FillBufferWithDualTemp(int leftTemperature, bool leftWithDecimal, @@ -497,7 +445,6 @@ void P073_data_struct::FillBufferWithString(const String& textToShow, showperiods[p] = true; p++; } else { - // if (p > 0) { showperiods[p - 1] = true; // The period displays as a dot on the previous digit! } @@ -697,10 +644,7 @@ void P073_data_struct::ClearBuffer() { } } -uint8_t P073_data_struct::tm1637_getFontChar(uint8_t index, - uint8_t fontset) { return P073_revert7bits(P073_getFontChar(index, fontset)); } - -bool P073_data_struct::plugin_once_a_second(struct EventStruct *event) { +bool P073_data_struct::plugin_once_a_second(struct EventStruct *event) { if (output == P073_DISP_MANUAL) { return false; } @@ -740,33 +684,13 @@ bool P073_data_struct::plugin_once_a_second(struct EventStruct *event) { } # endif // if P073_BLINK_DOT - switch (displayModel) - { - case P073_TM1637_4DGTCOLON: - case P073_TM1637_4DGTDOTS: - tm1637_ShowTimeTemp4(timesep, 0); - break; - case P073_TM1637_6DGT: - - if (P073_CFG_OUTPUTTYPE == P073_DISP_DATE) { - tm1637_ShowDate6(); - } else { - tm1637_ShowTime6(); - } - break; - case P073_MAX7219_8DGT: + if (P073_CFG_OUTPUTTYPE == P073_DISP_DATE) { + showDate(); + } else { + showperiods[1] = timesep; - if (P073_CFG_OUTPUTTYPE == P073_DISP_DATE) { - max7219_ShowDate(); - } else { - max7219_ShowTime(timesep); - } - break; - # if P073_USE_74HC595 - case P073_74HC595_2_8DGT: - hc595_ToOutputBuffer(); - break; - # endif // if P073_USE_74HC595 + if (digits > 4) { showperiods[3] = timesep; } + showTime(timesep); } return true; } @@ -779,42 +703,7 @@ bool P073_data_struct::plugin_ten_per_second(struct EventStruct *event) { } if (NextScroll()) { - switch (displayModel) - { - case P073_TM1637_4DGTCOLON: - case P073_TM1637_4DGTDOTS: - { - tm1637_ShowBuffer(0, 4 - # if P073_7DBIN_COMMAND - , binaryData - # endif // if P073_7DBIN_COMMAND - ); - break; - } - case P073_TM1637_6DGT: - { - tm1637_SwapDigitInBuffer(0); // only needed for 6-digits displays - tm1637_ShowBuffer(0, 6 - # if P073_7DBIN_COMMAND - , binaryData - # endif // if P073_7DBIN_COMMAND - ); - break; - } - case P073_MAX7219_8DGT: - { - dotpos = -1; // avoid to display the dot - max7219_ShowBuffer(); - break; - } - # if P073_USE_74HC595 - case P073_74HC595_2_8DGT: - { - hc595_ToOutputBuffer(); - break; - } - # endif // if P073_USE_74HC595 - } + toOutputBuffer(); } return true; } @@ -829,7 +718,7 @@ bool P073_data_struct::plugin_fifty_per_second(struct EventStruct *event) { # endif // ifdef P073_DEBUG if (is74HC595Multiplex()) { - hc595_ShowBuffer(); + showBuffer(); // Redisplay current buffer content return true; } return false; @@ -996,22 +885,7 @@ bool P073_data_struct::plugin_write(struct EventStruct *event, setScrollEnabled(newScroll); # endif // if P073_SCROLL_TEXT - switch (displayModel) - { - case P073_TM1637_4DGTCOLON: - case P073_TM1637_4DGTDOTS: - case P073_TM1637_6DGT: - tm1637_SetPowerBrightness(brightness / 2, displayon); - break; - case P073_MAX7219_8DGT: - max7219_SetPowerBrightness(brightness, displayon); - break; - # if P073_USE_74HC595 - case P073_74HC595_2_8DGT: - // 74HC595 don't have a brightness setting - break; - # endif // if P073_USE_74HC595 - } + setPowerBrightness(brightness, displayon); } return success; } @@ -1054,32 +928,13 @@ bool P073_data_struct::plugin_write_7dn(struct EventStruct *event, if (!text.isEmpty()) { if ((event->Par1 > lLimit) && (event->Par1 < uLimit)) { - FillBufferWithNumber(text.c_str()); + FillBufferWithNumber(text); } else { FillBufferWithDash(); } } - switch (displayModel) - { - case P073_TM1637_4DGTCOLON: - case P073_TM1637_4DGTDOTS: - tm1637_ShowBuffer(TM1637_4DIGIT, 8); - break; - case P073_TM1637_6DGT: - tm1637_SwapDigitInBuffer(2); // only needed for 6-digits displays - tm1637_ShowBuffer(TM1637_6DIGIT, 8); - break; - case P073_MAX7219_8DGT: - max7219_ShowBuffer(); - break; - # if P073_USE_74HC595 - case P073_74HC595_2_8DGT: - hc595_ShiftinView(); - hc595_ToOutputBuffer(); - break; - # endif // if P073_USE_74HC595 - } + showNumber(); return true; } @@ -1088,8 +943,8 @@ bool P073_data_struct::plugin_write_7dt(const String& text) { return false; } - float p073_temptemp = 0; - bool p073_tempflagdot = false; + float p073_temptemp{}; + int8_t p073_tempflagdot = -1; if (!text.isEmpty()) { validFloatFromString(text, p073_temptemp); @@ -1119,41 +974,37 @@ bool P073_data_struct::plugin_write_7dt(const String& text) { } else { if ((p073_temptemp < uLimitDec) && (p073_temptemp > lLimitDec)) { p073_temptemp = roundf(p073_temptemp * 10.0f); - p073_tempflagdot = true; + p073_tempflagdot = digits - (hideDegree ? 2 : 3); } FillBufferWithTemp(p073_temptemp); } + # ifdef P073_DEBUG + + if (loglevelActiveFor(LOG_LEVEL_INFO)) { + addLogMove(LOG_LEVEL_INFO, strformat(F("7DGT : 7dt preprocessed = %.1f dec: %d"), p073_temptemp, p073_tempflagdot)); + } + # endif // ifdef P073_DEBUG + switch (displayModel) { case P073_TM1637_4DGTCOLON: case P073_TM1637_4DGTDOTS: case P073_TM1637_6DGT: - if ((p073_temptemp == 0) && p073_tempflagdot) { + if (essentiallyZero(p073_temptemp) && (p073_tempflagdot > -1)) { // FIXME showbuffer[5] = 0; } - if (P073_TM1637_6DGT == displayModel) { - tm1637_ShowTemp6(p073_tempflagdot); - } else { - tm1637_ShowTimeTemp4(p073_tempflagdot, 4); - } + showTemperature(p073_tempflagdot, -1); + break; case P073_MAX7219_8DGT: - # ifdef P073_DEBUG - - if (loglevelActiveFor(LOG_LEVEL_INFO)) { - addLogMove(LOG_LEVEL_INFO, concat(F("7DGT : 7dt preprocessed ="), p073_temptemp)); - } - # endif // ifdef P073_DEBUG - - max7219_ShowTemp(hideDegree ? 6 : 5, -1); + showTemperature(hideDegree ? 6 : 5, -1); break; # if P073_USE_74HC595 case P073_74HC595_2_8DGT: - hc595_ShiftinView(); - hc595_ToOutputBuffer(); + showTemperature(p073_tempflagdot, -1); break; # endif // if P073_USE_74HC595 } @@ -1170,9 +1021,8 @@ bool P073_data_struct::plugin_write_7ddt(const String& text) { return false; } - float p073_lefttemp = 0.0f; - float p073_righttemp = 0.0f; - bool p073_tempflagdot = false; + float p073_lefttemp = 0.0f; + float p073_righttemp = 0.0f; if (!text.isEmpty()) { validFloatFromString(parseString(text, 1), p073_lefttemp); @@ -1197,11 +1047,7 @@ bool P073_data_struct::plugin_write_7ddt(const String& text) { { FillBufferWithDash(); - if (displayModel == P073_TM1637_6DGT) { - tm1637_ShowTemp6(p073_tempflagdot); - } else { - tm1637_ShowTimeTemp4(p073_tempflagdot, 4); - } + showTemperature(-1, -1); break; } case P073_MAX7219_8DGT: @@ -1242,7 +1088,7 @@ bool P073_data_struct::plugin_write_7ddt(const String& text) { bool alignSave = rightAlignTempMAX7219; // Save setting rightAlignTempMAX7219 = true; - max7219_ShowTemp(firstDot, secondDot); + showTemperature(firstDot, secondDot); rightAlignTempMAX7219 = alignSave; // Restore # if P073_USE_74HC595 @@ -1252,7 +1098,8 @@ bool P073_data_struct::plugin_write_7ddt(const String& text) { if (digits < 8) { FillBufferWithDash(); } - hc595_ToOutputBuffer(); + + toOutputBuffer(); # endif // if P073_USE_74HC595 } @@ -1287,24 +1134,7 @@ bool P073_data_struct::plugin_write_7dst(struct EventStruct *event) { # endif // if P073_SUPPRESS_ZERO ); - switch (displayModel) - { - case P073_TM1637_4DGTCOLON: - case P073_TM1637_4DGTDOTS: - tm1637_ShowTimeTemp4(timesep, 0); - break; - case P073_TM1637_6DGT: - tm1637_ShowTime6(); - break; - case P073_MAX7219_8DGT: - max7219_ShowTime(timesep); - break; - # if P073_USE_74HC595 - case P073_74HC595_2_8DGT: - hc595_ToOutputBuffer(); - break; - # endif // if P073_USE_74HC595 - } + showTime(timesep); return true; } @@ -1327,24 +1157,7 @@ bool P073_data_struct::plugin_write_7dsd(struct EventStruct *event) { # endif // if P073_SUPPRESS_ZERO ); - switch (displayModel) - { - case P073_TM1637_4DGTCOLON: - case P073_TM1637_4DGTDOTS: - tm1637_ShowTimeTemp4(timesep, 0); - break; - case P073_TM1637_6DGT: - tm1637_ShowDate6(); - break; - case P073_MAX7219_8DGT: - max7219_ShowDate(); - break; - # if P073_USE_74HC595 - case P073_74HC595_2_8DGT: - hc595_ToOutputBuffer(); - break; - # endif // if P073_USE_74HC595 - } + showDate(); return true; } @@ -1370,26 +1183,7 @@ bool P073_data_struct::plugin_write_7dtext(const String& text) { { FillBufferWithString(text); - switch (displayModel) - { - case P073_TM1637_4DGTCOLON: - case P073_TM1637_4DGTDOTS: - tm1637_ShowBuffer(0, 4); - break; - case P073_TM1637_6DGT: - tm1637_SwapDigitInBuffer(0); // only needed for 6-digits displays - tm1637_ShowBuffer(0, 6); - break; - case P073_MAX7219_8DGT: - dotpos = -1; // avoid to display the dot - max7219_ShowBuffer(); - break; - # if P073_USE_74HC595 - case P073_74HC595_2_8DGT: - hc595_ToOutputBuffer(); - break; - # endif // if P073_USE_74HC595 - } + toOutputBuffer(); } return true; } @@ -1451,26 +1245,7 @@ bool P073_data_struct::plugin_write_7dbin(const String& text) { { FillBufferWithString(data, true); - switch (displayModel) - { - case P073_TM1637_4DGTCOLON: - case P073_TM1637_4DGTDOTS: - tm1637_ShowBuffer(0, 4); - break; - case P073_TM1637_6DGT: - tm1637_SwapDigitInBuffer(0); // only needed for 6-digits displays - tm1637_ShowBuffer(0, 6, true); - break; - case P073_MAX7219_8DGT: - dotpos = -1; // avoid to display the dot - max7219_ShowBuffer(); - break; - # if P073_USE_74HC595 - case P073_74HC595_2_8DGT: - hc595_ToOutputBuffer(); - break; - # endif // if P073_USE_74HC595 - } + toOutputBuffer(); } return true; } @@ -1497,4 +1272,15 @@ void P073_data_struct::DIRECT_shiftOut(uint8_t dataPin, } } +void P073_data_struct::shiftinView() { + if (digits < 8) { + uint8_t n = 0; + + for (uint8_t i = 8 - digits; i < 8; ++i, ++n) { + showbuffer[n] = showbuffer[i]; + showperiods[n] = showperiods[i]; + } + } +} + #endif // ifdef USES_P073 diff --git a/src/src/PluginStructs/P073_data_struct.h b/src/src/PluginStructs/P073_data_struct.h index c41e863af9..1303e6cfaf 100644 --- a/src/src/PluginStructs/P073_data_struct.h +++ b/src/src/PluginStructs/P073_data_struct.h @@ -225,15 +225,16 @@ uint8_t P073_revert7bits(uint8_t character); struct P073_data_struct : public PluginTaskData_base { public: - P073_data_struct() = default; + P073_data_struct() = delete; + P073_data_struct(struct EventStruct *event); virtual ~P073_data_struct() = default; - void init(struct EventStruct *event); - bool plugin_write(struct EventStruct *event, - const String & string); - bool plugin_once_a_second(struct EventStruct *event); + virtual bool init(struct EventStruct *event); + bool plugin_write(struct EventStruct *event, + const String & string); + bool plugin_once_a_second(struct EventStruct *event); # if P073_SCROLL_TEXT - bool plugin_ten_per_second(struct EventStruct *event); + bool plugin_ten_per_second(struct EventStruct *event); # endif // if P073_SCROLL_TEXT # if P073_USE_74HC595 @@ -268,32 +269,46 @@ struct P073_data_struct : public PluginTaskData_base { int rightTemperature, bool rightWithDecimal); # endif // if P073_7DDT_COMMAND - void FillBufferWithString(const String& textToShow, - bool useBinaryData = false); + void FillBufferWithString(const String& textToShow, + bool useBinaryData = false); # if P073_SCROLL_TEXT - int getEffectiveTextLength(const String& text); - bool NextScroll(); - void setTextToScroll(const String& text); - void setScrollSpeed(uint8_t speed); - bool isScrollEnabled(); - void setScrollEnabled(bool scroll); + int getEffectiveTextLength(const String& text); + bool NextScroll(); + void setTextToScroll(const String& text); + void setScrollSpeed(uint8_t speed); + bool isScrollEnabled(); + void setScrollEnabled(bool scroll); # endif // if P073_SCROLL_TEXT # if P073_7DBIN_COMMAND - void setBinaryData(const String& data); + void setBinaryData(const String& data); # endif // if P073_7DBIN_COMMAND # ifdef P073_DEBUG - void LogBufferContent(String prefix); + void LogBufferContent(String prefix); # endif // ifdef P073_DEBUG - void FillBufferWithDash(); - void ClearBuffer(); + void FillBufferWithDash(); + void ClearBuffer(); - uint8_t tm1637_getFontChar(uint8_t index, - uint8_t fontset); + // To implement in derived structs + virtual void setPowerBrightness(uint8_t brightlvl, + bool poweron) {} + + virtual void showTime(bool sep) {} + + virtual void showDate() {} + + virtual void showNumber() {} + + virtual void showTemperature(int8_t firstDot, + int8_t secondDot) {} + + virtual void toOutputBuffer() {} + + virtual void showBuffer() {} + +protected: - int dotpos = -1; uint8_t showbuffer[8]{}; bool showperiods[8]{}; - uint8_t spidata[2]{}; uint8_t pin1 = 0xFF; uint8_t pin2 = 0xFF; uint8_t pin3 = 0xFF; @@ -320,24 +335,18 @@ struct P073_data_struct : public PluginTaskData_base { uint16_t scrollCount = 0; uint16_t scrollPos = 0; bool scrollFull = false; - -private: - - uint16_t _scrollSpeed = 0; + uint16_t _scrollSpeed = 0; # endif // P073_SCROLL_TEXT # if defined(P073_SCROLL_TEXT) || defined(P073_7DBIN_COMMAND) String _textToScroll; # endif // if defined(P073_SCROLL_TEXT) || defined(P073_7DBIN_COMMAND) - # ifdef P073_DEBUG + # if defined(P073_DEBUG) && P073_USE_74HC595 uint32_t counter50 = 0; - # endif // ifdef P073_DEBUG + # endif // if defined(P073_DEBUG) && P073_USE_74HC595 # if P073_USE_74HC595 - int8_t dspDgt = 0; - bool isSequential = false; + bool isSequential = false; # endif // if P073_USE_74HC595 -private: - void getDisplayLimits(int32_t& lLimit, int32_t& uLimit, int8_t offset = 0, @@ -359,7 +368,36 @@ struct P073_data_struct : public PluginTaskData_base { bool plugin_write_7dbin(const String& text); # endif // if P073_7DBIN_COMMAND - // ---- TM1637 specific functions ---- + void DIRECT_shiftOut(uint8_t dataPin, + uint8_t clockPin, + uint8_t bitOrder, + uint8_t val); + void shiftinView(); + +}; + +struct P073_TM1637 : public P073_data_struct +{ +public: + + P073_TM1637(struct EventStruct *event); + virtual ~P073_TM1637() {} + + virtual bool init(struct EventStruct *event) override; + virtual void setPowerBrightness(uint8_t brightlvl, + bool poweron) override; + virtual void showTime(bool sep) override; + virtual void showDate() override; + virtual void showNumber() override; + virtual void showTemperature(int8_t firstDot, + int8_t secondDot) override; + virtual void toOutputBuffer() override; + virtual void showBuffer() override; + +private: + + void initDisplay(); + void clearDisplay(); void tm1637_i2cStart(); void tm1637_i2cStop(); bool tm1637_i2cAck(); @@ -367,13 +405,10 @@ struct P073_data_struct : public PluginTaskData_base { uint8_t length); void tm1637_i2cWriteByte_ack(uint8_t bytetoprint); void tm1637_i2cWrite(uint8_t bytetoprint); - void tm1637_ClearDisplay(); - void tm1637_SetPowerBrightness(uint8_t brightlvl, - bool poweron); - void tm1637_InitDisplay(); + uint8_t tm1637_getFontChar(uint8_t index, + uint8_t fontset); uint8_t tm1637_separator(uint8_t value, bool sep); - void tm1637_ShowTime6(); void tm1637_ShowDate6(bool showTime = false); void tm1637_ShowTemp6(bool sep); void tm1637_ShowTimeTemp4(bool sep, @@ -383,38 +418,72 @@ struct P073_data_struct : public PluginTaskData_base { uint8_t lastPos, bool useBinaryData = false); - // ---- MAX7219 specific functions ---- +}; // struct P073_74HC595 + +struct P073_MAX7219 : public P073_data_struct +{ +public: + + P073_MAX7219(struct EventStruct *event); + virtual ~P073_MAX7219() {} + + virtual bool init(struct EventStruct *event) override; + virtual void setPowerBrightness(uint8_t brightlvl, + bool poweron) override; + virtual void showTime(bool sep) override; + virtual void showDate() override; + virtual void showNumber() override; + virtual void showTemperature(int8_t firstDot, + int8_t secondDot) override; + virtual void toOutputBuffer() override; + virtual void showBuffer() override; + +private: + + void initDisplay(); + void clearDisplay(); + void setDigit(int dgtpos, + uint8_t dgtvalue, + bool showdot, + bool binaryData = false); + void max7219_ShowTime(bool sep); + void max7219_ShowTemp(int8_t firstDot, + int8_t secondDot); + void max7219_ShowDate(); void max7219_spiTransfer(ESPEASY_VOLATILE(uint8_t) opcode, ESPEASY_VOLATILE(uint8_t) data); - void max7219_ClearDisplay(); - void max7219_SetPowerBrightness(uint8_t brightlvl, - bool poweron); - void max7219_SetDigit(int dgtpos, - uint8_t dgtvalue, - bool showdot, - bool binaryData = false); - void max7219_InitDisplay(); - void max7219_ShowTime(bool sep); - void max7219_ShowTemp(int8_t firstDot, - int8_t secondDot); - void max7219_ShowDate(); - void max7219_ShowBuffer(); - # if P073_USE_74HC595 - void hc595_InitDisplay(); - void hc595_ShowBuffer(); - void hc595_ShiftinView(); - void hc595_ToOutputBuffer(); - inline bool hc595_Sequential() { return P073_HC595_SEQUENTIAL; } + uint8_t spidata[2]{}; + uint8_t digitOffset = 0; + +}; // struct P073_MAX7219 +# if P073_USE_74HC595 +struct P073_74HC595 : public P073_data_struct +{ +public: + + P073_74HC595(struct EventStruct *event); + virtual ~P073_74HC595() {} + + virtual bool init(struct EventStruct *event) override; + virtual void showTime(bool sep) override; + virtual void showDate() override; + virtual void showNumber() override; + virtual void showTemperature(int8_t firstDot, + int8_t secondDot) override; + virtual void toOutputBuffer() override; + virtual void showBuffer() override; + +private: + + void initDisplay(); + + int8_t dspDgt = 0; uint8_t outputbuffer[8]{}; - # endif // if P073_USE_74HC595 - void DIRECT_shiftOut(uint8_t dataPin, - uint8_t clockPin, - uint8_t bitOrder, - uint8_t val); -}; +}; // struct P073_74HC595 +# endif // if P073_USE_74HC595 #endif // ifdef USES_P073 #endif // ifndef PLUGINSTRUCTS_P073_DATA_STRUCT_H diff --git a/src/src/PluginStructs/P073_display_74HC595.cpp b/src/src/PluginStructs/P073_display_74HC595.cpp index 6c179c8cea..ed029b1235 100644 --- a/src/src/PluginStructs/P073_display_74HC595.cpp +++ b/src/src/PluginStructs/P073_display_74HC595.cpp @@ -4,13 +4,73 @@ # if P073_USE_74HC595 # include +P073_74HC595::P073_74HC595(struct EventStruct *event) : P073_data_struct(event) { + + if ((digits > 0) && ((digits < 4) || (5 == digits) || (7 == digits) || (9 == digits) || (10 == digits) || (11 == digits))) { + isSequential = true; + + if (1 == digits) { // 2+2 + digits = 4; + } else + if (9 == digits) { // 4 sequential + digits = 4; + } else + if (10 == digits) { // 4+4 sequential + digits = 8; + } else + if (7 == digits) { // 3+3 + digits = 6; + } else + if (11 == digits) { // 3+4/4+3 sequential + digits = 7; + } + } +} + +bool P073_74HC595::init(struct EventStruct *event) { + if (P073_data_struct::init(event)) { + initDisplay(); + + if (output == P073_DISP_MANUAL) { + ClearBuffer(); + toOutputBuffer(); + } + + if (is74HC595Multiplex()) { + Scheduler.setPluginTaskTimer(10, event->TaskIndex, 0); + } + return true; + } + return false; +} + +void P073_74HC595::showTime(bool sep) { toOutputBuffer(); } + +void P073_74HC595::showDate() { toOutputBuffer(); } + +void P073_74HC595::showNumber() { + shiftinView(); + toOutputBuffer(); +} + +void P073_74HC595::showTemperature(int8_t firstDot, + int8_t secondDot) { + shiftinView(); + + if (firstDot > -1) { showperiods[firstDot] = true; } + + if (secondDot > -1) { showperiods[secondDot] = true; } + + toOutputBuffer(); +} + bool P073_data_struct::is74HC595Multiplex() { return P073_74HC595_2_8DGT == displayModel && P073_HC595_MULTIPLEX; } // ==================================== // ---- 74HC595 specific functions ---- // ==================================== -void P073_data_struct::hc595_ShowBuffer() { +void P073_74HC595::showBuffer() { # if P073_USE_74HCMULTIPLEX const uint8_t hc595digit4[] = { 0b00001000, // left segment @@ -85,13 +145,13 @@ void P073_data_struct::hc595_ShowBuffer() { // TODO disable log // if ((counter50 % 200 == 0) || P073_HC595_SEQUENTIAL) { - // addLog(LOG_LEVEL_INFO, strformat(F("P073: hc595_ShowBuffer (end) dgt:%d i:%d stop:%d incr:%d pin1: %d pin2: %d pin3: %d"), + // addLog(LOG_LEVEL_INFO, strformat(F("P073: showBuffer (end) dgt:%d i:%d stop:%d incr:%d pin1: %d pin2: %d pin3: %d"), // digits, i, stop, incr, pin1, pin2, pin3)); // } # endif // ifdef P073_DEBUG } -void P073_data_struct::hc595_ToOutputBuffer() { +void P073_74HC595::toOutputBuffer() { for (uint8_t i = 0; i < 8; ++i) { uint8_t value; @@ -104,22 +164,12 @@ void P073_data_struct::hc595_ToOutputBuffer() { outputbuffer[i] = P073_revert7bits(value); // Rotate bits 6..0 } - if (hc595_Sequential()) { // Sequential displays don't need continuous refreshing - hc595_ShowBuffer(); - } -} - -void P073_data_struct::hc595_ShiftinView() { - if (digits < 8) { - uint8_t n = 0; - - for (uint8_t i = 8 - digits; i < 8; ++i, ++n) { - showbuffer[n] = showbuffer[i]; - } + if (isSequential) { // Sequential displays don't need continuous refreshing + showBuffer(); } } -void P073_data_struct::hc595_InitDisplay() { +void P073_74HC595::initDisplay() { pinMode(pin1, OUTPUT); // Use Arduino pin initialization as some ESPs don't properly set up their pins with DIRECT_GPIO_OUTPUT pinMode(pin2, OUTPUT); pinMode(pin3, OUTPUT); diff --git a/src/src/PluginStructs/P073_display_MAX7219.cpp b/src/src/PluginStructs/P073_display_MAX7219.cpp index e2d908ff2d..998b6ead99 100644 --- a/src/src/PluginStructs/P073_display_MAX7219.cpp +++ b/src/src/PluginStructs/P073_display_MAX7219.cpp @@ -3,6 +3,35 @@ #ifdef USES_P073 # include +P073_MAX7219::P073_MAX7219(struct EventStruct *event) : P073_data_struct(event) { + // +} + +bool P073_MAX7219::init(struct EventStruct *event) { + if (P073_data_struct::init(event)) { + initDisplay(); + delay(10); // small poweroff/poweron delay + setPowerBrightness(brightness, true); + + if (output == P073_DISP_MANUAL) { + clearDisplay(); + } + return true; + } + return false; +} + +void P073_MAX7219::showTime(bool sep) { max7219_ShowTime(sep); } + +void P073_MAX7219::showDate() { max7219_ShowDate(); } + +void P073_MAX7219::showNumber() { toOutputBuffer(); } + +void P073_MAX7219::showTemperature(int8_t firstDot, + int8_t secondDot) { max7219_ShowTemp(firstDot, secondDot); } + +void P073_MAX7219::showBuffer() {} // n.a. + // ==================================== // ---- MAX7219 specific functions ---- // ==================================== @@ -13,48 +42,48 @@ # define OP_SHUTDOWN 12 # define OP_DISPLAYTEST 15 -void P073_data_struct::max7219_spiTransfer(ESPEASY_VOLATILE(uint8_t) opcode, - ESPEASY_VOLATILE(uint8_t) data) { - spidata[1] = opcode; - spidata[0] = data; +void P073_MAX7219::max7219_spiTransfer(ESPEASY_VOLATILE(uint8_t) opcode, + ESPEASY_VOLATILE(uint8_t) data) { + spidata[0] = opcode; + spidata[1] = data; DIRECT_pinWrite(pin3, LOW); - DIRECT_shiftOut(pin1, pin2, MSBFIRST, spidata[1]); DIRECT_shiftOut(pin1, pin2, MSBFIRST, spidata[0]); + DIRECT_shiftOut(pin1, pin2, MSBFIRST, spidata[1]); DIRECT_pinWrite(pin3, HIGH); } -void P073_data_struct::max7219_ClearDisplay() { +void P073_MAX7219::clearDisplay() { for (int i = 0; i < 8; i++) { max7219_spiTransfer(i + 1, 0); } } -void P073_data_struct::max7219_SetPowerBrightness(uint8_t brightlvl, - bool poweron) { +void P073_MAX7219::setPowerBrightness(uint8_t brightlvl, + bool poweron) { max7219_spiTransfer(OP_INTENSITY, brightlvl); max7219_spiTransfer(OP_SHUTDOWN, poweron ? 1 : 0); } -void P073_data_struct::max7219_SetDigit(int dgtpos, - uint8_t dgtvalue, - bool showdot, - bool binaryData) { - uint8_t p073_tempvalue; +void P073_MAX7219::setDigit(int dgtpos, + uint8_t dgtvalue, + bool showdot, + bool binaryData) { + uint8_t data; if (binaryData) { - p073_tempvalue = dgtvalue; // Overwrite if binary data + data = dgtvalue; // Overwrite if binary data } else { - p073_tempvalue = P073_getFontChar(dgtvalue, fontset); + data = P073_getFontChar(dgtvalue, fontset); if (showdot) { - p073_tempvalue |= 0b10000000; + data |= 0b10000000; } } - max7219_spiTransfer(dgtpos + 1, p073_tempvalue); + max7219_spiTransfer(dgtpos + 1, data); } -void P073_data_struct::max7219_InitDisplay() { +void P073_MAX7219::initDisplay() { pinMode(pin1, OUTPUT); // Use Arduino pin initialization as some ESPs don't properly set up their pins with DIRECT_GPIO_OUTPUT pinMode(pin2, OUTPUT); pinMode(pin3, OUTPUT); @@ -62,68 +91,57 @@ void P073_data_struct::max7219_InitDisplay() { max7219_spiTransfer(OP_DISPLAYTEST, 0); max7219_spiTransfer(OP_SCANLIMIT, 7); // scanlimit setup to max at Init max7219_spiTransfer(OP_DECODEMODE, 0); - max7219_ClearDisplay(); - max7219_SetPowerBrightness(0, false); + clearDisplay(); + setPowerBrightness(0, false); } -void P073_data_struct::max7219_ShowTime(bool sep) { +void P073_MAX7219::max7219_ShowTime(bool sep) { const uint8_t idx_list[] = { 7, 6, 4, 3, 1, 0 }; // Digits in reversed order, as the loop is backward for (int8_t i = 5; i >= 0; --i) { - max7219_SetDigit(idx_list[i], showbuffer[i], false); + setDigit(idx_list[i], showbuffer[i], false); } const uint8_t sepChar = P073_mapCharToFontPosition(sep ? '-' : ' ', fontset); - max7219_SetDigit(2, sepChar, false); - max7219_SetDigit(5, sepChar, false); + setDigit(2, sepChar, false); + setDigit(5, sepChar, false); } -void P073_data_struct::max7219_ShowTemp(int8_t firstDot, - int8_t secondDot) { - max7219_SetDigit(0, 10, false); +void P073_MAX7219::max7219_ShowTemp(int8_t firstDot, + int8_t secondDot) { + setDigit(0, 10, false); // FIXME Not sure about doing this every time... if (firstDot > -1) { showperiods[firstDot] = true; } if (secondDot > -1) { showperiods[secondDot] = true; } - const int alignRight = rightAlignTempMAX7219 ? 0 : 1; + digitOffset = rightAlignTempMAX7219 ? 0 : 1; - for (int i = alignRight; i < 8; ++i) { - const int bufIndex = (7 + alignRight) - i; - - if (bufIndex < 8) { - max7219_SetDigit(i, - showbuffer[bufIndex], - showperiods[bufIndex]); - } - } + toOutputBuffer(); } -void P073_data_struct::max7219_ShowDate() { - const uint8_t dotflags[8] = { false, true, false, true, false, false, false, false }; +void P073_MAX7219::max7219_ShowDate() { + // const uint8_t dotflags[8] = { false, true, false, true, false, false, false, false }; - for (int i = 0; i < 8; ++i) { - max7219_SetDigit(i, - showbuffer[7 - i], - dotflags[7 - i]); - } -} + showperiods[1] = true; + showperiods[3] = true; -void P073_data_struct::max7219_ShowBuffer() { - if (dotpos > -1) { - showperiods[dotpos] = true; - } + toOutputBuffer(); +} - for (int i = 0; i < 8; i++) { - max7219_SetDigit(i, - showbuffer[7 - i], - showperiods[7 - i] - # if P073_7DBIN_COMMAND - , binaryData - # endif // if P073_7DBIN_COMMAND - ); +void P073_MAX7219::toOutputBuffer() { + for (uint8_t i = digitOffset; i < 8; i++) { + const uint8_t bufIndex = (7 + digitOffset) - i; + setDigit(i, + showbuffer[bufIndex], + showperiods[bufIndex] + # if P073_7DBIN_COMMAND + , binaryData + # endif // if P073_7DBIN_COMMAND + ); } + digitOffset = 0; // Reset every time. } #endif // ifdef USES_P073 diff --git a/src/src/PluginStructs/P073_display_TM1637.cpp b/src/src/PluginStructs/P073_display_TM1637.cpp index 2c0995370e..dce4faa809 100644 --- a/src/src/PluginStructs/P073_display_TM1637.cpp +++ b/src/src/PluginStructs/P073_display_TM1637.cpp @@ -3,6 +3,80 @@ #ifdef USES_P073 # include +P073_TM1637::P073_TM1637(struct EventStruct *event) : P073_data_struct(event) { + // +} + +bool P073_TM1637::init(struct EventStruct *event) { + if (P073_data_struct::init(event)) { + initDisplay(); + setPowerBrightness(brightness / 2, true); + + if (output == P073_DISP_MANUAL) { + clearDisplay(); + } + return true; + } + return false; +} + +void P073_TM1637::showTime(bool sep) { + if (P073_TM1637_6DGT == displayModel) { + tm1637_ShowDate6(true); + } else { + tm1637_ShowTimeTemp4(sep, 0); + } +} + +void P073_TM1637::showDate() { + if (P073_TM1637_6DGT == displayModel) { + tm1637_ShowDate6(); + } else { + tm1637_ShowTimeTemp4(false, 0); + } +} + +void P073_TM1637::showNumber() { + if (P073_TM1637_6DGT == displayModel) { + tm1637_SwapDigitInBuffer(2); // only needed for 6-digits displays + tm1637_ShowBuffer(TM1637_6DIGIT, 8); + } else { + tm1637_ShowBuffer(TM1637_4DIGIT, 8); + } +} + +void P073_TM1637::showTemperature(int8_t firstDot, + int8_t secondDot) { + // if ((p073_temptemp == 0.0f) && p073_tempflagdot) { // TODO + // showbuffer[5] = 0; + // } + + if (P073_TM1637_6DGT == displayModel) { + tm1637_ShowTemp6(false); + } else { + tm1637_ShowTimeTemp4(false, 4); + } +} + +void P073_TM1637::showBuffer() {} // n.a. + +void P073_TM1637::toOutputBuffer() { + if (P073_TM1637_6DGT == displayModel) { + tm1637_SwapDigitInBuffer(0); // only needed for 6-digits displays + tm1637_ShowBuffer(0, 6 + # if P073_7DBIN_COMMAND + , binaryData + # endif // if P073_7DBIN_COMMAND + ); + } else { + tm1637_ShowBuffer(0, 4 + # if P073_7DBIN_COMMAND + , binaryData + # endif // if P073_7DBIN_COMMAND + ); + } +} + // =================================== // ---- TM1637 specific functions ---- // =================================== @@ -14,7 +88,7 @@ # define DIO_INPUT() DIRECT_PINMODE_INPUT(this->pin2) # define DIO_OUTPUT() DIRECT_PINMODE_OUTPUT(this->pin2) -void P073_data_struct::tm1637_i2cStart() { +void P073_TM1637::tm1637_i2cStart() { # if defined(P073_DEBUG) && !defined(BUILD_NO_DEBUG) addLog(LOG_LEVEL_DEBUG, F("7DGT : Comm Start")); # endif // if defined(P073_DEBUG) && !defined(BUILD_NO_DEBUG) @@ -22,7 +96,7 @@ void P073_data_struct::tm1637_i2cStart() { delayMicroseconds(TM1637_CLOCKDELAY); } -void P073_data_struct::tm1637_i2cStop() { +void P073_TM1637::tm1637_i2cStop() { # if defined(P073_DEBUG) && !defined(BUILD_NO_DEBUG) addLog(LOG_LEVEL_DEBUG, F("7DGT : Comm Stop")); # endif // if defined(P073_DEBUG) && !defined(BUILD_NO_DEBUG) @@ -34,7 +108,7 @@ void P073_data_struct::tm1637_i2cStop() { delayMicroseconds(TM1637_CLOCKDELAY); } -bool P073_data_struct::tm1637_i2cAck() { +bool P073_TM1637::tm1637_i2cAck() { CLK_LOW(); DIO_INPUT(); @@ -74,8 +148,8 @@ bool P073_data_struct::tm1637_i2cAck() { return acknowledged; } -void P073_data_struct::tm1637_i2cWrite_ack(uint8_t bytesToPrint[], - uint8_t length) { +void P073_TM1637::tm1637_i2cWrite_ack(uint8_t bytesToPrint[], + uint8_t length) { # ifdef P073_DEBUG if (loglevelActiveFor(LOG_LEVEL_INFO)) { @@ -90,12 +164,12 @@ void P073_data_struct::tm1637_i2cWrite_ack(uint8_t bytesToPrint[], tm1637_i2cStop(); } -void P073_data_struct::tm1637_i2cWriteByte_ack(uint8_t bytetoprint) { +void P073_TM1637::tm1637_i2cWriteByte_ack(uint8_t bytetoprint) { tm1637_i2cWrite(bytetoprint); tm1637_i2cAck(); } -void P073_data_struct::tm1637_i2cWrite(uint8_t bytetoprint) { +void P073_TM1637::tm1637_i2cWrite(uint8_t bytetoprint) { # if defined(P073_DEBUG) && !defined(BUILD_NO_DEBUG) addLog(LOG_LEVEL_DEBUG, F("7DGT : WriteByte")); # endif // if defined(P073_DEBUG) && !defined(BUILD_NO_DEBUG) @@ -116,15 +190,15 @@ void P073_data_struct::tm1637_i2cWrite(uint8_t bytetoprint) { } } -void P073_data_struct::tm1637_ClearDisplay() { +void P073_TM1637::clearDisplay() { uint8_t bytesToPrint[7]{}; bytesToPrint[0] = 0xC0; tm1637_i2cWrite_ack(bytesToPrint, 7); } -void P073_data_struct::tm1637_SetPowerBrightness(uint8_t brightlvl, - bool poweron) { +void P073_TM1637::setPowerBrightness(uint8_t brightlvl, + bool poweron) { # ifdef P073_DEBUG addLog(LOG_LEVEL_INFO, F("7DGT : Set BRIGHT")); # endif // ifdef P073_DEBUG @@ -140,7 +214,7 @@ void P073_data_struct::tm1637_SetPowerBrightness(uint8_t brightlvl, tm1637_i2cWrite_ack(bytesToPrint, NR_ELEMENTS(bytesToPrint)); } -void P073_data_struct::tm1637_InitDisplay() { +void P073_TM1637::initDisplay() { pinMode(this->pin1, OUTPUT); // Use Arduino pin initialization as some ESPs don't properly set up their pins with DIRECT_GPIO_OUTPUT pinMode(this->pin2, OUTPUT); @@ -150,22 +224,18 @@ void P073_data_struct::tm1637_InitDisplay() { delayMicroseconds(TM1637_CLOCKDELAY); uint8_t bytesToPrint[]{ 0x40 }; tm1637_i2cWrite_ack(bytesToPrint, NR_ELEMENTS(bytesToPrint)); - tm1637_ClearDisplay(); + clearDisplay(); } -uint8_t P073_data_struct::tm1637_separator(uint8_t value, - bool sep) { +uint8_t P073_TM1637::tm1637_separator(uint8_t value, + bool sep) { if (sep) { value |= 0b10000000; } return value; } -void P073_data_struct::tm1637_ShowTime6() { - tm1637_ShowDate6(true); // deduplicated -} - -void P073_data_struct::tm1637_ShowDate6(bool showTime) { +void P073_TM1637::tm1637_ShowDate6(bool showTime) { uint8_t bytesToPrint[7]{}; bytesToPrint[0] = 0xC0; @@ -185,7 +255,7 @@ void P073_data_struct::tm1637_ShowDate6(bool showTime) { tm1637_i2cWrite_ack(bytesToPrint, 7); } -void P073_data_struct::tm1637_ShowTemp6(bool sep) { +void P073_TM1637::tm1637_ShowTemp6(bool sep) { uint8_t bytesToPrint[7]{}; bytesToPrint[0] = 0xC0; @@ -199,8 +269,8 @@ void P073_data_struct::tm1637_ShowTemp6(bool sep) { tm1637_i2cWrite_ack(bytesToPrint, 7); } -void P073_data_struct::tm1637_ShowTimeTemp4(bool sep, - uint8_t bufoffset) { +void P073_TM1637::tm1637_ShowTimeTemp4(bool sep, + uint8_t bufoffset) { uint8_t bytesToPrint[5]{}; bytesToPrint[0] = 0xC0; @@ -212,32 +282,21 @@ void P073_data_struct::tm1637_ShowTimeTemp4(bool sep, tm1637_i2cWrite_ack(bytesToPrint, 5); } -void P073_data_struct::tm1637_SwapDigitInBuffer(uint8_t startPos) { +void P073_TM1637::tm1637_SwapDigitInBuffer(uint8_t startPos) { std::swap(showbuffer[2 + startPos], showbuffer[0 + startPos]); std::swap(showbuffer[3 + startPos], showbuffer[5 + startPos]); std::swap(showperiods[2 + startPos], showperiods[0 + startPos]); std::swap(showperiods[3 + startPos], showperiods[5 + startPos]); - - if (dotpos > -1) { - const uint8_t dotPositionSwap[] = { 0, 1, 4, 3, 2, 7, 6, 5, 8 }; - - dotpos = dotPositionSwap[dotpos]; - } } -void P073_data_struct::tm1637_ShowBuffer(uint8_t firstPos, - uint8_t lastPos, - bool useBinaryData) { +void P073_TM1637::tm1637_ShowBuffer(uint8_t firstPos, + uint8_t lastPos, + bool useBinaryData) { uint8_t bytesToPrint[8]{}; bytesToPrint[0] = 0xC0; uint8_t length = 1; - - if (dotpos > -1) { - showperiods[dotpos] = true; - } - uint8_t p073_datashowpos1; for (int i = firstPos; i < lastPos; ++i) { @@ -257,4 +316,7 @@ void P073_data_struct::tm1637_ShowBuffer(uint8_t firstPos, tm1637_i2cWrite_ack(bytesToPrint, length); } +uint8_t P073_TM1637::tm1637_getFontChar(uint8_t index, + uint8_t fontset) { return P073_revert7bits(P073_getFontChar(index, fontset)); } + #endif // ifdef USES_P073