mrcodetastic / ESP32-HUB75-MatrixPanel-DMA

An Adafruit GFX Compatible Library for the ESP32, ESP32-S2, ESP32-S3 to drive HUB75 LED matrix panels using DMA for high refresh rates. Supports panel chaining.
MIT License
921 stars 204 forks source link

1/8 Scan Panel support - 64 x 32 panel horizontal lines doubled #154

Closed donnersm closed 2 years ago

donnersm commented 3 years ago

I just tested a panel i just received today. Its a 64 x 32 panel. It looks like the horizontal is not working, lines are doubled in an array of 8 Anyone recognise this or is this a defective panel? (Beside from the defective pixel near one corner)

https://user-images.githubusercontent.com/60584210/126544627-5c615cfe-e9d1-433f-962e-325da9e36a2a.mp4

mrcodetastic commented 3 years ago

Can you draw a single diagonal line as well?

Looks like some address line issue, check the A,B,C,D pin mapping - perhaps the pins may have moved? Who knows. There seems to be a few of these issues being raised recently.

donnersm commented 3 years ago

I Checked the pins on the display and all is "standard" except the LAT pin is called STB. I tried a vertical line and a circle:

dma_display->clearScreen();
dma_display->drawLine(dma_display->width()-1, 0, 0, dma_display->height()-1, dma_display->color444(15, 0, 0));
dma_display->clearScreen();
delay(500);
dma_display->fillCircle(40, 21, 10, dma_display->color444(15, 0, 15));

Here are the photo's of that result: vertical circle

mrcodetastic commented 3 years ago

Closing this issue as it's superseded by #164

AlfioSaitta commented 2 years ago

I Checked the pins on the display and all is "standard" except the LAT pin is called STB. I tried a vertical line and a circle:

dma_display->clearScreen();
dma_display->drawLine(dma_display->width()-1, 0, 0, dma_display->height()-1, dma_display->color444(15, 0, 0));
dma_display->clearScreen();
delay(500);
dma_display->fillCircle(40, 21, 10, dma_display->color444(15, 0, 15));

Here are the photo's of that result: vertical circle

I have the exact same problem. Have you finally solved it?

DarrylStrong commented 2 years ago

Do you have a picture of the back of the PCB? Connectors and driver ICs?

donnersm commented 2 years ago

I didnt solve it. It turned out to be a 1/8 scan panel which is not supported by the library. We should be able to change the libary because it is al telated to the way the data is sorted bitwise before sending it to the panel but my knowledge of this lib is limited

AlfioSaitta commented 2 years ago

Do you have a picture of the back of the PCB? Connectors and driver ICs?

My simple code with the git version of the library:

#define MATRIX_WIDTH 64
#define MATRIX_HEIGHT 32
#define CHAIN_LENGTH 1
#define MATRIX_ROWS_IN_PARALLEL 2
#define PIXEL_COLOR_DEPTH_BITS 8

#define R1_PIN  2
#define G1_PIN  15
#define B1_PIN  4
#define R2_PIN  16
#define G2_PIN  27
#define B2_PIN  17

#define A_PIN   5
#define B_PIN   18
#define C_PIN   19
#define D_PIN   -1 // Connected to GND on panel (21 if exist)
#define E_PIN   -1 // Connected to GND on panel

#define LAT_PIN 26
#define OE_PIN  25
#define CLK_PIN 22

#include <Arduino.h>
#include <Wire.h>
#include <SPI.h>
#include <ESP32-HUB75-MatrixPanel-I2S-DMA.h>

MatrixPanel_I2S_DMA *dma_display = nullptr;

void setup() {

  Serial.begin(115200);

  delay(1000);

  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
  };

  // Module configuration
  HUB75_I2S_CFG mxconfig(
      MATRIX_WIDTH, // module width
      MATRIX_HEIGHT, // module height
      CHAIN_LENGTH, // Chain length
      _pins);

  //mxconfig.driver = HUB75_I2S_CFG::SHIFTREG;
  //mxconfig.double_buff = true;
  //mxconfig.clkphase = false;
  //mxconfig.i2sspeed = HUB75_I2S_CFG::HZ_20M;

  dma_display = new MatrixPanel_I2S_DMA(mxconfig);

  dma_display->begin();
  dma_display->setBrightness8(100); //0-255
  dma_display->clearScreen();

  // First Half Display
  dma_display->drawLine(0, 0, 15, 0, dma_display->color444(0, 15, 0));
  dma_display->drawLine(0, 1, 31, 1, dma_display->color444(15, 0, 0));
  dma_display->drawLine(0, 2, 63, 2, dma_display->color444(0, 0, 15));

  // Second Half Display
  dma_display->drawLine(0, 16, 15, 16, dma_display->color444(0, 15, 15));
  dma_display->drawLine(0, 17, 31, 17, dma_display->color444(15, 15, 0));
  dma_display->drawLine(0, 18, 63, 18, dma_display->color444(15, 0, 15));
}

void loop() {
    //delay(20); 
}

IMG_20211009_152437

IMG_20211009_151858

IMG_20211009_151833

IMG_20211009_151749

mrcodetastic commented 2 years ago

Looks like a pretty simple issue to fix with your own custom code, looks like 2 X 1/4th of the panel rows chained together, for both the top and bottom halves of the display.

Change the width of the display of the library to double the physical width and play around?

AlfioSaitta commented 2 years ago

Looks like a pretty simple issue to fix with your own custom code, looks like 2 X 1/4th of the panel rows chained together, for both the top and bottom halves of the display.

Change the width of the display of the library to double the physical width and play around?

#define MATRIX_WIDTH 128
#define MATRIX_HEIGHT 32
#define CHAIN_LENGTH 1
#define MATRIX_ROWS_IN_PARALLEL 2
#define PIXEL_COLOR_DEPTH_BITS 8

