diff --git a/src/ESP32-HUB75-MatrixPanel-I2S-DMA.cpp b/src/ESP32-HUB75-MatrixPanel-I2S-DMA.cpp index 8b9e3eb..128a3e9 100644 --- a/src/ESP32-HUB75-MatrixPanel-I2S-DMA.cpp +++ b/src/ESP32-HUB75-MatrixPanel-I2S-DMA.cpp @@ -625,7 +625,60 @@ void MatrixPanel_I2S_DMA::clearFrameBuffer(bool _buff_id) * @param brt - brightness level from 0 to 255 - NOT MATRIX_WIDTH * @param _buff_id - buffer id to control */ -void MatrixPanel_I2S_DMA::brtCtrlOEv2(uint8_t brt, const int _buff_id) +/* +void MatrixPanel_I2S_DMA::setBrightnessOE(uint8_t brightness, const int buffer_id) { + + if (!initialized) + return; + + frameStruct *frameBuffer = &frame_buffer[buffer_id]; + + uint8_t blanking = m_cfg.latch_blanking; // Prevent overwriting during latch blanking + uint8_t colorDepth = frameBuffer->rowBits[0]->colour_depth; + uint16_t width = frameBuffer->rowBits[0]->width; + + // Iterate through each row in the DMA buffer + for (int rowIdx = frameBuffer->rowBits.size() - 1; rowIdx >= 0; --rowIdx) { + + // Process each bitplane (color depth level) + for (int depthIdx = colorDepth - 1; depthIdx >= 0; --depthIdx) { + int bitPlane = (2 * colorDepth - depthIdx) % colorDepth; + int bitShift = (colorDepth - lsbMsbTransitionBit - 1) >> 1; + int rightShift = std::max(bitPlane - bitShift - 2, 0); + + // Calculate the brightness range for OE control + int activePixelRange = ((width - blanking) * brightness) >> (7 + rightShift); + activePixelRange = (activePixelRange >> 1) | (activePixelRange & 1); + + int xCoordMin = (width - activePixelRange) >> 1; + int xCoordMax = (width + activePixelRange + 1) >> 1; + + // Get pointer to the specific row and bitplane + ESP32_I2S_DMA_STORAGE_TYPE *rowData = frameBuffer->rowBits[rowIdx]->getDataPtr(depthIdx); + + // Set OE bits based on brightness thresholds + for (int x = width - 1; x >= 0; --x) { + if (x >= xCoordMin && x < xCoordMax) { + rowData[ESP32_TX_FIFO_POSITION_ADJUST(x)] &= BITMASK_OE_CLEAR; // Enable output + } else { + rowData[ESP32_TX_FIFO_POSITION_ADJUST(x)] |= BIT_OE; // Disable output + } + } + } + + // switch pointer to a row for a specific colour index + #if defined(SPIRAM_DMA_BUFFER) + ESP32_I2S_DMA_STORAGE_TYPE *row_hack = fb->rowBits[rowIdx]->getDataPtr(0); + //Cache_WriteBack_Addr((uint32_t)row_hack, sizeof(ESP32_I2S_DMA_STORAGE_TYPE) * ((fb->rowBits[row_idx]->width * fb->rowBits[row_idx]->colour_depth) - 1)); + Cache_WriteBack_Addr((uint32_t)row_hack, fb->rowBits[rowIdx]->getColorDepthSize()); + #endif + + } +} +*/ + + +void MatrixPanel_I2S_DMA::setBrightnessOE(uint8_t brt, const int _buff_id) { if (!initialized) @@ -691,6 +744,7 @@ void MatrixPanel_I2S_DMA::brtCtrlOEv2(uint8_t brt, const int _buff_id) } while (row_idx); } + /* * overload for compatibility */ diff --git a/src/ESP32-HUB75-MatrixPanel-I2S-DMA.h b/src/ESP32-HUB75-MatrixPanel-I2S-DMA.h index eccfae0..428f56b 100644 --- a/src/ESP32-HUB75-MatrixPanel-I2S-DMA.h +++ b/src/ESP32-HUB75-MatrixPanel-I2S-DMA.h @@ -640,11 +640,11 @@ public: } brightness = b; - brtCtrlOEv2(b, 0); + setBrightnessOE(b, 0); if (m_cfg.double_buff) { - brtCtrlOEv2(b, 1); + setBrightnessOE(b, 1); } } @@ -731,12 +731,12 @@ protected: inline void resetbuffers() { clearFrameBuffer(0); - brtCtrlOEv2(brightness, 0); + setBrightnessOE(brightness, 0); if (m_cfg.double_buff) { clearFrameBuffer(1); - brtCtrlOEv2(brightness, 1); + setBrightnessOE(brightness, 1); } } @@ -806,7 +806,7 @@ private: * @param brt - brightness level from 0 to row_width * @param _buff_id - buffer id to control */ - void brtCtrlOEv2(uint8_t brt, const int _buff_id = 0); + void setBrightnessOE(uint8_t brt, const int _buff_id = 0); /** * @brief - transforms coordinates according to orientation diff --git a/src/ESP32-HUB75-VirtualMatrixPanel_T.hpp b/src/ESP32-HUB75-VirtualMatrixPanel_T.hpp index 9a7e37d..0cebc2b 100644 --- a/src/ESP32-HUB75-VirtualMatrixPanel_T.hpp +++ b/src/ESP32-HUB75-VirtualMatrixPanel_T.hpp @@ -129,55 +129,20 @@ struct ScanTypeMapping { } else if constexpr (ScanType == FOUR_SCAN_40_80PX_HFARCAN) { - - /* - * Weird mapping: https://github.com/mrcodetastic/ESP32-HUB75-MatrixPanel-DMA/issues/759 - * Panel is annoyingly weird. When sent DMA signal as if it's a - * 160px wide and 20px high. Then the DMA signal pixel (0,0) is - * shown on row 10. - * Then pixel 15 (i.e. 16 in real world), is at the physical of - * 0,0 (i.e. top left pixel), which then goes for 32 pixel. - * Then the next 32 pixel are at row 10 again. And so on and so forth. - */ - - int panel_local_x = coords.x % 80; // compensate for chain of these panels - int logical_dma_y = (coords.y % 10) + 10 * ((coords.y / 20) % 2); // not impacted by chaining + // Weird mapping: https://github.com/mrcodetastic/ESP32-HUB75-MatrixPanel-DMA/issues/759 + panel_pixel_base = 16; - int logical_dma_x = 0; - int logical_x_option = (coords.y/10)%2; + // Mapping logic + int panel_local_x = coords.x % 80; // Compensate for chain of panels - // Option 0 - phyiscal lines 0-9, 20-29 - if (logical_x_option == 0) { - - if (panel_local_x < 32) { - logical_dma_x += 16; - } - else if (panel_local_x < 64) { - logical_dma_x += 48; - } - else if (panel_local_x < 80) { - logical_dma_x += 80; - } - - } else { + if ((((coords.y) / 10) % 2) ^ ((panel_local_x / panel_pixel_base) % 2)) { + coords.x += ((coords.x / panel_pixel_base) * panel_pixel_base); + } else { + coords.x += (((coords.x / panel_pixel_base) + 1) * panel_pixel_base); + } - // Option 1 - if (panel_local_x < 16) { - } - else if (panel_local_x < 48) { - logical_dma_x += 32; - } - else if (panel_local_x < 80) { - logical_dma_x += 64; - } - } + coords.y = (coords.y % 10) + 10 * ((coords.y / 20) % 2); - // What logical row are we addressing? - logical_dma_x += panel_local_x; - - coords.x = logical_dma_x; - coords.y = logical_dma_y; - } // FOUR_SCAN_64PX_HIGH || FOUR_SCAN_32PX_HIGH else if constexpr (ScanType == FOUR_SCAN_64PX_HIGH || ScanType == FOUR_SCAN_32PX_HIGH) diff --git a/testing/four_scan_40_80px_hfarcan.cpp b/testing/four_scan_40_80px_hfarcan.cpp new file mode 100644 index 0000000..5d0cd91 --- /dev/null +++ b/testing/four_scan_40_80px_hfarcan.cpp @@ -0,0 +1,45 @@ +#include <iostream> +#include <iomanip> // For output formatting + + +// FOUR_SCAN_40_80PX_HFARCAN test +struct Coords { + int x; + int y; +}; + +int main() { + int panel_pixel_base = 16; // Updated pixel base + Coords coords; + + // Header for easy Excel copying (Pipe-delimited format) + std::cout << "Input X|Input Y|Output X|Output Y" << std::endl; + + // Loop for testing multiple inputs + for (int y = 0; y < 40; y += 3) { // Updated y increment to 3 + for (int x = 0; x < 80; x += 10) { + coords.x = x; + coords.y = y; + + // Store original coordinates for display + int input_x = coords.x; + int input_y = coords.y; + + // Mapping logic + int panel_local_x = coords.x % 80; // Compensate for chain of panels + + if ((((coords.y) / 10) % 2) ^ ((panel_local_x / panel_pixel_base) % 2)) { + coords.x += ((coords.x / panel_pixel_base) * panel_pixel_base); + } else { + coords.x += (((coords.x / panel_pixel_base) + 1) * panel_pixel_base); + } + + coords.y = (coords.y % 10) + 10 * ((coords.y / 20) % 2); + + // Output results in pipe-delimited format for easy Excel import + std::cout << input_x << "|" << input_y << "|" << coords.x << "|" << coords.y << std::endl; + } + } + + return 0; +} \ No newline at end of file