Enhance VirtualMatrixPanel_T example

This commit is contained in:
mrcodetastic 2025-03-19 22:20:23 +00:00
parent c9a8c50702
commit aed04adfcd
2 changed files with 141 additions and 60 deletions

View file

@ -12,7 +12,7 @@
*
* 1) and 2) can be combined and utilsied together.
*
* There are THREE examples contained within this library. What example gets built depends
* There are FOUR examples contained within this library. What example gets built depends
* on the value of the "#define EXAMPLE_NUMBER X" value. Where X = Example number.
*
* Example 1: STANDARD 1/2 Scan (i.e. 1/16, 1/32) LED matrix panels, 64x32 pixels each,
@ -22,6 +22,9 @@
* in a grid of 2x2 panels, chained in a Serpentine manner.
*
* Example 3: A single non-standard 1/4 Scan (i.e. Four-Scan 1/8) outdoor LED matrix panel, 64x32 pixels.
*
* Example 4: Having your own panel pixel mapping logic of use only to a specific panel that isn't supported.
* In this case we re-use this to map an individual pixel in a weird way.
*/
#include <Arduino.h>
@ -31,6 +34,7 @@
#define EXAMPLE_NUMBER 1
//#define EXAMPLE_NUMBER 2
//#define EXAMPLE_NUMBER 3
//#define EXAMPLE_NUMBER 4 // Custom Special Effects example!
/**
* Configuration of the LED matrix panels number and individual pixel resolution.
@ -66,77 +70,121 @@
MatrixPanel_I2S_DMA *dma_display = nullptr;
// ------------------------------------------------------------------------------------------------------------
/**
* Template instantiation for the VirtualMatrixPanel_T class, depending on use-case.
**/
#if EXAMPLE_NUMBER == 1
// --- Example 1: STANDARD 1/2 Scan ---
// Declare a pointer to the specific instantiation:
VirtualMatrixPanel_T<PANEL_CHAIN_TYPE>* virtualDisp = nullptr;
// --- Example 1: STANDARD 1/2 Scan ---
// Declare a pointer to the specific instantiation:
VirtualMatrixPanel_T<PANEL_CHAIN_TYPE>* virtualDisp = nullptr;
#endif
#if EXAMPLE_NUMBER == 2
// --- Example 2: Non-Standard 1/4 Scan (Four-Scan 1/8) ---
// Use an existing library user-contributed Scan Type pixel mapping
using MyScanTypeMapping = ScanTypeMapping<PANEL_SCAN_TYPE>;
// --- Example 2: Non-Standard 1/4 Scan (Four-Scan 1/8) ---
// Create a pointer to the specific instantiation of the VirtualMatrixPanel_T class
VirtualMatrixPanel_T<PANEL_CHAIN_TYPE, MyScanTypeMapping>* virtualDisp = nullptr;
// Use an existing library user-contributed Scan Type pixel mapping
using MyScanTypeMapping = ScanTypeMapping<PANEL_SCAN_TYPE>;
// Create a pointer to the specific instantiation of the VirtualMatrixPanel_T class
VirtualMatrixPanel_T<PANEL_CHAIN_TYPE, MyScanTypeMapping>* virtualDisp = nullptr;
#endif
#if EXAMPLE_NUMBER == 3
// --- Example 3: Single non-standard 1/4 Scan (Four-Scan 1/8) ---
// Use an existing library user-contributed Scan Type pixel mapping
using MyScanTypeMapping = ScanTypeMapping<PANEL_SCAN_TYPE>;
// Use an existing library user-contributed Scan Type pixel mapping
using MyScanTypeMapping = ScanTypeMapping<PANEL_SCAN_TYPE>;
// Create a pointer to the specific instantiation of the VirtualMatrixPanel_T class
VirtualMatrixPanel_T<CHAIN_NONE, MyScanTypeMapping>* virtualDisp = nullptr;
// Create a pointer to the specific instantiation of the VirtualMatrixPanel_T class
VirtualMatrixPanel_T<CHAIN_NONE, MyScanTypeMapping>* virtualDisp = nullptr;
#endif
// Bonus non-existnat example. Create your own per-panel custom pixel mapping!
#if EXAMPLE_NUMBER == 4
// --- Custom ScanType Pixel Mapping ---
// This policy adds a fixed offset to the coordinates.
struct CustomScanTypeMapping {
static constexpr VirtualCoords apply(VirtualCoords coords, int virt_y, int panel_pixel_base) {
// For demonstration, add a fixed offset of +5 to x and +3 to y.
coords.x += 5;
coords.y += 3;
return coords;
}
};
// --- Custom ScanType Pixel Mapping ---
// This is not what you would use this for, but in any case it
// makes a flipped mirror image
struct CustomMirrorScanTypeMapping {
static VirtualCoords apply(VirtualCoords coords, int vy, int pb) {
// coords are the input coords for adjusting
int width = PANEL_RES_X;
int height = PANEL_RES_Y;
// Flip / Mirror x
coords.x = PANEL_RES_X - coords.x - 1;
// coords.y = PANEL_RES_Y - coords.y - 1;
return coords;
}
};
// Create a pointer to the specific instantiation of the VirtualMatrixPanel_T class
VirtualMatrixPanel_T<CHAIN_NONE, CustomMirrorScanTypeMapping>* virtualDisp = nullptr;
#endif
// ------------------------------------------------------------------------------------------------------------
void setup()
{
Serial.begin(115200);
delay(2000);
#if EXAMPLE_NUMBER == 3
/**
* HACK ALERT!
* For 1/4 scan panels (namely outdoor panels), electrically the pixels are connected in a chain that is
* twice the physical panel's pixel width, and half the pixel height. As such, we need to configure
* the underlying DMA library to match the same. Then we use the VirtualMatrixPanel_T class to map the
* physical pixels to the virtual pixels.
*/
HUB75_I2S_CFG mxconfig(
PANEL_RES_X*2, // DO NOT CHANGE THIS
PANEL_RES_Y/2, // DO NOT CHANGE THIS
1 // A Single panel
);
/*
#elif EXAMPLE_NUMBER == 2
#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
// 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};
*/
#if EXAMPLE_NUMBER == 1
// A grid of normal (i.e. supported out of the box) 1/16, 1/32 (two scan) panels
// Standard panel type natively supported by this library (Example 1, 4)
HUB75_I2S_CFG mxconfig(
PANEL_RES_X,
PANEL_RES_Y,
PANEL_CHAIN_LEN
//, _pins
);
#endif
#if EXAMPLE_NUMBER == 2
// A grid of 1/4 scan panels. This panel type is not supported 'out of the box' and require specific
// ScanTypeMapping (pixel mapping) within the panel itself.
/**
* HACK ALERT!
@ -149,15 +197,41 @@
PANEL_RES_X*2, // DO NOT CHANGE THIS
PANEL_RES_Y/2, // DO NOT CHANGE THIS
PANEL_CHAIN_LEN
//, _pins
);
#else
#endif
// Standard panel type natively supported by this library (Example 1)
#if EXAMPLE_NUMBER == 3
// A single 1/4 scan panel. This panel type is not supported 'out of the box' and require specific
// ScanTypeMapping (pixel mapping) within the panel itself.
/**
* HACK ALERT!
* For 1/4 scan panels (namely outdoor panels), electrically the pixels are connected in a chain that is
* twice the physical panel's pixel width, and half the pixel height. As such, we need to configure
* the underlying DMA library to match the same. Then we use the VirtualMatrixPanel_T class to map the
* physical pixels to the virtual pixels.
*/
HUB75_I2S_CFG mxconfig(
PANEL_RES_X*2, // DO NOT CHANGE THIS
PANEL_RES_Y/2, // DO NOT CHANGE THIS
1 // A Single panel
//, _pins
);
#endif
#if EXAMPLE_NUMBER == 4
// A single normal scan panel, but we're using a custom CustomScanTypeMapping in the 'wrong'
// way to demonstrate how it can be used to create custom physical LED Matrix panel mapping.
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};
// Standard panel type natively supported by this library (Example 1, 4)
HUB75_I2S_CFG mxconfig(
PANEL_RES_X,
PANEL_RES_Y,
PANEL_CHAIN_LEN
1
// , _pins
);
#endif
@ -185,6 +259,8 @@
virtualDisp = new VirtualMatrixPanel_T<PANEL_CHAIN_TYPE, MyScanTypeMapping>(VDISP_NUM_ROWS, VDISP_NUM_COLS, PANEL_RES_X, PANEL_RES_Y);
#elif EXAMPLE_NUMBER == 3
virtualDisp = new VirtualMatrixPanel_T<CHAIN_NONE, MyScanTypeMapping>(1, 1, PANEL_RES_X, PANEL_RES_Y); // Single 1/4 scan panel
#elif EXAMPLE_NUMBER == 4
virtualDisp = new VirtualMatrixPanel_T<CHAIN_NONE, CustomMirrorScanTypeMapping>(1, 1, PANEL_RES_X, PANEL_RES_Y); // Single 1/4 scan panel
#endif
// Pass a reference to the DMA display to the VirtualMatrixPanel_T class
@ -199,20 +275,25 @@
if (x == (virtualDisp->width()-1)) color = virtualDisp->color565(0, 0, 255); // b
virtualDisp->drawPixel(x, y, color);
delay(2);
delay(1);
}
}
virtualDisp->drawLine(virtualDisp->width() - 1, virtualDisp->height() - 1, 0, 0, virtualDisp->color565(255, 255, 255));
virtualDisp->print("Virtual Matrix Panel");
delay(3000);
virtualDisp->clearScreen();
virtualDisp->drawDisplayTest(); // re draw text numbering on each screen to check connectivity
}
// ------------------------------------------------------------------------------------------------------------
void loop() {
// Do nothing here.
delay (100);
}

View file

@ -103,7 +103,7 @@ template <PANEL_SCAN_TYPE ScanType>
struct ScanTypeMapping {
static constexpr VirtualCoords apply(VirtualCoords coords, int virt_y, int panel_pixel_base)
{
log_v("ScanTypeMapping: coords.x: %d, coords.y: %d, virt_y: %d, pixel_base: %d", coords.x, coords.y, virt_y, panel_pixel_base);
//log_v("ScanTypeMapping: coords.x: %d, coords.y: %d, virt_y: %d, pixel_base: %d", coords.x, coords.y, virt_y, panel_pixel_base);
// FOUR_SCAN_16PX_HIGH
if constexpr (ScanType == FOUR_SCAN_16PX_HIGH)
@ -301,7 +301,7 @@ public:
this->setCursor(start_x + panel_res_x/2 - 2, start_y + panel_res_y/2 - 4);
this->print(panel_id);
log_d("drawDisplayTest() Panel: %d, start_x: %d, start_y: %d", panel_id, start_x, start_y);
//log_d("drawDisplayTest() Panel: %d, start_x: %d, start_y: %d", panel_id, start_x, start_y);
}
}