Result with these settings: IMG_20211009_155330

AlfioSaitta commented 2 years ago

Looks like a pretty simple issue to fix with your own custom code, looks like 2 X 1/4th of the panel rows chained together, for both the top and bottom halves of the display.

Change the width of the display of the library to double the physical width and play around?

Eureka... very strange settings... but work :D

IMG_20211010_005725

My code:

#define CHAIN_LENGTH 2

#define R1_PIN  2
#define G1_PIN  15
#define B1_PIN  4
#define R2_PIN  16
#define G2_PIN  27
#define B2_PIN  17

#define A_PIN   5
#define B_PIN   18
#define C_PIN   19
#define D_PIN   -1 // Connected to GND on panel (21 if exist)
#define E_PIN   -1 // Connected to GND on panel

#define LAT_PIN 26
#define OE_PIN  25
#define CLK_PIN 22

#include <Arduino.h>
#include <ESP32-HUB75-MatrixPanel-I2S-DMA.h>

MatrixPanel_I2S_DMA *dma_display = nullptr;

void testScreen() {
  // Red 8 Rows
  for (int x=0; x <= 64; x++) {
    dma_display->drawPixel(63+x,0,dma_display->color565(255, 0, 0)); // ROW 1
    dma_display->drawPixel(63+x,1,dma_display->color565(210, 0, 0)); // ROW 2
    dma_display->drawPixel(63+x,2,dma_display->color565(180, 0, 0)); // ROW 3
    dma_display->drawPixel(63+x,3,dma_display->color565(150, 0, 0)); // ROW 4
    dma_display->drawPixel(63+x,4,dma_display->color565(125, 0, 0)); // ROW 5
    dma_display->drawPixel(63+x,5,dma_display->color565(90, 0, 0)); // ROW 6
    dma_display->drawPixel(63+x,6,dma_display->color565(60, 0, 0)); // ROW 7
    dma_display->drawPixel(63+x,7,dma_display->color565(40, 0, 0)); // ROW 8
  }

  // Green 8 Rows
  for (int x=0; x <= 63; x++) {
    dma_display->drawPixel(0+x,8,dma_display->color565(0, 255, 0)); // ROW 9
    dma_display->drawPixel(0+x,9,dma_display->color565(0, 210, 0)); // ROW 10
    dma_display->drawPixel(0+x,10,dma_display->color565(0, 180, 0)); // ROW 11
    dma_display->drawPixel(0+x,11,dma_display->color565(0, 150, 0)); // ROW 12
    dma_display->drawPixel(0+x,12,dma_display->color565(0, 125, 0)); // ROW 13
    dma_display->drawPixel(0+x,13,dma_display->color565(0, 90, 0)); // ROW 14
    dma_display->drawPixel(0+x,14,dma_display->color565(0, 60, 0)); // ROW 15
    dma_display->drawPixel(0+x,15,dma_display->color565(0, 40, 0)); // ROW 16
  }

  // Blue 8 Rows
  for (int x=0; x <= 63; x++) {
    dma_display->drawPixel(64+x,16,dma_display->color565(0, 0, 255)); // ROW 17
    dma_display->drawPixel(64+x,17,dma_display->color565(0, 0, 210)); // ROW 18
    dma_display->drawPixel(64+x,18,dma_display->color565(0, 0, 180)); // ROW 19
    dma_display->drawPixel(64+x,19,dma_display->color565(0, 0, 150)); // ROW 20
    dma_display->drawPixel(64+x,20,dma_display->color565(0, 0, 125)); // ROW 21
    dma_display->drawPixel(64+x,21,dma_display->color565(0, 0, 90)); // ROW 22
    dma_display->drawPixel(64+x,22,dma_display->color565(0, 0, 60)); // ROW 23
    dma_display->drawPixel(64+x,23,dma_display->color565(0, 0, 40)); // ROW 24
  }

  // White 8 Rows
  for (int x=0; x <= 63; x++) {
    dma_display->drawPixel(0+x,24,dma_display->color565(255, 255, 255)); // ROW 25
    dma_display->drawPixel(0+x,25,dma_display->color565(210, 210, 210)); // ROW 26
    dma_display->drawPixel(0+x,26,dma_display->color565(180, 180, 180)); // ROW 27
    dma_display->drawPixel(0+x,27,dma_display->color565(150, 150, 150)); // ROW 28
    dma_display->drawPixel(0+x,28,dma_display->color565(125, 125, 125)); // ROW 29
    dma_display->drawPixel(0+x,29,dma_display->color565(90, 90, 90)); // ROW 30
    dma_display->drawPixel(0+x,30,dma_display->color565(60, 60, 60)); // ROW 31
    dma_display->drawPixel(0+x,31,dma_display->color565(40, 40, 40)); // ROW 32
  }
}

void setup() {

  Serial.begin(115200);
  delay(1000);

  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( 64, 32, CHAIN_LENGTH, _pins);

  mxconfig.double_buff = true;
  mxconfig.i2sspeed = HUB75_I2S_CFG::HZ_20M;

  dma_display = new MatrixPanel_I2S_DMA(mxconfig);
  dma_display->begin();
  dma_display->setBrightness8(20); //0-255
  dma_display->clearScreen();
}

void loop() {
    delay(20); 
    testScreen();
}
mrcodetastic commented 2 years ago

Good work on figuring that out. As expected, it's actually a chain of panels, with some weird chaining going on there between the 1/4ths of the panel, with the 2nd 1/4th being chained to the first (top) 1/4th of the panel.

What happens when you set: HUB75_I2S_CFG mxconfig( 64, 32, CHAIN_LENGTH, _pins); to HUB75_I2S_CFG mxconfig( 64, 16, CHAIN_LENGTH, _pins);

