Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Indexed layer colour depth increase and layer disabling option #163

Open
wants to merge 7 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions src/Layer.h
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand All @@ -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:
};
Expand Down
42 changes: 17 additions & 25 deletions src/Layer_Indexed.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 <typename RGB, unsigned int optionFlags>
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);
Expand All @@ -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);
Expand All @@ -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;
Expand All @@ -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"
Expand Down
161 changes: 119 additions & 42 deletions src/Layer_Indexed_Impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,31 +23,34 @@

#include <string.h>

#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 <typename RGB, unsigned int optionFlags>
SMLayerIndexed<RGB, optionFlags>::SMLayerIndexed(uint8_t * bitmap, uint16_t width, uint16_t height) {
SMLayerIndexed<RGB, optionFlags>::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<<indexColourDepth)-1];
colourLookup[(2<<indexColourDepth)-1] = rgb48(0xffff, 0xffff, 0xffff);
}

template <typename RGB, unsigned int optionFlags>
SMLayerIndexed<RGB, optionFlags>::SMLayerIndexed(uint16_t width, uint16_t height) {
SMLayerIndexed<RGB, optionFlags>::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<<indexColourDepth)-1];
colourLookup[(2<<indexColourDepth)-1] = rgb48(0xffff, 0xffff, 0xffff);
}

template <typename RGB, unsigned int optionFlags>
Expand All @@ -65,7 +68,7 @@ void SMLayerIndexed<RGB, optionFlags>::frameRefreshCallback(void) {
// returns true and copies color to xyPixel if pixel is opaque, returns false if not
template<typename RGB, unsigned int optionFlags> template <typename RGB_OUT>
bool SMLayerIndexed<RGB, optionFlags>::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 ) {
Expand All @@ -90,20 +93,51 @@ bool SMLayerIndexed<RGB, optionFlags>::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 <typename RGB, unsigned int optionFlags>
void SMLayerIndexed<RGB, optionFlags>::fillRefreshRow(uint16_t hardwareY, rgb48 refreshRow[], int brightnessShifts) {
RGB currentPixel;
int i;
uint32_t i;

if(this->ccEnabled) {
for(i=0; i<this->matrixWidth; i++) {
Expand All @@ -126,7 +160,7 @@ void SMLayerIndexed<RGB, optionFlags>::fillRefreshRow(uint16_t hardwareY, rgb48
template <typename RGB, unsigned int optionFlags>
void SMLayerIndexed<RGB, optionFlags>::fillRefreshRow(uint16_t hardwareY, rgb24 refreshRow[], int brightnessShifts) {
RGB currentPixel;
int i;
uint32_t i;

if(this->ccEnabled) {
for(i=0; i<this->matrixWidth; i++) {
Expand All @@ -148,7 +182,10 @@ void SMLayerIndexed<RGB, optionFlags>::fillRefreshRow(uint16_t hardwareY, rgb24

template<typename RGB, unsigned int optionFlags>
void SMLayerIndexed<RGB, optionFlags>::setIndexedColor(uint8_t index, const RGB & newColor) {
color = newColor;
if(index>(2<<indexColourDepth)-1 || index==0)
return;

colourLookup[index-1] = newColor;
}

template<typename RGB, unsigned int optionFlags>
Expand All @@ -158,11 +195,27 @@ void SMLayerIndexed<RGB, optionFlags>::enableColorCorrection(bool enabled) {

template <typename RGB, unsigned int optionFlags>
void SMLayerIndexed<RGB, optionFlags>::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);
}
Expand Down Expand Up @@ -213,33 +266,52 @@ void SMLayerIndexed<RGB, optionFlags>::handleBufferSwap(void) {

template <typename RGB, unsigned int optionFlags>
void SMLayerIndexed<RGB, optionFlags>::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 <typename RGB, unsigned int optionFlags>
void SMLayerIndexed<RGB, optionFlags>::setFont(fontChoices newFont) {
layerFont = (bitmap_font *)fontLookup(newFont);
majorScrollFontChange = true;
}

template <typename RGB, unsigned int optionFlags>
void SMLayerIndexed<RGB, optionFlags>::drawChar(int16_t x, int16_t y, uint8_t index, char character) {
void SMLayerIndexed<RGB, optionFlags>::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;
}

Expand All @@ -249,36 +321,41 @@ void SMLayerIndexed<RGB, optionFlags>::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 <typename RGB, unsigned int optionFlags>
void SMLayerIndexed<RGB, optionFlags>::drawString(int16_t x, int16_t y, uint8_t index, const char text []) {
int offset = 0;
void SMLayerIndexed<RGB, optionFlags>::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 <typename RGB, unsigned int optionFlags>
void SMLayerIndexed<RGB, optionFlags>::drawMonoBitmap(int16_t x, int16_t y, uint8_t width, uint8_t height, uint8_t index, uint8_t *bitmap) {
int xcnt, ycnt;
void SMLayerIndexed<RGB, optionFlags>::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);
}
}
}
Expand Down
2 changes: 2 additions & 0 deletions src/MatrixHardware_ESP32_HUB75AdapterLite_V0.h
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
3 changes: 2 additions & 1 deletion src/MatrixHardware_ESP32_HUB75Adapter_SMT.h
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
Loading