Skip to content

Commit 855ce9a

Browse files
committed
Added partial updates between different bit depths
1 parent 18827b1 commit 855ce9a

File tree

3 files changed

+119
-3
lines changed

3 files changed

+119
-3
lines changed

library.properties

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
name=FastEPD
2-
version=1.5.1
2+
version=1.5.2
33
author=Larry Bank
44
maintainer=Larry Bank
55
sentence=A frustration-free e-paper library for parallel eink panels.

src/FastEPD.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -249,8 +249,10 @@ class FASTEPD
249249
uint8_t ioRead(uint8_t u8Pin);
250250
int getMode(void) {return _state.mode;}
251251
int getPreviousMode(void) {return _state.prev_mode;}
252+
void setPreviousMode(uint8_t prev_mode) { _state.prev_mode = prev_mode;}
252253
uint8_t *previousBuffer(void) { return _state.pPrevious;}
253254
uint8_t *currentBuffer(void) { return _state.pCurrent;}
255+
uint8_t *tempBuffer(void) { return _state.pTemp;}
254256
int einkPower(int bOn);
255257
void deInit(void) {if (_state.pfnIODeInit) (*_state.pfnIODeInit)(&_state);}
256258
int fullUpdate(int iClearMode = CLEAR_SLOW, bool bKeepOn = false, BB_RECT *pRect = NULL);

src/FastEPD.inl