Because if you do the math, 8 pixels of each 'half' of the panel don't actually get used given this library is designed for 1/2 scan panels, and these panels actually chain the 2nd 1/4th with the 1st 1/4.

mrcodetastic commented 2 years ago

All you need to do is make your own wrapper to this library, like the 'Virtual Display' cpp file, which will override the operation of the drawPixel() function based on the value of the x-coord - then you have yourself a working library for these 1/4 scan panels.

Feel free to contribute then :-)

AlfioSaitta commented 2 years ago

Good work on figuring that out. As expected, it's actually a chain of panels, with some weird chaining going on there between the 1/4ths of the panel, with the 2nd 1/4th being chained to the first (top) 1/4th of the panel.

What happens when you set: HUB75_I2S_CFG mxconfig( 64, 32, CHAIN_LENGTH, _pins); to HUB75_I2S_CFG mxconfig( 64, 16, CHAIN_LENGTH, _pins);

Because if you do the math, 8 pixels of each 'half' of the panel don't actually get used given this library is designed for 1/2 scan panels, and these panels actually chain the 2nd 1/4th with the 1st 1/4.

Result with your settings and corrected the math a bit:

IMG_20211010_120358

#define CHAIN_LENGTH 2 // 2 Chained panels
#define PANEL_WIDHT 64
#define PANEL_HEIGHT 16 // 1/8 Scan in the specifics ???

#define R1_PIN  2
#define G1_PIN  15
#define B1_PIN  4
#define R2_PIN  16
#define G2_PIN  27
#define B2_PIN  17

#define A_PIN   5
#define B_PIN   18
#define C_PIN   19
#define D_PIN   -1 // Connected to GND on panel (21 if exist)
#define E_PIN   -1 // Connected to GND on panel

#define LAT_PIN 26
#define OE_PIN  25
#define CLK_PIN 22

#include <Arduino.h>
#include <ESP32-HUB75-MatrixPanel-I2S-DMA.h>

MatrixPanel_I2S_DMA *dma_display = nullptr;

void testScreen() {

  for (int x=0; x <= 63; x++) {

    // Red 8 Rows
    dma_display->drawPixel(64+(x),0,dma_display->color565(255, 0, 0)); // ROW 1
    dma_display->drawPixel(64+(x),1,dma_display->color565(210, 0, 0)); // ROW 2
    dma_display->drawPixel(64+(x),2,dma_display->color565(180, 0, 0)); // ROW 3
    dma_display->drawPixel(64+(x),3,dma_display->color565(150, 0, 0)); // ROW 4
    dma_display->drawPixel(64+(x),4,dma_display->color565(125, 0, 0)); // ROW 5
    dma_display->drawPixel(64+(x),5,dma_display->color565(90, 0, 0)); // ROW 6
    dma_display->drawPixel(64+(x),6,dma_display->color565(60, 0, 0)); // ROW 7
    dma_display->drawPixel(64+(x),7,dma_display->color565(40, 0, 0)); // ROW 8

    // Blue 8 Rows
    dma_display->drawPixel(0+x,0,dma_display->color565(0, 0, 255)); // ROW 9
    dma_display->drawPixel(0+x,1,dma_display->color565(0, 0, 210)); // ROW 10
    dma_display->drawPixel(0+x,2,dma_display->color565(0, 0, 180)); // ROW 11
    dma_display->drawPixel(0+x,3,dma_display->color565(0, 0, 150)); // ROW 12
    dma_display->drawPixel(0+x,4,dma_display->color565(0, 0, 125)); // ROW 13
    dma_display->drawPixel(0+x,5,dma_display->color565(0, 0, 90)); // ROW 14
    dma_display->drawPixel(0+x,6,dma_display->color565(0, 0, 60)); // ROW 15
    dma_display->drawPixel(0+x,7,dma_display->color565(0, 0, 40)); // ROW 16

    // White 8 Rows
    dma_display->drawPixel(64+x,8,dma_display->color565(255, 255, 255)); // ROW 17
    dma_display->drawPixel(64+x,9,dma_display->color565(210, 210, 210)); // ROW 18
    dma_display->drawPixel(64+x,10,dma_display->color565(180, 180, 180)); // ROW 19
    dma_display->drawPixel(64+x,11,dma_display->color565(150, 150, 150)); // ROW 20
    dma_display->drawPixel(64+x,12,dma_display->color565(125, 125, 125)); // ROW 21
    dma_display->drawPixel(64+x,13,dma_display->color565(90, 90, 90)); // ROW 22
    dma_display->drawPixel(64+x,14,dma_display->color565(60, 60, 60)); // ROW 23
    dma_display->drawPixel(64+x,15,dma_display->color565(40, 40, 40)); // ROW 24

    // Green 8 Rows
    dma_display->drawPixel(0+x,8,dma_display->color565(0, 255, 0)); // ROW 25
    dma_display->drawPixel(0+x,9,dma_display->color565(0, 210, 0)); // ROW 26
    dma_display->drawPixel(0+x,10,dma_display->color565(0, 180, 0)); // ROW 27
    dma_display->drawPixel(0+x,11,dma_display->color565(0, 150, 0)); // ROW 28
    dma_display->drawPixel(0+x,12,dma_display->color565(0, 125, 0)); // ROW 29
    dma_display->drawPixel(0+x,13,dma_display->color565(0, 90, 0)); // ROW 30
    dma_display->drawPixel(0+x,14,dma_display->color565(0, 60, 0)); // ROW 31
    dma_display->drawPixel(0+x,15,dma_display->color565(0, 40, 0)); // ROW 32
  }
}

void setup() {

  Serial.begin(115200);
  delay(1000);

  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_WIDHT, PANEL_HEIGHT, CHAIN_LENGTH, _pins);

  mxconfig.double_buff = true; // ????
  mxconfig.i2sspeed = HUB75_I2S_CFG::HZ_20M;

  dma_display = new MatrixPanel_I2S_DMA(mxconfig);
  dma_display->begin();
  dma_display->setBrightness8(200); //0-255
  dma_display->clearScreen();
}

