mirror of
https://github.com/usetrmnl/bb_epaper.git
synced 2026-04-29 13:43:26 -07:00
Added red color support
This commit is contained in:
+67
-2
@@ -108,7 +108,7 @@ const uint8_t epd29_init_sequence_full[] PROGMEM = {
|
||||
0x00 // end of table
|
||||
};
|
||||
|
||||
const uint8_t epd42r_init_sequence[] PROGMEM = {
|
||||
const uint8_t epd42r_init_sequence_full[] PROGMEM = {
|
||||
0x01, 0x12, // soft reset
|
||||
BUSY_WAIT,
|
||||
0x02, 0x74, 0x54, // set analog block control
|
||||
@@ -948,6 +948,7 @@ const EPD_PANEL panelDefs[] PROGMEM = {
|
||||
{0}, // undefined panel
|
||||
{400, 300, epd42_init_sequence_full, NULL, epd42_init_sequence_part, 0, BBEI_CHIP_UC81xx}, // EPD42_400x300
|
||||
{400, 300, epd42b_init_sequence_full, epd42b_init_sequence_fast, epd42b_init_sequence_part, 0, BBEI_CHIP_SSD16xx}, // EPD42B_400x300
|
||||
{122, 250, epd213_122x250_init_sequence_full, NULL, epd213_122x250_init_sequence_part, 0, BBEI_CHIP_SSD16xx}, // EPD213_122x250 WaveShare
|
||||
{122, 250, epd213b_init_sequence_full, NULL, epd213b_init_sequence_part, 0, BBEI_CHIP_SSD16xx}, // EPD213B_122x250
|
||||
{128, 296, epd293_init_sequence_full, epd293_init_sequence_fast, epd293_init_sequence_part, 0, BBEI_CHIP_SSD16xx}, // EPD293_128x296
|
||||
{128, 296, epd294_init_sequence_full, NULL, NULL, 0, BBEI_CHIP_SSD16xx}, // EPD294_128x296
|
||||
@@ -958,6 +959,9 @@ const EPD_PANEL panelDefs[] PROGMEM = {
|
||||
{128, 296, epd29r_init_sequence_full, NULL, NULL, BBEI_3COLOR, BBEI_CHIP_SSD16xx}, // EPD29R_128x296
|
||||
{192, 176, epd122_init_sequence_full, epd122_init_sequence_fast, epd122_init_sequence_part, 0, BBEI_CHIP_SSD16xx}, // EPD122_192x176
|
||||
{152, 152, epd154r_init_sequence_full, NULL, NULL, BBEI_3COLOR, BBEI_CHIP_SSD16xx}, // EPD154R_152x152
|
||||
{400, 300, epd42r_init_sequence_full, NULL, NULL, BBEI_3COLOR, BBEI_CHIP_SSD16xx}, // EPD42R_400x300
|
||||
{400, 300, epd42r2_init_sequence_full, NULL, NULL, BBEI_3COLOR, BBEI_CHIP_UC81xx}, // EPD42R2_400x300
|
||||
{240, 416, epd37_init_sequence_full, NULL, epd37_init_sequence_part, 0, BBEI_CHIP_UC81xx}, // EPD37_240x416
|
||||
};
|
||||
int bbeiSetPanelType(BBEIDISP *pBBEI, int iPanel)
|
||||
{
|
||||
@@ -1059,12 +1063,73 @@ uint8_t *s;
|
||||
} // while more commands to send
|
||||
} /* bbeiSendCMDSequence() */
|
||||
|
||||
//
|
||||
// Fill the display with a color or byte pattern
|
||||
// e.g. all black (0x00) or all white (0xff)
|
||||
// if there is no backing buffer, write directly to
|
||||
// the EPD's framebuffer
|
||||
//
|
||||
void bbeiFill(BBEIDISP *pBBEI, unsigned char ucData, int iPlane)
|
||||
{
|
||||
uint8_t uc1, uc2;
|
||||
int y, iSize, iPitch;
|
||||
uint8_t ucCMD1, ucCMD2;
|
||||
|
||||
if (pBBEI == NULL) return;
|
||||
|
||||
pBBEI->iCursorX = pBBEI->iCursorY = 0;
|
||||
iPitch = ((pBBEI->native_width+7)/8);
|
||||
iSize = pBBEI->native_height * iPitch;
|
||||
if (pBBEI->ucScreen) { // there's a local framebuffer, use it
|
||||
if (ucData == BBEI_WHITE) ucData = 0xff;
|
||||
else if (ucData == BBEI_BLACK) ucData = 0;
|
||||
memset(pBBEI->ucScreen, ucData, iSize);
|
||||
} else { // write directly to the EPD's framebuffer
|
||||
if (pBBEI->iFlags & BBEI_3COLOR) {
|
||||
if (ucData == BBEI_WHITE) {
|
||||
uc1 = 0xff; uc2 = 0x00; // red plane has priority
|
||||
} else if (ucData == BBEI_BLACK) {
|
||||
uc1 = 0x00; uc2 = 0x00;
|
||||
} else if (ucData == BBEI_RED) {
|
||||
uc1 = 0x00; uc2 = 0xff;
|
||||
}
|
||||
} else { // for B/W, both planes get the same data
|
||||
if (ucData == BBEI_WHITE) ucData = 0xff;
|
||||
else if (ucData == BBEI_BLACK) ucData = 0;
|
||||
uc1 = uc2 = ucData;
|
||||
}
|
||||
if (pBBEI->chip_type == BBEI_CHIP_UC81xx) {
|
||||
ucCMD1 = UC8151_DTM2;
|
||||
ucCMD2 = UC8151_DTM1;
|
||||
} else {
|
||||
ucCMD1 = SSD1608_WRITE_RAM;
|
||||
ucCMD2 = SSD1608_WRITE_ALTRAM;
|
||||
}
|
||||
// Write one or both memory planes to the EPD
|
||||
if (iPlane == PLANE_0 || iPlane == PLANE_DUPLICATE) { // write to first plane
|
||||
bbeiSetPosition(pBBEI, 0,0, pBBEI->native_width, pBBEI->native_height);
|
||||
bbeiWriteCmd(pBBEI, ucCMD1);
|
||||
for (y=0; y<pBBEI->native_height; y++) {
|
||||
memset(u8Cache, uc1, iPitch); // the data is overwritten after each write
|
||||
bbeiWriteData(pBBEI, u8Cache, iPitch);
|
||||
} // for y
|
||||
}
|
||||
if (iPlane == PLANE_1 || iPlane == PLANE_DUPLICATE) { // write to first plane
|
||||
bbeiSetPosition(pBBEI, 0,0, pBBEI->native_width, pBBEI->native_height);
|
||||
bbeiWriteCmd(pBBEI, ucCMD2);
|
||||
for (y=0; y<pBBEI->native_height; y++) {
|
||||
memset(u8Cache, uc2, iPitch); // the data is overwritten after each write
|
||||
bbeiWriteData(pBBEI, u8Cache, iPitch);
|
||||
} // for y
|
||||
}
|
||||
}
|
||||
} /* bbeiFill() */
|
||||
|
||||
int bbeiRefresh(BBEIDISP *pBBEI, int iMode)
|
||||
{
|
||||
if (iMode != REFRESH_FULL && iMode != REFRESH_FAST && iMode != REFRESH_PARTIAL)
|
||||
return BBEI_ERROR_BAD_PARAMETER;
|
||||
|
||||
bbeiWakeUp(pBBEI); // tickle the reset line
|
||||
switch (iMode) {
|
||||
case REFRESH_FULL:
|
||||
bbeiSendCMDSequence(pBBEI, pBBEI->pInitFull);
|
||||
|
||||
+37
-183
@@ -574,9 +574,9 @@ void bbeiWriteStringCustom(BBEIDISP *pBBEI, BB_FONT *pFont, int x, int y, char *
|
||||
{
|
||||
int rc, i, h, w, end_y, dx, dy, ty, iSrcPitch, iPitch;
|
||||
unsigned int c;
|
||||
uint8_t *s;
|
||||
uint8_t *s, bInvert = 0;
|
||||
BB_GLYPH *pGlyph;
|
||||
uint8_t *pBits, u8CMD, u8EndMask;
|
||||
uint8_t *pBits, u8CMD1, u8CMD2, u8CMD, u8EndMask;
|
||||
|
||||
if (x == -1)
|
||||
x = pBBEI->iCursorX;
|
||||
@@ -636,9 +636,16 @@ uint8_t *pBits, u8CMD, u8EndMask;
|
||||
iPitch = (w+7)/8;
|
||||
// start writing into the correct plane
|
||||
if (pBBEI->chip_type == BBEI_CHIP_UC81xx) {
|
||||
u8CMD = /*(iPlane) ? UC8151_DTM1 : */UC8151_DTM2;
|
||||
u8CMD1 = UC8151_DTM2;
|
||||
u8CMD2 = UC8151_DTM1;
|
||||
} else {
|
||||
u8CMD = /*(iPlane) ? SSD1608_WRITE_ALTRAM :*/ SSD1608_WRITE_RAM;
|
||||
u8CMD1 = SSD1608_WRITE_RAM;
|
||||
u8CMD2 = SSD1608_WRITE_ALTRAM;
|
||||
}
|
||||
u8CMD = u8CMD1;
|
||||
if (iColor == BBEI_BLACK) bInvert = 1;
|
||||
else if (iColor == BBEI_RED && (pBBEI->iFlags & BBEI_3COLOR)) {
|
||||
u8CMD = u8CMD2; // second plane is red (inverted)
|
||||
}
|
||||
bbeiWriteCmd(pBBEI, u8CMD); // memory write command
|
||||
for (ty=dy; ty<end_y && ty < pBBEI->native_height; ty++) {
|
||||
@@ -657,7 +664,7 @@ uint8_t *pBits, u8CMD, u8EndMask;
|
||||
*s++ = uc0; // store final byte
|
||||
*s++ = 0; // and a zero for good measure
|
||||
}
|
||||
if (iColor == BBEI_BLACK) InvertBytes(u8Cache, iPitch);
|
||||
if (bInvert) InvertBytes(u8Cache, iPitch);
|
||||
bbeiWriteData(pBBEI, u8Cache, iPitch); // write each row into the EPD framebuffer
|
||||
} // for y
|
||||
} // if not drawing a space
|
||||
@@ -669,14 +676,15 @@ uint8_t *pBits, u8CMD, u8EndMask;
|
||||
} // while drawing characters
|
||||
pBBEI->iCursorX = x;
|
||||
pBBEI->iCursorY = y;
|
||||
} /* EPDWriteStringDirect() *///
|
||||
} /* EPDWriteStringCustom() */
|
||||
//
|
||||
// Draw a string of normal (8x8), small (6x8) or large (16x32) characters
|
||||
// At the given col+row
|
||||
//
|
||||
int bbeiWriteString(BBEIDISP *pBBEI, int x, int y, char *szMsg, int iSize, int iColor)
|
||||
{
|
||||
int i, iFontOff, iLen;
|
||||
uint8_t c, *s, ucCMD1, ucCMD2;
|
||||
uint8_t c, *s, ucCMD, ucCMD1, ucCMD2;
|
||||
int iOldFG; // old fg color to make sure red works
|
||||
uint8_t u8Temp[128];
|
||||
|
||||
@@ -688,10 +696,9 @@ uint8_t u8Temp[128];
|
||||
ucCMD1 = SSD1608_WRITE_RAM;
|
||||
ucCMD2 = SSD1608_WRITE_ALTRAM;
|
||||
}
|
||||
|
||||
// If we're in bufferless mode, we'll need to invert the requested color
|
||||
if (!pBBEI->ucScreen) {
|
||||
iColor = 1 - iColor; // invert the color
|
||||
ucCMD = ucCMD1;
|
||||
if ((pBBEI->iFlags & BBEI_3COLOR) && iColor == BBEI_RED || pBBEI->iPlane == 1) {
|
||||
ucCMD = ucCMD2; // write to second plane for red
|
||||
}
|
||||
if (x == -1 || y == -1) // use the cursor position
|
||||
{
|
||||
@@ -720,14 +727,14 @@ uint8_t u8Temp[128];
|
||||
// we can't directly use the pointer to FLASH memory, so copy to a local buffer
|
||||
u8Temp[0] = 0; // first column is blank
|
||||
memcpy_P(&u8Temp[1], &ucFont[iFontOff], 7); // only needed on AVR
|
||||
if (iColor == BBEI_WHITE) InvertBytes(u8Temp, 8);
|
||||
if (iColor == BBEI_BLACK) InvertBytes(u8Temp, 8);
|
||||
iLen = 8;
|
||||
if (pBBEI->iCursorX + iLen > pBBEI->width) { // clip right edge
|
||||
iLen = pBBEI->width - pBBEI->iCursorX;
|
||||
}
|
||||
if (!pBBEI->ucScreen) { // bufferless mode, rotate the coordinate system to fit the situation
|
||||
bbeiSetPosition(pBBEI, pBBEI->native_width-8-pBBEI->iCursorY, pBBEI->iCursorX, 8, pBBEI->native_height-pBBEI->iCursorX);
|
||||
bbeiWriteCmd(pBBEI, ucCMD1); // write to "new" plane
|
||||
bbeiWriteCmd(pBBEI, ucCMD); // write to "new" plane
|
||||
bbeiWriteData(pBBEI, u8Temp, iLen);
|
||||
} else { // draw in memory
|
||||
// DEBUG
|
||||
@@ -751,7 +758,7 @@ uint8_t u8Temp[128];
|
||||
s = (unsigned char *)&ucSmallFont[(int)c*5];
|
||||
u8Temp[0] = 0; // first column is blank
|
||||
memcpy_P(&u8Temp[1], s, 6);
|
||||
if (iColor == BBEI_WHITE)
|
||||
if (iColor == BBEI_BLACK)
|
||||
InvertBytes(u8Temp, 6);
|
||||
// Stretch the font to double width + double height
|
||||
memset(&u8Temp[6], 0, 24); // write 24 new bytes
|
||||
@@ -789,7 +796,7 @@ uint8_t u8Temp[128];
|
||||
{
|
||||
if (ty < 3) // top half
|
||||
{
|
||||
if (iColor == BBEI_WHITE) {
|
||||
if (iColor == BBEI_BLACK) {
|
||||
pDest[1] &= ~(1 << ((ty * 2)+1));
|
||||
pDest[2] &= ~(1 << ((ty * 2)+1));
|
||||
pDest[1] &= ~(1 << ((ty+1) * 2));
|
||||
@@ -803,7 +810,7 @@ uint8_t u8Temp[128];
|
||||
}
|
||||
else if (ty == 3) // on the border
|
||||
{
|
||||
if (iColor == BBEI_WHITE) {
|
||||
if (iColor == BBEI_BLACK) {
|
||||
pDest[1] &= ~0x80; pDest[2] &= ~0x80;
|
||||
pDest[13] &= ~1; pDest[14] &= ~1;
|
||||
} else {
|
||||
@@ -813,7 +820,7 @@ uint8_t u8Temp[128];
|
||||
}
|
||||
else // bottom half
|
||||
{
|
||||
if (iColor == BBEI_WHITE) {
|
||||
if (iColor == BBEI_BLACK) {
|
||||
pDest[13] &= ~(1 << (2*(ty-4)+1));
|
||||
pDest[14] &= ~(1 << (2*(ty-4)+1));
|
||||
pDest[13] &= ~(1 << ((ty-3) * 2));
|
||||
@@ -830,7 +837,7 @@ uint8_t u8Temp[128];
|
||||
{
|
||||
if (ty < 4) // top half
|
||||
{
|
||||
if (iColor == BBEI_WHITE) {
|
||||
if (iColor == BBEI_BLACK) {
|
||||
pDest[1] &= ~(1 << ((ty * 2)+1));
|
||||
pDest[2] &= ~(1 << ((ty+1) * 2));
|
||||
} else {
|
||||
@@ -840,7 +847,7 @@ uint8_t u8Temp[128];
|
||||
}
|
||||
else
|
||||
{
|
||||
if (iColor == BBEI_WHITE) {
|
||||
if (iColor == BBEI_BLACK) {
|
||||
pDest[13] &= ~(1 << (2*(ty-4)+1));
|
||||
pDest[14] &= ~(1 << ((ty-3) * 2));
|
||||
} else {
|
||||
@@ -857,10 +864,10 @@ uint8_t u8Temp[128];
|
||||
iLen = pBBEI->width - pBBEI->iCursorX;
|
||||
if (!pBBEI->ucScreen) { // bufferless mode
|
||||
bbeiSetPosition(pBBEI, pBBEI->native_width-8-pBBEI->iCursorY, pBBEI->iCursorX, 8, iLen);
|
||||
bbeiWriteCmd(pBBEI, ucCMD1); // write to "new" plane
|
||||
bbeiWriteCmd(pBBEI, ucCMD); // write to "new" plane
|
||||
bbeiWriteData(pBBEI, &u8Temp[6], iLen);
|
||||
bbeiSetPosition(pBBEI, pBBEI->native_width-16-pBBEI->iCursorY, pBBEI->iCursorX, 8, iLen);
|
||||
bbeiWriteCmd(pBBEI, ucCMD1); // write to "new" plane
|
||||
bbeiWriteCmd(pBBEI, ucCMD); // write to "new" plane
|
||||
bbeiWriteData(pBBEI, &u8Temp[18], iLen);
|
||||
} else { // write to RAM
|
||||
// DEBUG
|
||||
@@ -885,13 +892,13 @@ uint8_t u8Temp[128];
|
||||
// we can't directly use the pointer to FLASH memory, so copy to a local buffer
|
||||
u8Temp[0] = 0; // first column is blank
|
||||
memcpy_P(&u8Temp[1], &ucSmallFont[(int)c*5], 5);
|
||||
if (iColor == BBEI_WHITE) InvertBytes(u8Temp, 6);
|
||||
if (iColor == BBEI_BLACK) InvertBytes(u8Temp, 6);
|
||||
iLen = 6;
|
||||
if (pBBEI->iCursorX + iLen > pBBEI->width) // clip right edge
|
||||
iLen = pBBEI->width - pBBEI->iCursorX;
|
||||
if (!pBBEI->ucScreen) { // bufferless mode
|
||||
bbeiSetPosition(pBBEI, pBBEI->iCursorX, pBBEI->iCursorY, 8, iLen);
|
||||
bbeiWriteCmd(pBBEI, ucCMD1); // write to "new" plane
|
||||
bbeiWriteCmd(pBBEI, ucCMD); // write to "new" plane
|
||||
bbeiWriteData(pBBEI, u8Temp, iLen);
|
||||
} else { // write to RAM
|
||||
// DEBUG
|
||||
@@ -910,186 +917,33 @@ uint8_t u8Temp[128];
|
||||
pBBEI->iFG = iOldFG; // restore color
|
||||
return BBEI_ERROR_BAD_PARAMETER; // invalid size
|
||||
} /* bbeiWriteString() */
|
||||
#ifdef FUTURE
|
||||
//
|
||||
// Get the width of text in a custom font
|
||||
//
|
||||
void bbeiGetStringBox(BB_FONT *pFont, char *szMsg, int *width, int *top, int *bottom)
|
||||
void bbeiGetStringBox(BB_FONT *pFont, const char *szMsg, int *width, int *top, int *bottom)
|
||||
{
|
||||
int cx = 0;
|
||||
unsigned int c, i = 0;
|
||||
GFXglyph *pGlyph;
|
||||
BB_GLYPH *pBBG;
|
||||
int miny, maxy;
|
||||
|
||||
if (width == NULL || top == NULL || bottom == NULL || pFont == NULL || szMsg == NULL) return; // bad pointers
|
||||
miny = 100; maxy = 0;
|
||||
miny = 1000; maxy = 0;
|
||||
while (szMsg[i]) {
|
||||
c = szMsg[i++];
|
||||
if (c < pFont->first || c > pFont->last) // undefined character
|
||||
continue; // skip it
|
||||
c -= pFont->first; // first char of font defined
|
||||
pGlyph = &pFont->glyph[c];
|
||||
cx += pGlyph->xAdvance;
|
||||
if (pGlyph->yOffset < miny) miny = pGlyph->yOffset;
|
||||
if (pGlyph->height+pGlyph->yOffset > maxy) maxy = pGlyph->height+pGlyph->yOffset;
|
||||
pBBG = &pFont->glyphs[c];
|
||||
cx += pBBG->xAdvance;
|
||||
if (pBBG->yOffset < miny) miny = pBBG->yOffset;
|
||||
if (pBBG->height+pBBG->yOffset > maxy) maxy = pBBG->height+pBBG->yOffset;
|
||||
}
|
||||
*width = cx;
|
||||
*top = miny;
|
||||
*bottom = maxy;
|
||||
} /* bbeiGetStringBox() */
|
||||
|
||||
//
|
||||
// Draw a string of characters in a custom font
|
||||
// A back buffer must be defined
|
||||
//
|
||||
int bbeiWriteStringCustom(BBEIDISP *pBBEI, GFXfont *pFont, int x, int y, char *szMsg, uint8_t ucColor)
|
||||
{
|
||||
int i, end_y, dx, dy, tx, ty, iBitOff;
|
||||
unsigned int c;
|
||||
uint8_t *s, *d, bits, ucFill=0, ucMask, uc;
|
||||
GFXfont font;
|
||||
GFXglyph glyph, *pGlyph;
|
||||
int iPitch, iRedOffset = 0;
|
||||
|
||||
if (pBBEI == NULL || pFont == NULL)
|
||||
return BBEI_ERROR_BAD_PARAMETER;
|
||||
if (pBBEI->ucScreen == NULL && pBBEI->type >= EPD42_400x300) {
|
||||
// EPD direct draw mode; colors are inverted
|
||||
if (ucColor == BBEI_BLACK)
|
||||
ucColor = 1-ucColor;
|
||||
ucFill = 0xff;
|
||||
}
|
||||
if (x == -1)
|
||||
x = pBBEI->iCursorX;
|
||||
if (y == -1)
|
||||
y = pBBEI->iCursorY;
|
||||
if (ucColor >= BBEI_YELLOW && pBBEI->iFlags & (BBEI_3COLOR | BBEI_4COLOR)) {
|
||||
// use the second half of the image buffer
|
||||
iRedOffset = pBBEI->width * ((pBBEI->height+7)/8);
|
||||
ucFill = 0x00;
|
||||
ucColor = BBEI_BLACK;
|
||||
}
|
||||
iPitch = pBBEI->width;
|
||||
// in case of running on Harvard architecture, get copy of data from FLASH
|
||||
memcpy_P(&font, pFont, sizeof(font));
|
||||
pGlyph = &glyph;
|
||||
|
||||
i = 0;
|
||||
while (szMsg[i] && x < pBBEI->width)
|
||||
{
|
||||
c = szMsg[i++];
|
||||
if (c < font.first || c > font.last) // undefined character
|
||||
continue; // skip it
|
||||
c -= font.first; // first char of font defined
|
||||
memcpy_P(&glyph, &font.glyph[c], sizeof(glyph));
|
||||
dx = x + pGlyph->xOffset; // offset from character UL to start drawing
|
||||
dy = y + pGlyph->yOffset;
|
||||
s = font.bitmap + pGlyph->bitmapOffset; // start of bitmap data
|
||||
// Bitmap drawing loop. Image is MSB first and each pixel is packed next
|
||||
// to the next (continuing on to the next character line)
|
||||
iBitOff = 0; // bitmap offset (in bits)
|
||||
bits = uc = 0; // bits left in this font byte
|
||||
end_y = dy + pGlyph->height;
|
||||
if (dy < 0) { // skip these lines
|
||||
iBitOff += (pGlyph->width * (-dy));
|
||||
dy = 0;
|
||||
}
|
||||
if (!pBBEI->ucScreen) {
|
||||
memset(u8Cache, ucFill, sizeof(u8Cache));
|
||||
}
|
||||
for (ty=dy; ty<end_y && ty < pBBEI->height; ty++) {
|
||||
ucMask = 1<<(ty & 7); // destination bit number for this line
|
||||
if (pBBEI->ucScreen) {
|
||||
d = &pBBEI->ucScreen[iRedOffset + (ty >> 3) * iPitch + dx]; // internal buffer dest
|
||||
} else {
|
||||
d = u8Cache; // no ram; buffer 8 lines at a time
|
||||
}
|
||||
for (tx=0; tx<pGlyph->width; tx++) {
|
||||
if (bits == 0) { // need to read more font data
|
||||
uc = pgm_read_byte(&s[iBitOff>>3]); // get more font bitmap data
|
||||
bits = 8 - (iBitOff & 7); // we might not be on a byte boundary
|
||||
iBitOff += bits; // because of a clipped line
|
||||
uc <<= (8-bits);
|
||||
} // if we ran out of bits
|
||||
if ((dx+tx) < pBBEI->width) { // foreground pixel
|
||||
if (uc & 0x80) {
|
||||
if (ucColor == BBEI_BLACK)
|
||||
d[tx] |= ucMask;
|
||||
else
|
||||
d[tx] &= ~ucMask;
|
||||
} else {
|
||||
if (ucColor == BBEI_BLACK)
|
||||
d[tx] &= ~ucMask;
|
||||
else
|
||||
d[tx] |= ucMask;
|
||||
}
|
||||
}
|
||||
bits--; // next bit
|
||||
uc <<= 1;
|
||||
} // for x
|
||||
if (!pBBEI->ucScreen && (ucMask == 0x80 || ty == end_y-1)) { // dump this line
|
||||
bbeiSetPosition(pBBEI, dx, (ty & 0xfff8), pGlyph->width*8, 1);
|
||||
bbeiWriteData(pBBEI, u8Cache, pGlyph->width);
|
||||
memset(u8Cache, ucFill, sizeof(u8Cache)); // NB: assume no DMA
|
||||
}
|
||||
} // for y
|
||||
x += pGlyph->xAdvance; // width of this character
|
||||
} // while drawing characters
|
||||
pBBEI->iCursorX = x;
|
||||
pBBEI->iCursorY = y;
|
||||
return BBEI_SUCCESS;
|
||||
} /* bbeiWriteStringCustom() */
|
||||
#endif // FUTURE
|
||||
//
|
||||
// Fill the display with a color or byte pattern
|
||||
// e.g. all black (0x00) or all white (0xff)
|
||||
// if there is no backing buffer, write directly to
|
||||
// the EPD's framebuffer
|
||||
//
|
||||
void bbeiFill(BBEIDISP *pBBEI, unsigned char ucData, int iPlane)
|
||||
{
|
||||
uint8_t uc;
|
||||
int y, iSize, iPitch;
|
||||
uint8_t ucCMD1, ucCMD2;
|
||||
|
||||
if (pBBEI == NULL) return;
|
||||
|
||||
pBBEI->iCursorX = pBBEI->iCursorY = 0;
|
||||
iPitch = ((pBBEI->native_width+7)/8);
|
||||
iSize = pBBEI->native_height * iPitch;
|
||||
uc = ucData;
|
||||
if (ucData == BBEI_WHITE) uc = 0xff;
|
||||
else if (ucData == BBEI_BLACK) uc = 0;
|
||||
if (pBBEI->ucScreen) { // there's a local framebuffer, use it
|
||||
memset(pBBEI->ucScreen, uc, iSize);
|
||||
} else { // write directly to the EPD's framebuffer
|
||||
if (pBBEI->chip_type == BBEI_CHIP_UC81xx) {
|
||||
ucCMD1 = UC8151_DTM1;
|
||||
ucCMD2 = UC8151_DTM2;
|
||||
} else {
|
||||
ucCMD1 = SSD1608_WRITE_RAM;
|
||||
ucCMD2 = SSD1608_WRITE_ALTRAM;
|
||||
}
|
||||
// Write one or both memory planes to the EPD
|
||||
if (iPlane == PLANE_0 || iPlane == PLANE_DUPLICATE) { // write to first plane
|
||||
bbeiSetPosition(pBBEI, 0,0, pBBEI->native_width, pBBEI->native_height);
|
||||
bbeiWriteCmd(pBBEI, ucCMD1);
|
||||
for (y=0; y<pBBEI->native_height; y++) {
|
||||
memset(u8Cache, uc, iPitch); // the data is overwritten after each write
|
||||
bbeiWriteData(pBBEI, u8Cache, iPitch);
|
||||
} // for y
|
||||
}
|
||||
if (iPlane == PLANE_1 || iPlane == PLANE_DUPLICATE) { // write to first plane
|
||||
bbeiSetPosition(pBBEI, 0,0, pBBEI->native_width, pBBEI->native_height);
|
||||
bbeiWriteCmd(pBBEI, ucCMD2);
|
||||
for (y=0; y<pBBEI->native_height; y++) {
|
||||
memset(u8Cache, uc, iPitch); // the data is overwritten after each write
|
||||
bbeiWriteData(pBBEI, u8Cache, iPitch);
|
||||
} // for y
|
||||
}
|
||||
}
|
||||
} /* bbeiFill() */
|
||||
|
||||
void bbeiAllocBuffer(BBEIDISP *pBBEI)
|
||||
{
|
||||
pBBEI->ucScreen = (uint8_t *)malloc(pBBEI->width * ((pBBEI->height+7)>>3));
|
||||
|
||||
+11
-1
@@ -76,6 +76,11 @@ void bbeiWaitBusy(BBEIDISP *pBBEI)
|
||||
//
|
||||
void bbeiCMD2(BBEIDISP *pBBEI, uint8_t cmd1, uint8_t cmd2)
|
||||
{
|
||||
if (!pBBEI->is_awake) {
|
||||
// if it's asleep, it can't receive commands
|
||||
bbeiWakeUp(pBBEI);
|
||||
pBBEI->is_awake = 1;
|
||||
}
|
||||
digitalWrite(pBBEI->iDCPin, LOW);
|
||||
#ifndef ARDUINO_ARCH_ESP32
|
||||
digitalWrite(pBBEI->iCSPin, LOW);
|
||||
@@ -93,6 +98,11 @@ void bbeiCMD2(BBEIDISP *pBBEI, uint8_t cmd1, uint8_t cmd2)
|
||||
//
|
||||
void bbeiWriteCmd(BBEIDISP *pBBEI, uint8_t cmd)
|
||||
{
|
||||
if (!pBBEI->is_awake) {
|
||||
// if it's asleep, it can't receive commands
|
||||
bbeiWakeUp(pBBEI);
|
||||
pBBEI->is_awake = 1;
|
||||
}
|
||||
digitalWrite(pBBEI->iDCPin, LOW);
|
||||
#ifndef ARDUINO_ARCH_ESP32
|
||||
digitalWrite(pBBEI->iCSPin, LOW);
|
||||
@@ -117,8 +127,8 @@ void bbeiSleep(BBEIDISP *pBBEI, int bDeep)
|
||||
}
|
||||
} else {
|
||||
bbeiCMD2(pBBEI, SSD1608_DEEP_SLEEP, (bDeep) ? 0x02 : 0x01); // deep sleep mode 1 keeps RAM, mode 2 loses RAM
|
||||
return;
|
||||
}
|
||||
pBBEI->is_awake = 0;
|
||||
} /* bbeiSleep() */
|
||||
//
|
||||
// Write 1 or more bytes as DATA (D/C set high)
|
||||
|
||||
+35
-44
@@ -314,78 +314,52 @@ char ucTemp[4];
|
||||
//
|
||||
#ifndef __AVR__
|
||||
size_t BBEINK::write(uint8_t c) {
|
||||
#ifdef FUTURE
|
||||
char szTemp[2]; // used to draw 1 character at a time to the C methods
|
||||
int w, h;
|
||||
|
||||
szTemp[0] = c; szTemp[1] = 0;
|
||||
if (_bbei.pFreeFont == NULL) { // use built-in fonts
|
||||
if (_bbei.iFont == -1) { // scaled 5x7 font
|
||||
h = (int)(_bbei.u32FontScaleY >> 8) * 8;
|
||||
w = (int)(_bbei.u32FontScaleX >> 8) * 6;
|
||||
} else if (_bbei.iFont == FONT_8x8 || _bbei.iFont == FONT_6x8) {
|
||||
if (_bbei.pFont == NULL) { // use built-in fonts
|
||||
if (_bbei.iFont == FONT_8x8 || _bbei.iFont == FONT_6x8) {
|
||||
h = 8;
|
||||
w = (_bbei.iFont == FONT_8x8) ? 8 : 6;
|
||||
} else if (_bbei.iFont == FONT_12x16 || _bbei.iFont == FONT_16x16) {
|
||||
} else if (_bbei.iFont == FONT_12x16) {
|
||||
h = 16;
|
||||
w = (_bbei.iFont == FONT_12x16) ? 12 : 16;
|
||||
} else { w = 16; h = 32; }
|
||||
w = 12;
|
||||
}
|
||||
|
||||
if (c == '\n') { // Newline?
|
||||
_bbei.iCursorX = 0; // Reset x to zero,
|
||||
_bbei.iCursorY += h; // advance y one line
|
||||
// should we scroll the screen up 1 line?
|
||||
if (_bbei.iCursorY >= _bbei.height && _bbei.ucScreen && _bbei.bScroll) {
|
||||
obdScroll1Line(&_bbei, h/8);
|
||||
if (_bbei.render) {
|
||||
obdDumpBuffer(&_bbei, NULL, false, false, false);
|
||||
}
|
||||
_bbei.iCursorY -= h;
|
||||
}
|
||||
} else if (c != '\r') { // Ignore carriage returns
|
||||
if (_bbei.wrap && ((_bbei.iCursorX + w) > _bbei.width)) { // Off right?
|
||||
_bbei.iCursorX = 0; // Reset x to zero,
|
||||
_bbei.iCursorY += h; // advance y one line
|
||||
// should we scroll the screen up 1 line?
|
||||
if (_bbei.iCursorY >= _bbei.height && _bbei.ucScreen && _bbei.bScroll) {
|
||||
obdScroll1Line(&_bbei, h/8);
|
||||
if (_bbei.render) {
|
||||
obdDumpBuffer(&_bbei, NULL, false, false, false);
|
||||
}
|
||||
_bbei.iCursorY -= h;
|
||||
}
|
||||
}
|
||||
if (_bbei.iFont == -1) { // scaled drawing
|
||||
obdScaledString(&_bbei, _bbei.iCursorX, _bbei.iCursorY, szTemp, FONT_6x8, _bbei.iFG, _bbei.u32FontScaleX, _bbei.u32FontScaleY, 0);
|
||||
_bbei.iCursorX += w;
|
||||
} else {
|
||||
obdWriteString(&_bbei, 0, -1, -1, szTemp, _bbei.iFont, _bbei.iFG, _bbei.render);
|
||||
if (_bbei.wrap && ((_bbei.iCursorX + w) > _bbei.width)) { // Off right?
|
||||
_bbei.iCursorX = 0; // Reset x to zero,
|
||||
_bbei.iCursorY += h; // advance y one line
|
||||
}
|
||||
bbeiWriteString(&_bbei, -1, -1, szTemp, _bbei.iFont, _bbei.iFG);
|
||||
}
|
||||
} else { // Custom font
|
||||
BB_FONT *pBBF = (BB_FONT *)_bbei.pFont;
|
||||
if (c == '\n') {
|
||||
_bbei.iCursorX = 0;
|
||||
_bbei.iCursorY += (uint8_t)pgm_read_byte(&_bbei.pFreeFont->yAdvance);
|
||||
_bbei.iCursorY += pBBF->height;
|
||||
} else if (c != '\r') {
|
||||
uint8_t first = pgm_read_word((const uint8_t*)&_bbei.pFreeFont->first);
|
||||
if ((c >= first) && (c <= (uint8_t)pgm_read_word((const uint8_t*)&_bbei.pFreeFont->last))) {
|
||||
GFXglyph *glyph = pgm_read_glyph_ptr(_bbei.pFreeFont, c - first);
|
||||
w = pgm_read_byte(&glyph->width);
|
||||
h = pgm_read_byte(&glyph->height);
|
||||
if (c >= pBBF->first && c <= pBBF->last) {
|
||||
BB_GLYPH *pBBG = &pBBF->glyphs[c-pBBF->first];
|
||||
w = pBBG->width;
|
||||
h = pBBG->height;
|
||||
if ((w > 0) && (h > 0)) { // Is there an associated bitmap?
|
||||
int16_t xo = (int8_t)pgm_read_word((const uint8_t*)&glyph->xOffset);
|
||||
int16_t xo = pBBG->xOffset;
|
||||
w += xo; // xadvance
|
||||
h = (uint8_t)pgm_read_byte(&_bbei.pFreeFont->yAdvance);
|
||||
h = pBBF->height;
|
||||
if (_bbei.wrap && ((_bbei.iCursorX + w) > _bbei.width)) {
|
||||
_bbei.iCursorX = 0;
|
||||
_bbei.iCursorY += h;
|
||||
}
|
||||
bbeiWriteStringCustom(&_bbei, _bbei.pFreeFont, -1, -1, szTemp, _bbei.iFG);
|
||||
bbeiWriteStringCustom(&_bbei, (BB_FONT *)_bbei.pFont, -1, -1, szTemp, _bbei.iFG, _bbei.iPlane);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif // FUTURE
|
||||
return 1;
|
||||
} /* write() */
|
||||
#endif // !__AVR__
|
||||
@@ -467,4 +441,21 @@ void BBEINK::drawString(const char *pText, int x, int y)
|
||||
}
|
||||
} /* drawString() */
|
||||
|
||||
void BBEINK::setPlane(int iPlane)
|
||||
{
|
||||
_bbei.iPlane = iPlane;
|
||||
}
|
||||
int BBEINK::getPlane(void)
|
||||
{
|
||||
return _bbei.iPlane;
|
||||
}
|
||||
|
||||
int BBEINK::getChip(void)
|
||||
{
|
||||
return _bbei.chip_type;
|
||||
}
|
||||
void BBEINK::getStringBox(const char *szMsg, int *width, int *top, int *bottom)
|
||||
{
|
||||
bbeiGetStringBox((BB_FONT *)_bbei.pFont, szMsg, width, top, bottom);
|
||||
}
|
||||
#endif // __cplusplus
|
||||
|
||||
+16
-13
@@ -44,11 +44,10 @@ enum {
|
||||
#define DEEP_SLEEP 1
|
||||
|
||||
// Display refresh modes
|
||||
enum {
|
||||
REFRESH_FULL=0,
|
||||
REFRESH_FAST,
|
||||
REFRESH_PARTIAL
|
||||
};
|
||||
#define REFRESH_FULL 0
|
||||
#define REFRESH_FAST 1
|
||||
#define REFRESH_PARTIAL 2
|
||||
|
||||
// controller chip types
|
||||
enum {
|
||||
BBEI_CHIP_NOT_DEFINED = 0,
|
||||
@@ -90,7 +89,8 @@ enum {
|
||||
EPD_PANEL_UNDEFINED=0,
|
||||
EPD42_400x300, // WFT0420CZ15
|
||||
EPD42B_400x300, // DEPG0420BN / GDEY042T81
|
||||
EPD213B_104x212,
|
||||
EPD213_122x250, // waveshare
|
||||
EPD213B_122x250, // GDEY0213B74
|
||||
EPD293_128x296,
|
||||
EPD294_128x296, // Waveshare newer 2.9" 1-bit 128x296
|
||||
EPD295_128x296, // harvested from Solum 2.9" BW ESLs
|
||||
@@ -100,6 +100,9 @@ enum {
|
||||
EPD29R_128x296,
|
||||
EPD122_192x176, // GDEM0122T61
|
||||
EPD154R_152x152,
|
||||
EPD42R_400x300,
|
||||
EPD42R2_400x300, // GDEQ042Z21
|
||||
EPD37_240x416, // GDEY037T03
|
||||
EPD_PANEL_COUNT
|
||||
};
|
||||
#ifdef FUTURE
|
||||
@@ -108,14 +111,10 @@ enum {
|
||||
EPD29_128x296,
|
||||
EPD29B_128x296,
|
||||
EPD29Y_128x296, // DEPG0290YN
|
||||
EPD42R_400x300,
|
||||
EPD42R2_400x300, // GDEQ042Z21
|
||||
EPD213R_104x212,
|
||||
EPD213R2_122x250, // DEPG0213RW
|
||||
EPD213R_104x212_d,
|
||||
EPD213_104x212,
|
||||
EPD213_122x250, // waveshare
|
||||
EPD213B_122x250, // GDEY0213B74
|
||||
EPD154_152x152, // GDEW0154M10
|
||||
EPD154R_152x152,
|
||||
EPD154Y_152x152, // DEPG0154YN
|
||||
@@ -126,7 +125,6 @@ enum {
|
||||
EPD266Y_152x296, // DEPG0266YN
|
||||
EPD31R_168x296, // DEPG0310RW
|
||||
EPD37Y_240x416, // DEPG0370YN
|
||||
EPD37_240x416, // GDEY037T03
|
||||
EPD579_792x272, // GDEY0579T93
|
||||
EPD583R_600x448,
|
||||
EPD75_800x480, // GDEY075T7
|
||||
@@ -260,7 +258,7 @@ uint32_t iSpeed;
|
||||
uint32_t iTimeout; // for e-ink panels
|
||||
uint8_t iDCPin, iMOSIPin, iCLKPin, iCSPin, iRSTPin, iBUSYPin;
|
||||
uint8_t x_offset, y_offset; // memory offsets
|
||||
uint8_t bBitBang, iPlane;
|
||||
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
|
||||
@@ -320,7 +318,10 @@ class BBEINK
|
||||
void sleep(int bDeep);
|
||||
void wait(bool bQuick = false);
|
||||
void drawString(const char *pText, int x, int y);
|
||||
|
||||
void setPlane(int iPlane);
|
||||
int getPlane(void);
|
||||
int getChip(void);
|
||||
void getStringBox(const char *szMsg, int *width, int *top, int *bottom);
|
||||
#ifdef FUTURE
|
||||
void setPlane(int iPlane);
|
||||
void drawSprite(uint8_t *pSprite, int cx, int cy, int iPitch, int x, int y, uint8_t iPriority);
|
||||
@@ -344,8 +345,10 @@ class BBEINK
|
||||
size_t write(uint8_t ucChar);
|
||||
void delayMicroseconds(int iTime);
|
||||
#else
|
||||
#ifndef __AVR__
|
||||
using Print::write;
|
||||
virtual size_t write(uint8_t);
|
||||
#endif // __AVR__
|
||||
#endif // _LINUX_
|
||||
|
||||
private:
|
||||
|
||||
Reference in New Issue
Block a user