Lines changed: 116 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2107,8 +2107,8 @@ int bbepFullUpdate(FASTEPDSTATE *pState, int iClearMode, bool bKeepOn, BB_RECT *
21072107
bbepClear(pState, BB_CLEAR_LIGHTEN, 8, pRect);
21082108
break;
21092109
case CLEAR_FAST:
2110-
bbepClear(pState, BB_CLEAR_DARKEN, 6, pRect);
2111-
bbepClear(pState, BB_CLEAR_LIGHTEN, 6, pRect);
2110+
bbepClear(pState, BB_CLEAR_DARKEN, 8, pRect);
2111+
bbepClear(pState, BB_CLEAR_LIGHTEN, 8, pRect);
21122112
break;
21132113
case CLEAR_WHITE:
21142114
if (pState->panelDef.flags & BB_PANEL_FLAG_DARK) {
@@ -2383,6 +2383,115 @@ int bbepFullUpdate(FASTEPDSTATE *pState, int iClearMode, bool bKeepOn, BB_RECT *
23832383
return BBEP_SUCCESS;
23842384
} /* bbepFullUpdate() */
23852385
//
2386+
// Convert the previous image buffer contents to be
2387+
// the same bit depth as the current mode (1 or 2-bpp) so that
2388+
// it can do a differential (partial/non-flickering) update
2389+
//
2390+
void bbepConvertPrevBuffer(FASTEPDSTATE *pState)
2391+
{
2392+
uint8_t *s, *d, *c;
2393+
int i, n, x, y, iSrcPitch, iDestPitch;
2394+
2395+
switch (pState->prev_mode) {
2396+
case BB_MODE_1BPP:
2397+
iSrcPitch = pState->native_width / 8;
2398+
break;
2399+
case BB_MODE_2BPP:
2400+
iSrcPitch = pState->native_width / 4;
2401+
break;
2402+
case BB_MODE_4BPP:
2403+
iSrcPitch = pState->native_width / 2;
2404+
break;
2405+
}
2406+
if (pState->mode == BB_MODE_1BPP) { // convert to 1-bpp
2407+
iDestPitch = pState->native_width / 8;
2408+
for (y=0; y<pState->native_height; y++) {
2409+
s = &pState->pPrevious[iSrcPitch * y];
2410+
d = &pState->pTemp[iDestPitch * y];
2411+
c = &pState->pCurrent[iDestPitch * y];
2412+
if (pState->prev_mode == BB_MODE_2BPP) {
2413+
for (x=0; x<pState->native_width; x+=8) { // work 8 pixels at a time
2414+
uint8_t ucSrc, ucCurr, ucDest = 0;
2415+
ucCurr = *c++; // get current pixels in case we need to make a decision
2416+
for (n=0; n<2; n++) { // work on 2 sets of 4 pixels
2417+
ucSrc = *s++; // get 4 source pixels
2418+
for (i=0; i<4; i++) {
2419+
ucDest <<= 1;
2420+
switch (ucSrc & 0xc0) {
2421+
case 0xc0: // white - easy
2422+
ucDest |= 1; // compared pixel will be white
2423+
case 0x00: // black - easy
2424+
break;
2425+
case 0x80: // light or dark gray - difficult, check current pixel
2426+
case 0x40:
2427+
ucDest |= ((ucCurr >> 7) ^ 1); // opposite of current color
2428+
break;
2429+
}
2430+
ucCurr <<= 1;
2431+
ucSrc <<= 2;
2432+
} // for i
2433+
} // for n
2434+
*d++ = ucDest;
2435+
} // for x
2436+
} else { // 4bpp => 1bpp
2437+
for (x=0; x<pState->native_width; x+=8) { // work 8 pixels at a time
2438+
uint8_t ucSrc, ucCurr, ucDest = 0;
2439+
ucCurr = *c++; // get current pixels in case we need to make a decision
2440+
for (n=0; n<4; n++) { // work on 4 sets of 2 pixels
2441+
ucSrc = *s++; // get 2 source pixels
2442+
for (i=0; i<2; i++) {
2443+
ucDest <<= 1;
2444+
switch (ucSrc & 0xf0) {
2445+
case 0xf0: // white - easy
2446+
ucDest |= 1; // compared pixel will be white
2447+
case 0x00: // black - easy
2448+
break;
2449+
default: // middle grays - difficult, check current pixel
2450+
ucDest |= ((ucCurr >> 7) ^ 1); // opposite of current color
2451+
break;
2452+
}
2453+
ucCurr <<= 1;
2454+
ucSrc <<= 4;
2455+
} // for i
2456+
} // for n
2457+
*d++ = ucDest;
2458+
} // for x
2459+
} // previous pixels are 4-bpp
2460+
} // for y
2461+
} else { // convert to 2-bpp
2462+
iDestPitch = pState->native_width / 4;
2463+
for (y=0; y<pState->native_height; y++) {
2464+
s = &pState->pPrevious[iSrcPitch * y];
2465+
d = &pState->pTemp[iDestPitch * y];
2466+
c = &pState->pCurrent[iDestPitch * y];
2467+
if (pState->prev_mode == BB_MODE_1BPP) {
2468+
const uint8_t u8Conv1To2[16] = {0, 3, 0xc, 0xf, 0x30, 0x33, 0x3c, 0x3f,
2469+
0xc0, 0xc3, 0xcc, 0xcf, 0xf0, 0xf3, 0xfc, 0xff}; // convert each nibble
2470+
// Simple direct convertsion: 0->00, 1->11
2471+
for (x=0; x<pState->native_width; x += 8) { // work 8 pixels at a time
2472+
uint8_t ucSrc = *s++; // get 8 source pixels
2473+
*d++ = u8Conv1To2[ucSrc>>4];
2474+
*d++ = u8Conv1To2[ucSrc & 0xf];
2475+
} // for x
2476+
} else { // 4bpp => 2bpp
2477+
for (x=0; x<pState->native_width; x += 4) { // work 4 pixels at a time
2478+
uint8_t ucSrc, ucDest;
2479+
ucSrc = *s++; // get 2 source pixels
2480+
ucDest = (ucSrc & 0xc0); // left pixel top 2 bits
2481+
ucDest |= ((ucSrc >> 2) << 4); // right pixel top 2 bits
2482+
ucSrc = *s++; // another 2 source pixels
2483+
ucDest |= ((ucSrc >> 6) << 2);
2484+
ucDest |= (ucSrc >> 2);
2485+
*d++ = ucDest;
2486+
} // for x
2487+
} // previous pixels are 4-bpp
2488+
} // for y
2489+
}
2490+
// Now we can overwrite the old pixels with the converted ones
2491+
memcpy(pState->pPrevious, pState->pTemp, iDestPitch * pState->native_height);
2492+
pState->prev_mode = pState->mode;
2493+
} /* bbepConvertPrevBuffer() */
2494+
//
23862495
// Non-flickering update in 2-bpp gray mode
23872496
//
23882497
int bbep2BppPartial(FASTEPDSTATE *pState, bool bKeepOn, int iStartLine, int iEndLine)
@@ -2574,6 +2683,11 @@ int bbepPartialUpdate(FASTEPDSTATE *pState, bool bKeepOn, int iStartLine, int iE
25742683

25752684
// Only supported in 1-bit mode (for now)
25762685
if (pState->mode != BB_MODE_1BPP && pState->mode != BB_MODE_2BPP) return BBEP_ERROR_BAD_PARAMETER;
2686+
if (pState->prev_mode == BB_MODE_NONE) return BBEP_ERROR_BAD_PARAMETER;
2687+
2688+
if (pState->prev_mode != pState->mode) { // convert 1/2/4-bpp previous image to make current bit depth
2689+
bbepConvertPrevBuffer(pState);
2690+
}
25772691

25782692
if (bbepEinkPower(pState, 1) != BBEP_SUCCESS) return BBEP_IO_ERROR;
25792693

0 commit comments

Comments
 (0)