void loop() {
    //delay(40); 
    testScreen();
}

After researching in various Chinese retailers and factories, i found some more information on the panel:

Pixel Pitch: P4
Dimension: 128X256
Lamp bead: RGB
LED Type: SMD1921
Scanning Mode: 1/8
mrcodetastic commented 2 years ago

Hi @AlfioSaitta - thanks again for the great work with trying this out, really helps me understand what's going on here!

I did notice one thing with you photo, what's the go on the top left? Looks to be a row of missing pixels? Or is the pixels broken in that area?

image

AlfioSaitta commented 2 years ago

Hi @AlfioSaitta - thanks again for the great work with trying this out, really helps me understand what's going on here!

I did notice one thing with you photo, what's the go on the top left? Looks to be a row of missing pixels? Or is the pixels broken in that area?

I think it's a power problem. I'm using the raspberry power supply to power the panel :dancers:

https://user-images.githubusercontent.com/10280718/136692822-862c8240-afb5-4614-b84d-488f79f492cf.mp4

mrcodetastic commented 2 years ago

Good work. I've created a 'VirtualDisplay' like class that does co-ordinate re-mapping, like it seems you have coded manually.

I don't have one of these 1/8 scan panels - can you try this out?

https://github.com/mrfaptastic/ESP32-HUB75-MatrixPanel-I2S-DMA/tree/master/examples/One_Eighth_1_8_ScanPanel

AlfioSaitta commented 2 years ago

Good work. I've created a 'VirtualDisplay' like class that does co-ordinate re-mapping, like it seems you have coded manually.

I don't have one of these 1/8 scan panels - can you try this out?

https://github.com/mrfaptastic/ESP32-HUB75-MatrixPanel-I2S-DMA/tree/master/examples/One_Eighth_1_8_ScanPanel

Yes, of course

AlfioSaitta commented 2 years ago

Generate error here: rows and cols are not defined https://github.com/mrfaptastic/ESP32-HUB75-MatrixPanel-I2S-DMA/blob/ad2cb3c9767125e682fa4a494f47e357bbb0fb3f/examples/One_Eighth_1_8_ScanPanel/OneEighthScanMatrixPanel.h#L175

mrcodetastic commented 2 years ago

Whoops. I've fixed that.

AlfioSaitta commented 2 years ago

Something went wrong!!!

IMG_20211010_224105

#define PANEL_WIDHT 64
#define PANEL_HEIGHT 32

#define PANEL_CHAIN NUM_ROWS*NUM_COLS    // total number of panels chained one to another

// Change this to your needs, for details on VirtualPanel pls read the PDF!
#define SERPENT true
#define TOPDOWN false

#define R1_PIN  2
#define G1_PIN  15
#define B1_PIN  4
#define R2_PIN  16
#define G2_PIN  27
#define B2_PIN  17

#define A_PIN   5
#define B_PIN   18
#define C_PIN   19
#define D_PIN   -1 // Connected to GND on panel (21 if exist)
#define E_PIN   -1 // Connected to GND on panel

#define LAT_PIN 26
#define OE_PIN  25
#define CLK_PIN 22

#include <Arduino.h>
//#include <ESP32-HUB75-MatrixPanel-I2S-DMA.h>
#include <OneEighthScanMatrixPanel.h>

MatrixPanel_I2S_DMA *dma_display = nullptr;
OneEighthMatrixPanel *virtualDisp = nullptr;

void setup() {

  Serial.begin(115200);
  delay(100);

  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_WIDHT*2, PANEL_HEIGHT/2, PANEL_CHAIN, _pins);

  mxconfig.i2sspeed = HUB75_I2S_CFG::HZ_20M;

  dma_display = new MatrixPanel_I2S_DMA(mxconfig);
  dma_display->begin();
  dma_display->setBrightness8(30); //0-255
  dma_display->clearScreen();

  // create VirtualDisplay object based on our newly created dma_display object
  virtualDisp = new OneEighthMatrixPanel((*dma_display), 1, 1, PANEL_WIDHT, PANEL_HEIGHT, SERPENT, TOPDOWN);

  virtualDisp->setTextColor(virtualDisp->color565(0, 0, 255));
  virtualDisp->setCursor(0, virtualDisp->height()/2); 

  // Red text inside red rect (2 pix in from edge)
  virtualDisp->print("  1234");
  virtualDisp->drawRect(1,1, virtualDisp->width()-2, virtualDisp->height()-2, virtualDisp->color565(255,0,0));

  // White line from top left to bottom right
  virtualDisp->drawLine(0,0, virtualDisp->width()-1, virtualDisp->height()-1, virtualDisp->color565(255,255,255));

}

void loop() {
  //delay(40); 
}
mrcodetastic commented 2 years ago

I've made another change. Problem is I don't know if I should have the -= 8; enabled where it is, or uncommented/enabled on line 163 of https://github.com/mrfaptastic/ESP32-HUB75-MatrixPanel-I2S-DMA/blob/master/examples/One_Eighth_1_8_ScanPanel/OneEighthScanMatrixPanel.h#L158

https://github.com/mrfaptastic/ESP32-HUB75-MatrixPanel-I2S-DMA/blob/32f86bb87061e8d16feadcc50e2dd8c53221ef3a/examples/One_Eighth_1_8_ScanPanel/OneEighthScanMatrixPanel.h#L158

Please test and find out :-)

AlfioSaitta commented 2 years ago

