diff options
| author | mrfaptastic <12006953+mrfaptastic@users.noreply.github.com> | 2021-11-22 07:43:07 +0000 |
|---|---|---|
| committer | mrfaptastic <12006953+mrfaptastic@users.noreply.github.com> | 2021-11-22 07:43:07 +0000 |
| commit | b810dca9d18c7074adbe9a088c97b5e0e2a0649e (patch) | |
| tree | d4ad137ccbfd566a5120ddf0b578dd0016561c1a /examples/One_Eight_1_8_ScanPanel | |
| parent | d952839a0dabb525ff4f0a91ead1eef48810a7f4 (diff) | |
1/8 Scan Panel Example
#154 #204
Also supports chaining.
Diffstat (limited to 'examples/One_Eight_1_8_ScanPanel')
| -rw-r--r-- | examples/One_Eight_1_8_ScanPanel/1_8_ScanPanel.h | 69 | ||||
| -rw-r--r-- | examples/One_Eight_1_8_ScanPanel/One_Eight_1_8_ScanPanel.ino | 147 | ||||
| -rw-r--r-- | examples/One_Eight_1_8_ScanPanel/README.md | 13 |
3 files changed, 229 insertions, 0 deletions
diff --git a/examples/One_Eight_1_8_ScanPanel/1_8_ScanPanel.h b/examples/One_Eight_1_8_ScanPanel/1_8_ScanPanel.h new file mode 100644 index 0000000..238b5a6 --- /dev/null +++ b/examples/One_Eight_1_8_ScanPanel/1_8_ScanPanel.h @@ -0,0 +1,69 @@ +#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 diff --git a/examples/One_Eight_1_8_ScanPanel/One_Eight_1_8_ScanPanel.ino b/examples/One_Eight_1_8_ScanPanel/One_Eight_1_8_ScanPanel.ino new file mode 100644 index 0000000..65050aa --- /dev/null +++ b/examples/One_Eight_1_8_ScanPanel/One_Eight_1_8_ScanPanel.ino @@ -0,0 +1,147 @@ +/************************************************************************* + * Description: + * + * The underlying implementation of the ESP32-HUB75-MatrixPanel-I2S-DMA only + * supports output to 1/16 or 1/32 scan panels - which means outputting + * two lines at the same time, 16 or 32 rows apart. This cannot be changed + * at the DMA layer as it would require a messy and complex rebuild of the + * library's DMA internals. + * + * However, it is possible to connect 1/8 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. + * + **************************************************************************/ +#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" + + + // 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 + OneEightScanPanel *OneEightMatrixDisplay = nullptr; + + /****************************************************************************** + * Setup! + ******************************************************************************/ + void setup() + { + delay(250); + + Serial.begin(115200); + Serial.println(""); Serial.println(""); Serial.println(""); + Serial.println("*****************************************************"); + Serial.println("* 1/8 Scan Panel Demonstration *"); + Serial.println("*****************************************************"); + +/* + // 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 OneEightScanPanel((*dma_display), NUM_ROWS, NUM_COLS, PANEL_RES_X, PANEL_RES_Y, SERPENT, TOPDOWN); + + } + + + void loop() { + + // What the panel sees from the DMA engine! + for (int i=PANEL_RES_X*2+10; i< PANEL_RES_X*(NUM_ROWS*NUM_COLS)*2; i++) + { + dma_display->drawLine(i, 0, i, 7, dma_display->color565(255, 0, 0)); // red + delay(10); + } + + dma_display->clearScreen(); + delay(1000); +/* + // Try again using the pixel / dma memory remapper + for (int i=PANEL_RES_X+5; i< (PANEL_RES_X*2)-1; i++) + { + OneEightMatrixDisplay->drawLine(i, 0, i, 7, dma_display->color565(0, 0, 255)); // blue + delay(10); + } +*/ + + // Try again using the pixel / dma memory remapper + int offset = PANEL_RES_X*((NUM_ROWS*NUM_COLS)-1); + for (int i=0; i< PANEL_RES_X; i++) + { + OneEightMatrixDisplay->drawLine(i+offset, 0, i+offset, 7, dma_display->color565(0, 0, 255)); // blue + OneEightMatrixDisplay->drawLine(i+offset, 8, i+offset, 15, dma_display->color565(0, 128,0)); // g + OneEightMatrixDisplay->drawLine(i+offset, 16, i+offset, 23, dma_display->color565(128, 0,0)); // red + OneEightMatrixDisplay->drawLine(i+offset, 24, i+offset, 31, dma_display->color565(0, 128, 128)); // blue + delay(10); + } + + delay(1000); + + + // Print on each chained panel 1/8 module! + // This only really works for a single horizontal chain + for (int i = 0; i < NUM_ROWS*NUM_COLS; i++) + { + OneEightMatrixDisplay->setTextColor(OneEightMatrixDisplay->color565(255, 255, 255)); + OneEightMatrixDisplay->setCursor(i*PANEL_RES_X+7, OneEightMatrixDisplay->height()/3); + + // Red text inside red rect (2 pix in from edge) + OneEightMatrixDisplay->print("Panel " + String(i+1)); + OneEightMatrixDisplay->drawRect(1,1, OneEightMatrixDisplay->width()-2, OneEightMatrixDisplay->height()-2, OneEightMatrixDisplay->color565(255,0,0)); + + // White line from top left to bottom right + OneEightMatrixDisplay->drawLine(0,0, OneEightMatrixDisplay->width()-1, OneEightMatrixDisplay->height()-1, OneEightMatrixDisplay->color565(255,255,255)); + } + + delay(2000); + dma_display->clearScreen(); + + } // end loop diff --git a/examples/One_Eight_1_8_ScanPanel/README.md b/examples/One_Eight_1_8_ScanPanel/README.md new file mode 100644 index 0000000..4147bcb --- /dev/null +++ b/examples/One_Eight_1_8_ScanPanel/README.md @@ -0,0 +1,13 @@ +# Using this library with 32x16 1/8 Scan Panels + +## Problem +ESP32-HUB75-MatrixPanel-I2S-DMA library will not display output correctly with 1/8 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 ESP32-HUB75-MatrixPanel-I2S-DMA library (in this example, it is the 'dmaOutput' class). + +Creation of a 'OneEighthScanMatrixPanel.h' class which sends an adjusted drawPixel() x,y co-ordinates to the underlying ESP32-HUB75-MatrixPanel-I2S-DMA library's drawPixel routine, to trick the output to look pixel perfect. + +Refer to the '1_8_ScanPanel.h' logic which builds upon the library's core 'Virtual Display' (ESP32-VirtualMatrixPanel-I2S-DMA.h) to also support chaining of 1/8 Scan Panels. Refer to 'ChainedPanels' example on how to configure panel chaining to create bigger displays. + + |
