diff --git a/lib/lib_display/LedControl/LICENSE b/lib/lib_display/LedControl/LICENSE new file mode 100644 index 000000000..8d59812aa --- /dev/null +++ b/lib/lib_display/LedControl/LICENSE @@ -0,0 +1,23 @@ +LedControl.h - A library for controling Leds with a MAX7219/MAX7221 +Copyright (c) 2007-2015 Eberhard Fahle + +Permission is hereby granted, free of charge, to any person +obtaining a copy of this software and associated documentation +files (the "Software"), to deal in the Software without +restriction, including without limitation the rights to use, +copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the +Software is furnished to do so, subject to the following +conditions: + +This permission notice shall be included in all copies or +substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. diff --git a/lib/lib_display/LedControl/README.md b/lib/lib_display/LedControl/README.md new file mode 100644 index 000000000..8c832d654 --- /dev/null +++ b/lib/lib_display/LedControl/README.md @@ -0,0 +1,25 @@ +LedControl +========== +LedControl is an [Arduino](http://arduino.cc) library for MAX7219 and MAX7221 Led display drivers. +The code also works with the [Teensy (3.1)](https://www.pjrc.com/teensy/) + +Documentation +------------- +Documentation for the library is on the [Github Project Pages](http://wayoda.github.io/LedControl/) + +Download +-------- +The lastest binary version of the Library is always available from the +[LedControl Release Page](https://github.com/wayoda/LedControl/releases) + + +Install +------- +The library can be installed using the [standard Arduino library install procedure](http://arduino.cc/en/Guide/Libraries#.UwxndHX5PtY) + + + + + + + diff --git a/lib/lib_display/LedControl/keywords.txt b/lib/lib_display/LedControl/keywords.txt new file mode 100644 index 000000000..9d2a94f1f --- /dev/null +++ b/lib/lib_display/LedControl/keywords.txt @@ -0,0 +1,28 @@ +####################################### +# Syntax Coloring Map For LedControl +####################################### + +####################################### +# Datatypes (KEYWORD1) +####################################### + +LedControl KEYWORD1 + +####################################### +# Methods and Functions (KEYWORD2) +####################################### + +shutdown KEYWORD2 +setScanLimit KEYWORD2 +setIntensity KEYWORD2 +clearDisplay KEYWORD2 +setLed KEYWORD2 +setRow KEYWORD2 +setColumn KEYWORD2 +setDigit KEYWORD2 +setChar KEYWORD2 + +####################################### +# Constants (LITERAL1) +####################################### + diff --git a/lib/lib_display/LedControl/library.properties b/lib/lib_display/LedControl/library.properties new file mode 100644 index 000000000..66baced18 --- /dev/null +++ b/lib/lib_display/LedControl/library.properties @@ -0,0 +1,10 @@ +name=LedControl +version=1.0.6 +author=Eberhard Fahle +maintainer=Eberhard Fahle +sentence=A library for the MAX7219 and the MAX7221 Led display drivers. +paragraph=The library supports multiple daisychained drivers and supports Led-Matrix displays as well as 7-Segment displays. +category=Display +url=http://wayoda.github.io/LedControl/ +architectures=* + diff --git a/lib/lib_display/LedControl/src/LedControl.cpp b/lib/lib_display/LedControl/src/LedControl.cpp new file mode 100644 index 000000000..e43211fd8 --- /dev/null +++ b/lib/lib_display/LedControl/src/LedControl.cpp @@ -0,0 +1,211 @@ +/* + * LedControl.cpp - A library for controling Leds with a MAX7219/MAX7221 + * Copyright (c) 2007 Eberhard Fahle + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * This permission notice shall be included in all copies or + * substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + + +#include "LedControl.h" + +//the opcodes for the MAX7221 and MAX7219 +#define OP_NOOP 0 +#define OP_DIGIT0 1 +#define OP_DIGIT1 2 +#define OP_DIGIT2 3 +#define OP_DIGIT3 4 +#define OP_DIGIT4 5 +#define OP_DIGIT5 6 +#define OP_DIGIT6 7 +#define OP_DIGIT7 8 +#define OP_DECODEMODE 9 +#define OP_INTENSITY 10 +#define OP_SCANLIMIT 11 +#define OP_SHUTDOWN 12 +#define OP_DISPLAYTEST 15 + +LedControl::LedControl(int dataPin, int clkPin, int csPin, int numDevices) { + SPI_MOSI=dataPin; + SPI_CLK=clkPin; + SPI_CS=csPin; + if(numDevices<=0 || numDevices>8 ) + numDevices=8; + maxDevices=numDevices; + pinMode(SPI_MOSI,OUTPUT); + pinMode(SPI_CLK,OUTPUT); + pinMode(SPI_CS,OUTPUT); + digitalWrite(SPI_CS,HIGH); + SPI_MOSI=dataPin; + for(int i=0;i<64;i++) + status[i]=0x00; + for(int i=0;i=maxDevices) + return; + if(b) + spiTransfer(addr, OP_SHUTDOWN,0); + else + spiTransfer(addr, OP_SHUTDOWN,1); +} + +void LedControl::setScanLimit(int addr, int limit) { + if(addr<0 || addr>=maxDevices) + return; + if(limit>=0 && limit<8) + spiTransfer(addr, OP_SCANLIMIT,limit); +} + +void LedControl::setIntensity(int addr, int intensity) { + if(addr<0 || addr>=maxDevices) + return; + if(intensity>=0 && intensity<16) + spiTransfer(addr, OP_INTENSITY,intensity); +} + +void LedControl::clearDisplay(int addr) { + int offset; + + if(addr<0 || addr>=maxDevices) + return; + offset=addr*8; + for(int i=0;i<8;i++) { + status[offset+i]=0; + spiTransfer(addr, i+1,status[offset+i]); + } +} + +void LedControl::setLed(int addr, int row, int column, boolean state) { + int offset; + byte val=0x00; + + if(addr<0 || addr>=maxDevices) + return; + if(row<0 || row>7 || column<0 || column>7) + return; + offset=addr*8; + val=B10000000 >> column; + if(state) + status[offset+row]=status[offset+row]|val; + else { + val=~val; + status[offset+row]=status[offset+row]&val; + } + spiTransfer(addr, row+1,status[offset+row]); +} + +void LedControl::setRow(int addr, int row, byte value) { + int offset; + if(addr<0 || addr>=maxDevices) + return; + if(row<0 || row>7) + return; + offset=addr*8; + status[offset+row]=value; + spiTransfer(addr, row+1,status[offset+row]); +} + +void LedControl::setColumn(int addr, int col, byte value) { + byte val; + + if(addr<0 || addr>=maxDevices) + return; + if(col<0 || col>7) + return; + for(int row=0;row<8;row++) { + val=value >> (7-row); + val=val & 0x01; + setLed(addr,row,col,val); + } +} + +void LedControl::setDigit(int addr, int digit, byte value, boolean dp) { + int offset; + byte v; + + if(addr<0 || addr>=maxDevices) + return; + if(digit<0 || digit>7 || value>15) + return; + offset=addr*8; + v=pgm_read_byte_near(charTable + value); + if(dp) + v|=B10000000; + status[offset+digit]=v; + spiTransfer(addr, digit+1,v); +} + +void LedControl::setChar(int addr, int digit, char value, boolean dp) { + int offset; + byte index,v; + + if(addr<0 || addr>=maxDevices) + return; + if(digit<0 || digit>7) + return; + offset=addr*8; + index=(byte)value; + if(index >127) { + //no defined beyond index 127, so we use the space char + index=32; + } + v=pgm_read_byte_near(charTable + index); + if(dp) + v|=B10000000; + status[offset+digit]=v; + spiTransfer(addr, digit+1,v); +} + +void LedControl::spiTransfer(int addr, volatile byte opcode, volatile byte data) { + //Create an array with the data to shift out + int offset=addr*2; + int maxbytes=maxDevices*2; + + for(int i=0;i0;i--) + shiftOut(SPI_MOSI,SPI_CLK,MSBFIRST,spidata[i-1]); + //latch the data onto the display + digitalWrite(SPI_CS,HIGH); +} + + diff --git a/lib/lib_display/LedControl/src/LedControl.h b/lib/lib_display/LedControl/src/LedControl.h new file mode 100644 index 000000000..f8180d07d --- /dev/null +++ b/lib/lib_display/LedControl/src/LedControl.h @@ -0,0 +1,190 @@ +/* + * LedControl.h - A library for controling Leds with a MAX7219/MAX7221 + * Copyright (c) 2007 Eberhard Fahle + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * This permission notice shall be included in all copies or + * substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef LedControl_h +#define LedControl_h + +#include + +#if (ARDUINO >= 100) +#include +#else +#include +#endif + +/* + * Segments to be switched on for characters and digits on + * 7-Segment Displays + */ +const static byte charTable [] PROGMEM = { + B01111110,B00110000,B01101101,B01111001,B00110011,B01011011,B01011111,B01110000, + B01111111,B01111011,B01110111,B00011111,B00001101,B00111101,B01001111,B01000111, + B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000, + B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000, + B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000, + B00000000,B00000000,B00000000,B00000000,B10000000,B00000001,B10000000,B00000000, + B01111110,B00110000,B01101101,B01111001,B00110011,B01011011,B01011111,B01110000, + B01111111,B01111011,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000, + B00000000,B01110111,B00011111,B00001101,B00111101,B01001111,B01000111,B00000000, + B00110111,B00000000,B00000000,B00000000,B00001110,B00000000,B00000000,B00000000, + B01100111,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000, + B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00001000, + B00000000,B01110111,B00011111,B00001101,B00111101,B01001111,B01000111,B00000000, + B00110111,B00000000,B00000000,B00000000,B00001110,B00000000,B00010101,B00011101, + B01100111,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000, + B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000 +}; + +class LedControl { + private : + /* The array for shifting the data to the devices */ + byte spidata[16]; + /* Send out a single command to the device */ + void spiTransfer(int addr, byte opcode, byte data); + + /* We keep track of the led-status for all 8 devices in this array */ + byte status[64]; + /* Data is shifted out of this pin*/ + int SPI_MOSI; + /* The clock is signaled on this pin */ + int SPI_CLK; + /* This one is driven LOW for chip selectzion */ + int SPI_CS; + /* The maximum number of devices we use */ + int maxDevices; + + public: + /* + * Create a new controler + * Params : + * dataPin pin on the Arduino where data gets shifted out + * clockPin pin for the clock + * csPin pin for selecting the device + * numDevices maximum number of devices that can be controled + */ + LedControl(int dataPin, int clkPin, int csPin, int numDevices=1); + + /* + * Gets the number of devices attached to this LedControl. + * Returns : + * int the number of devices on this LedControl + */ + int getDeviceCount(); + + /* + * Set the shutdown (power saving) mode for the device + * Params : + * addr The address of the display to control + * status If true the device goes into power-down mode. Set to false + * for normal operation. + */ + void shutdown(int addr, bool status); + + /* + * Set the number of digits (or rows) to be displayed. + * See datasheet for sideeffects of the scanlimit on the brightness + * of the display. + * Params : + * addr address of the display to control + * limit number of digits to be displayed (1..8) + */ + void setScanLimit(int addr, int limit); + + /* + * Set the brightness of the display. + * Params: + * addr the address of the display to control + * intensity the brightness of the display. (0..15) + */ + void setIntensity(int addr, int intensity); + + /* + * Switch all Leds on the display off. + * Params: + * addr address of the display to control + */ + void clearDisplay(int addr); + + /* + * Set the status of a single Led. + * Params : + * addr address of the display + * row the row of the Led (0..7) + * col the column of the Led (0..7) + * state If true the led is switched on, + * if false it is switched off + */ + void setLed(int addr, int row, int col, boolean state); + + /* + * Set all 8 Led's in a row to a new state + * Params: + * addr address of the display + * row row which is to be set (0..7) + * value each bit set to 1 will light up the + * corresponding Led. + */ + void setRow(int addr, int row, byte value); + + /* + * Set all 8 Led's in a column to a new state + * Params: + * addr address of the display + * col column which is to be set (0..7) + * value each bit set to 1 will light up the + * corresponding Led. + */ + void setColumn(int addr, int col, byte value); + + /* + * Display a hexadecimal digit on a 7-Segment Display + * Params: + * addr address of the display + * digit the position of the digit on the display (0..7) + * value the value to be displayed. (0x00..0x0F) + * dp sets the decimal point. + */ + void setDigit(int addr, int digit, byte value, boolean dp); + + /* + * Display a character on a 7-Segment display. + * There are only a few characters that make sense here : + * '0','1','2','3','4','5','6','7','8','9','0', + * 'A','b','c','d','E','F','H','L','P', + * '.','-','_',' ' + * Params: + * addr address of the display + * digit the position of the character on the display (0..7) + * value the character to be displayed. + * dp sets the decimal point. + */ + void setChar(int addr, int digit, char value, boolean dp); +}; + +#endif //LedControl.h + + + diff --git a/tasmota/language/af_AF.h b/tasmota/language/af_AF.h index b61c82c6e..7693ec42c 100644 --- a/tasmota/language/af_AF.h +++ b/tasmota/language/af_AF.h @@ -643,6 +643,9 @@ #define D_SENSOR_TM1638_CLK "TM1638 CLK" #define D_SENSOR_TM1638_DIO "TM1638 DIO" #define D_SENSOR_TM1638_STB "TM1638 STB" +#define D_SENSOR_MAX7219_DIN "MAX7219 DIN" +#define D_SENSOR_MAX7219_CS "MAX7219 CS" +#define D_SENSOR_MAX7219_CLK "MAX7219 CLK" #define D_SENSOR_HX711_SCK "HX711 SCK" #define D_SENSOR_HX711_DAT "HX711 DAT" #define D_SENSOR_FTC532 "FTC532" diff --git a/tasmota/language/bg_BG.h b/tasmota/language/bg_BG.h index 2061eb460..96d1783c1 100644 --- a/tasmota/language/bg_BG.h +++ b/tasmota/language/bg_BG.h @@ -642,6 +642,9 @@ #define D_SENSOR_TM1638_CLK "TM1638 CLK" #define D_SENSOR_TM1638_DIO "TM1638 DIO" #define D_SENSOR_TM1638_STB "TM1638 STB" +#define D_SENSOR_MAX7219_DIN "MAX7219 DIN" +#define D_SENSOR_MAX7219_CS "MAX7219 CS" +#define D_SENSOR_MAX7219_CLK "MAX7219 CLK" #define D_SENSOR_HX711_SCK "HX711 SCK" #define D_SENSOR_HX711_DAT "HX711 DAT" #define D_SENSOR_FTC532 "FTC532" diff --git a/tasmota/language/cs_CZ.h b/tasmota/language/cs_CZ.h index be329c3e2..9359c0c3a 100644 --- a/tasmota/language/cs_CZ.h +++ b/tasmota/language/cs_CZ.h @@ -643,6 +643,9 @@ #define D_SENSOR_TM1638_CLK "TM1638 CLK" #define D_SENSOR_TM1638_DIO "TM1638 DIO" #define D_SENSOR_TM1638_STB "TM1638 STB" +#define D_SENSOR_MAX7219_DIN "MAX7219 DIN" +#define D_SENSOR_MAX7219_CS "MAX7219 CS" +#define D_SENSOR_MAX7219_CLK "MAX7219 CLK" #define D_SENSOR_HX711_SCK "HX711 SCK" #define D_SENSOR_HX711_DAT "HX711 DAT" #define D_SENSOR_FTC532 "FTC532" diff --git a/tasmota/language/de_DE.h b/tasmota/language/de_DE.h index 9eaff2441..e042317bd 100644 --- a/tasmota/language/de_DE.h +++ b/tasmota/language/de_DE.h @@ -643,6 +643,9 @@ #define D_SENSOR_TM1638_CLK "TM1638 CLK" #define D_SENSOR_TM1638_DIO "TM1638 DIO" #define D_SENSOR_TM1638_STB "TM1638 STB" +#define D_SENSOR_MAX7219_DIN "MAX7219 DIN" +#define D_SENSOR_MAX7219_CS "MAX7219 CS" +#define D_SENSOR_MAX7219_CLK "MAX7219 CLK" #define D_SENSOR_HX711_SCK "HX711 SCK" #define D_SENSOR_HX711_DAT "HX711 DAT" #define D_SENSOR_FTC532 "FTC532" diff --git a/tasmota/language/el_GR.h b/tasmota/language/el_GR.h index ca14da7c1..677ea5c1d 100644 --- a/tasmota/language/el_GR.h +++ b/tasmota/language/el_GR.h @@ -643,6 +643,9 @@ #define D_SENSOR_TM1638_CLK "TM1638 CLK" #define D_SENSOR_TM1638_DIO "TM1638 DIO" #define D_SENSOR_TM1638_STB "TM1638 STB" +#define D_SENSOR_MAX7219_DIN "MAX7219 DIN" +#define D_SENSOR_MAX7219_CS "MAX7219 CS" +#define D_SENSOR_MAX7219_CLK "MAX7219 CLK" #define D_SENSOR_HX711_SCK "HX711 SCK" #define D_SENSOR_HX711_DAT "HX711 DAT" #define D_SENSOR_FTC532 "FTC532" diff --git a/tasmota/language/en_GB.h b/tasmota/language/en_GB.h index 12a476a32..a2afce3f0 100644 --- a/tasmota/language/en_GB.h +++ b/tasmota/language/en_GB.h @@ -643,6 +643,9 @@ #define D_SENSOR_TM1638_CLK "TM1638 CLK" #define D_SENSOR_TM1638_DIO "TM1638 DIO" #define D_SENSOR_TM1638_STB "TM1638 STB" +#define D_SENSOR_MAX7219_DIN "MAX7219 DIN" +#define D_SENSOR_MAX7219_CS "MAX7219 CS" +#define D_SENSOR_MAX7219_CLK "MAX7219 CLK" #define D_SENSOR_HX711_SCK "HX711 SCK" #define D_SENSOR_HX711_DAT "HX711 DAT" #define D_SENSOR_FTC532 "FTC532" diff --git a/tasmota/language/es_ES.h b/tasmota/language/es_ES.h index 93967a818..4316797d7 100644 --- a/tasmota/language/es_ES.h +++ b/tasmota/language/es_ES.h @@ -643,6 +643,9 @@ #define D_SENSOR_TM1638_CLK "TM1638 CLK" #define D_SENSOR_TM1638_DIO "TM1638 DIO" #define D_SENSOR_TM1638_STB "TM1638 STB" +#define D_SENSOR_MAX7219_DIN "MAX7219 DIN" +#define D_SENSOR_MAX7219_CS "MAX7219 CS" +#define D_SENSOR_MAX7219_CLK "MAX7219 CLK" #define D_SENSOR_HX711_SCK "HX711 SCK" #define D_SENSOR_HX711_DAT "HX711 DAT" #define D_SENSOR_FTC532 "FTC532" diff --git a/tasmota/language/fr_FR.h b/tasmota/language/fr_FR.h index fdced5059..283404723 100644 --- a/tasmota/language/fr_FR.h +++ b/tasmota/language/fr_FR.h @@ -643,6 +643,9 @@ #define D_SENSOR_TM1638_CLK "TM1638 CLK" #define D_SENSOR_TM1638_DIO "TM1638 DIO" #define D_SENSOR_TM1638_STB "TM1638 STB" +#define D_SENSOR_MAX7219_DIN "MAX7219 DIN" +#define D_SENSOR_MAX7219_CS "MAX7219 CS" +#define D_SENSOR_MAX7219_CLK "MAX7219 CLK" #define D_SENSOR_HX711_SCK "HX711 SCK" #define D_SENSOR_HX711_DAT "HX711 DAT" #define D_SENSOR_FTC532 "FTC532" diff --git a/tasmota/language/fy_NL.h b/tasmota/language/fy_NL.h index 8b166dd94..ca6688f57 100644 --- a/tasmota/language/fy_NL.h +++ b/tasmota/language/fy_NL.h @@ -643,6 +643,9 @@ #define D_SENSOR_TM1638_CLK "TM1638 CLK" #define D_SENSOR_TM1638_DIO "TM1638 DIO" #define D_SENSOR_TM1638_STB "TM1638 STB" +#define D_SENSOR_MAX7219_DIN "MAX7219 DIN" +#define D_SENSOR_MAX7219_CS "MAX7219 CS" +#define D_SENSOR_MAX7219_CLK "MAX7219 CLK" #define D_SENSOR_HX711_SCK "HX711 SCK" #define D_SENSOR_HX711_DAT "HX711 DAT" #define D_SENSOR_FTC532 "FTC532" diff --git a/tasmota/language/he_HE.h b/tasmota/language/he_HE.h index 8bf5e5e97..0b4374f5c 100644 --- a/tasmota/language/he_HE.h +++ b/tasmota/language/he_HE.h @@ -643,6 +643,9 @@ #define D_SENSOR_TM1638_CLK "TM1638 CLK" #define D_SENSOR_TM1638_DIO "TM1638 DIO" #define D_SENSOR_TM1638_STB "TM1638 STB" +#define D_SENSOR_MAX7219_DIN "MAX7219 DIN" +#define D_SENSOR_MAX7219_CS "MAX7219 CS" +#define D_SENSOR_MAX7219_CLK "MAX7219 CLK" #define D_SENSOR_HX711_SCK "HX711 SCK" #define D_SENSOR_HX711_DAT "HX711 DAT" #define D_SENSOR_FTC532 "FTC532" diff --git a/tasmota/language/hu_HU.h b/tasmota/language/hu_HU.h index 239239348..5c4b3a150 100644 --- a/tasmota/language/hu_HU.h +++ b/tasmota/language/hu_HU.h @@ -643,6 +643,9 @@ #define D_SENSOR_TM1638_CLK "TM1638 CLK" #define D_SENSOR_TM1638_DIO "TM1638 DIO" #define D_SENSOR_TM1638_STB "TM1638 STB" +#define D_SENSOR_MAX7219_DIN "MAX7219 DIN" +#define D_SENSOR_MAX7219_CS "MAX7219 CS" +#define D_SENSOR_MAX7219_CLK "MAX7219 CLK" #define D_SENSOR_HX711_SCK "HX711 SCK" #define D_SENSOR_HX711_DAT "HX711 DAT" #define D_SENSOR_FTC532 "FTC532" diff --git a/tasmota/language/it_IT.h b/tasmota/language/it_IT.h index b8a7d828b..c449f9362 100644 --- a/tasmota/language/it_IT.h +++ b/tasmota/language/it_IT.h @@ -643,6 +643,9 @@ #define D_SENSOR_TM1638_CLK "TM1638 - CLK" #define D_SENSOR_TM1638_DIO "TM1638 - DIO" #define D_SENSOR_TM1638_STB "TM1638 - STB" +#define D_SENSOR_MAX7219_DIN "MAX7219 - DIN" +#define D_SENSOR_MAX7219_CS "MAX7219 - CS" +#define D_SENSOR_MAX7219_CLK "MAX7219 - CLK" #define D_SENSOR_HX711_SCK "HX711 - SCK" #define D_SENSOR_HX711_DAT "HX711 - DAT" #define D_SENSOR_FTC532 "FTC532" diff --git a/tasmota/language/ko_KO.h b/tasmota/language/ko_KO.h index 964ab46a7..442aaa4cb 100644 --- a/tasmota/language/ko_KO.h +++ b/tasmota/language/ko_KO.h @@ -643,6 +643,9 @@ #define D_SENSOR_TM1638_CLK "TM1638 CLK" #define D_SENSOR_TM1638_DIO "TM1638 DIO" #define D_SENSOR_TM1638_STB "TM1638 STB" +#define D_SENSOR_MAX7219_DIN "MAX7219 DIN" +#define D_SENSOR_MAX7219_CS "MAX7219 CS" +#define D_SENSOR_MAX7219_CLK "MAX7219 CLK" #define D_SENSOR_HX711_SCK "HX711 SCK" #define D_SENSOR_HX711_DAT "HX711 DAT" #define D_SENSOR_FTC532 "FTC532" diff --git a/tasmota/language/nl_NL.h b/tasmota/language/nl_NL.h index bc855e4a8..87ad91eae 100644 --- a/tasmota/language/nl_NL.h +++ b/tasmota/language/nl_NL.h @@ -643,6 +643,9 @@ #define D_SENSOR_TM1638_CLK "TM1638 CLK" #define D_SENSOR_TM1638_DIO "TM1638 DIO" #define D_SENSOR_TM1638_STB "TM1638 STB" +#define D_SENSOR_MAX7219_DIN "MAX7219 DIN" +#define D_SENSOR_MAX7219_CS "MAX7219 CS" +#define D_SENSOR_MAX7219_CLK "MAX7219 CLK" #define D_SENSOR_HX711_SCK "HX711 SCK" #define D_SENSOR_HX711_DAT "HX711 DAT" #define D_SENSOR_FTC532 "FTC532" diff --git a/tasmota/language/pl_PL.h b/tasmota/language/pl_PL.h index 78710996f..da1151789 100644 --- a/tasmota/language/pl_PL.h +++ b/tasmota/language/pl_PL.h @@ -643,6 +643,9 @@ #define D_SENSOR_TM1638_CLK "TM1638 CLK" #define D_SENSOR_TM1638_DIO "TM1638 DIO" #define D_SENSOR_TM1638_STB "TM1638 STB" +#define D_SENSOR_MAX7219_DIN "MAX7219 DIN" +#define D_SENSOR_MAX7219_CS "MAX7219 CS" +#define D_SENSOR_MAX7219_CLK "MAX7219 CLK" #define D_SENSOR_HX711_SCK "HX711 SCK" #define D_SENSOR_HX711_DAT "HX711 DAT" #define D_SENSOR_FTC532 "FTC532" diff --git a/tasmota/language/pt_BR.h b/tasmota/language/pt_BR.h index a2929b529..138799cbd 100644 --- a/tasmota/language/pt_BR.h +++ b/tasmota/language/pt_BR.h @@ -643,6 +643,9 @@ #define D_SENSOR_TM1638_CLK "TM1638 CLK" #define D_SENSOR_TM1638_DIO "TM1638 DIO" #define D_SENSOR_TM1638_STB "TM1638 STB" +#define D_SENSOR_MAX7219_DIN "MAX7219 DIN" +#define D_SENSOR_MAX7219_CS "MAX7219 CS" +#define D_SENSOR_MAX7219_CLK "MAX7219 CLK" #define D_SENSOR_HX711_SCK "HX711 SCK" #define D_SENSOR_HX711_DAT "HX711 DAT" #define D_SENSOR_FTC532 "FTC532" diff --git a/tasmota/language/pt_PT.h b/tasmota/language/pt_PT.h index c5b524875..c448703bd 100644 --- a/tasmota/language/pt_PT.h +++ b/tasmota/language/pt_PT.h @@ -643,6 +643,9 @@ #define D_SENSOR_TM1638_CLK "TM1638 CLK" #define D_SENSOR_TM1638_DIO "TM1638 DIO" #define D_SENSOR_TM1638_STB "TM1638 STB" +#define D_SENSOR_MAX7219_DIN "MAX7219 DIN" +#define D_SENSOR_MAX7219_CS "MAX7219 CS" +#define D_SENSOR_MAX7219_CLK "MAX7219 CLK" #define D_SENSOR_HX711_SCK "HX711 SCK" #define D_SENSOR_HX711_DAT "HX711 DAT" #define D_SENSOR_FTC532 "FTC532" diff --git a/tasmota/language/ro_RO.h b/tasmota/language/ro_RO.h index c8182eb75..9329d95ef 100644 --- a/tasmota/language/ro_RO.h +++ b/tasmota/language/ro_RO.h @@ -643,6 +643,9 @@ #define D_SENSOR_TM1638_CLK "TM1638 CLK" #define D_SENSOR_TM1638_DIO "TM1638 DIO" #define D_SENSOR_TM1638_STB "TM1638 STB" +#define D_SENSOR_MAX7219_DIN "MAX7219 DIN" +#define D_SENSOR_MAX7219_CS "MAX7219 CS" +#define D_SENSOR_MAX7219_CLK "MAX7219 CLK" #define D_SENSOR_HX711_SCK "HX711 SCK" #define D_SENSOR_HX711_DAT "HX711 DAT" #define D_SENSOR_FTC532 "FTC532" diff --git a/tasmota/language/ru_RU.h b/tasmota/language/ru_RU.h index 6d8d0b932..ac7a9479a 100644 --- a/tasmota/language/ru_RU.h +++ b/tasmota/language/ru_RU.h @@ -643,6 +643,9 @@ #define D_SENSOR_TM1638_CLK "TM1638 CLK" #define D_SENSOR_TM1638_DIO "TM1638 DIO" #define D_SENSOR_TM1638_STB "TM1638 STB" +#define D_SENSOR_MAX7219_DIN "MAX7219 DIN" +#define D_SENSOR_MAX7219_CS "MAX7219 CS" +#define D_SENSOR_MAX7219_CLK "MAX7219 CLK" #define D_SENSOR_HX711_SCK "HX711 SCK" #define D_SENSOR_HX711_DAT "HX711 DAT" #define D_SENSOR_FTC532 "FTC532" diff --git a/tasmota/language/sk_SK.h b/tasmota/language/sk_SK.h index b0fbc5c3f..1342d88ae 100644 --- a/tasmota/language/sk_SK.h +++ b/tasmota/language/sk_SK.h @@ -643,6 +643,9 @@ #define D_SENSOR_TM1638_CLK "TM1638 CLK" #define D_SENSOR_TM1638_DIO "TM1638 DIO" #define D_SENSOR_TM1638_STB "TM1638 STB" +#define D_SENSOR_MAX7219_DIN "MAX7219 DIN" +#define D_SENSOR_MAX7219_CS "MAX7219 CS" +#define D_SENSOR_MAX7219_CLK "MAX7219 CLK" #define D_SENSOR_HX711_SCK "HX711 SCK" #define D_SENSOR_HX711_DAT "HX711 DAT" #define D_SENSOR_FTC532 "FTC532" diff --git a/tasmota/language/sv_SE.h b/tasmota/language/sv_SE.h index 5ccbc77fe..1300e6295 100644 --- a/tasmota/language/sv_SE.h +++ b/tasmota/language/sv_SE.h @@ -643,6 +643,9 @@ #define D_SENSOR_TM1638_CLK "TM1638 CLK" #define D_SENSOR_TM1638_DIO "TM1638 DIO" #define D_SENSOR_TM1638_STB "TM1638 STB" +#define D_SENSOR_MAX7219_DIN "MAX7219 DIN" +#define D_SENSOR_MAX7219_CS "MAX7219 CS" +#define D_SENSOR_MAX7219_CLK "MAX7219 CLK" #define D_SENSOR_HX711_SCK "HX711 SCK" #define D_SENSOR_HX711_DAT "HX711 DAT" #define D_SENSOR_FTC532 "FTC532" diff --git a/tasmota/language/tr_TR.h b/tasmota/language/tr_TR.h index e6429fed1..bcf01e1ea 100644 --- a/tasmota/language/tr_TR.h +++ b/tasmota/language/tr_TR.h @@ -643,6 +643,9 @@ #define D_SENSOR_TM1638_CLK "TM1638 CLK" #define D_SENSOR_TM1638_DIO "TM1638 DIO" #define D_SENSOR_TM1638_STB "TM1638 STB" +#define D_SENSOR_MAX7219_DIN "MAX7219 DIN" +#define D_SENSOR_MAX7219_CS "MAX7219 CS" +#define D_SENSOR_MAX7219_CLK "MAX7219 CLK" #define D_SENSOR_HX711_SCK "HX711 SCK" #define D_SENSOR_HX711_DAT "HX711 DAT" #define D_SENSOR_FTC532 "FTC532" diff --git a/tasmota/language/uk_UA.h b/tasmota/language/uk_UA.h index 286b851dc..27527d226 100644 --- a/tasmota/language/uk_UA.h +++ b/tasmota/language/uk_UA.h @@ -643,6 +643,9 @@ #define D_SENSOR_TM1638_CLK "TM1638 CLK" #define D_SENSOR_TM1638_DIO "TM1638 DIO" #define D_SENSOR_TM1638_STB "TM1638 STB" +#define D_SENSOR_MAX7219_DIN "MAX7219 DIN" +#define D_SENSOR_MAX7219_CS "MAX7219 CS" +#define D_SENSOR_MAX7219_CLK "MAX7219 CLK" #define D_SENSOR_HX711_SCK "HX711 SCK" #define D_SENSOR_HX711_DAT "HX711 DAT" #define D_SENSOR_FTC532 "FTC532" diff --git a/tasmota/language/vi_VN.h b/tasmota/language/vi_VN.h index c04e43010..5b9b2c9c2 100644 --- a/tasmota/language/vi_VN.h +++ b/tasmota/language/vi_VN.h @@ -643,6 +643,9 @@ #define D_SENSOR_TM1638_CLK "TM1638 CLK" #define D_SENSOR_TM1638_DIO "TM1638 DIO" #define D_SENSOR_TM1638_STB "TM1638 STB" +#define D_SENSOR_MAX7219_DIN "MAX7219 DIN" +#define D_SENSOR_MAX7219_CS "MAX7219 CS" +#define D_SENSOR_MAX7219_CLK "MAX7219 CLK" #define D_SENSOR_HX711_SCK "HX711 SCK" #define D_SENSOR_HX711_DAT "HX711 DAT" #define D_SENSOR_FTC532 "FTC532" diff --git a/tasmota/language/zh_CN.h b/tasmota/language/zh_CN.h index a7e1847ca..9f99d4cf8 100644 --- a/tasmota/language/zh_CN.h +++ b/tasmota/language/zh_CN.h @@ -643,6 +643,9 @@ #define D_SENSOR_TM1638_CLK "TM1638 CLK" #define D_SENSOR_TM1638_DIO "TM1638 DIO" #define D_SENSOR_TM1638_STB "TM1638 STB" +#define D_SENSOR_MAX7219_DIN "MAX7219 DIN" +#define D_SENSOR_MAX7219_CS "MAX7219 CS" +#define D_SENSOR_MAX7219_CLK "MAX7219 CLK" #define D_SENSOR_HX711_SCK "HX711 SCK" #define D_SENSOR_HX711_DAT "HX711 DAT" #define D_SENSOR_FTC532 "FTC532" diff --git a/tasmota/language/zh_TW.h b/tasmota/language/zh_TW.h index 13cc6e858..cfeed1ff7 100644 --- a/tasmota/language/zh_TW.h +++ b/tasmota/language/zh_TW.h @@ -643,6 +643,9 @@ #define D_SENSOR_TM1638_CLK "TM1638 CLK" #define D_SENSOR_TM1638_DIO "TM1638 DIO" #define D_SENSOR_TM1638_STB "TM1638 STB" +#define D_SENSOR_MAX7219_DIN "MAX7219 DIN" +#define D_SENSOR_MAX7219_CS "MAX7219 CS" +#define D_SENSOR_MAX7219_CLK "MAX7219 CLK" #define D_SENSOR_HX711_SCK "HX711 SCK" #define D_SENSOR_HX711_DAT "HX711 DAT" #define D_SENSOR_FTC532 "FTC532" diff --git a/tasmota/tasmota_configurations.h b/tasmota/tasmota_configurations.h index c4956bdbd..fa25e67f0 100644 --- a/tasmota/tasmota_configurations.h +++ b/tasmota/tasmota_configurations.h @@ -306,6 +306,7 @@ #define USE_DISPLAY // Add Display Support (+2k code) #define USE_DISPLAY_TM1637 // [DisplayModel 15] Enable TM1637 module + #define USE_DISPLAY_MAX7219 // [DisplayModel 16] Enable MAX7219 7-segment module #define USE_I2C // I2C using library wire (+10k code, 0k2 mem, 124 iram) #define USE_DISPLAY_MODES1TO5 // Enable display mode 1 to 5 in addition to mode 0 diff --git a/tasmota/tasmota_template.h b/tasmota/tasmota_template.h index 197596b7b..4bdeee62d 100644 --- a/tasmota/tasmota_template.h +++ b/tasmota/tasmota_template.h @@ -155,6 +155,7 @@ enum UserSelectablePins { GPIO_XPT2046_CS, // XPT2046 SPI Chip Select GPIO_CSE7761_TX, GPIO_CSE7761_RX, // CSE7761 Serial interface (Dual R3) GPIO_VL53L0X_XSHUT1, // VL53L0X_XSHUT (the max number of sensors is VL53L0X_MAX_SENSORS)- Used when connecting multiple VL53L0X + GPIO_MAX7219CLK, GPIO_MAX7219DIN, GPIO_MAX7219CS, // MAX7219 interface GPIO_SENSOR_END }; enum ProgramSelectablePins { @@ -330,6 +331,7 @@ const char kSensorNames[] PROGMEM = D_SENSOR_XPT2046_CS "|" D_SENSOR_CSE7761_TX "|" D_SENSOR_CSE7761_RX "|" D_SENSOR_VL53L0X_XSHUT "|" + D_SENSOR_MAX7219_CLK "|" D_SENSOR_MAX7219_DIN "|" D_SENSOR_MAX7219_CS "|" ; const char kSensorNamesFixed[] PROGMEM = @@ -789,8 +791,13 @@ const uint16_t kGpioNiceList[] PROGMEM = { #endif #ifdef USE_VL53L0X AGPIO(GPIO_VL53L0X_XSHUT1) + VL53L0X_MAX_SENSORS, // When using multiple VL53L0X. -#endif +#endif +#ifdef USE_DISPLAY_MAX7219 + AGPIO(GPIO_MAX7219CLK), + AGPIO(GPIO_MAX7219DIN), + AGPIO(GPIO_MAX7219CS), +#endif // USE_DISPLAY_MAX7219 /*-------------------------------------------------------------------------------------------*\ * ESP32 specifics \*-------------------------------------------------------------------------------------------*/ diff --git a/tasmota/xdrv_13_display.ino b/tasmota/xdrv_13_display.ino index cf5e384eb..0377e5cf2 100755 --- a/tasmota/xdrv_13_display.ino +++ b/tasmota/xdrv_13_display.ino @@ -1864,15 +1864,9 @@ void CmndDisplayScrollText(void) void CmndDisplaySize(void) { -#ifdef USE_DISPLAY_TM1637 - if ((XdrvMailbox.payload > 0) && (XdrvMailbox.payload <= 6)) { -#else - if ((XdrvMailbox.payload > 0) && (XdrvMailbox.payload <= 4)) { -#endif - Settings.display_size = XdrvMailbox.payload; - if (renderer) renderer->setTextSize(Settings.display_size); - //else DisplaySetSize(Settings.display_size); - } + Settings.display_size = XdrvMailbox.payload; + if (renderer) renderer->setTextSize(Settings.display_size); + //else DisplaySetSize(Settings.display_size); ResponseCmndNumber(Settings.display_size); } diff --git a/tasmota/xdsp_15_tm1637.ino b/tasmota/xdsp_15_tm1637.ino index 0b507fce5..e2c5ae8ea 100644 --- a/tasmota/xdsp_15_tm1637.ino +++ b/tasmota/xdsp_15_tm1637.ino @@ -21,7 +21,7 @@ #ifdef USE_DISPLAY_TM1637 /*********************************************************************************************\ This driver enables the display of numbers (both integers and floats) and basic text - on the inexpensive TM1637- and TM1638-based seven-segment modules. + on the inexpensive TM1637-, TM1638- and MAX7219-based seven-segment modules. Raw segments can also be displayed. @@ -45,14 +45,24 @@ CLK hardware pin --> "TM1638 CLK" STB hardware pin --> "TM1638 STB" + For MAX7219: + Connect the MAX7219 display module's pins to any free GPIOs of the ESP8266 module + and assign the pins as follows from Tasmota's GUI: - Once the GPIO configuration is saved and the ESP8266/ESP32 module restarts, set the Display Model to 15 - using the command "DisplayModel 15" + DIN hardware pin --> "MAX7219 DIN" + CS hardware pin --> "MAX7219 CS" + CLK hardware pin --> "MAX7219 CLK" - If your display is a TM1637 with 6 digits, set Display Columns to the number of digits your - display has, using the command "DisplayCols 6" and restart the ESP module. + Once the GPIO configuration is saved and the ESP8266/ESP32 module restarts, + set the Display Model to 15 and Display Mode to 0 + using the command "Backlog DisplayModel 15 ; DisplayMode 0" - After the ESP8266/ESP32 module restarts again, the following "Display" commands can be used: + If your display is a TM1637 with 6 digits, set Display Width to the number of digits your + display has, using the command "DisplayWidth 6". + + After the ESP8266/ESP32 module restarts again, turn ON the display with the command "Power 1" + + Now, the following "Display" commands can be used: DisplayClear @@ -136,63 +146,83 @@ "DisplayClock 0" // turn off clock +In addition, setting DisplayMode to 1 shows the time, setting it to 2 shows the date +and setting it to 3 alternates between time and date. + \*********************************************************************************************/ -#define XDSP_15 15 +#define XDSP_15 15 + +#define CMD_MAX_LEN 55 +#define LEVEL_MIN 0 +#define LEVEL_MAX 100 +#define SCROLL_MAX_LEN 50 +#define POSITION_MIN 0 +#define POSITION_MAX 8 +#define LED_MIN 0 +#define LED_MAX 255 +#define MAX7219_ADDR 0 -#define CMD_MAX_LEN 55 -#define LEVEL_MIN 0 -#define LEVEL_MAX 100 -#define SCROLL_MAX_LEN 50 -#define POSITION_MIN 0 -#define POSITION_MAX 8 -#define LED_MIN 0 -#define LED_MAX 255 #include "SevenSegmentTM1637.h" #include +#include SevenSegmentTM1637 *tm1637display; TM1638plus *tm1638display; +LedControl *max7219display; -enum display_types { TM1637, TM1638 }; +enum display_types +{ + TM1637, + TM1638, + MAX7219 +}; -struct { +struct +{ char scroll_text[CMD_MAX_LEN]; char msg[60]; char model_name[8]; uint8_t scroll_delay = 4; uint8_t scroll_index = 0; uint8_t iteration = 0; - uint8_t buttons; uint8_t display_type = TM1637; - uint8_t prev_buttons; bool init_done = false; bool scroll = false; bool show_clock = false; bool clock_24 = false; - bool LED[8] = {false, false, false, false, false, false, false, false}; } TM1637Data; /*********************************************************************************************\ * Init function \*********************************************************************************************/ -void TM1637Init(void) { - if (PinUsed(GPIO_TM1638CLK) && PinUsed(GPIO_TM1638DIO) && PinUsed(GPIO_TM1638STB)) { +void TM1637Init(void) +{ + if (PinUsed(GPIO_TM1638CLK) && PinUsed(GPIO_TM1638DIO) && PinUsed(GPIO_TM1638STB)) + { TM1637Data.display_type = TM1638; Settings.display_width = 8; } - else if (PinUsed(GPIO_TM1637CLK) && PinUsed(GPIO_TM1637DIO)) { + else if (PinUsed(GPIO_TM1637CLK) && PinUsed(GPIO_TM1637DIO)) + { TM1637Data.display_type = TM1637; - if ((!Settings.display_width || Settings.display_width > 6)) { + if ((!Settings.display_width || Settings.display_width > 6)) + { Settings.display_width = 4; } } - else { + else if (PinUsed(GPIO_MAX7219DIN) && PinUsed(GPIO_MAX7219CLK) && PinUsed(GPIO_MAX7219CS)) + { + TM1637Data.display_type = MAX7219; + Settings.display_width = 8; + } + else + { return; } @@ -200,30 +230,73 @@ void TM1637Init(void) { Settings.display_cols[0] = Settings.display_width; Settings.display_height = 1; Settings.display_rows = Settings.display_height; + if(!Settings.display_dimmer || Settings.display_dimmer < 2 || Settings.display_dimmer > 15) Settings.display_dimmer = 8; - if (TM1637 == TM1637Data.display_type) { + if (TM1637 == TM1637Data.display_type) + { strcpy_P(TM1637Data.model_name, PSTR("TM1637")); tm1637display = new SevenSegmentTM1637(Pin(GPIO_TM1637CLK), Pin(GPIO_TM1637DIO)); tm1637display->begin(Settings.display_width, 1); } - else if (TM1638 == TM1637Data.display_type) { + else if (TM1638 == TM1637Data.display_type) + { strcpy_P(TM1637Data.model_name, PSTR("TM1638")); - tm1638display = new TM1638plus(Pin(GPIO_TM1638STB), Pin(GPIO_TM1638CLK), Pin(GPIO_TM1638DIO), true ); + tm1638display = new TM1638plus(Pin(GPIO_TM1638STB), Pin(GPIO_TM1638CLK), Pin(GPIO_TM1638DIO), true); tm1638display->displayBegin(); } + else if (MAX7219 == TM1637Data.display_type) + { + strcpy_P(TM1637Data.model_name, PSTR("MAX7219")); + max7219display = new LedControl(Pin(GPIO_MAX7219DIN), Pin(GPIO_MAX7219CLK), Pin(GPIO_MAX7219CS), 1); + max7219display->shutdown(MAX7219_ADDR, false); + } TM1637ClearDisplay(); TM1637Dim(); TM1637Data.init_done = true; AddLog(LOG_LEVEL_INFO, PSTR("DSP: %s with %d digits"), TM1637Data.model_name, Settings.display_width); } +// Function to display specified ascii char at specified position for MAX7219 +void displayMAX7219ASCII(uint8_t pos, char c) +{ + pos = 7 - pos; + max7219display->setChar(MAX7219_ADDR, pos, c, false); +} + +// Function to display specified ascii char with dot at specified position for MAX7219 +void displayMAX7219ASCIIwDot(uint8_t pos, char c) +{ + pos = 7 - pos; + max7219display->setChar(MAX7219_ADDR, pos, c, true); +} + +// Function to display raw segments at specified position for MAX7219 +void displayMAX72197Seg(uint8_t pos, uint8_t seg) +{ + bool dec_bit = seg & 128; + seg = seg << 1; + seg = seg | dec_bit; + uint8_t NO_OF_BITS = 8; + uint8_t reverse_num = 0; + for (uint8_t i = 0; i < NO_OF_BITS; i++) + { + if ((seg & (1 << i))) + reverse_num |= 1 << ((NO_OF_BITS - 1) - i); + } + seg = reverse_num; + + pos = 7 - pos; + max7219display->setRow(MAX7219_ADDR, pos, seg); +} + /*********************************************************************************************\ * Displays number without decimal, with/without leading zeros, specifying start-position * and length, optionally skipping clearing display before displaying the number. * commands: DisplayNumber num [,position {0-(Settings.display_width-1)} [,leading_zeros {0|1} [,length {1 to Settings.display_width}]]] * DisplayNumberNC num [,position {0-(Settings.display_width-1)} [,leading_zeros {0|1} [,length {1 to Settings.display_width}]]] // "NC" --> "No Clear" \*********************************************************************************************/ -bool CmndTM1637Number(bool clear) { +bool CmndTM1637Number(bool clear) +{ char sNum[CMD_MAX_LEN]; char sLeadingzeros[CMD_MAX_LEN]; char sPosition[CMD_MAX_LEN]; @@ -236,47 +309,79 @@ bool CmndTM1637Number(bool clear) { switch (ArgC()) { - case 4 : - subStr(sLength, XdrvMailbox.data, ",", 4); - length = atoi(sLength); - case 3 : - subStr(sLeadingzeros, XdrvMailbox.data, ",", 3); - leadingzeros = atoi(sLeadingzeros); - case 2 : - subStr(sPosition, XdrvMailbox.data, ",", 2); - position = atoi(sPosition); - case 1 : - subStr(sNum, XdrvMailbox.data, ",", 1); - num = atof(sNum); + case 4: + subStr(sLength, XdrvMailbox.data, ",", 4); + length = atoi(sLength); + case 3: + subStr(sLeadingzeros, XdrvMailbox.data, ",", 3); + leadingzeros = atoi(sLeadingzeros); + case 2: + subStr(sPosition, XdrvMailbox.data, ",", 2); + position = atoi(sPosition); + case 1: + subStr(sNum, XdrvMailbox.data, ",", 1); + num = atof(sNum); } - - if((position < 0) || (position > (Settings.display_width-1))) position = 0; + if ((position < 0) || (position > (Settings.display_width - 1))) + position = 0; AddLog(LOG_LEVEL_DEBUG, PSTR("TM7: num %d, pos %d, lead %d, len %d"), num, position, leadingzeros, length); - if(clear) TM1637ClearDisplay(); + if (clear) + TM1637ClearDisplay(); char txt[30]; snprintf_P(txt, sizeof(txt), PSTR("%d"), num); - if(!length) length = strlen(txt); - if((length < 0) || (length > Settings.display_width)) length = Settings.display_width; + if (!length) + length = strlen(txt); + if ((length < 0) || (length > Settings.display_width)) + length = Settings.display_width; - char pad = (leadingzeros ? '0': ' '); + char pad = (leadingzeros ? '0' : ' '); uint32_t i = position; uint8_t rawBytes[1]; - for(; iSettings.display_width) break; - if(TM1637Data.display_type == TM1637) { rawBytes[0] = tm1637display->encode(pad); tm1637display->printRaw(rawBytes, 1, i); } - else if(TM1637Data.display_type == TM1638) tm1638display->displayASCII(i, pad); + for (; i < position + (length - strlen(txt)); i++) + { + if (i > Settings.display_width) + break; + if (TM1637 == TM1637Data.display_type) + { + rawBytes[0] = tm1637display->encode(pad); + tm1637display->printRaw(rawBytes, 1, i); + } + else if (TM1638 == TM1637Data.display_type) + tm1638display->displayASCII(i, pad); + else if (MAX7219 == TM1637Data.display_type) + { + if (i > 7) + break; + displayMAX7219ASCII(i, pad); + } } - for(uint32_t j = 0; i< position + length; i++, j++) { - if(i>Settings.display_width) break; - if(txt[j] == 0) break; - if(TM1637Data.display_type == TM1637) { rawBytes[0] = tm1637display->encode(txt[j]); tm1637display->printRaw(rawBytes, 1, i); } - else if(TM1637Data.display_type == TM1638) tm1638display->displayASCII(i, txt[j]); + for (uint32_t j = 0; i < position + length; i++, j++) + { + if (i > Settings.display_width) + break; + if (txt[j] == 0) + break; + if (TM1637 == TM1637Data.display_type) + { + rawBytes[0] = tm1637display->encode(txt[j]); + tm1637display->printRaw(rawBytes, 1, i); + } + else if (TM1638 == TM1637Data.display_type) + tm1638display->displayASCII(i, txt[j]); + else if (MAX7219 == TM1637Data.display_type) + { + if (i > 7) + break; + if (txt[j] == 0) + break; + displayMAX7219ASCII(i, txt[j]); + } } return true; @@ -288,7 +393,8 @@ bool CmndTM1637Number(bool clear) { * commands: DisplayFloat num [,position {0-(Settings.display_width-1)} [,precision {0-Settings.display_width} [,length {1 to Settings.display_width}]]] * DisplayFloatNC num [,position {0-(Settings.display_width-1)} [,precision {0-Settings.display_width} [,length {1 to Settings.display_width}]]] // "NC" --> "No Clear" \*********************************************************************************************/ -bool CmndTM1637Float(bool clear) { +bool CmndTM1637Float(bool clear) +{ char sNum[CMD_MAX_LEN]; char sPrecision[CMD_MAX_LEN]; @@ -302,102 +408,148 @@ bool CmndTM1637Float(bool clear) { switch (ArgC()) { - case 4 : - subStr(sLength, XdrvMailbox.data, ",", 4); - length = atoi(sLength); - case 3 : - subStr(sPrecision, XdrvMailbox.data, ",", 3); - precision = atoi(sPrecision); - case 2 : - subStr(sPosition, XdrvMailbox.data, ",", 2); - position = atoi(sPosition); - case 1 : - subStr(sNum, XdrvMailbox.data, ",", 1); - fnum = atof(sNum); + case 4: + subStr(sLength, XdrvMailbox.data, ",", 4); + length = atoi(sLength); + case 3: + subStr(sPrecision, XdrvMailbox.data, ",", 3); + precision = atoi(sPrecision); + case 2: + subStr(sPosition, XdrvMailbox.data, ",", 2); + position = atoi(sPosition); + case 1: + subStr(sNum, XdrvMailbox.data, ",", 1); + fnum = atof(sNum); } + if ((position < 0) || (position > (Settings.display_width - 1))) + position = 0; + if ((precision < 0) || (precision > Settings.display_width)) + precision = Settings.display_width; - if((position < 0) || (position > (Settings.display_width-1))) position = 0; - if((precision < 0) || (precision > Settings.display_width)) precision = Settings.display_width; - - if(clear) TM1637ClearDisplay(); + if (clear) + TM1637ClearDisplay(); char txt[30]; ext_snprintf_P(txt, sizeof(txt), PSTR("%*_f"), precision, &fnum); - if(!length) length = strlen(txt); - if((length <= 0) || (length > Settings.display_width)) length = Settings.display_width; + if (!length) + length = strlen(txt); + if ((length <= 0) || (length > Settings.display_width)) + length = Settings.display_width; AddLog(LOG_LEVEL_DEBUG, PSTR("TM7: num %4_f, prec %d, len %d"), &fnum, precision, length); - if(TM1637Data.display_type == TM1637) { + if (TM1637 == TM1637Data.display_type) + { uint8_t rawBytes[1]; - for(uint32_t i=0, j=0; iencode(txt[i]); - if(txt[i+1] == '.') { + if (txt[i + 1] == '.') + { rawBytes[0] = rawBytes[0] | 128; i++; length++; } - if((j+position) > Settings.display_width) break; - tm1637display->printRaw(rawBytes, 1, j+position); + if ((j + position) > Settings.display_width) + break; + tm1637display->printRaw(rawBytes, 1, j + position); } - } else if(TM1637Data.display_type == TM1638) { - for(uint32_t i=0, j=0; i 7) break; - if(txt[i] == 0) break; - if(txt[i+1] == '.') { - tm1638display->displayASCIIwDot(j+position, txt[i]); + } + else if (TM1638 == TM1637Data.display_type) + { + for (uint32_t i = 0, j = 0; i < length; i++, j++) + { + if ((j + position) > 7) + break; + if (txt[i] == 0) + break; + if (txt[i + 1] == '.') + { + tm1638display->displayASCIIwDot(j + position, txt[i]); i++; length++; } - else tm1638display->displayASCII(j+position, txt[i]); + else + tm1638display->displayASCII(j + position, txt[i]); + } + } + else if (MAX7219 == TM1637Data.display_type) + { + for (uint32_t i = 0, j = 0; i < length; i++, j++) + { + if ((j + position) > 7) + break; + if (txt[i] == 0) + break; + if (txt[i + 1] == '.') + { + displayMAX7219ASCIIwDot(j + position, txt[i]); + i++; + length++; + } + else + displayMAX7219ASCII(j + position, txt[i]); } } return true; } - // /*********************************************************************************************\ // * Clears the display // * Command: DisplayClear // \*********************************************************************************************/ -bool CmndTM1637Clear(void) { +bool CmndTM1637Clear(void) +{ TM1637ClearDisplay(); sprintf(TM1637Data.msg, PSTR("Cleared")); XdrvMailbox.data = TM1637Data.msg; return true; } - // /*********************************************************************************************\ // * Clears the display // \*********************************************************************************************/ -void TM1637ClearDisplay (void) { - if(TM1637Data.display_type == TM1637) { - unsigned char arr[] = {0}; - for(int i=0; iprintRaw(arr, 1, i); - } else if(TM1637Data.display_type == TM1638) { - for(int i=0; idisplay7Seg(i, 0); +void TM1637ClearDisplay(void) +{ + if (TM1637 == TM1637Data.display_type) + { + unsigned char arr[] = {0}; + for (int i = 0; i < Settings.display_width; i++) + tm1637display->printRaw(arr, 1, i); + } + else if (TM1638 == TM1637Data.display_type) + { + for (int i = 0; i < Settings.display_width; i++) + tm1638display->display7Seg(i, 0); + } + else if (MAX7219 == TM1637Data.display_type) + { + max7219display->clearDisplay(MAX7219_ADDR); } } - /*********************************************************************************************\ * Display scrolling text * Command: DisplayTM1637Data.scroll_text text \*********************************************************************************************/ -bool CmndTM1637ScrollText(void) { +bool CmndTM1637ScrollText(void) +{ AddLog(LOG_LEVEL_DEBUG, PSTR("TM7: Text %s"), XdrvMailbox.data); - if(XdrvMailbox.data_len > SCROLL_MAX_LEN) { + if (XdrvMailbox.data_len > SCROLL_MAX_LEN) + { snprintf(TM1637Data.msg, sizeof(TM1637Data.msg), PSTR("Text too long. Length should be less than %d"), SCROLL_MAX_LEN); XdrvMailbox.data = TM1637Data.msg; return false; - } else { + } + else + { snprintf(TM1637Data.scroll_text, sizeof(TM1637Data.scroll_text), PSTR(" ")); snprintf(TM1637Data.scroll_text, sizeof(TM1637Data.scroll_text), PSTR("%s"), XdrvMailbox.data); TM1637Data.scroll_text[XdrvMailbox.data_len] = 0; @@ -405,65 +557,85 @@ bool CmndTM1637ScrollText(void) { TM1637Data.scroll = true; return true; } - } - - /*********************************************************************************************\ * Sets the scroll delay for scrolling text. * Command: DisplayTM1637Data.scroll_delay delay {0-15} // default = 4 \*********************************************************************************************/ -bool CmndTM1637ScrollDelay(void) { - if(ArgC() == 0) { +bool CmndTM1637ScrollDelay(void) +{ + if (ArgC() == 0) + { XdrvMailbox.payload = TM1637Data.scroll_delay; return true; } - if(TM1637Data.scroll_delay<0) TM1637Data.scroll_delay=0; + if (TM1637Data.scroll_delay < 0) + TM1637Data.scroll_delay = 0; TM1637Data.scroll_delay = XdrvMailbox.payload; return true; } - - /*********************************************************************************************\ * Scrolls a given string. Called every 50ms \*********************************************************************************************/ -void TM1637ScrollText(void) { +void TM1637ScrollText(void) +{ TM1637Data.iteration++; - if(TM1637Data.scroll_delay) TM1637Data.iteration = TM1637Data.iteration % TM1637Data.scroll_delay; - else TM1637Data.iteration = 0; - if(TM1637Data.iteration) return; + if (TM1637Data.scroll_delay) + TM1637Data.iteration = TM1637Data.iteration % TM1637Data.scroll_delay; + else + TM1637Data.iteration = 0; + if (TM1637Data.iteration) + return; - if(TM1637Data.scroll_index > strlen(TM1637Data.scroll_text)) { - TM1637Data.scroll= false; + if (TM1637Data.scroll_index > strlen(TM1637Data.scroll_text)) + { + TM1637Data.scroll = false; TM1637Data.scroll_index = 0; return; } uint8_t rawBytes[1]; - for(uint32_t i=0, j=TM1637Data.scroll_index; i< 1 + strlen(TM1637Data.scroll_text); i++, j++) { - if(i > (Settings.display_width-1)) { break; } + for (uint32_t i = 0, j = TM1637Data.scroll_index; i < 1 + strlen(TM1637Data.scroll_text); i++, j++) + { + if (i > (Settings.display_width - 1)) + { + break; + } rawBytes[0] = tm1637display->encode(TM1637Data.scroll_text[j]); bool dotSkipped = false; - if(TM1637Data.scroll_text[j+1] == '.') { + if (TM1637Data.scroll_text[j + 1] == '.') + { dotSkipped = true; rawBytes[0] = rawBytes[0] | 128; j++; - } else if(TM1637Data.scroll_text[j] == '^') { + } + else if (TM1637Data.scroll_text[j] == '^') + { rawBytes[0] = 1 | 2 | 32 | 64; } - if(!dotSkipped && TM1637Data.scroll_text[j] == '.') { + if (!dotSkipped && TM1637Data.scroll_text[j] == '.') + { j++; TM1637Data.scroll_index++; rawBytes[0] = tm1637display->encode(TM1637Data.scroll_text[j]); } - if(TM1637Data.scroll_text[j+1] == '.') { rawBytes[0] = rawBytes[0] | 128; } - if(TM1637Data.display_type == TM1637) { + if (TM1637Data.scroll_text[j + 1] == '.') + { + rawBytes[0] = rawBytes[0] | 128; + } + if (TM1637 == TM1637Data.display_type) + { tm1637display->printRaw(rawBytes, 1, i); - } else if(TM1637Data.display_type == TM1638) { + } + else if (TM1638 == TM1637Data.display_type) + { tm1638display->display7Seg(i, rawBytes[0]); } - + else if (MAX7219 == TM1637Data.display_type) + { + displayMAX72197Seg(i, rawBytes[0]); + } } TM1637Data.scroll_index++; } @@ -472,14 +644,16 @@ void TM1637ScrollText(void) { * Displays a horizontal bar graph. Takes a percentage number (0-100) as input * Command: DisplayLevel level {0-100} \*********************************************************************************************/ -bool CmndTM1637Level(void) { +bool CmndTM1637Level(void) +{ uint16_t val = XdrvMailbox.payload; - if((val < LEVEL_MIN) || (val > LEVEL_MAX)) { + if ((val < LEVEL_MIN) || (val > LEVEL_MAX)) + { Response_P(PSTR("{\"Error\":\"Level should be a number in the range [%d, %d]\"}"), LEVEL_MIN, LEVEL_MAX); return false; } - uint8_t totalBars = 2*Settings.display_width; + uint8_t totalBars = 2 * Settings.display_width; AddLog(LOG_LEVEL_DEBUG, PSTR("TM7: TM1637Data.model_name %s CmndTM1637Level totalBars=%d"), TM1637Data.model_name, totalBars); float barsToDisplay = totalBars * val / 100.0f; char txt[5]; @@ -492,16 +666,23 @@ bool CmndTM1637Level(void) { TM1637ClearDisplay(); uint8_t rawBytes[1]; - for(int i=1; i<=numBars; i++) { - uint8_t digit = (i-1) / 2; - uint8_t value = (((i%2) == 0) ? 54 : 48); - if(TM1637Data.display_type == TM1637) { + for (int i = 1; i <= numBars; i++) + { + uint8_t digit = (i - 1) / 2; + uint8_t value = (((i % 2) == 0) ? 54 : 48); + if (TM1637 == TM1637Data.display_type) + { rawBytes[0] = value; tm1637display->printRaw(rawBytes, 1, digit); - } else if(TM1637Data.display_type == TM1638) { + } + else if (TM1638 == TM1637Data.display_type) + { tm1638display->display7Seg(digit, value); } - + else if (MAX7219 == TM1637Data.display_type) + { + displayMAX72197Seg(digit, value); + } } return true; } @@ -514,8 +695,9 @@ bool CmndTM1637Level(void) { * bit 1 is segment B etc. The function may either set the entire display * or any desired part using the length and position parameters. \*********************************************************************************************/ -bool CmndTM1637Raw(void) { - uint8_t DATA[6] = { 0, 0, 0, 0, 0, 0 }; +bool CmndTM1637Raw(void) +{ + uint8_t DATA[6] = {0, 0, 0, 0, 0, 0}; char as[CMD_MAX_LEN]; char bs[CMD_MAX_LEN]; @@ -527,60 +709,76 @@ bool CmndTM1637Raw(void) { char sLength[CMD_MAX_LEN]; char sPos[CMD_MAX_LEN]; - uint32_t position = 0; uint32_t length = 0; switch (ArgC()) { - case 8 : - subStr(fs, XdrvMailbox.data, ",", 8); - DATA[5] = atoi(fs); - case 7 : - subStr(es, XdrvMailbox.data, ",", 7); - DATA[4] = atoi(es); - case 6 : - subStr(ds, XdrvMailbox.data, ",", 6); - DATA[3] = atoi(ds); - case 5 : - subStr(cs, XdrvMailbox.data, ",", 5); - DATA[2] = atoi(cs); - case 4 : - subStr(bs, XdrvMailbox.data, ",", 4); - DATA[1] = atoi(bs); - case 3 : - subStr(as, XdrvMailbox.data, ",", 3); - DATA[0] = atoi(as); - case 2 : - subStr(sLength, XdrvMailbox.data, ",", 2); - length = atoi(sLength); - case 1 : - subStr(sPos, XdrvMailbox.data, ",", 1); - position = atoi(sPos); + case 8: + subStr(fs, XdrvMailbox.data, ",", 8); + DATA[5] = atoi(fs); + case 7: + subStr(es, XdrvMailbox.data, ",", 7); + DATA[4] = atoi(es); + case 6: + subStr(ds, XdrvMailbox.data, ",", 6); + DATA[3] = atoi(ds); + case 5: + subStr(cs, XdrvMailbox.data, ",", 5); + DATA[2] = atoi(cs); + case 4: + subStr(bs, XdrvMailbox.data, ",", 4); + DATA[1] = atoi(bs); + case 3: + subStr(as, XdrvMailbox.data, ",", 3); + DATA[0] = atoi(as); + case 2: + subStr(sLength, XdrvMailbox.data, ",", 2); + length = atoi(sLength); + case 1: + subStr(sPos, XdrvMailbox.data, ",", 1); + position = atoi(sPos); } - if(!length) length = ArgC() - 2; - if(length < 0 || length > Settings.display_width) length = Settings.display_width; - if(position < 0 || position > (Settings.display_width-1)) position = 0; + if (!length) + length = ArgC() - 2; + if (length < 0 || length > Settings.display_width) + length = Settings.display_width; + if (position < 0 || position > (Settings.display_width - 1)) + position = 0; AddLog(LOG_LEVEL_DEBUG, PSTR("TM7: a %d, b %d, c %d, d %d, e %d, f %d, len %d, pos %d"), - DATA[0], DATA[1], DATA[2], DATA[3], DATA[4], DATA[5], length, position); + DATA[0], DATA[1], DATA[2], DATA[3], DATA[4], DATA[5], length, position); - if(TM1637Data.display_type == TM1637) { + if (TM1637 == TM1637Data.display_type) + { uint8_t rawBytes[1]; - for(uint32_t i=position; i(Settings.display_width-1)) break; - rawBytes[0] = DATA[i-position]; + for (uint32_t i = position; i < position + length; i++) + { + if (i > (Settings.display_width - 1)) + break; + rawBytes[0] = DATA[i - position]; tm1637display->printRaw(rawBytes, 1, i); } - } else if(TM1637Data.display_type == TM1638) { - for(uint32_t i=position; i7) break; - tm1638display->display7Seg(i, DATA[i-position]); + } + else if (TM1638 == TM1637Data.display_type) + { + for (uint32_t i = position; i < position + length; i++) + { + if (i > 7) + break; + tm1638display->display7Seg(i, DATA[i - position]); + } + } + else if (MAX7219 == TM1637Data.display_type) + { + for (uint32_t i = position; i < position + length; i++) + { + if (i > 7) + break; + displayMAX72197Seg(i, DATA[i - position]); } } - - return true; } @@ -590,7 +788,8 @@ bool CmndTM1637Raw(void) { * position parameters without affecting the rest of the display. * Command: DisplayText text [, position {0-(Settings.display_width-1)} [,length {1 to Settings.display_width}]] \*********************************************************************************************/ -bool CmndTM1637Text(bool clear) { +bool CmndTM1637Text(bool clear) +{ char sString[CMD_MAX_LEN + 1]; char sPosition[CMD_MAX_LEN]; char sLength[CMD_MAX_LEN]; @@ -599,74 +798,126 @@ bool CmndTM1637Text(bool clear) { switch (ArgC()) { - case 3 : - subStr(sLength, XdrvMailbox.data, ",", 3); - length = atoi(sLength); - case 2 : - subStr(sPosition, XdrvMailbox.data, ",", 2); - position = atoi(sPosition); - case 1 : - subStr(sString, XdrvMailbox.data, ",", 1); + case 3: + subStr(sLength, XdrvMailbox.data, ",", 3); + length = atoi(sLength); + case 2: + subStr(sPosition, XdrvMailbox.data, ",", 2); + position = atoi(sPosition); + case 1: + subStr(sString, XdrvMailbox.data, ",", 1); } - - if((position < 0) || (position > (Settings.display_width-1))) position = 0; + if ((position < 0) || (position > (Settings.display_width - 1))) + position = 0; AddLog(LOG_LEVEL_DEBUG, PSTR("TM7: sString %s, pos %d, len %d"), sString, position, length); - if(clear) TM1637ClearDisplay(); + if (clear) + TM1637ClearDisplay(); - if(!length) length = strlen(sString); - if((length < 0) || (length > Settings.display_width)) length = Settings.display_width; + if (!length) + length = strlen(sString); + if ((length < 0) || (length > Settings.display_width)) + length = Settings.display_width; uint32_t i = position; - if(TM1637Data.display_type == TM1637) { + if (TM1637 == TM1637Data.display_type) + { uint8_t rawBytes[1]; - for(uint32_t j = 0; i< position + length; i++, j++) { - if(i > (Settings.display_width-1)) break; - if(sString[j] == 0) break; + for (uint32_t j = 0; i < position + length; i++, j++) + { + if (i > (Settings.display_width - 1)) + break; + if (sString[j] == 0) + break; rawBytes[0] = tm1637display->encode(sString[j]); bool dotSkipped = false; - if(sString[j+1] == '.') { + if (sString[j + 1] == '.') + { dotSkipped = true; rawBytes[0] = rawBytes[0] | 128; j++; - } else if(sString[j] == '^') { + } + else if (sString[j] == '^') + { rawBytes[0] = 1 | 2 | 32 | 64; } - if(!dotSkipped && sString[j] == '.') rawBytes[0] = 128; + if (!dotSkipped && sString[j] == '.') + rawBytes[0] = 128; tm1637display->printRaw(rawBytes, 1, i); } - } else if(TM1637Data.display_type == TM1638) { - for(uint32_t j = 0; i< position + length; i++, j++) { - if(i > 7) break; - if(sString[j] == 0) break; - if(sString[j+1] == '.') { + } + else if (TM1638 == TM1637Data.display_type) + { + for (uint32_t j = 0; i < position + length; i++, j++) + { + if (i > 7) + break; + if (sString[j] == 0) + break; + if (sString[j + 1] == '.') + { tm1638display->displayASCIIwDot(i, sString[j]); j++; - } else if(sString[j] == '^') { + } + else if (sString[j] == '^') + { tm1638display->display7Seg(i, (1 | 2 | 32 | 64)); - } else tm1638display->displayASCII(i, sString[j]); + } + else + tm1638display->displayASCII(i, sString[j]); + } + } + else if (MAX7219 == TM1637Data.display_type) + { + uint8_t rawBytes[1]; + for (uint32_t j = 0; i < position + length; i++, j++) + { + if (i > 7) + break; + if (sString[j] == 0) + break; + rawBytes[0] = tm1637display->encode(sString[j]); + bool dotSkipped = false; + if (sString[j + 1] == '.') + { + dotSkipped = true; + rawBytes[0] = rawBytes[0] | 128; + j++; + } + else if (sString[j] == '^') + { + rawBytes[0] = 1 | 2 | 32 | 64; + } + if (!dotSkipped && sString[j] == '.') + rawBytes[0] = 128; + displayMAX72197Seg(i, rawBytes[0]); } } - return true; } - /*********************************************************************************************\ * Displays a clock. * Command: DisplayClock 1 // 12-hour format * DisplayClock 2 // 24-hour format * DisplayClock 0 // turn off clock and clear \*********************************************************************************************/ -bool CmndTM1637Clock(void) { +bool CmndTM1637Clock(void) +{ TM1637Data.show_clock = XdrvMailbox.payload; - if(ArgC() == 0) XdrvMailbox.payload = 1; - if(XdrvMailbox.payload > 1) TM1637Data.clock_24 = true; - else if(XdrvMailbox.payload == 1) TM1637Data.clock_24 = false; + if (ArgC() == 0) + XdrvMailbox.payload = 1; + if (XdrvMailbox.payload > 1) { + TM1637Data.clock_24 = true; + XdrvMailbox.payload = 2; + } else { + TM1637Data.clock_24 = false; + XdrvMailbox.payload = 1; + } AddLog(LOG_LEVEL_DEBUG, PSTR("TM7: TM1637Data.show_clock %d, TM1637Data.clock_24 %d"), TM1637Data.show_clock, TM1637Data.clock_24); @@ -674,110 +925,149 @@ bool CmndTM1637Clock(void) { return true; } - /*********************************************************************************************\ * refreshes the time if clock is displayed \*********************************************************************************************/ -void TM1637ShowTime() { +void TM1637ShowTime() +{ uint8_t hr = RtcTime.hour; uint8_t mn = RtcTime.minute; // uint8_t hr = 1; // uint8_t mn = 0; char z = ' '; - if(TM1637Data.clock_24) { + if (TM1637Data.clock_24) + { z = '0'; - } else { - if(hr > 12) hr -= 12; - if(hr == 0) hr = 12; + } + else + { + if (hr > 12) + hr -= 12; + if (hr == 0) + hr = 12; } char tm[5]; - if(hr < 10) { - if(mn < 10) snprintf(tm, sizeof(tm), PSTR("%c%d0%d"), z, hr, mn); - else snprintf(tm, sizeof(tm), PSTR("%c%d%d"), z, hr, mn); - } else { - if(mn < 10) snprintf(tm, sizeof(tm), PSTR("%d0%d"), hr, mn); - else snprintf(tm, sizeof(tm), PSTR("%d%d"), hr, mn); + if (hr < 10) + { + if (mn < 10) + snprintf(tm, sizeof(tm), PSTR("%c%d0%d"), z, hr, mn); + else + snprintf(tm, sizeof(tm), PSTR("%c%d%d"), z, hr, mn); + } + else + { + if (mn < 10) + snprintf(tm, sizeof(tm), PSTR("%d0%d"), hr, mn); + else + snprintf(tm, sizeof(tm), PSTR("%d%d"), hr, mn); } - if(TM1637Data.display_type == TM1637) { + if (TM1637 == TM1637Data.display_type) + { uint8_t rawBytes[1]; - for(uint32_t i = 0; i< 4; i++) { + for (uint32_t i = 0; i < 4; i++) + { rawBytes[0] = tm1637display->encode(tm[i]); - if((millis() % 1000) > 500 && (i == 1)) rawBytes[0] = rawBytes[0] | 128; + if ((millis() % 1000) > 500 && (i == 1)) + rawBytes[0] = rawBytes[0] | 128; tm1637display->printRaw(rawBytes, 1, i); } - } else if(TM1637Data.display_type == TM1638) { - for(uint32_t i = 0; i< 4; i++) { - if((millis() % 1000) > 500 && (i == 1)) tm1638display->displayASCIIwDot(i, tm[i]); - else tm1638display->displayASCII(i, tm[i]); + } + else if (TM1638 == TM1637Data.display_type) + { + for (uint32_t i = 0; i < 4; i++) + { + if ((millis() % 1000) > 500 && (i == 1)) + tm1638display->displayASCIIwDot(i, tm[i]); + else + tm1638display->displayASCII(i, tm[i]); + } + } + else if (MAX7219 == TM1637Data.display_type) + { + for (uint32_t i = 0; i < 4; i++) + { + if ((millis() % 1000) > 500 && (i == 1)) + displayMAX7219ASCIIwDot(i, tm[i]); + else + displayMAX7219ASCII(i, tm[i]); } } - } /*********************************************************************************************\ * This function is called for all Display functions. \*********************************************************************************************/ -bool TM1637MainFunc(uint8_t fn) { +bool TM1637MainFunc(uint8_t fn) +{ bool result = false; - if(XdrvMailbox.data_len > CMD_MAX_LEN) { + if (XdrvMailbox.data_len > CMD_MAX_LEN) + { Response_P(PSTR("{\"Error\":\"Command text too long. Please limit it to %d characters\"}"), CMD_MAX_LEN); return false; } - switch (fn) { - case FUNC_DISPLAY_CLEAR: - result = CmndTM1637Clear(); - break; - case FUNC_DISPLAY_NUMBER : - result = CmndTM1637Number(true); - break; - case FUNC_DISPLAY_NUMBERNC : - result = CmndTM1637Number(false); - break; - case FUNC_DISPLAY_FLOAT : - result = CmndTM1637Float(true); - break; - case FUNC_DISPLAY_FLOATNC : - result = CmndTM1637Float(false); - break; - case FUNC_DISPLAY_RAW: - result = CmndTM1637Raw(); - break; - case FUNC_DISPLAY_SEVENSEG_TEXT: - result = CmndTM1637Text(true); - break; - case FUNC_DISPLAY_SEVENSEG_TEXTNC: - result = CmndTM1637Text(false); - break; - case FUNC_DISPLAY_LEVEL: - result = CmndTM1637Level(); - break; - case FUNC_DISPLAY_SCROLLTEXT: - result = CmndTM1637ScrollText(); - break; - case FUNC_DISPLAY_SCROLLDELAY: - result = CmndTM1637ScrollDelay(); - break; - case FUNC_DISPLAY_CLOCK: - result = CmndTM1637Clock(); - break; + switch (fn) + { + case FUNC_DISPLAY_CLEAR: + result = CmndTM1637Clear(); + break; + case FUNC_DISPLAY_NUMBER: + result = CmndTM1637Number(true); + break; + case FUNC_DISPLAY_NUMBERNC: + result = CmndTM1637Number(false); + break; + case FUNC_DISPLAY_FLOAT: + result = CmndTM1637Float(true); + break; + case FUNC_DISPLAY_FLOATNC: + result = CmndTM1637Float(false); + break; + case FUNC_DISPLAY_RAW: + result = CmndTM1637Raw(); + break; + case FUNC_DISPLAY_SEVENSEG_TEXT: + result = CmndTM1637Text(true); + break; + case FUNC_DISPLAY_SEVENSEG_TEXTNC: + result = CmndTM1637Text(false); + break; + case FUNC_DISPLAY_LEVEL: + result = CmndTM1637Level(); + break; + case FUNC_DISPLAY_SCROLLTEXT: + result = CmndTM1637ScrollText(); + break; + case FUNC_DISPLAY_SCROLLDELAY: + result = CmndTM1637ScrollDelay(); + break; + case FUNC_DISPLAY_CLOCK: + result = CmndTM1637Clock(); + break; } return result; } -void TM1637Dim(void) { +void TM1637Dim(void) +{ // Settings.display_dimmer = 0 - 15 - uint8_t brightness = Settings.display_dimmer >> 1; // 0 - 7 + uint8_t brightness = Settings.display_dimmer >> 1; // 0 - 7 - if (TM1637 == TM1637Data.display_type) { - tm1637display->setBacklight(brightness * 12); // 0 - 84 + if (TM1637 == TM1637Data.display_type) + { + tm1637display->setBacklight(brightness * 12); // 0 - 84 } - else if (TM1637Data.display_type == TM1638) { - tm1638display->brightness(brightness); // 0 - 7 + else if (TM1638 == TM1637Data.display_type) + { + tm1638display->brightness(brightness); // 0 - 7 + } + else if (MAX7219 == TM1637Data.display_type) + { + max7219display->setIntensity(MAX7219_ADDR, brightness); // 0 - 7 } } @@ -785,35 +1075,50 @@ void TM1637Dim(void) { #ifdef USE_DISPLAY_MODES1TO5 -void TM1637Print(char* txt) { - for (uint32_t i = 0; i < Settings.display_cols[0]; i++) { - if (TM1637 == TM1637Data.display_type) { +void TM1637Print(char *txt) +{ + for (uint32_t i = 0; i < Settings.display_cols[0]; i++) + { + if (TM1637 == TM1637Data.display_type) + { uint8_t rawBytes[1]; rawBytes[0] = tm1637display->encode(txt[i]); -// if ((millis() % 1000) > 500 && (i == 1)) { rawBytes[0] = rawBytes[0] | 128; } + // if ((millis() % 1000) > 500 && (i == 1)) { rawBytes[0] = rawBytes[0] | 128; } tm1637display->printRaw(rawBytes, 1, i); } - else if (TM1638 == TM1637Data.display_type) { -// if ((millis() % 1000) > 500 && (i == 1)) { tm1638display->displayASCIIwDot(i, txt[i]); } + else if (TM1638 == TM1637Data.display_type) + { + // if ((millis() % 1000) > 500 && (i == 1)) { tm1638display->displayASCIIwDot(i, txt[i]); } tm1638display->displayASCII(i, txt[i]); } + else if (MAX7219 == TM1637Data.display_type) + { + // if ((millis() % 1000) > 500 && (i == 1)) { tm1638display->displayASCIIwDot(i, txt[i]); } + displayMAX7219ASCII(i, txt[i]); + } + } } -void TM1637Center(char* txt) { - char line[Settings.display_cols[0] +2]; +void TM1637Center(char *txt) +{ + char line[Settings.display_cols[0] + 2]; int len = strlen(txt); int offset = 0; - if (len >= Settings.display_cols[0]) { + if (len >= Settings.display_cols[0]) + { len = Settings.display_cols[0]; - } else { + } + else + { offset = (Settings.display_cols[0] - len) / 2; } memset(line, 0x20, Settings.display_cols[0]); line[Settings.display_cols[0]] = 0; - for (uint32_t i = 0; i < len; i++) { - line[offset +i] = txt[i]; + for (uint32_t i = 0; i < len; i++) + { + line[offset + i] = txt[i]; } TM1637Print(line); } @@ -845,54 +1150,70 @@ bool TM1637PrintLog(void) { } */ -void TM1637Time(void) { - char line[Settings.display_cols[0] +1]; +void TM1637Time(void) +{ + char line[Settings.display_cols[0] + 1]; - if (Settings.display_cols[0] >= 8) { + if (Settings.display_cols[0] >= 8) + { snprintf_P(line, sizeof(line), PSTR("%02d %02d %02d"), RtcTime.hour, RtcTime.minute, RtcTime.second); } - else if (Settings.display_cols[0] >= 6) { + else if (Settings.display_cols[0] >= 6) + { snprintf_P(line, sizeof(line), PSTR("%02d%02d%02d"), RtcTime.hour, RtcTime.minute, RtcTime.second); } - else { + else + { snprintf_P(line, sizeof(line), PSTR("%02d%02d"), RtcTime.hour, RtcTime.minute); } TM1637Center(line); } -void TM1637Date(void) { - char line[Settings.display_cols[0] +1]; +void TM1637Date(void) +{ + char line[Settings.display_cols[0] + 1]; - if (Settings.display_cols[0] >= 8) { - snprintf_P(line, sizeof(line), PSTR("%02d-%02d-%02d"), RtcTime.day_of_month, RtcTime.month, RtcTime.year -2000); + if (Settings.display_cols[0] >= 8) + { + snprintf_P(line, sizeof(line), PSTR("%02d-%02d-%02d"), RtcTime.day_of_month, RtcTime.month, RtcTime.year - 2000); } - else if (Settings.display_cols[0] >= 6) { - snprintf_P(line, sizeof(line), PSTR("%02d%02d%02d"), RtcTime.day_of_month, RtcTime.month, RtcTime.year -2000); + else if (Settings.display_cols[0] >= 6) + { + snprintf_P(line, sizeof(line), PSTR("%02d%02d%02d"), RtcTime.day_of_month, RtcTime.month, RtcTime.year - 2000); } - else { + else + { snprintf_P(line, sizeof(line), PSTR("%02d%02d"), RtcTime.day_of_month, RtcTime.month); } TM1637Center(line); } -void TM1637Refresh(void) { // Every second - if (!disp_power || !Settings.display_mode) { return; } // Mode 0 is User text +void TM1637Refresh(void) +{ // Every second + if (!disp_power || !Settings.display_mode) + { + return; + } // Mode 0 is User text - switch (Settings.display_mode) { - case 1: // Time + switch (Settings.display_mode) + { + case 1: // Time + TM1637Time(); + break; + case 2: // Date + TM1637Date(); + break; + case 3: // Time + if (TasmotaGlobal.uptime % Settings.display_refresh) + { TM1637Time(); - break; - case 2: // Date + } + else + { TM1637Date(); - break; - case 3: // Time - if (TasmotaGlobal.uptime % Settings.display_refresh) { - TM1637Time(); - } else { - TM1637Date(); - } - break; -/* + } + break; + /* case 4: // Mqtt TM1637PrintLog(); break; @@ -904,61 +1225,76 @@ void TM1637Refresh(void) { // Every second } } -#endif // USE_DISPLAY_MODES1TO5 +#endif // USE_DISPLAY_MODES1TO5 /*********************************************************************************************\ * Interface \*********************************************************************************************/ -bool Xdsp15(uint8_t function) { +bool Xdsp15(uint8_t function) +{ bool result = false; - if (FUNC_DISPLAY_INIT_DRIVER == function) { + if (FUNC_DISPLAY_INIT_DRIVER == function) + { TM1637Init(); } - else if (TM1637Data.init_done && (XDSP_15 == Settings.display_model)) { - switch (function) { - case FUNC_DISPLAY_EVERY_50_MSECOND: - if (disp_power && !Settings.display_mode) { - if (TM1637Data.scroll) { TM1637ScrollText(); } - if (TM1637Data.show_clock) { TM1637ShowTime(); } + else if (TM1637Data.init_done && (XDSP_15 == Settings.display_model)) + { + switch (function) + { + case FUNC_DISPLAY_EVERY_50_MSECOND: + if (disp_power && !Settings.display_mode) + { + if (TM1637Data.scroll) + { + TM1637ScrollText(); } - break; + if (TM1637Data.show_clock) + { + TM1637ShowTime(); + } + } + break; #ifdef USE_DISPLAY_MODES1TO5 - case FUNC_DISPLAY_EVERY_SECOND: - TM1637Refresh(); - break; -#endif // USE_DISPLAY_MODES1TO5 - case FUNC_DISPLAY_MODEL: - result = true; - break; - case FUNC_DISPLAY_SEVENSEG_TEXT: - case FUNC_DISPLAY_CLEAR: - case FUNC_DISPLAY_NUMBER: - case FUNC_DISPLAY_FLOAT: - case FUNC_DISPLAY_NUMBERNC: - case FUNC_DISPLAY_FLOATNC: - case FUNC_DISPLAY_RAW: - case FUNC_DISPLAY_LEVEL: - case FUNC_DISPLAY_SEVENSEG_TEXTNC: - case FUNC_DISPLAY_SCROLLTEXT: - case FUNC_DISPLAY_SCROLLDELAY: - case FUNC_DISPLAY_CLOCK: - if (disp_power && !Settings.display_mode) { - TM1637Data.show_clock = false; - result = TM1637MainFunc(function); - } - break; - case FUNC_DISPLAY_DIM: - TM1637Dim(); - break; - case FUNC_DISPLAY_POWER: - if (!disp_power) { TM1637ClearDisplay(); } - break; + case FUNC_DISPLAY_EVERY_SECOND: + TM1637Refresh(); + break; +#endif // USE_DISPLAY_MODES1TO5 + case FUNC_DISPLAY_MODEL: + result = true; + break; + case FUNC_DISPLAY_SEVENSEG_TEXT: + case FUNC_DISPLAY_CLEAR: + case FUNC_DISPLAY_NUMBER: + case FUNC_DISPLAY_FLOAT: + case FUNC_DISPLAY_NUMBERNC: + case FUNC_DISPLAY_FLOATNC: + case FUNC_DISPLAY_RAW: + case FUNC_DISPLAY_LEVEL: + case FUNC_DISPLAY_SEVENSEG_TEXTNC: + case FUNC_DISPLAY_SCROLLTEXT: + case FUNC_DISPLAY_SCROLLDELAY: + case FUNC_DISPLAY_CLOCK: + if (disp_power && !Settings.display_mode) + { + TM1637Data.show_clock = false; + result = TM1637MainFunc(function); + } + break; + case FUNC_DISPLAY_DIM: + TM1637Dim(); + break; + case FUNC_DISPLAY_POWER: + if (!disp_power) + { + TM1637ClearDisplay(); + } + break; } } return result; } -#endif // USE_DISPLAY_TM1637 -#endif // USE_DISPLAY +#endif // USE_DISPLAY_TM1637 +#endif // USE_DISPLAY