use LedMatrix 1234

This commit is contained in:
Michael 2021-11-20 17:28:38 +01:00
parent b3dd33f248
commit 532e506946
3 changed files with 373 additions and 89 deletions

View File

@ -0,0 +1,186 @@
/*
* LedMatrix.h - Extends the Library LedControl for multiple LED dot matrix modules, based on MAX7219/MAX7221
* Copyright (c) 2021 Michael Beuss
*
* 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 "LedMatrix.h"
// public
LedMatrix::LedMatrix(int dataPin, int clkPin, int csPin, unsigned int colums, unsigned int rows)
{
if (colums * rows > MATRIX_MAX_MODULES)
{
// dimension exeeds maximum buffer size
if (colums >= MATRIX_MAX_MODULES)
{
colums = MATRIX_MAX_MODULES;
rows = 1;
}
else
{
rows = MATRIX_MAX_MODULES / colums;
}
}
modulesPerRow = colums;
modulesPerCol = rows;
width = colums * 8;
height = rows * 8;
modules = colums * rows;
moduleOrientation = ORIENTATION_UPSIDE_DOWN;
ledControl = new LedControl(dataPin, clkPin, csPin, modules);
shutdown(false); // false: on, true: off
clear();
setIntensity(7);
}
bool LedMatrix::clear(void)
{
for (int i = 0; i < MATRIX_BUFFER_SIZE; i++)
{
buffer[i] = 0;
}
for (int addr = 0; addr < modules; addr++)
{
ledControl->clearDisplay(addr);
}
return true;
}
bool LedMatrix::setIntensity(byte dim)
{
for (int addr = 0; addr < modules; addr++)
{
ledControl->setIntensity(addr, dim); // 1..15
}
return true;
}
bool LedMatrix::setOrientation(ModuleOrientation orientation)
{
moduleOrientation = orientation;
return true;
}
bool LedMatrix::setPixel(int x, int y, bool on)
{
if (x >= width || y >= height)
return false;
int modul_col = x / 8; // x pos divided by 8 is the index of the modul to the right
int buffer_pos = modul_col + y * width / 8;
byte buffer_byte = 8 >> (x % 8);
if (on)
{
buffer[buffer_pos] |= buffer_byte; // set bit
}
else
{
buffer[buffer_pos] &= ~buffer_byte; // reset bit
}
refreshByteOfBuffer(buffer_pos);
return true;
}
void LedMatrix::test()
{
const static byte testMatrix[] PROGMEM = {
B00000010, B00111100, B00111100, B00001000,
B00000110, B01000010, B01000010, B00010000,
B00001010, B00000010, B00000010, B00100000,
B00000010, B00000100, B00001100, B01000100,
B00000010, B00011000, B00000010, B01111110,
B00000010, B00100000, B01000010, B00000100,
B00000000, B11111110, B00111100, B00000100,
B00000000, B00000000, B00000000, B00000000,
};
for (int i = 0; i < 32; i++)
{
buffer[i] = testMatrix[i];
}
refresh();
}
// private
bool LedMatrix::shutdown(bool b)
{
for (int addr = 0; addr < modules; addr++)
{
ledControl->shutdown(addr, b); // b: false: on, true: off
}
return true;
}
void LedMatrix::refresh()
{
for (int i = 0; i < modulesPerRow * height; i++)
{
refreshByteOfBuffer(i);
}
}
void LedMatrix::refreshByteOfBuffer(int i)
{
int line = i / modulesPerRow;
int addr = line / 8 + i % modulesPerRow;
byte b = buffer[i];
if (moduleOrientation == ORIENTATION_NORMAL || moduleOrientation == ORIENTATION_UPSIDE_DOWN)
{
int rowOfAddr = 0;
if (moduleOrientation == ORIENTATION_NORMAL)
{
rowOfAddr = line % 8; // ORIENTATION_NORMAL
}
else
{
rowOfAddr = 7 - line % 8; // ORIENTATION_UPSIDE_DOWN
b = revereBitorder(b);
}
ledControl->setRow(addr, rowOfAddr, b);
}
else
{
// ORIENTATION_TURN_RIGHT or ORIENTATION_TURN_LEFT
int colOfAddr = 0;
if (moduleOrientation == ORIENTATION_TURN_LEFT)
{
colOfAddr = line % 8; // ORIENTATION_TURN_LEFT
}
else
{
colOfAddr = 7 - line % 8; // ORIENTATION_TURN_RIGHT
b = revereBitorder(b);
}
ledControl->setColumn(addr, colOfAddr, b);
}
}
byte LedMatrix::revereBitorder (byte b)
{
const static byte lookup[] PROGMEM = {
0x0, 0x8, 0x4, 0xc, 0x2, 0xa, 0x6, 0xe,
0x1, 0x9, 0x5, 0xd, 0x3, 0xb, 0x7, 0xf,
};
return (lookup[b & 0b1111] << 4) | lookup[b >> 4];
}

View File

@ -0,0 +1,124 @@
/*
* LedMatrix.h - Extends the Library LedControl for multiple LED dot matrix modules, based on MAX7219/MAX7221
* Copyright (c) 2021 Michael Beuss
*
* 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 LedMatrix_h
#define LedMatrix_h
#include <LedControl.h>
#define MATRIX_MAX_MODULES 32
#define MATRIX_BUFFER_SIZE MATRIX_MAX_MODULES * 8 // 8 bytes per modul. One byte represents 8 LEDs.
/**
* @brief LedMatric controls multiple 8x8 LED dot matrx modules.
* All modules in rows and clolums together build a common matrix.
*
*/
class LedMatrix
{
public:
enum ModuleOrientation // orientation of 8x8 LED dot matrix mdules (first module is top left)
{
ORIENTATION_NORMAL, // first pixel is on top left, no turn is necessary
ORIENTATION_TURN_RIGHT, // first pixel is on bottom left, for correction it has to turn 90° right
ORIENTATION_UPSIDE_DOWN, // first pixel is on bottom right, fpr correction it has to turn 180°
ORIENTATION_TURN_LEFT, // first pixel is on top right, for correction is has to turn 90° left.
};
private:
unsigned int modulesPerRow;
unsigned int modulesPerCol;
unsigned int width; // matrix width [pixel]
unsigned int height; // matrix height [pixel]
unsigned int modules; // number of 8x8 mudules
ModuleOrientation moduleOrientation;
byte buffer[MATRIX_BUFFER_SIZE];
LedControl* ledControl;
public:
/**
* @brief Construct a new Led Matrix object
*
* @param colums of 8x8 LED dot matrix modules
* @param rows of 8x8 LED dot matrix modules
*/
LedMatrix(int dataPin, int clkPin, int csPin, unsigned int colums, unsigned int rows);
/**
* @brief Set all LEDs off.
*
*/
bool clear(void);
/**
* @brief Set the brightness of the display
*
* @param dim 0..15
*/
bool setIntensity(byte dim);
/**
* @brief Switches the display on or off
*
* @param on true: on false: off
*/
void power( bool on );
/**
* @brief Set the orientation of the 8x8 LED dot matrix module
*
* @param orientation
*/
bool setOrientation(ModuleOrientation orientation);
/**
* @brief Set the Pixel object
*
* @param x horizontal position from left
* @param y vertical position from top
* @param on true: on, false: off
*/
bool setPixel( int x, int y, bool on);
void test();
private:
bool shutdown(bool b);
/**
* @brief sends the changed content of the buffer to the display
*
*/
void refresh();
void refreshByteOfBuffer( int i);
byte revereBitorder (byte b);
};
#endif //LedMatrix_h

