Merge pull request #14091 from sternegugger/PR2_MAX7219_dot_matrix

PR2 max7219 dot matrix, less memory
This commit is contained in:
Theo Arends 2021-12-20 11:15:08 +01:00 committed by GitHub
commit d4b9381ab0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 3022 additions and 2 deletions

View File

@ -208,4 +208,3 @@ void LedControl::spiTransfer(int addr, volatile byte opcode, volatile byte data)
digitalWrite(SPI_CS,HIGH);
}

View File

@ -187,4 +187,3 @@ class LedControl {
#endif //LedControl.h

View File

@ -0,0 +1,422 @@
/*
* LedMatrix.h - Extends the Library LedControl for multiple 8x8 LED dot matrix maxDevices, 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"
#include "font_6x8_base.h"
//#include "font_6x8_UTF8_C2.h" // additional characters if needed
//#include "font_6x8_UTF8_C3.h" // additional characters (latin1) if needed
#include "../../../../tasmota/my_user_config.h" // to check compiler option USE_UTF8_LATIN1
#ifdef USE_UTF8_LATIN1
#include "font_6x8_UTF8_C2.h" // 256 bytes
#include "font_6x8_UTF8_C3.h" // 512 bytes
#endif
//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
LedMatrix::LedMatrix(int dataPin, int clkPin, int csPin, unsigned int colums, unsigned int rows)
{
if (colums * rows > MAX72XX_MAX_DEVICES)
{
// dimension exeeds maximum buffer size
if (colums >= MAX72XX_MAX_DEVICES)
{
colums = MAX72XX_MAX_DEVICES;
rows = 1;
}
else
{
rows = MAX72XX_MAX_DEVICES / colums;
}
}
charWidth = font_char_width; // defined in header file of font
charHeight = font_char_height; // defined in header file of font
modulesPerRow = colums;
modulesPerCol = rows;
displayWidth = colums * 8;
displayHeight = rows * 8;
maxDevices = colums * rows;
moduleOrientation = ORIENTATION_UPSIDE_DOWN; // use setOrientation() to turn it
textBuf[0] = 0;
textWidth = 0;
textPosX = 0;
textPosY = 0;
appendTextBuf[0] = 0;
setScrollAppendText(" ");
powerIsOn = false;
// initialize all connected MAX7219/MAX7221 devices
SPI_MOSI = dataPin;
SPI_CLK = clkPin;
SPI_CS = csPin;
pinMode(SPI_MOSI, OUTPUT);
pinMode(SPI_CLK, OUTPUT);
pinMode(SPI_CS, OUTPUT);
SPI_MOSI = dataPin;
//spiTransfer_value(OP_DISPLAYTEST, 0); // display test
spiTransfer_value(OP_SCANLIMIT, 7); // scanlimit is set to max on startup
spiTransfer_value(OP_DECODEMODE, 0); // decode is done in source
clearDisplay();
//spiTransfer_value(OP_SHUTDOWN, 0); //we go into shutdown-mode (LEDs off) on startup
setIntensity(7); // initialize with the half of the maximum intensity [0..15]
power(true); // power on;
}
bool LedMatrix::drawText( const char *str, bool clearBefore)
{
if(clearBefore) clearDisplay();
strncpy(textBuf, str, TEXT_BUFFER_SIZE -1);
textPosX = 0;
textPosY = 0;
textLen = countChars(str);
textWidth = textLen * charWidth;
if(textWidth <= displayWidth)
{
// text fits into the display, place it into the center
textPosX = (displayWidth - textWidth) / 2; // center
}
else
{
// The text ist longer than the display width. Scrolling is needed.
// Add a space in front of text to have a distance to the pervious scroll text.
addSpace();
}
drawTextAt(textBuf, textPosX, textPosY);
refresh(); // refresh display with the new drawed string content
return true;
}
bool LedMatrix::drawTextAt( const char *str, const int x, const int y )
{
// draw character by character
int xPos = x;
const char* fontChar = nullptr;
for (unsigned int i = 0; (i<TEXT_BUFFER_SIZE && str[i]!=0); i++)
{
char c = str[i];
fontChar = font_20_7F[char('_') - 0x20]; // default character in case of non printable or undefined
if( c >= 0x20 && c < 0x80) // basic font
{
fontChar = font_20_7F[c-0x20];
}
#ifdef font_6x8_UTF8_C2_h
else if(c == 0xC2) // UTF special characters
{
i++;
c= str[i];
if(c>= 0xA0 && c < 0xC0)
{
fontChar = font_UTF_C2_A0_BF[c - 0xA0];
}
}
#endif // font_6x8_UTF8_C2_h
#ifdef font_6x8_UTF8_C3_h
else if(c == 0xC3) // UTF latin1
{
i++;
c= str[i];
if(c>= 0x80 && c < 0xC0)
{
fontChar = font_UTF_C3_80_BF[c - 0x80];
}
}
#endif // font_6x8_UTF8_C3_h
else if(c>= 0xC0 && c <= 0xDF)
{
i += 1; // 2 byte UTF sequence
}
else if(c>= 0xE0 && c <= 0xEF)
{
i += 2; // 3 byte UTF sequence
}
else if(c>= 0xF0 && c <= 0xF7)
{
i += 3; // 4 byte UTF sequence
}
drawCharAt(fontChar, xPos, y);
xPos += charWidth;
}
return true;
}
int LedMatrix::countChars( const char* utfText)
{
int len = 0;
for( int i = 0; (i<TEXT_BUFFER_SIZE && utfText[i]!=0); i++)
{
char c = utfText[i];
if( c < 0xC0)
{
// 1 byte UTF sequence
}
else if(c <= 0xDF)
{
i += 1; // 2 byte UTF sequence
}
else if(c <= 0xEF)
{
i += 2; // 3 byte UTF sequence
}
else if(c <= 0xF7)
{
i += 3; // 4 byte UTF sequence
}
len++;
}
return len;
}
bool LedMatrix::scrollText()
{
if(textWidth <= displayWidth) return false; // do not scroll when text fits into the display
textPosX--;
if(textPosX + textWidth < (int)0)
{
textPosX = 0; // start from the beginning after text scrolled out of display;
}
drawTextAt(textBuf, textPosX, textPosY);
int startOfRepeatingTextPos = textPosX + textWidth;
if(startOfRepeatingTextPos < displayWidth)
{
// draw repeating text
drawTextAt(textBuf, startOfRepeatingTextPos, textPosY);
}
refresh();
return true;
}
void LedMatrix::power(bool on)
{
powerIsOn = on;
byte value = 0; // 0: shutdown
if(on) value = 1; // 1: power on
spiTransfer_value(OP_SHUTDOWN, value); // power(false) shuts down the display
}
bool LedMatrix::isPowerOn()
{
return powerIsOn;
}
bool LedMatrix::clearDisplay(void)
{
memset(textBuf, 0, TEXT_BUFFER_SIZE);
textWidth = 0;
memset(buffer, 0, MATRIX_BUFFER_SIZE);
for (int row = 0; row < 8; row++)
{
spiTransfer_value(row + 1, 0);
}
return true;
}
bool LedMatrix::setIntensity(byte intensity)
{
if (intensity < 0 || intensity > 15)
return false;
spiTransfer_value(OP_INTENSITY, intensity);
return true;
}
bool LedMatrix::setOrientation(LedMatrix::ModuleOrientation orientation)
{
if(moduleOrientation != orientation)
{
moduleOrientation = orientation;
refresh();
}
return true;
}
bool LedMatrix::setScrollAppendText(const char* append )
{
strncpy(appendTextBuf, append, TEXT_APPEND_BUFFER_SIZE -1);
return (strlen(append) < TEXT_APPEND_BUFFER_SIZE);
}
bool LedMatrix::setPixel(const int x, const int y, bool on)
{
if (x >= displayWidth || y >= displayHeight)
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 * modulesPerRow;
byte buffer_byte = 0x80 >> (x % 8);
if (on)
{
buffer[buffer_pos] |= buffer_byte; // set bit
}
else
{
buffer[buffer_pos] &= ~buffer_byte; // reset bit
}
return true;
}
void LedMatrix::refresh()
{
int col = 0;
int pixelRow = 0;
int bufPos = 0;
int deviceRow = 0;
for(int ledRow = 7; ledRow >= 0; ledRow--) // refresh from buttom to top
{
for( int addr = 0; addr < maxDevices; addr++)
{
if(moduleOrientation == ORIENTATION_NORMAL || moduleOrientation == ORIENTATION_UPSIDE_DOWN)
{
col = addr % modulesPerRow;
pixelRow = (addr / modulesPerRow) * 8 + ledRow;
bufPos = pixelRow * modulesPerRow + col;
if(moduleOrientation == ORIENTATION_NORMAL)
{
// ORIENTATION_NORMAL
deviceDataBuff[addr] = revereBitorder(buffer[bufPos]); // mirror
deviceRow = 7 - ledRow; // upside down
}
else
{
// ORIENTATION_UPSIDE_DOWN
deviceDataBuff[maxDevices -1 - addr] = buffer[bufPos];
deviceRow = ledRow;
}
}
else // ORIENTATION_TURN_RIGHT || ORIENTATION_TURN_LEFT
{
// not implemented yet
}
}
setRow_allDevices(deviceRow, deviceDataBuff);
}
}
// private functions
/**
* @brief
*
* @param fontChar defines the pixelrows of a character. const char fontChar[charHeight]
* @param x
* @param y
*/
bool LedMatrix::drawCharAt( const char* fontChar, const int x, const int y)
{
// ignore when the character position is not visible on the display
bool visible = (
x > 0 - (int)charWidth && x < (int)displayWidth &&
y > 0 - (int)charHeight && y < (int)displayHeight
);
if (!visible) return false;
// ignore the leading bits above charWidth of the font definition
static const byte charOffset = 8 - charWidth;
for (byte charY = 0; charY < charHeight; charY++)
{
char pixelRow = (fontChar[charY]) << charOffset; // skip the first bits when the character width is smaller than 8 pixel
for (byte charX = 0; charX < charWidth; charX++)
{
bool pixel = (pixelRow & 0x80); // pixel=true when upper bit is set
setPixel(x + charX, y + charY, pixel);
pixelRow = pixelRow << 1; // next pixel
}
}
return true;
}
byte LedMatrix::revereBitorder (byte b)
{
static const byte lookup[16] = {
0x0, 0x8, 0x4, 0xc, 0x2, 0xa, 0x6, 0xe,
0x1, 0x9, 0x5, 0xd, 0x3, 0xb, 0x7, 0xf
};
return (lookup[b & 0b1111] << 4) | lookup[b >> 4];
}
void LedMatrix::addSpace()
{
strncat(textBuf, appendTextBuf, TEXT_BUFFER_SIZE -1);
textPosX = strlen(appendTextBuf) * charWidth; // start scrolling with space
textLen = countChars(textBuf);
textWidth = countChars(textBuf) * charWidth;
}
void LedMatrix::setRow_allDevices(int row, byte *data)
{
if (row < 0 || row > 7)
return;
spiTransfer_array(row + 1, data);
}
void LedMatrix::spiTransfer_array(byte opcode, const byte* data) {
// create an array with the data to shift out
for (int addr = 0; addr < maxDevices; addr++)
{
spidata[addr * 2 + 1] = opcode;
spidata[addr * 2] = data[addr];
}
// enable the line
digitalWrite(SPI_CS, LOW);
// shift out the data
for (int i = maxDevices * 2 -1; i >= 0; i--)
{
shiftOut(SPI_MOSI, SPI_CLK, MSBFIRST, spidata[i]);
}
// latch the data onto the display
digitalWrite(SPI_CS, HIGH);
}
void LedMatrix::spiTransfer_value(byte opcode, byte value)
{
memset(deviceDataBuff, (byte)value, maxDevices);
spiTransfer_array(opcode, deviceDataBuff);
}

View File

@ -0,0 +1,211 @@
/*
* LedMatrix.h - Extends the Library LedControl for multiple 8x8 LED dot matrix devices, 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 <pgmspace.h>
#if (ARDUINO >= 100)
#include <Arduino.h>
#else
#include <WProgram.h>
#endif
#ifndef MAX72XX_MAX_DEVICES
#define MAX72XX_MAX_DEVICES 32 // maximum number of devices based on MXA7219/MAX7221
#endif
#define MATRIX_BUFFER_SIZE MAX72XX_MAX_DEVICES * 8 // 8 bytes per modul. One byte represents 8 LEDs.
#define TEXT_BUFFER_SIZE 256 // maximum text length that can be scrolled
#define TEXT_APPEND_BUFFER_SIZE 16 // used for characters that are appended to the scroll text, before it repeats
#define SPI_BUFFER_SIZE MAX72XX_MAX_DEVICES * 2 // buffer size fort shifting commands to all devices (2 bytes each)
/**
* @brief LedMatrix controls multiple 8x8 LED dot matrx devices.
* All devices in rows and clolums together build a common display pixel matrix.
*
*/
class LedMatrix
{
public:
enum ModuleOrientation // orientation of 8x8 LED dot matrix mdules (first module starts at 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.
};
public:
/**
* @brief Construct a new LED Matrix object
*
* @param colums of 8x8 LED dot matrix devices
* @param rows of 8x8 LED dot matrix devices
*/
LedMatrix(int dataPin, int clkPin, int csPin, unsigned int colums, unsigned int rows);
/**
* @brief Draws a string to the display.
* When the text fits into the display, it will be shown in the center.
* When the text is longer than than the display width, it can be scrolled per pixel with function scrollText().
*
* @param str string to display
* @param clearBefore true (default) clears old display content before, false: do not clear display before
*/
bool drawText( const char *str, bool clearBefore = true );
/**
* @brief Dwaws a character string to a defined display position. The position (x,y) is used for the upper left pixel of the text.
* Existing content outside the drawing text area will not be cleared. But you can use clearDisplay() before.
* Use refresh() after all text parts are drawed.
*
* @param str string to display
* @param x horizantal pixel position to start with string (0 is most left)
* @param y vertical pixel position for the top position of the string (0 is top)
*/
bool drawTextAt( const char *str, const int x, const int y );
/**
* @brief Scroll the current text one pixel to the left.
* Repeat with from start when end of text reached. This function can be called every 50 ms to get a propper scroll speed.
*
*/
bool scrollText();
/**
* @brief switches the display on or off
*
* @param on true: on false: off
*/
void power( bool on );
bool isPowerOn();
/**
* @brief cleares the display and text buffer
*
*/
bool clearDisplay(void);
/**
* @brief Set the brightness of the display
*
* @param dim 0..15 (0: dark .. 15: light)
*/
bool setIntensity(byte dim);
/**
* @brief Set the orientation of the 8x8 LED dot matrix module
*
* @param orientation
*/
bool setOrientation(LedMatrix::ModuleOrientation orientation);
/**
* @brief Set ap pixel at a defined position.
* After all Pixels are set, call refresh() to send it to the display.
*
* @param x horizontal position from left
* @param y vertical position from top
* @param on true: on, false: off
*/
/**
* @brief Adds a string before the scrolling text to set a distance. Usually some spaces are used.
*
* @param append text to append to the scrolling text before repeating.
*/
bool setScrollAppendText(const char* append );
bool setPixel( const int x, const int y, bool on=true);
/**
* @brief sends the changed content of the buffer to the display
*
*/
void refresh();
private:
bool drawCharAt( const char* fontChar, int x, int y ); // Draws a character to a defined position
int countChars( const char* utfText); // count the characters of an UTF8 string. To be uesd instead of strlen().
byte revereBitorder(byte b); // returnes the byte in the reverse bit order.
void addSpace(); // adds characters in front of the text to get a distance to the repeating scroll text
// device contrl MAX7219/MAX7221
/**
* @brief Set data for the same row of all devices
*
* @param row [0..8]
* @param value array of bytes, one for each device
*/
void setRow_allDevices(int row, byte* value);
/* Send out a command with the same opcode to all devices */
/**
* @brief sends opcode with specific data values to each device
*
* @param opcode
* @param data array of byte values (data[0] is the value for the first device)
*/
void spiTransfer_array(byte opcode, const byte* data);
/**
* @brief sends opcode with same value to all devices
*/
void spiTransfer_value(byte opcode, byte value);
private:
int SPI_MOSI; // Data is shifted out of this pin
int SPI_CLK; // The clock is signaled on this pin
int SPI_CS; // This one is driven LOW for chip selectzion
unsigned int modulesPerRow;
unsigned int modulesPerCol;
unsigned int displayWidth; // matrix width [pixel]
unsigned int displayHeight; // matrix height [pixel]
int maxDevices; // number of used 8x8 devices
uint8_t moduleOrientation;
byte buffer[MATRIX_BUFFER_SIZE];
byte deviceDataBuff[MAX72XX_MAX_DEVICES];
int charWidth;
int charHeight;
char textBuf[TEXT_BUFFER_SIZE];
char appendTextBuf[TEXT_APPEND_BUFFER_SIZE];
int textLen; // number of UTF8 characters
int textWidth; // width of text [pixel]
int textPosX; // horizontal pixel position of scrolling text
int textPosY; // vertical pixelposition of scrolling text;
byte spidata[SPI_BUFFER_SIZE]; // The array for shifting the data to the devices
bool powerIsOn;
};
#endif //LedMatrix_h

