Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Pixel_Mapping_Test example. #739

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions examples/Four_Scan_Panel/README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# Using this library with 32x16 1/8 Scan Panels
# Using this library with 32x16 1/4 Scan Panels

## Problem
ESP32-HUB75-MatrixPanel-I2S-DMA library will not display output correctly with 'Four Scan' or 1/8 scan panels such [as this](https://github.com/mrfaptastic/ESP32-HUB75-MatrixPanel-I2S-DMA/issues/154) by default.
ESP32-HUB75-MatrixPanel-I2S-DMA library will not display output correctly with 'Four Scan' 64x32 1/8 or 32x16 1/4 scan panels such [as this](https://github.com/mrfaptastic/ESP32-HUB75-MatrixPanel-I2S-DMA/issues/154) by default.

## Solution
It is possible to connect 1/8 scan panels to this library and 'trick' the output to work correctly on these panels by way of adjusting the pixel co-ordinates that are 'sent' to the underlying ESP32-HUB75-MatrixPanel-I2S-DMA library (in this example, it is the 'dmaOutput' class).
143 changes: 143 additions & 0 deletions examples/Pixel_Mapping_Test/Pixel_Mapping_Test.ino
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
/*************************************************************************
Description:

The underlying implementation of the ESP32-HUB75-MatrixPanel-I2S-DMA only
supports output to HALF scan panels - which means outputting
two lines at the same time, 16 or 32 rows apart if a 32px or 64px high panel
respectively.
This cannot be changed at the DMA layer as it would require a messy and complex
rebuild of the library's internals.

However, it is possible to connect QUARTER (i.e. FOUR lines updated in parallel)
scan panels to this same library and
'trick' the output to work correctly on these panels by way of adjusting the
pixel co-ordinates that are 'sent' to the ESP32-HUB75-MatrixPanel-I2S-DMA
library.

**************************************************************************/

/* Use the Virtual Display class to re-map co-ordinates such that they draw
correctly on a 32x16 1/4 or 64x32 1/8 Scan panel (or chain of such panels).
*/
#include "ESP32-VirtualMatrixPanel-I2S-DMA.h"

// Define custom class derived from VirtualMatrixPanel
class CustomPxBasePanel : public VirtualMatrixPanel
{
public:
using VirtualMatrixPanel::VirtualMatrixPanel; // inherit VirtualMatrixPanel's constructor(s)

protected:

VirtualCoords getCoords(int16_t x, int16_t y); // custom getCoords() method for specific pixel mapping

};

// custom getCoords() method for specific pixel mapping
inline VirtualCoords CustomPxBasePanel ::getCoords(int16_t x, int16_t y) {

coords = VirtualMatrixPanel::getCoords(x, y); // call base class method to update coords for chaining approach

if ( coords.x == -1 || coords.y == -1 ) { // Co-ordinates go from 0 to X-1 remember! width() and height() are out of range!
return coords;
}

uint8_t pxbase = panelResX; // pixel base
// mapper for panels with 32 pixs height (64x32 or 32x32)
if (panelResY == 32)
{
if ((coords.y & 8) == 0)
{
coords.x += ((coords.x / pxbase) + 1) * pxbase; // 1st, 3rd 'block' of 8 rows of pixels
}
else
{
coords.x += (coords.x / pxbase) * pxbase; // 2nd, 4th 'block' of 8 rows of pixels
}
coords.y = (coords.y >> 4) * 8 + (coords.y & 0b00000111);
}

// mapper for panels with 16 pixs height (32x16 1/4)
else if (panelResY == 16)
{
if ((coords.y & 4) == 0)
{
// 1. Normal line, from left to right
coords.x += ((coords.x / pxbase) + 1) * pxbase; // 1st, 3rd 'block' of 4 rows of pixels
//2. in case the line filled from right to left, use this (and comment 1st)
//coords.x = ((coords.x / pxbase) + 1) * 2 * pxbase - (coords.x % pxbase) - 1;
}
else
{
coords.x += (coords.x / pxbase) * pxbase; // 2nd, 4th 'block' of 4 rows of pixels
}
coords.y = (coords.y >> 3) * 4 + (coords.y & 0b00000011);
}
return coords;
}

// Panel configuration
#define PANEL_RES_X 32 // Number of pixels wide of each INDIVIDUAL panel module.
#define PANEL_RES_Y 16 // Number of pixels tall of each INDIVIDUAL panel module.

// Use a single panel for tests
#define NUM_ROWS 1 // Number of rows of chained INDIVIDUAL PANELS
#define NUM_COLS 1 // Number of INDIVIDUAL PANELS per ROW

// Chain settings, do not cnahge
#define SERPENT true
#define TOPDOWN false
#define VIRTUAL_MATRIX_CHAIN_TYPE CHAIN_BOTTOM_RIGHT_UP

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

// placeholder for the virtual display object
CustomPxBasePanel *FourScanPanel = nullptr;

/******************************************************************************
Setup!
******************************************************************************/
void setup()
{
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.

// 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(40); // 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 FourScanPanellay object based on our newly created dma_display object
FourScanPanel = new CustomPxBasePanel ((*dma_display), NUM_ROWS, NUM_COLS, PANEL_RES_X, PANEL_RES_Y, VIRTUAL_MATRIX_CHAIN_TYPE);

}


void loop() {
for (int i = 0; i < FourScanPanel->height(); i++)
{
for (int j = 0; j < FourScanPanel->width(); j++)
{
FourScanPanel->drawPixel(j, i, FourScanPanel->color565(255, 0, 0));
delay(30);
}
}
delay(2000);
dma_display->clearScreen();
} // end loop
17 changes: 17 additions & 0 deletions examples/Pixel_Mapping_Test/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
## Four Scan Panel pixel mapping test and tune
This example is to help you set up pixel coordinate mapping on most common cases of Four_Scan_Panels such as 64x32 1/8 or 32x16 1/4. Please follow the steps below in sequence.

### 1. Run this code on a single panel
If the panel lines are filled sequentially, from left to right and from top to bottom, then you don't need to change the setting.

### 2. If your panel filling in parts
Most often, the panel rows are filled in small segments, 4, 8 or 16 pixels (there are other values). This number is the pixel base of the panel. Substitute it into line 45 of the example and run the code again.

### 3. Wrong order of rows
At this point, your panel should already be filled with whole rows. If the top row is not the first to be filled, swap the expressions, marked in the comments as "1st, 3rd 'block' of rows" with "2nd, 4th 'block' of rows" one.

### 4. Wrong filling direction
If any block of rows is filled from right to left, change the formula according to the example shown in the lines 65-68 of the code.

### Conclusion
If your panel works correctly now - congratulations. But if not - it's okay. There are many types of different panels and it is impossible to foresee all the nuances. Create an issue and you will be helped!
Loading