View File

@ -133,70 +133,45 @@ and setting it to 3 alternates between time and date.
#define XDSP_19 19 #define XDSP_19 19
#define CMD_MAX_LEN 55 #define CMD_MAX_LEN 55
#include <LedMatrix.h>
#include <LedControl.h> LedMatrix *max7219_Matrix;
LedControl *max7219_Matrix;
bool max2791Matrix_init_done = false; bool max2791Matrix_init_done = false;
byte modulesPerRow = 4; byte modulesPerRow = 4;
byte modulesPerCol = 1;
bool MAX7291Matrix_init(void) bool MAX7291Matrix_init(void)
{ {
if (!PinUsed(GPIO_MAX7219DIN) || !PinUsed(GPIO_MAX7219CLK) || !PinUsed(GPIO_MAX7219CS)) if (!PinUsed(GPIO_MAX7219DIN) || !PinUsed(GPIO_MAX7219CLK) || !PinUsed(GPIO_MAX7219CS))
{ {
AddLog(LOG_LEVEL_INFO, PSTR("DSP: MAX7291Matrix_init GPIO pins missing DIN, CLK or CS")); AddLog(LOG_LEVEL_INFO, PSTR("DSP: MAX7291Matrix_init GPIO pins missing DIN:%d, CLK:%d, CS:%d"), Pin(GPIO_MAX7219DIN), Pin(GPIO_MAX7219CLK), Pin(GPIO_MAX7219CS) );
return false; // ensure necessariy pins are configurated return false; // ensure necessariy pins are configurated
} }
Settings->display_model = XDSP_19; Settings->display_model = XDSP_19;
if (Settings->display_width) // [pixel]
{
modulesPerRow = (Settings->display_width - 1) / 8 + 1;
}
Settings->display_width = 8 * modulesPerRow;
Settings->display_cols[0] = Settings->display_width; Settings->display_cols[0] = Settings->display_width;
Settings->display_height = 1; if (Settings->display_height) // [pixel]
{
modulesPerCol = (Settings->display_height - 1) / 8 + 1;
}
Settings->display_height = 8 * modulesPerCol;
Settings->display_rows = Settings->display_height; Settings->display_rows = Settings->display_height;
max7219_Matrix = new LedControl(Pin(GPIO_MAX7219DIN), Pin(GPIO_MAX7219CLK), Pin(GPIO_MAX7219CS), modulesPerRow); Settings->display_cols[1] = Settings->display_height;
MAX7291Matrix_On(true); max7219_Matrix = new LedMatrix(Pin(GPIO_MAX7219DIN), Pin(GPIO_MAX7219CLK), Pin(GPIO_MAX7219CS), modulesPerRow, modulesPerCol);
MAX7291Matrix_Clear(); int intensity = GetDisplayDimmer16(); // 0..15
MAX7291Matrix_Dim(); max7219_Matrix->setIntensity(intensity);
AddLog(LOG_LEVEL_INFO, PSTR("DSP: MAX7291Matrix_init")); int orientation = Settings->display_rotate;
max7219_Matrix->setOrientation((LedMatrix::ModuleOrientation)orientation );
AddLog(LOG_LEVEL_INFO, PSTR("DSP: MAX7291Matrix_init %dx%d modules, orientation: %d, intensity: %d"), modulesPerRow , modulesPerCol, orientation, intensity);
max2791Matrix_init_done = true; max2791Matrix_init_done = true;
max7219_Matrix->setLed(0, 3, 3, true); max7219_Matrix->test();
AddLog(LOG_LEVEL_INFO, PSTR("DSP: setLed 3,3")); AddLog(LOG_LEVEL_INFO, PSTR("DSP: display test"));
return true;
}
bool MAX7291Matrix_On( bool on )
{
for (int addr = 0; addr < modulesPerRow; addr++)
{
max7219_Matrix->shutdown (addr, !on); // false: on, true: off
}
AddLog(LOG_LEVEL_INFO, PSTR("MTX: On %d"), on);
return true;
}
bool MAX7291Matrix_Dim(void)
{
int dim = GetDisplayDimmer16();
for (int addr = 0; addr < modulesPerRow; addr++)
{
max7219_Matrix->setIntensity(addr, dim); // 1..15
}
AddLog(LOG_LEVEL_INFO, PSTR("DSP: Dim %d"), dim);
return true;
}
// /*********************************************************************************************\
// * Clears the display
// * Command: DisplayClear
// \*********************************************************************************************/
bool MAX7291Matrix_Clear(void)
{
for(int addr=0; addr<modulesPerRow; addr++){
max7219_Matrix->clearDisplay(addr);
}
AddLog(LOG_LEVEL_INFO, PSTR("DSP: Clear"));
return true; return true;
} }
@ -208,7 +183,7 @@ bool MAX7291Matrix_Text()
{ {
char sString[CMD_MAX_LEN + 1]; char sString[CMD_MAX_LEN + 1];
subStr(sString, XdrvMailbox.data, ",", 1); subStr(sString, XdrvMailbox.data, ",", 1);
MAX7291Matrix_Clear; max7219_Matrix->clear();
AddLog(LOG_LEVEL_DEBUG, PSTR("MTX: sString %s"), sString); AddLog(LOG_LEVEL_DEBUG, PSTR("MTX: sString %s"), sString);
// test // test
@ -216,9 +191,10 @@ bool MAX7291Matrix_Text()
//if(length > modulesPerRow) //if(length > modulesPerRow)
length = modulesPerRow; length = modulesPerRow;
for(int addr = 0; addr<length; addr++ ){ for (int addr = 0; addr < length; addr++)
max7219_Matrix->setLed(addr, 0, 1, true); {
AddLog(LOG_LEVEL_DEBUG, PSTR("MTX: setLed() %d, 0, 1)"), addr); max7219_Matrix->setPixel(addr, addr, true);
AddLog(LOG_LEVEL_DEBUG, PSTR("MTX: setPixel() %d, %d)"), addr, addr);
} }
return true; return true;
@ -228,22 +204,22 @@ bool Xdsp19(uint8_t function)
{ {
bool result = false; bool result = false;
if (FUNC_DISPLAY_INIT_DRIVER == function) if (FUNC_DISPLAY_INIT_DRIVER == function)
{ {
result = MAX7291Matrix_init(); result = MAX7291Matrix_init();
} }
else{ else if (max7219_Matrix && (XDSP_19 == Settings->display_model))
//if (max2791Matrix_init_done && (XDSP_19 == Settings->display_model)) { {
switch (function) { switch (function)
{
case FUNC_DISPLAY_MODEL: case FUNC_DISPLAY_MODEL:
result = true; result = true;
break; break;
case FUNC_DISPLAY_CLEAR: case FUNC_DISPLAY_CLEAR:
result = MAX7291Matrix_Clear(); result = max7219_Matrix->clear();
break; break;
case FUNC_DISPLAY_DIM: case FUNC_DISPLAY_DIM:
result = MAX7291Matrix_Dim(); result = max7219_Matrix->setIntensity(GetDisplayDimmer16());
break; break;
case FUNC_DISPLAY_SEVENSEG_TEXT: case FUNC_DISPLAY_SEVENSEG_TEXT:
case FUNC_DISPLAY_SEVENSEG_TEXTNC: case FUNC_DISPLAY_SEVENSEG_TEXTNC:
@ -269,7 +245,5 @@ bool Xdsp19(uint8_t function)
return result; return result;
} }
#endif // USE_DISPLAY_MAX7219_MATRIX #endif // USE_DISPLAY_MAX7219_MATRIX
#endif // USE_DISPLAY #endif // USE_DISPLAY