Integrate 1/8 Scan Panel logic into VirtualMatrixPanel class

This commit is contained in:
mrfaptastic 2021-12-20 21:35:16 +00:00
parent 239de3a5eb
commit 229b0d874c
3 changed files with 79 additions and 93 deletions

View file

@ -34,6 +34,7 @@ struct VirtualCoords {
};
enum PANEL_SCAN_RATE {NORMAL_ONE_SIXTEEN, ONE_EIGHT};
#ifdef USE_GFX_ROOT
class VirtualMatrixPanel : public GFX
@ -108,6 +109,8 @@ class VirtualMatrixPanel
void drawDisplayTest();
void setRotate(bool rotate);
void setPhysicalPanelScanRate(PANEL_SCAN_RATE rate);
protected:
virtual VirtualCoords getCoords(int16_t &x, int16_t &y);
@ -117,6 +120,8 @@ class VirtualMatrixPanel
bool _chain_top_down = false; // is the ESP at the top or bottom of the matrix of devices?
bool _rotate = false;
PANEL_SCAN_RATE _panelScanRate = NORMAL_ONE_SIXTEEN;
}; // end Class header
/**
@ -180,6 +185,47 @@ inline VirtualCoords VirtualMatrixPanel::getCoords(int16_t &x, int16_t &y) {
coords.y = (panelResY-1) - coords.y;
}
/* START: Pixel remapping AGAIN to convert 1/16 SCAN output that the
* the underlying hardware library is designed for (because
* there's only 2 x RGB pins... and convert this to 1/8 or something
*/
if ( _panelScanRate == ONE_EIGHT)
{
/* 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 One_Eight_1_8_ScanPanel code and you'll see that the DMA buffer is setup
as if the panel is 2 * W and 0.5 * H !
*/
/*
Serial.print("VirtualMatrixPanel Mapping ("); Serial.print(x, DEC); Serial.print(","); Serial.print(y, DEC); Serial.print(") ");
// to
Serial.print("to ("); Serial.print(coords.x, DEC); Serial.print(","); Serial.print(coords.y, DEC); Serial.println(") ");
*/
if ( (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 = (y >> 4)*8 + (y & 0b00000111);
/*
Serial.print("OneEightScanPanel Mapping ("); Serial.print(x, DEC); Serial.print(","); Serial.print(y, DEC); Serial.print(") ");
// to
Serial.print("to ("); Serial.print(coords.x, DEC); Serial.print(","); Serial.print(coords.y, DEC); Serial.println(") ");
*/
}
//Serial.print("Mapping to x: "); Serial.print(coords.x, DEC); Serial.print(", y: "); Serial.println(coords.y, DEC);
return coords;
}
@ -205,6 +251,11 @@ inline void VirtualMatrixPanel::setRotate(bool rotate) {
if (rotate) { setRotation(1); } else { setRotation(0); }
}
inline void VirtualMatrixPanel::setPhysicalPanelScanRate(PANEL_SCAN_RATE rate) {
_panelScanRate=rate;
}
#ifndef NO_GFX
inline void VirtualMatrixPanel::drawDisplayTest()

View file

@ -1,69 +0,0 @@
#ifndef _ESP32_ONE_EIGHT_SCAN_PANEL
#define _ESP32_ONE_EIGHT_SCAN_PANEL
#include <ESP32-VirtualMatrixPanel-I2S-DMA.h>
/* This class inherits all the goodness of the VirtualMatrixPanel class used to created
large displays of chained panels, but does trickery to convert from 1/16 to 1/8
DMA output.
Some guidance given by looking at hzeller's code, in relation to the 'stretch factor'
concept where these panels are really double width and half the height, from the perspective
of the digital input required to get the 'real world' resolution and output.
https://github.com/hzeller/rpi-rgb-led-matrix/blob/master/lib/multiplex-mappers.cc
*/
class OneEightScanPanel : public VirtualMatrixPanel
{
public:
using VirtualMatrixPanel::VirtualMatrixPanel; // inherit VirtualMatrixPanel's constructor(s)
protected:
/* 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 One_Eight_1_8_ScanPanel code and you'll see that the DMA buffer is setup
as if the panel is 2 * W and 0.5 * H !
*/
VirtualCoords getCoords(int16_t &x, int16_t &y);
}; // end class header note the ;
inline VirtualCoords OneEightScanPanel::getCoords(int16_t &x, int16_t &y) {
VirtualMatrixPanel::getCoords(x, y); // call to base 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;
}
/*
Serial.print("VirtualMatrixPanel Mapping ("); Serial.print(x, DEC); Serial.print(","); Serial.print(y, DEC); Serial.print(") ");
// to
Serial.print("to ("); Serial.print(coords.x, DEC); Serial.print(","); Serial.print(coords.y, DEC); Serial.println(") ");
*/
if ( (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 = (y >> 4)*8 + (y & 0b00000111);
/*
Serial.print("OneEightScanPanel Mapping ("); Serial.print(x, DEC); Serial.print(","); Serial.print(y, DEC); Serial.print(") ");
// to
Serial.print("to ("); Serial.print(coords.x, DEC); Serial.print(","); Serial.print(coords.y, DEC); Serial.println(") ");
*/
return coords;
}
#endif

View file

@ -15,8 +15,10 @@
**************************************************************************/
#include "ESP32-HUB75-MatrixPanel-I2S-DMA.h"
// Virtual Display to re-map co-ordinates such that they draw correctly on a 32x16 1/4 Scan panel
#include "1_8_ScanPanel.h"
/* Use the Virtual Display class to re-map co-ordinates such that they draw
* correctly on a 32x16 1/8 Scan panel (or chain of such panels).
*/
#include "ESP32-VirtualMatrixPanel-I2S-DMA.h"
// Panel configuration
@ -37,7 +39,7 @@
MatrixPanel_I2S_DMA *dma_display = nullptr;
// placeholder for the virtual display object
OneEightScanPanel *OneEightMatrixDisplay = nullptr;
VirtualMatrixPanel *OneEightMatrixDisplay = nullptr;
/******************************************************************************
* Setup!
@ -87,8 +89,10 @@
delay(500);
// create OneEightMatrixDisplaylay object based on our newly created dma_display object
OneEightMatrixDisplay = new OneEightScanPanel((*dma_display), NUM_ROWS, NUM_COLS, PANEL_RES_X, PANEL_RES_Y, SERPENT, TOPDOWN);
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);
}