Some tests with lines before your last changes:

  virtualDisp->drawLine(0, 0, 63, 0, virtualDisp->color565(255,255,255)); // VISIBLE ON ROW 1
  virtualDisp->drawLine(0, 8, 63, 8, virtualDisp->color565(255,255,0)); // VISIBLE ON ROW 13 (WITH LAST PIXEL RED)
  virtualDisp->drawLine(0, 9, 63, 9, virtualDisp->color565(255,0,0)); // VISIBLE ON ROW 13 (COVERS THE PREVIOUS ROW)
  virtualDisp->drawLine(0, 17, 63, 17, virtualDisp->color565(255,0,255)); // VISIBLE ON ROW 17
  virtualDisp->drawLine(0, 31, 63, 31, virtualDisp->color565(0,255,0)); // VISIBLE ON ROW 32

IMG_20211010_230950

AlfioSaitta commented 2 years ago

With your latest changes:

IMG_20211010_231434

#define PANEL_WIDHT 64
#define PANEL_HEIGHT 32 // 1/8 Scan in the specifics ???

#define NUM_ROWS 1 // Number of rows of chained INDIVIDUAL PANELS
#define NUM_COLS 1 // Number of INDIVIDUAL PANELS per ROW

#define PANEL_CHAIN NUM_ROWS*NUM_COLS    // total number of panels chained one to another

// Change this to your needs, for details on VirtualPanel pls read the PDF!
#define SERPENT true
#define TOPDOWN false

#define R1_PIN  2
#define G1_PIN  15
#define B1_PIN  4
#define R2_PIN  16
#define G2_PIN  27
#define B2_PIN  17

#define A_PIN   5
#define B_PIN   18
#define C_PIN   19
#define D_PIN   -1 // Connected to GND on panel (21 if exist)
#define E_PIN   -1 // Connected to GND on panel

#define LAT_PIN 26
#define OE_PIN  25
#define CLK_PIN 22

#include <Arduino.h>
//#include <ESP32-HUB75-MatrixPanel-I2S-DMA.h>
#include <OneEighthScanMatrixPanel.h>

MatrixPanel_I2S_DMA *dma_display = nullptr;
OneEighthMatrixPanel *virtualDisp = nullptr;

void drawPicture() {

  int counter = 0;

  for (int y = 0; y <= 7; y++){
    for (int x=0; x <= 63; x++) {
      dma_display->drawPixel(64+x , y, mycar[counter]);
      counter++;
    }
  }

  for (int y = 0; y <= 7; y++){
    for (int x=0; x <= 63; x++) {
      dma_display->drawPixel(0+x , y, mycar[counter]);
      counter++;
    }
  }

  for (int y = 8; y <= 15; y++){
    for (int x=0; x <= 63; x++) {
      dma_display->drawPixel(64+x , y, mycar[counter]);
      counter++;
    }
  }

  for (int y = 8; y <= 15; y++){
    for (int x=0; x <= 63; x++) {
      dma_display->drawPixel(0+x , y, mycar[counter]);
      counter++;
    }
  }
}

void setup() {

  Serial.begin(115200);
  delay(100);

  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_WIDHT*2, PANEL_HEIGHT/2, PANEL_CHAIN, _pins);

  mxconfig.i2sspeed = HUB75_I2S_CFG::HZ_20M;

  dma_display = new MatrixPanel_I2S_DMA(mxconfig);
  dma_display->begin();
  dma_display->setBrightness8(30); //0-255
  dma_display->clearScreen();

  virtualDisp = new OneEighthMatrixPanel((*dma_display), 1, 1, PANEL_WIDHT, PANEL_HEIGHT, SERPENT, TOPDOWN);

  virtualDisp->drawLine(0, 0, 63, 0, virtualDisp->color565(255,255,255)); // VISIBLE ON ROW 1
  virtualDisp->drawLine(0, 8, 63, 8, virtualDisp->color565(255,255,0)); // VISIBLE ON ROW 13 (WITH LAST PIXEL RED)
  virtualDisp->drawLine(0, 9, 63, 9, virtualDisp->color565(255,0,0)); // VISIBLE ON ROW 13 (COVERS THE PREVIOUS ROW)
  virtualDisp->drawLine(0, 17, 63, 17, virtualDisp->color565(255,0,255)); // VISIBLE ON ROW 17
  virtualDisp->drawLine(0, 31, 63, 31, virtualDisp->color565(0,255,0)); // VISIBLE ON ROW 32
}
mrcodetastic commented 2 years ago

Yeah, I figured out the problem and my last commit in my previous comment was wrong.

Hopefully it's fixed now !

AlfioSaitta commented 2 years ago

Sorry. I figured out the problem and my last commit in my previous comment was wrong.

Hopefully it's fixed now !

IMG_20211010_231945

mrcodetastic commented 2 years ago

Try again now. 5th time lucky.

Wrote some code to emulate my logic: http://cpp.sh/6skpy

AlfioSaitta commented 2 years ago

Try again now. 5th time lucky.

Wrote some code to emulate my logic: http://cpp.sh/6skpy

IMG_20211011_001130 IMG_20211011_001240

mrcodetastic commented 2 years ago

So it's ok? Not sure why there are missing bits of the red box but that was your power supply right?

AlfioSaitta commented 2 years ago

I'm doing various tests... but i think my panel doesn't like the color red without proper power supply, but the library is working perfectly. Great work ;)

https://user-images.githubusercontent.com/10280718/136715954-d978209b-1994-4407-b95c-2bae184db484.mp4

AlfioSaitta commented 2 years ago

Tomorrow in the office i will check if it works well in chain with other panels, and especially with their power supplies :kissing_closed_eyes:

mrcodetastic commented 2 years ago

Nice one. They have to be a chain of all the same type of panel scan rate though.

AlfioSaitta commented 2 years ago

Nice one. They have to be a chain of all the same type of panel scan rate though.

#define NUM_ROWS 1 // Number of rows of chained INDIVIDUAL PANELS
#define NUM_COLS 1 // Number of INDIVIDUAL PANELS per ROW