View File

@ -0,0 +1,340 @@
// 6x8 ascii font
#ifndef font_6x8_UTF8_C2_h
#define font_6x8_UTF8_C2_h
/**
* additional characters to font_6x8_base.h
* 256 bytes
*
*/
/*
UTF8 after 0xC2
0 1 2 3 4 5 6 7 8 9 A B C D E F
A NBSP¡ ¢ £ ¤ ¥ ¦ § ¨ © ª « ¬ SHY ® ¯
B ° ± ² ³ ´ µ · ¸ ¹ º » ¼ ½ ¾ ¿
*/
const char font_UTF_C2_A0_BF[0xC0-0xA0][8] = {
{
0b00000000,
0b00000000,
0b00000000,
0b00000000,
0b00000000,
0b00000000,
0b00000000,
0b00000000,
}, // 0x80 NBSP
{
0b00000100,
0b00000000,
0b00000100,
0b00000100,
0b00001110,
0b00001110,
0b00000100,
0b00000000,
}, // 0x81 ¡
{
0b00000000,
0b00000100,
0b00001110,
0b00010000,
0b00010000,
0b00001110,
0b00000100,
0b00000000,
}, // 0x82 ¢
{
0b00000110,
0b00001001,
0b00001000,
0b00011110,
0b00001000,
0b00001001,
0b00010111,
0b00000000,
}, // 0x83 £
{
0b00010001,
0b00001110,
0b00010001,
0b00010001,
0b00010001,
0b00001110,
0b00010001,
0b00000000,
}, // 0x84 ¤
{
0b00010001,
0b00001010,
0b00000100,
0b00011111,
0b00000100,
0b00011111,
0b00000100,
0b00000000,
}, // 0x85 ¥
{
0b00000100,
0b00000100,
0b00000100,
0b00000000,
0b00000100,
0b00000100,
0b00000100,
0b00000000,
}, // 0x86 ¦
{
0b00001110,
0b00010001,
0b00001100,
0b00001010,
0b00000110,
0b00010001,
0b00001110,
0b00000000,
}, // 0x87 §
{
0b00000000,
0b00000000,
0b00000000,
0b00001010,
0b00000000,
0b00000000,
0b00000000,
0b00000000,
}, // 0x88 ¨
{
0b00011110,
0b00100001,
0b00101101,
0b00101001,
0b00101101,
0b00100001,
0b00011110,
0b00000000,
}, // 0x89 ©
{
0b00001110,
0b00000001,
0b00001111,
0b00010001,
0b00001111,
0b00000000,
0b00001111,
0b00000000,
}, // 0x8A ª
{
0b00000000,
0b00000000,
0b00001001,
0b00010010,
0b00001001,
0b00000000,
0b00000000,
0b00000000,
}, // 0x8B «
{
0b00000000,
0b00000000,
0b00111111,
0b00000001,
0b00000001,
0b00000000,
0b00000000,
0b00000000,
}, // 0x8C ¬
{
0b00000000,
0b00000000,
0b00000000,
0b00000001,
0b00000001,
0b00000000,
0b11111111,
0b00000000,
}, // 0x8D SHY
{
0b00011110,
0b00100101,
0b00101011,
0b00101101,
0b00101011,
0b00100001,
0b00011110,
0b00000000,
}, // 0x8E ®
{
0b00000000,
0b00001110,
0b00000000,
0b00000000,
0b00000000,
0b00000000,
0b00000000,
0b00000000,
}, // 0x8F ¯
{
0b00001100,
0b00010010,
0b00010010,
0b00001100,
0b00000000,
0b00000000,
0b00000000,
0b00000000,
}, // 0x90 °
{
0b00000000,
0b00000100,
0b00001110,
0b00000100,
0b00000000,
0b00001110,
0b00000000,
0b00000000,
}, // 0x91 ±
{
0b00011000,
0b00000100,
0b00001000,
0b00011100,
0b00000000,
0b00000000,
0b00000000,
0b00000000,
}, // 0x92 ²
{
0b00011100,
0b00001000,
0b00001100,
0b00011000,
0b00000000,
0b00000000,
0b00000000,
0b00000000,
}, // 0x93 ³
{
0b00001100,
0b00001100,
0b00001000,
0b00000000,
0b00000000,
0b00000000,
0b00000000,
0b00000000,
}, // 0x94 ´
{
0b00000000,
0b00000000,
0b00010010,
0b00010010,
0b00010010,
0b00011100,
0b00010000,
0b00010000,
}, // 0x95 µ
{
0b00001111,
0b00010101,
0b00010101,
0b00001101,
0b00000101,
0b00000101,
0b00000101,
0b00000000,
}, // 0x96 ¶
{
0b00000000,
0b00000000,
0b00000000,
0b00001000,
0b00000000,
0b00000000,
0b00000000,
0b00000000,
}, // 0x97 ·
{
0b00000000,
0b00000000,
0b00000000,
0b00001110,
0b00000110,
0b00000000,
0b00000000,
0b00000000,
}, // 0x98 ¸
{
0b00001000,
0b00011000,
0b00001000,
0b00001000,
0b00000000,
0b00000000,
0b00000000,
0b00000000,
}, // 0x99 ¹
{
0b00001100,
0b00010010,
0b00010010,
0b00010010,
0b00001100,
0b00000000,
0b00011110,
0b00000000,
}, // 0x9A º
{
0b00000000,
0b00000000,
0b00010010,
0b00001001,
0b00010010,
0b00000000,
0b00000000,
0b00000000,
}, // 0x9B »
{
0b00010000,
0b00010010,
0b00010100,
0b00001011,
0b00010101,
0b00000111,
0b00000001,
0b00000000,
}, // 0x9C ¼
{
0b00010000,
0b00010010,
0b00010100,
0b00001110,
0b00010001,
0b00000010,
0b00000111,
0b00000000,
}, // 0x9D ½
{
0b00110000,
0b00011010,
0b00110100,
0b00001011,
0b00010101,
0b00000111,
0b00000001,
0b00000000,
}, // 0x9E ¾
{
0b00000100,
0b00000000,
0b00000100,
0b00001100,
0b00010000,
0b00010001,
0b00001110,
0b00000000,
}, // 0x9F ¿
};
#endif // font_6x8_UTF8_C2_h

