Added support for MAX7219 Seven-Segment Display

This commit is contained in:
Ajith Vasudevan 2021-03-19 15:56:48 +05:30
parent add48e8bd9
commit 27288ac603
36 changed files with 1457 additions and 12 deletions

View File

@ -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.

View File

@ -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)

View File

@ -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)
#######################################

View File

@ -0,0 +1,10 @@
name=LedControl
version=1.0.6
author=Eberhard Fahle <e.fahle@wayoda.org>
maintainer=Eberhard Fahle <e.fahle@wayoda.org>
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=*

View File

@ -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;i++) {
spiTransfer(i,OP_DISPLAYTEST,0);
//scanlimit is set to max on startup
setScanLimit(i,7);
//decode is done in source
spiTransfer(i,OP_DECODEMODE,0);
clearDisplay(i);
//we go into shutdown-mode on startup
shutdown(i,true);
}
}
int LedControl::getDeviceCount() {
return maxDevices;
}
void LedControl::shutdown(int addr, bool b) {
if(addr<0 || addr>=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;i<maxbytes;i++)
spidata[i]=(byte)0;
//put our device data into the array
spidata[offset+1]=opcode;
spidata[offset]=data;
//enable the line
digitalWrite(SPI_CS,LOW);
//Now shift out the data
for(int i=maxbytes;i>0;i--)
shiftOut(SPI_MOSI,SPI_CLK,MSBFIRST,spidata[i-1]);
//latch the data onto the display
digitalWrite(SPI_CS,HIGH);
}

View File

@ -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 <avr/pgmspace.h>
#if (ARDUINO >= 100)
#include <Arduino.h>
#else
#include <WProgram.h>
#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

View File

@ -643,6 +643,9 @@
#define D_SENSOR_TM1638_CLK "TM1638 CLK" #define D_SENSOR_TM1638_CLK "TM1638 CLK"
#define D_SENSOR_TM1638_DIO "TM1638 DIO" #define D_SENSOR_TM1638_DIO "TM1638 DIO"
#define D_SENSOR_TM1638_STB "TM1638 STB" #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_SCK "HX711 SCK"
#define D_SENSOR_HX711_DAT "HX711 DAT" #define D_SENSOR_HX711_DAT "HX711 DAT"
#define D_SENSOR_FTC532 "FTC532" #define D_SENSOR_FTC532 "FTC532"

View File

@ -642,6 +642,9 @@
#define D_SENSOR_TM1638_CLK "TM1638 CLK" #define D_SENSOR_TM1638_CLK "TM1638 CLK"
#define D_SENSOR_TM1638_DIO "TM1638 DIO" #define D_SENSOR_TM1638_DIO "TM1638 DIO"
#define D_SENSOR_TM1638_STB "TM1638 STB" #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_SCK "HX711 SCK"
#define D_SENSOR_HX711_DAT "HX711 DAT" #define D_SENSOR_HX711_DAT "HX711 DAT"
#define D_SENSOR_FTC532 "FTC532" #define D_SENSOR_FTC532 "FTC532"

View File

@ -643,6 +643,9 @@
#define D_SENSOR_TM1638_CLK "TM1638 CLK" #define D_SENSOR_TM1638_CLK "TM1638 CLK"
#define D_SENSOR_TM1638_DIO "TM1638 DIO" #define D_SENSOR_TM1638_DIO "TM1638 DIO"
#define D_SENSOR_TM1638_STB "TM1638 STB" #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_SCK "HX711 SCK"
#define D_SENSOR_HX711_DAT "HX711 DAT" #define D_SENSOR_HX711_DAT "HX711 DAT"
#define D_SENSOR_FTC532 "FTC532" #define D_SENSOR_FTC532 "FTC532"

View File

@ -643,6 +643,9 @@
#define D_SENSOR_TM1638_CLK "TM1638 CLK" #define D_SENSOR_TM1638_CLK "TM1638 CLK"
#define D_SENSOR_TM1638_DIO "TM1638 DIO" #define D_SENSOR_TM1638_DIO "TM1638 DIO"
#define D_SENSOR_TM1638_STB "TM1638 STB" #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_SCK "HX711 SCK"
#define D_SENSOR_HX711_DAT "HX711 DAT" #define D_SENSOR_HX711_DAT "HX711 DAT"
#define D_SENSOR_FTC532 "FTC532" #define D_SENSOR_FTC532 "FTC532"

View File

@ -643,6 +643,9 @@
#define D_SENSOR_TM1638_CLK "TM1638 CLK" #define D_SENSOR_TM1638_CLK "TM1638 CLK"
#define D_SENSOR_TM1638_DIO "TM1638 DIO" #define D_SENSOR_TM1638_DIO "TM1638 DIO"
#define D_SENSOR_TM1638_STB "TM1638 STB" #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_SCK "HX711 SCK"
#define D_SENSOR_HX711_DAT "HX711 DAT" #define D_SENSOR_HX711_DAT "HX711 DAT"
#define D_SENSOR_FTC532 "FTC532" #define D_SENSOR_FTC532 "FTC532"

View File

@ -643,6 +643,9 @@
#define D_SENSOR_TM1638_CLK "TM1638 CLK" #define D_SENSOR_TM1638_CLK "TM1638 CLK"
#define D_SENSOR_TM1638_DIO "TM1638 DIO" #define D_SENSOR_TM1638_DIO "TM1638 DIO"
#define D_SENSOR_TM1638_STB "TM1638 STB" #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_SCK "HX711 SCK"
#define D_SENSOR_HX711_DAT "HX711 DAT" #define D_SENSOR_HX711_DAT "HX711 DAT"
#define D_SENSOR_FTC532 "FTC532" #define D_SENSOR_FTC532 "FTC532"