drawPicture(mario, 0, 0);

IMG_20211011_102612

#define NUM_ROWS 1 // Number of rows of chained INDIVIDUAL PANELS
#define NUM_COLS 3 // Number of INDIVIDUAL PANELS per ROW

drawPicture(mario, 0, 0);

IMG_20211011_102937

AlfioSaitta commented 2 years ago

I can't draw starting after the first panel

#define NUM_ROWS 1 // Number of rows of chained INDIVIDUAL PANELS
#define NUM_COLS 3 // Number of INDIVIDUAL PANELS per ROW

virtualDisp = new OneEighthMatrixPanel((*dma_display), NUM_ROWS, NUM_COLS, PANEL_WIDHT, PANEL_HEIGHT, SERPENT, TOPDOWN);

void drawPicture(uint16_t Picture[2048], int StartX, int StartY) {
  int counter = 0;
  for (int y = StartY; y <= StartY+(PANEL_HEIGHT-1); y++){
    for (int x=StartX; x <= StartX+(PANEL_WIDHT-1); x++) {
      virtualDisp->drawPixel(x , y, Picture[counter]);
      counter++;
    }
  }
}

drawPicture(mario, 64, 0);

IMG_20211011_104325

AlfioSaitta commented 2 years ago

drawPicture(mario, 128, 0);

IMG_20211011_104722

mrcodetastic commented 2 years ago

Made another change. No idea if it'll work.

AlfioSaitta commented 2 years ago

Made another change. No idea if it'll work.

Tomorrow morning at the office i'll try again. Thank you very much for your work :)

Today i was quite busy trying to divide on two different cores, the part concerning the drawing on the panel and the retrieval of frames from the network

mrcodetastic commented 2 years ago

No problems. What are you trying to make? I'll be interested to see what frame rate you can achieve eventually.

AlfioSaitta commented 2 years ago

No problems. What are you trying to make? I'll be interested to see what frame rate you can achieve eventually.

I want to divide the tasks to be performed on the two cores.

Actually i don't know the potential of the Esp, but i hope it behaves well :P

AlfioSaitta commented 2 years ago

What frame rate did you get in your tests?

mrcodetastic commented 2 years ago

I have never made such a thing or ever looked a frame rates.

AlfioSaitta commented 2 years ago

With your last changes:

#define PANEL_WIDHT 64
#define PANEL_HEIGHT 32

#define NUM_ROWS 1 // Number of rows of chained INDIVIDUAL PANELS
#define NUM_COLS 3 // Number of INDIVIDUAL PANELS per ROW

#define PANEL_CHAIN NUM_ROWS*NUM_COLS

#define SERPENT true
#define TOPDOWN false

setup() {
  ....
  HUB75_I2S_CFG mxconfig( PANEL_WIDHT*2, PANEL_HEIGHT/2, PANEL_CHAIN, _pins);

  mxconfig.i2sspeed = HUB75_I2S_CFG::HZ_20M;

  dma_display = new MatrixPanel_I2S_DMA(mxconfig);
  dma_display->begin();
  dma_display->setBrightness8(30); //0-255
  dma_display->clearScreen();
  ....
}

loop() {
  virtualDisp->drawLine(0,1,191,1,virtualDisp->color565(255,255,255));

  virtualDisp->drawLine(0,0,63,0,virtualDisp->color565(255,0,0));
  virtualDisp->drawLine(0,8,63,8,virtualDisp->color565(255,0,0));
  virtualDisp->drawLine(0,16,63,16,virtualDisp->color565(255,0,0));
  virtualDisp->drawLine(0,31,63,31,virtualDisp->color565(255,0,0));

  virtualDisp->drawLine(64,0,127,0,virtualDisp->color565(0,255,0));
  virtualDisp->drawLine(64,8,127,8,virtualDisp->color565(0,255,0));
  virtualDisp->drawLine(64,16,127,16,virtualDisp->color565(0,255,0));
  virtualDisp->drawLine(64,31,127,31,virtualDisp->color565(0,255,0));

  virtualDisp->drawLine(128,0,191,0,virtualDisp->color565(0,0,255));
  virtualDisp->drawLine(128,8,191,8,virtualDisp->color565(0,0,255));
  virtualDisp->drawLine(128,16,191,16,virtualDisp->color565(0,0,255));
  virtualDisp->drawLine(128,31,191,31,virtualDisp->color565(0,0,255));
}

IMG_20211012_141901

AlfioSaitta commented 2 years ago

After several tests, i still don't understand how the chain works and i haven't been able to solve the problem.

#define PANEL_WIDHT 64
#define PANEL_HEIGHT 32

#define NUM_ROWS 1
#define NUM_COLS 3

#define PANEL_CHAIN NUM_ROWS*NUM_COLS

#define SERPENT true
#define TOPDOWN false

#include <OneEighthScanMatrixPanel.h>

MatrixPanel_I2S_DMA *dma_display = nullptr;
OneEighthMatrixPanel *virtualDisp = nullptr;

void setup() {
  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_WIDHT*2, PANEL_HEIGHT/2, PANEL_CHAIN, _pins);

  mxconfig.i2sspeed = HUB75_I2S_CFG::HZ_20M;

  dma_display = new MatrixPanel_I2S_DMA(mxconfig);
  dma_display->begin();

  virtualDisp = new OneEighthMatrixPanel((*dma_display), NUM_ROWS, NUM_COLS, PANEL_WIDHT, PANEL_HEIGHT, SERPENT, TOPDOWN);
  virtualDisp->clearScreen();
}

X=0 Y=0 IMG_20211019_192622

X=65 Y=0 IMG_20211019_194813

X=65 Y=8 IMG_20211019_192718

Some times for a 2048px Image:

