HUB75 cleanup, double buffer improvement
* code cleanup, removing some unneeded sanity checks * use dirty bits in double buffer mode, too -> only not-black pixels are drawn into the back-buffer (20%-30% faster)
This commit is contained in:
@@ -19,7 +19,7 @@ bool getBitFromArray(const uint8_t* byteArray, size_t position) { // get bit val
|
|||||||
}
|
}
|
||||||
|
|
||||||
void setBitInArray(uint8_t* byteArray, size_t position, bool value) { // set bit - with error handling for nullptr
|
void setBitInArray(uint8_t* byteArray, size_t position, bool value) { // set bit - with error handling for nullptr
|
||||||
if (byteArray == nullptr) return;
|
//if (byteArray == nullptr) return;
|
||||||
size_t byteIndex = position / 8;
|
size_t byteIndex = position / 8;
|
||||||
unsigned bitIndex = position % 8;
|
unsigned bitIndex = position % 8;
|
||||||
if (value)
|
if (value)
|
||||||
@@ -526,7 +526,6 @@ BusHub75Matrix::BusHub75Matrix(BusConfig &bc) : Bus(bc.type, bc.start, bc.autoWh
|
|||||||
|
|
||||||
_valid = false;
|
_valid = false;
|
||||||
mxconfig.double_buff = false; // default to off, known to cause issue with some effects but needs more memory
|
mxconfig.double_buff = false; // default to off, known to cause issue with some effects but needs more memory
|
||||||
isBlack = false;
|
|
||||||
|
|
||||||
fourScanPanel = nullptr;
|
fourScanPanel = nullptr;
|
||||||
|
|
||||||
@@ -700,14 +699,20 @@ BusHub75Matrix::BusHub75Matrix(BusConfig &bc) : Bus(bc.type, bc.start, bc.autoWh
|
|||||||
|
|
||||||
if (_ledBuffer) free(_ledBuffer); // should not happen
|
if (_ledBuffer) free(_ledBuffer); // should not happen
|
||||||
if (_ledsDirty) free(_ledsDirty); // should not happen
|
if (_ledsDirty) free(_ledsDirty); // should not happen
|
||||||
if(mxconfig.double_buff == false) {
|
_ledsDirty = (byte*) malloc(getBitArrayBytes(_len)); // create LEDs dirty bits
|
||||||
_ledBuffer = (CRGB*) calloc(_len, sizeof(CRGB)); // create LEDs buffer (initialized to BLACK)
|
|
||||||
_ledsDirty = (byte*) malloc(getBitArrayBytes(_len)); // create LEDs dirty bits
|
|
||||||
//_ledsDirty = nullptr;
|
|
||||||
setBitArray(_ledsDirty, _len, false); // reset dirty bits
|
|
||||||
}
|
|
||||||
|
|
||||||
isBlack = true;
|
if (_ledsDirty == nullptr) {
|
||||||
|
display->stopDMAoutput();
|
||||||
|
delete display; display = nullptr;
|
||||||
|
_valid = false;
|
||||||
|
USER_PRINTLN(F("MatrixPanel_I2S_DMA not started - not enough memory for dirty bits!"));
|
||||||
|
return; // fail is we cannot get memory for the buffer
|
||||||
|
}
|
||||||
|
setBitArray(_ledsDirty, _len, false); // reset dirty bits
|
||||||
|
|
||||||
|
if (mxconfig.double_buff == false) {
|
||||||
|
_ledBuffer = (CRGB*) calloc(_len, sizeof(CRGB)); // create LEDs buffer (initialized to BLACK)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
switch(bc.type) {
|
switch(bc.type) {
|
||||||
@@ -753,11 +758,12 @@ void __attribute__((hot)) BusHub75Matrix::setPixelColor(uint16_t pix, uint32_t c
|
|||||||
if (_ledBuffer[pix] != fastled_col) {
|
if (_ledBuffer[pix] != fastled_col) {
|
||||||
_ledBuffer[pix] = fastled_col;
|
_ledBuffer[pix] = fastled_col;
|
||||||
setBitInArray(_ledsDirty, pix, true); // flag pixel as "dirty"
|
setBitInArray(_ledsDirty, pix, true); // flag pixel as "dirty"
|
||||||
isBlack = false;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (isBlack && (c == BLACK)) return; // reject black pixels directly after clearScreen()
|
if ((c == BLACK) && (getBitFromArray(_ledsDirty, pix) == false)) return; // ignore black if pixel is already black
|
||||||
|
setBitInArray(_ledsDirty, pix, c != BLACK); // dirty = true means "color is not BLACK"
|
||||||
|
|
||||||
#ifndef NO_CIE1931
|
#ifndef NO_CIE1931
|
||||||
c = unGamma24(c); // to use the driver linear brightness feature, we first need to undo WLED gamma correction
|
c = unGamma24(c); // to use the driver linear brightness feature, we first need to undo WLED gamma correction
|
||||||
#endif
|
#endif
|
||||||
@@ -776,7 +782,6 @@ void __attribute__((hot)) BusHub75Matrix::setPixelColor(uint16_t pix, uint32_t c
|
|||||||
int y = pix / width;
|
int y = pix / width;
|
||||||
display->drawPixelRGB888(int16_t(x), int16_t(y), r, g, b);
|
display->drawPixelRGB888(int16_t(x), int16_t(y), r, g, b);
|
||||||
}
|
}
|
||||||
isBlack = false;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -785,7 +790,7 @@ uint32_t BusHub75Matrix::getPixelColor(uint16_t pix) const {
|
|||||||
if (_ledBuffer)
|
if (_ledBuffer)
|
||||||
return uint32_t(_ledBuffer[pix].scale8(_bri)) & 0x00FFFFFF; // scale8() is needed to mimic NeoPixelBus, which returns scaled-down colours
|
return uint32_t(_ledBuffer[pix].scale8(_bri)) & 0x00FFFFFF; // scale8() is needed to mimic NeoPixelBus, which returns scaled-down colours
|
||||||
else
|
else
|
||||||
return BLACK;
|
return getBitFromArray(_ledsDirty, pix) ? DARKGREY: BLACK; // just a hack - we only know if the pixel is black or not
|
||||||
}
|
}
|
||||||
|
|
||||||
void BusHub75Matrix::setBrightness(uint8_t b, bool immediate) {
|
void BusHub75Matrix::setBrightness(uint8_t b, bool immediate) {
|
||||||
@@ -797,7 +802,6 @@ void __attribute__((hot)) BusHub75Matrix::show(void) {
|
|||||||
if (!_valid) return;
|
if (!_valid) return;
|
||||||
if (_ledBuffer) {
|
if (_ledBuffer) {
|
||||||
// write out buffered LEDs
|
// write out buffered LEDs
|
||||||
bool haveDirtyBits = (_ledsDirty != nullptr);
|
|
||||||
bool isFourScan = (fourScanPanel != nullptr);
|
bool isFourScan = (fourScanPanel != nullptr);
|
||||||
unsigned width = isFourScan ? fourScanPanel->width() : display->width();
|
unsigned width = isFourScan ? fourScanPanel->width() : display->width();
|
||||||
unsigned height = isFourScan ? fourScanPanel->height() : display->height();
|
unsigned height = isFourScan ? fourScanPanel->height() : display->height();
|
||||||
@@ -806,7 +810,7 @@ void __attribute__((hot)) BusHub75Matrix::show(void) {
|
|||||||
|
|
||||||
size_t pix = 0; // running pixel index
|
size_t pix = 0; // running pixel index
|
||||||
for (int y=0; y<height; y++) for (int x=0; x<width; x++) {
|
for (int y=0; y<height; y++) for (int x=0; x<width; x++) {
|
||||||
if ( !haveDirtyBits || (getBitFromArray(_ledsDirty, pix) == true)) { // only repaint the "dirty" pixels
|
if (getBitFromArray(_ledsDirty, pix) == true) { // only repaint the "dirty" pixels
|
||||||
uint32_t c = uint32_t(_ledBuffer[pix]) & 0x00FFFFFF; // get RGB color, removing FastLED "alpha" component
|
uint32_t c = uint32_t(_ledBuffer[pix]) & 0x00FFFFFF; // get RGB color, removing FastLED "alpha" component
|
||||||
#ifndef NO_CIE1931
|
#ifndef NO_CIE1931
|
||||||
c = unGamma24(c); // to use the driver linear brightness feature, we first need to undo WLED gamma correction
|
c = unGamma24(c); // to use the driver linear brightness feature, we first need to undo WLED gamma correction
|
||||||
@@ -819,14 +823,14 @@ void __attribute__((hot)) BusHub75Matrix::show(void) {
|
|||||||
}
|
}
|
||||||
pix ++;
|
pix ++;
|
||||||
}
|
}
|
||||||
if (haveDirtyBits) setBitArray(_ledsDirty, _len, false); // reset dirty bits
|
setBitArray(_ledsDirty, _len, false); // buffer shown - reset all dirty bits
|
||||||
}
|
}
|
||||||
|
|
||||||
if(mxconfig.double_buff) {
|
if(mxconfig.double_buff) {
|
||||||
display->flipDMABuffer(); // Show the back buffer, set current output buffer to the back (i.e. no longer being sent to LED panels)
|
display->flipDMABuffer(); // Show the back buffer, set current output buffer to the back (i.e. no longer being sent to LED panels)
|
||||||
// while(!previousBufferFree) delay(1); // experimental - Wait before we allow any writing to the buffer. Stop flicker.
|
// while(!previousBufferFree) delay(1); // experimental - Wait before we allow any writing to the buffer. Stop flicker.
|
||||||
display->clearScreen(); // Now clear the back-buffer
|
display->clearScreen(); // Now clear the back-buffer
|
||||||
isBlack = true;
|
setBitArray(_ledsDirty, _len, false); // dislay buffer is blank - reset all dirty bits
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -840,7 +844,6 @@ void BusHub75Matrix::cleanup() {
|
|||||||
delete display;
|
delete display;
|
||||||
display = nullptr;
|
display = nullptr;
|
||||||
fourScanPanel = nullptr;
|
fourScanPanel = nullptr;
|
||||||
isBlack = false;
|
|
||||||
if (_ledBuffer != nullptr) free(_ledBuffer); _ledBuffer = nullptr;
|
if (_ledBuffer != nullptr) free(_ledBuffer); _ledBuffer = nullptr;
|
||||||
if (_ledsDirty != nullptr) free(_ledsDirty); _ledsDirty = nullptr;
|
if (_ledsDirty != nullptr) free(_ledsDirty); _ledsDirty = nullptr;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -389,7 +389,6 @@ class BusHub75Matrix : public Bus {
|
|||||||
MatrixPanel_I2S_DMA *display = nullptr;
|
MatrixPanel_I2S_DMA *display = nullptr;
|
||||||
VirtualMatrixPanel *fourScanPanel = nullptr;
|
VirtualMatrixPanel *fourScanPanel = nullptr;
|
||||||
HUB75_I2S_CFG mxconfig;
|
HUB75_I2S_CFG mxconfig;
|
||||||
bool isBlack = false;
|
|
||||||
CRGB *_ledBuffer = nullptr;
|
CRGB *_ledBuffer = nullptr;
|
||||||
byte *_ledsDirty = nullptr;
|
byte *_ledsDirty = nullptr;
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user