359 lines
10 KiB
C++
359 lines
10 KiB
C++
/**
|
|
* Test de cascade de panneaux P10 RGB
|
|
*
|
|
* Ce programme permet de tester l'affichage sur plusieurs panneaux P10 en cascade
|
|
* Il affiche différents motifs visuels pour vérifier que toute la surface est utilisée
|
|
*
|
|
* Compatible avec toutes les configurations de cascade définies dans platformio.ini
|
|
*/
|
|
|
|
#define PxMATRIX_SPI_FREQUENCY 100000000
|
|
|
|
#include <Arduino.h>
|
|
#include <PxMatrix.h>
|
|
|
|
// Pins pour la matrice LED
|
|
#define P_LAT 5
|
|
#define P_A 19
|
|
#define P_B 23
|
|
#define P_C 18
|
|
#define P_OE 4
|
|
|
|
// Configuration des panneaux - définie par les build flags
|
|
#ifndef MATRIX_WIDTH
|
|
#define MATRIX_WIDTH 32
|
|
#endif
|
|
|
|
#ifndef MATRIX_HEIGHT
|
|
#define MATRIX_HEIGHT 16
|
|
#endif
|
|
|
|
#ifndef MATRIX_PANELS_X
|
|
#define MATRIX_PANELS_X 3
|
|
#endif
|
|
|
|
#ifndef MATRIX_PANELS_Y
|
|
#define MATRIX_PANELS_Y 1
|
|
#endif
|
|
|
|
// Calcul des dimensions totales
|
|
#define TOTAL_WIDTH (MATRIX_WIDTH * MATRIX_PANELS_X)
|
|
#define TOTAL_HEIGHT (MATRIX_HEIGHT * MATRIX_PANELS_Y)
|
|
|
|
// Configuration du timer
|
|
hw_timer_t * timer = nullptr;
|
|
portMUX_TYPE timerMux = portMUX_INITIALIZER_UNLOCKED;
|
|
|
|
// Temps d'affichage ajusté selon le nombre de panneaux
|
|
uint8_t display_draw_time = (MATRIX_PANELS_X * MATRIX_PANELS_Y > 4) ? 20 : 30;
|
|
|
|
// Objet matrice
|
|
PxMATRIX display(TOTAL_WIDTH, TOTAL_HEIGHT, P_LAT, P_OE, P_A, P_B, P_C);
|
|
|
|
// Couleurs
|
|
uint16_t myRED = display.color565(255, 0, 0);
|
|
uint16_t myGREEN = display.color565(0, 255, 0);
|
|
uint16_t myBLUE = display.color565(0, 0, 255);
|
|
uint16_t myYELLOW = display.color565(255, 255, 0);
|
|
uint16_t myCYAN = display.color565(0, 255, 255);
|
|
uint16_t myMAGENTA = display.color565(255, 0, 255);
|
|
uint16_t myWHITE = display.color565(255, 255, 255);
|
|
uint16_t myBLACK = display.color565(0, 0, 0);
|
|
uint16_t myORANGE = display.color565(255, 165, 0);
|
|
uint16_t myPURPLE = display.color565(128, 0, 255);
|
|
uint16_t myPINK = display.color565(255, 128, 128);
|
|
|
|
// Tableau de couleurs pour les tests
|
|
uint16_t myColorArray[] = {
|
|
myRED, myGREEN, myBLUE, myYELLOW,
|
|
myCYAN, myMAGENTA, myORANGE, myPURPLE,
|
|
myPINK, myWHITE
|
|
};
|
|
|
|
// Variables pour les animations
|
|
unsigned long lastUpdate = 0;
|
|
uint8_t testMode = 0;
|
|
uint8_t testStep = 0;
|
|
bool transitionActive = false;
|
|
unsigned long transitionStartTime = 0;
|
|
const unsigned long TEST_DURATION = 5000; // 5 secondes par test
|
|
|
|
// Gestionnaire d'interruption pour l'affichage
|
|
void IRAM_ATTR display_updater() {
|
|
portENTER_CRITICAL_ISR(&timerMux);
|
|
display.display(display_draw_time);
|
|
portEXIT_CRITICAL_ISR(&timerMux);
|
|
}
|
|
|
|
// Activation du timer d'affichage
|
|
void display_update_enable() {
|
|
timer = timerBegin(0, 80, true);
|
|
if (timer != NULL) {
|
|
timerAttachInterrupt(timer, &display_updater, true);
|
|
timerAlarmWrite(timer, 1500, true);
|
|
timerAlarmEnable(timer);
|
|
Serial.println("Display timer enabled successfully");
|
|
} else {
|
|
Serial.println("ERROR: Failed to create display timer");
|
|
}
|
|
}
|
|
|
|
// Affichage de la grille des panneaux
|
|
void testGrid() {
|
|
display.clearDisplay();
|
|
|
|
// Dessiner les bordures de chaque panneau
|
|
for (int x = 0; x < MATRIX_PANELS_X; x++) {
|
|
for (int y = 0; y < MATRIX_PANELS_Y; y++) {
|
|
int panelX = x * MATRIX_WIDTH;
|
|
int panelY = y * MATRIX_HEIGHT;
|
|
|
|
// Bordure colorée pour chaque panneau (couleur différente pour chaque panneau)
|
|
uint16_t color = myColorArray[(x + y * MATRIX_PANELS_X) % 10];
|
|
|
|
// Dessiner le contour du panneau
|
|
display.drawRect(panelX, panelY, MATRIX_WIDTH, MATRIX_HEIGHT, color);
|
|
|
|
// Afficher le numéro du panneau au centre
|
|
char panelText[5];
|
|
sprintf(panelText, "%d,%d", x, y);
|
|
|
|
int textX = panelX + (MATRIX_WIDTH - strlen(panelText) * 6) / 2;
|
|
int textY = panelY + (MATRIX_HEIGHT - 8) / 2;
|
|
|
|
display.setTextColor(myWHITE);
|
|
display.setCursor(textX, textY);
|
|
display.print(panelText);
|
|
}
|
|
}
|
|
}
|
|
|
|
// Afficher un cadre complet autour de tous les panneaux
|
|
void testFullFrame() {
|
|
display.clearDisplay();
|
|
|
|
// Cadre extérieur
|
|
display.drawRect(0, 0, TOTAL_WIDTH, TOTAL_HEIGHT, myWHITE);
|
|
|
|
// Cadre intérieur
|
|
display.drawRect(2, 2, TOTAL_WIDTH-4, TOTAL_HEIGHT-4, myRED);
|
|
|
|
// Diagonales pour visualiser la taille complète
|
|
display.drawLine(0, 0, TOTAL_WIDTH-1, TOTAL_HEIGHT-1, myYELLOW);
|
|
display.drawLine(0, TOTAL_HEIGHT-1, TOTAL_WIDTH-1, 0, myYELLOW);
|
|
|
|
// Afficher la résolution totale
|
|
char resText[20];
|
|
sprintf(resText, "%dx%d", TOTAL_WIDTH, TOTAL_HEIGHT);
|
|
|
|
display.setTextColor(myCYAN);
|
|
display.setCursor((TOTAL_WIDTH - strlen(resText) * 6) / 2, TOTAL_HEIGHT / 2 - 4);
|
|
display.print(resText);
|
|
}
|
|
|
|
// Test avec des barres de couleur horizontales
|
|
void testColorBars() {
|
|
display.clearDisplay();
|
|
|
|
// Nombre de barres à afficher
|
|
int numBars = min(10, TOTAL_HEIGHT / 2);
|
|
int barHeight = TOTAL_HEIGHT / numBars;
|
|
|
|
// Dessiner des barres horizontales de couleurs différentes
|
|
for (int i = 0; i < numBars; i++) {
|
|
int y = i * barHeight;
|
|
uint16_t color = myColorArray[i % 10];
|
|
display.fillRect(0, y, TOTAL_WIDTH, barHeight, color);
|
|
}
|
|
}
|
|
|
|
// Test avec quadrillage sur toute la surface
|
|
void testCheckerboard() {
|
|
display.clearDisplay();
|
|
|
|
// Taille des carrés
|
|
int squareSize = 8;
|
|
|
|
// Dessiner un quadrillage alternant deux couleurs
|
|
for (int x = 0; x < TOTAL_WIDTH; x += squareSize) {
|
|
for (int y = 0; y < TOTAL_HEIGHT; y += squareSize) {
|
|
// Alterner les couleurs
|
|
uint16_t color = ((x/squareSize + y/squareSize) % 2 == 0) ? myBLUE : myYELLOW;
|
|
display.fillRect(x, y, squareSize, squareSize, color);
|
|
}
|
|
}
|
|
}
|
|
|
|
// Test avec du texte qui défile sur toute la largeur
|
|
void testScrollingText() {
|
|
static int scrollX = TOTAL_WIDTH;
|
|
static unsigned long lastScrollTime = 0;
|
|
unsigned long currentTime = millis();
|
|
|
|
if (currentTime - lastScrollTime >= 50) {
|
|
lastScrollTime = currentTime;
|
|
|
|
// Effacer l'écran
|
|
display.clearDisplay();
|
|
|
|
// Texte de test qui affiche la configuration des panneaux
|
|
char text[100];
|
|
sprintf(text, "CONFIGURATION: %dx%d PANNEAUX (%dx%d PIXELS)",
|
|
MATRIX_PANELS_X, MATRIX_PANELS_Y, TOTAL_WIDTH, TOTAL_HEIGHT);
|
|
|
|
// Calculer la largeur approximative du texte
|
|
int textWidth = strlen(text) * 6;
|
|
|
|
// Afficher le texte à la position actuelle
|
|
display.setCursor(scrollX, (TOTAL_HEIGHT - 8) / 2);
|
|
display.setTextColor(myWHITE);
|
|
display.print(text);
|
|
|
|
// Déplacer le texte
|
|
scrollX--;
|
|
|
|
// Réinitialiser la position quand le texte est complètement sorti de l'écran
|
|
if (scrollX < -textWidth) {
|
|
scrollX = TOTAL_WIDTH;
|
|
}
|
|
|
|
// Afficher un indicateur de la largeur totale
|
|
display.drawPixel(0, 0, myRED);
|
|
display.drawPixel(TOTAL_WIDTH-1, 0, myRED);
|
|
display.drawPixel(0, TOTAL_HEIGHT-1, myRED);
|
|
display.drawPixel(TOTAL_WIDTH-1, TOTAL_HEIGHT-1, myRED);
|
|
}
|
|
}
|
|
|
|
// Test avec des cercles concentriques
|
|
void testCircles() {
|
|
display.clearDisplay();
|
|
|
|
// Centre de l'écran
|
|
int centerX = TOTAL_WIDTH / 2;
|
|
int centerY = TOTAL_HEIGHT / 2;
|
|
|
|
// Rayon maximum possible
|
|
int maxRadius = min(TOTAL_WIDTH, TOTAL_HEIGHT) / 2;
|
|
|
|
// Dessiner plusieurs cercles concentriques de couleurs différentes
|
|
for (int r = maxRadius; r > 0; r -= 2) {
|
|
uint16_t color = myColorArray[(maxRadius - r) % 10];
|
|
display.drawCircle(centerX, centerY, r, color);
|
|
}
|
|
}
|
|
|
|
// Transition entre les tests
|
|
void performTransition() {
|
|
static int transitionStep = 0;
|
|
static unsigned long lastTransitionUpdate = 0;
|
|
unsigned long currentTime = millis();
|
|
|
|
if (currentTime - lastTransitionUpdate >= 50) {
|
|
lastTransitionUpdate = currentTime;
|
|
|
|
if (transitionStep < TOTAL_HEIGHT) {
|
|
// Transition par balayage horizontal
|
|
display.fillRect(0, 0, TOTAL_WIDTH, transitionStep, myBLACK);
|
|
transitionStep++;
|
|
} else {
|
|
// Transition terminée
|
|
transitionStep = 0;
|
|
transitionActive = false;
|
|
testMode = (testMode + 1) % 6; // Passer au test suivant (6 tests au total)
|
|
}
|
|
}
|
|
}
|
|
|
|
void setup() {
|
|
Serial.begin(115200);
|
|
delay(1000);
|
|
Serial.println("\n=== ESP32 P10 RGB CASCADE TEST ===");
|
|
Serial.printf("Configuration: %dx%d panels (%dx%d total resolution)\n",
|
|
MATRIX_PANELS_X, MATRIX_PANELS_Y, TOTAL_WIDTH, TOTAL_HEIGHT);
|
|
|
|
// Initialisation de l'affichage avec configuration P10 optimisée
|
|
display.begin(8); // 1/8 scan pour P10
|
|
display.setScanPattern(ZAGZIG);
|
|
display.setMuxPattern(BINARY);
|
|
const int muxdelay = 1; // Délai de multiplexage
|
|
display.setMuxDelay(muxdelay, muxdelay, muxdelay, muxdelay, muxdelay);
|
|
display.setPanelsWidth(MATRIX_PANELS_X);
|
|
delay(100);
|
|
|
|
display_update_enable();
|
|
display.clearDisplay();
|
|
|
|
// Luminosité adaptée au nombre de panneaux
|
|
int brightness = 150;
|
|
if (MATRIX_PANELS_X > 2) brightness = 100;
|
|
if (MATRIX_PANELS_X > 4) brightness = 80;
|
|
if (MATRIX_PANELS_X > 6) brightness = 60;
|
|
|
|
display.setBrightness(brightness);
|
|
Serial.printf("Brightness set to: %d\n", brightness);
|
|
|
|
display.setTextWrap(false);
|
|
display.setRotation(0);
|
|
display.setTextSize(1);
|
|
|
|
// Message de bienvenue
|
|
display.clearDisplay();
|
|
display.setTextColor(myGREEN);
|
|
|
|
char welcomeText[50];
|
|
sprintf(welcomeText, "P10 CASCADE TEST");
|
|
int textWidth = strlen(welcomeText) * 6;
|
|
int textX = (TOTAL_WIDTH - textWidth) / 2;
|
|
if (textX < 0) textX = 0;
|
|
|
|
display.setCursor(textX, TOTAL_HEIGHT / 2 - 4);
|
|
display.print(welcomeText);
|
|
|
|
delay(2000);
|
|
|
|
// Démarrer les tests
|
|
lastUpdate = millis();
|
|
|
|
Serial.println("Starting cascade tests...");
|
|
}
|
|
|
|
void loop() {
|
|
unsigned long currentTime = millis();
|
|
|
|
// Vérifier s'il faut changer de mode de test
|
|
if (!transitionActive && (currentTime - lastUpdate >= TEST_DURATION)) {
|
|
transitionActive = true;
|
|
transitionStartTime = currentTime;
|
|
}
|
|
|
|
// Gérer la transition entre les tests
|
|
if (transitionActive) {
|
|
performTransition();
|
|
} else {
|
|
// Exécuter le test actuel
|
|
switch (testMode) {
|
|
case 0:
|
|
testGrid();
|
|
break;
|
|
case 1:
|
|
testFullFrame();
|
|
break;
|
|
case 2:
|
|
testColorBars();
|
|
break;
|
|
case 3:
|
|
testCheckerboard();
|
|
break;
|
|
case 4:
|
|
testScrollingText();
|
|
break;
|
|
case 5:
|
|
testCircles();
|
|
break;
|
|
}
|
|
}
|
|
|
|
delay(10);
|
|
}
|