Create ScrollingTextLayer.ino

This commit is contained in:
mrcodetastic 2025-03-17 20:55:35 +00:00
parent 0be6f369ad
commit c9a8c50702

View file

@ -0,0 +1,267 @@
// Modified from: https://github.com/wilson3682/My-HUB75-ESP32-Practice-Files/tree/main
// by MrCodetastic
/***************************************************************************************
* This sketch does a couple of things, it uses GFX_Lite's GFX_Layer to independently
* draw the background and the text onto separate layers. (memory used for each)
* Then these are stacked on top of each other with some opacity, and drawn directly
* to the dma_display via a callback (layer_draw_callback).
*
* These layers are offscreen pixel buffers that use memory of their own
* (approx 3 bytes for each pixel).
*
* By using this approach, we don't really need to use DMA double buffering though.
*
***************************************************************************************/
#include <ESP32-HUB75-MatrixPanel-I2S-DMA.h>
// You need to have: https://github.com/mrcodetastic/GFX_Lite
#include <GFX_Layer.hpp>
//------------------------------------------------------------------------------------------------------------------
// Configure for your panel(s) as appropriate!
#define PANEL_WIDTH 64
#define PANEL_HEIGHT 32 // Panel height of 64 will required PIN_E to be defined.
#define CHAIN_LENGTH 1 // Number of chained panels, if just a single panel, obviously set to 1
//------------------------------------------------------------------------------------------------------------------
/*
#define RL1 18
#define GL1 17
#define BL1 16
#define RL2 15
#define GL2 7
#define BL2 6
#define CH_A 4
#define CH_B 10
#define CH_C 14
#define CH_D 21
#define CH_E 5 // assign to any available pin if using two panels or 64x64 panels with 1/32 scan
#define CLK 47
#define LAT 48
#define OE 38
*/
//------------------------------------------------------------------------------------------------------------------
MatrixPanel_I2S_DMA *dma_display = nullptr;
//------------------------------------------------------------------------------------------------------------------
//====================== Variables For scrolling Text=====================================================
unsigned long isAnimationDue;
int delayBetweeenAnimations = 18; // Smaller == faster
int textXPosition = PANEL_WIDTH * CHAIN_LENGTH; // Will start off screen
int textYPosition = PANEL_HEIGHT / 2 - 7; // center of screen - 8 (half of the text height)
//====================== Variables For scrolling Text=====================================================
// Pointers to this variable will be passed into getTextBounds,
// they will be updated from inside the method
int16_t xOne, yOne;
uint16_t w, h;
//------------------------------------------------------------------------------------------------------------------
// The layers don't draw to hardware directly, they use a callback function.
// You could be smart here and additionally draw to the VirtualMatrixPanel_T class...
void layer_draw_callback(int16_t x, int16_t y, uint8_t r_data, uint8_t g_data, uint8_t b_data) {
dma_display->drawPixelRGB888(x,y,r_data,g_data,b_data);
}
// Global GFX_Layer object
GFX_Layer gfx_layer_bg(PANEL_WIDTH*CHAIN_LENGTH, PANEL_HEIGHT, layer_draw_callback); // background
GFX_Layer gfx_layer_fg(PANEL_WIDTH*CHAIN_LENGTH, PANEL_HEIGHT, layer_draw_callback); // foreground
GFX_LayerCompositor gfx_compositor(layer_draw_callback);
//------------------------------------------------------------------------------------------------------------------
void setup() {
Serial.begin(115200);
//Custom pin mapping for all pins
HUB75_I2S_CFG::i2s_pins _pins={RL1, GL1, BL1, RL2, GL2, BL2, CH_A, CH_B, CH_C, CH_D, CH_E, LAT, OE, CLK};
HUB75_I2S_CFG mxconfig(
PANEL_WIDTH, // width
PANEL_HEIGHT, // height
CHAIN_LENGTH // chain length
// ,_pins // pin mapping
// ,HUB75_I2S_CFG::FM6126A // driver chip
);
mxconfig.i2sspeed = HUB75_I2S_CFG::HZ_20M;
// If you are using a 64x64 matrix you need to pass a value for the E pin
// The trinity connects GPIO 18 to E.
// This can be commented out for any smaller displays (but should work fine with it)
//mxconfig.gpio.e = -1;
// May or may not be needed depending on your matrix
// Example of what needing it looks like:
// https://github.com/mrfaptastic/ESP32-HUB75-MatrixPanel-I2S-DMA/issues/134#issuecomment-866367216
//mxconfig.clkphase = false;
// Some matrix panels use different ICs for driving them and some of them have strange quirks.
// If the display is not working right, try this.
//mxconfig.driver = HUB75_I2S_CFG::FM6126A;
dma_display = new MatrixPanel_I2S_DMA(mxconfig);
dma_display->begin();
dma_display->setBrightness8(120); //0-255
dma_display->clearScreen();
// Clear the layers
gfx_layer_fg.clear();
gfx_layer_fg.setTextWrap(false);
gfx_layer_bg.clear();
}
void printTextRainbowCentered(int colorWheelOffset, const char *text, int yPos) {
gfx_layer_fg.setTextSize(1); // size 1 == 8 pixels high
// Calculate the width of the text in pixels
int textWidth = strlen(text) * 6; // Assuming 6 pixels per character for size 1
// Center the text horizontally
int xPos = (gfx_layer_fg.width() - textWidth) / 2;
gfx_layer_fg.setCursor(xPos, yPos); // Set cursor position for centered text
// Draw text with a rotating color
for (uint8_t w = 0; w < strlen(text); w++) {
gfx_layer_fg.setTextColor(colorWheel((w * 32) + colorWheelOffset));
gfx_layer_fg.print(text[w]);
}
}
// Code taken from: https://github.com/witnessmenow/ESP32-Trinity/blob/master/examples/BuildingBlocks/Text/ScrollingText/ScrollingText.ino
//
void scrollText(int colorWheelOffset, const char *text) {
const char *str = text;
byte offSet = 25;
unsigned long now = millis();
if (now > isAnimationDue)
{
gfx_layer_fg.setTextSize(2); // size 2 == 16 pixels high
isAnimationDue = now + delayBetweeenAnimations;
textXPosition -= 1;
// Checking is the very right of the text off screen to the left
gfx_layer_fg.getTextBounds(str, textXPosition, textYPosition, &xOne, &yOne, &w, &h);
if (textXPosition + w <= 0) {
textXPosition = gfx_layer_fg.width() + offSet;
}
gfx_layer_fg.setCursor(textXPosition, textYPosition);
// Clear the area of text to be drawn to
gfx_layer_fg.drawRect(1, textYPosition, gfx_layer_fg.width() - 1, 14, gfx_layer_fg.color565(0, 0, 0));
gfx_layer_fg.fillRect(1, textYPosition, gfx_layer_fg.width() - 1, 14, gfx_layer_fg.color565(0, 0, 0));
uint8_t w = 0;
for (w = 0; w < strlen(str); w++) {
//gfx_layer_fg.setTextColor(colorWheel((w * 32) + colorWheelOffset));
gfx_layer_fg.setTextColor(gfx_layer_fg.color565(255, 255, 255));
gfx_layer_fg.print(str[w]);
}
}
}
void drawTextCentered(int colorWheelOffset, const char *text, int yPos) {
// draw text with a rotating colour
gfx_layer_fg.setTextSize(1); // size 1 == 8 pixels high
// Calculate the width of the text in pixels
int textWidth = strlen(text) * 6; // Assuming 6 pixels per character for size 1
// Center the text horizontally
int xPos = (gfx_layer_fg.width() - textWidth) / 2;
gfx_layer_fg.setCursor(xPos, yPos); // start at top left, with 8 pixel of spacing
uint8_t w = 0;
//const char *str = "ESP32 DMA";
const char *str = text;
for (w = 0; w < strlen(str); w++) {
gfx_layer_fg.setTextColor(colorWheel((w * 32) + colorWheelOffset));
gfx_layer_fg.print(str[w]);
}
}
// Input a value 0 to 255 to get a color value.
// The colours are a transition r - g - b - back to r.
// From: https://gist.github.com/davidegironi/3144efdc6d67e5df55438cc3cba613c8
uint16_t colorWheel(uint8_t pos) {
if (pos < 85) {
return dma_display->color565(pos * 3, 255 - pos * 3, 0);
} else if (pos < 170) {
pos -= 85;
return dma_display->color565(255 - pos * 3, 0, pos * 3);
} else {
pos -= 170;
return dma_display->color565(0, pos * 3, 255 - pos * 3);
}
}
unsigned long last_increment = 0;
unsigned long increment_amt = 0;
void updateBackground()
{
CRGBPalette16 currentPalette = CloudColors_p;
if ( (millis() - last_increment) > 20) {
increment_amt++;
last_increment = millis();
}
for (int x = 0; x < gfx_layer_bg.width(); x++) {
for (int y = 0; y < gfx_layer_bg.height(); y++) {
int val = sin8(x + increment_amt);
val += sin8(y + increment_amt);
CRGB currentColor = ColorFromPalette(currentPalette, val); //, brightness, currentBlendType);
// Set a pixel in the back layer
gfx_layer_bg.setPixel(x, y, currentColor.r, currentColor.g, currentColor.b);
}
}
gfx_layer_bg.dim(192); // darken it a little
}
uint8_t wheelval = 0;
void loop() {
updateBackground();
scrollText(wheelval, "HAVE A WONDERFUL DAY!"); //Prints Scrolling text with a rainbow color
printTextRainbowCentered(wheelval, "ENJOY IT", 24); //Prints text X-Centered to chosen Y position with rainbow color
//gfx_layer_fg.display();
//gfx_layer_bg.display();
gfx_compositor.Blend(gfx_layer_bg, gfx_layer_fg); // blend and immediately display
wheelval += 1;
}