ESP32-HUB75-MatrixPanel-DMA
ESP32-HUB75-MatrixPanel-DMA copied to clipboard
Problem with ICN2037BP driver chip
Hi
I'm working with ESP32 and 32*64 P5 panel with ICN2037BP chip. I'm trying to write simple HELLO message but it is not displayed properly. Same code works with FM6124 chip.
This is my code:
#define R1_PIN 25
#define G1_PIN 26
#define B1_PIN 27
#define R2_PIN 14
#define G2_PIN 12
#define B2_PIN 13
#define A_PIN 23
#define B_PIN 19
#define C_PIN 5
#define D_PIN 33 // Connected to GND on panel (21 if exist)
#define E_PIN -1 // Connected to GND on panel
#define LAT_PIN 4
#define OE_PIN 15
#define CLK_PIN 18
const int panelResX = 64; // Number of pixels wide of each INDIVIDUAL panel module.
const int panelResY = 32; // Number of pixels tall of each INDIVIDUAL panel module.
const int panel_chain = 1; // Total number of panels chained one to another
MatrixPanel_I2S_DMA *dma_display = nullptr;
uint16_t myBLACK = dma_display->color565(0, 0, 0);
uint16_t myWHITE = dma_display->color565(255, 255, 255);
uint16_t myRED = dma_display->color565(255, 0, 0);
uint16_t myGREEN = dma_display->color565(0, 255, 0);
uint16_t myBLUE = dma_display->color565(0, 0, 255);
void displaySetup() {
HUB75_I2S_CFG::i2s_pins _pins = {
R1_PIN, G1_PIN, B1_PIN, R2_PIN, G2_PIN, B2_PIN,
A_PIN, B_PIN, C_PIN, D_PIN, E_PIN,
LAT_PIN, OE_PIN, CLK_PIN
};
HUB75_I2S_CFG mxconfig(
panelResX, // module width
panelResY, // module height
panel_chain, // Chain length
_pins
);
mxconfig.clkphase = false;
dma_display = new MatrixPanel_I2S_DMA(mxconfig);
dma_display->begin();
}
void setup() {
Serial.begin(115200);
displaySetup();
dma_display->clearScreen();
dma_display->fillScreen(myBLACK);
dma_display->setTextWrap(false);
dma_display->setTextSize(2); // size 2 == 16 pixels high
dma_display->setTextColor(myGREEN);
dma_display->setCursor(0, 8);
dma_display->print("Hello");
}
void loop() {
}
I found a solution with in 1/8 Scan Panel Demonstration. I changed the code, it's working like a virtual 2nd panel. Everything is OK for now.
This is my code:
#include "ESP32-HUB75-MatrixPanel-I2S-DMA.h"
#include "ESP32-VirtualMatrixPanel-I2S-DMA.h"
#define R1_PIN 25
#define G1_PIN 26
#define B1_PIN 27
#define R2_PIN 14
#define G2_PIN 12
#define B2_PIN 13
#define A_PIN 23
#define B_PIN 19
#define C_PIN 5
#define D_PIN 33 // Connected to GND on panel (21 if exist)
#define E_PIN -1 // Connected to GND on panel
#define LAT_PIN 4
#define OE_PIN 15
#define CLK_PIN 18
// Panel configuration
#define PANEL_RES_X 64 // Number of pixels wide of each INDIVIDUAL panel module.
#define PANEL_RES_Y 32 // Number of pixels tall of each INDIVIDUAL panel module.
#define NUM_ROWS 1 // Number of rows of chained INDIVIDUAL PANELS
#define NUM_COLS 2 // Number of INDIVIDUAL PANELS per ROW
// NOTE: DEFAULT EXAMPLE SETUP IS FOR A CHAIN OF TWO x 1/8 SCAN PANELS
// Change this to your needs, for details on VirtualPanel pls read the PDF!
#define SERPENT true
#define TOPDOWN false
// placeholder for the matrix object
MatrixPanel_I2S_DMA *dma_display = nullptr;
// placeholder for the virtual display object
VirtualMatrixPanel *OneEightMatrixDisplay = nullptr;
uint16_t myBLACK = OneEightMatrixDisplay->color565(0, 0, 0);
uint16_t myWHITE = OneEightMatrixDisplay->color565(255, 255, 255);
uint16_t myRED = OneEightMatrixDisplay->color565(255, 0, 0);
uint16_t myGREEN = OneEightMatrixDisplay->color565(0, 255, 0);
uint16_t myBLUE = OneEightMatrixDisplay->color565(0, 0, 255);
void setup()
{
delay(250);
Serial.begin(115200);
// 62x32 1/8 Scan Panels don't have a D and E pin
HUB75_I2S_CFG::i2s_pins _pins = {
R1_PIN, G1_PIN, B1_PIN, R2_PIN, G2_PIN, B2_PIN,
A_PIN, B_PIN, C_PIN, D_PIN, E_PIN,
LAT_PIN, OE_PIN, CLK_PIN
};
HUB75_I2S_CFG mxconfig(
PANEL_RES_X*2, // DO NOT CHANGE THIS
PANEL_RES_Y/2, // DO NOT CHANGE THIS
NUM_ROWS*NUM_COLS // DO NOT CHANGE THIS
,_pins // Uncomment to enable custom pins
);
mxconfig.clkphase = false; // Change this if you see pixels showing up shifted wrongly by one column the left or right.
//mxconfig.driver = HUB75_I2S_CFG::FM6126A; // in case that we use panels based on FM6126A chip, we can set it here before creating MatrixPanel_I2S_DMA object
// OK, now we can create our matrix object
dma_display = new MatrixPanel_I2S_DMA(mxconfig);
// let's adjust default brightness to about 75%
dma_display->setBrightness8(96); // range is 0-255, 0 - 0%, 255 - 100%
// Allocate memory and start DMA display
if( not dma_display->begin() )
Serial.println("****** !KABOOM! I2S memory allocation failed ***********");
dma_display->clearScreen();
delay(500);
// create OneEightMatrixDisplaylay object based on our newly created dma_display object
OneEightMatrixDisplay = new VirtualMatrixPanel((*dma_display), NUM_ROWS, NUM_COLS, PANEL_RES_X, PANEL_RES_Y, SERPENT, TOPDOWN);
// THE IMPORTANT BIT BELOW!
OneEightMatrixDisplay->setPhysicalPanelScanRate(ONE_EIGHT_32);
OneEightMatrixDisplay->clearScreen();
OneEightMatrixDisplay->fillScreen(myBLACK);
OneEightMatrixDisplay->setTextWrap(false);
OneEightMatrixDisplay->setTextSize(2); // size 2 == 16 pixels high
OneEightMatrixDisplay->setTextColor(myGREEN);
OneEightMatrixDisplay->setCursor(65, 8);
OneEightMatrixDisplay->print("Hello");
}
void loop() {
}
Thank you for this workaround @kucukkose. I have a chain of two 64x64 outdoor 1/16 scan panels driven by the ICN2037BP chips (https://aliexpress.com/item/1005002233901619.html). Using the workaround described in this issue I kind of got them working, but not quite: the rows 16..23 were swapped with the rows 8..15, and the rows 40..47 were swapped with the rows 48..55.
As I needed a quick solution, I have made a dirty patch to VirtualMatrixPanel::getCoords() method, adding this line:
if ((virt_y & 8) != ((virt_y & 16) >> 1)) { virt_y = (virt_y & 0b11000) ^ 0b11000 + (virt_y & 0b11100111); }
But that's of course mega ugly, so I'd love to hear @mrfaptastic suggestion on how to integrate this properly. Add a new PANEL_SCAN_RATE for this type of panels? And thanks a lot for the great library, it really rocks!
But that's of course mega ugly, so I'd love to hear @mrfaptastic suggestion on how to integrate this properly. Add a new PANEL_SCAN_RATE for this type of panels? And thanks a lot for the great library, it really rocks!
Thank you for the kind words. To be honest, the whole VirtualMatrixPanel is a bit of a hack, especially for these non-standard scan-rate panels.
I've copy-pasted your code as a 'FOUR_SCAN_64PX_HIGH' option.
@mrfaptastic thanks for a super speedy response! The fix is a little bit more complex than that: for these 64px high panels to work we need to apply my code, but then we also need to apply all of your code from FOUR_SCAN_32PX_HIGH section (including x coordinate transformation and further y transformation too). So I guess a proper way would be to nest the ifs as follows:
...
else if ((panel_scan_rate == FOUR_SCAN_32PX_HIGH) || (panel_scan_rate == FOUR_SCAN_64PX_HIGH))
{
if (panel_scan_rate == FOUR_SCAN_64PX_HIGH)
{
// https://github.com/mrfaptastic/ESP32-HUB75-MatrixPanel-DMA/issues/345#issuecomment-1510401192
if ((virt_y & 8) != ((virt_y & 16) >> 1)) { virt_y = (virt_y & 0b11000) ^ 0b11000 + (virt_y & 0b11100111); }
}
/* Convert Real World 'VirtualMatrixPanel' co-ordinates (i.e. Real World pixel you're looking at
on the panel or chain of panels, per the chaining configuration) to a 1/8 panels
double 'stretched' and 'squished' coordinates which is what needs to be sent from the
DMA buffer.
Note: Look at the FourScanPanel example code and you'll see that the DMA buffer is setup
as if the panel is 2 * W and 0.5 * H !
*/
if ((virt_y & 8) == 0)
{
coords.x += ((coords.x / panelResX) + 1) * panelResX; // 1st, 3rd 'block' of 8 rows of pixels, offset by panel width in DMA buffer
}
else
{
coords.x += (coords.x / panelResX) * panelResX; // 2nd, 4th 'block' of 8 rows of pixels, offset by panel width in DMA buffer
}
// http://cpp.sh/4ak5u
// Real number of DMA y rows is half reality
// coords.y = (y / 16)*8 + (y & 0b00000111);
coords.y = (virt_y >> 4) * 8 + (virt_y & 0b00000111);
}
...
BTW the http://cpp.sh/4ak5u
link appear to be dead, so can be removed from the code for clarity.
Ah ok. Thanks for this feedback! Can you raise a pull request and I'll integrate?
KUCUKKOSE, I have the same problem on my P6 8S 32x32 led panel with TC5020AP IC led driver. I try your advice and code from Nov 24 2022 but I have a problem with lib. Can you please share full code with used lib?
When I try to use your code 2 problems appear:
OneEightMatrixDisplay = new VirtualMatrixPanel((*dma_display), NUM_ROWS, NUM_COLS, PANEL_RES_X, PANEL_RES_Y, SERPENT, TOPDOWN);
and
OneEightMatrixDisplay->setPhysicalPanelScanRate(ONE_EIGHT_32);
with explanations "candidate expects 6 arguments, 7 provided" and "error: 'ONE_EIGHT_32' was not declared in this scope".
Thanks, regards
@rigorka Did you try to chain Your outdoor panels in more than one row scheme? like 2x2 or more? I cannot run more than one row with FOUR_SCAN_64PX_HIGH option.
@primus192 - can you post an example of the sketch code and also pictures of the test pattern to show the issue?
I think it is better to discuss it here https://github.com/mrfaptastic/ESP32-HUB75-MatrixPanel-DMA/issues/468#issuecomment-1624820750