diff --git a/src/bb_ep.inl b/src/bb_ep.inl index 0ff89ea..0717c95 100644 --- a/src/bb_ep.inl +++ b/src/bb_ep.inl @@ -19,6 +19,12 @@ #define __BB_EP__ // forward declarations void InvertBytes(uint8_t *pData, uint8_t bLen); +void bbepSetPixelFast4Clr(void *pb, int x, int y, unsigned char ucColor); +void bbepSetPixelFast3Clr(void *pb, int x, int y, unsigned char ucColor); +void bbepSetPixelFast2Clr(void *pb, int x, int y, unsigned char ucColor); +int bbepSetPixel4Clr(void *pb, int x, int y, unsigned char ucColor); +int bbepSetPixel3Clr(void *pb, int x, int y, unsigned char ucColor); +int bbepSetPixel2Clr(void *pb, int x, int y, unsigned char ucColor); const uint8_t ucMirror[256] PROGMEM = {0, 128, 64, 192, 32, 160, 96, 224, 16, 144, 80, 208, 48, 176, 112, 240, @@ -1223,6 +1229,17 @@ int bbepSetPanelType(BBEPDISP *pBBEP, int iPanel) pBBEP->pInitFast = panelDefs[iPanel].pInitFast; pBBEP->pInitPart = panelDefs[iPanel].pInitPart; pBBEP->type = iPanel; + // select the correct pixel drawing functions (2/3/4 color) + if (pBBEP->iFlags & BBEP_4COLOR) { + pBBEP->pfnSetPixel = bbepSetPixel4Clr; + pBBEP->pfnSetPixelFast = bbepSetPixelFast4Clr; + } else if (pBBEP->iFlags & BBEP_3COLOR) { + pBBEP->pfnSetPixel = bbepSetPixel3Clr; + pBBEP->pfnSetPixelFast = bbepSetPixelFast3Clr; + } else { // must be B/W + pBBEP->pfnSetPixel = bbepSetPixel2Clr; + pBBEP->pfnSetPixelFast = bbepSetPixelFast2Clr; + } return BBEP_SUCCESS; } /* bbepSetPanelType() */ diff --git a/src/bb_ep_gfx.inl b/src/bb_ep_gfx.inl index 75565d0..cf596e8 100644 --- a/src/bb_ep_gfx.inl +++ b/src/bb_ep_gfx.inl @@ -25,7 +25,6 @@ static G5DECIMAGE g5dec; // forward declarations void InvertBytes(uint8_t *pData, uint8_t bLen); -int bbepSetPixel(BBEPDISP *pBBEP, int x, int y, unsigned char ucColor); const uint8_t ucFont[]PROGMEM = { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x5f,0x5f,0x06,0x00, @@ -269,7 +268,7 @@ void bbepDrawSprite(BBEPDISP *pBBEP, const uint8_t *pSprite, int cx, int cy, int pix = *s++; for (tx=0; txpfnSetPixelFast)(pBBEP, dx+tx, dy+ty, iColor); } ucSrcMask >>= 1; if (ucSrcMask == 0) { // read next byte @@ -284,26 +283,56 @@ void bbepDrawSprite(BBEPDISP *pBBEP, const uint8_t *pSprite, int cx, int cy, int } /* bbepDrawSprite() */ // // Set (or clear) an individual pixel -// This function only works with a back buffer defined. A bufferless version +// These functions only works with a back buffer defined. A bufferless version // is possible, but would be too impractical. // -int bbepSetPixel(BBEPDISP *pBBEP, int x, int y, unsigned char ucColor) +int bbepSetPixel4Clr(void *pb, int x, int y, unsigned char ucColor) { - int i; - int iPitch, iSize; +int i; +int iPitch; +uint8_t u8, ucMask; +BBEPDISP *pBBEP = (BBEPDISP *)pb; + + // only available for local buffer operations + if (!pBBEP || !pBBEP->ucScreen) return BBEP_ERROR_BAD_PARAMETER; + + ucMask = 0xc0 >> ((x & 3)*2); + iPitch = (pBBEP->width+3)>>2; + i = (x >> 2) + (y * iPitch); + if (i < 0 || i >= (iPitch * pBBEP->height)) return BBEP_ERROR_BAD_PARAMETER; + u8 = pBBEP->ucScreen[i]; + u8 &= ~ucMask; + u8 |= ucColor << ((3-(x & 3))*2); + pBBEP->ucScreen[i] = u8; + return BBEP_SUCCESS; + +} /* bbepSetPixel4Clr() */ +// Fast version (no pointer verification + no boundary checking) +void bbepSetPixelFast4Clr(void *pb, int x, int y, unsigned char ucColor) +{ +int i; +int iPitch; +uint8_t u8, ucMask; +BBEPDISP *pBBEP = (BBEPDISP *)pb; + + ucMask = 0xc0 >> ((x & 3)*2); + iPitch = (pBBEP->width+3)>>2; + i = (x >> 2) + (y * iPitch); + u8 = pBBEP->ucScreen[i]; + u8 &= ~ucMask; + u8 |= ucColor << ((3-(x & 3))*2); + pBBEP->ucScreen[i] = u8; +} /* bbepSetPixelFast4Clr() */ + +int bbepSetPixel3Clr(void *pb, int x, int y, unsigned char ucColor) +{ +int i; +int iPitch, iSize; +BBEPDISP *pBBEP = (BBEPDISP *)pb; // only available for local buffer operations if (!pBBEP || !pBBEP->ucScreen) return BBEP_ERROR_BAD_PARAMETER; - if (pBBEP->iFlags & BBEP_4COLOR) { // 2-bits per pixel - uint8_t ucMask = 0xc0 >> ((x & 3)*2); - iPitch = (pBBEP->width+3)>>2; - i = (x >> 2) + (y * iPitch); - if (i < 0 || i >= (iPitch * pBBEP->height)) return BBEP_ERROR_BAD_PARAMETER; - pBBEP->ucScreen[i] &= ~ucMask; - pBBEP->ucScreen[i] |= ucColor << ((3-(x & 3))*2); - return BBEP_SUCCESS; - } iPitch = (pBBEP->width+7)>>3; iSize = ((pBBEP->native_width+7)>>3) * pBBEP->native_height; @@ -312,23 +341,10 @@ int bbepSetPixel(BBEPDISP *pBBEP, int x, int y, unsigned char ucColor) pBBEP->last_error = BBEP_ERROR_BAD_PARAMETER; return BBEP_ERROR_BAD_PARAMETER; } - // special case for 3-color e-ink - if (pBBEP->iFlags & BBEP_3COLOR) { - if (ucColor >= BBEP_YELLOW) { // yellow/red has priority - pBBEP->ucScreen[iSize + i] |= (0x80 >> (x & 7)); - } else { - pBBEP->ucScreen[iSize + i] &= ~(0x80 >> (x & 7)); // clear red plane bit - if (ucColor == BBEP_WHITE) { - pBBEP->ucScreen[i] |= (0x80 >> (x & 7)); - } else { // must be black - pBBEP->ucScreen[i] &= ~(0x80 >> (x & 7)); - } - } - return BBEP_SUCCESS; - } else { // 2-color - if (pBBEP->iPlane == PLANE_1) { - i += iSize; - } + if (ucColor >= BBEP_YELLOW) { // yellow/red has priority + pBBEP->ucScreen[iSize + i] |= (0x80 >> (x & 7)); + } else { + pBBEP->ucScreen[iSize + i] &= ~(0x80 >> (x & 7)); // clear red plane bit if (ucColor == BBEP_WHITE) { pBBEP->ucScreen[i] |= (0x80 >> (x & 7)); } else { // must be black @@ -336,7 +352,83 @@ int bbepSetPixel(BBEPDISP *pBBEP, int x, int y, unsigned char ucColor) } } return BBEP_SUCCESS; -} /* obdSetPixel() */ +} /* bbepSetPixel3Clr() */ + +void bbepSetPixelFast3Clr(void *pb, int x, int y, unsigned char ucColor) +{ +int i; +int iPitch, iSize; +BBEPDISP *pBBEP = (BBEPDISP *)pb; + + iPitch = (pBBEP->width+7)>>3; + iSize = ((pBBEP->native_width+7)>>3) * pBBEP->native_height; + + i = (x >> 3) + (y * iPitch); + if (ucColor >= BBEP_YELLOW) { // yellow/red has priority + pBBEP->ucScreen[iSize + i] |= (0x80 >> (x & 7)); + } else { + pBBEP->ucScreen[iSize + i] &= ~(0x80 >> (x & 7)); // clear red plane bit + if (ucColor == BBEP_WHITE) { + pBBEP->ucScreen[i] |= (0x80 >> (x & 7)); + } else { // must be black + pBBEP->ucScreen[i] &= ~(0x80 >> (x & 7)); + } + } +} /* bbepSetPixelFast3Clr() */ + +int bbepSetPixel2Clr(void *pb, int x, int y, unsigned char ucColor) +{ + int i; + int iPitch, iSize; + uint8_t u8; + BBEPDISP *pBBEP = (BBEPDISP *)pb; + + // only available for local buffer operations + if (!pBBEP || !pBBEP->ucScreen) return BBEP_ERROR_BAD_PARAMETER; + + iPitch = (pBBEP->width+7)>>3; + iSize = ((pBBEP->native_width+7)>>3) * pBBEP->native_height; + + i = (x >> 3) + (y * iPitch); + if (x < 0 || x >= pBBEP->width || i < 0 || i > iSize-1) { // off the screen + pBBEP->last_error = BBEP_ERROR_BAD_PARAMETER; + return BBEP_ERROR_BAD_PARAMETER; + } + if (pBBEP->iPlane == PLANE_1) { + i += iSize; + } + u8 = pBBEP->ucScreen[i]; + if (ucColor == BBEP_WHITE) { + u8 |= (0x80 >> (x & 7)); + } else { // must be black + u8 &= ~(0x80 >> (x & 7)); + } + pBBEP->ucScreen[i] = u8; + return BBEP_SUCCESS; +} /* bbepSetPixel2Clr() */ + +void bbepSetPixelFast2Clr(void *pb, int x, int y, unsigned char ucColor) +{ + int i; + int iPitch, iSize; + uint8_t u8; + BBEPDISP *pBBEP = (BBEPDISP *)pb; + + iPitch = (pBBEP->width+7)>>3; + iSize = ((pBBEP->native_width+7)>>3) * pBBEP->native_height; + + i = (x >> 3) + (y * iPitch); + if (pBBEP->iPlane == PLANE_1) { + i += iSize; + } + u8 = pBBEP->ucScreen[i]; + if (ucColor == BBEP_WHITE) { + u8 |= (0x80 >> (x & 7)); + } else { // must be black + u8 &= ~(0x80 >> (x & 7)); + } + pBBEP->ucScreen[i] = u8; +} /* bbepSetPixelFast2Clr() */ // // Invert font data @@ -412,10 +504,10 @@ int bbepLoadG5(BBEPDISP *pBBEP, const uint8_t *pG5, int x, int y, int iFG, int i } if (u8 & src_mask) { if (iFG >= 0) - bbepSetPixel(pBBEP, x+tx, y+ty, (uint8_t)iFG); + (*pBBEP->pfnSetPixelFast)(pBBEP, x+tx, y+ty, (uint8_t)iFG); } else { if (iBG >= 0) - bbepSetPixel(pBBEP, x+tx, y+ty, (uint8_t)iBG); + (*pBBEP->pfnSetPixelFast)(pBBEP, x+tx, y+ty, (uint8_t)iBG); } src_mask >>= 1; } // for tx @@ -517,10 +609,10 @@ int bbepLoadBMP(BBEPDISP *pBBEP, const uint8_t *pBMP, int dx, int dy, int iFG, i } if (b & src_mask) { if (iFG >= 0) - bbepSetPixel(pBBEP, dx+x, dy+y, (uint8_t)iFG); + (*pBBEP->pfnSetPixelFast)(pBBEP, dx+x, dy+y, (uint8_t)iFG); } else { if (iBG >= 0) - bbepSetPixel(pBBEP, dx+x, dy+y, (uint8_t)iBG); + (*pBBEP->pfnSetPixelFast)(pBBEP, dx+x, dy+y, (uint8_t)iBG); } src_mask >>= 1; } // for x @@ -741,7 +833,7 @@ int bbepWriteStringCustom(BBEPDISP *pBBEP, BB_FONT *pFont, int x, int y, char *s u8Count = 8; for (tx=x; txpfnSetPixelFast)(pBBEP, tx, ty, iColor); } u8 <<= 1; u8Count--; @@ -1002,7 +1094,7 @@ int bbepWriteString(BBEPDISP *pBBEP, int x, int y, char *szMsg, int iSize, int i u8Mask = 1<pfnSetPixelFast)(pBBEP, x+tx, y+ty, iColor); } } } @@ -1013,10 +1105,10 @@ int bbepWriteString(BBEPDISP *pBBEP, int x, int y, char *szMsg, int iSize, int i u8Mask = 0x80; for (int tx = 7; tx>=0; tx--) { if (s[0] & u8Mask) { - bbepSetPixel(pBBEP, x+ty, y+tx+8, iColor); + (*pBBEP->pfnSetPixelFast)(pBBEP, x+ty, y+tx+8, iColor); } if (s[1] & u8Mask) { - bbepSetPixel(pBBEP, x+ty, y+tx, iColor); + (*pBBEP->pfnSetPixelFast)(pBBEP, x+ty, y+tx, iColor); } u8Mask >>= 1; } @@ -1167,10 +1259,10 @@ int bbepWriteString(BBEPDISP *pBBEP, int x, int y, char *szMsg, int iSize, int i u8Mask = 1<pfnSetPixelFast)(pBBEP, x+tx, y+ty, iColor); } if (u8Temp[18+tx] & u8Mask) { - bbepSetPixel(pBBEP, x+tx, y+ty+8, iColor); + (*pBBEP->pfnSetPixelFast)(pBBEP, x+tx, y+ty+8, iColor); } } } @@ -1211,7 +1303,7 @@ int bbepWriteString(BBEPDISP *pBBEP, int x, int y, char *szMsg, int iSize, int i u8Mask = 1<pfnSetPixelFast)(pBBEP, x+tx, ty+y, iColor); } } } @@ -1612,7 +1704,7 @@ void bbepRectangle(BBEPDISP *pBBEP, int x1, int y1, int x2, int y2, uint8_t ucCo int tx, ty; for (ty = y1; ty <= y2; ty++) { for (tx = x1; tx <= x2; tx++) { - bbepSetPixel(pBBEP, tx, ty, ucColor); + (*pBBEP->pfnSetPixelFast)(pBBEP, tx, ty, ucColor); } } } else @@ -1629,74 +1721,21 @@ void bbepRectangle(BBEPDISP *pBBEP, int x1, int y1, int x2, int y2, uint8_t ucCo } } } - else // outline + else // outline (only support on backbuffer for now { - // see if top and bottom lines are within the same byte rows - d = &pBBEP->ucScreen[iRedOffset + (y1 >> 3)*iPitch + x1]; - if ((y1 >> 3) == (y2 >> 3)) - { - ucMask2 = 0xff << (y1 & 7); // L/R end masks - ucMask = 1 << (y1 & 7); - ucMask |= 1 << (y2 & 7); - ucMask2 &= (0xff >> (7-(y2 & 7))); - if (ucColor) - { - *d++ |= ucMask2; // start - x1++; - for (; x1 < x2; x1++) - *d++ |= ucMask; - if (x1 <= x2) - *d++ |= ucMask2; // right edge +#ifndef NO_RAM + if (pBBEP->ucScreen) { // has a buffer to fill + int tx, ty; + for (ty = y1; ty <= y2; ty++) { + (*pBBEP->pfnSetPixelFast)(pBBEP, x1, ty, ucColor); + (*pBBEP->pfnSetPixelFast)(pBBEP, x2, ty, ucColor); } - else - { - *d++ &= ~ucMask2; - x1++; - for (; x1 < x2; x1++) - *d++ &= ~ucMask; - if (x1 <= x2) - *d++ &= ~ucMask2; // right edge - } - } - else - { - int y; - // L/R sides - iOff = (x2 - x1); - ucMask = 1 << (y1 & 7); - for (y=y1; y <= y2; y++) - { - if (ucColor) { - *d |= ucMask; - d[iOff] |= ucMask; - } else { - *d &= ~ucMask; - d[iOff] &= ~ucMask; - } - ucMask <<= 1; - if (ucMask == 0) { - ucMask = 1; - d += iPitch; - } - } - // T/B sides - ucMask = 1 << (y1 & 7); - ucMask2 = 1 << (y2 & 7); - x1++; - d = &pBBEP->ucScreen[iRedOffset + (y1 >> 3)*iPitch + x1]; - iOff = (y2 >> 3) - (y1 >> 3); - iOff *= iPitch; - for (; x1 < x2; x1++) { - if (ucColor) { - *d |= ucMask; - d[iOff] |= ucMask2; - } else { - *d &= ~ucMask; - d[iOff] &= ~ucMask2; - } - d++; + for (tx = x1; tx <= x2; tx++) { + (*pBBEP->pfnSetPixelFast)(pBBEP, tx, y1, ucColor); + (*pBBEP->pfnSetPixelFast)(pBBEP, tx, y2, ucColor); } } +#endif } // outline } /* bbepRectangle() */ diff --git a/src/bb_epaper.cpp b/src/bb_epaper.cpp index ba6805a..bb5e803 100644 --- a/src/bb_epaper.cpp +++ b/src/bb_epaper.cpp @@ -420,7 +420,7 @@ int w=8, h=8; void BBEPAPER::drawPixel(int16_t x, int16_t y, uint8_t color) { - bbepSetPixel(&_bbep, x, y, color); + (*_bbep.pfnSetPixel)(&_bbep, x, y, color); } int16_t BBEPAPER::getCursorX(void) { diff --git a/src/bb_epaper.h b/src/bb_epaper.h index bdc213c..25d828d 100644 --- a/src/bb_epaper.h +++ b/src/bb_epaper.h @@ -264,6 +264,11 @@ enum { #define BUSY_WAIT 0xff +// Normal pixel drawing function pointer +typedef int (BB_SET_PIXEL)(void *pBBEP, int x, int y, unsigned char color); +// Fast pixel drawing function pointer (no boundary checking) +typedef void (BB_SET_PIXEL_FAST)(void *pBBEP, int x, int y, unsigned char color); + typedef struct bbepstruct { uint8_t wrap, type, chip_type, last_error; @@ -283,6 +288,8 @@ uint8_t is_awake, iPlane; const uint8_t *pInitFull; // full update init sequence const uint8_t *pInitFast; // fast update init sequence const uint8_t *pInitPart; // partial update init sequence +BB_SET_PIXEL *pfnSetPixel; +BB_SET_PIXEL_FAST *pfnSetPixelFast; } BBEPDISP; #ifdef __cplusplus @@ -382,6 +389,7 @@ class BBEPAPER private: BBEPDISP _bbep; + }; // class BBEPAPER #endif // __cplusplus