From e15f11ac46e46baed387713e14718713de4e8f12 Mon Sep 17 00:00:00 2001 From: mrfaptastic <12006953+mrfaptastic@users.noreply.github.com> Date: Mon, 13 Mar 2023 18:27:39 +0000 Subject: [PATCH 1/3] Update ESP32-HUB75-MatrixPanel-I2S-DMA.cpp --- src/ESP32-HUB75-MatrixPanel-I2S-DMA.cpp | 88 +++---------------------- 1 file changed, 8 insertions(+), 80 deletions(-) diff --git a/src/ESP32-HUB75-MatrixPanel-I2S-DMA.cpp b/src/ESP32-HUB75-MatrixPanel-I2S-DMA.cpp index cf1915c..694150e 100644 --- a/src/ESP32-HUB75-MatrixPanel-I2S-DMA.cpp +++ b/src/ESP32-HUB75-MatrixPanel-I2S-DMA.cpp @@ -186,11 +186,11 @@ void MatrixPanel_I2S_DMA::configureDMA(const HUB75_I2S_CFG& _cfg) //link_dma_desc(&dmadesc_a[current_dmadescriptor_offset], previous_dmadesc_a, dma_buff.rowBits[row]->getDataPtr(), dma_buff.rowBits[row]->size(num_dma_payload_colour_depths)); // previous_dmadesc_a = &dmadesc_a[current_dmadescriptor_offset]; - dma_bus.create_dma_desc_link(dma_buff.rowBits[row]->getDataPtr(0, 0), dma_buff.rowBits[row]->size(num_dma_payload_colour_depths), false); + dma_bus.create_dma_desc_link( dma_buff.rowBits[row]->getDataPtr(0, 0), dma_buff.rowBits[row]->size(num_dma_payload_colour_depths), false); if (m_cfg.double_buff) { - dma_bus.create_dma_desc_link(dma_buff.rowBits[row]->getDataPtr(0, 1), dma_buff.rowBits[row]->size(num_dma_payload_colour_depths), true); + dma_bus.create_dma_desc_link( dma_buff.rowBits[row]->getDataPtr(0, 1), dma_buff.rowBits[row]->size(num_dma_payload_colour_depths), true); } current_dmadescriptor_offset++; @@ -205,7 +205,7 @@ void MatrixPanel_I2S_DMA::configureDMA(const HUB75_I2S_CFG& _cfg) if (m_cfg.double_buff) { dma_bus.create_dma_desc_link(dma_buff.rowBits[row]->getDataPtr(cd, 1), dma_buff.rowBits[row]->size(num_dma_payload_colour_depths), true); - } + } current_dmadescriptor_offset++; @@ -336,14 +336,6 @@ uint16_t red16, green16, blue16; * so we have to check for this and check the correct position of the MATRIX_DATA_STORAGE_TYPE * data. */ -/* -#if defined (ESP32_THE_ORIG) - // We need to update the correct uint16_t in the rowBitStruct array, that gets sent out in parallel - // 16 bit parallel mode - Save the calculated value to the bitplane memory in reverse order to account for I2S Tx FIFO mode1 ordering - // Irrelevant for ESP32-S2 the way the FIFO ordering works is different - refer to page 679 of S2 technical reference manual - x_coord & 1U ? --x_coord : ++x_coord; -#endif -*/ x_coord = ESP32_TX_FIFO_POSITION_ADJUST(x_coord); @@ -359,14 +351,7 @@ uint16_t red16, green16, blue16; uint8_t colour_depth_idx = m_cfg.getPixelColorDepthBits(); do { --colour_depth_idx; -/* -// uint8_t mask = (1 << (colour_depth_idx COLOR_DEPTH_LESS_THAN_8BIT_ADJUST)); // expect 24 bit colour (8 bits per RGB subpixel) - #if PIXEL_COLOUR_DEPTH_BITS < 8 - uint8_t mask = (1 << (colour_depth_idx+MASK_OFFSET)); // expect 24 bit colour (8 bits per RGB subpixel) - #else - uint8_t mask = (1 << (colour_depth_idx)); // expect 24 bit color (8 bits per RGB subpixel) - #endif -*/ + uint16_t mask = PIXEL_COLOR_MASK_BIT(colour_depth_idx, MASK_OFFSET); uint16_t RGB_output_bits = 0; @@ -417,13 +402,7 @@ uint16_t red16, green16, blue16; for(uint8_t colour_depth_idx=0; colour_depth_idx < m_cfg.getPixelColorDepthBits(); colour_depth_idx++) // colour depth - 8 iterations { // let's precalculate RGB1 and RGB2 bits than flood it over the entire DMA buffer - uint16_t RGB_output_bits = 0; -// uint8_t mask = (1 << colour_depth_idx COLOR_DEPTH_LESS_THAN_8BIT_ADJUST); // 24 bit colour - // #if PIXEL_COLOR_DEPTH_BITS < 8 - // uint8_t mask = (1 << (colour_depth_idx+MASK_OFFSET)); // expect 24 bit colour (8 bits per RGB subpixel) - // #else - // uint8_t mask = (1 << (colour_depth_idx)); // expect 24 bit colour (8 bits per RGB subpixel) - // #endif + uint16_t RGB_output_bits = 0; uint16_t mask = PIXEL_COLOR_MASK_BIT(colour_depth_idx, MASK_OFFSET); @@ -503,7 +482,7 @@ void MatrixPanel_I2S_DMA::clearFrameBuffer(bool _buff_id){ } else { row[ESP32_TX_FIFO_POSITION_ADJUST(x_pixel)] = abcde; } - // ESP_LOGI("", "x pixel 1: %d", x_pixel); + } while(x_pixel!=dma_buff.rowBits[row_idx]->width && x_pixel); // colour_index[0] (LSB) x_pixels must be "marked" with a previous's row address, 'cause it is used to display @@ -519,8 +498,7 @@ void MatrixPanel_I2S_DMA::clearFrameBuffer(bool _buff_id){ } else { row[ESP32_TX_FIFO_POSITION_ADJUST(x_pixel)] = abcde; } - //row[x_pixel] = abcde; - // ESP_LOGI("", "x pixel 2: %d", x_pixel); + } while(x_pixel); @@ -548,18 +526,7 @@ void MatrixPanel_I2S_DMA::clearFrameBuffer(bool _buff_id){ // switch pointer to a row for a specific colour index row = dma_buff.rowBits[row_idx]->getDataPtr(colouridx, _buff_id); - - /* - #if defined(ESP32_THE_ORIG) - // We need to update the correct uint16_t in the rowBitStruct array, that gets sent out in parallel - // 16 bit parallel mode - Save the calculated value to the bitplane memory in reverse order to account for I2S Tx FIFO mode1 ordering - // Irrelevant for ESP32-S2 the way the FIFO ordering works is different - refer to page 679 of S2 technical reference manual - row[dma_buff.rowBits[row_idx]->width - 2] |= BIT_LAT; // -2 in the DMA array is actually -1 when it's reordered by TX FIFO - #else - // -1 works better on ESP32-S2 ? Because bytes get sent out in order... - row[dma_buff.rowBits[row_idx]->width - 1] |= BIT_LAT; // -1 pixel to compensate array index starting at 0 - #endif - */ + row[ESP32_TX_FIFO_POSITION_ADJUST(dma_buff.rowBits[row_idx]->width - 1)] |= BIT_LAT; // -1 pixel to compensate array index starting at 0 //ESP32_TX_FIFO_POSITION_ADJUST(dma_buff.rowBits[row_idx]->width - 1) @@ -569,21 +536,6 @@ void MatrixPanel_I2S_DMA::clearFrameBuffer(bool _buff_id){ uint8_t _blank = m_cfg.latch_blanking; do { --_blank; - /* - #if defined(ESP32_THE_ORIG) - // Original ESP32 WROOM FIFO Ordering Sucks - uint8_t _blank_row_tx_fifo_tmp = 0 + _blank; - (_blank_row_tx_fifo_tmp & 1U) ? --_blank_row_tx_fifo_tmp : ++_blank_row_tx_fifo_tmp; - row[_blank_row_tx_fifo_tmp] |= BIT_OE; - - _blank_row_tx_fifo_tmp = dma_buff.rowBits[row_idx]->width - _blank - 1; // (LAT pulse is (width-2) -1 pixel to compensate array index starting at 0 - (_blank_row_tx_fifo_tmp & 1U) ? --_blank_row_tx_fifo_tmp : ++_blank_row_tx_fifo_tmp; - row[_blank_row_tx_fifo_tmp] |= BIT_OE; - #else - row[0 + _blank] |= BIT_OE; - row[dma_buff.rowBits[row_idx]->width - _blank - 1 ] |= BIT_OE; // (LAT pulse is (width-2) -1 pixel to compensate array index starting at 0 - #endif - */ row[ESP32_TX_FIFO_POSITION_ADJUST(0 + _blank)] |= BIT_OE; // disable output row[ESP32_TX_FIFO_POSITION_ADJUST(dma_buff.rowBits[row_idx]->width - 1)] |= BIT_OE; // disable output @@ -742,30 +694,6 @@ void MatrixPanel_I2S_DMA::brtCtrlOEv2(uint8_t brt, const int _buff_id) { row[ESP32_TX_FIFO_POSITION_ADJUST(x_coord)] |= BIT_OE; // Disable output after this point. } - - // Note: Old code below from 'brtCtrlOE' - - /* - // clear OE bit for all other pixels (that is, turn on output) - row[ESP32_TX_FIFO_POSITION_ADJUST(x_coord)] &= BITMASK_OE_CLEAR; - - - // Brightness control via OE toggle - disable matrix output at specified x_coord - if((colouridx > lsbMsbTransitionBit || !colouridx) && ((x_coord) >= brt)){ - row[ESP32_TX_FIFO_POSITION_ADJUST(x_coord)] |= BIT_OE; // Disable output after this point. - continue; - } - // special case for the bits *after* LSB through (lsbMsbTransitionBit) - OE is output after data is shifted, so need to set OE to fractional brightness - if(colouridx && colouridx <= lsbMsbTransitionBit) { - // divide brightness in half for each bit below lsbMsbTransitionBit - int lsbBrightness = brt >> (lsbMsbTransitionBit - colouridx + 1); - if((x_coord) >= lsbBrightness) { - row[ESP32_TX_FIFO_POSITION_ADJUST(x_coord)] |= BIT_OE; // Disable output after this point. - continue; - } - } - */ - } while(x_coord); } while(colouridx); From 1d21b165df6733b5d58d8d3fd5ea38e557e527b7 Mon Sep 17 00:00:00 2001 From: mrfaptastic <12006953+mrfaptastic@users.noreply.github.com> Date: Wed, 15 Mar 2023 13:46:43 +0000 Subject: [PATCH 2/3] Add CHAIN_TOP_RIGHT_DOWN_ZZ --- src/ESP32-VirtualMatrixPanel-I2S-DMA.h | 17 +++++- testing/README.md | 2 +- testing/baseline.hpp | 2 +- testing/virtual.cpp | 83 ++++++++++++++++++++++---- 4 files changed, 90 insertions(+), 14 deletions(-) diff --git a/src/ESP32-VirtualMatrixPanel-I2S-DMA.h b/src/ESP32-VirtualMatrixPanel-I2S-DMA.h index 93b35a0..6408a30 100644 --- a/src/ESP32-VirtualMatrixPanel-I2S-DMA.h +++ b/src/ESP32-VirtualMatrixPanel-I2S-DMA.h @@ -57,7 +57,8 @@ enum PANEL_CHAIN_TYPE CHAIN_TOP_LEFT_DOWN, CHAIN_TOP_RIGHT_DOWN, CHAIN_BOTTOM_LEFT_UP, - CHAIN_BOTTOM_RIGHT_UP + CHAIN_BOTTOM_RIGHT_UP, + CHAIN_TOP_RIGHT_DOWN_ZZ /// ZigZag chaining. Might need a big ass cable to do this, all panels right way up. }; #ifdef USE_GFX_ROOT @@ -275,6 +276,20 @@ inline VirtualCoords VirtualMatrixPanel::getCoords(int16_t &virt_x, int16_t &vir } break; + + + case CHAIN_TOP_RIGHT_DOWN_ZZ: + { + // Right side up. Starting from top left 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; + + } + + default: diff --git a/testing/README.md b/testing/README.md index 3efe11a..fe6137f 100644 --- a/testing/README.md +++ b/testing/README.md @@ -1,5 +1,5 @@ Sample app to simulate the VirtualMatrixPanel class for testing / optimisation, without having to test with physical panels. ``` -g++ -o myapp.exe testing.cpp +g++ -o myapp.exe virtual.cpp ``` \ No newline at end of file diff --git a/testing/baseline.hpp b/testing/baseline.hpp index 417409b..43d13e7 100644 --- a/testing/baseline.hpp +++ b/testing/baseline.hpp @@ -5,7 +5,7 @@ * Not thread safe, but not a concern for ESP32 sketch anyway... I think. */ // DO NOT CHANGE -inline VirtualCoords VirtualMatrixPanelTest::getCoords_WorkingBaslineMarch2023(int16_t &virt_x, int16_t &virt_y) +inline VirtualCoords VirtualMatrixPanelTest::getCoords_WorkingBaslineMarch2023(int16_t virt_x, int16_t virt_y) { coords.x = coords.y = -1; // By defalt use an invalid co-ordinates that will be rejected by updateMatrixDMABuffer diff --git a/testing/virtual.cpp b/testing/virtual.cpp index b367c40..f13b2ea 100644 --- a/testing/virtual.cpp +++ b/testing/virtual.cpp @@ -28,7 +28,8 @@ enum PANEL_CHAIN_TYPE CHAIN_TOP_LEFT_DOWN, CHAIN_TOP_RIGHT_DOWN, CHAIN_BOTTOM_LEFT_UP, - CHAIN_BOTTOM_RIGHT_UP + CHAIN_BOTTOM_RIGHT_UP, + CHAIN_TOP_RIGHT_DOWN_ZZ /// ZigZag chaining. Might need a big ass cable to do this, all panels right way up. }; @@ -70,6 +71,10 @@ public: chain_type_str = "CHAIN_TOP_RIGHT_DOWN"; break; + case CHAIN_TOP_RIGHT_DOWN_ZZ: + chain_type_str = "CHAIN_TOP_RIGHT_DOWN_ZZ"; + break; + case CHAIN_BOTTOM_RIGHT_UP: chain_type_str = "CHAIN_BOTTOM_RIGHT_UP"; break; @@ -95,9 +100,9 @@ public: std::string chain_type_str = "UNKNOWN"; // Internal co-ord conversion function - VirtualCoords getCoords_Dev(int16_t &x, int16_t &y); + VirtualCoords getCoords_Dev(int16_t x, int16_t y); - VirtualCoords getCoords_WorkingBaslineMarch2023(int16_t &x, int16_t &y); + VirtualCoords getCoords_WorkingBaslineMarch2023(int16_t x, int16_t y); VirtualCoords coords; @@ -127,7 +132,7 @@ private: /** * Development version for testing. */ -inline VirtualCoords VirtualMatrixPanelTest::getCoords_Dev(int16_t &virt_x, int16_t &virt_y) +inline VirtualCoords VirtualMatrixPanelTest::getCoords_Dev(int16_t virt_x, int16_t virt_y) { coords.x = coords.y = -1; // By defalt use an invalid co-ordinates that will be rejected by updateMatrixDMABuffer @@ -246,6 +251,18 @@ inline VirtualCoords VirtualMatrixPanelTest::getCoords_Dev(int16_t &virt_x, int1 } break; + + case CHAIN_TOP_RIGHT_DOWN_ZZ: + { + // Right side up. Starting from top left 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; + + } + default: @@ -309,6 +326,23 @@ inline VirtualCoords VirtualMatrixPanelTest::getCoords_Dev(int16_t &virt_x, int1 return coords; } +bool check(VirtualCoords expected, VirtualCoords result, int x = -1, int y = -1) +{ + + if ( result.x != expected.x || result.y != expected.y ) + { + std::printf("Requested (%d, %d) -> expecting physical (%d, %d) got (%d, %d).", x, y, expected.x, expected.y, result.x, result.y); + std::cout << "\t *** FAIL ***\n "; + std::cout << "\n"; + + return false; + } + else + { + return true; + } +} + main(int argc, char* argv[]) { @@ -343,13 +377,11 @@ main(int argc, char* argv[]) { VirtualCoords expected = test.getCoords_WorkingBaslineMarch2023(x,y); VirtualCoords result = test.getCoords_Dev(x,y); + + bool chk_result = check(expected, result, x, y); - if ( result.x != expected.x || result.y != expected.y ) - { - std::printf("Requested (%d, %d) -> expecting physical (%d, %d) got (%d, %d).", x, y, expected.x, expected.y, result.x, result.y); - std::cout << "\t *** FAIL ***\n "; - std::cout << "\n"; - + if ( chk_result ) + { fail_counter++; } else @@ -366,7 +398,36 @@ main(int argc, char* argv[]) } } // end chain type test list - + + + std::cout << "Performing NON-SERPENTINE (ZIG ZAG) TEST"; + + rows = 3; + cols = 1; + panel_width_x = 64; + panel_height_y = 64; + + VirtualMatrixPanelTest test = VirtualMatrixPanelTest(rows,cols,panel_width_x,panel_height_y, CHAIN_TOP_RIGHT_DOWN_ZZ); + + // CHAIN_TOP_RIGHT_DOWN_ZZ test 1 + // (x,y) + VirtualCoords result = test.getCoords_Dev(0,0); + VirtualCoords expected; expected.x = 64*2; expected.y = 0; + std::printf("Expected physical (%d, %d) got (%d, %d).\n", expected.x, expected.y, result.x, result.y); + + // CHAIN_TOP_RIGHT_DOWN_ZZ test 2 + result = test.getCoords_Dev(10,64*3-1); + expected.x = 10; expected.y = 63; + std::printf("Expected physical (%d, %d) got (%d, %d).\n", expected.x, expected.y, result.x, result.y); + + + // CHAIN_TOP_RIGHT_DOWN_ZZ test 3 + result = test.getCoords_Dev(16,64*2-1); + expected.x = 80; expected.y = 63; + std::printf("Expected physical (%d, %d) got (%d, %d).\n", expected.x, expected.y, result.x, result.y); + + + std::cout << "\n\n"; return 0; } \ No newline at end of file From fe5d4148252382fed393211e2b6a163188d16312 Mon Sep 17 00:00:00 2001 From: mrfaptastic <12006953+mrfaptastic@users.noreply.github.com> Date: Wed, 15 Mar 2023 14:05:18 +0000 Subject: [PATCH 3/3] Add ZigZag options. Close #414 CHAIN_BOTTOM_RIGHT_UP_ZZ CHAIN_TOP_RIGHT_DOWN_ZZ --- src/ESP32-VirtualMatrixPanel-I2S-DMA.h | 20 +++++++++++++----- testing/virtual.cpp | 28 +++++++++++++++++++++++++- 2 files changed, 42 insertions(+), 6 deletions(-) diff --git a/src/ESP32-VirtualMatrixPanel-I2S-DMA.h b/src/ESP32-VirtualMatrixPanel-I2S-DMA.h index 6408a30..cfa295b 100644 --- a/src/ESP32-VirtualMatrixPanel-I2S-DMA.h +++ b/src/ESP32-VirtualMatrixPanel-I2S-DMA.h @@ -58,7 +58,8 @@ enum PANEL_CHAIN_TYPE CHAIN_TOP_RIGHT_DOWN, CHAIN_BOTTOM_LEFT_UP, CHAIN_BOTTOM_RIGHT_UP, - CHAIN_TOP_RIGHT_DOWN_ZZ /// ZigZag chaining. Might need a big ass cable to do this, all panels right way up. + CHAIN_TOP_RIGHT_DOWN_ZZ, /// ZigZag chaining. Might need a big ass cable to do this, all panels right way up. + CHAIN_BOTTOM_RIGHT_UP_ZZ }; #ifdef USE_GFX_ROOT @@ -280,7 +281,7 @@ inline VirtualCoords VirtualMatrixPanel::getCoords(int16_t &virt_x, int16_t &vir case CHAIN_TOP_RIGHT_DOWN_ZZ: { - // Right side up. Starting from top left all the way down. + // 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); @@ -288,9 +289,18 @@ inline VirtualCoords VirtualMatrixPanel::getCoords(int16_t &virt_x, int16_t &vir coords.y = virt_y % panelResY; } - - - + + 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 + + //Serial.printf("Condition 2, row %d ", row); + coords.x = (row*virtualResX)+virt_x; + coords.y = virt_y % panelResY; + + } + default: coords.x = coords.y = -1; // By defalt use an invalid co-ordinates that will be rejected by updateMatrixDMABuffer diff --git a/testing/virtual.cpp b/testing/virtual.cpp index f13b2ea..168acb1 100644 --- a/testing/virtual.cpp +++ b/testing/virtual.cpp @@ -29,7 +29,8 @@ enum PANEL_CHAIN_TYPE CHAIN_TOP_RIGHT_DOWN, CHAIN_BOTTOM_LEFT_UP, CHAIN_BOTTOM_RIGHT_UP, - CHAIN_TOP_RIGHT_DOWN_ZZ /// ZigZag chaining. Might need a big ass cable to do this, all panels right way up. + CHAIN_TOP_RIGHT_DOWN_ZZ, /// ZigZag chaining. Might need a big ass cable to do this, all panels right way up. + CHAIN_BOTTOM_RIGHT_UP_ZZ }; @@ -262,6 +263,18 @@ inline VirtualCoords VirtualMatrixPanelTest::getCoords_Dev(int16_t virt_x, int16 coords.y = virt_y % panelResY; } + + case CHAIN_BOTTOM_RIGHT_UP_ZZ: + { + // Right side up. Starting from top left 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 = (row*virtualResX)+virt_x; + coords.y = virt_y % panelResY; + + } + @@ -425,6 +438,19 @@ main(int argc, char* argv[]) result = test.getCoords_Dev(16,64*2-1); expected.x = 80; expected.y = 63; std::printf("Expected physical (%d, %d) got (%d, %d).\n", expected.x, expected.y, result.x, result.y); + + + + // CHAIN_BOTTOM_RIGHT_UP_ZZ test 4 + result = test.getCoords_Dev(0,0); + expected.x = 0; expected.y = 0; + std::printf("Expected physical (%d, %d) got (%d, %d).\n", expected.x, expected.y, result.x, result.y); + + // CHAIN_BOTTOM_RIGHT_UP_ZZ test 4 + result = test.getCoords_Dev(63,64); + expected.x = 64*2-1; expected.y = 0; + std::printf("Expected physical (%d, %d) got (%d, %d).\n", expected.x, expected.y, result.x, result.y); + std::cout << "\n\n";