diff --git a/Layer.cpp b/Layer.cpp deleted file mode 100644 index aa8dc1c..0000000 --- a/Layer.cpp +++ /dev/null @@ -1,338 +0,0 @@ -/** - * Experimental layer class to do play with pixel in an off-screen buffer before painting to the DMA - * - * Requires FastLED - * - * Faptastic 2020 - **/ - -#include "Layer.h" - -// For adafruit -void Layer::drawPixel(int16_t x, int16_t y, uint16_t color) { - - // 565 color conversion - uint8_t r = ((((color >> 11) & 0x1F) * 527) + 23) >> 6; - uint8_t g = ((((color >> 5) & 0x3F) * 259) + 33) >> 6; - uint8_t b = (((color & 0x1F) * 527) + 23) >> 6; - - drawPixel(x, y, CRGB(r,g,b)); -} - -void Layer::drawPixel(int16_t x, int16_t y, int r, int g, int b) { - drawPixel(x, y, CRGB(r,g,b)); -} - -void Layer::drawPixel(int16_t x, int16_t y, CRGB color) { - - if( x >= LAYER_WIDTH || x < 0) return; // 0; - if( y >= LAYER_HEIGHT || y < 0) return; // 0; - - pixels->data[y][x] = color; - //pixel[XY(x,y)] = color; -} - -void Layer::dim(byte value) { - - // nscale8 max value is 255, or it'll flip back to 0 - // (documentation is wrong when it says x/256), it's actually x/255 - for (int y = 0; y < LAYER_HEIGHT; y++) { - for (int x = 0; x < LAYER_WIDTH; x++) { - pixels->data[y][x].nscale8(value); - }} -// for (int i = 0; i < NUM_PIXELS; i++) pixel[i].nscale8(value); - -} - -void Layer::clear() { - - memset(pixels, BLACK_BACKGROUND_PIXEL_COLOUR, sizeof(layerPixels) ); -} - -void Layer::display() { - - CRGB _pixel = 0 ; - for (int y = 0; y < LAYER_HEIGHT; y++) { - for (int x = 0; x < LAYER_WIDTH; x++) - { - //_pixel = pixel[XY(x, y)]; - _pixel = pixels->data[y][x]; - - matrix->drawPixelRGB888( x, y, _pixel.r, _pixel.g, _pixel.b); - - /* - if ( !transparency_enabled ){ - matrix->drawPixelRGB888( x, y, _pixel.r, _pixel.g, _pixel.b); - } else { - if (_pixel != transparency_colour) { - matrix->drawPixelRGB888( x, y, _pixel.r, _pixel.g, _pixel.b); - } - } - */ - } // end loop to copy fast led to the dma matrix - } - -} // display - -void Layer::overridePixelColor(int r, int g, int b) { - CRGB _pixel = 0 ; - for (int y = 0; y < LAYER_HEIGHT; y++) { - for (int x = 0; x < LAYER_WIDTH; x++) - { - //_pixel = pixel[XY(x, y)]; - _pixel = pixels->data[y][x]; - - if (_pixel != transparency_colour) { - matrix->drawPixelRGB888( x, y, _pixel.r, _pixel.g, _pixel.b); - } - - } // end loop to copy fast led to the dma matrix - } -} - - -// default value is in definition -void Layer::drawCentreText(const char *buf, textPosition textPos, const GFXfont *f, CRGB color, int yadjust) -{ - int16_t x1, y1; - uint16_t w, h; - - setTextWrap(false); - - if (f) { // Font struct pointer passed in? - setFont((GFXfont *)f); - } else { // NULL passed. Current font struct defined? - setFont(); // use default - } - - // getTextBounds isn't correct for variable width fonts - getTextBounds(buf, 0, 0, &x1, &y1, &w, &h); //calc width of new string - - //Serial.printf("The width of the text is %d pixels, the height is %d pixels.\n", w,h); - - /* - - From: https://learn.adafruit.com/adafruit-gfx-graphics-library/using-fonts - - For example, whereas the cursor position when printing with the classic font identified - the top-left corner of the character cell, with new fonts the cursor position indicates the baseline — - the bottom-most row — of subsequent text. Characters may vary in size and width, and don’t - necessarily begin at the exact cursor column (as in below, this character starts one pixel - left of the cursor, but others may be on or to the right of it). - */ - - if (!f) { - if (textPos == TOP) { - setCursor((LAYER_WIDTH - w) / 2, 0); // top - } else if (textPos == BOTTOM) { - setCursor((LAYER_WIDTH - w) / 2, LAYER_HEIGHT - h); - } else { // middle - setCursor((LAYER_WIDTH - w) / 2, (LAYER_HEIGHT - h) / 2); // top - } - } - else // custom font - /* As we can't reliable know what is the actual FIRST and last 'lit' pixel, we need to check what was printed to the layer.*/ - { - int wstart = 0; - - if (w > 42) wstart = (LAYER_WIDTH - w) / 2; - else wstart = (LAYER_WIDTH - w) / 2; - - if (textPos == TOP) { - setCursor(wstart, h+yadjust); // top - } else if (textPos == BOTTOM) { - setCursor(wstart+1, (LAYER_HEIGHT-1)+yadjust); - } else { // middle - setCursor( wstart, ((LAYER_HEIGHT/2) + (h/2)) + yadjust); - } - - //Serial.printf("Layer: x1: %d, y1: %d, w: %d, h: %d.\n", x1, y1, w, h); - } - - // setCursor(0,16); - setTextColor(this->color565(color.r, color.g, color.b)); // Need to confirm from FastLed CRGB to adafruit 565 - print(buf); - -} // end drawCentreText - - - // Move the contents of the screen left (-ve) or right (+ve) - void Layer::moveX(int offset) - { - if(offset > 0) { // move right - // Sprintln("Moving right"); - - for(int x = LAYER_WIDTH - 1; x >= 0; x--){ // 63 to 0 - for(int y = 0; y < LAYER_HEIGHT; y++){ // 0 to 31 - if (x - offset >= 0) - { - // Serial.printf("setting y %d x %d to y %d x %d\n", y, x, y, x-offset); - pixels->data[y][x] = pixels->data[y][x-offset]; - } - else { - pixels->data[y][x] = BLACK_BACKGROUND_PIXEL_COLOUR; - } - } - } - } else { // move left - - // Sprintln("Moving Left"); - for(int x = 0; x <=LAYER_WIDTH - 1; x++){ - for(int y = 0; y < LAYER_HEIGHT; y++){ - if ( x > (LAYER_WIDTH-1)+offset ) - { - pixels->data[y][x] = BLACK_BACKGROUND_PIXEL_COLOUR; - //Serial.println("eh?"); - } - else - { - pixels->data[y][x] = pixels->data[y][x-offset]; - // Serial.println("eh?"); - } - } - } - } - } - - // Find the leftmost and rightmost pixels across all rows. Centre the contents of the layer. - void Layer::autoCenterX() - { - int leftmost_x = 0, rightmost_x = 0, adjusted_leftmost_x = 0; - - // Find leftmost - for(int x = 0; x < LAYER_WIDTH; x++) { - for(int y = 0; y < LAYER_HEIGHT; y++) { - if (pixels->data[y][x] != BLACK_BACKGROUND_PIXEL_COLOUR) - { - leftmost_x = x; - //Serial.printf("Left most x pixel is %d\n", leftmost_x); - goto rightmost; - } - } - } - - rightmost: - for(int x = LAYER_WIDTH-1; x >= 0; x--) { - for(int y = 0; y < LAYER_HEIGHT; y++) { - if (pixels->data[y][x] != BLACK_BACKGROUND_PIXEL_COLOUR) - { - rightmost_x = x+1; - //Serial.printf("Right most x pixel is %d\n", rightmost_x); - goto centreit; - } - } - } - - centreit: - adjusted_leftmost_x = ( LAYER_WIDTH - (rightmost_x - leftmost_x))/2; - //Serial.printf("Adjusted: %d, Moving x coords by %d pixels.\n", adjusted_leftmost_x, adjusted_leftmost_x-leftmost_x); - moveX(adjusted_leftmost_x-leftmost_x); - } // end autoCentreX - - void Layer::moveY(int delta) - { - - } - - -Layer::~Layer(void) -{ - free(pixels); -} - - - - -/* Merge FastLED layers into a super layer and display. Definition */ -namespace LayerCompositor -{ - /* - * Display the foreground pixels if they're not the background/transparent color. - * If not, then fill with whatever is in the background. - * - * writeToBg = write the result back to the _bgLayer, and not directly to the output device! - * -> no need to do a subsequent bgLayer.display() otherwise. - */ - void Stack(RGB64x32MatrixPanel_I2S_DMA &disp, const Layer &_bgLayer, const Layer &_fgLayer, bool writeBackToBg) - { - for (int y = 0; y < LAYER_HEIGHT; y++) { - for (int x = 0; x < LAYER_WIDTH; x++) - { - //https://www.educative.io/edpresso/how-to-resolve-the-expression-must-have-class-type-error-in-cpp - if (_fgLayer.pixels->data[y][x] == _fgLayer.transparency_colour) // foreground is transparent, show the _bgLayer colors - { - if (writeBackToBg) // write the foreground to the background layer... perhaps so we can do stuff later with the _fgLayer. - _bgLayer.pixels->data[y][x] = _bgLayer.pixels->data[y][x]; - else - disp.drawPixelRGB888(x,y, _bgLayer.pixels->data[y][x].r, _bgLayer.pixels->data[y][x].g, _bgLayer.pixels->data[y][x].b ); - - } // if the foreground is NOT transparent, then print whatever is the bg - else - { - if (writeBackToBg) // write the foreground to the background layer... perhaps so we can do stuff later with the _fgLayer. - _bgLayer.pixels->data[y][x] = _fgLayer.pixels->data[y][x]; - else - disp.drawPixelRGB888(x,y, _fgLayer.pixels->data[y][x].r, _fgLayer.pixels->data[y][x].g, _fgLayer.pixels->data[y][x].b ); - } - - } // end x loop - } // end y loop - } // end stack - - - /* - * Where the foreground pixels are not the background/transparent color, populate with - * whatever is in the background. - */ - void Siloette(RGB64x32MatrixPanel_I2S_DMA &disp, const Layer &_bgLayer, const Layer &_fgLayer) - { - //const Layer *bg = &_bgLayer; - //const Layer *fg = &_fgLayer; - - for (int y = 0; y < LAYER_HEIGHT; y++) { - for (int x = 0; x < LAYER_WIDTH; x++) - { - //https://www.educative.io/edpresso/how-to-resolve-the-expression-must-have-class-type-error-in-cpp - if (_fgLayer.pixels->data[y][x] != _fgLayer.transparency_colour) - { - disp.drawPixelRGB888(x,y, _bgLayer.pixels->data[y][x].r, _bgLayer.pixels->data[y][x].g, _bgLayer.pixels->data[y][x].b ); - } // if the foreground is transparent, then print whatever is the bg - else - { - disp.drawPixelRGB888(x,y, 0,0,0); - } - - } // end x loop - } // end y loop - } // end stack - - - - - - void Blend(RGB64x32MatrixPanel_I2S_DMA &disp, const Layer &_bgLayer, const Layer &_fgLayer, uint8_t ratio) - { - CRGB _pixel = 0 ; - - for (int y = 0; y < LAYER_HEIGHT; y++) - { - for (int x = 0; x < LAYER_WIDTH; x++) - { - /* - // set the blend ratio for the video cross fade - // (set ratio to 127 for a constant 50% / 50% blend) - uint8_t ratio = beatsin8(5); - */ - - _pixel = blend(_bgLayer.pixels->data[y][x], _fgLayer.pixels->data[y][x], ratio); - - // https://gist.github.com/StefanPetrick/0c0d54d0f35ea9cca983 - disp.drawPixelRGB888(x,y, _pixel.r, _pixel.g, _pixel.b ); - - } // end x loop - } // end y loop - - - - } // end blend -} diff --git a/Layer.h b/Layer.h deleted file mode 100644 index ed08fa0..0000000 --- a/Layer.h +++ /dev/null @@ -1,104 +0,0 @@ -/** - * Experimental layer class to do play with pixel in an off-screen buffer before painting to the DMA - * - * Requires FastLED - * - * Faptastic 2020 - **/ - - -#ifndef DISPLAY_MATRIX_LAYER -#define DISPLAY_MATRIX_LAYER - -#include -#include -#include - -#define HALF_WHITE_COLOUR 0x8410 -#define BLACK_BACKGROUND_PIXEL_COLOUR CRGB(0,0,0) - -#define LAYER_WIDTH 64 -#define LAYER_HEIGHT 32 - -enum textPosition { TOP, MIDDLE, BOTTOM }; - - -/* To help with direct pixel referencing by width and height */ -struct layerPixels { - CRGB data[LAYER_HEIGHT][LAYER_WIDTH]; -}; - -class Layer : public GFX // use GFX Root for now -{ - public: - - // Static allocation of memory for layer - //CRGB pixels[LAYER_WIDTH][LAYER_HEIGHT] = {{0}}; - - Layer(RGB64x32MatrixPanel_I2S_DMA &disp) : GFX (LAYER_WIDTH, LAYER_HEIGHT) { - matrix = &disp; - } - - inline void init() - { - // https://stackoverflow.com/questions/5914422/proper-way-to-initialize-c-structs - pixels = new layerPixels(); - - //pixels = (layerPixels *) malloc(sizeof(layerPixels)); - // pixel = (CRGB *) &pixels[0]; - //Serial.printf("Allocated %d bytes of memory for standard CRGB (24bit) layer.\r\n", NUM_PIXELS*sizeof(CRGB)); - Serial.printf("Allocated %d bytes of memory for layerPixels.\r\n", sizeof(layerPixels)); - - } // end Layer - - void drawPixel(int16_t x, int16_t y, uint16_t color); // overwrite adafruit implementation - void drawPixel(int16_t x, int16_t y, int r, int g, int b); // Layer implementation - void drawPixel(int16_t x, int16_t y, CRGB color); // Layer implementation - - // Font Stuff - //https://forum.arduino.cc/index.php?topic=642749.0 - void drawCentreText(const char *buf, textPosition textPos = BOTTOM, const GFXfont *f = NULL, CRGB color = 0x8410, int yadjust = 0); // 128,128,128 RGB @ bottom row by default - - - void dim(byte value); - void clear(); - void display(); // flush to display / LED matrix - - // override the color of all pixels that aren't the transparent color - void overridePixelColor(int r, int g, int b); - - inline uint16_t color565(uint8_t r, uint8_t g, uint8_t b) { - return ((r & 0xF8) << 8) | ((g & 0xFC) << 3) | (b >> 3); - } - - inline void setTransparency(bool t) { transparency_enabled = t; } - - // Effects - void moveX(int delta); - void autoCenterX(); - void moveY(int delta); - - // For layer composition - accessed publically - CRGB transparency_colour = BLACK_BACKGROUND_PIXEL_COLOUR; - bool transparency_enabled = true; - layerPixels *pixels; - //CRGB *pixel; - - - // Release Memory - ~Layer(void); - - private: - RGB64x32MatrixPanel_I2S_DMA *matrix = NULL; -}; - - -/* Merge FastLED layers into a super layer and display. */ -namespace LayerCompositor -{ - void Stack(RGB64x32MatrixPanel_I2S_DMA &disp, const Layer &_bgLayer, const Layer &_fgLayer, bool writeToBgLayer = false); - void Siloette(RGB64x32MatrixPanel_I2S_DMA &disp, const Layer &_bgLayer, const Layer &_fgLayer); - void Blend(RGB64x32MatrixPanel_I2S_DMA &disp, const Layer &_bgLayer, const Layer &_fgLayer, uint8_t ratio); -} - -#endif