View File

@ -643,6 +643,9 @@
#define D_SENSOR_TM1638_CLK "TM1638 CLK" #define D_SENSOR_TM1638_CLK "TM1638 CLK"
#define D_SENSOR_TM1638_DIO "TM1638 DIO" #define D_SENSOR_TM1638_DIO "TM1638 DIO"
#define D_SENSOR_TM1638_STB "TM1638 STB" #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_SCK "HX711 SCK"
#define D_SENSOR_HX711_DAT "HX711 DAT" #define D_SENSOR_HX711_DAT "HX711 DAT"
#define D_SENSOR_FTC532 "FTC532" #define D_SENSOR_FTC532 "FTC532"

View File

@ -643,6 +643,9 @@
#define D_SENSOR_TM1638_CLK "TM1638 CLK" #define D_SENSOR_TM1638_CLK "TM1638 CLK"
#define D_SENSOR_TM1638_DIO "TM1638 DIO" #define D_SENSOR_TM1638_DIO "TM1638 DIO"
#define D_SENSOR_TM1638_STB "TM1638 STB" #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_SCK "HX711 SCK"
#define D_SENSOR_HX711_DAT "HX711 DAT" #define D_SENSOR_HX711_DAT "HX711 DAT"
#define D_SENSOR_FTC532 "FTC532" #define D_SENSOR_FTC532 "FTC532"

View File

@ -643,6 +643,9 @@
#define D_SENSOR_TM1638_CLK "TM1638 CLK" #define D_SENSOR_TM1638_CLK "TM1638 CLK"
#define D_SENSOR_TM1638_DIO "TM1638 DIO" #define D_SENSOR_TM1638_DIO "TM1638 DIO"
#define D_SENSOR_TM1638_STB "TM1638 STB" #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_SCK "HX711 SCK"
#define D_SENSOR_HX711_DAT "HX711 DAT" #define D_SENSOR_HX711_DAT "HX711 DAT"
#define D_SENSOR_FTC532 "FTC532" #define D_SENSOR_FTC532 "FTC532"

View File

@ -643,6 +643,9 @@
#define D_SENSOR_TM1638_CLK "TM1638 CLK" #define D_SENSOR_TM1638_CLK "TM1638 CLK"
#define D_SENSOR_TM1638_DIO "TM1638 DIO" #define D_SENSOR_TM1638_DIO "TM1638 DIO"
#define D_SENSOR_TM1638_STB "TM1638 STB" #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_SCK "HX711 SCK"
#define D_SENSOR_HX711_DAT "HX711 DAT" #define D_SENSOR_HX711_DAT "HX711 DAT"
#define D_SENSOR_FTC532 "FTC532" #define D_SENSOR_FTC532 "FTC532"

View File

@ -643,6 +643,9 @@
#define D_SENSOR_TM1638_CLK "TM1638 CLK" #define D_SENSOR_TM1638_CLK "TM1638 CLK"
#define D_SENSOR_TM1638_DIO "TM1638 DIO" #define D_SENSOR_TM1638_DIO "TM1638 DIO"
#define D_SENSOR_TM1638_STB "TM1638 STB" #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_SCK "HX711 SCK"
#define D_SENSOR_HX711_DAT "HX711 DAT" #define D_SENSOR_HX711_DAT "HX711 DAT"
#define D_SENSOR_FTC532 "FTC532" #define D_SENSOR_FTC532 "FTC532"

View File

@ -643,6 +643,9 @@
#define D_SENSOR_TM1638_CLK "TM1638 - CLK" #define D_SENSOR_TM1638_CLK "TM1638 - CLK"
#define D_SENSOR_TM1638_DIO "TM1638 - DIO" #define D_SENSOR_TM1638_DIO "TM1638 - DIO"
#define D_SENSOR_TM1638_STB "TM1638 - STB" #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_SCK "HX711 - SCK"
#define D_SENSOR_HX711_DAT "HX711 - DAT" #define D_SENSOR_HX711_DAT "HX711 - DAT"
#define D_SENSOR_FTC532 "FTC532" #define D_SENSOR_FTC532 "FTC532"

View File

@ -643,6 +643,9 @@
#define D_SENSOR_TM1638_CLK "TM1638 CLK" #define D_SENSOR_TM1638_CLK "TM1638 CLK"
#define D_SENSOR_TM1638_DIO "TM1638 DIO" #define D_SENSOR_TM1638_DIO "TM1638 DIO"
#define D_SENSOR_TM1638_STB "TM1638 STB" #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_SCK "HX711 SCK"
#define D_SENSOR_HX711_DAT "HX711 DAT" #define D_SENSOR_HX711_DAT "HX711 DAT"
#define D_SENSOR_FTC532 "FTC532" #define D_SENSOR_FTC532 "FTC532"

View File

@ -643,6 +643,9 @@
#define D_SENSOR_TM1638_CLK "TM1638 CLK" #define D_SENSOR_TM1638_CLK "TM1638 CLK"
#define D_SENSOR_TM1638_DIO "TM1638 DIO" #define D_SENSOR_TM1638_DIO "TM1638 DIO"
#define D_SENSOR_TM1638_STB "TM1638 STB" #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_SCK "HX711 SCK"
#define D_SENSOR_HX711_DAT "HX711 DAT" #define D_SENSOR_HX711_DAT "HX711 DAT"
#define D_SENSOR_FTC532 "FTC532" #define D_SENSOR_FTC532 "FTC532"

View File