View File

@ -0,0 +1,678 @@
// 6x8 ascii font
#ifndef font_6x8_UTF8_C3_h
#define font_6x8_UTF8_C3_h
/**
* additional characters to font_6x8_base.h
* 512 bytes
*
*/
/*
UTF8 after 0xC3
0 1 2 3 4 5 6 7 8 9 A B C D E F
8 À Á Â Ã Ä Å Æ Ç È É Ê Ë Ì Í Î Ï
9 Ð Ñ Ò Ó Ô Õ Ö × Ø Ù Ú Û Ü Ý Þ ß
A à á â ã ä å æ ç è é ê ë ì í î ï
B ð ñ ò ó ô õ ö ÷ ø ù ú û ü ý þ ÿ
*/
const char font_UTF_C3_80_BF[0xC0-0x80][8] = {
{
0b00001100,
0b00000000,
0b00000100,
0b00001010,
0b00010001,
0b00011111,
0b00010001,
0b00000000,
}, // 0x80 À
{
0b00000110,
0b00000000,
0b00000100,
0b00001010,
0b00010001,
0b00011111,
0b00010001,
0b00000000,
}, // 0x81 Á
{
0b00001110,
0b00000000,
0b00000100,
0b00001010,
0b00010001,
0b00011111,
0b00010001,
0b00000000,
}, // 0x82 Â
{
0b00000101,
0b00001010,
0b00000100,
0b00001010,
0b00010001,
0b00011111,
0b00010001,
0b00000000,
}, // 0x83 Ã
{
0b00001010,
0b00000000,
0b00000100,
0b00001010,
0b00010001,
0b00011111,
0b00010001,
0b00000000,
}, // 0x84 Ä
{
0b00001110,
0b00001010,
0b00001110,
0b00011011,
0b00010001,
0b00011111,
0b00010001,
0b00000000,
}, // 0x85 Å
{
0b00000111,
0b00001100,
0b00010100,
0b00010111,
0b00011100,
0b00010100,
0b00010111,
0b00000000,
}, // 0x86 Æ
{
0b00001110,
0b00010001,
0b00010000,
0b00010000,
0b00010001,
0b00001110,
0b00000100,
0b00001100,
}, // 0x87 Ç
{
0b00001100,
0b00000000,
0b00011111,
0b00010000,
0b00011110,
0b00010000,
0b00011111,
0b00000000,
}, // 0x88 È
{
0b00000011,
0b00000000,
0b00011111,
0b00010000,
0b00011110,
0b00010000,
0b00011111,
0b00000000,
}, // 0x89 É
{
0b00001110,
0b00000000,
0b00011111,
0b00010000,
0b00011110,
0b00010000,
0b00011111,
0b00000000,
}, // 0x8A Ê
{
0b00001010,
0b00000000,
0b00011111,
0b00010000,
0b00011110,
0b00010000,
0b00011111,
0b00000000,
}, // 0x8B Ë
{
0b00001100,
0b00000000,
0b00001110,
0b00000100,
0b00000100,
0b00000100,
0b00001110,
0b00000000,
}, // 0x8C Ì
{
0b00000110,
0b00000000,
0b00001110,
0b00000100,
0b00000100,
0b00000100,
0b00001110,
0b00000000,
}, // 0x8D Í
{
0b00001110,
0b00000000,
0b00001110,
0b00000100,
0b00000100,
0b00000100,
0b00001110,
0b00000000,
}, // 0x8E Î
{
0b00001010,
0b00000000,
0b00001110,
0b00000100,
0b00000100,
0b00000100,
0b00001110,
0b00000000,
}, // 0x8F Ï
{
0b00001110,
0b00001001,
0b00001001,
0b00011101,
0b00001001,
0b00001001,
0b00001110,
0b00000000,
}, // 0x90 Ð
{
0b00001010,
0b00010100,
0b00000000,
0b00010010,
0b00011010,
0b00010110,
0b00010010,
0b00000000,
}, // 0x91 Ñ
{
0b00011000,
0b00001100,
0b00010010,
0b00010010,
0b00010010,
0b00010010,
0b00001100,
0b00000000,
}, // 0x92 Ò
{
0b00000110,
0b00001100,
0b00010010,
0b00010010,
0b00010010,
0b00010010,
0b00001100,
0b00000000,
}, // 0x93 Ó
{
0b00001110,
0b00001100,
0b00010010,
0b00010010,
0b00010010,
0b00010010,
0b00001100,
0b00000000,
}, // 0x94 Ô
{
0b00001010,
0b00010100,
0b00001100,
0b00010010,
0b00010010,
0b00010010,
0b00001100,
0b00000000,
}, // 0x95 Õ
{
0b00010010,
0b00001100,
0b00010010,
0b00010010,
0b00010010,
0b00010010,
0b00001100,
0b00000000,
}, // 0x96 Ö
{
0b00000000,
0b00010001,
0b00001010,
0b00000100,
0b00001010,
0b00010001,
0b00000000,
0b00000000,
}, // 0x97 ×
{
0b00001111,
0b00010011,
0b00010101,
0b00010101,
0b00010101,
0b00011001,
0b00011110,
0b00000000,
}, // 0x98 Ø
{
0b00011000,
0b00000000,
0b00010010,
0b00010010,
0b00010010,
0b00010010,
0b00001100,
0b00000000,
}, // 0x99 Ù
{
0b00000110,
0b00000000,
0b00010010,
0b00010010,
0b00010010,
0b00010010,
0b00001100,
0b00000000,
}, // 0x9A Ú
{
0b00001110,
0b00000000,
0b00010010,
0b00010010,
0b00010010,
0b00010010,
0b00001100,
0b00000000,
}, // 0x9B Û
{
0b00001010,
0b00000000,
0b00010010,
0b00010010,
0b00010010,
0b00010010,
0b00001100,
0b00000000,
}, // 0x9C Ü
{
0b00000110,
0b00000000,
0b00010001,
0b00001010,
0b00000100,
0b00000100,
0b00000100,
0b00000000,
}, // 0x9D Ý
{
0b00011000,
0b00010000,
0b00011100,
0b00010010,
0b00010010,
0b00011100,
0b00010000,
0b00011000,
}, // 0x9E Þ
{
0b00000000,
0b00011100,
0b00010010,
0b00011100,
0b00010010,
0b00010010,
0b00011100,
0b00010000,
}, // 0x9F ß
{
0b00001100,
0b00000000,
0b00001110,
0b00000001,
0b00001111,
0b00010001,
0b00001111,
0b00000000,
}, // 0xA0 à
{
0b00000110,
0b00000000,
0b00001110,
0b00000001,
0b00001111,
0b00010001,
0b00001111,
0b00000000,
}, // 0xA1 á
{
0b00001110,
0b00000000,
0b00001110,
0b00000001,
0b00001111,
0b00010001,
0b00001111,
0b00000000,
}, // 0xA2 â
{
0b00000101,
0b00001010,
0b00001110,
0b00000001,
0b00001111,
0b00010001,
0b00001111,
0b00000000,
}, // 0xA3 ã
{
0b00001010,
0b00000000,
0b00001110,
0b00000001,
0b00001111,
0b00010001,
0b00001111,
0b00000000,
}, // 0xA4 ä
{
0b00001110,
0b00001010,
0b00001110,
0b00000001,
0b00001111,
0b00010001,
0b00001111,
0b00000000,
}, // 0xA5 å
{
0b00000000,
0b00000000,
0b00011110,
0b00000101,
0b00011111,
0b00010100,
0b00001111,
0b00000000,
}, // 0xA6 æ
{
0b00000000,
0b00001110,
0b00010001,
0b00010000,
0b00010001,
0b00001110,
0b00000100,
0b00001100,
}, // 0xA7 ç
{
0b00001100,
0b00000000,
0b00001110,
0b00010001,
0b00011110,
0b00010000,
0b00001110,
0b00000000,
}, // 0xA8 è
{
0b00000011,
0b00000000,
0b00001110,
0b00010001,
0b00011110,
0b00010000,
0b00001110,
0b00000000,
}, // 0xA9 é
{
0b00001110,
0b00000000,
0b00001110,
0b00010001,
0b00011110,
0b00010000,
0b00001110,
0b00000000,
}, // 0xAA ê
{
0b00001010,
0b00000000,
0b00001110,
0b00010001,
0b00011110,
0b00010000,
0b00001110,
0b00000000,
}, // 0xAB ë
{
0b00001000,
0b00000000,
0b00000100,
0b00000100,
0b00000100,
0b00000100,
0b00000110,
0b00000000,
}, // 0xAC ì
{
0b00000110,
0b00000000,
0b00000100,
0b00000100,
0b00000100,
0b00000100,
0b00000110,
0b00000000,
}, // 0xAD í
{
0b00000110,
0b00000000,
0b00000100,
0b00000100,
0b00000100,
0b00000100,
0b00000110,
0b00000000,
}, // 0xAE î
{
0b00001010,
0b00000000,
0b00000100,
0b00000100,
0b00000100,
0b00000100,
0b00000110,
0b00000000,
}, // 0xAF ï
{
0b00001100,
0b00010000,
0b00001000,
0b00000100,
0b00001110,
0b00010010,
0b00001100,
0b00000000,
}, // 0xB0 ð
{
0b00001010,
0b00010100,
0b00000000,
0b00011100,
0b00010010,
0b00010010,
0b00010010,
0b00000000,
}, // 0xB1 ñ
{
0b00011000,
0b00000000,
0b00001100,
0b00010010,
0b00010010,
0b00010010,
0b00001100,
0b00000000,
}, // 0xB2 ò
{
0b00000110,
0b00000000,
0b00001100,
0b00010010,
0b00010010,
0b00010010,
0b00001100,
0b00000000,
}, // 0xB3 ó
{
0b00001110,
0b00000000,
0b00001100,
0b00010010,
0b00010010,
0b00010010,
0b00001100,
0b00000000,
}, // 0xB4 ô
{
0b00001010,
0b00010100,
0b00000000,
0b00001100,
0b00010010,
0b00010010,
0b00001100,
0b00000000,
}, // 0xB5 õ
{
0b00001010,
0b00000000,
0b00001100,
0b00010010,
0b00010010,
0b00010010,
0b00001100,
0b00000000,
}, // 0xB6 ö
{
0b00000000,
0b00000100,
0b00000000,
0b00011111,
0b00000000,
0b00000100,
0b00000000,
0b00000000,
}, // 0xB7 ÷
{
0b00000000,
0b00000000,
0b00000001,
0b00001110,
0b00010110,
0b00011010,
0b00011100,
0b00100000,
}, // 0xB8 ø
{
0b00011000,
0b00000000,
0b00010010,
0b00010010,
0b00010010,
0b00010110,
0b00001010,
0b00000000,
}, // 0xB9 ù
{
0b00000110,
0b00000000,
0b00010010,
0b00010010,
0b00010010,
0b00010110,
0b00001010,
0b00000000,
}, // 0xBA ú
{
0b00001110,
0b00000000,
0b00010010,
0b00010010,
0b00010010,
0b00010110,
0b00001010,
0b00000000,
}, // 0xBB û
{
0b00010010,
0b00000000,
0b00010010,
0b00010010,
0b00010010,
0b00010110,
0b00001010,
0b00000000,
}, // 0xBC ü
{
0b00000110,
0b00000000,
0b00010010,
0b00010010,
0b00010010,
0b00001110,
0b00000100,
0b00011000,
}, // 0xBD ý
{
0b00000000,
0b00011000,
0b00010000,
0b00011100,
0b00010010,
0b00011100,
0b00010000,
0b00011000,
}, // 0xBE þ
{
0b00001010,
0b00000000,
0b00010010,
0b00010010,
0b00010010,
0b00001110,
0b00000100,
0b00011000,
}, // 0xBF ÿ
};
/*
ISO/IEC 8859-1 (latin1)
0 1 2 3 4 5 6 7 8 9 A B C D E F
A NBSP ¡ ¢ £ ¤ ¥ ¦ § ¨ © ª « ¬ SHY ® ¯
B ° ± ² ³ ´ µ · ¸ ¹ º » ¼ ½ ¾ ¿
C À Á Â Ã Ä Å Æ Ç È É Ê Ë Ì Í Î Ï
D Ð Ñ Ò Ó Ô Õ Ö × Ø Ù Ú Û Ü Ý Þ ß
E à á â ã ä å æ ç è é ê ë ì í î ï
F ð ñ ò ó ô õ ö ÷ ø ù ú û ü ý þ ÿ
*/
#endif // font_6x8_UTF8_C3_h

