//https://forum.arduino.cc/t/escribir-en-matriz-8x8-desde-monitor-serial/1425639
/*
MATRIZ 8x8 + MONITOR + POTENCIOMETRO
IDE: Archivo/Ejemplos/MD_MAX72xx/MD_MAX72xx_Message_Serial
https://github.com/MajicDesigns/MD_MAX72XX/blob/main/examples/MD_MAX72xx_Message_Serial/MD_MAX72xx_Message_Serial.ino
GITHUB: examples/MD_MAX72xx_Message_Serial/MD_MAX72xx_Message_Serial.ino
*/
// Desplazar texto en la pantalla; Biblioteca MD_MAX72XX
//
// Demuestra el uso de la función de devolución de llamada para controlar qué se desplaza en el texto de la pantalla.
//
// El usuario puede introducir texto en el monitor serie y este se mostrará como un mensaje desplazable en la pantalla.
// La velocidad de la pantalla se controla mediante un potenciómetro en la entrada analógica SPEED_IN: (A5).
//
#include <MD_MAX72xx.h>
#include <SPI.h>
#define IMMEDIATE_NEW 1 // Si "1": mostrará inmediatamente un nuevo mensaje
#define USE_POT_CONTROL 1 // Si "1": Habilita uso potenciometro.
#define PRINT_CALLBACK 1 // Si "1": Imprime en monitor valores: potenciometro(velocidad)
#define PRINT(s, v) { Serial.print(F(s)); Serial.print(v); }
// Define la cantidad de dispositivos que tenemos en la cadena y la interfaz de hardware.
// NOTA: Es probable que estos números de pin no funcionen con tu hardware y deban adaptarse.
// VARIAS SOLUCIONES de HARDWARE_TYPE: //>>PAROLA_HW--DR1CR1RR1_HW--DR0CR0RR1_HW--DR0CR1RR0_HW
#define HARDWARE_TYPE MD_MAX72XX::ICSTATION_HW
#define MAX_DEVICES 1
#define CLK_PIN 13 // or SCK
#define DATA_PIN 11 // or MOSI
#define CS_PIN 10 // or SS
// SPI hardware interface
//MD_MAX72XX mx = MD_MAX72XX(HARDWARE_TYPE, CS_PIN, MAX_DEVICES);
// pines arbitrarios
MD_MAX72XX mx = MD_MAX72XX(HARDWARE_TYPE, DATA_PIN, CLK_PIN, CS_PIN, MAX_DEVICES);
// Scrolling parameters
#if USE_POT_CONTROL
#define SPEED_IN A5 // Entrada potenciometro: Analogica 5
#else
#define SCROLL_DELAY 75 // 75 in milliseconds
#endif // USE_POT_CONTROL
#define CHAR_SPACING 1 // píxeles entre caracteres
#define BUF_SIZE 75 // Buffers de mensajes globales compartidos por las funciones seriales y de desplazamiento
uint8_t curMessage[BUF_SIZE] = { "Hola.12" };
uint8_t newMessage[BUF_SIZE];
bool newMessageAvailable = false;
uint16_t scrollDelay; // en milliseconds
void readSerial(void)
{
static uint8_t putIndex = 0;
while (Serial.available())
{
newMessage[putIndex] = (char)Serial.read();
if ((newMessage[putIndex] == '\n') || (putIndex >= BUF_SIZE - 3)) // end of message character or full buffer
{
// Coloque un separador de mensajes y finalice la cadena
newMessage[putIndex++] = ' ';
newMessage[putIndex] = '\0';
// Reiniciar el índice para la próxima ola de llenado y marcar que tenemos un mensaje en espera.
putIndex = 0;
newMessageAvailable = true;
}
else if (newMessage[putIndex] != '\r')// guarde el siguiente carácter en la siguiente ubicación
putIndex++;
}
}
//Función de devolución de llamada para datos que se desplazan fuera de la pantalla
void scrollDataSink(uint8_t dev, MD_MAX72XX::transformType_t t, uint8_t col)
{
#if PRINT_CALLBACK
Serial.print("\n cb ");
Serial.print(dev);
Serial.print(' ');
Serial.print(t); // tabulador
Serial.print(' ');
Serial.println(col);
#endif
}
// Función de devolución de llamada para los datos que se requieren para desplazarse por la pantalla
uint8_t scrollDataSource(uint8_t dev, MD_MAX72XX::transformType_t t)
{
static uint8_t* p = curMessage;
static enum { NEW_MESSAGE, LOAD_CHAR, SHOW_CHAR, BETWEEN_CHAR } state = LOAD_CHAR;
static uint8_t curLen, showLen;
static uint8_t cBuf[15];
uint8_t colData = 0; // La columna en blanco es la predeterminada
#if IMMEDIATE_NEW
if (newMessageAvailable) // Hay un nuevo mensaje esperando
{
state = NEW_MESSAGE;
mx.clear(); // borrar la pantalla
}
#endif
// máquina de estados finitos para controlar lo que hacemos en la devolución de llamada
switch (state)
{
case NEW_MESSAGE: // Cargar el nuevo mensaje
memcpy(curMessage, newMessage, BUF_SIZE); // copiarlo en
newMessageAvailable = false; // ¡Lo usé!
p = curMessage;
state = LOAD_CHAR;
break;
case LOAD_CHAR: // Cargar el siguiente carácter de la tabla de fuentes
showLen = mx.getChar(*p++, sizeof(cBuf) / sizeof(cBuf[0]), cBuf);
curLen = 0;
state = SHOW_CHAR;
// Si llegamos al final del mensaje, oportunidad de cargar el siguiente.
if (*p == '\0')
{
p = curMessage; // restablecer el puntero al inicio del mensaje
#if !IMMEDIATE_NEW
if (newMessageAvailable) // SI Hay un nuevo mensaje esperando
{
state = NEW_MESSAGE; // Lo cargaremos aqui
break;
}
#endif
}
// !! pasar deliberadamente al siguiente estado para comenzar a mostrar
case SHOW_CHAR: //mostrar la siguiente parte del mensaje
colData = cBuf[curLen++];
if (curLen == showLen)
{
showLen = CHAR_SPACING;
curLen = 0;
state = BETWEEN_CHAR;
}
break;
case BETWEEN_CHAR: // mostrar el espaciado entre caracteres (columnas en blanco)
colData = 0;
curLen++;
if (curLen == showLen)
state = LOAD_CHAR;
break;
default:
state = LOAD_CHAR;
}
return (colData);
}
void scrollText(void)
{
static uint32_t prevTime = 0;
//¿Es hora de desplazarse por el texto?
if (millis() - prevTime >= scrollDelay)
{
mx.transform(MD_MAX72XX::TSL); // desplazarse a lo largo del camino - la devolución de llamada cargará todos los datos
prevTime = millis(); // punto de partida para la próxima vez
}
}
uint16_t getScrollDelay(void)
{
#if USE_POT_CONTROL
uint16_t t;
t = analogRead(SPEED_IN); // Entrada potenciometro: analogica 5
t = map(t, 0, 1023, 25, 250);
return (t);
#else
return (SCROLL_DELAY); // 75 milliseconds
#endif
}
void setup()
{
Serial.begin(57600);
mx.begin();
mx.setShiftDataInCallback(scrollDataSource);
mx.setShiftDataOutCallback(scrollDataSink);
#if USE_POT_CONTROL
pinMode(SPEED_IN, INPUT); // Entrada potenciometro: analogica 5
#else
scrollDelay = SCROLL_DELAY; // 75 milliseconds
#endif
newMessage[0] = '\0';
Serial.print("\n[MD_MAX72XX Visualización de mensajes]\nEscriba un mensaje para la pantalla desplazable\nFin de la línea del mensaje con una nueva línea");
}
void loop()
{
scrollDelay = getScrollDelay();
readSerial();
scrollText();
}
//************************** FIN ******************************