@ -643,6 +643,9 @@
#define D_SENSOR_TM1638_CLK "TM1638 CLK" #define D_SENSOR_TM1638_CLK "TM1638 CLK"
#define D_SENSOR_TM1638_DIO "TM1638 DIO" #define D_SENSOR_TM1638_DIO "TM1638 DIO"
#define D_SENSOR_TM1638_STB "TM1638 STB" #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_SCK "HX711 SCK"
#define D_SENSOR_HX711_DAT "HX711 DAT" #define D_SENSOR_HX711_DAT "HX711 DAT"
#define D_SENSOR_FTC532 "FTC532" #define D_SENSOR_FTC532 "FTC532"

View File

@ -643,6 +643,9 @@
#define D_SENSOR_TM1638_CLK "TM1638 CLK" #define D_SENSOR_TM1638_CLK "TM1638 CLK"
#define D_SENSOR_TM1638_DIO "TM1638 DIO" #define D_SENSOR_TM1638_DIO "TM1638 DIO"
#define D_SENSOR_TM1638_STB "TM1638 STB" #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_SCK "HX711 SCK"
#define D_SENSOR_HX711_DAT "HX711 DAT" #define D_SENSOR_HX711_DAT "HX711 DAT"
#define D_SENSOR_FTC532 "FTC532" #define D_SENSOR_FTC532 "FTC532"

View File

@ -643,6 +643,9 @@
#define D_SENSOR_TM1638_CLK "TM1638 CLK" #define D_SENSOR_TM1638_CLK "TM1638 CLK"
#define D_SENSOR_TM1638_DIO "TM1638 DIO" #define D_SENSOR_TM1638_DIO "TM1638 DIO"
#define D_SENSOR_TM1638_STB "TM1638 STB" #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_SCK "HX711 SCK"
#define D_SENSOR_HX711_DAT "HX711 DAT" #define D_SENSOR_HX711_DAT "HX711 DAT"
#define D_SENSOR_FTC532 "FTC532" #define D_SENSOR_FTC532 "FTC532"

View File

@ -643,6 +643,9 @@
#define D_SENSOR_TM1638_CLK "TM1638 CLK" #define D_SENSOR_TM1638_CLK "TM1638 CLK"
#define D_SENSOR_TM1638_DIO "TM1638 DIO" #define D_SENSOR_TM1638_DIO "TM1638 DIO"
#define D_SENSOR_TM1638_STB "TM1638 STB" #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_SCK "HX711 SCK"
#define D_SENSOR_HX711_DAT "HX711 DAT" #define D_SENSOR_HX711_DAT "HX711 DAT"
#define D_SENSOR_FTC532 "FTC532" #define D_SENSOR_FTC532 "FTC532"

View File

@ -643,6 +643,9 @@
#define D_SENSOR_TM1638_CLK "TM1638 CLK" #define D_SENSOR_TM1638_CLK "TM1638 CLK"
#define D_SENSOR_TM1638_DIO "TM1638 DIO" #define D_SENSOR_TM1638_DIO "TM1638 DIO"
#define D_SENSOR_TM1638_STB "TM1638 STB" #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_SCK "HX711 SCK"
#define D_SENSOR_HX711_DAT "HX711 DAT" #define D_SENSOR_HX711_DAT "HX711 DAT"
#define D_SENSOR_FTC532 "FTC532" #define D_SENSOR_FTC532 "FTC532"

View File

@ -643,6 +643,9 @@
#define D_SENSOR_TM1638_CLK "TM1638 CLK" #define D_SENSOR_TM1638_CLK "TM1638 CLK"
#define D_SENSOR_TM1638_DIO "TM1638 DIO" #define D_SENSOR_TM1638_DIO "TM1638 DIO"
#define D_SENSOR_TM1638_STB "TM1638 STB" #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_SCK "HX711 SCK"
#define D_SENSOR_HX711_DAT "HX711 DAT" #define D_SENSOR_HX711_DAT "HX711 DAT"
#define D_SENSOR_FTC532 "FTC532" #define D_SENSOR_FTC532 "FTC532"

View File

@ -643,6 +643,9 @@
#define D_SENSOR_TM1638_CLK "TM1638 CLK" #define D_SENSOR_TM1638_CLK "TM1638 CLK"
#define D_SENSOR_TM1638_DIO "TM1638 DIO" #define D_SENSOR_TM1638_DIO "TM1638 DIO"
#define D_SENSOR_TM1638_STB "TM1638 STB" #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_SCK "HX711 SCK"
#define D_SENSOR_HX711_DAT "HX711 DAT" #define D_SENSOR_HX711_DAT "HX711 DAT"
#define D_SENSOR_FTC532 "FTC532" #define D_SENSOR_FTC532 "FTC532"

View File

@ -643,6 +643,9 @@
#define D_SENSOR_TM1638_CLK "TM1638 CLK" #define D_SENSOR_TM1638_CLK "TM1638 CLK"
#define D_SENSOR_TM1638_DIO "TM1638 DIO" #define D_SENSOR_TM1638_DIO "TM1638 DIO"
#define D_SENSOR_TM1638_STB "TM1638 STB" #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_SCK "HX711 SCK"
#define D_SENSOR_HX711_DAT "HX711 DAT" #define D_SENSOR_HX711_DAT "HX711 DAT"
#define D_SENSOR_FTC532 "FTC532" #define D_SENSOR_FTC532 "FTC532"

View File

@ -643,6 +643,9 @@
#define D_SENSOR_TM1638_CLK "TM1638 CLK" #define D_SENSOR_TM1638_CLK "TM1638 CLK"
#define D_SENSOR_TM1638_DIO "TM1638 DIO" #define D_SENSOR_TM1638_DIO "TM1638 DIO"
#define D_SENSOR_TM1638_STB "TM1638 STB" #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_SCK "HX711 SCK"
#define D_SENSOR_HX711_DAT "HX711 DAT" #define D_SENSOR_HX711_DAT "HX711 DAT"
#define D_SENSOR_FTC532 "FTC532" #define D_SENSOR_FTC532 "FTC532"

