diff options
| author | mrfaptastic <12006953+mrfaptastic@users.noreply.github.com> | 2023-03-10 18:13:09 +0000 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2023-03-10 18:13:09 +0000 |
| commit | da22841fc5962427b8a9f319a35f37a817bfd056 (patch) | |
| tree | 577d7c088ffd3a20f2a7af11455f42911c8b5216 /src | |
| parent | 5393f649fd62e723d3740e76608b59d760a7e8b1 (diff) | |
| parent | c804f0d7afe2f3af49793d475780c6a19737bde5 (diff) | |
Merge pull request #410 from Lukaswnd/master
PIXEL_COLOR_DEPTH_BITS as part of HUB75_I2S_CFG
Diffstat (limited to 'src')
| -rw-r--r-- | src/ESP32-HUB75-MatrixPanel-I2S-DMA.cpp | 64 | ||||
| -rw-r--r-- | src/ESP32-HUB75-MatrixPanel-I2S-DMA.h | 50 |
2 files changed, 78 insertions, 36 deletions
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 +//#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 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<rowBitStruct>(PIXELS_PER_ROW, PIXEL_COLOR_DEPTH_BITS, m_cfg.double_buff); + auto ptr = std::make_shared<rowBitStruct>(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<PIXEL_COLOR_DEPTH_BITS; i++) - nsPerRow += (1<<(i - lsbMsbTransitionBit - 1)) * (PIXEL_COLOR_DEPTH_BITS - i) * nsPerLatch; + for(int i=lsbMsbTransitionBit + 1; i < m_cfg.getPixelColorDepthBits(); i++) + nsPerRow += (1<<(i - lsbMsbTransitionBit - 1)) * (m_cfg.getPixelColorDepthBits() - i) * nsPerLatch; int nsPerFrame = nsPerRow * ROWS_PER_FRAME; int actualRefreshRate = 1000000000UL/(nsPerFrame); @@ -103,7 +105,7 @@ bool MatrixPanel_I2S_DMA::allocateDMAmemory() if (actualRefreshRate > 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; i<PIXEL_COLOR_DEPTH_BITS; i++) { + for(int i=lsbMsbTransitionBit + 1; i < m_cfg.getPixelColorDepthBits(); i++) { numDMAdescriptorsPerRow += (1<<(i - lsbMsbTransitionBit - 1)); } @@ -133,9 +137,9 @@ bool MatrixPanel_I2S_DMA::allocateDMAmemory() if ( dma_buff.rowBits[0]->size() > 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; i<PIXEL_COLOR_DEPTH_BITS; i++) + for(int i=lsbMsbTransitionBit + 1; i < m_cfg.getPixelColorDepthBits(); i++) { // binary time division setup: we need 2 of bit (LSBMSB_TRANSITION_BIT + 1) four of (LSBMSB_TRANSITION_BIT + 2), etc // because we sweep through to MSB each time, it divides the number of times we have to sweep in half (saving linked list RAM) @@ -217,10 +221,10 @@ void MatrixPanel_I2S_DMA::configureDMA(const HUB75_I2S_CFG& _cfg) for(int k=0; k < (1<<(i - lsbMsbTransitionBit - 1)); k++) { - dma_bus.create_dma_desc_link(dma_buff.rowBits[row]->getDataPtr(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<PIXEL_COLOR_DEPTH_BITS; colour_depth_idx++) // colour depth - 8 iterations + 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; @@ -421,7 +425,7 @@ uint16_t red16, green16, blue16; // uint8_t mask = (1 << (colour_depth_idx)); // expect 24 bit colour (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()); /* Per the .h file, the order of the output RGB bits is: * BIT_B2, BIT_G2, BIT_R2, BIT_B1, BIT_G1, BIT_R1 */ @@ -864,7 +868,7 @@ uint16_t red16, green16, blue16; } // Iterating through colour depth bits (8 iterations) - uint8_t colour_depth_idx = PIXEL_COLOR_DEPTH_BITS; + uint8_t colour_depth_idx = m_cfg.getPixelColorDepthBits(); do { --colour_depth_idx; @@ -876,7 +880,7 @@ uint16_t red16, green16, blue16; // #else // uint8_t mask = (1 << (colour_depth_idx)); // expect 24 bit colour (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()); /* Per the .h file, the order of the output RGB bits is: * BIT_B2, BIT_G2, BIT_R2, BIT_B1, BIT_G1, BIT_R1 */ @@ -957,7 +961,7 @@ uint16_t red16, green16, blue16; */ x_coord = ESP32_TX_FIFO_POSITION_ADJUST(x_coord); - uint8_t colour_depth_idx = PIXEL_COLOR_DEPTH_BITS; + uint8_t colour_depth_idx = m_cfg.getPixelColorDepthBits(); do { // Iterating through colour depth bits (8 iterations) --colour_depth_idx; @@ -969,7 +973,7 @@ uint16_t red16, green16, blue16; // uint8_t mask = (1 << (colour_depth_idx)); // expect 24 bit colour (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: diff --git a/src/ESP32-HUB75-MatrixPanel-I2S-DMA.h b/src/ESP32-HUB75-MatrixPanel-I2S-DMA.h index bbf3ae4..f0f1941 100644 --- a/src/ESP32-HUB75-MatrixPanel-I2S-DMA.h +++ b/src/ESP32-HUB75-MatrixPanel-I2S-DMA.h @@ -68,13 +68,17 @@ // can be extended to offer deeper colors, or // might be reduced to save DMA RAM #ifdef PIXEL_COLOUR_DEPTH_BITS - #define PIXEL_COLOR_DEPTH_BITS PIXEL_COLOUR_DEPTH_BITS + #define PIXEL_COLOR_DEPTH_BITS PIXEL_COLOUR_DEPTH_BITS #endif -#ifndef PIXEL_COLOR_DEPTH_BITS - #define PIXEL_COLOR_DEPTH_BITS 8 +//support backwarts compatibility +#ifdef PIXEL_COLOR_DEPTH_BITS + #define PIXEL_COLOR_DEPTH_BITS_DEFAULT PIXEL_COLOR_DEPTH_BITS +#else + #define PIXEL_COLOR_DEPTH_BITS_DEFAULT 8 #endif +#define PIXEL_COLOR_DEPTH_BITS_MAX 12 /***************************************************************************************/ /* Definitions below should NOT be ever changed without rewriting library logic */ @@ -290,17 +294,51 @@ struct HUB75_I2S_CFG { clk_speed _i2sspeed = HZ_15M, uint8_t _latblk = DEFAULT_LAT_BLANKING, // Anything > 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 |
