diff --git a/examples/g5_mini_epaper/bart.h b/examples/g5_mini_epaper/bart.h new file mode 100644 index 0000000..18cf0dd --- /dev/null +++ b/examples/g5_mini_epaper/bart.h @@ -0,0 +1,33 @@ +// Created with image_to_c +// https://github.com/bitbank2/image_to_c +// +// bart +// Data size = 349 bytes +// +// for non-Arduino builds... +#ifndef PROGMEM +#define PROGMEM +#endif +const uint8_t bart[] PROGMEM = { + 0xcc,0xa8,0xe9,0xcc,0x9f,0x09,0x1c,0x2c,0x3c,0x14,0x11,0x0a,0xa0,0xb6,0xe6,0x3e, + 0xe1,0x04,0xec,0xbc,0x74,0x21,0xf6,0x61,0x35,0x91,0xc5,0x98,0x25,0x74,0x14,0x1e, + 0xe0,0x91,0x09,0x98,0x29,0xa5,0x22,0xe6,0x0a,0x32,0x23,0x84,0x08,0x17,0xce,0x10, + 0x4e,0xa9,0x88,0xf0,0x49,0x8b,0xb2,0x13,0xac,0xc2,0x3f,0x85,0x08,0x84,0xec,0x96, + 0x18,0x51,0x79,0x85,0xcc,0x7f,0x59,0xc2,0x43,0x43,0x5f,0xfe,0xa0,0xcc,0x1b,0x61, + 0x75,0x94,0x85,0x84,0x42,0x5f,0xa0,0x47,0x10,0x09,0x91,0x10,0x88,0x4a,0xff,0xff, + 0x6c,0xc2,0xfa,0xa6,0x08,0x5e,0xbd,0x90,0xdf,0xbb,0xfb,0xff,0xfe,0xa6,0x1c,0x3c, + 0xa4,0x2b,0xff,0xc7,0x08,0x2c,0x76,0x88,0x55,0xa5,0xeb,0x44,0x26,0x1a,0x11,0x61, + 0xcc,0x21,0xbf,0x4f,0xe1,0xc8,0x48,0x8c,0x90,0xc7,0xfd,0xf0,0xcb,0xc3,0x57,0x1f, + 0xc2,0x46,0x28,0x39,0x82,0x09,0x84,0xd2,0xca,0xc2,0x3f,0x48,0xc2,0xfb,0xc6,0x2b, + 0x58,0xf4,0x83,0xee,0xa3,0x5b,0xc8,0xa7,0x79,0x48,0x58,0x44,0x26,0x08,0x84,0xd9, + 0x50,0x98,0x41,0xbf,0xc1,0x16,0x04,0x84,0x13,0x21,0x3f,0x0b,0xdd,0xff,0xf7,0xf4, + 0x92,0x77,0xf4,0x08,0x84,0xf6,0x42,0xbf,0x0a,0x9f,0xfa,0xf7,0xfe,0xde,0x4a,0xbb, + 0x5f,0xfb,0x05,0xf7,0xdd,0xeb,0xaf,0xac,0x77,0x5f,0x75,0xff,0x82,0x6a,0x96,0xd3, + 0xe8,0x11,0x0b,0xeb,0x4b,0xe9,0x38,0xfd,0x06,0x0f,0x58,0xfa,0xde,0xba,0xce,0x10, + 0x27,0x54,0x38,0x44,0x26,0x1f,0xe2,0x99,0x0a,0xf5,0x2a,0x09,0x5f,0xbe,0xb6,0x44, + 0xce,0x10,0x19,0xaa,0x7f,0xa5,0x7d,0x37,0x24,0x2f,0x09,0x61,0x90,0xef,0x5d,0x78, + 0x8b,0x55,0x5b,0xfd,0x3d,0x61,0x91,0xad,0x56,0xff,0x61,0xb2,0x2c,0x9c,0x49,0xac, + 0x45,0x32,0x19,0xfa,0x1e,0xc3,0xab,0x4f,0xa5,0x83,0x12,0xa1,0xa1,0x08,0x84,0xea, + 0x45,0xd6,0x0d,0x3f,0x4a,0xb4,0x85,0x8f,0x07,0x82,0x05,0x92,0x1f,0x87,0xd3,0xfc, + 0x6d,0x7f,0xf5,0xff,0xe8,0xe1,0x61,0x7f,0xff,0x8f,0xf3,0x88,0x05,0x7e,0x94,0xc3, + 0x52,0xc2,0xfb,0x89,0x82,0x16,0xfd,0x4c,0x3f,0xc2,0x56,0x86,0x38}; diff --git a/examples/g5_mini_epaper/bart_80x128.h b/examples/g5_mini_epaper/bart_80x128.h new file mode 100644 index 0000000..2bf9ff5 --- /dev/null +++ b/examples/g5_mini_epaper/bart_80x128.h @@ -0,0 +1,33 @@ +// Created with image_to_c +// https://github.com/bitbank2/image_to_c +// +// bart_80x128 +// Data size = 347 bytes +// +// for non-Arduino builds... +#ifndef PROGMEM +#define PROGMEM +#endif +const uint8_t bart_80x128[] PROGMEM = { + 0xf9,0x8a,0xa2,0x44,0x46,0x89,0x14,0xc4,0x14,0x5d,0x84,0xc8,0x91,0x21,0xda,0x22, + 0x20,0x88,0x68,0x42,0x08,0x85,0x27,0xe3,0x70,0xc2,0x6a,0xc8,0x90,0x4c,0x88,0xe4, + 0x4a,0x22,0x2e,0xc4,0x11,0x0e,0xe2,0x2e,0xc2,0x21,0x44,0x4b,0x8d,0x47,0xc6,0x08, + 0x85,0x70,0x6b,0xff,0xaf,0x85,0xf0,0x82,0xff,0xfa,0xfa,0xff,0xff,0x09,0x2d,0x4c, + 0x4d,0x56,0x61,0xac,0xe3,0x06,0xf2,0xb1,0x0d,0x15,0x89,0x0f,0xd3,0x6f,0xd0,0x58, + 0x65,0x42,0x75,0xab,0xf9,0x2c,0xdf,0xf7,0x98,0x4b,0xc2,0x5e,0xb5,0xeb,0x8e,0xd7, + 0xd8,0xc5,0x7b,0x2b,0x12,0xeb,0xd3,0x85,0x87,0xb0,0xca,0x85,0x04,0x10,0x22,0x17, + 0xd9,0x2a,0x42,0xf9,0xc5,0x09,0x12,0xa1,0xaf,0x2a,0x4f,0xed,0x73,0x23,0xfc,0x30, + 0x5f,0xa0,0xbf,0xd9,0x51,0xa2,0x6b,0xb0,0xcc,0x52,0xf0,0x64,0xf0,0x17,0x39,0x71, + 0x21,0x94,0x9a,0x31,0xe7,0x70,0xc3,0x0b,0x0d,0xa7,0x6d,0x03,0xa6,0x4b,0x88,0x51, + 0x32,0xc4,0x86,0x36,0xe1,0x15,0x8c,0xb0,0xe9,0x53,0xd0,0x22,0x14,0xb7,0x0b,0xd3, + 0xe9,0x2f,0xa5,0xff,0xff,0x1a,0x1d,0x84,0xcb,0x04,0xfb,0x4d,0x57,0xf0,0x88,0x4f, + 0xe3,0xff,0xf5,0xee,0x97,0x04,0x42,0xb5,0xa8,0x65,0x23,0xe1,0x6b,0x0e,0xbd,0x3e, + 0xbe,0xff,0xbd,0x2f,0xfa,0xff,0xac,0x32,0x91,0x7f,0xdf,0xd7,0xcb,0x88,0xeb,0xb0, + 0x8a,0x4a,0x59,0x25,0xb9,0x88,0x58,0xac,0x38,0x22,0x27,0x22,0xfd,0xe0,0xc9,0x55, + 0x2c,0x11,0x0a,0xc1,0x8b,0x5e,0x19,0x58,0xa8,0x84,0x17,0x6d,0xba,0xec,0x1b,0x0f, + 0xe0,0xc1,0x8f,0x61,0x98,0x53,0xec,0x9b,0xf9,0xcf,0x8b,0x5b,0x22,0xc2,0xb8,0x64, + 0xdc,0xa8,0xbf,0xfe,0x44,0xbf,0xff,0xff,0xff,0xff,0xff,0xe9,0xff,0x41,0x15,0x0a, + 0xfe,0x61,0x3b,0x84,0x08,0x8a,0x82,0x10,0xe9,0x13,0xe2,0x18,0x61,0x12,0x10,0x50, + 0x90,0x30,0xb4,0xa1,0x04,0x45,0xc1,0x92,0xaa,0x41,0xa1,0xe1,0x69,0xbd,0x84,0x13, + 0xe0,0x8a,0x86,0xae,0x24,0x3e,0x72,0x22,0x27,0x34,0x48,0xb4,0x51,0x12,0x99,0x13, + 0x2e,0x10,0x08,0x38,0x62,0x45,0x44,0x29,0x95,0xf8,0xf8}; diff --git a/examples/g5_mini_epaper/g5_mini_epaper.ino b/examples/g5_mini_epaper/g5_mini_epaper.ino new file mode 100644 index 0000000..f39b92f --- /dev/null +++ b/examples/g5_mini_epaper/g5_mini_epaper.ino @@ -0,0 +1,46 @@ +// +// Getting_started with the Group5 image compression library +// Written by Larry Bank, September 20, 2024 +// +// This sketch will demonstrate how to decode a 128x64 1-bit image +// and display it on an OLED display +// +#include +#include +#include "bart_80x128.h" // a pre-compressed image made with the Linux CLI tool in this repo + +BBEPAPER bbep; +G5DECODER g5dec; +#define IMAGE_WIDTH 80 +#define IMAGE_HEIGHT 128 +// Pinout for the LilyGo mini-epaper S3 +#define PIN_BUSY 10 +#define PIN_RST 11 +#define PIN_DC 12 +#define PIN_CS 13 +#define PIN_SCK 14 +#define PIN_MOSI 15 + +void setup() +{ +uint8_t u8Line[16]; // current decoded line +int rc, y; + + bbep.setPanelType(EPD102_80x128); + bbep.initIO(PIN_DC, PIN_RST, PIN_BUSY, PIN_CS, PIN_MOSI, PIN_SCK, 4000000); + bbep.setAddrWindow(0, 0, IMAGE_WIDTH, IMAGE_HEIGHT); // set memory window to whole display + bbep.startWrite(PLANE_0); // write the data to plane 0 + rc = g5dec.init(IMAGE_WIDTH, IMAGE_HEIGHT, (uint8_t *)bart_80x128, sizeof(bart_80x128)); + if (rc == G5_SUCCESS) { + for (y=0; y -#include "../src/g5dec.h" -#include "../src/g5enc.h" +#include "../../../src/g5enc.inl" // // Read a Windows BMP file into memory // @@ -112,7 +111,7 @@ int main(int argc, const char * argv[]) { pOut = (uint8_t *)malloc(OUTSIZE); rc = g5_encode_init(&g5enc, w, h, pOut, OUTSIZE); for (y=0; ynative_width, pBBEP->native_height); + bbepSetAddrWindow(pBBEP, 0,0, pBBEP->native_width, pBBEP->native_height); bbepWriteCmd(pBBEP, ucCMD1); for (y=0; ynative_height; y++) { memset(u8Cache, uc1, iPitch); // the data is overwritten after each write @@ -1133,7 +1133,7 @@ uint8_t ucCMD1, ucCMD2; } // for y } if (iPlane == PLANE_1 || iPlane == PLANE_DUPLICATE) { // write to first plane - bbepSetPosition(pBBEP, 0,0, pBBEP->native_width, pBBEP->native_height); + bbepSetAddrWindow(pBBEP, 0,0, pBBEP->native_width, pBBEP->native_height); bbepWriteCmd(pBBEP, ucCMD2); for (y=0; ynative_height; y++) { memset(u8Cache, uc2, iPitch); // the data is overwritten after each write diff --git a/src/bb_ep_gfx.inl b/src/bb_ep_gfx.inl index 8d6c617..4695cba 100644 --- a/src/bb_ep_gfx.inl +++ b/src/bb_ep_gfx.inl @@ -19,8 +19,9 @@ #ifndef __BB_EP_GFX__ #define __BB_EP_GFX__ #include +#include "g5dec.inl" #include "bb_font.h" -G5DECIMAGE g5dec; +static G5DECIMAGE g5dec; // forward declarations void InvertBytes(uint8_t *pData, uint8_t bLen); @@ -220,7 +221,7 @@ void bbepDrawSprite(BBEPDISP *pBBEP, const uint8_t *pSprite, int cx, int cy, int s = (uint8_t *)pSprite; // set the memory window for this character cx += (x & 7); // add parital byte - bbepSetPosition(pBBEP, x, y, cx, cy); + bbepSetAddrWindow(pBBEP, x, y, cx, cy); iDestPitch = (cx+7)/8; bbepWriteCmd(pBBEP, u8CMD); // memory write command for (int ty=dy; tyucScreen == NULL && ((y & 7) == 7 || y == cy-1)) // dump to LCD { - bbepSetPosition(pBBEP, dx, y+dy, cx, 1); + bbepSetAddrWindow(pBBEP, dx, y+dy, cx, 1); bbepWriteData(pBBEP, u8Cache, cx); } } // for y @@ -667,7 +668,7 @@ uint8_t *pBits, u8CMD1, u8CMD2, u8CMD, u8EndMask; // set the memory window for this character iSrcPitch = (w+7)/8; w += (dx & 7); // add parital byte - bbepSetPosition(pBBEP, dx, dy, w, h); + bbepSetAddrWindow(pBBEP, dx, dy, w, h); iPitch = (w+7)/8; // start writing into the correct plane if (pBBEP->chip_type == BBEP_CHIP_UC81xx) { @@ -753,7 +754,7 @@ uint8_t u8Temp[128]; { i = 0; if (!pBBEP->ucScreen) { // bufferless mode, rotate the coordinate system to fit the situation - // bbepSetPosition(pBBEP, √, pBBEP->iCursorX, 8, pBBEP->native_height-pBBEP->iCursorX); + // bbepSetAddrWindow(pBBEP, √, pBBEP->iCursorX, 8, pBBEP->native_height-pBBEP->iCursorX); // bbepWriteCmd(pBBEP, ucCMD1); // write to "new" plane } while (pBBEP->iCursorX < pBBEP->width && szMsg[i] != 0 && pBBEP->iCursorY < pBBEP->height) @@ -769,7 +770,7 @@ uint8_t u8Temp[128]; iLen = pBBEP->width - pBBEP->iCursorX; } if (!pBBEP->ucScreen) { // bufferless mode, rotate the coordinate system to fit the situation - bbepSetPosition(pBBEP, pBBEP->native_width-8-pBBEP->iCursorY, pBBEP->iCursorX, 8, pBBEP->native_height-pBBEP->iCursorX); + bbepSetAddrWindow(pBBEP, pBBEP->native_width-8-pBBEP->iCursorY, pBBEP->iCursorX, 8, pBBEP->native_height-pBBEP->iCursorX); bbepWriteCmd(pBBEP, ucCMD); // write to "new" plane bbepWriteData(pBBEP, u8Temp, iLen); } else { // draw in memory @@ -899,10 +900,10 @@ uint8_t u8Temp[128]; if (pBBEP->iCursorX + iLen > pBBEP->width) // clip right edge iLen = pBBEP->width - pBBEP->iCursorX; if (!pBBEP->ucScreen) { // bufferless mode - bbepSetPosition(pBBEP, pBBEP->native_width-8-pBBEP->iCursorY, pBBEP->iCursorX, 8, iLen); + bbepSetAddrWindow(pBBEP, pBBEP->native_width-8-pBBEP->iCursorY, pBBEP->iCursorX, 8, iLen); bbepWriteCmd(pBBEP, ucCMD); // write to "new" plane bbepWriteData(pBBEP, &u8Temp[6], iLen); - bbepSetPosition(pBBEP, pBBEP->native_width-16-pBBEP->iCursorY, pBBEP->iCursorX, 8, iLen); + bbepSetAddrWindow(pBBEP, pBBEP->native_width-16-pBBEP->iCursorY, pBBEP->iCursorX, 8, iLen); bbepWriteCmd(pBBEP, ucCMD); // write to "new" plane bbepWriteData(pBBEP, &u8Temp[18], iLen); } else { // write to RAM @@ -933,7 +934,7 @@ uint8_t u8Temp[128]; if (pBBEP->iCursorX + iLen > pBBEP->width) // clip right edge iLen = pBBEP->width - pBBEP->iCursorX; if (!pBBEP->ucScreen) { // bufferless mode - bbepSetPosition(pBBEP, pBBEP->iCursorX, pBBEP->iCursorY, 8, iLen); + bbepSetAddrWindow(pBBEP, pBBEP->iCursorX, pBBEP->iCursorY, 8, iLen); bbepWriteCmd(pBBEP, ucCMD); // write to "new" plane bbepWriteData(pBBEP, u8Temp, iLen); } else { // write to RAM @@ -1062,7 +1063,7 @@ void bbepDrawLine(BBEPDISP *pBBEP, int x1, int y1, int x2, int y2, uint8_t ucCol mask >>= 1; if (mask == 0) // we've moved outside the current row, write the data we changed { - bbepSetPosition(pBBEP, x, y, 8*(int)(p-pStart), 1); + bbepSetAddrWindow(pBBEP, x, y, 8*(int)(p-pStart), 1); bbepWriteData(pBBEP, pStart, (int)(p-pStart)); // write the row we changed x = x1+1; // we've already written the byte at x1 y1 = y+yinc; @@ -1080,7 +1081,7 @@ void bbepDrawLine(BBEPDISP *pBBEP, int x1, int y1, int x2, int y2, uint8_t ucCol } // for x1 if (p != pStart) // some data needs to be written { - bbepSetPosition(pBBEP, x, y, 8*(int)(p-pStart), 1); + bbepSetAddrWindow(pBBEP, x, y, 8*(int)(p-pStart), 1); bbepWriteData(pBBEP, pStart, (int)(p-pStart)); } } else { @@ -1122,7 +1123,7 @@ void bbepDrawLine(BBEPDISP *pBBEP, int x1, int y1, int x2, int y2, uint8_t ucCol if (bOld != bNew) { p[0] = bNew; // save to RAM - bbepSetPosition(pBBEP, x, y1, 8, 1); + bbepSetAddrWindow(pBBEP, x, y1, 8, 1); bbepWriteData(pBBEP, &bNew, 1); } // data changed if (pBBEP->ucScreen) { @@ -1139,7 +1140,7 @@ void bbepDrawLine(BBEPDISP *pBBEP, int x1, int y1, int x2, int y2, uint8_t ucCol if (bOld != bNew) // write the last byte we modified if it changed { p[0] = bNew; // save to RAM - bbepSetPosition(pBBEP, x, y1, 8, 1); + bbepSetAddrWindow(pBBEP, x, y1, 8, 1); bbepWriteData(pBBEP, &bNew, 1); } x += xinc; @@ -1154,7 +1155,7 @@ void bbepDrawLine(BBEPDISP *pBBEP, int x1, int y1, int x2, int y2, uint8_t ucCol if (bOld != bNew) // write the last byte we modified if it changed { p[0] = bNew; // save to RAM - bbepSetPosition(pBBEP, x, y2, 8, 1); + bbepSetAddrWindow(pBBEP, x, y2, 8, 1); bbepWriteData(pBBEP, &bNew, 1); } } // y major case diff --git a/src/bb_epaper.cpp b/src/bb_epaper.cpp index a769e51..4bf4b31 100644 --- a/src/bb_epaper.cpp +++ b/src/bb_epaper.cpp @@ -37,7 +37,6 @@ void delay(int); #include "arduino_io.inl" // I/O (non-portable) code is in here #include "bb_ep.inl" // All of the display interface code is in here #include "bb_ep_gfx.inl" // drawing code -#include "Group5.h" // Group5 data compression library #include "bb_font.h" // bitbank compressed font info #ifdef __cplusplus // @@ -48,9 +47,9 @@ void delay(int); // return _bbep.iTimeout; //} -void BBEPAPER::setPosition(int x, int y, int w, int h) +void BBEPAPER::setAddrWindow(int x, int y, int w, int h) { - bbepSetPosition(&_bbep, x, y, w, h); + bbepSetAddrWindow(&_bbep, x, y, w, h); } int BBEPAPER::setPanelType(int iPanel) { @@ -458,4 +457,32 @@ void BBEPAPER::drawSprite(const uint8_t *pSprite, int cx, int cy, int iPitch, in { bbepDrawSprite(&_bbep, pSprite, cx, cy, iPitch, x, y, iColor); } +void BBEPAPER::startWrite(int iPlane) +{ +uint8_t u8Cmd; + + if (_bbep.chip_type == BBEP_CHIP_UC81xx) { + if (iPlane == PLANE_0) + u8Cmd = UC8151_DTM2; + else + u8Cmd = UC8151_DTM1; + } else { // SSD16xx + if (iPlane == PLANE_0) + u8Cmd = SSD1608_WRITE_RAM; + else + u8Cmd = SSD1608_WRITE_ALTRAM; + } + bbepWriteCmd(&_bbep, u8Cmd); +} /* startWrite() */ + +void BBEPAPER::writeData(uint8_t *pData, int iLen) +{ + bbepWriteData(&_bbep, pData, iLen); +} /* writeData() */ + +void BBEPAPER::writeCmd(uint8_t u8Cmd) +{ + bbepWriteCmd(&_bbep, u8Cmd); +} /* writeCmd() */ + #endif // __cplusplus diff --git a/src/bb_epaper.h b/src/bb_epaper.h index 1f918c7..5aa69ed 100644 --- a/src/bb_epaper.h +++ b/src/bb_epaper.h @@ -279,10 +279,13 @@ class BBEPAPER { public: BBEPAPER() { memset(&_bbep, 0, sizeof(_bbep)); _bbep.iFG = BBEP_BLACK; _bbep.type = EPD_PANEL_UNDEFINED;} - void setPosition(int x, int y, int w, int h); + void setAddrWindow(int x, int y, int w, int h); int setPanelType(int iPanel); void initIO(int iDC, int iReset, int iBusy, int iCS = SS, int iMOSI = MOSI, int iSCLK = SCK, uint32_t u32Speed = 8000000); int writePlane(int iPlane = PLANE_DUPLICATE); + void startWrite(int iPlane); + void writeData(uint8_t *pData, int iLen); + void writeCmd(uint8_t u8Cmd); int refresh(int iMode, bool bWait = true); void setBuffer(uint8_t *pBuffer); int allocBuffer(void); diff --git a/src/g5dec.inl b/src/g5dec.inl index 5c1374a..4bf3466 100644 --- a/src/g5dec.inl +++ b/src/g5dec.inl @@ -44,7 +44,7 @@ static const uint8_t code_table[128] = 0x11, 3, 0x11, 3, 0x11, 3, 0x11, 3, 0x11, 3, 0x11, 3, 0x11, 3, 0x11, 3}; -int g5_decode_init(G5DECIMAGE *pImage, int iWidth, int iHeight, uint8_t *pData, int iDataSize) +static int g5_decode_init(G5DECIMAGE *pImage, int iWidth, int iHeight, uint8_t *pData, int iDataSize) { if (pImage == NULL || iWidth < 1 || iHeight < 1 || pData == NULL || iDataSize < 1) return G5_INVALID_PARAMETER; @@ -303,7 +303,7 @@ pilreadg5z: // // Decompress the VLC data // -int g5_decode_line(G5DECIMAGE *pPage, uint8_t *pOut) +static int g5_decode_line(G5DECIMAGE *pPage, uint8_t *pOut) { int rc; uint8_t *pBufEnd;