diff --git a/src/Layer.h b/src/Layer.h index 8c46c56..f34f371 100644 --- a/src/Layer.h +++ b/src/Layer.h @@ -45,6 +45,9 @@ class SM_Layer { virtual int getRequestedBrightnessShifts(); virtual bool isLayerChanged(); + virtual void enable(bool en) { layerEnabled=en; } + virtual bool isEnabled() { return layerEnabled; } + SM_Layer * nextLayer; protected: @@ -57,6 +60,8 @@ class SM_Layer { // the local dimensions of this layer with rotation applied, local x=0,y=0 in the upper left uint16_t localWidth, localHeight; uint8_t refreshRate; + + bool layerEnabled=true; private: }; diff --git a/src/Layer_Indexed.h b/src/Layer_Indexed.h index 2a39616..658f437 100644 --- a/src/Layer_Indexed.h +++ b/src/Layer_Indexed.h @@ -29,14 +29,22 @@ #define SM_INDEXED_OPTIONS_NONE 0 +enum SMIndexedLayerColourDepth : uint32_t +{ + ONEBIT=0, + TWOBITS=1, + FOURBITS=3, + EIGHTBITS=7 +}; + // font #include "MatrixFontCommon.h" template class SMLayerIndexed : public SM_Layer { public: - SMLayerIndexed(uint8_t * bitmap, uint16_t width, uint16_t height); - SMLayerIndexed(uint16_t width, uint16_t height); + SMLayerIndexed(uint8_t * bitmap, uint16_t width, uint16_t height, SMIndexedLayerColourDepth colourDepthBits=ONEBIT); + SMLayerIndexed(uint16_t width, uint16_t height, SMIndexedLayerColourDepth colourDepthBits=ONEBIT); void begin(void); void frameRefreshCallback(); void fillRefreshRow(uint16_t hardwareY, rgb48 refreshRow[], int brightnessShifts = 0); @@ -51,10 +59,10 @@ class SMLayerIndexed : public SM_Layer { void drawPixel(int16_t x, int16_t y, uint8_t index); void setFont(fontChoices newFont); // todo: handle index (draw transparent) - void drawChar(int16_t x, int16_t y, uint8_t index, char character); - void drawString(int16_t x, int16_t y, uint8_t index, const char text []); - void drawMonoBitmap(int16_t x, int16_t y, uint8_t width, uint8_t height, uint8_t index, uint8_t *bitmap); - + void drawChar(int16_t x, int16_t y, uint8_t index, char character, uint8_t backgroundIndex=0); + void drawString(int16_t x, int16_t y, uint8_t index, const char text [], uint8_t backgroundIndex=0); + void drawMonoBitmap(int16_t x, int16_t y, uint8_t width, uint8_t height, uint8_t index, uint8_t *bitmap, uint8_t backgroundIndex=0); + protected: // todo: move somewhere else static bool getBitmapPixelAtXY(uint8_t x, uint8_t y, uint8_t width, uint8_t height, const uint8_t *bitmap); @@ -66,27 +74,9 @@ class SMLayerIndexed : public SM_Layer { // double buffered to prevent flicker while drawing uint8_t * indexedBitmap; - - RGB color; - unsigned char currentframe = 0; - char text[textLayerMaxStringLength]; - - unsigned char textlen; - int scrollcounter = 0; - const bitmap_font *scrollFont = &apple5x7; - - int fontTopOffset = 1; - int fontLeftOffset = 1; - bool majorScrollFontChange = false; + RGB *colourLookup; bool ccEnabled = sizeof(RGB) <= 3 ? true : false; - ScrollMode scrollmode = bounceForward; - unsigned char framesperscroll = 4; - - // these variables describe the text bitmap: size, location on the screen, and bounds of where it moves - unsigned int textWidth; - int scrollMin, scrollMax; - int scrollPosition; // keeping track of drawing buffers volatile unsigned char currentDrawBuffer; @@ -95,6 +85,8 @@ class SMLayerIndexed : public SM_Layer { void handleBufferSwap(void); bitmap_font *layerFont = (bitmap_font *) &apple3x5; + private: + const SMIndexedLayerColourDepth indexColourDepth; }; #include "Layer_Indexed_Impl.h" diff --git a/src/Layer_Indexed_Impl.h b/src/Layer_Indexed_Impl.h index 0aa83d1..5f2acb8 100644 --- a/src/Layer_Indexed_Impl.h +++ b/src/Layer_Indexed_Impl.h @@ -23,31 +23,34 @@ #include -#define INDEXED_BUFFER_ROW_SIZE (this->localWidth / 8) +#define INDEXED_BUFFER_ROW_SIZE (this->localWidth * (indexColourDepth+1) / 8 ) #define INDEXED_BUFFER_SIZE (INDEXED_BUFFER_ROW_SIZE * this->localHeight) template -SMLayerIndexed::SMLayerIndexed(uint8_t * bitmap, uint16_t width, uint16_t height) { +SMLayerIndexed::SMLayerIndexed(uint8_t * bitmap, uint16_t width, uint16_t height, SMIndexedLayerColourDepth colourDepthBits) : indexColourDepth(colourDepthBits) { // size of bitmap is 2 * INDEXED_BUFFER_SIZE + //indexColourDepth=colourDepthBits; indexedBitmap = bitmap; this->matrixWidth = width; this->matrixHeight = height; - this->color = rgb48(0xffff, 0xffff, 0xffff); + colourLookup=new RGB[(2< -SMLayerIndexed::SMLayerIndexed(uint16_t width, uint16_t height) { +SMLayerIndexed::SMLayerIndexed(uint16_t width, uint16_t height, SMIndexedLayerColourDepth colourDepthBits) : indexColourDepth(colourDepthBits) { // size of bitmap is 2 * INDEXED_BUFFER_SIZE - indexedBitmap = (uint8_t*)malloc(2 * width * (height / 8)); + indexedBitmap = (uint8_t*)malloc(2 * width * (height / (8/(indexColourDepth+1)))); #ifdef ESP32 assert(indexedBitmap != NULL); #else //this->assert(indexedBitmap != NULL); #endif - memset(indexedBitmap, 0x00, 2 * width * (height / 8)); + memset(indexedBitmap, 0x00, 2 * width * (height / (8/(indexColourDepth+1)))); this->matrixWidth = width; this->matrixHeight = height; - this->color = rgb48(0xffff, 0xffff, 0xffff); + colourLookup=new RGB[(2< @@ -65,7 +68,7 @@ void SMLayerIndexed::frameRefreshCallback(void) { // returns true and copies color to xyPixel if pixel is opaque, returns false if not template template bool SMLayerIndexed::getPixel(uint16_t hardwareX, uint16_t hardwareY, RGB_OUT &xyPixel) { - uint16_t localScreenX, localScreenY; + uint32_t localScreenX, localScreenY; // convert hardware x/y to the pixel in the local screen switch( this->layerRotation ) { @@ -90,20 +93,51 @@ bool SMLayerIndexed::getPixel(uint16_t hardwareX, uint16_t har return false; }; - uint8_t bitmask = 0x80 >> (localScreenX % 8); + uint32_t bitmask=0; + uint32_t indxshift;//=(localScreenX % (8/(indexColourDepth+1))); + uint32_t xbytefind; + switch(indexColourDepth) + { + default: + case ONEBIT: + indxshift=localScreenX & 7; + bitmask=0x80 >> indxshift; + xbytefind=localScreenX >> 3; + indxshift=7-indxshift; + break; + case TWOBITS: + indxshift=localScreenX & 3; + bitmask=0xC0 >> (indxshift << 1); + xbytefind=localScreenX >> 2; + indxshift=6-indxshift; + break; + case FOURBITS: + indxshift=localScreenX & 1; + bitmask=0xF0 >> (indxshift << 2); + xbytefind=localScreenX >> 1; + indxshift=4-indxshift; + break; + case EIGHTBITS: + bitmask=0xFF; + indxshift=0; + xbytefind=localScreenX; + } - if (indexedBitmap[(currentRefreshBuffer * INDEXED_BUFFER_SIZE) + (localScreenY * INDEXED_BUFFER_ROW_SIZE) + (localScreenX/8)] & bitmask) { - xyPixel = color; + uint32_t indx=(indexedBitmap[(currentRefreshBuffer * INDEXED_BUFFER_SIZE) + (localScreenY * INDEXED_BUFFER_ROW_SIZE) + xbytefind] & bitmask); + if (indx) { + xyPixel = colourLookup[(indx>>indxshift)-1]; return true; } return false; } + + template void SMLayerIndexed::fillRefreshRow(uint16_t hardwareY, rgb48 refreshRow[], int brightnessShifts) { RGB currentPixel; - int i; + uint32_t i; if(this->ccEnabled) { for(i=0; imatrixWidth; i++) { @@ -126,7 +160,7 @@ void SMLayerIndexed::fillRefreshRow(uint16_t hardwareY, rgb48 template void SMLayerIndexed::fillRefreshRow(uint16_t hardwareY, rgb24 refreshRow[], int brightnessShifts) { RGB currentPixel; - int i; + uint32_t i; if(this->ccEnabled) { for(i=0; imatrixWidth; i++) { @@ -148,7 +182,10 @@ void SMLayerIndexed::fillRefreshRow(uint16_t hardwareY, rgb24 template void SMLayerIndexed::setIndexedColor(uint8_t index, const RGB & newColor) { - color = newColor; + if(index>(2< @@ -158,11 +195,27 @@ void SMLayerIndexed::enableColorCorrection(bool enabled) { template void SMLayerIndexed::fillScreen(uint8_t index) { - uint8_t fillValue; + + uint8_t fillValue=0; + if(index) - fillValue = 0xFF; - else - fillValue = 0x00; + { + switch(indexColourDepth) + { + case ONEBIT: + fillValue=0xFF; + break; + case TWOBITS: + fillValue=(index & 3) + ((index & 3)<<2) + ((index & 3)<<4) + ((index & 3)<<6); + break; + case FOURBITS: + fillValue=(index & 15) + ((index & 15)<<4); + break; + case EIGHTBITS: + fillValue=index; + break; + } + } memset(&indexedBitmap[currentDrawBuffer*INDEXED_BUFFER_SIZE], fillValue, INDEXED_BUFFER_SIZE); } @@ -213,33 +266,52 @@ void SMLayerIndexed::handleBufferSwap(void) { template void SMLayerIndexed::drawPixel(int16_t x, int16_t y, uint8_t index) { - uint8_t tempBitmask; if(x < 0 || x >= this->localWidth || y < 0 || y >= this->localHeight) return; - if(index) { - tempBitmask = 0x80 >> (x%8); - indexedBitmap[currentDrawBuffer*INDEXED_BUFFER_SIZE + (y * INDEXED_BUFFER_ROW_SIZE) + (x/8)] |= tempBitmask; - } else { - tempBitmask = ~(0x80 >> (x%8)); - indexedBitmap[currentDrawBuffer*INDEXED_BUFFER_SIZE + (y * INDEXED_BUFFER_ROW_SIZE) + (x/8)] &= tempBitmask; + uint32_t bitmask; + uint32_t indxshift; + uint32_t arrayIndex; + + switch(indexColourDepth) + { + case ONEBIT: + arrayIndex=currentDrawBuffer*INDEXED_BUFFER_SIZE + (y * INDEXED_BUFFER_ROW_SIZE) + (x >> 3); + indxshift=(x & 7); + bitmask=0x80 >> indxshift; + indexedBitmap[arrayIndex]=(indexedBitmap[arrayIndex] & ~bitmask) | ((index & 1) << (7-indxshift)); + break; + case TWOBITS: + arrayIndex=currentDrawBuffer*INDEXED_BUFFER_SIZE + (y * INDEXED_BUFFER_ROW_SIZE) + (x >> 2); + indxshift=(2*(x & 3)); + bitmask=0xC0 >> indxshift; + indexedBitmap[arrayIndex]=(indexedBitmap[arrayIndex] & ~bitmask) | ((index & 3) << (6-indxshift)); + break; + case FOURBITS: + arrayIndex=currentDrawBuffer*INDEXED_BUFFER_SIZE + (y * INDEXED_BUFFER_ROW_SIZE) + (x >> 1); + indxshift=(4*(x & 1)); + bitmask=0xF0 >> indxshift; + indexedBitmap[arrayIndex]=(indexedBitmap[arrayIndex] & ~bitmask) | ((index & 15) << (4-indxshift)); + break; + case EIGHTBITS: + arrayIndex=currentDrawBuffer*INDEXED_BUFFER_SIZE + (y * INDEXED_BUFFER_ROW_SIZE) + x; + indexedBitmap[arrayIndex]=index; } } template void SMLayerIndexed::setFont(fontChoices newFont) { layerFont = (bitmap_font *)fontLookup(newFont); - majorScrollFontChange = true; } template -void SMLayerIndexed::drawChar(int16_t x, int16_t y, uint8_t index, char character) { +void SMLayerIndexed::drawChar(int16_t x, int16_t y, uint8_t index, char character, uint8_t backgroundIndex) { uint8_t tempBitmask; - int k; + int32_t k; // only draw if character is on the screen - if (x + scrollFont->Width < 0 || x >= this->localWidth) { + if (x + layerFont->Width < 0 || x >= this->localWidth) { return; } @@ -249,36 +321,41 @@ void SMLayerIndexed::drawChar(int16_t x, int16_t y, uint8_t in if (k >= this->localHeight) return; tempBitmask = getBitmapFontRowAtXY(character, k - y, layerFont); - if (x < 0) { - indexedBitmap[currentDrawBuffer*INDEXED_BUFFER_SIZE + (k * INDEXED_BUFFER_ROW_SIZE) + 0] |= tempBitmask << -x; - } else { - indexedBitmap[currentDrawBuffer*INDEXED_BUFFER_SIZE + (k * INDEXED_BUFFER_ROW_SIZE) + (x/8)] |= tempBitmask >> (x%8); - // do two writes if the shifted 8-bit wide bitmask is still on the screen - if(x + 8 < this->localWidth && x % 8) - indexedBitmap[currentDrawBuffer*INDEXED_BUFFER_SIZE + (k * INDEXED_BUFFER_ROW_SIZE) + (x/8) + 1] |= tempBitmask << (8-(x%8)); - } + drawMonoBitmap(x,k,8,1,index,&tempBitmask,backgroundIndex); + + + // if (x < 0) { + // indexedBitmap[currentDrawBuffer*INDEXED_BUFFER_SIZE + (k * INDEXED_BUFFER_ROW_SIZE) + 0] |= tempBitmask << -x; + // } else { + // indexedBitmap[currentDrawBuffer*INDEXED_BUFFER_SIZE + (k * INDEXED_BUFFER_ROW_SIZE) + (x/8)] |= tempBitmask >> (x%8); + // // do two writes if the shifted 8-bit wide bitmask is still on the screen + // if(x + 8 < this->localWidth && x % 8) + // indexedBitmap[currentDrawBuffer*INDEXED_BUFFER_SIZE + (k * INDEXED_BUFFER_ROW_SIZE) + (x/8) + 1] |= tempBitmask << (8-(x%8)); + // } } } template -void SMLayerIndexed::drawString(int16_t x, int16_t y, uint8_t index, const char text []) { - int offset = 0; +void SMLayerIndexed::drawString(int16_t x, int16_t y, uint8_t index, const char text [],uint8_t backgroundIndex) { + uint32_t offset = 0; char character; while ((character = text[offset++]) != '\0') { - drawChar(x, y, index, character); + drawChar(x, y, index, character,backgroundIndex); x += layerFont->Width; } } template -void SMLayerIndexed::drawMonoBitmap(int16_t x, int16_t y, uint8_t width, uint8_t height, uint8_t index, uint8_t *bitmap) { - int xcnt, ycnt; +void SMLayerIndexed::drawMonoBitmap(int16_t x, int16_t y, uint8_t width, uint8_t height, uint8_t index, uint8_t *bitmap,uint8_t backgroundIndex) { + uint32_t xcnt, ycnt; for (ycnt = 0; ycnt < height; ycnt++) { for (xcnt = 0; xcnt < width; xcnt++) { if (getBitmapPixelAtXY(xcnt, ycnt, width, height, bitmap)) { drawPixel(x + xcnt, y + ycnt, index); + } else { + drawPixel(x + xcnt, y + ycnt, backgroundIndex); } } } diff --git a/src/MatrixHardware_ESP32_HUB75AdapterLite_V0.h b/src/MatrixHardware_ESP32_HUB75AdapterLite_V0.h index 30e5963..ddaaa92 100755 --- a/src/MatrixHardware_ESP32_HUB75AdapterLite_V0.h +++ b/src/MatrixHardware_ESP32_HUB75AdapterLite_V0.h @@ -37,7 +37,9 @@ #define GPIOPINOUT HUB75_ADAPTER_LITE_V0_PINOUT +#ifndef SM_INTERNAL #pragma message "MatrixHardware: HUB75 Adapter Lite V0 pinout" +#endif //Upper half RGB #define BIT_R1 (1<<0) diff --git a/src/MatrixHardware_ESP32_HUB75Adapter_SMT.h b/src/MatrixHardware_ESP32_HUB75Adapter_SMT.h index fe448e9..1a9df10 100755 --- a/src/MatrixHardware_ESP32_HUB75Adapter_SMT.h +++ b/src/MatrixHardware_ESP32_HUB75Adapter_SMT.h @@ -38,8 +38,9 @@ #define GPIOPINOUT HUB75_ADAPTER_V0_SMT_PINOUT - +#ifndef SM_INTERNAL #pragma message "MatrixHardware: HUB75 Adapter V0 SMT pinout" +#endif //Upper half RGB #define BIT_R1 (1<<0) diff --git a/src/MatrixHardware_ESP32_HUB75Adapter_THT.h b/src/MatrixHardware_ESP32_HUB75Adapter_THT.h index 34006a2..548b02d 100755 --- a/src/MatrixHardware_ESP32_HUB75Adapter_THT.h +++ b/src/MatrixHardware_ESP32_HUB75Adapter_THT.h @@ -38,7 +38,9 @@ #define GPIOPINOUT HUB75_ADAPTER_V0_THT_PINOUT +#ifndef SM_INTERNAL #pragma message "MatrixHardware: HUB75 Adapter V0 THT pinout" +#endif //Upper half RGB #define BIT_R1 (1<<0) diff --git a/src/MatrixHardware_ESP32_RGB64x32MatrixPanel-I2S-DMA_default.h b/src/MatrixHardware_ESP32_RGB64x32MatrixPanel-I2S-DMA_default.h index fbc15bb..0428825 100755 --- a/src/MatrixHardware_ESP32_RGB64x32MatrixPanel-I2S-DMA_default.h +++ b/src/MatrixHardware_ESP32_RGB64x32MatrixPanel-I2S-DMA_default.h @@ -37,7 +37,9 @@ #define GPIOPINOUT HUB75_ADAPTER_LITE_V0_PINOUT +#ifndef SM_INTERNAL #pragma message "MatrixHardware: ESP32-RGB64x32MatrixPanel-I2S-DMA default pinout" +#endif //Upper half RGB #define BIT_R1 (1<<0) diff --git a/src/MatrixHardware_ESP32_SmartLedShieldV0.h b/src/MatrixHardware_ESP32_SmartLedShieldV0.h index 85629dc..3833de8 100755 --- a/src/MatrixHardware_ESP32_SmartLedShieldV0.h +++ b/src/MatrixHardware_ESP32_SmartLedShieldV0.h @@ -46,7 +46,9 @@ #define GPIOPINOUT SMARTLED_SHIELD_V0_PINOUT +#ifndef SM_INTERNAL #pragma message "MatrixHardware: ESP32 SmartLED shield V0 pinout" +#endif //Upper half RGB #define BIT_R1 (1<<0) diff --git a/src/MatrixHardware_ESP32_V0.h b/src/MatrixHardware_ESP32_V0.h index 6468950..74c5cf0 100755 --- a/src/MatrixHardware_ESP32_V0.h +++ b/src/MatrixHardware_ESP32_V0.h @@ -67,7 +67,11 @@ #if (GPIOPINOUT == ESP32_JC_RIBBON_PINOUT) + + #ifndef SM_INTERNAL #pragma message "MatrixHardware: Jason Coon ESP32 NodeMCU shield wiring" + #endif + // This pinout takes a ribbon cable and flattens it, pin order is 1, 9, 2, 10 ... // it connects to https://www.tindie.com/products/jasoncoon/16-output-nodemcu-esp32-wifi-ble-led-controller/ // *** WARNING, I cut the trace on Jason's board that went to pin 3, and patched a wire @@ -135,7 +139,10 @@ #define OE_PIN GPIO_NUM_12 #elif (GPIOPINOUT == ESP32_JC_RIBBON_PINOUT_WEMOS) + #ifndef SM_INTERNAL #pragma message "MatrixHardware: Jason Coon ESP32 Wemos/Lolin shield wiring" + #endif + // This pinout takes a ribbon cable and flattens it, pin order is 1, 9, 2, 10 ... // it connects to https://www.tindie.com/products/jasoncoon/16-output-wemos-d32-wifi-ble-led-controller/ // *** WARNING, I cut the trace on Jason's board that went to pin 3, and patched a wire @@ -205,7 +212,9 @@ #elif (GPIOPINOUT == ESP32_FORUM_PINOUT) + #ifndef SM_INTERNAL #pragma message "MatrixHardware: ESP32 forum wiring" + #endif // ADDX is output directly using GPIO #define CLKS_DURING_LATCH 0 @@ -267,7 +276,9 @@ #elif (GPIOPINOUT == HUB75_ADAPTER_PINOUT) + #ifndef SM_INTERNAL #pragma message "MatrixHardware: Hub75 Adapter Pinout" + #endif // ADDX is output directly using GPIO #define CLKS_DURING_LATCH 0 @@ -328,7 +339,9 @@ #define CLK_PIN GPIO_NUM_2 #elif (GPIOPINOUT == ESP32_FORUM_PINOUT_WITH_LATCH) + #ifndef SM_INTERNAL #pragma message "MatrixHardware: ESP32 forum wiring with external 74AHCT373 latch circuit - note untested since 2018, may be broken" + #endif // Note: this is untested since 2018, may be broken @@ -356,7 +369,9 @@ #elif (GPIOPINOUT == SMARTLED_SHIELD_V0_PINOUT) + #ifndef SM_INTERNAL #pragma message "MatrixHardware: ESP32 SmartLED shield V0 pinout" + #endif // ADDX is output on RGB pins and stored in external latch (need multiple of 32-bits for full data struct, so pad 2 CLKs to 4 here) #define MATRIX_I2S_MODE I2S_PARALLEL_BITS_8 @@ -389,7 +404,9 @@ #elif (GPIOPINOUT == HUB75_ADAPTER_LATCH_BREADBOARD_PINOUT) + #ifndef SM_INTERNAL #pragma message "MatrixHardware: HUB75 Adapter Latch Breadboard pinout" + #endif // ADDX is output on RGB pins and stored in external latch (need multiple of 32-bits for full data struct, so pad 2 CLKs to 4 here) #define MATRIX_I2S_MODE I2S_PARALLEL_BITS_8 @@ -422,7 +439,9 @@ #elif (GPIOPINOUT == HUB75_ADAPTER_V0_THT_PINOUT) + #ifndef SM_INTERNAL #pragma message "MatrixHardware: HUB75 Adapter V0 THT pinout" + #endif // ADDX is output on RGB pins and stored in external latch (need multiple of 32-bits for full data struct, so pad 2 CLKs to 4 here) #define MATRIX_I2S_MODE I2S_PARALLEL_BITS_8 @@ -458,7 +477,9 @@ #elif (GPIOPINOUT == HUB75_ADAPTER_V0_SMT_PINOUT) + #ifndef SM_INTERNAL #pragma message "MatrixHardware: HUB75 Adapter V0 SMT pinout" + #endif // ADDX is output on RGB pins and stored in external latch (need multiple of 32-bits for full data struct, so pad 2 CLKs to 4 here) #define MATRIX_I2S_MODE I2S_PARALLEL_BITS_8 diff --git a/src/MatrixHardware_Esp32_AtomLiteApaOnly.h b/src/MatrixHardware_Esp32_AtomLiteApaOnly.h index 5ab4731..62a0301 100644 --- a/src/MatrixHardware_Esp32_AtomLiteApaOnly.h +++ b/src/MatrixHardware_Esp32_AtomLiteApaOnly.h @@ -49,8 +49,9 @@ #define BIT_E (1<<12) - +#ifndef SM_INTERNAL #pragma message "MatrixHardware: Atom Lite Apa102-Only" +#endif // ADDX is output directly using GPIO #define CLKS_DURING_LATCH 0 diff --git a/src/MatrixHardware_Teensy3_ShieldV1toV3.h b/src/MatrixHardware_Teensy3_ShieldV1toV3.h index 3b86247..0f78938 100755 --- a/src/MatrixHardware_Teensy3_ShieldV1toV3.h +++ b/src/MatrixHardware_Teensy3_ShieldV1toV3.h @@ -26,7 +26,9 @@ #ifndef MATRIX_HARDWARE_H #define MATRIX_HARDWARE_H +#ifndef SM_INTERNAL #pragma message "MatrixHardware: SmartMatrix Shield for Teensy 3 V1-V3" +#endif #define COLOR_CHANNELS_PER_PIXEL 3 #define PIXELS_UPDATED_PER_CLOCK 2 diff --git a/src/MatrixHardware_Teensy3_ShieldV4.h b/src/MatrixHardware_Teensy3_ShieldV4.h index 14f46cb..85a6fef 100755 --- a/src/MatrixHardware_Teensy3_ShieldV4.h +++ b/src/MatrixHardware_Teensy3_ShieldV4.h @@ -26,7 +26,9 @@ #ifndef MATRIX_HARDWARE_H #define MATRIX_HARDWARE_H +#ifndef SM_INTERNAL #pragma message "MatrixHardware: SmartLED Shield for Teensy 3 (V4)" +#endif #define DMA_UPDATES_PER_CLOCK 2 #define ADDX_UPDATE_ON_DATA_PINS diff --git a/src/MatrixHardware_Teensy4_ShieldV0.h b/src/MatrixHardware_Teensy4_ShieldV0.h index 6ffb1f5..10ed0e6 100644 --- a/src/MatrixHardware_Teensy4_ShieldV0.h +++ b/src/MatrixHardware_Teensy4_ShieldV0.h @@ -38,7 +38,9 @@ #ifndef MATRIX_HARDWARE_H #define MATRIX_HARDWARE_H +#ifndef SM_INTERNAL #pragma message "MatrixHardware: SmartLED Shield for Teensy 4 V0" +#endif /* an advanced user may need to tweak these values */ diff --git a/src/MatrixHardware_Teensy4_ShieldV4Adapter.h b/src/MatrixHardware_Teensy4_ShieldV4Adapter.h index 8daf6a8..ce03702 100644 --- a/src/MatrixHardware_Teensy4_ShieldV4Adapter.h +++ b/src/MatrixHardware_Teensy4_ShieldV4Adapter.h @@ -44,7 +44,9 @@ #ifndef MATRIX_HARDWARE_H #define MATRIX_HARDWARE_H +#ifndef SM_INTERNAL #pragma message "MatrixHardware: Teensy 4 Adapter attached to SmartLED Shield for Teensy 3 (V4)" +#endif /* an advanced user may need to tweak these values */ diff --git a/src/MatrixHardware_Teensy4_ShieldV4WireMod.h b/src/MatrixHardware_Teensy4_ShieldV4WireMod.h index d872529..9cbd929 100644 --- a/src/MatrixHardware_Teensy4_ShieldV4WireMod.h +++ b/src/MatrixHardware_Teensy4_ShieldV4WireMod.h @@ -41,7 +41,9 @@ #ifndef MATRIX_HARDWARE_H #define MATRIX_HARDWARE_H +#ifndef SM_INTERNAL #pragma message "MatrixHardware: Teensy 4 Wired to SmartLED Shield for Teensy 3 (V4)" +#endif /* an advanced user may need to tweak these values */ diff --git a/src/MatrixHardware_Teensy4_ShieldV5.h b/src/MatrixHardware_Teensy4_ShieldV5.h index 750ff2c..2769464 100644 --- a/src/MatrixHardware_Teensy4_ShieldV5.h +++ b/src/MatrixHardware_Teensy4_ShieldV5.h @@ -38,7 +38,9 @@ #ifndef MATRIX_HARDWARE_H #define MATRIX_HARDWARE_H +#ifndef SM_INTERNAL #pragma message "MatrixHardware: SmartLED Shield for Teensy 4 (V5)" +#endif /* an advanced user may need to tweak these values */ diff --git a/src/MatrixTeensy4Hub75Calc_Impl.h b/src/MatrixTeensy4Hub75Calc_Impl.h index 2b23f70..d0de50b 100644 --- a/src/MatrixTeensy4Hub75Calc_Impl.h +++ b/src/MatrixTeensy4Hub75Calc_Impl.h @@ -390,54 +390,57 @@ FASTRUN INLINE void SmartMatrixHub75Calc::baseLayer; int y0, y1; // positions of the two rows we need while (templayer) { - for (i = 0; i < MATRIX_STACK_HEIGHT; i++) { - // Z-shape, bottom to top - if (!(optionFlags & SMARTMATRIX_OPTIONS_C_SHAPE_STACKING) && - (optionFlags & SMARTMATRIX_OPTIONS_BOTTOM_TO_TOP_STACKING)) { - // Bottom to Top Stacking: load data buffer with top panels first, bottom panels last, as top panels are at the furthest end of the chain (initial data is shifted out the furthest) - y0 = currentRow + multiRowRefreshRowOffset + i * MATRIX_PANEL_HEIGHT; - y1 = y0 + ROW_PAIR_OFFSET; - // Z-shape, top to bottom - } else if (!(optionFlags & SMARTMATRIX_OPTIONS_C_SHAPE_STACKING) && - !(optionFlags & SMARTMATRIX_OPTIONS_BOTTOM_TO_TOP_STACKING)) { - // Top to Bottom Stacking: load data buffer with bottom panels first, top panels last, as bottom panels are at the furthest end of the chain (initial data is shifted out the furthest) - y0 = currentRow + multiRowRefreshRowOffset + (MATRIX_STACK_HEIGHT - i - 1) * MATRIX_PANEL_HEIGHT; - y1 = y0 + ROW_PAIR_OFFSET; - // C-shape, bottom to top - } else if ((optionFlags & SMARTMATRIX_OPTIONS_C_SHAPE_STACKING) && - (optionFlags & SMARTMATRIX_OPTIONS_BOTTOM_TO_TOP_STACKING)) { - // C-shaped stacking: alternate direction of filling (or loading) for each matrixwidth-sized stack, stack closest to Teensy is right-side up - // swap row order from top to bottom for each stack (tempRow1 filled with top half of panel, tempRow0 filled with bottom half when upside down) - // the last stack is always right-side up, figure out orientation of other stacks based on that - // Bottom to Top Stacking: load data buffer with top panels first, bottom panels last, as top panels are at the furthest end of the chain (initial data is shifted out the furthest) - - // is i the last stack, or an even number of stacks away from the last stack? - if((i % 2) == ((MATRIX_STACK_HEIGHT - 1) % 2)) { - y0 = currentRow + multiRowRefreshRowOffset + (i) * MATRIX_PANEL_HEIGHT; + if(templayer->isEnabled()) + { + for (i = 0; i < MATRIX_STACK_HEIGHT; i++) { + // Z-shape, bottom to top + if (!(optionFlags & SMARTMATRIX_OPTIONS_C_SHAPE_STACKING) && + (optionFlags & SMARTMATRIX_OPTIONS_BOTTOM_TO_TOP_STACKING)) { + // Bottom to Top Stacking: load data buffer with top panels first, bottom panels last, as top panels are at the furthest end of the chain (initial data is shifted out the furthest) + y0 = currentRow + multiRowRefreshRowOffset + i * MATRIX_PANEL_HEIGHT; y1 = y0 + ROW_PAIR_OFFSET; - } else { - y1 = (MATRIX_SCAN_MOD - currentRow + multiRowRefreshRowOffset - 1) + (i) * MATRIX_PANEL_HEIGHT; - y0 = y1 + ROW_PAIR_OFFSET; - } - // C-shape, top to bottom - } else if ((optionFlags & SMARTMATRIX_OPTIONS_C_SHAPE_STACKING) && - !(optionFlags & SMARTMATRIX_OPTIONS_BOTTOM_TO_TOP_STACKING)) { - // C-shaped stacking: alternate direction of filling (or loading) for each matrixwidth-sized stack, stack closest to Teensy is right-side up - // swap row order from top to bottom for each stack (tempRow1 filled with top half of panel, tempRow0 filled with bottom half when upside down) - // the last stack is always right-side up, figure out orientation of other stacks based on that - // Top to Bottom Stacking: load data buffer with bottom panels first, top panels last, as bottom panels are at the furthest end of the chain (initial data is shifted out the furthest) - - // is i the last stack, or an even number of stacks away from the last stack? - if((i % 2) == ((MATRIX_STACK_HEIGHT - 1) % 2)) { + // Z-shape, top to bottom + } else if (!(optionFlags & SMARTMATRIX_OPTIONS_C_SHAPE_STACKING) && + !(optionFlags & SMARTMATRIX_OPTIONS_BOTTOM_TO_TOP_STACKING)) { + // Top to Bottom Stacking: load data buffer with bottom panels first, top panels last, as bottom panels are at the furthest end of the chain (initial data is shifted out the furthest) y0 = currentRow + multiRowRefreshRowOffset + (MATRIX_STACK_HEIGHT - i - 1) * MATRIX_PANEL_HEIGHT; y1 = y0 + ROW_PAIR_OFFSET; - } else { - y1 = (MATRIX_SCAN_MOD - currentRow + multiRowRefreshRowOffset - 1) + (MATRIX_STACK_HEIGHT - i - 1) * MATRIX_PANEL_HEIGHT; - y0 = y1 + ROW_PAIR_OFFSET; + // C-shape, bottom to top + } else if ((optionFlags & SMARTMATRIX_OPTIONS_C_SHAPE_STACKING) && + (optionFlags & SMARTMATRIX_OPTIONS_BOTTOM_TO_TOP_STACKING)) { + // C-shaped stacking: alternate direction of filling (or loading) for each matrixwidth-sized stack, stack closest to Teensy is right-side up + // swap row order from top to bottom for each stack (tempRow1 filled with top half of panel, tempRow0 filled with bottom half when upside down) + // the last stack is always right-side up, figure out orientation of other stacks based on that + // Bottom to Top Stacking: load data buffer with top panels first, bottom panels last, as top panels are at the furthest end of the chain (initial data is shifted out the furthest) + + // is i the last stack, or an even number of stacks away from the last stack? + if((i % 2) == ((MATRIX_STACK_HEIGHT - 1) % 2)) { + y0 = currentRow + multiRowRefreshRowOffset + (i) * MATRIX_PANEL_HEIGHT; + y1 = y0 + ROW_PAIR_OFFSET; + } else { + y1 = (MATRIX_SCAN_MOD - currentRow + multiRowRefreshRowOffset - 1) + (i) * MATRIX_PANEL_HEIGHT; + y0 = y1 + ROW_PAIR_OFFSET; + } + // C-shape, top to bottom + } else if ((optionFlags & SMARTMATRIX_OPTIONS_C_SHAPE_STACKING) && + !(optionFlags & SMARTMATRIX_OPTIONS_BOTTOM_TO_TOP_STACKING)) { + // C-shaped stacking: alternate direction of filling (or loading) for each matrixwidth-sized stack, stack closest to Teensy is right-side up + // swap row order from top to bottom for each stack (tempRow1 filled with top half of panel, tempRow0 filled with bottom half when upside down) + // the last stack is always right-side up, figure out orientation of other stacks based on that + // Top to Bottom Stacking: load data buffer with bottom panels first, top panels last, as bottom panels are at the furthest end of the chain (initial data is shifted out the furthest) + + // is i the last stack, or an even number of stacks away from the last stack? + if((i % 2) == ((MATRIX_STACK_HEIGHT - 1) % 2)) { + y0 = currentRow + multiRowRefreshRowOffset + (MATRIX_STACK_HEIGHT - i - 1) * MATRIX_PANEL_HEIGHT; + y1 = y0 + ROW_PAIR_OFFSET; + } else { + y1 = (MATRIX_SCAN_MOD - currentRow + multiRowRefreshRowOffset - 1) + (MATRIX_STACK_HEIGHT - i - 1) * MATRIX_PANEL_HEIGHT; + y0 = y1 + ROW_PAIR_OFFSET; + } } + templayer->fillRefreshRow(y0, &tempRow0[i * matrixWidth]); + templayer->fillRefreshRow(y1, &tempRow1[i * matrixWidth]); } - templayer->fillRefreshRow(y0, &tempRow0[i * matrixWidth]); - templayer->fillRefreshRow(y1, &tempRow1[i * matrixWidth]); } templayer = templayer->nextLayer; } diff --git a/src/SmartMatrix.h b/src/SmartMatrix.h index 8a76580..4914637 100644 --- a/src/SmartMatrix.h +++ b/src/SmartMatrix.h @@ -162,6 +162,12 @@ typedef RGB_TYPE(storage_depth) SM_RGB; \ static uint8_t layer_name##Bitmap[2 * width * (height / 8)]; \ static SMLayerIndexed layer_name(layer_name##Bitmap, width, height) + + #define SMARTMATRIX_ALLOCATE_INDEXED_LAYER_EXTENDED(layer_name, width, height, storage_depth, indexed_options, index_colour_depth) \ + typedef RGB_TYPE(storage_depth) SM_RGB; \ + static uint8_t layer_name##Bitmap[2 * width * (height / (8/(index_colour_depth+1)))]; \ + static SMLayerIndexed layer_name(layer_name##Bitmap, width, height,index_colour_depth) + #endif #endif