2023-03-12 21:04:16 +01:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Calculate virtual->real co-ordinate mapping to underlying single chain of panels connected to ESP32.
|
|
|
|
* Updates the private class member variable 'coords', so no need to use the return value.
|
|
|
|
* Not thread safe, but not a concern for ESP32 sketch anyway... I think.
|
|
|
|
*/
|
|
|
|
// DO NOT CHANGE
|
2023-03-15 14:46:43 +01:00
|
|
|
inline VirtualCoords VirtualMatrixPanelTest::getCoords_WorkingBaslineMarch2023(int16_t virt_x, int16_t virt_y)
|
2023-03-12 21:04:16 +01:00
|
|
|
{
|
|
|
|
coords.x = coords.y = -1; // By defalt use an invalid co-ordinates that will be rejected by updateMatrixDMABuffer
|
|
|
|
|
|
|
|
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!
|
|
|
|
return coords;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Do we want to rotate?
|
|
|
|
if (_rotate)
|
|
|
|
{
|
|
|
|
int16_t temp_x = virt_x;
|
|
|
|
virt_x = virt_y;
|
|
|
|
virt_y = virtualResY - 1 - temp_x;
|
|
|
|
}
|
|
|
|
|
|
|
|
int row = (virt_y / panelResY); // 0 indexed
|
|
|
|
switch(panel_chain_type)
|
|
|
|
{
|
|
|
|
|
|
|
|
case (CHAIN_TOP_RIGHT_DOWN):
|
|
|
|
{
|
|
|
|
if ( (row % 2) == 1 )
|
|
|
|
{ // upside down panel
|
|
|
|
|
|
|
|
//Serial.printf("Condition 1, row %d ", row);
|
|
|
|
|
|
|
|
// refersed for the row
|
|
|
|
coords.x = dmaResX - virt_x - (row*virtualResX);
|
|
|
|
|
|
|
|
// y co-ord inverted within the panel
|
|
|
|
coords.y = panelResY - 1 - (virt_y % panelResY);
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
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): // OK -> modulus opposite of CHAIN_TOP_RIGHT_DOWN
|
|
|
|
{
|
|
|
|
if ( (row % 2) == 0 )
|
|
|
|
{ // refersed panel
|
|
|
|
|
|
|
|
//Serial.printf("Condition 1, row %d ", row);
|
|
|
|
coords.x = dmaResX - virt_x - (row*virtualResX);
|
|
|
|
|
|
|
|
// y co-ord inverted within the panel
|
|
|
|
coords.y = panelResY - 1 - (virt_y % panelResY);
|
|
|
|
|
|
|
|
}
|
|
|
|
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_BOTTOM_LEFT_UP): //
|
|
|
|
{
|
|
|
|
row = vmodule_rows - row - 1;
|
|
|
|
|
|
|
|
if ( (row % 2) == 1 )
|
|
|
|
{
|
|
|
|
// Serial.printf("Condition 1, row %d ", row);
|
|
|
|
coords.x = ((vmodule_rows - (row+1))*virtualResX)+virt_x;
|
|
|
|
coords.y = virt_y % panelResY;
|
|
|
|
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{ // inverted panel
|
|
|
|
|
|
|
|
// Serial.printf("Condition 2, row %d ", row);
|
|
|
|
coords.x = dmaResX - (row*virtualResX) - virt_x;
|
|
|
|
coords.y = panelResY - 1 - (virt_y % panelResY);
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case (CHAIN_BOTTOM_RIGHT_UP): // OK -> modulus opposite of CHAIN_BOTTOM_LEFT_UP
|
|
|
|
{
|
|
|
|
row = vmodule_rows - row - 1;
|
|
|
|
|
|
|
|
if ( (row % 2) == 0 )
|
|
|
|
{ // right side up
|
|
|
|
|
|
|
|
// Serial.printf("Condition 1, row %d ", row);
|
|
|
|
// refersed for the row
|
|
|
|
coords.x = ((vmodule_rows - (row+1))*virtualResX)+virt_x;
|
|
|
|
coords.y = virt_y % panelResY;
|
|
|
|
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{ // inverted panel
|
|
|
|
|
|
|
|
// Serial.printf("Condition 2, row %d ", row);
|
|
|
|
coords.x = dmaResX - (row*virtualResX) - virt_x;
|
|
|
|
coords.y = panelResY - 1 - (virt_y % panelResY);
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
|
|
default:
|
|
|
|
return coords;
|
|
|
|
break;
|
|
|
|
|
|
|
|
} // end switch
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* 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)
|
|
|
|
{
|
|
|
|
/* 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 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;
|
|
|
|
}
|