View File

@ -643,6 +643,9 @@
#define D_SENSOR_TM1638_CLK "TM1638 CLK" #define D_SENSOR_TM1638_CLK "TM1638 CLK"
#define D_SENSOR_TM1638_DIO "TM1638 DIO" #define D_SENSOR_TM1638_DIO "TM1638 DIO"
#define D_SENSOR_TM1638_STB "TM1638 STB" #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_SCK "HX711 SCK"
#define D_SENSOR_HX711_DAT "HX711 DAT" #define D_SENSOR_HX711_DAT "HX711 DAT"
#define D_SENSOR_FTC532 "FTC532" #define D_SENSOR_FTC532 "FTC532"

View File

@ -643,6 +643,9 @@
#define D_SENSOR_TM1638_CLK "TM1638 CLK" #define D_SENSOR_TM1638_CLK "TM1638 CLK"
#define D_SENSOR_TM1638_DIO "TM1638 DIO" #define D_SENSOR_TM1638_DIO "TM1638 DIO"
#define D_SENSOR_TM1638_STB "TM1638 STB" #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_SCK "HX711 SCK"
#define D_SENSOR_HX711_DAT "HX711 DAT" #define D_SENSOR_HX711_DAT "HX711 DAT"
#define D_SENSOR_FTC532 "FTC532" #define D_SENSOR_FTC532 "FTC532"

View File

@ -643,6 +643,9 @@
#define D_SENSOR_TM1638_CLK "TM1638 CLK" #define D_SENSOR_TM1638_CLK "TM1638 CLK"
#define D_SENSOR_TM1638_DIO "TM1638 DIO" #define D_SENSOR_TM1638_DIO "TM1638 DIO"
#define D_SENSOR_TM1638_STB "TM1638 STB" #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_SCK "HX711 SCK"
#define D_SENSOR_HX711_DAT "HX711 DAT" #define D_SENSOR_HX711_DAT "HX711 DAT"
#define D_SENSOR_FTC532 "FTC532" #define D_SENSOR_FTC532 "FTC532"

View File

@ -306,6 +306,7 @@
#define USE_DISPLAY // Add Display Support (+2k code) #define USE_DISPLAY // Add Display Support (+2k code)
#define USE_DISPLAY_TM1637 // [DisplayModel 15] Enable TM1637 module #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_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 #define USE_DISPLAY_MODES1TO5 // Enable display mode 1 to 5 in addition to mode 0

View File

