From c804f0d7afe2f3af49793d475780c6a19737bde5 Mon Sep 17 00:00:00 2001 From: Lukas Date: Fri, 10 Mar 2023 11:46:17 +0100 Subject: Make PIXEL_COLOR_DEPTH_BITS part of HUB75_I2S_CFG (able to set at runtime) --- src/ESP32-HUB75-MatrixPanel-I2S-DMA.cpp | 66 +++++++++++++++++---------------- src/ESP32-HUB75-MatrixPanel-I2S-DMA.h | 50 ++++++++++++++++++++++--- 2 files changed, 79 insertions(+), 37 deletions(-) (limited to 'src') diff --git a/src/ESP32-HUB75-MatrixPanel-I2S-DMA.cpp b/src/ESP32-HUB75-MatrixPanel-I2S-DMA.cpp index 23ba3e0..2db698a 100644 --- a/src/ESP32-HUB75-MatrixPanel-I2S-DMA.cpp +++ b/src/ESP32-HUB75-MatrixPanel-I2S-DMA.cpp @@ -27,14 +27,15 @@ * However, if the library is to be used with lower colour depth (i.e. 6 bit colour), then we need to ensure the 8-bit value passed to the colour masking * is adjusted accordingly to ensure the LSB's are shifted left to MSB, by the difference. Otherwise the colours will be all screwed up. */ -#if PIXEL_COLOR_DEPTH_BITS > 12 - #error "Color depth bits cannot be greater than 12." -#elif PIXEL_COLOR_DEPTH_BITS < 2 - #error "Color depth bits cannot be less than 2." -#endif - - #define MASK_OFFSET (16 - PIXEL_COLOR_DEPTH_BITS) - #define PIXEL_COLOR_MASK_BIT(color_depth_index) (1 << (color_depth_index + MASK_OFFSET)) +//#if PIXEL_COLOR_DEPTH_BITS > 12 +// #error "Color depth bits cannot be greater than 12." +//#elif PIXEL_COLOR_DEPTH_BITS < 2 +// #error "Color depth bits cannot be less than 2." +//#endif + + //#define MASK_OFFSET (16 - PIXEL_COLOR_DEPTH_BITS) + //#define PIXEL_COLOR_MASK_BIT(color_depth_index) (1 << (color_depth_index + MASK_OFFSET)) + #define PIXEL_COLOR_MASK_BIT(color_depth_index, mask_offset) (1 << (color_depth_index + mask_offset)) //static constexpr uint8_t const MASK_OFFSET = 8-PIXEL_COLOUR_DEPTH_BITS; /* @@ -57,15 +58,16 @@ bool MatrixPanel_I2S_DMA::allocateDMAmemory() // lets allocate a chunk of memory for each row (a row could span multiple panels if chaining is in place) dma_buff.rowBits.reserve(ROWS_PER_FRAME); + ESP_LOGI("I2S-DMA", "allocating rowBitStructs with pixel_color_depth_bits of %d", m_cfg.getPixelColorDepthBits()); // iterate through number of rows, allocate memory for each size_t allocated_fb_memory = 0; for (int malloc_num =0; malloc_num < ROWS_PER_FRAME; ++malloc_num) { - auto ptr = std::make_shared(PIXELS_PER_ROW, PIXEL_COLOR_DEPTH_BITS, m_cfg.double_buff); + auto ptr = std::make_shared(PIXELS_PER_ROW, m_cfg.getPixelColorDepthBits(), m_cfg.double_buff); if (ptr->data == nullptr) { - ESP_LOGE("I2S-DMA", "CRITICAL ERROR: Not enough memory for requested colour depth! Please reduce PIXEL_COLOR_DEPTH_BITS value.\r\n"); + ESP_LOGE("I2S-DMA", "CRITICAL ERROR: Not enough memory for requested colour depth! Please reduce pixel_color_depth_bits value.\r\n"); ESP_LOGE("I2S-DMA", "Could not allocate rowBitStruct %d!.\r\n", malloc_num); return false; @@ -88,11 +90,11 @@ bool MatrixPanel_I2S_DMA::allocateDMAmemory() int nsPerLatch = ((PIXELS_PER_ROW + CLKS_DURING_LATCH) * psPerClock) / 1000; // add time to shift out LSBs + LSB-MSB transition bit - this ignores fractions... - int nsPerRow = PIXEL_COLOR_DEPTH_BITS * nsPerLatch; + int nsPerRow = m_cfg.getPixelColorDepthBits() * nsPerLatch; // add time to shift out MSBs - for(int i=lsbMsbTransitionBit + 1; i m_cfg.min_refresh_rate) break; - if(lsbMsbTransitionBit < PIXEL_COLOR_DEPTH_BITS - 1) + if(lsbMsbTransitionBit < m_cfg.getPixelColorDepthBits() - 1) lsbMsbTransitionBit++; else break; @@ -114,6 +116,8 @@ bool MatrixPanel_I2S_DMA::allocateDMAmemory() ESP_LOGW("I2S-DMA", "lsbMsbTransitionBit of %d used to achieve refresh rate of %d Hz. Percieved colour depth to the eye may be reduced.", lsbMsbTransitionBit, m_cfg.min_refresh_rate); } + ESP_LOGI("I2S-DMA", "DMA has pixel_color_depth_bits of %d", m_cfg.getPixelColorDepthBits() - lsbMsbTransitionBit); + #endif @@ -122,7 +126,7 @@ bool MatrixPanel_I2S_DMA::allocateDMAmemory() * memory allocation of the DMA linked list memory structure. */ int numDMAdescriptorsPerRow = 1; - for(int i=lsbMsbTransitionBit + 1; isize() > DMA_MAX ) { - ESP_LOGW("I2S-DMA", "rowBits struct is too large to fit in one DMA transfer payload, splitting required. Adding %d DMA descriptors\n", PIXEL_COLOR_DEPTH_BITS-1); + ESP_LOGW("I2S-DMA", "rowBits struct is too large to fit in one DMA transfer payload, splitting required. Adding %d DMA descriptors\n", m_cfg.getPixelColorDepthBits()-1); - numDMAdescriptorsPerRow += PIXEL_COLOR_DEPTH_BITS-1; + numDMAdescriptorsPerRow += m_cfg.getPixelColorDepthBits()-1; // Note: If numDMAdescriptorsPerRow is even just one descriptor too large, DMA linked list will not correctly loop. } @@ -169,7 +173,7 @@ void MatrixPanel_I2S_DMA::configureDMA(const HUB75_I2S_CFG& _cfg) int current_dmadescriptor_offset = 0; // HACK: If we need to split the payload in 1/2 so that it doesn't breach DMA_MAX, lets do it by the colour_depth. - int num_dma_payload_colour_depths = PIXEL_COLOR_DEPTH_BITS; + int num_dma_payload_colour_depths = m_cfg.getPixelColorDepthBits(); if ( dma_buff.rowBits[0]->size() > DMA_MAX ) { num_dma_payload_colour_depths = 1; } @@ -195,7 +199,7 @@ void MatrixPanel_I2S_DMA::configureDMA(const HUB75_I2S_CFG& _cfg) if ( dma_buff.rowBits[0]->size() > DMA_MAX ) { - for (int cd = 1; cd < PIXEL_COLOR_DEPTH_BITS; cd++) + for (int cd = 1; cd < m_cfg.getPixelColorDepthBits(); cd++) { dma_bus.create_dma_desc_link(dma_buff.rowBits[row]->getDataPtr(cd, 0), dma_buff.rowBits[row]->size(num_dma_payload_colour_depths), false); @@ -209,7 +213,7 @@ void MatrixPanel_I2S_DMA::configureDMA(const HUB75_I2S_CFG& _cfg) } // row depth struct - for(int i=lsbMsbTransitionBit + 1; igetDataPtr(i, 0), dma_buff.rowBits[row]->size(PIXEL_COLOR_DEPTH_BITS - i), false); + dma_bus.create_dma_desc_link(dma_buff.rowBits[row]->getDataPtr(i, 0), dma_buff.rowBits[row]->size(m_cfg.getPixelColorDepthBits() - i), false); if (m_cfg.double_buff) { - dma_bus.create_dma_desc_link(dma_buff.rowBits[row]->getDataPtr(i, 1), dma_buff.rowBits[row]->size(PIXEL_COLOR_DEPTH_BITS - i), true ); + dma_bus.create_dma_desc_link(dma_buff.rowBits[row]->getDataPtr(i, 1), dma_buff.rowBits[row]->size(m_cfg.getPixelColorDepthBits() - i), true ); } current_dmadescriptor_offset++; @@ -237,7 +241,7 @@ void MatrixPanel_I2S_DMA::configureDMA(const HUB75_I2S_CFG& _cfg) // auto bus_cfg = dma_bus.config(); // バス設定用の構造体を取得します。 - bus_cfg.bus_freq = _cfg.i2sspeed; + bus_cfg.bus_freq = m_cfg.i2sspeed; bus_cfg.pin_wr = m_cfg.gpio.clk; // WR を接続しているピン番号 bus_cfg.pin_d0 = m_cfg.gpio.r1; @@ -352,7 +356,7 @@ uint16_t red16, green16, blue16; } // Iterating through colour depth bits, which we assume are 8 bits per RGB subpixel (24bpp) - uint8_t colour_depth_idx = PIXEL_COLOR_DEPTH_BITS; + uint8_t colour_depth_idx = m_cfg.getPixelColorDepthBits(); do { --colour_depth_idx; /* @@ -363,7 +367,7 @@ uint16_t red16, green16, blue16; 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); + uint16_t mask = PIXEL_COLOR_MASK_BIT(colour_depth_idx, m_cfg.getMaskOffset()); uint16_t RGB_output_bits = 0; /* Per the .h file, the order of the output RGB bits is: @@ -410,7 +414,7 @@ uint16_t red16, green16, blue16; blue16 = blue << 8; #endif - for(uint8_t colour_depth_idx=0; colour_depth_idx 1 seems to cause artefacts on ICS panels bool _clockphase = true, - uint16_t _min_refresh_rate = 60 + uint16_t _min_refresh_rate = 60, + uint8_t _pixel_color_depth_bits = PIXEL_COLOR_DEPTH_BITS_DEFAULT ) : mx_width(_w), mx_height(_h), chain_length(_chain), gpio(_pinmap), driver(_drv), - i2sspeed(_i2sspeed), + i2sspeed(_i2sspeed), double_buff(_dbuff), latch_blanking(_latblk), clkphase(_clockphase), - min_refresh_rate (_min_refresh_rate) {} + min_refresh_rate(_min_refresh_rate) + { + setPixelColorDepthBits(_pixel_color_depth_bits); + } + + //pixel_color_depth_bits must be between 12 and 2, and mask_offset needs to be calculated accordently + //so they have to be private with getter (and setter) + void setPixelColorDepthBits(uint8_t _pixel_color_depth_bits){ + if(_pixel_color_depth_bits > PIXEL_COLOR_DEPTH_BITS_MAX || _pixel_color_depth_bits < 2){ + + if(_pixel_color_depth_bits > PIXEL_COLOR_DEPTH_BITS_MAX){ + pixel_color_depth_bits = PIXEL_COLOR_DEPTH_BITS_MAX; + }else{ + pixel_color_depth_bits = 2; + } + ESP_LOGW("HUB75_I2S_CFG", "Invalid pixel_color_depth_bits (%d): 2 <= pixel_color_depth_bits <= %d, choosing nearest valid %d", _pixel_color_depth_bits, PIXEL_COLOR_DEPTH_BITS_MAX, pixel_color_depth_bits); + }else{ + pixel_color_depth_bits = _pixel_color_depth_bits; + } + mask_offset = 16 - pixel_color_depth_bits; + } + + uint8_t getPixelColorDepthBits(){ + return pixel_color_depth_bits; + } + uint8_t getMaskOffset(){ + return mask_offset; + } + + private: + //these were priviously handeld as defines (PIXEL_COLOR_DEPTH_BITS, MASK_OFFSET) + //to make it changable after compilation, it is now part of the config + uint8_t pixel_color_depth_bits; + uint8_t mask_offset; }; // end of structure HUB75_I2S_CFG -- cgit v1.3.1