diff --git a/tasmota/my_user_config.h b/tasmota/my_user_config.h index 57ebbd121..d7dd6b2cc 100644 --- a/tasmota/my_user_config.h +++ b/tasmota/my_user_config.h @@ -563,6 +563,9 @@ // MTX_ADDRESS2 at y=1, up to MTX_ADDRESS8 at y=7 // Command: DisplayText [yn]8888 // will display 8888 at sevenseg display at I2C address MTX_ADDRESS(n-1) + // Each segment may be address Command: DisplayText [xn]m + // where n is 0..4 (4 digits and middle :) and m is decimal for bitmap of which segment to turn on. + // Reference: https://cdn-learn.adafruit.com/downloads/pdf/adafruit-led-backpack.pdf // #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 d01637204..1db043ef2 100644 --- a/tasmota/xdsp_11_sevenseg.ino +++ b/tasmota/xdsp_11_sevenseg.ino @@ -106,16 +106,18 @@ void SevensegOnOff(void) void SevensegDrawStringAt(uint16_t x, uint16_t y, char *str, uint16_t color, uint8_t flag) { - uint16_t number = 0; + enum OutNumType {DECIMAL, HEXADECIMAL, FLOAT, SEGMENTS}; + int16_t number = 0; + double numberf = 0; boolean hasnumber= false; uint8_t dots= 0; - boolean t=false; - boolean T=false; - boolean d=false; - boolean hex=false; - boolean done=false; - boolean s=false; - uint8_t unit=y; + OutNumType outnumtype= DECIMAL; + uint8 fds = 0; // number of fractional digits for fp number + boolean done= false; + boolean s= false; + uint8_t unit= y; + char *buf; + if ((unit>=sevensegs) || (unit<0)) { unit=0; } @@ -123,29 +125,41 @@ void SevensegDrawStringAt(uint16_t x, uint16_t y, char *str, uint16_t color, uin for (int i=0; (str[i]!='\0') && (!done); i++) { // [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 + // Reference: https://cdn-learn.adafruit.com/downloads/pdf/adafruit-led-backpack.pdf + // This code has been tested on 1.2" and 0.56" 7-Segment LED displays, but should mostly work for others. // // Prefixes: - // x upcoming number decimal integer displayed as hex + // x upcoming decimal integer number displayed as hex // : turn on middle colon // ^ turn 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 + // f upcoming number is floating point + // r raw segment based on bitmap of upcoming integer number (see reference document above) // // Some sample valid combinations: - // 787 -> 787 - // x47 -> 2F - // s:241 -> 04:01 - // s241 -> 4 01 - // s1241 -> 20:41 - // z -> - // x88 -> 58 + // 787 -> 787 + // x47 -> 2F + // s:241 -> 04:01 + // s241 -> 4 01 + // s1241 -> 20:41 + // z -> + // x88 -> 58 + // f8.5 -> 8.5 + // f-9.34 -> -9.34 + // f:-9.34 -> -9.:34 + // r255 -> 8. (all 8 segments on) switch (str[i]) { case 'x': // print given dec value as hex - hex = true; + // hex = true; + outnumtype = HEXADECIMAL; + break; + case 'f': // given number is floating point number + // fp = true; + outnumtype = FLOAT; break; case ':': // print colon dots |= 0x02; @@ -162,6 +176,7 @@ void SevensegDrawStringAt(uint16_t x, uint16_t y, char *str, uint16_t color, uin case 's': // duration in seconds s = true; break; + case '-': case '0': case '1': case '2': @@ -173,7 +188,21 @@ void SevensegDrawStringAt(uint16_t x, uint16_t y, char *str, uint16_t color, uin case '8': case '9': hasnumber= true; - number = atoi(str+i); + if (outnumtype == FLOAT) { + // Floating point number is given + numberf = atof(str+i); + // Find number of fractional digits + buf= str+i; + char *cp= strchr(buf, '.'); + if (cp == NULL) { + fds= 0; + } else { + fds= buf+strlen(buf) - 1 - cp; + } + } else { + // Integer is given + number = atoi(str+i); + } done = true; break; case 'z': // Clear this display @@ -182,30 +211,41 @@ void SevensegDrawStringAt(uint16_t x, uint16_t y, char *str, uint16_t color, uin s=false; sevenseg[unit]->clear(); break; + case 'r': // Raw segment + outnumtype= SEGMENTS; + break; default: // unknown format, ignore break; } } - if (s) { - // number is duration in seconds - hex = false; - int hour = number/60/60; - int minute = (number/60)%60; - - if (hour) { - // HH:MM - number = hour*100 + minute; - } else { - // MM:SS - number = minute*100 + number%60; - } - } if (hasnumber) { - if (hex) { + if (s) { + // number is duration in seconds + int hour = number/60/60; + int minute = (number/60)%60; + + if (hour) { + // HH:MM + number = hour*100 + minute; + } else { + // MM:SS + number = minute*100 + number%60; + } + } + + if (outnumtype == HEXADECIMAL) { + // Hex sevenseg[unit]->print(number, HEX); + } else if (outnumtype == FLOAT) { + // Floating point + sevenseg[unit]->printFloat(numberf, fds, 10); + } else if (outnumtype == SEGMENTS) { + // Raw segments + sevenseg[unit]->writeDigitRaw(x, number); } else { + // Decimal sevenseg[unit]->print(number, DEC); } }