View File

@ -0,0 +1,986 @@
// 6x8 ascii font
#ifndef font_6x8_base_h
#define font_6x8_base_h
/**
* Momory size of basic ascii font: 768 bytes
*
*/
/*
0 1 2 3 4 5 6 7 8 9 A B C D E F
2 SP ! " # $ % & ' ( ) * + , - . /
3 0 1 2 3 4 5 6 7 8 9 : ; < = > ?
4 @ A B C D E F G H I J K L M N O
5 P Q R S T U V W X Y Z [ \ ] ^ _
6 ` a b c d e f g h i j k l m n o
7 p q r s t u v w x y z { | } ~
*/
const unsigned int font_char_width = 6;
const unsigned int font_char_height = 8;
const char font_20_7F[0x80-0x20][8] = {
{
0b00000000,
0b00000000,
0b00000000,
0b00000000,
0b00000000,
0b00000000,
0b00000000,
0b00000000,
}, // 0x20
{
0b00000100,
0b00001110,
0b00001110,
0b00000100,
0b00000100,
0b00000000,
0b00000100,
0b00000000,
}, // 0x21 !
{
0b00011011,
0b00011011,
0b00010010,
0b00000000,
0b00000000,
0b00000000,
0b00000000,
0b00000000,
}, // 0x22 "
{
0b00000000,
0b00001010,
0b00011111,
0b00001010,
0b00001010,
0b00011111,
0b00001010,
0b00000000,
}, // 0x23 #
{
0b00001000,
0b00001110,
0b00010000,
0b00001100,
0b00000010,
0b00011100,
0b00000100,
0b00000000,
}, // 0x24 $
{
0b00011001,
0b00011001,
0b00000010,
0b00000100,
0b00001000,
0b00010011,
0b00010011,
0b00000000,
}, // 0x25 %
{
0b00001000,
0b00010100,
0b00010100,
0b00001000,
0b00010101,
0b00010010,
0b00001101,
0b00000000,
}, // 0x26 &
{
0b00001100,
0b00001100,
0b00001000,
0b00000000,
0b00000000,
0b00000000,
0b00000000,
0b00000000,
}, // 0x27 '
{
0b00000100,
0b00001000,
0b00001000,
0b00001000,
0b00001000,
0b00001000,
0b00000100,
0b00000000,
}, // 0x28 (
{
0b00001000,
0b00000100,
0b00000100,
0b00000100,
0b00000100,
0b00000100,
0b00001000,
0b00000000,
}, // 0x29 )
{
0b00000000,
0b00001010,
0b00001110,
0b00011111,
0b00001110,
0b00001010,
0b00000000,
0b00000000,
}, // 0x2A *
{
0b00000000,
0b00000100,
0b00000100,
0b00011111,
0b00000100,
0b00000100,
0b00000000,
0b00000000,
}, // 0x2B +
{
0b00000000,
0b00000000,
0b00000000,
0b00000000,
0b00000000,
0b00001100,
0b00001100,
0b00001000,
}, // 0x2C ,
{
0b00000000,
0b00000000,
0b00000000,
0b00011111,
0b00000000,
0b00000000,
0b00000000,
0b00000000,
}, // 0x2D -
{
0b00000000,
0b00000000,
0b00000000,
0b00000000,
0b00000000,
0b00001100,
0b00001100,
0b00000000,
}, // 0x2E .
{
0b00000000,
0b00000001,
0b00000010,
0b00000100,
0b00001000,
0b00010000,
0b00000000,
0b00000000,
}, // 0x2F /
{
0b00001110,
0b00010001,
0b00010011,
0b00010101,
0b00011001,
0b00010001,
0b00001110,
0b00000000,
}, // 0x30 0
{
0b00000100,
0b00001100,
0b00000100,
0b00000100,
0b00000100,
0b00000100,
0b00001110,
0b00000000,
}, // 0x31 1
{
0b00001110,
0b00010001,
0b00000001,
0b00000110,
0b00001000,
0b00010000,
0b00011111,
0b00000000,
}, // 0x32 2
{
0b00001110,
0b00010001,
0b00000001,
0b00001110,
0b00000001,
0b00010001,
0b00001110,
0b00000000,
}, // 0x33 3
{
0b00000010,
0b00000110,
0b00001010,
0b00010010,
0b00011111,
0b00000010,
0b00000010,
0b00000000,
}, // 0x34 4
{
0b00011111,
0b00010000,
0b00010000,
0b00011110,
0b00000001,
0b00010001,
0b00001110,
0b00000000,
}, // 0x35 5
{
0b00000110,
0b00001000,
0b00010000,
0b00011110,
0b00010001,
0b00010001,
0b00001110,
0b00000000,
}, // 0x36 6
{
0b00011111,
0b00000001,
0b00000010,
0b00000100,
0b00001000,
0b00001000,
0b00001000,
0b00000000,
}, // 0x37 7
{
0b00001110,
0b00010001,
0b00010001,
0b00001110,
0b00010001,
0b00010001,
0b00001110,
0b00000000,
}, // 0x38 8
{
0b00001110,
0b00010001,
0b00010001,
0b00001111,
0b00000001,
0b00000010,
0b00001100,
0b00000000,
}, // 0x39 9
{
0b00000000,
0b00000000,
0b00001100,
0b00001100,
0b00000000,
0b00001100,
0b00001100,
0b00000000,
}, // 0x3A :
{
0b00000000,
0b00000000,
0b00001100,
0b00001100,
0b00000000,
0b00001100,
0b00001100,
0b00001000,
}, // 0x3B ;
{
0b00000010,
0b00000100,
0b00001000,
0b00010000,
0b00001000,
0b00000100,
0b00000010,
0b00000000,
}, // 0x3C <
{
0b00000000,
0b00000000,
0b00011111,
0b00000000,
0b00000000,
0b00011111,
0b00000000,
0b00000000,
}, // 0x3D =
{
0b00001000,
0b00000100,
0b00000010,
0b00000001,
0b00000010,
0b00000100,
0b00001000,
0b00000000,
}, // 0x3E >
{
0b00001110,
0b00010001,
0b00000001,
0b00000110,
0b00000100,
0b00000000,
0b00000100,
0b00000000,
}, // 0x3F ?
{
0b00001110,
0b00010001,
0b00010111,
0b00010101,
0b00010111,
0b00010000,
0b00001110,
0b00000000,
}, // 0x40 @
{
0b00001110,
0b00010001,
0b00010001,
0b00010001,
0b00011111,
0b00010001,
0b00010001,
0b00000000,
}, // 0x41 A
{
0b00011110,
0b00010001,
0b00010001,
0b00011110,
0b00010001,
0b00010001,
0b00011110,
0b00000000,
}, // 0x42 B
{
0b00001110,
0b00010001,
0b00010000,
0b00010000,
0b00010000,
0b00010001,
0b00001110,
0b00000000,
}, // 0x43 C
{
0b00011110,
0b00010001,
0b00010001,
0b00010001,
0b00010001,
0b00010001,
0b00011110,
0b00000000,
}, // 0x44 D
{
0b00011111,
0b00010000,
0b00010000,
0b00011110,
0b00010000,
0b00010000,
0b00011111,
0b00000000,
}, // 0x45 E
{
0b00011111,
0b00010000,
0b00010000,
0b00011110,
0b00010000,
0b00010000,
0b00010000,
0b00000000,
}, // 0x46 F
{
0b00001110,
0b00010001,
0b00010000,
0b00010111,
0b00010001,
0b00010001,
0b00001111,
0b00000000,
}, // 0x47 G
{
0b00010001,
0b00010001,
0b00010001,
0b00011111,
0b00010001,
0b00010001,
0b00010001,
0b00000000,
}, // 0x48 H
{
0b00001110,
0b00000100,
0b00000100,
0b00000100,
0b00000100,
0b00000100,
0b00001110,
0b00000000,
}, // 0x49 I
{
0b00000001,
0b00000001,
0b00000001,
0b00000001,
0b00010001,
0b00010001,
0b00001110,
0b00000000,
}, // 0x4A J
{
0b00010001,
0b00010010,
0b00010100,
0b00011000,
0b00010100,
0b00010010,
0b00010001,
0b00000000,
}, // 0x4B K
{
0b00010000,
0b00010000,
0b00010000,
0b00010000,
0b00010000,
0b00010000,
0b00011111,
0b00000000,
}, // 0x4C L
{
0b00010001,
0b00011011,
0b00010101,
0b00010001,
0b00010001,
0b00010001,
0b00010001,
0b00000000,
}, // 0x4D M
{
0b00010001,
0b00011001,
0b00010101,
0b00010011,
0b00010001,
0b00010001,
0b00010001,
0b00000000,
}, // 0x4E N
{
0b00001110,
0b00010001,
0b00010001,
0b00010001,
0b00010001,
0b00010001,
0b00001110,
0b00000000,
}, // 0x4F O
{
0b00011110,
0b00010001,
0b00010001,
0b00011110,
0b00010000,
0b00010000,
0b00010000,
0b00000000,
}, // 0x50 P
{
0b00001110,
0b00010001,
0b00010001,
0b00010001,
0b00010101,
0b00010010,
0b00001101,
0b00000000,
}, // 0x51 Q
{
0b00011110,
0b00010001,
0b00010001,
0b00011110,
0b00010010,
0b00010001,
0b00010001,
0b00000000,
}, // 0x52 R
{
0b00001110,
0b00010001,
0b00010000,
0b00001110,
0b00000001,
0b00010001,
0b00001110,
0b00000000,
}, // 0x53 S
{
0b00011111,
0b00000100,
0b00000100,
0b00000100,
0b00000100,
0b00000100,
0b00000100,
0b00000000,
}, // 0x54 T
{
0b00010001,
0b00010001,
0b00010001,
0b00010001,
0b00010001,
0b00010001,
0b00001110,
0b00000000,
}, // 0x55 U
{
0b00010001,
0b00010001,
0b00010001,
0b00010001,
0b00010001,
0b00001010,
0b00000100,
0b00000000,
}, // 0x56 V
{
0b00010001,
0b00010001,
0b00010101,
0b00010101,
0b00010101,
0b00010101,
0b00001010,
0b00000000,
}, // 0x57 W
{
0b00010001,
0b00010001,
0b00001010,
0b00000100,
0b00001010,
0b00010001,
0b00010001,
0b00000000,
}, // 0x58 X
{
0b00010001,
0b00010001,
0b00010001,
0b00001010,
0b00000100,
0b00000100,
0b00000100,
0b00000000,
}, // 0x59 Y
{
0b00011110,
0b00000010,
0b00000100,
0b00001000,
0b00010000,
0b00010000,
0b00011110,
0b00000000,
}, // 0x5A Z
{
0b00001110,
0b00001000,
0b00001000,
0b00001000,
0b00001000,
0b00001000,
0b00001110,
0b00000000,
}, // 0x5B [
{
0b00000000,
0b00010000,
0b00001000,
0b00000100,
0b00000010,
0b00000001,
0b00000000,
0b00000000,
}, // 0x5C backslash
{
0b00001110,
0b00000010,
0b00000010,
0b00000010,
0b00000010,
0b00000010,
0b00001110,
0b00000000,
}, // 0x5D ]
{
0b00000100,
0b00001010,
0b00010001,
0b00000000,
0b00000000,
0b00000000,
0b00000000,
0b00000000,
}, // 0x5E ^
{
0b00000000,
0b00000000,
0b00000000,
0b00000000,
0b00000000,
0b00000000,
0b00000000,
0b00111111,
}, // 0x5F _
{
0b00001100,
0b00001100,
0b00000100,
0b00000000,
0b00000000,
0b00000000,
0b00000000,
0b00000000,
}, // 0x60 `
{
0b00000000,
0b00000000,
0b00001110,
0b00000001,
0b00001111,
0b00010001,
0b00001111,
0b00000000,
}, // 0x61 a
{
0b00010000,
0b00010000,
0b00011110,
0b00010001,
0b00010001,
0b00010001,
0b00011110,
0b00000000,
}, // 0x62 b
{
0b00000000,
0b00000000,
0b00001110,
0b00010001,
0b00010000,
0b00010001,
0b00001110,
0b00000000,
}, // 0x63 c
{
0b00000001,
0b00000001,
0b00001111,
0b00010001,
0b00010001,
0b00010001,
0b00001111,
0b00000000,
}, // 0x64 d
{
0b00000000,
0b00000000,
0b00001110,
0b00010001,
0b00011110,
0b00010000,
0b00001110,
0b00000000,
}, // 0x65 e
{
0b00000110,
0b00001000,
0b00001000,
0b00011110,
0b00001000,
0b00001000,
0b00001000,
0b00000000,
}, // 0x66 f
{
0b00000000,
0b00000000,
0b00001111,
0b00010001,
0b00010001,
0b00001111,
0b00000001,
0b00001110,
}, // 0x67 g
{
0b00010000,
0b00010000,
0b00011100,
0b00010010,
0b00010010,
0b00010010,
0b00010010,
0b00000000,
}, // 0x68 h
{
0b00000100,
0b00000000,
0b00000100,
0b00000100,
0b00000100,
0b00000100,
0b00000110,
0b00000000,
}, // 0x69 i
{
0b00000010,
0b00000000,
0b00000110,
0b00000010,
0b00000010,
0b00000010,
0b00010010,
0b00001100,
}, // 0x6A j
{
0b00010000,
0b00010000,
0b00010010,
0b00010100,
0b00011000,
0b00010100,
0b00010010,
0b00000000,
}, // 0x6B k
{
0b00000100,
0b00000100,
0b00000100,
0b00000100,
0b00000100,
0b00000100,
0b00000110,
0b00000000,
}, // 0x6C l
{
0b00000000,
0b00000000,
0b00011010,
0b00010101,
0b00010101,
0b00010001,
0b00010001,
0b00000000,
}, // 0x6D m
{
0b00000000,
0b00000000,
0b00011100,
0b00010010,
0b00010010,
0b00010010,
0b00010010,
0b00000000,
}, // 0x6E n
{
0b00000000,
0b00000000,
0b00001110,
0b00010001,
0b00010001,
0b00010001,
0b00001110,
0b00000000,
}, // 0x6F o
{
0b00000000,
0b00000000,
0b00011110,
0b00010001,
0b00010001,
0b00010001,
0b00011110,
0b00010000,
}, // 0x70 p
{
0b00000000,
0b00000000,
0b00001111,
0b00010001,
0b00010001,
0b00010001,
0b00001111,
0b00000001,
}, // 0x71 q
{
0b00000000,
0b00000000,
0b00010110,
0b00001001,
0b00001000,
0b00001000,
0b00011100,
0b00000000,
}, // 0x72 r
{
0b00000000,
0b00000000,
0b00001110,
0b00010000,
0b00001110,
0b00000001,
0b00001110,
0b00000000,
}, // 0x73 s
{
0b00000000,
0b00001000,
0b00011110,
0b00001000,
0b00001000,
0b00001010,
0b00000100,
0b00000000,
}, // 0x74 t
{
0b00000000,
0b00000000,
0b00010010,
0b00010010,
0b00010010,
0b00010110,
0b00001010,
0b00000000,
}, // 0x75 u
{
0b00000000,
0b00000000,
0b00010001,
0b00010001,
0b00010001,
0b00001010,
0b00000100,
0b00000000,
}, // 0x76 v
{
0b00000000,
0b00000000,
0b00010001,
0b00010001,
0b00010101,
0b00011111,
0b00001010,
0b00000000,
}, // 0x77 w
{
0b00000000,
0b00000000,
0b00010010,
0b00010010,
0b00001100,
0b00010010,
0b00010010,
0b00000000,
}, // 0x78 x
{
0b00000000,
0b00000000,
0b00010010,
0b00010010,
0b00010010,
0b00001110,
0b00000100,
0b00011000,
}, // 0x79 y
{
0b00000000,
0b00000000,
0b00011110,
0b00000010,
0b00001100,
0b00010000,
0b00011110,
0b00000000,
}, // 0x7A z
{
0b00000110,
0b00001000,
0b00001000,
0b00011000,
0b00001000,
0b00001000,
0b00000110,
0b00000000,
}, // 0x7B {
{
0b00000100,
0b00000100,
0b00000100,
0b00000000,
0b00000100,
0b00000100,
0b00000100,
0b00000000,
}, // 0x7C |
{
0b00001100,
0b00000010,
0b00000010,
0b00000011,
0b00000010,
0b00000010,
0b00001100,
0b00000000,
}, // 0x7D }
{
0b00001010,
0b00010100,
0b00000000,
0b00000000,
0b00000000,
0b00000000,
0b00000000,
0b00000000,
}, // 0x7E ~
{
0b00000100,
0b00001110,
0b00011011,
0b00010001,
0b00010001,
0b00011111,
0b00000000,
0b00000000,
}, // 0x7F ␡
};
#endif // font_6x8_base_h

