Update ESP32-VirtualMatrixPanel-I2S-DMA.h

This commit is contained in:
mrfaptastic 2023-03-18 11:36:37 +00:00
parent 264d997618
commit 7d1841e355

View file

@ -10,16 +10,16 @@
However, the function of this class has expanded now to also manage However, the function of this class has expanded now to also manage
the output for the output for
1) TWO scan panels = Two rows updated in parallel. 1) TWO scan panels = Two rows updated in parallel.
* 64px high panel = sometimes referred to as 1/32 scan * 64px high panel = sometimes referred to as 1/32 scan
* 32px high panel = sometimes referred to as 1/16 scan * 32px high panel = sometimes referred to as 1/16 scan
* 16px high panel = sometimes referred to as 1/8 scan * 16px high panel = sometimes referred to as 1/8 scan
2) FOUR scan panels = Four rows updated in parallel 2) FOUR scan panels = Four rows updated in parallel
* 32px high panel = sometimes referred to as 1/8 scan * 32px high panel = sometimes referred to as 1/8 scan
* 16px high panel = sometimes referred to as 1/4 scan * 16px high panel = sometimes referred to as 1/4 scan
YouTube: https://www.youtube.com/brianlough YouTube: https://www.youtube.com/brianlough
Tindie: https://www.tindie.com/stores/brianlough/ Tindie: https://www.tindie.com/stores/brianlough/
Twitter: https://twitter.com/witnessmenow Twitter: https://twitter.com/witnessmenow
@ -30,37 +30,39 @@
#include <Fonts/FreeSansBold12pt7b.h> #include <Fonts/FreeSansBold12pt7b.h>
#endif #endif
//#include <iostream> // #include <iostream>
struct VirtualCoords struct VirtualCoords
{ {
int16_t x; int16_t x;
int16_t y; int16_t y;
int16_t virt_row; // chain of panels row int16_t virt_row; // chain of panels row
int16_t virt_col; // chain of panels col int16_t virt_col; // chain of panels col
VirtualCoords() : x(0), y(0) VirtualCoords() : x(0), y(0)
{ {
} }
}; };
enum PANEL_SCAN_RATE enum PANEL_SCAN_RATE
{ {
NORMAL_TWO_SCAN, NORMAL_ONE_SIXTEEN, // treated as the same NORMAL_TWO_SCAN,
FOUR_SCAN_32PX_HIGH, NORMAL_ONE_SIXTEEN, // treated as the same
FOUR_SCAN_16PX_HIGH FOUR_SCAN_32PX_HIGH,
FOUR_SCAN_16PX_HIGH
}; };
// Chaining approach... From the perspective of the DISPLAY / LED side of the chain of panels. // Chaining approach... From the perspective of the DISPLAY / LED side of the chain of panels.
enum PANEL_CHAIN_TYPE enum PANEL_CHAIN_TYPE
{ {
CHAIN_TOP_LEFT_DOWN, CHAIN_NONE,
CHAIN_TOP_RIGHT_DOWN, CHAIN_TOP_LEFT_DOWN,
CHAIN_BOTTOM_LEFT_UP, CHAIN_TOP_RIGHT_DOWN,
CHAIN_BOTTOM_RIGHT_UP, CHAIN_BOTTOM_LEFT_UP,
CHAIN_TOP_LEFT_DOWN_ZZ, /// ZigZag chaining. Might need a big ass cable to do this, all panels right way up. CHAIN_BOTTOM_RIGHT_UP,
CHAIN_TOP_RIGHT_DOWN_ZZ, CHAIN_TOP_LEFT_DOWN_ZZ, /// ZigZag chaining. Might need a big ass cable to do this, all panels right way up.
CHAIN_BOTTOM_RIGHT_UP_ZZ, CHAIN_TOP_RIGHT_DOWN_ZZ,
CHAIN_BOTTOM_RIGHT_UP_ZZ,
CHAIN_BOTTOM_LEFT_UP_ZZ CHAIN_BOTTOM_LEFT_UP_ZZ
}; };
@ -74,84 +76,86 @@ class VirtualMatrixPanel
{ {
public: public:
VirtualMatrixPanel(MatrixPanel_I2S_DMA &disp, int _vmodule_rows, int _vmodule_cols, int _panelResX, int _panelResY, PANEL_CHAIN_TYPE _panel_chain_type = CHAIN_NONE)
VirtualMatrixPanel(MatrixPanel_I2S_DMA &disp, int _vmodule_rows, int _vmodule_cols, int _panelResX, int _panelResY, PANEL_CHAIN_TYPE _panel_chain_type = CHAIN_TOP_RIGHT_DOWN)
#ifdef USE_GFX_ROOT #ifdef USE_GFX_ROOT
: GFX(_vmodule_cols * _panelResX, _vmodule_rows * _panelResY) : GFX(_vmodule_cols * _panelResX, _vmodule_rows * _panelResY)
#elif !defined NO_GFX #elif !defined NO_GFX
: Adafruit_GFX(_vmodule_cols * _panelResX, _vmodule_rows * _panelResY) : Adafruit_GFX(_vmodule_cols * _panelResX, _vmodule_rows * _panelResY)
#endif #endif
{ {
this->display = &disp; this->display = &disp;
panel_chain_type = _panel_chain_type; panel_chain_type = _panel_chain_type;
panelResX = _panelResX; panelResX = _panelResX;
panelResY = _panelResY; panelResY = _panelResY;
vmodule_rows = _vmodule_rows; vmodule_rows = _vmodule_rows;
vmodule_cols = _vmodule_cols; vmodule_cols = _vmodule_cols;
virtualResX = vmodule_cols * _panelResX; virtualResX = vmodule_cols * _panelResX;
virtualResY = vmodule_rows * _panelResY; virtualResY = vmodule_rows * _panelResY;
dmaResX = panelResX * vmodule_rows * vmodule_cols - 1; dmaResX = panelResX * vmodule_rows * vmodule_cols - 1;
/* Virtual Display width() and height() will return a real-world value. For example: /* Virtual Display width() and height() will return a real-world value. For example:
* Virtual Display width: 128 * Virtual Display width: 128
* Virtual Display height: 64 * Virtual Display height: 64
* *
* So, not values that at 0 to X-1 * So, not values that at 0 to X-1
*/ */
coords.x = coords.y = -1; // By default use an invalid co-ordinates that will be rejected by updateMatrixDMABuffer coords.x = coords.y = -1; // By default use an invalid co-ordinates that will be rejected by updateMatrixDMABuffer
} }
// equivalent methods of the matrix library so it can be just swapped out. // equivalent methods of the matrix library so it can be just swapped out.
virtual void drawPixel(int16_t x, int16_t y, uint16_t color); virtual void drawPixel(int16_t x, int16_t y, uint16_t color);
virtual void fillScreen(uint16_t color); // overwrite adafruit implementation virtual void fillScreen(uint16_t color); // overwrite adafruit implementation
virtual void fillScreenRGB888(uint8_t r, uint8_t g, uint8_t b); virtual void fillScreenRGB888(uint8_t r, uint8_t g, uint8_t b);
void clearScreen() { display->clearScreen(); } void clearScreen() { display->clearScreen(); }
void drawPixelRGB888(int16_t x, int16_t y, uint8_t r, uint8_t g, uint8_t b); void drawPixelRGB888(int16_t x, int16_t y, uint8_t r, uint8_t g, uint8_t b);
#ifdef USE_GFX_ROOT #ifdef USE_GFX_ROOT
// 24bpp FASTLED CRGB colour struct support // 24bpp FASTLED CRGB colour struct support
void fillScreen(CRGB color); void fillScreen(CRGB color);
void drawPixel(int16_t x, int16_t y, CRGB color); void drawPixel(int16_t x, int16_t y, CRGB color);
#endif #endif
uint16_t color444(uint8_t r, uint8_t g, uint8_t b) { return display->color444(r, g, b); } uint16_t color444(uint8_t r, uint8_t g, uint8_t b)
uint16_t color565(uint8_t r, uint8_t g, uint8_t b) { return display->color565(r, g, b); } {
uint16_t color333(uint8_t r, uint8_t g, uint8_t b) { return display->color333(r, g, b); } return display->color444(r, g, b);
}
uint16_t color565(uint8_t r, uint8_t g, uint8_t b) { return display->color565(r, g, b); }
uint16_t color333(uint8_t r, uint8_t g, uint8_t b) { return display->color333(r, g, b); }
void flipDMABuffer() { display->flipDMABuffer(); } void flipDMABuffer() { display->flipDMABuffer(); }
void drawDisplayTest(); void drawDisplayTest();
void setRotate(bool rotate); void setRotate(bool rotate);
void setPhysicalPanelScanRate(PANEL_SCAN_RATE rate); void setPhysicalPanelScanRate(PANEL_SCAN_RATE rate);
private: private:
MatrixPanel_I2S_DMA *display; MatrixPanel_I2S_DMA *display;
PANEL_CHAIN_TYPE panel_chain_type; PANEL_CHAIN_TYPE panel_chain_type;
PANEL_SCAN_RATE panel_scan_rate = NORMAL_TWO_SCAN; PANEL_SCAN_RATE panel_scan_rate = NORMAL_TWO_SCAN;
virtual VirtualCoords getCoords(int16_t &x, int16_t &y); virtual VirtualCoords getCoords(int16_t &x, int16_t &y);
VirtualCoords coords; VirtualCoords coords;
int16_t virtualResX; int16_t virtualResX;
int16_t virtualResY; int16_t virtualResY;
int16_t vmodule_rows; int16_t vmodule_rows;
int16_t vmodule_cols; int16_t vmodule_cols;
int16_t panelResX; int16_t panelResX;
int16_t panelResY; int16_t panelResY;
int16_t dmaResX; // The width of the chain in pixels (as the DMA engine sees it) int16_t dmaResX; // The width of the chain in pixels (as the DMA engine sees it)
bool _rotate = false; bool _rotate = false;
}; // end Class header }; // end Class header
@ -162,11 +166,11 @@ private:
*/ */
inline VirtualCoords VirtualMatrixPanel::getCoords(int16_t &virt_x, int16_t &virt_y) inline VirtualCoords VirtualMatrixPanel::getCoords(int16_t &virt_x, int16_t &virt_y)
{ {
if (virt_x < 0 || virt_x >= virtualResX || virt_y < 0 || virt_y >= virtualResY) if (virt_x < 0 || virt_x >= virtualResX || virt_y < 0 || virt_y >= virtualResY)
{ // Co-ordinates go from 0 to X-1 remember! otherwise they are out of range! { // Co-ordinates go from 0 to X-1 remember! otherwise they are out of range!
coords.x = coords.y = -1; // By defalt use an invalid co-ordinates that will be rejected by updateMatrixDMABuffer coords.x = coords.y = -1; // By defalt use an invalid co-ordinates that will be rejected by updateMatrixDMABuffer
return coords; return coords;
} }
// Do we want to rotate? // Do we want to rotate?
if (_rotate) if (_rotate)
@ -176,272 +180,266 @@ inline VirtualCoords VirtualMatrixPanel::getCoords(int16_t &virt_x, int16_t &vir
virt_y = virtualResY - 1 - temp_x; virt_y = virtualResY - 1 - temp_x;
} }
int row = (virt_y / panelResY); // 0 indexed int row = (virt_y / panelResY); // 0 indexed
switch(panel_chain_type) switch (panel_chain_type)
{ {
case (CHAIN_TOP_RIGHT_DOWN): case (CHAIN_TOP_RIGHT_DOWN):
{ {
if ( (row % 2) == 1 ) if ((row % 2) == 1)
{ // upside down panel { // upside down panel
//Serial.printf("Condition 1, row %d ", row); // Serial.printf("Condition 1, row %d ", row);
// reversed for the row // reversed for the row
coords.x = dmaResX - virt_x - (row*virtualResX); coords.x = dmaResX - virt_x - (row * virtualResX);
// y co-ord inverted within the panel // y co-ord inverted within the panel
coords.y = panelResY - 1 - (virt_y % panelResY); coords.y = panelResY - 1 - (virt_y % panelResY);
} }
else else
{ {
//Serial.printf("Condition 2, row %d ", row); // Serial.printf("Condition 2, row %d ", row);
coords.x = ((vmodule_rows - (row+1))*virtualResX)+virt_x; coords.x = ((vmodule_rows - (row + 1)) * virtualResX) + virt_x;
coords.y = virt_y % panelResY; coords.y = virt_y % panelResY;
} }
}
}
break;
case (CHAIN_TOP_RIGHT_DOWN_ZZ):
{
// Right side up. Starting from top right all the way down.
// Connected in a Zig Zag manner = some long ass cables being used potentially
//Serial.printf("Condition 2, row %d ", row);
coords.x = ((vmodule_rows - (row+1))*virtualResX)+virt_x;
coords.y = virt_y % panelResY;
}
break; break;
case (CHAIN_TOP_LEFT_DOWN): // OK -> modulus opposite of CHAIN_TOP_RIGHT_DOWN case (CHAIN_TOP_RIGHT_DOWN_ZZ):
{ {
if ( (row % 2) == 0 ) // Right side up. Starting from top right all the way down.
{ // reversed panel // Connected in a Zig Zag manner = some long ass cables being used potentially
//Serial.printf("Condition 1, row %d ", row); // Serial.printf("Condition 2, row %d ", row);
coords.x = dmaResX - virt_x - (row*virtualResX); coords.x = ((vmodule_rows - (row + 1)) * virtualResX) + virt_x;
coords.y = virt_y % panelResY;
}
break;
// y co-ord inverted within the panel case (CHAIN_TOP_LEFT_DOWN): // OK -> modulus opposite of CHAIN_TOP_RIGHT_DOWN
coords.y = panelResY - 1 - (virt_y % panelResY); {
} if ((row % 2) == 0)
else { // reversed panel
{
//Serial.printf("Condition 2, row %d ", row); // Serial.printf("Condition 1, row %d ", row);
coords.x = ((vmodule_rows - (row+1))*virtualResX)+virt_x; coords.x = dmaResX - virt_x - (row * virtualResX);
coords.y = virt_y % panelResY;
} // y co-ord inverted within the panel
} coords.y = panelResY - 1 - (virt_y % panelResY);
break; }
else
{
// Serial.printf("Condition 2, row %d ", row);
coords.x = ((vmodule_rows - (row + 1)) * virtualResX) + virt_x;
coords.y = virt_y % panelResY;
}
}
break;
case (CHAIN_TOP_LEFT_DOWN_ZZ): case (CHAIN_TOP_LEFT_DOWN_ZZ):
{ {
//Serial.printf("Condition 2, row %d ", row); // Serial.printf("Condition 2, row %d ", row);
coords.x = ((vmodule_rows - (row+1))*virtualResX)+virt_x; coords.x = ((vmodule_rows - (row + 1)) * virtualResX) + virt_x;
coords.y = virt_y % panelResY; coords.y = virt_y % panelResY;
} }
break; break;
case (CHAIN_BOTTOM_LEFT_UP): //
case (CHAIN_BOTTOM_LEFT_UP): // {
{
row = vmodule_rows - row - 1; row = vmodule_rows - row - 1;
if ( (row % 2) == 1 ) if ((row % 2) == 1)
{ {
// Serial.printf("Condition 1, row %d ", row); // Serial.printf("Condition 1, row %d ", row);
coords.x = ((vmodule_rows - (row+1))*virtualResX)+virt_x; coords.x = ((vmodule_rows - (row + 1)) * virtualResX) + virt_x;
coords.y = virt_y % panelResY; coords.y = virt_y % panelResY;
} }
else else
{ // inverted panel { // inverted panel
// Serial.printf("Condition 2, row %d ", row); // Serial.printf("Condition 2, row %d ", row);
coords.x = dmaResX - (row*virtualResX) - virt_x; coords.x = dmaResX - (row * virtualResX) - virt_x;
coords.y = panelResY - 1 - (virt_y % panelResY); coords.y = panelResY - 1 - (virt_y % panelResY);
} }
}
} break;
break;
case (CHAIN_BOTTOM_LEFT_UP_ZZ): // case (CHAIN_BOTTOM_LEFT_UP_ZZ): //
{ {
row = vmodule_rows - row - 1; row = vmodule_rows - row - 1;
// Serial.printf("Condition 1, row %d ", row); // Serial.printf("Condition 1, row %d ", row);
coords.x = ((vmodule_rows - (row+1))*virtualResX)+virt_x; coords.x = ((vmodule_rows - (row + 1)) * virtualResX) + virt_x;
coords.y = virt_y % panelResY; coords.y = virt_y % panelResY;
} }
break; break;
case (CHAIN_BOTTOM_RIGHT_UP): // OK -> modulus opposite of CHAIN_BOTTOM_LEFT_UP case (CHAIN_BOTTOM_RIGHT_UP): // OK -> modulus opposite of CHAIN_BOTTOM_LEFT_UP
{ {
row = vmodule_rows - row - 1; row = vmodule_rows - row - 1;
if ( (row % 2) == 0 ) if ((row % 2) == 0)
{ // right side up { // right side up
// Serial.printf("Condition 1, row %d ", row); // Serial.printf("Condition 1, row %d ", row);
// refersed for the row // refersed for the row
coords.x = ((vmodule_rows - (row+1))*virtualResX)+virt_x; coords.x = ((vmodule_rows - (row + 1)) * virtualResX) + virt_x;
coords.y = virt_y % panelResY; coords.y = virt_y % panelResY;
} }
else else
{ // inverted panel { // inverted panel
// Serial.printf("Condition 2, row %d ", row); // Serial.printf("Condition 2, row %d ", row);
coords.x = dmaResX - (row*virtualResX) - virt_x; coords.x = dmaResX - (row * virtualResX) - virt_x;
coords.y = panelResY - 1 - (virt_y % panelResY); coords.y = panelResY - 1 - (virt_y % panelResY);
} }
}
}
break;
case (CHAIN_BOTTOM_RIGHT_UP_ZZ):
{
// Right side up. Starting bottom right all the way up.
// Connected in a Zig Zag manner = some long ass cables being used potentially
row = vmodule_rows - row - 1;
//Serial.printf("Condition 2, row %d ", row);
coords.x = ((vmodule_rows - (row+1))*virtualResX)+virt_x;
coords.y = virt_y % panelResY;
}
break; break;
default:
coords.x = coords.y = -1; // By defalt use an invalid co-ordinates that will be rejected by updateMatrixDMABuffer
return coords;
break;
} // end switch
case (CHAIN_BOTTOM_RIGHT_UP_ZZ):
{
// Right side up. Starting bottom right all the way up.
// Connected in a Zig Zag manner = some long ass cables being used potentially
/* START: Pixel remapping AGAIN to convert TWO parallel scanline output that the row = vmodule_rows - row - 1;
* the underlying hardware library is designed for (because // Serial.printf("Condition 2, row %d ", row);
* there's only 2 x RGB pins... and convert this to 1/4 or something coords.x = ((vmodule_rows - (row + 1)) * virtualResX) + virt_x;
*/ coords.y = virt_y % panelResY;
if (panel_scan_rate == FOUR_SCAN_32PX_HIGH) }
{ break;
/* 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 // Q: 1 row!? Why?
as if the panel is 2 * W and 0.5 * H ! // A: In cases people are only using virtual matrix panel for panels of non-standard scan rates.
*/ default:
coords.x = virt_x; coords.y = virt_y;
break;
} // end switch
if ((virt_y & 8) == 0) /* START: Pixel remapping AGAIN to convert TWO parallel scanline output that the
* the underlying hardware library is designed for (because
* there's only 2 x RGB pins... and convert this to 1/4 or something
*/
if (panel_scan_rate == FOUR_SCAN_32PX_HIGH)
{ {
coords.x += ((coords.x / panelResX) + 1) * panelResX; // 1st, 3rd 'block' of 8 rows of pixels, offset by panel width in DMA buffer /* 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);
} }
else else if (panel_scan_rate == FOUR_SCAN_16PX_HIGH)
{ {
coords.x += (coords.x / panelResX) * panelResX; // 2nd, 4th 'block' of 8 rows of pixels, offset by panel width in DMA buffer if ((virt_y & 8) == 0)
{
coords.x += (panelResX >> 2) * (((coords.x & 0xFFF0) >> 4) + 1); // 1st, 3rd 'block' of 8 rows of pixels, offset by panel width in DMA buffer
}
else
{
coords.x += (panelResX >> 2) * (((coords.x & 0xFFF0) >> 4)); // 2nd, 4th 'block' of 8 rows of pixels, offset by panel width in DMA buffer
}
if (virt_y < 32)
coords.y = (virt_y >> 4) * 8 + (virt_y & 0b00000111);
else
{
coords.y = ((virt_y - 32) >> 4) * 8 + (virt_y & 0b00000111);
coords.x += 256;
}
} }
// http://cpp.sh/4ak5u return coords;
// 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);
}
else if (panel_scan_rate == FOUR_SCAN_16PX_HIGH)
{
if ((virt_y & 8) == 0)
{
coords.x += (panelResX >> 2) * (((coords.x & 0xFFF0) >> 4) + 1); // 1st, 3rd 'block' of 8 rows of pixels, offset by panel width in DMA buffer
}
else
{
coords.x += (panelResX >> 2) * (((coords.x & 0xFFF0) >> 4)); // 2nd, 4th 'block' of 8 rows of pixels, offset by panel width in DMA buffer
}
if (virt_y < 32)
coords.y = (virt_y >> 4) * 8 + (virt_y & 0b00000111);
else
{
coords.y = ((virt_y - 32) >> 4) * 8 + (virt_y & 0b00000111);
coords.x += 256;
}
}
return coords;
} }
inline void VirtualMatrixPanel::drawPixel(int16_t x, int16_t y, uint16_t color) inline void VirtualMatrixPanel::drawPixel(int16_t x, int16_t y, uint16_t color)
{ // adafruit virtual void override { // adafruit virtual void override
getCoords(x, y); getCoords(x, y);
// Serial.printf("Requested virtual x,y coord (%d, %d), got phyical chain coord of (%d,%d)\n", x,y, coords.x, coords.y); // Serial.printf("Requested virtual x,y coord (%d, %d), got phyical chain coord of (%d,%d)\n", x,y, coords.x, coords.y);
this->display->drawPixel(coords.x, coords.y, color); this->display->drawPixel(coords.x, coords.y, color);
} }
inline void VirtualMatrixPanel::fillScreen(uint16_t color) inline void VirtualMatrixPanel::fillScreen(uint16_t color)
{ // adafruit virtual void override { // adafruit virtual void override
this->display->fillScreen(color); this->display->fillScreen(color);
} }
inline void VirtualMatrixPanel::fillScreenRGB888(uint8_t r, uint8_t g, uint8_t b) inline void VirtualMatrixPanel::fillScreenRGB888(uint8_t r, uint8_t g, uint8_t b)
{ {
this->display->fillScreenRGB888(r, g, b); this->display->fillScreenRGB888(r, g, b);
} }
inline void VirtualMatrixPanel::drawPixelRGB888(int16_t x, int16_t y, uint8_t r, uint8_t g, uint8_t b) inline void VirtualMatrixPanel::drawPixelRGB888(int16_t x, int16_t y, uint8_t r, uint8_t g, uint8_t b)
{ {
getCoords(x, y); getCoords(x, y);
this->display->drawPixelRGB888(coords.x, coords.y, r, g, b); this->display->drawPixelRGB888(coords.x, coords.y, r, g, b);
} }
#ifdef USE_GFX_ROOT #ifdef USE_GFX_ROOT
// Support for CRGB values provided via FastLED // Support for CRGB values provided via FastLED
inline void VirtualMatrixPanel::drawPixel(int16_t x, int16_t y, CRGB color) inline void VirtualMatrixPanel::drawPixel(int16_t x, int16_t y, CRGB color)
{ {
getCoords(x, y); getCoords(x, y);
this->display->drawPixel(coords.x, coords.y, color); this->display->drawPixel(coords.x, coords.y, color);
} }
inline void VirtualMatrixPanel::fillScreen(CRGB color) inline void VirtualMatrixPanel::fillScreen(CRGB color)
{ {
this->display->fillScreen(color); this->display->fillScreen(color);
} }
#endif #endif
inline void VirtualMatrixPanel::setRotate(bool rotate) inline void VirtualMatrixPanel::setRotate(bool rotate)
{ {
_rotate = rotate; _rotate = rotate;
#ifndef NO_GFX #ifndef NO_GFX
// We don't support rotation by degrees. // We don't support rotation by degrees.
if (rotate) if (rotate)
{ {
setRotation(1); setRotation(1);
} }
else else
{ {
setRotation(0); setRotation(0);
} }
#endif #endif
} }
inline void VirtualMatrixPanel::setPhysicalPanelScanRate(PANEL_SCAN_RATE rate) inline void VirtualMatrixPanel::setPhysicalPanelScanRate(PANEL_SCAN_RATE rate)
{ {
panel_scan_rate = rate; panel_scan_rate = rate;
} }
#ifndef NO_GFX #ifndef NO_GFX
inline void VirtualMatrixPanel::drawDisplayTest() inline void VirtualMatrixPanel::drawDisplayTest()
{ {
this->display->setFont(&FreeSansBold12pt7b); this->display->setFont(&FreeSansBold12pt7b);
this->display->setTextColor(this->display->color565(255, 255, 0)); this->display->setTextColor(this->display->color565(255, 255, 0));
this->display->setTextSize(1); this->display->setTextSize(1);
for (int panel = 0; panel < vmodule_cols * vmodule_rows; panel++) for (int panel = 0; panel < vmodule_cols * vmodule_rows; panel++)
{ {
int top_left_x = (panel == 0) ? 0 : (panel * panelResX); int top_left_x = (panel == 0) ? 0 : (panel * panelResX);
this->display->drawRect(top_left_x, 0, panelResX, panelResY, this->display->color565(0, 255, 0)); this->display->drawRect(top_left_x, 0, panelResX, panelResY, this->display->color565(0, 255, 0));
this->display->setCursor( (panel * panelResX)+2, panelResY - 4); this->display->setCursor((panel * panelResX) + 2, panelResY - 4);
this->display->print((vmodule_cols * vmodule_rows) - panel); this->display->print((vmodule_cols * vmodule_rows) - panel);
} }
} }
#endif #endif