// https://kit.alexgyver.ru/tutorials/max7219/
#include "MAX7219.h"
#define CLK 18
#define DATA 23
#define CS 15
#define X_SEGMENTS 8
#define Y_SEGMENTS 2
#define AM_W X_SEGMENTS * 8 // 8 матрицы (64 точки)
#define AM_H Y_SEGMENTS * 8 // 2 матрицы (16 точек)
//MAX7219 < W, H, CS, DATA, CLK > mtrx; // подключение к любым пинам
// W и H - количество МАТРИЦ по горизонтали и вертикали
// CS, DATA, CLK - номера пинов
MAX7219 < X_SEGMENTS, Y_SEGMENTS, CS, DATA, CLK > mtrx;
// дисплей 8х2, пин CS 5, остальные на аппаратный SPI
// MAX7219 < 8, 2, 5 > mtrx;
// каждый массив - одby emoji
const uint8_t angryface_B[] PROGMEM = {0x00, 0x66, 0x66, 0x00, 0x18, 0x24, 0x42, 0x81};
const uint8_t circle_B[] PROGMEM = {0x3c, 0x42, 0x81, 0x81, 0x81, 0x81, 0x42, 0x3c};
const uint8_t cdot_B[] PROGMEM = {0x3c, 0x42, 0x81, 0x99, 0x99, 0x81, 0x42, 0x3c};
const uint8_t donut_B[] PROGMEM = {0x3c, 0x7e, 0xff, 0xe7, 0xe7, 0xff, 0x7e, 0x3c};
const uint8_t equality_B[] PROGMEM = {0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00};
const uint8_t ball_B[] PROGMEM = {0x3c, 0x7e, 0xff, 0xff, 0xff, 0xff, 0x7e, 0x3c};
const uint8_t thinsquare_B[] PROGMEM = {0xff, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0xff};
const uint8_t thicksquare_B[] PROGMEM = {0xff, 0xff, 0xc3, 0xc3, 0xc3, 0xc3, 0xff, 0xff};
const uint8_t centeredsquare1_B[] PROGMEM = {0x00, 0x00, 0x3c, 0x3c, 0x3c, 0x3c, 0x00, 0x00};
const uint8_t centeredsquare2_B[] PROGMEM = {0x00, 0x00, 0x3c, 0x3c, 0x3c, 0x3c, 0x00, 0x00};
const uint8_t arrowright_B[] PROGMEM = {0x00, 0x04, 0x06, 0xff, 0xff, 0x06, 0x04, 0x00};
const uint8_t arrowleft_B[] PROGMEM = {0x00, 0x20, 0x60, 0xff, 0xff, 0x60, 0x20, 0x00};
const uint8_t note_B[] PROGMEM = {0x04, 0x06, 0x07, 0x04, 0x3c, 0x7c, 0x7c, 0x38};
const uint8_t clock_B[] PROGMEM = {0x3c, 0x52, 0x91, 0x91, 0x8f, 0x81, 0x42, 0x3c};
const uint8_t heartoutline_B[] PROGMEM = {0x66, 0x99, 0x81, 0x81, 0x42, 0x24, 0x18, 0x00};
const uint8_t heartfull_B[] PROGMEM = {0x66, 0xff, 0xff, 0xff, 0x7e, 0x3c, 0x18, 0x00};
const uint8_t thincheck_B[] PROGMEM = {0x00, 0x00, 0x01, 0x02, 0x04, 0x88, 0x50, 0x20};
const uint8_t thickcheck_B[] PROGMEM = {0x00, 0x01, 0x03, 0x06, 0x8c, 0xd8, 0x70, 0x20};
const uint8_t speaker_B[] PROGMEM = {0x03, 0x07, 0x3f, 0x3f, 0x3f, 0x3f, 0x07, 0x03};
const uint8_t sound_B[] PROGMEM = {0x00, 0x40, 0x80, 0x00, 0xc0, 0x00, 0x80, 0x40};
const uint8_t xbig_B[] PROGMEM = {0xc3, 0xe7, 0x7e, 0x3c, 0x3c, 0x7e, 0xe7, 0xc3};
const uint8_t target_B[] PROGMEM = {0x3c, 0x7e, 0xc3, 0xdb, 0xdb, 0xc3, 0x7e, 0x3c};
const uint8_t bell_B[] PROGMEM = {0x18, 0x3c, 0x3c, 0x3c, 0x3c, 0x7e, 0x00, 0x18};
const uint8_t smile_B[] PROGMEM = {0x00, 0x66, 0x66, 0x00, 0x00, 0x81, 0x42, 0x3c};
const uint8_t frown_B[] PROGMEM = {0x00, 0x66, 0x66, 0x00, 0x00, 0x3c, 0x42, 0x81};
const uint8_t winkright_B[] PROGMEM = {0x00, 0x60, 0x66, 0x00, 0x00, 0x81, 0x42, 0x3c};
const uint8_t winkleft_B[] PROGMEM = {0x00, 0x06, 0x66, 0x00, 0x00, 0x81, 0x42, 0x3c};
const uint8_t blink_B[] PROGMEM = {0x00, 0x00, 0x66, 0x00, 0x00, 0x81, 0x42, 0x3c};
const uint8_t laughing_B[] PROGMEM = {0x00, 0x66, 0x66, 0x00, 0xff, 0x81, 0x42, 0x3c};
const uint8_t tongueout_B[] PROGMEM = {0x00, 0x66, 0x66, 0x00, 0x00, 0x7e, 0x0a, 0x04};
const uint8_t expressionless_B[] PROGMEM = {0x00, 0x66, 0x66, 0x00, 0x00, 0xff, 0x00, 0x00};
// список массивов для вывода в цикле
const uint8_t* const emojis[] PROGMEM = {
angryface_B, circle_B, cdot_B, donut_B, equality_B, ball_B, thinsquare_B, thicksquare_B,
centeredsquare1_B, centeredsquare2_B, arrowright_B, arrowleft_B, note_B, clock_B, heartoutline_B, heartfull_B,
thincheck_B, thickcheck_B, speaker_B, sound_B, xbig_B, target_B, bell_B, smile_B,
frown_B, winkright_B, winkleft_B, blink_B, laughing_B, tongueout_B, expressionless_B,
};
String tape = "MAX7219";
int spacer = 1;
int width = 5 + spacer;
unsigned long ticker_next;
void handleTicker(uint8_t size = 1);
void setup() {
// put your setup code here, to run once:
Serial.begin(115200);
Serial.println("Hello, ESP32!");
mtrx.begin(); // запускаем
mtrx.setBright(2); // яркость 0..15
//mtrx.setRotation(1); // можно повернуть 0..3, по 90 град по часовой стрелке
tape = "іЖІїЇ - Привіт, ESP32!";
// for (int b = 0; b < 100; b++) {
handleTicker(2);
// }
delay(1000);
mtrx.clear();
mtrx.drawChar(1,1,'A');
mtrx.update();
delay(4000);
mtrx.clear();
mtrx.drawChar(1,1,'1', GFX_FILL, 2);
mtrx.update();
delay(4000);
mtrx.clear();
mtrx.dot(0, 0); // пиксель на координатах 0,0
mtrx.update(); // показать
delay(1000);
mtrx.clear();
// линии крест накрест
mtrx.line(0, 0, 7, 7); // (x0, y0, x1, y1)
mtrx.line(7, 0, 0, 7);
mtrx.update();
delay(1000);
mtrx.clear();
// круг
mtrx.circle(3, 3, 3, GFX_FILL); // х, у, радиус, заливка
mtrx.update();
delay(1000);
mtrx.clear();
// окружность
mtrx.circle(3, 3, 3, GFX_STROKE);
mtrx.update();
delay(1000);
mtrx.clear();
mtrx.setScale(1); // масштаб текста
mtrx.setCursor(1,1); // установить курсор
mtrx.println("MAX7219!");
mtrx.print("Demo ...");
mtrx.update();
delay(3000);
mtrx.clear();
mtrx.setScale(1); // масштаб текста
mtrx.drawChar(1,1,'s');
mtrx.update();
delay(3000);
mtrx.clear();
mtrx.setScale(2); // масштаб текста
mtrx.setCursor(1,1); // установить курсор
mtrx.println("7219");
mtrx.update();
delay(3000);
mtrx.setScale(2); // масштаб текста
mtrx.setCursor(1,1); // установить курсор
mtrx.invertText(1); // инвертировать текст
mtrx.println("7219");
mtrx.update();
delay(3000);
tape = "this wont more then i wont show now !!!";
handleTicker(1);
delay(1000);
mtrx.clear();
tape = "1 2 3 4 5 - this wont more then i wont show now !!!";
handleTicker(2);
delay(2000);
}
void loop() {
static uint32_t tmrM;
static byte mode;
if (millis() - tmrM >= 8000) { // 8 секунд
tmrM = millis();
if (++mode >= 8) mode = 0; // меняем режим от 0 до 5
mtrx.clear();
}
switch (mode) {
case 0: lines(); break;
case 1: ball(); break;
case 2: bigBall(); break;
case 3: net(); break;
case 4: bezier(); break;
case 5: bitmap(); break;
case 6: emoji(); break; // рисуем одну любую emoji
case 7: all_emoji();break; // выводим все для демонстрации
}
}
// редактор тут http://jorydotcom.github.io/matrix-emoji/
const uint8_t bmp[] PROGMEM = {
0b00100100,
0b00100100,
0b01111110,
0b11011011,
0b11111111,
0b11111111,
0b10100101,
0b00100100,
};
void bitmap() {
mtrx.clear();
static int x, y;
static int velX = 6, velY = 4;
x += velX;
y += velY;
if (x >= (AM_W - 8) * 10 || x < 0) velX = -velX;
if (y >= (AM_H - 8) * 10 || y < 0) velY = -velY;
mtrx.drawBitmap(x / 10, y / 10, bmp, 8, 8, 24);
mtrx.update();
delay(30);
}
void net() {
const byte radius = 2;
const byte amount = 5;
static bool start = false;
static int x[amount], y[amount];
static int velX[amount], velY[amount];
if (!start) {
start = 1;
for (byte i = 0; i < amount; i++) {
x[i] = random(10, (AM_W - 1) * 10);
y[i] = random(10, (AM_H - 1) * 10);
velX[i] = random(2, 9);
velY[i] = random(2, 9);
}
}
mtrx.clear();
for (byte i = 0; i < amount; i++) {
x[i] += velX[i];
y[i] += velY[i];
if (x[i] >= (AM_W - 1 - radius) * 10 || x[i] < radius * 10) velX[i] = -velX[i];
if (y[i] >= (AM_H - 1 - radius) * 10 || y[i] < radius * 10) velY[i] = -velY[i];
mtrx.circle(x[i] / 10, y[i] / 10, radius);
}
for (int i = 0; i < amount; i++) {
for (int j = 0; j < amount; j++) {
if (i != j && dist(x[i] / 10, y[i] / 10, x[j] / 10, y[j] / 10) < 35) mtrx.line(x[i] / 10, y[i] / 10, x[j] / 10, y[j] / 10);
}
}
mtrx.update();
delay(20);
}
int dist(int x1, int y1, int x2, int y2) {
int lx = (x2 - x1);
int ly = (y2 - y1);
return (sqrt(lx * lx + ly * ly));
}
void bigBall() {
mtrx.clear();
byte radius = 3;
static int x = (AM_W / 2) * 10, y = (AM_H / 2) * 10;
static int velX = 9, velY = 5;
static bool fillFlag = 0;
x += velX;
y += velY;
if (x >= (AM_W - 4) * 10 || x < radius * 10) {
velX = -velX;
fillFlag = !fillFlag;
}
if (y >= (AM_H - 4) * 10 || y < radius * 10) {
velY = -velY;
fillFlag = !fillFlag;
}
mtrx.circle(x / 10, y / 10, radius, fillFlag ? GFX_STROKE : GFX_FILL);
mtrx.update();
delay(30);
}
void bezier() {
byte data[] = {0, 0, AM_W / 2, AM_H / 2, 0, AM_H - 1};
for (int i = 0; i < AM_W; i++) {
mtrx.clear();
data[0] = data[4] = AM_W - i;
data[2] = i;
mtrx.bezier(data, 3, 6);
mtrx.update();
delay(30);
}
for (int i = AM_W; i > 0; i--) {
mtrx.clear();
data[0] = data[4] = AM_W - i;
data[2] = i;
mtrx.bezier(data, 3, 6);
mtrx.update();
delay(30);
}
}
void lines() {
mtrx.clear();
for (byte i = 0; i < AM_W - 1; i += 3) {
mtrx.line(0, 0, i, AM_H);
mtrx.update();
delay(30);
}
for (int i = AM_H - 1; i >= 0 ; i -= 3) {
mtrx.line(0, 0, AM_W, i);
mtrx.update();
delay(30);
}
delay(100);
mtrx.clear();
for (int i = AM_W - 1; i > 0; i -= 3) {
mtrx.line(AM_W - 1, 0, i, AM_H);
mtrx.update();
delay(30);
}
for (int i = AM_H; i >= 0; i -= 3) {
mtrx.line(AM_W - 1, 0, 0, i);
mtrx.update();
delay(30);
}
delay(100);
}
void ball() {
static int x, y;
static int velX = 17, velY = 12;
x += velX;
y += velY;
if (x >= (AM_W - 1) * 10 || x < 0) velX = -velX;
if (y >= (AM_H - 1) * 10 || y < 0) velY = -velY;
mtrx.dot(x / 10, y / 10);
mtrx.update();
delay(40);
}
// рисуем одну любую emoji
void emoji(){
mtrx.drawBitmap(0, 0, winkleft_B, 8, 8, 5);
mtrx.update();
delay(2000);
}
// выводим все для демонстрации
void all_emoji(){
for (int i = 0; i < 31; i++) {
for (int b = 0; b < 100; b++) {
mtrx.clear();
static int x, y;
static int velX = 6, velY = 4;
x += velX;
y += velY;
if (x >= (AM_W - 8) * 10 || x < 0) velX = -velX;
if (y >= (AM_H - 8) * 10 || y < 0) velY = -velY;
mtrx.drawBitmap(x / 10, y / 10, (emojis[i]), 8, 8, 24);// получаем адрес из таблицы ссылок
mtrx.update();
delay(30);
}
delay(1000);
}
}
void handleTicker(uint8_t size) {
int letter, x, y;
tape = mtrx.utf8rus(tape);
for ( int i = 0 ; i < (width * size) * tape.length() + mtrx._width() - 1 - spacer; i++ ) {
mtrx.clear();
letter = i / (width * size);
x = (mtrx._width() - 1) - i % (width * size);
y = (mtrx._height() - (8 * size)) / 2;
while ( x + (width * size) - spacer >= 0 && letter >= 0 ) {
if ( letter < tape.length() ) {
mtrx.drawChar(x, y, tape[letter], GFX_FILL, size);
}
letter--;
x -= (width * size);
}
mtrx.update();
delay(50);
}
}