View File

@ -523,6 +523,15 @@ const uint16_t kGpioNiceList[] PROGMEM = {
AGPIO(GPIO_SSD1331_CS),
AGPIO(GPIO_SSD1331_DC),
#endif // USE_DISPLAY_SSD1331
#ifdef USE_DISPLAY_MAX7219_MATRIX
#undef USE_DISPLAY_MAX7219
#undef USE_DISPLAY_TM1637
AGPIO(GPIO_MAX7219CLK),
AGPIO(GPIO_MAX7219DIN),
AGPIO(GPIO_MAX7219CS),
#endif // USE_DISPLAY_MAX7219_MATRIX
#ifdef USE_DISPLAY_TM1637
AGPIO(GPIO_TM1637CLK),
AGPIO(GPIO_TM1637DIO),

View File

@ -0,0 +1,376 @@
/*
xdsp_19_max7219_matrix.ino.ino - Support for MAX7219 based 8x8 dot matrix displays for Tasmota
Copyright (C) 2021 Michael Beuss
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_MATRIX
/*********************************************************************************************\
This driver enables the display of ascii text on MAX7219 based 8x8 LED dot matrix modules (1088AS).
Connect the MAX7219 display module's pins to any free GPIOs of the ESP8266 or ESP32 module.
VCC should be 5V. Depending on the number of used modules and the brightness, the used current can be more than 500 mA.
Connect the 5 outgoing pins (VCC, GND, DI, CS, CLK) of the first module to the next one.
With this you can connect up to 32 modules.
To extend the display hieght, multiple rows are supported. Each module row starts from left to right.
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 19 and Display Mode to 0
Depending on order of the wired 8x8 matrix modules you have got a display of size pixel_width x pixel_height.
The size has to be set with the commands "DisplayWidth <pixel_width>" and "DisplayHeight <pixel_height>"
After the ESP8266/ESP32 module restarts again, turn ON the display with the command "Power 1"
Now, the following "Display" commands can be used:
DisplayText text
Sends the text to the display.
If the text fits into the display, it is shown in the center.
Otherwise it scrolls to the left and repeats as long it is cleared or new "DisplayText" overwrites it.
DisplayDimmer [0..100]
Sets the intensity of the display.
DisplayBlinkrate [0..3]
0: not blinking
1: slow, 2: medium 3: fast blinking
Power [ON|OFF]
Sitches the display on or off. When "off", the display buffer is not cleared and will be shown again when after "Power ON".
Other display commands are still active when off.
DisplayClear
Clears the display
DisplayScrollDelay [0..15] // default = 0
Sets the speed of text scroll. Smaller delay = faster scrolling.
The maximum scroll speed is 50ms per pixel on DisplayScrollDelay 0.
DisplayWidth [8..256]
Sets the pixel width of the display (8x number of modules in a row)
DisplayHeight [8..256]
Sets the pixel height of the display (8x number of module rows)
DisplayRotate [0|2]
0: normal orientation; devide 0 starts at top left
2: upside down; device 0 starts at bottom right
DisplayClock [0|1|2]
Displays a clock.
Commands "DisplayClock 1" // 12 hr format
"DisplayClock 2" // 24 hr format
"DisplayClock 0" // turn off clock; please use additional cammand: DisplayMode 0
If you would like to use the UTF8 latin1 character set, it cam be added by copile option:
#define USE_UTF8_LATIN1
\*********************************************************************************************/
#define XDSP_19 19
#include <LedMatrix.h>
LedMatrix *max7219_Matrix = nullptr;
bool max2791Matrix_initDriver_done = false;
struct
{
byte modulesPerRow = 4;
byte modulesPerCol = 1;
byte scroll_delay = 0;
byte scroll_iteration = 0;
bool show_clock = false;
bool timeFormat24 = true;
byte blink_delay = 0; // 0: not blinking
byte blink_iteration = 0;
} LedMatrix_settings;
// FUNC_DISPLAY_INIT_DRIVER
bool MAX7291Matrix_initDriver(void)
{
if (!PinUsed(GPIO_MAX7219DIN) || !PinUsed(GPIO_MAX7219CLK) || !PinUsed(GPIO_MAX7219CS))
{
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
}
Settings->display_model = XDSP_19;
renderer = nullptr; // renderer not yet used
if (Settings->display_width) // [pixel]
{
LedMatrix_settings.modulesPerRow = (Settings->display_width - 1) / 8 + 1;
}
Settings->display_width = 8 * LedMatrix_settings.modulesPerRow;
Settings->display_cols[0] = LedMatrix_settings.modulesPerRow;
if (Settings->display_height) // [pixel]
{
LedMatrix_settings.modulesPerCol = (Settings->display_height - 1) / 8 + 1;
}
Settings->display_height = 8 * LedMatrix_settings.modulesPerCol;
Settings->display_rows = LedMatrix_settings.modulesPerCol;
Settings->display_cols[1] = LedMatrix_settings.modulesPerCol;
max7219_Matrix = new LedMatrix(Pin(GPIO_MAX7219DIN), Pin(GPIO_MAX7219CLK), Pin(GPIO_MAX7219CS), LedMatrix_settings.modulesPerRow, LedMatrix_settings.modulesPerCol);
max2791Matrix_initDriver_done = true;
AddLog(LOG_LEVEL_INFO, PSTR("MTX: MAX7291Matrix_initDriver DIN:%d CLK:%d CS:%d size(%dx%d)"), Pin(GPIO_MAX7219DIN), Pin(GPIO_MAX7219CLK), Pin(GPIO_MAX7219CS), LedMatrix_settings.modulesPerRow, LedMatrix_settings.modulesPerCol);
return MAX7291Matrix_init();
}
// FUNC_DISPLAY_INIT
bool MAX7291Matrix_init(void)
{
Settings->display_mode = 0; // text mode
LedMatrix_settings.show_clock = 0; // no
LedMatrix_settings.blink_delay = 0; // no blinking
int intensity = GetDisplayDimmer16(); // 0..15
max7219_Matrix->setIntensity(intensity);
max7219_Matrix->power(true); // power on
if(Settings->display_rotate <= 3)
{
max7219_Matrix->setOrientation((LedMatrix::ModuleOrientation)Settings->display_rotate );
}
else
{
// default for most 32x8 modules
Settings->display_rotate = LedMatrix::ORIENTATION_UPSIDE_DOWN;
max7219_Matrix->setOrientation( LedMatrix::ORIENTATION_UPSIDE_DOWN );
}
AddLog(LOG_LEVEL_INFO, PSTR("MTX: MAX7291Matrix_init orientation: %d, intensity: %d"), Settings->display_rotate, intensity);
return true;
}
bool MAX7291Matrix_setText(bool clearBefore=true)
{
if(Settings->display_mode != 0) MAX7291Matrix_init();
LedMatrix_settings.blink_delay = 0; // no blinking
return max7219_Matrix->drawText(XdrvMailbox.data, clearBefore);
}
// FUNC_DISPLAY_SCROLLDELAY
bool MAX7291Matrix_scrollDelay(void)
{
if (ArgC() == 0)
{
XdrvMailbox.payload = LedMatrix_settings.scroll_delay;
return true;
}
if (LedMatrix_settings.scroll_delay < 0)
LedMatrix_settings.scroll_delay = 0;
LedMatrix_settings.scroll_delay = XdrvMailbox.payload;
return true;
}
// FUNC_DISPLAY_EVERY_50_MSECOND
bool MAX7291Matrix_scrollText(void)
{
// This function is called every 50 ms.
// scroll_delay defines the number of cycles to be ignored until the display scrolls by one pixel to the left.
// e.g. scrall_delay = 4 causes a scroll each 200 ms.
if(!max7219_Matrix->isPowerOn()) return false; // do not scroll on power off
LedMatrix_settings.scroll_iteration++;
if (LedMatrix_settings.scroll_delay)
LedMatrix_settings.scroll_iteration = LedMatrix_settings.scroll_iteration % LedMatrix_settings.scroll_delay;
else
LedMatrix_settings.scroll_iteration = 0;
if (LedMatrix_settings.scroll_iteration)
return false;
return max7219_Matrix->scrollText();
}
bool MAX7291Matrix_blink(void)
{
// This function is called every 50 ms.
// blink_delay defines the number of cycles to be ignored until the blinkstate changes.
if(LedMatrix_settings.blink_delay == 0) return false;
LedMatrix_settings.blink_iteration++;
if(LedMatrix_settings.blink_iteration == LedMatrix_settings.blink_delay)
{
max7219_Matrix->power(false);
}
else if(LedMatrix_settings.blink_iteration == 2* LedMatrix_settings.blink_delay )
{
LedMatrix_settings.blink_iteration = 0;
max7219_Matrix->power(true);
}
return true;
}
bool MAX7291Matrix_setBlinkRate()
{
LedMatrix_settings.blink_iteration = 0;
max7219_Matrix->power(true);
if (ArgC() == 0)
{
XdrvMailbox.payload = 0;
}
if (XdrvMailbox.payload)
LedMatrix_settings.blink_delay = 20 / XdrvMailbox.payload; // 1: once per second; 2: twice per second; 3: three times per second
else
LedMatrix_settings.blink_delay = 0; // do not blink
return true;
}
#ifdef USE_DISPLAY_MODES1TO5
// FUNC_DISPLAY_CLOCK
bool MAX7291Matrix_clock(void)
{
LedMatrix_settings.show_clock = XdrvMailbox.payload;
if (ArgC() == 0)
XdrvMailbox.payload = 2;
switch(XdrvMailbox.payload)
{
case 0:
// no clock, switch to text mode
Settings->display_mode = 0;
return true;
case 1:
// 12 h clock
LedMatrix_settings.timeFormat24 = false;
Settings->display_mode = 1;
break;
case 2:
// 24 h clock
LedMatrix_settings.timeFormat24 = true;
Settings->display_mode = 1;
break;
default:
return false;
}
AddLog(LOG_LEVEL_DEBUG, PSTR("MTX: LedMatrix_settings.show_clock %d, 24h: %b"), LedMatrix_settings.show_clock, LedMatrix_settings.timeFormat24);
max7219_Matrix->clearDisplay();
MAX7291Matrix_showTime();
return true;
}
// FUNC_DISPLAY_EVERY_SECOND
bool MAX7291Matrix_showTime()
{
if(!LedMatrix_settings.show_clock) return false;
uint8_t hr = RtcTime.hour;
uint8_t mn = RtcTime.minute;
uint8_t sc = RtcTime.second;
char timeStr[10];
if(!LedMatrix_settings.timeFormat24)
{
if(hr == 0) hr = 12;
if(hr > 12 ) hr -= 12;
}
if(LedMatrix_settings.modulesPerRow >= 6)
{
snprintf(timeStr, 10, "%02d:%02d:%02d", hr , mn, sc);
}
else
{
snprintf(timeStr, 10, "%02d:%02d", hr , mn);
}
max7219_Matrix->drawText(timeStr, false); // false: do not clear desplay on update to prevent flicker
return true;
}
#endif // USE_DISPLAY_MODES1TO5
bool Xdsp19(uint8_t function)
{
bool result = false;
if (FUNC_DISPLAY_INIT_DRIVER == function && !max2791Matrix_initDriver_done )
{
result = MAX7291Matrix_initDriver();
}
else if (max2791Matrix_initDriver_done && max7219_Matrix && (XDSP_19 == Settings->display_model))
{
switch (function)
{
case FUNC_DISPLAY_INIT:
result = MAX7291Matrix_init();
break;
case FUNC_DISPLAY_POWER:
max7219_Matrix->power(disp_power!=0);
break;
case FUNC_DISPLAY_MODEL:
result = true;
break;
case FUNC_DISPLAY_CLEAR:
result = max7219_Matrix->clearDisplay();
break;
case FUNC_DISPLAY_DIM:
result = max7219_Matrix->setIntensity(GetDisplayDimmer16());
break;
case FUNC_DISPLAY_DRAW_STRING:
case FUNC_DISPLAY_SCROLLTEXT:
case FUNC_DISPLAY_SEVENSEG_TEXT:
result = MAX7291Matrix_setText(true); // true: clears display before drawing text
break;
case FUNC_DISPLAY_SEVENSEG_TEXTNC:
result = MAX7291Matrix_setText(false); // false: does not clear display before drawing text
break;
case FUNC_DISPLAY_SCROLLDELAY:
result = MAX7291Matrix_scrollDelay();
break;
case FUNC_DISPLAY_BLINKRATE:
{
result = MAX7291Matrix_setBlinkRate();
break;
}
case FUNC_DISPLAY_EVERY_50_MSECOND:
MAX7291Matrix_blink();
result = MAX7291Matrix_scrollText();
break;
#ifdef USE_DISPLAY_MODES1TO5
case FUNC_DISPLAY_CLOCK:
result = MAX7291Matrix_clock();
break;
case FUNC_DISPLAY_EVERY_SECOND:
if (LedMatrix_settings.show_clock)
{
result = MAX7291Matrix_showTime();
}
break;
#endif // USE_DISPLAY_MODES1TO5
default:
result = false;
}
}
return result;
}
#endif // USE_DISPLAY_MAX7219_MATRIX
#endif // USE_DISPLAY