From cc1278bea3fb4e11fd73392b3e6a584b51c1fd91 Mon Sep 17 00:00:00 2001 From: Laurence Bank Date: Sat, 10 Aug 2024 20:24:38 +0100 Subject: [PATCH] Fixed drawBMP to handle images larger than 256x256 --- library.properties | 2 +- src/OneBitDisplay.cpp | 4 +- src/OneBitDisplay.h | 9 ++-- src/obd.inl | 97 +++++++++++++++++++++++++++++++++++++++---- src/obd_gfx.inl | 14 +++---- 5 files changed, 104 insertions(+), 22 deletions(-) diff --git a/library.properties b/library.properties index ab13bd8..e64556c 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=OneBitDisplay -version=2.3.1 +version=2.3.2 author=Larry Bank maintainer=Larry Bank sentence=OLED, LCD and e-paper library for 1-bit per pixel displays. diff --git a/src/OneBitDisplay.cpp b/src/OneBitDisplay.cpp index e95eae5..e6ba50e 100644 --- a/src/OneBitDisplay.cpp +++ b/src/OneBitDisplay.cpp @@ -214,7 +214,7 @@ void ONE_BIT_DISPLAY::setCursor(int x, int y) _obd.iCursorY = y; } /* setCursor() */ -int ONE_BIT_DISPLAY::loadBMP(uint8_t *pBMP, int x, int y, int iFG, int iBG) +int ONE_BIT_DISPLAY::loadBMP(const uint8_t *pBMP, int x, int y, int iFG, int iBG) { return obdLoadBMP(&_obd, pBMP, x, y, iFG, iBG); } /* loadBMP() */ @@ -224,7 +224,7 @@ int ONE_BIT_DISPLAY::drawEPDGFX(int x, int y, int cx, int cy, uint8_t *pPlane0, return obdDrawEPDGFX(&_obd, x, y, cx, cy, pPlane0, pPlane1); } /* drawEPDGFX() */ -int ONE_BIT_DISPLAY::loadBMP3(uint8_t *pBMP, int x, int y) +int ONE_BIT_DISPLAY::loadBMP3(const uint8_t *pBMP, int x, int y) { return obdLoadBMP3(&_obd, pBMP, x, y); } /* loadBMP3() */ diff --git a/src/OneBitDisplay.h b/src/OneBitDisplay.h index cd2fd9b..8d9e1c8 100644 --- a/src/OneBitDisplay.h +++ b/src/OneBitDisplay.h @@ -109,6 +109,7 @@ enum { EPD29R_128x296, EPD29Y_128x296, // DEPG0290YN EPD293_128x296, + EPD294_128x296, // Waveshare newer 2.9" 1-bit 128x296 EPD42R_400x300, EPD42R2_400x300, // GDEQ042Z21 EPD213B_104x212, @@ -374,8 +375,8 @@ class ONE_BIT_DISPLAY void setCursor(int x, int y); void setPower(bool bOn); int drawEPDGFX(int x, int y, int cx, int cy, uint8_t *pPlane0, uint8_t *pPlane1); - int loadBMP(uint8_t *pBMP, int x, int y, int iFG, int iBG); - int loadBMP3(uint8_t *pBMP, int x, int y); + int loadBMP(const uint8_t *pBMP, int x, int y, int iFG, int iBG); + int loadBMP3(const uint8_t *pBMP, int x, int y); int16_t getCursorX(void); int16_t getCursorY(void); void wake(void); @@ -566,7 +567,7 @@ void obdSetContrast(OBDISP *pOBD, unsigned char ucContrast); // Pass the pointer to the beginning of the BMP file // First pass version assumes a full screen bitmap // -int obdLoadBMP(OBDISP *pOBD, uint8_t *pBMP, int x, int y, int iFG, int iBG); +int obdLoadBMP(OBDISP *pOBD, const uint8_t *pBMP, int x, int y, int iFG, int iBG); // // load a 4-bpp Windows bitmap // into memory for 3-color (BLACK/WHITE/RED) @@ -574,7 +575,7 @@ int obdLoadBMP(OBDISP *pOBD, uint8_t *pBMP, int x, int y, int iFG, int iBG); // It does a 'best match' of the colors to // B/W/R // -int obdLoadBMP3(OBDISP *pOBD, uint8_t *pBMP, int dx, int dy); +int obdLoadBMP3(OBDISP *pOBD, const uint8_t *pBMP, int dx, int dy); // // Power up/down the display // useful for low power situations diff --git a/src/obd.inl b/src/obd.inl index 6ceae38..b8990e4 100644 --- a/src/obd.inl +++ b/src/obd.inl @@ -791,6 +791,27 @@ const uint8_t epd213b_init_sequence_full[] PROGMEM = 0x00 // end of table }; /* epd213b_init_sequence_full[] */ +const uint8_t epd294_init_sequence_full[] PROGMEM = +{ +// 0x02, 0x74, 0x54, +// 0x02, 0x7e, 0x3b, +// 0x03, 0x2b, 0x04, 0x63, +// 0x05, 0x0c, 0x8f, 0x8f, 0x8f, 0x3f, + 0x04, 0x01, 0x27, 0x01, 0x00, + 0x02, 0x11, 0x03, + 0x03, 0x44, 0x00, 0x0f, + 0x05, 0x45, 0x00, 0x00, 0x27, 0x01, + 0x03, 0x21, 0x00, 0x80, + 0x02, 0x3c, 0xc0, + 0x02, 0x18, 0x80, + 0x02, 0x22, 0xb1, + 0x01, 0x20, + BUSY_WAIT, + 0x02, 0x4e, 0x00, + 0x03, 0x4f, 0x00, 0x00, + 0x00 // end of table +}; /* epd294_init_sequence_full[] */ + const uint8_t epd293_init_sequence_full[] PROGMEM = { // 0x01, SSD1608_SW_RESET, @@ -1411,6 +1432,28 @@ const uint8_t epd213_lut[] PROGMEM = }; #endif +static const uint8_t epd294_lut_partial[] PROGMEM = { +0x0,0x40,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, +0x80,0x80,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, +0x40,0x40,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, +0x0,0x80,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, +0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, +0x0A,0x0,0x0,0x0,0x0,0x0,0x2, +0x1,0x0,0x0,0x0,0x0,0x0,0x0, +0x1,0x0,0x0,0x0,0x0,0x0,0x0, +0x0,0x0,0x0,0x0,0x0,0x0,0x0, +0x0,0x0,0x0,0x0,0x0,0x0,0x0, +0x0,0x0,0x0,0x0,0x0,0x0,0x0, +0x0,0x0,0x0,0x0,0x0,0x0,0x0, +0x0,0x0,0x0,0x0,0x0,0x0,0x0, +0x0,0x0,0x0,0x0,0x0,0x0,0x0, +0x0,0x0,0x0,0x0,0x0,0x0,0x0, +0x0,0x0,0x0,0x0,0x0,0x0,0x0, +0x0,0x0,0x0,0x0,0x0,0x0,0x0, +0x22,0x22,0x22,0x22,0x22,0x22,0x0,0x0,0x0, +//0x22,0x17,0x41,0xB0,0x32,0x36, +}; + static const uint8_t epd293_lut_partial[] PROGMEM = { 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, @@ -1681,6 +1724,19 @@ void obdSPIInit(OBDISP *pOBD, int iType, int iDC, int iCS, int iReset, int iMOSI return; // nothing else to do yet } #endif // __AVR__ + else if (iType == EPD294_128x296) + { + pOBD->native_width = pOBD->width = 128; + pOBD->native_height = pOBD->height = 296; + pOBD->busy_idle = LOW; + pOBD->can_flip = 0; + //pOBD->x_offset = 2; // column byte offset + pOBD->chip_type = OBD_CHIP_SSD16xx; + pOBD->iFlags |= OBD_HAS_FAST_UPDATE; + pOBD->pInitFull = epd294_init_sequence_full; + pOBD->type = EPD293_128x296; // same for the rest + return; // nothing else to do yet + } else if (iType == EPD42B_400x300) { pOBD->native_width = pOBD->width = 400; @@ -3523,6 +3579,23 @@ uint8_t *pBuffer; } // 270 } /* EPDWriteImage4bpp() */ #endif // !WIMPY_MCU +const uint8_t epd294_init_sequence_part[] = +{ + 0x0b, 0x37, 0,0,0,0,0,0x40,0,0,0,0, + 0x04, 0x01, 0x27, 0x01, 0x00, + 0x02, 0x11, 0x03, + 0x03, 0x44, 0x00, 0x0f, + 0x05, 0x45, 0x00, 0x00, 0x27, 0x01, + 0x03, 0x21, 0x00, 0x80, + 0x02, 0x3c, 0xc0, + 0x02, 0x22, 0xc0, + 0x01, 0x20, + BUSY_WAIT, + 0x02, 0x4e, 0x00, + 0x03, 0x4f, 0x00, 0x00, + 0x00 // end of sequence +}; /* epd294_init_sequence_part */ + const uint8_t epd293_init_sequence_part[] = { // 0x01, SSD1608_SW_RESET, @@ -3545,7 +3618,7 @@ const uint8_t epd293_init_sequence_part[] = 0x02, 0x4e, 0x00, 0x03, 0x4f, 0x00, 0x00, 0x00 // end of table -}; /* epd293_init_sequence_full[] */ +}; /* epd293_init_sequence_part[] */ const uint8_t epd293_lut[] = { @@ -3563,13 +3636,21 @@ void EPD293_Begin(OBDISP *pOBD, int x, int y, int w, int h, int bPartial) (void)w; (void)h; if (bPartial) { - EPDSendCMDSequence(pOBD, epd293_init_sequence_part); - // send LUT - obdWriteCommand(pOBD, 0x32); - memcpy_P(u8Cache, epd293_lut_partial, sizeof(epd293_lut_partial)); - RawWriteData(pOBD, u8Cache, sizeof(epd293_lut_partial)); + if (pOBD->pInitFull == epd294_init_sequence_full) { // 294 + // send LUT + obdWriteCommand(pOBD, 0x32); + memcpy_P(u8Cache, epd294_lut_partial, sizeof(epd294_lut_partial)); + RawWriteData(pOBD, u8Cache, sizeof(epd294_lut_partial)); + EPDSendCMDSequence(pOBD, epd294_init_sequence_part); + } else { + EPDSendCMDSequence(pOBD, epd293_init_sequence_part); + // send LUT + obdWriteCommand(pOBD, 0x32); + memcpy_P(u8Cache, epd293_lut_partial, sizeof(epd293_lut_partial)); + RawWriteData(pOBD, u8Cache, sizeof(epd293_lut_partial)); + } } else { - EPDSendCMDSequence(pOBD, epd293_init_sequence_full); + EPDSendCMDSequence(pOBD, pOBD->pInitFull); } } /* EPD293_Begin() */ @@ -4412,7 +4493,7 @@ int i, tx, ty; } RawWriteData(pOBD, uc, 4); // set ram counter to start of this region - EPD_CMD2(pOBD, SSD1608_SET_RAMXCOUNT, tx); + EPD_CMD2(pOBD, SSD1608_SET_RAMXCOUNT, tx+pOBD->x_offset); uc[0] = ty; uc[1] = (ty>>8); obdWriteCommand(pOBD, SSD1608_SET_RAMYCOUNT); diff --git a/src/obd_gfx.inl b/src/obd_gfx.inl index 61dc175..bbb8299 100644 --- a/src/obd_gfx.inl +++ b/src/obd_gfx.inl @@ -572,7 +572,7 @@ static void obdCachedWrite(OBDISP *pOBD, uint8_t *pData, uint8_t u8Len, int bRen obdCachedFlush(pOBD, bRender); // write the old data } memcpy(&u8Cache[u8End], pData, u8Len); - u8End += u8Len; + u8End = u8End + u8Len; } /* obdCachedWrite() */ // @@ -1104,12 +1104,12 @@ uint8_t i; // draw the 1's bits as the FG color and leave // the background (0 pixels) unchanged - aka transparent. // -int obdLoadBMP(OBDISP *pOBD, uint8_t *pBMP, int dx, int dy, int iFG, int iBG) +int obdLoadBMP(OBDISP *pOBD, const uint8_t *pBMP, int dx, int dy, int iFG, int iBG) { int16_t i16, cx, cy; int iOffBits; // offset to bitmap data -int iPitch; -uint8_t x, y, b=0, *s, *d=NULL; +int x, y, iPitch; +uint8_t b=0, *s, *d=NULL; uint8_t ucFill, dst_mask=0, src_mask; uint8_t bFlipped = 0; @@ -1162,7 +1162,7 @@ uint8_t bFlipped = 0; if ((y & 7) == 0) memset(u8Cache, ucFill, sizeof(u8Cache)); } - s = &pBMP[iOffBits + (y*iPitch)]; + s = (uint8_t *)&pBMP[iOffBits + (y*iPitch)]; src_mask = 0; if (!pOBD->ucScreen) // direct to display { @@ -1220,7 +1220,7 @@ uint8_t bFlipped = 0; // Pass the pointer to the beginning of the BMP file // First pass version assumes a full screen bitmap // -int obdLoadBMP3(OBDISP *pOBD, uint8_t *pBMP, int dx, int dy) +int obdLoadBMP3(OBDISP *pOBD, const uint8_t *pBMP, int dx, int dy) { int16_t i16, cx, cy, bpp; int x, y, iOffBits; // offset to bitmap data @@ -1288,7 +1288,7 @@ uint8_t ucColorMap[16]; { dst_mask = 1 << ((y+dy) & 7); d = &pOBD->ucScreen[(((y+dy)>>3)*iDestPitch)+dx]; - s = &pBMP[iOffBits+(y*iPitch)]; + s = (uint8_t *)&pBMP[iOffBits+(y*iPitch)]; for (x=0; x