Fill picture time: 9ms on core 1 (extract from a json)
Draw picture time: 4ms on core 1 (draw to the matrix)

My Web Application: 192 168 1 214_8000_(HalfHD)

mrcodetastic commented 2 years ago

Made another change, not sure if it fixes the issue.

Experiment with lines 158-164 of 'OneEighthScanMatrixPanel.h' to see what works.

macduyhai commented 2 years ago

Good work on figuring that out. As expected, it's actually a chain of panels, with some weird chaining going on there between the 1/4ths of the panel, with the 2nd 1/4th being chained to the first (top) 1/4th of the panel. What happens when you set: HUB75_I2S_CFG mxconfig( 64, 32, CHAIN_LENGTH, _pins); to HUB75_I2S_CFG mxconfig( 64, 16, CHAIN_LENGTH, _pins); Because if you do the math, 8 pixels of each 'half' of the panel don't actually get used given this library is designed for 1/2 scan panels, and these panels actually chain the 2nd 1/4th with the 1st 1/4.

Result with your settings and corrected the math a bit:

IMG_20211010_120358

#define CHAIN_LENGTH 2 // 2 Chained panels
#define PANEL_WIDHT 64
#define PANEL_HEIGHT 16 // 1/8 Scan in the specifics ???

#define R1_PIN  2
#define G1_PIN  15
#define B1_PIN  4
#define R2_PIN  16
#define G2_PIN  27
#define B2_PIN  17

#define A_PIN   5
#define B_PIN   18
#define C_PIN   19
#define D_PIN   -1 // Connected to GND on panel (21 if exist)
#define E_PIN   -1 // Connected to GND on panel

#define LAT_PIN 26
#define OE_PIN  25
#define CLK_PIN 22

#include <Arduino.h>
#include <ESP32-HUB75-MatrixPanel-I2S-DMA.h>

MatrixPanel_I2S_DMA *dma_display = nullptr;

void testScreen() {

  for (int x=0; x <= 63; x++) {

    // Red 8 Rows
    dma_display->drawPixel(64+(x),0,dma_display->color565(255, 0, 0)); // ROW 1
    dma_display->drawPixel(64+(x),1,dma_display->color565(210, 0, 0)); // ROW 2
    dma_display->drawPixel(64+(x),2,dma_display->color565(180, 0, 0)); // ROW 3
    dma_display->drawPixel(64+(x),3,dma_display->color565(150, 0, 0)); // ROW 4
    dma_display->drawPixel(64+(x),4,dma_display->color565(125, 0, 0)); // ROW 5
    dma_display->drawPixel(64+(x),5,dma_display->color565(90, 0, 0)); // ROW 6
    dma_display->drawPixel(64+(x),6,dma_display->color565(60, 0, 0)); // ROW 7
    dma_display->drawPixel(64+(x),7,dma_display->color565(40, 0, 0)); // ROW 8

    // Blue 8 Rows
    dma_display->drawPixel(0+x,0,dma_display->color565(0, 0, 255)); // ROW 9
    dma_display->drawPixel(0+x,1,dma_display->color565(0, 0, 210)); // ROW 10
    dma_display->drawPixel(0+x,2,dma_display->color565(0, 0, 180)); // ROW 11
    dma_display->drawPixel(0+x,3,dma_display->color565(0, 0, 150)); // ROW 12
    dma_display->drawPixel(0+x,4,dma_display->color565(0, 0, 125)); // ROW 13
    dma_display->drawPixel(0+x,5,dma_display->color565(0, 0, 90)); // ROW 14
    dma_display->drawPixel(0+x,6,dma_display->color565(0, 0, 60)); // ROW 15
    dma_display->drawPixel(0+x,7,dma_display->color565(0, 0, 40)); // ROW 16

    // White 8 Rows
    dma_display->drawPixel(64+x,8,dma_display->color565(255, 255, 255)); // ROW 17
    dma_display->drawPixel(64+x,9,dma_display->color565(210, 210, 210)); // ROW 18
    dma_display->drawPixel(64+x,10,dma_display->color565(180, 180, 180)); // ROW 19
    dma_display->drawPixel(64+x,11,dma_display->color565(150, 150, 150)); // ROW 20
    dma_display->drawPixel(64+x,12,dma_display->color565(125, 125, 125)); // ROW 21
    dma_display->drawPixel(64+x,13,dma_display->color565(90, 90, 90)); // ROW 22
    dma_display->drawPixel(64+x,14,dma_display->color565(60, 60, 60)); // ROW 23
    dma_display->drawPixel(64+x,15,dma_display->color565(40, 40, 40)); // ROW 24

    // Green 8 Rows
    dma_display->drawPixel(0+x,8,dma_display->color565(0, 255, 0)); // ROW 25
    dma_display->drawPixel(0+x,9,dma_display->color565(0, 210, 0)); // ROW 26
    dma_display->drawPixel(0+x,10,dma_display->color565(0, 180, 0)); // ROW 27
    dma_display->drawPixel(0+x,11,dma_display->color565(0, 150, 0)); // ROW 28
    dma_display->drawPixel(0+x,12,dma_display->color565(0, 125, 0)); // ROW 29
    dma_display->drawPixel(0+x,13,dma_display->color565(0, 90, 0)); // ROW 30
    dma_display->drawPixel(0+x,14,dma_display->color565(0, 60, 0)); // ROW 31
    dma_display->drawPixel(0+x,15,dma_display->color565(0, 40, 0)); // ROW 32
  }
}

void setup() {

  Serial.begin(115200);
  delay(1000);

  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_WIDHT, PANEL_HEIGHT, CHAIN_LENGTH, _pins);

  mxconfig.double_buff = true; // ????
  mxconfig.i2sspeed = HUB75_I2S_CFG::HZ_20M;

  dma_display = new MatrixPanel_I2S_DMA(mxconfig);
  dma_display->begin();
  dma_display->setBrightness8(200); //0-255
  dma_display->clearScreen();
}

