From 833f47fd1518c73b79d9d720bfc87d970cc2011f Mon Sep 17 00:00:00 2001 From: Khoa Ton Date: Sat, 11 Jul 2020 23:16:29 -0700 Subject: [PATCH] Support up to 8 I2C Seven Segment Displays --- tasmota/my_user_config.h | 2 +- tasmota/xdsp_11_sevenseg.ino | 95 ++++++++++++++++++++++++------------ 2 files changed, 65 insertions(+), 32 deletions(-) diff --git a/tasmota/my_user_config.h b/tasmota/my_user_config.h index 0ab09d224..3447295a0 100644 --- a/tasmota/my_user_config.h +++ b/tasmota/my_user_config.h @@ -559,7 +559,7 @@ #define MTX_ADDRESS7 0x00 // [DisplayAddress7] I2C address of seventh 8x8 matrix module #define MTX_ADDRESS8 0x00 // [DisplayAddress8] I2C address of eigth 8x8 matrix module #define USE_DISPLAY_SEVENSEG // [DisplayModel 11] [I2cDriver47] Enable sevenseg display (I2C 0x70-0x77) (<+11k code) - #define SEVENSEG_ADDRESS1 0x70 // [DisplayAddress1] I2C address of first sevenseg matrix module + // #define SEVENSEG_ADDRESS1 0x70 // No longer used. Use MTX_ADDRESS1 - MTX_ADDRESS8 instead to specify I2C address of sevenseg displays // #define USE_DISPLAY_SH1106 // [DisplayModel 7] [I2cDriver6] Enable SH1106 Oled 128x64 display (I2C addresses 0x3C and 0x3D) #endif // USE_I2C diff --git a/tasmota/xdsp_11_sevenseg.ino b/tasmota/xdsp_11_sevenseg.ino index 20193e54e..0978cc466 100644 --- a/tasmota/xdsp_11_sevenseg.ino +++ b/tasmota/xdsp_11_sevenseg.ino @@ -28,20 +28,24 @@ #include #include // Seven segment LED -Adafruit_7segment sevenseg = Adafruit_7segment(); - +Adafruit_7segment *sevenseg[8]; +uint8_t sevensegs = 0; uint8_t sevenseg_state = 0; /*********************************************************************************************/ void SevensegWrite(void) { - sevenseg.writeDisplay(); + for (uint32_t i = 0; i < sevensegs; i++) { + sevenseg[i]->writeDisplay(); + } } void SevensegClear(void) { - sevenseg.clear(); + for (uint32_t i = 0; i < sevensegs; i++) { + sevenseg[i]->clear(); + } SevensegWrite(); } @@ -50,8 +54,10 @@ void SevensegClear(void) void SevensegInitMode(void) { - sevenseg.setBrightness(Settings.display_dimmer); - sevenseg.blinkRate(0); // 0 - 3 + for (uint32_t i = 0; i < sevensegs; i++) { + sevenseg[i]->setBrightness(Settings.display_dimmer); + sevenseg[i]->blinkRate(0); + } SevensegClear(); } @@ -69,17 +75,25 @@ void SevensegInit(uint8_t mode) void SevensegInitDriver(void) { if (!Settings.display_model) { - if (I2cSetDevice(SEVENSEG_ADDRESS1)) { + if (I2cSetDevice(Settings.display_address[0])) { Settings.display_model = XDSP_11; } } if (XDSP_11 == Settings.display_model) { sevenseg_state = 1; - sevenseg.begin(SEVENSEG_ADDRESS1); - + for (sevensegs = 0; sevensegs < 8; sevensegs++) { + if (Settings.display_address[sevensegs]) { + I2cSetActiveFound(Settings.display_address[sevensegs], "SevenSeg"); + sevenseg[sevensegs] = new Adafruit_7segment(); + sevenseg[sevensegs]->begin(Settings.display_address[sevensegs]); + } else { + break; + } + } + Settings.display_width = 4; - Settings.display_height = 1; + Settings.display_height = sevensegs; SevensegInitMode(); } @@ -101,15 +115,34 @@ void SevensegDrawStringAt(uint16_t x, uint16_t y, char *str, uint16_t color, uin boolean hex=false; boolean done=false; boolean s=false; + uint8_t unit=y; + if ((unit>=sevensegs) || (unit<0)) { + unit=0; + } + for (int i=0; (str[i]!='\0') && (!done); i++) { - // [prefix(es) chars]digits + // [optional prefix(es) chars]digits // Some combinations won't make sense. // Reference: https://learn.adafruit.com/adafruit-led-backpack/1-2-inch-7-segment-backpack-arduino-wiring-and-setup + // + // Prefixes: + // x upcoming number decimal integer displayed as hex + // : turn on middle colon + // ^ turh on top left dot + // v turn on bottom left dot + // . turn on AM/PM/Degree dot + // s upcoming number is seconds, print as HH:MM or MM:SS + // z clear this display + // // Some sample valid combinations: - // 787 -> 787 - // x47 -> 2F - // st:241 -> 04:01 - // sT241 -> 4 01 + // 787 -> 787 + // x47 -> 2F + // s:241 -> 04:01 + // s241 -> 4 01 + // s1241 -> 20:41 + // z -> + // x88 -> 58 + switch (str[i]) { case 'x': // print given dec value as hex hex = true; @@ -126,12 +159,6 @@ void SevensegDrawStringAt(uint16_t x, uint16_t y, char *str, uint16_t color, uin case '.': // print ampm dots |= 0x10; break; - case 'T': // print as time 12 format - t = true; - break; - case 't': // print as time 24 format - T = true; - break; case 's': // duration in seconds s = true; break; @@ -149,6 +176,12 @@ void SevensegDrawStringAt(uint16_t x, uint16_t y, char *str, uint16_t color, uin number = atoi(str+i); done = true; break; + case 'z': // Clear this display + hasnumber=false; + dots=0; + s=false; + sevenseg[unit]->clear(); + break; default: // unknown format, ignore break; } @@ -171,17 +204,17 @@ void SevensegDrawStringAt(uint16_t x, uint16_t y, char *str, uint16_t color, uin if (hasnumber) { if (hex) { - sevenseg.print(number, HEX); + sevenseg[unit]->print(number, HEX); } else { - sevenseg.print(number, DEC); + sevenseg[unit]->print(number, DEC); } } if (dots) { - sevenseg.writeDigitRaw(2, dots); + sevenseg[unit]->writeDigitRaw(2, dots); } - sevenseg.writeDisplay(); + sevenseg[unit]->writeDisplay(); } /*********************************************************************************************/ @@ -210,7 +243,7 @@ void SevensegTime(boolean time_24) // Now print the time value to the display. - sevenseg.print(displayValue, DEC); + sevenseg[0]->print(displayValue, DEC); // Add zero padding when in 24 hour mode and it's midnight. // In this case the print function above won't have leading 0's @@ -218,15 +251,15 @@ void SevensegTime(boolean time_24) if (time_24) { if (hours == 0) { // Pad hour 0. - sevenseg.writeDigitNum(1, 0); + sevenseg[0]->writeDigitNum(1, 0); // Also pad when the 10's minute is 0 and should be padded. if (minutes < 10) { - sevenseg.writeDigitNum(3, 0); + sevenseg[0]->writeDigitNum(3, 0); } } if (hours < 10) { // Always have 4 digits time - sevenseg.writeDigitNum(0, 0); + sevenseg[0]->writeDigitNum(0, 0); } } else { // Identify and display AM/PM @@ -235,8 +268,8 @@ void SevensegTime(boolean time_24) } } - sevenseg.writeDigitRaw(2, dots |= ((second%2) << 1)); - sevenseg.writeDisplay(); + sevenseg[0]->writeDigitRaw(2, dots |= ((second%2) << 1)); + sevenseg[0]->writeDisplay(); } void SevensegRefresh(void) // Every second