@ -155,6 +155,7 @@ enum UserSelectablePins {
GPIO_XPT2046_CS, // XPT2046 SPI Chip Select GPIO_XPT2046_CS, // XPT2046 SPI Chip Select
GPIO_CSE7761_TX, GPIO_CSE7761_RX, // CSE7761 Serial interface (Dual R3) 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_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 }; GPIO_SENSOR_END };
enum ProgramSelectablePins { enum ProgramSelectablePins {
@ -330,6 +331,7 @@ const char kSensorNames[] PROGMEM =
D_SENSOR_XPT2046_CS "|" D_SENSOR_XPT2046_CS "|"
D_SENSOR_CSE7761_TX "|" D_SENSOR_CSE7761_RX "|" D_SENSOR_CSE7761_TX "|" D_SENSOR_CSE7761_RX "|"
D_SENSOR_VL53L0X_XSHUT "|" D_SENSOR_VL53L0X_XSHUT "|"
D_SENSOR_MAX7219_CLK "|" D_SENSOR_MAX7219_DIN "|" D_SENSOR_MAX7219_CS "|"
; ;
const char kSensorNamesFixed[] PROGMEM = const char kSensorNamesFixed[] PROGMEM =
@ -789,8 +791,13 @@ const uint16_t kGpioNiceList[] PROGMEM = {
#endif #endif
#ifdef USE_VL53L0X #ifdef USE_VL53L0X
AGPIO(GPIO_VL53L0X_XSHUT1) + VL53L0X_MAX_SENSORS, // When using multiple 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 * ESP32 specifics
\*-------------------------------------------------------------------------------------------*/ \*-------------------------------------------------------------------------------------------*/

View File

@ -42,7 +42,7 @@ uint16_t bg_color = 0;
uint8_t color_type = COLOR_BW; uint8_t color_type = COLOR_BW;
uint8_t auto_draw = 1; uint8_t auto_draw = 1;
const uint8_t DISPLAY_MAX_DRIVERS = 16; // Max number of display drivers/models supported by xdsp_interface.ino const uint8_t DISPLAY_MAX_DRIVERS = 17; // Max number of display drivers/models supported by xdsp_interface.ino
const uint8_t DISPLAY_MAX_COLS = 64; // Max number of columns allowed with command DisplayCols const uint8_t DISPLAY_MAX_COLS = 64; // Max number of columns allowed with command DisplayCols
const uint8_t DISPLAY_MAX_ROWS = 64; // Max number of lines allowed with command DisplayRows const uint8_t DISPLAY_MAX_ROWS = 64; // Max number of lines allowed with command DisplayRows
@ -1873,15 +1873,9 @@ void CmndDisplayScrollText(void)
void CmndDisplaySize(void) void CmndDisplaySize(void)
{ {
#ifdef USE_DISPLAY_TM1637 Settings.display_size = XdrvMailbox.payload;
if ((XdrvMailbox.payload > 0) && (XdrvMailbox.payload <= 6)) { if (renderer) renderer->setTextSize(Settings.display_size);
#else //else DisplaySetSize(Settings.display_size);
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);
}
ResponseCmndNumber(Settings.display_size); ResponseCmndNumber(Settings.display_size);
} }
@ -1945,7 +1939,7 @@ void CmndDisplayText(void)
#ifndef USE_DISPLAY_MODES1TO5 #ifndef USE_DISPLAY_MODES1TO5
DisplayText(); DisplayText();
#else #else
if(Settings.display_model == 15) { if(Settings.display_model == 15 || Settings.display_model == 16) {
XdspCall(FUNC_DISPLAY_SEVENSEG_TEXT); XdspCall(FUNC_DISPLAY_SEVENSEG_TEXT);
} else if (!Settings.display_mode) { } else if (!Settings.display_mode) {
DisplayText(); DisplayText();

878
tasmota/xdsp_16_max7219.ino Normal file
View File

@ -0,0 +1,878 @@
/*
xdsp_16_max7219.ino - Support for MAX7219- based seven-segment displays for Tasmota
Copyright (C) 2021 Ajith Vasudevan
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifdef USE_DISPLAY
#ifdef USE_DISPLAY_MAX7219
/*********************************************************************************************\
This driver enables the display of numbers (both integers and floats) and basic text
on the inexpensive MAX7219-based seven-segment modules.
Raw segments can also be displayed.
In addition, it is also possible to set brightness (8 levels), clear the display, scroll text,
display a rudimentary bar graph, and a Clock (12 hr and 24 hr).
To use, compile Tasmota with USE_DISPLAY and USE_DISPLAY_MAX7219, or build the tasmota-display env.
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:
DIN hardware pin --> "MAX7219 DIN"
CS hardware pin --> "MAX7219 CS"
CLK hardware pin --> "MAX7219 CLK"
Once the GPIO configuration is saved and the ESP8266/ESP32 module restarts, set the Display Model to 16
using the command "DisplayModel 16"
After the ESP8266/ESP32 module restarts again, the following "Display" commands can be used:
DisplayClear
Clears the display, command: "DisplayClear"
DisplayNumber num [,position {0-(MAX7219Data.num_digits-1))} [,leading_zeros {0|1} [,length {1 to MAX7219Data.num_digits}]]]
Clears and then displays number without decimal. command e.g., "DisplayNumber 1234"
Control 'leading zeros', 'length' and 'position' with "DisplayNumber 1234, <position>, <leadingZeros>, <length>"
'leading zeros' can be 1 or 0 (default), 'length' can be 1 to MAX7219Data.num_digits, 'position' can be 0 (left-most) to MAX7219Data.num_digits (right-most).
See function description below for more details.
DisplayNumberNC num [,position {0-(MAX7219Data.num_digits-1))} [,leading_zeros {0|1} [,length {1 to MAX7219Data.num_digits}]]]
Display integer number as above, but without clearing first. e.g., "DisplayNumberNC 1234". Usage is same as above.
DisplayFloat num [,position {0-(MAX7219Data.num_digits-1)} [,precision {0-MAX7219Data.num_digits} [,length {1 to MAX7219Data.num_digits}]]]
Clears and then displays float (with decimal point) command e.g., "DisplayFloat 12.34"
See function description below for more details.
DisplayFloatNC num [,position {0-(MAX7219Data.num_digits-1)} [,precision {0-MAX7219Data.num_digits} [,length {1 to MAX7219Data.num_digits}]]]
Displays float (with decimal point) as above, but without clearing first. command e.g., "DisplayFloatNC 12.34"
See function description below for more details.
DisplayBrightness num {1-8}
Set brightness (1 to 8) command e.g., "DisplayBrightness 2"
DisplayRaw position {0-(MAX7219Data.num_digits-1)},length {1 to MAX7219Data.num_digits}, num1 [, num2[, num3[, num4[, ...upto MAX7219Data.num_digits numbers]]]]]
Takes upto MAX7219Data.num_digits comma-separated integers (0-255) and displays raw segments. Each number represents a
7-segment digit. Each 8-bit number represents individual segments of a digit.
For example, the command "DisplayRaw 0, 4, 255, 255, 255, 255" would display "[8.8.8.8.]"
DisplayText text [, position {0-(MAX7219Data.num_digits-1)} [,length {1 to MAX7219Data.num_digits}]]
Clears and then displays basic text. command e.g., "DisplayText ajith vasudevan"
Control 'length' and 'position' with "DisplayText <text>, <position>, <length>"
'length' can be 1 to MAX7219Data.num_digits, 'position' can be 0 (left-most) to MAX7219Data.num_digits-1 (right-most)
A caret(^) symbol in the text input is dispayed as the degrees(°) symbol. This is useful for displaying Temperature!
For example, the command "DisplayText 22.5^" will display "22.5°".
DisplayTextNC text [, position {0-MAX7219Data.num_digits-1} [,length {1 to MAX7219Data.num_digits}]]
Clears first, then displays text. Usage is same as above.
DisplayScrollText text
Displays scrolling text.
DisplayScrollDelay delay {0-15} // default = 4
Sets the speed of text scroll. Smaller delay = faster scrolling.
DisplayLevel num {0-100}
Display a horizontal bar graph (0-100) command e.g., "DisplayLevel 50" will display [|||| ]
DisplayClock 1|2|0
Displays a clock.
Commands "DisplayClock 1" // 12 hr format
"DisplayClock 2" // 24 hr format
"DisplayClock 0" // turn off clock
\*********************************************************************************************/
#define XDSP_16 16
#define BRIGHTNESS_MIN 1
#define BRIGHTNESS_MAX 8
#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
#include <LedControl.h>
LedControl *max7219display;
struct
{
char scroll_text[CMD_MAX_LEN];
char msg[60];
char model_name[8];
uint8_t num_digits = 4;
uint8_t scroll_delay = 4;
uint8_t scroll_index = 0;
uint8_t iteration = 0;
uint8_t brightness = 5;
uint8_t prev_buttons;
bool init_done = false;
bool scroll = false;
bool show_clock = false;
bool clock_24 = false;
} MAX7219Data;
/*********************************************************************************************\
* Init function
\*********************************************************************************************/
void MAXDriverInit(void)
{
if (!(PinUsed(GPIO_MAX7219DIN) && PinUsed(GPIO_MAX7219CLK) && PinUsed(GPIO_MAX7219CS)))
return;
Settings.display_model == XDSP_16;
MAX7219Data.num_digits = 8;
strcpy(MAX7219Data.model_name, "MAX7219");
max7219display = new LedControl(Pin(GPIO_MAX7219DIN), Pin(GPIO_MAX7219CLK), Pin(GPIO_MAX7219CS), 1);
max7219display->shutdown(MAX7219_ADDR, false);
maxClearDisplay();
MAX7219Data.brightness = (Settings.display_dimmer ? Settings.display_dimmer : MAX7219Data.brightness);
maxSetBrightness(MAX7219Data.brightness);
MAX7219Data.init_done = true;
AddLog(LOG_LEVEL_INFO, PSTR("DSP: %s display driver initialized with %d digits"), MAX7219Data.model_name, MAX7219Data.num_digits);
}
// 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-(MAX7219Data.num_digits-1)} [,leading_zeros {0|1} [,length {1 to MAX7219Data.num_digits}]]]
* DisplayNumberNC num [,position {0-(MAX7219Data.num_digits-1)} [,leading_zeros {0|1} [,length {1 to MAX7219Data.num_digits}]]] // "NC" --> "No Clear"
\*********************************************************************************************/
bool MAXCmndNumber(bool clear)
{
char sNum[CMD_MAX_LEN];
char sLeadingzeros[CMD_MAX_LEN];
char sPosition[CMD_MAX_LEN];
char sLength[CMD_MAX_LEN];
uint8_t length = 0;
bool leadingzeros = false;
uint8_t position = 0;
uint32_t num = 0;
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);
}
if ((position < 0) || (position > (MAX7219Data.num_digits - 1)))
position = 0;
AddLog(LOG_LEVEL_DEBUG, PSTR("MAX: num %d, pos %d, lead %d, len %d"), num, position, leadingzeros, length);
if (clear)
maxClearDisplay();
char txt[30];
snprintf_P(txt, sizeof(txt), PSTR("%d"), num);
if (!length)
length = strlen(txt);
if ((length < 0) || (length > MAX7219Data.num_digits))
length = MAX7219Data.num_digits;
char pad = (leadingzeros ? '0' : ' ');
uint32_t i = position;
uint8_t rawBytes[1];
for (; i < position + (length - strlen(txt)); i++)
{
if (i > MAX7219Data.num_digits)
break;
displayMAX7219ASCII(i, pad);
}
for (uint32_t j = 0; i < position + length; i++, j++)
{
if (i > MAX7219Data.num_digits)
break;
if (txt[j] == 0)
break;
displayMAX7219ASCII(i, txt[j]);
}
return true;
}
/*********************************************************************************************\
* Displays number with decimal, specifying position, precision and length,
* optionally skipping clearing display before displaying the number.
* commands: DisplayFloat num [,position {0-(MAX7219Data.num_digits-1)} [,precision {0-MAX7219Data.num_digits} [,length {1 to MAX7219Data.num_digits}]]]
* DisplayFloatNC num [,position {0-(MAX7219Data.num_digits-1)} [,precision {0-MAX7219Data.num_digits} [,length {1 to MAX7219Data.num_digits}]]] // "NC" --> "No Clear"
\*********************************************************************************************/
bool MAXCmndFloat(bool clear)
{
char sNum[CMD_MAX_LEN];
char sPrecision[CMD_MAX_LEN];
char sPosition[CMD_MAX_LEN];
char sLength[CMD_MAX_LEN];
uint8_t length = 0;
uint8_t precision = MAX7219Data.num_digits;
uint8_t position = 0;
float fnum = 0.0f;
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);
}
if ((position < 0) || (position > (MAX7219Data.num_digits - 1)))
position = 0;
if ((precision < 0) || (precision > MAX7219Data.num_digits))
precision = MAX7219Data.num_digits;
if (clear)
maxClearDisplay();
char txt[30];
ext_snprintf_P(txt, sizeof(txt), PSTR("%*_f"), precision, &fnum);
if (!length)
length = strlen(txt);
if ((length <= 0) || (length > MAX7219Data.num_digits))
length = MAX7219Data.num_digits;
AddLog(LOG_LEVEL_DEBUG, PSTR("MAX: num %4_f, prec %d, len %d"), &fnum, precision, length);
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 MAXCmndClear(void)
{
maxClearDisplay();
sprintf(MAX7219Data.msg, PSTR("Cleared"));
XdrvMailbox.data = MAX7219Data.msg;
return true;
}
// /*********************************************************************************************\
// * Clears the display
// \*********************************************************************************************/
void maxClearDisplay(void)
{
max7219display->clearDisplay(MAX7219_ADDR);
}
/*********************************************************************************************\
* Display scrolling text
* Command: DisplayMAX7219Data.scroll_text text
\*********************************************************************************************/
bool MAXCmndScrollText(void)
{
AddLog(LOG_LEVEL_DEBUG, PSTR("MAX: Text %s"), XdrvMailbox.data);
if (XdrvMailbox.data_len > SCROLL_MAX_LEN)
{
snprintf(MAX7219Data.msg, sizeof(MAX7219Data.msg), PSTR("Text too long. Length should be less than %d"), SCROLL_MAX_LEN);
XdrvMailbox.data = MAX7219Data.msg;
return false;
}
else
{
snprintf(MAX7219Data.scroll_text, sizeof(MAX7219Data.scroll_text), PSTR(" "));
snprintf(MAX7219Data.scroll_text, sizeof(MAX7219Data.scroll_text), PSTR("%s"), XdrvMailbox.data);
MAX7219Data.scroll_text[XdrvMailbox.data_len] = 0;
MAX7219Data.scroll_index = 0;
MAX7219Data.scroll = true;
return true;
}
}
/*********************************************************************************************\
* Sets the scroll delay for scrolling text.
* Command: DisplayMAX7219Data.scroll_delay delay {0-15} // default = 4
\*********************************************************************************************/
bool MAXCmndScrollDelay(void)
{
if (ArgC() == 0)
{
XdrvMailbox.payload = MAX7219Data.scroll_delay;
return true;
}
if (MAX7219Data.scroll_delay < 0)
MAX7219Data.scroll_delay = 0;
MAX7219Data.scroll_delay = XdrvMailbox.payload;
return true;
}
/*********************************************************************************************\
* Scrolls a given string. Called every 50ms
\*********************************************************************************************/
void maxScrollText(void)
{
MAX7219Data.iteration++;
if (MAX7219Data.scroll_delay)
MAX7219Data.iteration = MAX7219Data.iteration % MAX7219Data.scroll_delay;
else
MAX7219Data.iteration = 0;
if (MAX7219Data.iteration)
return;
if (MAX7219Data.scroll_index > strlen(MAX7219Data.scroll_text))
{
MAX7219Data.scroll = false;
MAX7219Data.scroll_index = 0;
return;
}
uint8_t rawBytes[1];
for (uint32_t i = 0, j = MAX7219Data.scroll_index; i < 1 + strlen(MAX7219Data.scroll_text); i++, j++)
{
if (i > (MAX7219Data.num_digits - 1))
{
break;
}
rawBytes[0] = tm1637display->encode(MAX7219Data.scroll_text[j]);
bool dotSkipped = false;
if (MAX7219Data.scroll_text[j + 1] == '.')
{
dotSkipped = true;
rawBytes[0] = rawBytes[0] | 128;
j++;
}
else if (MAX7219Data.scroll_text[j] == '^')
{
rawBytes[0] = 1 | 2 | 32 | 64;
}
if (!dotSkipped && MAX7219Data.scroll_text[j] == '.')
{
j++;
MAX7219Data.scroll_index++;
rawBytes[0] = tm1637display->encode(MAX7219Data.scroll_text[j]);
}
if (MAX7219Data.scroll_text[j + 1] == '.')
{
rawBytes[0] = rawBytes[0] | 128;
}
displayMAX72197Seg(i, rawBytes[0]);
}
MAX7219Data.scroll_index++;
}
/*********************************************************************************************\
* Displays a horizontal bar graph. Takes a percentage number (0-100) as input
* Command: DisplayLevel level {0-100}
\*********************************************************************************************/
bool MAXCmndLevel(void)
{
uint16_t val = XdrvMailbox.payload;
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 * MAX7219Data.num_digits;
AddLog(LOG_LEVEL_DEBUG, PSTR("MAX: MAX7219Data.model_name %s MAXCmndLevel totalBars=%d"), MAX7219Data.model_name, totalBars);
float barsToDisplay = totalBars * val / 100.0f;
char txt[5];
ext_snprintf_P(txt, sizeof(txt), PSTR("%*_f"), 1, &barsToDisplay);
AddLog(LOG_LEVEL_DEBUG, PSTR("MAX: MAX7219Data.model_name %s MAXCmndLevel barsToDisplay=%s"), MAX7219Data.model_name, txt);
char s[4];
ext_snprintf_P(s, sizeof(s), PSTR("%0_f"), &barsToDisplay);
uint8_t numBars = atoi(s);
AddLog(LOG_LEVEL_DEBUG, PSTR("MAX: CmndTM1637Level numBars %d"), numBars);
maxClearDisplay();
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);
displayMAX72197Seg(digit, value);
}
return true;
}
/*********************************************************************************************\
* Display arbitrary data on the display module
* Command: DisplayRaw position {0-(MAX7219Data.num_digits-1)},length {1 to MAX7219Data.num_digits}, a [, b[, c[, d[...upto MAX7219Data.num_digits]]]]
* where a,b,c,d... are upto MAX7219Data.num_digits numbers in the range 0-255, each number (byte)
* corresponding to a single 7-segment digit. Within each byte, bit 0 is segment A,
* 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 MAXCmndRaw(void)
{
uint8_t DATA[8] = {0, 0, 0, 0, 0, 0, 0, 0};
char as[CMD_MAX_LEN];
char bs[CMD_MAX_LEN];
char cs[CMD_MAX_LEN];
char ds[CMD_MAX_LEN];
char es[CMD_MAX_LEN];
char fs[CMD_MAX_LEN];
char gs[CMD_MAX_LEN];
char hs[CMD_MAX_LEN];
char sLength[CMD_MAX_LEN];
char sPos[CMD_MAX_LEN];
uint32_t position = 0;
uint32_t length = 0;
switch (ArgC())
{
case 10:
subStr(hs, XdrvMailbox.data, ",", 10);
DATA[7] = atoi(hs);
case 9:
subStr(gs, XdrvMailbox.data, ",", 9);
DATA[6] = atoi(gs);
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 > MAX7219Data.num_digits)
length = MAX7219Data.num_digits;
if (position < 0 || position > (MAX7219Data.num_digits - 1))
position = 0;
AddLog(LOG_LEVEL_DEBUG, PSTR("MAX: a %d, b %d, c %d, d %d, e %d, f %d, g %d, h %d, len %d, pos %d"),
DATA[0], DATA[1], DATA[2], DATA[3], DATA[4], DATA[5], DATA[6], DATA[7], length, position);
for (uint32_t i = position; i < position + length; i++)
{
if (i > 7)
break;
displayMAX72197Seg(i, DATA[i - position]);
}
return true;
}
/*********************************************************************************************\
* Display a given string.
* Text can be placed at arbitrary location on the display using the length and
* position parameters without affecting the rest of the display.
* Command: DisplayText text [, position {0-(MAX7219Data.num_digits-1)} [,length {1 to MAX7219Data.num_digits}]]
\*********************************************************************************************/
bool MAXCmndText(bool clear)
{
char sString[CMD_MAX_LEN + 1];
char sPosition[CMD_MAX_LEN];
char sLength[CMD_MAX_LEN];
uint8_t length = 0;
uint8_t position = 0;
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);
}
if ((position < 0) || (position > (MAX7219Data.num_digits - 1)))
position = 0;
AddLog(LOG_LEVEL_DEBUG, PSTR("MAX: sString %s, pos %d, len %d"), sString, position, length);
if (clear)
maxClearDisplay();
if (!length)
length = strlen(sString);
if ((length < 0) || (length > MAX7219Data.num_digits))
length = MAX7219Data.num_digits;
uint32_t i = position;
uint8_t rawBytes[1];
for (uint32_t j = 0; i < position + length; i++, j++)
{
if (i > (MAX7219Data.num_digits - 1))
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;
}
/*********************************************************************************************\
* Sets brightness of the display.
* Command: DisplayBrightness {1-8}
\*********************************************************************************************/
bool MAXCmndBrightness(void)
{
uint16_t val = XdrvMailbox.payload;
if (ArgC() == 0)
{
XdrvMailbox.payload = MAX7219Data.brightness;
return true;
}
if ((val < BRIGHTNESS_MIN) || (val > BRIGHTNESS_MAX))
{
Response_P(PSTR("{\"Error\":\"Brightness should be a number in the range [%d, %d]\"}"), BRIGHTNESS_MIN, BRIGHTNESS_MAX);
return false;
}
MAX7219Data.brightness = val;
maxSetBrightness(MAX7219Data.brightness);
return true;
}
void maxSetBrightness(uint8_t val)
{
if ((val < BRIGHTNESS_MIN) || (val > BRIGHTNESS_MAX))
val = 5;
Settings.display_dimmer = val;
max7219display->setIntensity(MAX7219_ADDR, val - 1);
}
/*********************************************************************************************\
* Displays a clock.
* Command: DisplayClock 1 // 12-hour format
* DisplayClock 2 // 24-hour format
* DisplayClock 0 // turn off clock and clear
\*********************************************************************************************/
bool MAXCmndClock(void)
{
MAX7219Data.show_clock = XdrvMailbox.payload;
if (ArgC() == 0)
XdrvMailbox.payload = 1;
if (XdrvMailbox.payload > 1)
MAX7219Data.clock_24 = true;
else if (XdrvMailbox.payload == 1)
MAX7219Data.clock_24 = false;
AddLog(LOG_LEVEL_DEBUG, PSTR("MAX: MAX7219Data.show_clock %d, MAX7219Data.clock_24 %d"), MAX7219Data.show_clock, MAX7219Data.clock_24);
maxClearDisplay();
return true;
}
/*********************************************************************************************\
* refreshes the time if clock is displayed
\*********************************************************************************************/
void maxShowTime()
{
uint8_t hr = RtcTime.hour;
uint8_t mn = RtcTime.minute;
// uint8_t hr = 1;
// uint8_t mn = 0;
char z = ' ';
if (MAX7219Data.clock_24)
{
z = '0';
}
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);
}
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 MAXMainFunc(uint8_t fn)
{
bool result = false;
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 = MAXCmndClear();
break;
case FUNC_DISPLAY_NUMBER:
result = MAXCmndNumber(true);
break;
case FUNC_DISPLAY_NUMBERNC:
result = MAXCmndNumber(false);
break;
case FUNC_DISPLAY_FLOAT:
result = MAXCmndFloat(true);
break;
case FUNC_DISPLAY_FLOATNC:
result = MAXCmndFloat(false);
break;
case FUNC_DISPLAY_BRIGHTNESS:
result = MAXCmndBrightness();
break;
case FUNC_DISPLAY_RAW:
result = MAXCmndRaw();
break;
case FUNC_DISPLAY_SEVENSEG_TEXT:
result = MAXCmndText(true);
break;
case FUNC_DISPLAY_SEVENSEG_TEXTNC:
result = MAXCmndText(false);
break;
case FUNC_DISPLAY_LEVEL:
result = MAXCmndLevel();
break;
case FUNC_DISPLAY_SCROLLTEXT:
result = MAXCmndScrollText();
break;
case FUNC_DISPLAY_SCROLLDELAY:
result = MAXCmndScrollDelay();
break;
case FUNC_DISPLAY_CLOCK:
result = MAXCmndClock();
break;
}
return result;
}
/*********************************************************************************************\
* Interface
\*********************************************************************************************/
bool Xdsp16(uint8_t function)
{
bool result = false;
if (Settings.display_model == XDSP_16)
{
switch (function)
{
case FUNC_DISPLAY_MODEL:
result = true;
break;
case FUNC_DISPLAY_INIT_DRIVER:
MAXDriverInit(); // init
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:
MAX7219Data.show_clock = false;
case FUNC_DISPLAY_BRIGHTNESS:
result = MAXMainFunc(function);
break;
case FUNC_DISPLAY_EVERY_50_MSECOND:
if (MAX7219Data.scroll)
maxScrollText();
if (MAX7219Data.show_clock)
maxShowTime();
break;
}
}
return result;
}
#endif // USE_DISPLAY_MAX7219
#endif // USE_DISPLAY