void loop() {
    //delay(40); 
    testScreen();
}

After researching in various Chinese retailers and factories, i found some more information on the panel:

Pixel Pitch: P4
Dimension: 128X256
Lamp bead: RGB
LED Type: SMD1921
Scanning Mode: 1/8

This code on your brand ?? patch-1 or legacy-1.2.4 ?? thanks

macduyhai commented 2 years ago

Thank you @mrfaptastic but I try example "One_Eighth_1_8_ScanPanel" and change GPIO define Link git : https://github.com/AlfioSaitta/ESP32-HUB75-MatrixPanel-I2S-DMA/tree/patch-1

` // 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 1 // Number of INDIVIDUAL PANELS per ROW

define PANEL_CHAIN NUM_ROWS*NUM_COLS // total number of panels chained one to another

// Change this to your needs, for details on VirtualPanel pls read the PDF!

define SERPENT true

define TOPDOWN false

// GPIO Configuration

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 35 // 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 33

include "OneEighthScanMatrixPanel.h" // Virtual Display to re-map co-ordinates such that they draw correctly on a32x16 1/4 Scan panel

// placeholder for the matrix object MatrixPanel_I2S_DMA *dma_display = nullptr;

// placeholder for the virtual display object OneEighthMatrixPanel *virtualDisp = nullptr;

/**

// virtualDisp->setTextColor(virtualDisp->color565(0, 0, 255)); // virtualDisp->setCursor(0, virtualDisp->height()/2);

// Red text inside red rect (2 pix in from edge)
virtualDisp->setCursor(0, 0); 
virtualDisp->print("  1234");

// virtualDisp->drawRect(1,1, virtualDisp->width()-2, virtualDisp->height()-2, virtualDisp->color565(255,0,0));

// White line from top left to bottom right

// virtualDisp->drawLine(0,0, virtualDisp->width()-1, virtualDisp->height()-1, virtualDisp->color565(255,255,255)); }

void loop() {

} // end loop`

--> There's something incorrect here ?????

image

mrcodetastic commented 2 years ago

Unfortunately the 1/8 Scan panel workaround was never completed. I do not have one of these panels either so I cannot test.

Can you try drawing a line from pixel 0,0 to 32,63 without the use of the virtualDisp library and tell me what it looks like?

donnersm commented 2 years ago

Unfortunately the 1/8 Scan panel workaround was never completed. I do not have one of these panels either so I cannot test.

Can you try drawing a line from pixel 0,0 to 32,63 without the use of the virtualDisp library and tell me what it looks like?

Since i have one of those panels and without working lib its useless to me.., might as well put a stamp on it and ship it to someone @mrfaptastic pm me if your interested

mrcodetastic commented 2 years ago

If you want i can send you various panels of different sizes and with different scan rates.

If you are happy to donate then I certainly won't say no. Mark is kindly sending a 1/8 which I can use to get those panels working properly (and that will help you as well with your 3 x 1/8 scan panel display).

Feel free to send what you think is of value to get supported and is most used. Can start continue expanding support in the library.

dickshaydle commented 2 years ago

I have a 64x32 RGB Panel that worked with a setting for 1/8 scan with another library so i guess it is an 1/8 scan display. image

I couldn't get it to run with current master branch of mrfaptastic but with the patch-1 branch of Alfio.

But there were a some errors in the displayed image. image

After a lot of trial and error i found some changes to the OneEighthScanMatrixPanel.h image

if(   ( _s_chain_party && !_chain_top_down && (row % 2 == 0) )  // serpentine vertically stacked chain starting from bottom row (i.e. ESP closest to ground), upwards
      ||
      ( _s_chain_party && _chain_top_down  && (row % 2 != 0) )  // serpentine vertically stacked chain starting from the sky downwards
)
{
  // First portion gets you to the correct offset for the row you need
  // Second portion inverts the x on the row
    coords.x = ((y / panelResY) * (virtualResX)) + (virtualResX - x) - 1;

  // inverts the y the row
  coords.y = panelResY - 1 - (y % panelResY);  
} 
else 
{
// Normal chain pixel co-ordinate
  coords.x = x + ((y / panelResY) * (virtualResX)) +1 ;
  coords.y = y % panelResY;
}

/* *******
* START: 1/8 Scan Panel Pixel Re-Mapping
*
* We have calculated the x, y co-ordinates as if we have a chain of standard panels this library is designed 
* for, this being 1/8 or 1/16 scan panels. We have to do some further hacking to convert co-ords to the 
* double length and 1/2 physical dma output length that is required for these panels to work electronically.
*/

 if ( (coords.y /8) % 4 == 0) { // 1st 8 rows
    coords.x += 64;
 }
 if ( (coords.y /8) % 4 == 1) { // 2nd 8 rows
    coords.y -= 8;
 }

 if ( (coords.y /8) % 4 == 2) { // returns true/1 for the 1st and 3rd 8-pixel 1/4th of a 32px high panel
    coords.x += 64;
    coords.y -= 8;
 }

 if ( (coords.y /8) % 4 == 3) { // returns true/1 for the 1st and 3rd 8-pixel 1/4th of a 32px high panel
    coords.y -= 16;
 }

/* 
 * END: 1/8 Scan Panel Pixel Re-Mapping
 * *******
 */

Any ideas why it behaves this way?

What is needed to make this run with the aurora demo or with displaying images? The aurora demos looks like it has double 8row blocks. The blocks are not equal but look very similar,

mrcodetastic commented 2 years ago

Hi @dickshaydle. I am working on a fix for 1/8 scan panels as @donnersm has kindly provided me a 1/8 scan panel to test with.

I hope to have something that works with chaining as well, soon.