Added support for Badger2040 (EPD29_128x296)

This commit is contained in:
Laurence Bank
2024-10-20 13:57:22 +01:00
parent 4eff9915ed
commit 8230c2de5e
5 changed files with 164 additions and 37 deletions
+11 -6
View File
@@ -28,13 +28,18 @@
// both old and new data each update.
//
#include <bb_epaper.h>
BBEPAPER bbep(EPD295_128x296);
//BBEPAPER bbep(EPD122_192x176);
//BBEPAPER bbep(EPD295_128x296);
BBEPAPER bbep(EPD29_128x296); // Badger2040
// My Arduino Nano 33 BLE e-paper adapter
#define DC_PIN 16
#define BUSY_PIN 15
#define RESET_PIN 14
#define CS_PIN 10
//#define DC_PIN 16
//#define BUSY_PIN 15
//#define RESET_PIN 14
//#define CS_PIN 10
// Badger2040
#define CS_PIN 17
#define BUSY_PIN 26
#define RESET_PIN 21
#define DC_PIN 20
void DrawScene(int i, int iPlane)
{
+55
View File
@@ -126,6 +126,59 @@ const uint8_t epd29_init_sequence_full[] PROGMEM = {
0x00 // end of table
};
const uint8_t epd29_init_sequence_part[] PROGMEM = {
0x02, UC8151_PSR, 0x80 | 0x20 | 0x10 | 0x08 | 0x04 | 0x02 | 0x01, // RES_128x296, LUT_REG, FORMAT_BW, SHIFT_LEFT, BOOSTER_ON, RESET_NONE
0x06, UC8151_PWR, 0x03, 0x00, 0x2b, 0x2b, 0x03,
0x04, UC8151_BTST, 0x17,0x17,0x17, // booster soft-start config - START_10MS | STRENGTH_3 | OFF_6_58US
0x01, UC8151_PON, // power on
BUSY_WAIT,
0x04, UC8151_TRES, 0x80, 1, 0x28, // resolution
0x02, UC8151_PLL, 0x3a, // HZ_100
0x02, UC8151_VDCS, 0x12, // VCOM DC setting
0x02, UC8151_CDI, 0x6C, // white border & non-inverted partial update old->new changes
0x2d, UC8151_LUT_VCOM, // VCOM LUT
0x00, 0x19, 0x01, 0x00, 0x00, 0x01,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00
,0x00, 0x00,
0x2b, UC8151_LUT_WW, // WW LUT
0x00, 0x19, 0x01, 0x00, 0x00, 0x01,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x2b, UC8151_LUT_BW,
0x80, 0x19, 0x01, 0x00, 0x00, 0x01,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x2b, UC8151_LUT_WB,
0x40, 0x19, 0x01, 0x00, 0x00, 0x01,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x2b, UC8151_LUT_BB,
0x00, 0x19, 0x01, 0x00, 0x00, 0x01,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00 // end of table
};
const uint8_t epd42r_init_sequence_full[] PROGMEM = {
0x01, 0x12, // soft reset
BUSY_WAIT,
@@ -508,6 +561,7 @@ const uint8_t epd122_init_sequence_part[] PROGMEM =
BUSY_WAIT,
0x00 // end of table
};
const uint8_t epd293_init_sequence_full[] PROGMEM =
{
0x01, SSD1608_SW_RESET,
@@ -1004,6 +1058,7 @@ const EPD_PANEL panelDefs[] PROGMEM = {
{240, 416, epd37_init_sequence_full, NULL, epd37_init_sequence_part, 0, BBEP_CHIP_UC81xx}, // EPD37_240x416
{104, 212, epd213_inky_init_sequence_full, NULL, NULL, 0, BBEP_CHIP_UC81xx}, // EPD213_104x212 InkyPHAT black and white
{800, 480, epd75_init_sequence_full, epd75_init_sequence_fast, epd75_init_sequence_partial, 0, BBEP_CHIP_UC81xx}, // EPD75_800x480
{128, 296, epd29_init_sequence_full, NULL, epd29_init_sequence_part, 0, BBEP_CHIP_UC81xx}, // Badger 2040
};
//
// Set the e-paper panel type
+89 -29
View File
@@ -191,8 +191,10 @@ void bbepDrawSprite(BBEPDISP *pBBEP, const uint8_t *pSprite, int cx, int cy, int
iLocalPitch = pBBEP->width;
if (pBBEP == NULL) return;
if (x+cx < 0 || y+cy < 0 || x >= pBBEP->native_width || y >= pBBEP->native_height)
if (x+cx < 0 || y+cy < 0 || x >= pBBEP->native_width || y >= pBBEP->native_height) {
pBBEP->last_error = BBEP_ERROR_BAD_PARAMETER;
return; // out of bounds
}
dy = y; // destination y
if (y < 0) // skip the invisible parts
{
@@ -244,6 +246,7 @@ void bbepDrawSprite(BBEPDISP *pBBEP, const uint8_t *pSprite, int cx, int cy, int
bbepWriteData(pBBEP, u8Cache, iDestPitch); // write each row into the EPD framebuffer
} // for y
} else {
#ifndef NO_RAM
iStartX = 0;
dx = x;
if (x < 0)
@@ -297,6 +300,7 @@ void bbepDrawSprite(BBEPDISP *pBBEP, const uint8_t *pSprite, int cx, int cy, int
dy++;
pSprite += iPitch;
} // for ty
#endif // NO_RAM
}
} /* bbepDrawSprite() */
//
@@ -317,6 +321,7 @@ int bbepSetPixel(BBEPDISP *pBBEP, int x, int y, unsigned char ucColor)
i = (x >> 3) + (y * iPitch);
if (i < 0 || i > iSize-1) { // off the screen
pBBEP->last_error = BBEP_ERROR_BAD_PARAMETER;
return BBEP_ERROR_BAD_PARAMETER;
}
// special case for 3-color e-ink
@@ -406,6 +411,7 @@ int bbepLoadG5(BBEPDISP *pBBEP, const uint8_t *pG5, int x, int y, int iFG, int i
}
bbepWriteData(pBBEP, u8Cache, (cx+(x&7)+7)>>3);
} else { // use the setPixel function for more features
#ifndef NO_RAM
src_mask = 0; // make it read a byte to start
s = u8Cache;
for (tx=0; tx<cx; tx++) {
@@ -421,7 +427,8 @@ int bbepLoadG5(BBEPDISP *pBBEP, const uint8_t *pG5, int x, int y, int iFG, int i
bbepSetPixel(pBBEP, x+tx, y+ty, (uint8_t)iBG);
}
src_mask >>= 1;
} // for x
} // for tx
#endif // NO_RAM
}
} // for y
return BBEP_SUCCESS;
@@ -446,18 +453,24 @@ int bbepLoadBMP(BBEPDISP *pBBEP, const uint8_t *pBMP, int dx, int dy, int iFG, i
// access on RP2040 for odd addresses
i16 = pgm_read_byte(pBMP);
i16 += (pgm_read_byte(&pBMP[1]) << 8);
if (i16 != 0x4d42) // must start with 'BM'
if (i16 != 0x4d42) { // must start with 'BM'
pBBEP->last_error = BBEP_ERROR_BAD_DATA;
return BBEP_ERROR_BAD_DATA; // not a BMP file
}
cx = pgm_read_byte(pBMP + 18);
cx += (pgm_read_byte(pBMP+19)<<8);
if (cx + dx > pBBEP->width) // must fit on the display
if (cx + dx > pBBEP->width) { // must fit on the display
pBBEP->last_error = BBEP_ERROR_BAD_PARAMETER;
return BBEP_ERROR_BAD_PARAMETER;
}
cy = pgm_read_byte(pBMP + 22);
cy += (pgm_read_byte(pBMP+23)<<8);
if (cy < 0) cy = -cy;
else bFlipped = 1;
if (cy + dy > pBBEP->height) // must fit on the display
if (cy + dy > pBBEP->height) { // must fit on the display
pBBEP->last_error = BBEP_ERROR_BAD_PARAMETER;
return BBEP_ERROR_BAD_PARAMETER;
}
if (pBBEP->ucScreen == NULL) {
// no BG specified or no back buffer, BG color is opposite of FG
if (iFG == -1) iFG = BBEP_WHITE;
@@ -468,8 +481,10 @@ int bbepLoadBMP(BBEPDISP *pBBEP, const uint8_t *pBMP, int dx, int dy, int iFG, i
i16 = pgm_read_byte(pBMP + 28);
i16 += (pgm_read_byte(pBMP+29)<<8);
if (i16 != 1) // must be 1 bit per pixel
if (i16 != 1) { // must be 1 bit per pixel
pBBEP->last_error = BBEP_ERROR_BAD_DATA;
return BBEP_ERROR_BAD_DATA;
}
iOffBits = pgm_read_byte(pBMP + 10);
iOffBits += (pgm_read_byte(pBMP+11));
iPitch = (((cx+7)>>3) + 3) & 0xfffc; // must be DWORD aligned
@@ -502,6 +517,7 @@ int bbepLoadBMP(BBEPDISP *pBBEP, const uint8_t *pBMP, int dx, int dy, int iFG, i
}
bbepWriteData(pBBEP, u8Cache, (cx+(dx&7)+7)>>3);
} else { // use the setPixel function for more features
#ifndef NO_RAM
src_mask = 0; // make it read a byte to start
for (x=0; x<cx; x++) {
if (src_mask == 0) { // need to load the next byte
@@ -517,6 +533,7 @@ int bbepLoadBMP(BBEPDISP *pBBEP, const uint8_t *pBMP, int dx, int dy, int iFG, i
}
src_mask >>= 1;
} // for x
#endif // NO_RAM
}
} // for y
return BBEP_SUCCESS;
@@ -537,33 +554,45 @@ int bbepLoadBMP3(BBEPDISP *pBBEP, const uint8_t *pBMP, int dx, int dy)
uint8_t bFlipped = 0;
uint8_t ucColorMap[16];
if (!(pBBEP->iFlags & BBEP_3COLOR) || pBBEP->ucScreen == 0)
return BBEP_ERROR_NOT_SUPPORTED; // if not 3-color EPD or no back buffer, bye-byte
if (!(pBBEP->iFlags & BBEP_3COLOR) || pBBEP->ucScreen == 0) {
pBBEP->last_error = BBEP_ERROR_NOT_SUPPORTED;
return BBEP_ERROR_NOT_SUPPORTED; // if not 3-color EPD or no back buffer
}
iDestPitch = pBBEP->width;
iRedOff = ((pBBEP->height+7)>>3) * iDestPitch;
// Need to avoid pgm_read_word because it can cause an
// unaligned address exception on the RP2040 for odd addresses
i16 = pgm_read_byte(pBMP);
i16 += (pgm_read_byte(pBMP+1)<<8);
if (i16 != 0x4d42) // must start with 'BM'
if (i16 != 0x4d42) { // must start with 'BM'
pBBEP->last_error = BBEP_ERROR_BAD_DATA;
return BBEP_ERROR_BAD_DATA; // not a BMP file
}
cx = pgm_read_byte(&pBMP[18]);
cx += (pgm_read_byte(&pBMP[19]) << 8);
if (cx + dx > pBBEP->width) // must fit on the display
if (cx + dx > pBBEP->width) { // must fit on the display
pBBEP->last_error = BBEP_ERROR_BAD_PARAMETER;
return BBEP_ERROR_BAD_PARAMETER;
}
cy = pgm_read_byte(&pBMP[22]);
cy += (pgm_read_byte(&pBMP[23])<<8);
if (cy < 0)
cy = -cy;
else
bFlipped = 1;
if (cy + dy > pBBEP->height) // must fit on the display
if (cy + dy > pBBEP->height) { // must fit on the display
pBBEP->last_error = BBEP_ERROR_BAD_PARAMETER;
return BBEP_ERROR_BAD_PARAMETER;
if (pgm_read_byte(&pBMP[30]) != 0) // compression must be NONE
}
if (pgm_read_byte(&pBMP[30]) != 0) { // compression must be NONE
pBBEP->last_error = BBEP_ERROR_BAD_DATA;
return BBEP_ERROR_BAD_DATA;
}
bpp = pgm_read_byte(&pBMP[28]);
if (bpp != 4) // must be 4 bits per pixel
if (bpp != 4) { // must be 4 bits per pixel
pBBEP->last_error = BBEP_ERROR_BAD_DATA;
return BBEP_ERROR_BAD_DATA;
}
iOffBits = pgm_read_byte(&pBMP[10]);
iOffBits += (pgm_read_byte(&pBMP[11])<<8);
iColors = pgm_read_byte(&pBMP[46]); // colors used BMP field
@@ -646,7 +675,11 @@ void bbepWriteStringCustom(BBEPDISP *pBBEP, BB_FONT *pFont, int x, int y, char *
uint8_t *pBits, u8CMD1, u8CMD2, u8CMD, u8EndMask;
uint8_t first, last;
if (pBBEP == NULL || pFont == NULL) return; // invalid param
if (pBBEP == NULL) return;
if (pFont == NULL) {
pBBEP->last_error = BBEP_ERROR_BAD_PARAMETER;
return; // invalid param
}
if (x == -1)
x = pBBEP->iCursorX;
if (y == -1)
@@ -704,6 +737,7 @@ void bbepWriteStringCustom(BBEPDISP *pBBEP, BB_FONT *pFont, int x, int y, char *
if (ty < 0 || ty > 4096) ty = 4096; // DEBUG
rc = g5_decode_init(&g5dec, w, h, s, ty);
if (rc != G5_SUCCESS) {
pBBEP->last_error = BBEP_ERROR_BAD_DATA;
return; // corrupt data?
}
if (pBBEP->ucScreen) { // backbuffer, draw pixels
@@ -810,7 +844,9 @@ int bbepWriteString(BBEPDISP *pBBEP, int x, int y, char *szMsg, int iSize, int i
int iOldFG; // old fg color to make sure red works
uint8_t u8Temp[40];
if (pBBEP == NULL) return BBEP_ERROR_BAD_PARAMETER;
if (pBBEP == NULL) {
return BBEP_ERROR_BAD_PARAMETER;
}
if (pBBEP->chip_type == BBEP_CHIP_UC81xx) {
ucCMD1 = UC8151_DTM2;
ucCMD2 = UC8151_DTM1;
@@ -828,8 +864,10 @@ int bbepWriteString(BBEPDISP *pBBEP, int x, int y, char *szMsg, int iSize, int i
} else {
pBBEP->iCursorX = x; pBBEP->iCursorY = y;
}
if (pBBEP->iCursorX >= pBBEP->width || pBBEP->iCursorY >= pBBEP->height)
if (pBBEP->iCursorX >= pBBEP->width || pBBEP->iCursorY >= pBBEP->height) {
pBBEP->last_error = BBEP_ERROR_BAD_PARAMETER;
return BBEP_ERROR_BAD_PARAMETER; // can't draw off the display
}
iOldFG = pBBEP->iFG; // save old fg color
if (iColor >= BBEP_YELLOW) {
@@ -1105,19 +1143,25 @@ int bbepWriteString(BBEPDISP *pBBEP, int x, int y, char *szMsg, int iSize, int i
return BBEP_SUCCESS;
} // 6x8
pBBEP->iFG = iOldFG; // restore color
pBBEP->last_error = BBEP_ERROR_BAD_PARAMETER;
return BBEP_ERROR_BAD_PARAMETER; // invalid size
} /* bbepWriteString() */
//
// Get the width of text in a custom font
//
void bbepGetStringBox(BB_FONT *pFont, const char *szMsg, int *width, int *top, int *bottom)
void bbepGetStringBox(BBEPDISP *pBBEP, BB_FONT *pFont, const char *szMsg, int *width, int *top, int *bottom)
{
int cx = 0;
unsigned int c, i = 0;
BB_GLYPH *pBBG;
int miny, maxy;
if (width == NULL || top == NULL || bottom == NULL || pFont == NULL || szMsg == NULL) return; // bad pointers
if (!pBBEP) return;
if (width == NULL || top == NULL || bottom == NULL || pFont == NULL || szMsg == NULL) {
pBBEP->last_error = BBEP_ERROR_BAD_PARAMETER;
return; // bad pointers
}
miny = 1000; maxy = 0;
while (szMsg[i]) {
c = szMsg[i++];
@@ -1157,10 +1201,14 @@ void bbepDrawLine(BBEPDISP *pBBEP, int x1, int y1, int x2, int y2, uint8_t ucCol
int iPitch;
int iRedOffset = 0;
if (pBBEP == NULL) return;
if (x1 < 0 || x2 < 0 || y1 < 0 || y2 < 0 || x1 >= pBBEP->width || x2 >= pBBEP->width || y1 >= pBBEP->height || y2 >= pBBEP->height)
if (pBBEP == NULL) {
return;
}
if (x1 < 0 || x2 < 0 || y1 < 0 || y2 < 0 || x1 >= pBBEP->width || x2 >= pBBEP->width || y1 >= pBBEP->height || y2 >= pBBEP->height) {
pBBEP->last_error = BBEP_ERROR_BAD_PARAMETER;
return;
}
iPitch = (pBBEP->width + 7)>>3;
if (ucColor >= BBEP_YELLOW && pBBEP->iFlags & (BBEP_3COLOR | BBEP_4COLOR)) {
// use the second half of the image buffer
@@ -1304,8 +1352,10 @@ static void DrawScaledPixel(BBEPDISP *pBBEP, int iCX, int iCY, int x, int y, int
if (iXFrac != 0x10000) x = ((x * iXFrac) >> 16);
if (iYFrac != 0x10000) y = ((y * iYFrac) >> 16);
x += iCX; y += iCY;
if (x < 0 || x >= pBBEP->width || y < 0 || y >= pBBEP->height)
if (x < 0 || x >= pBBEP->width || y < 0 || y >= pBBEP->height) {
pBBEP->last_error = BBEP_ERROR_BAD_PARAMETER;
return; // off the screen
}
d = &pBBEP->ucScreen[iRedOffset + (x>>3) + (y * iPitch)];
ucMask = 0x80 >> (x & 7);
if (ucColor)
@@ -1325,8 +1375,10 @@ static void DrawScaledLine(BBEPDISP *pBBEP, int iCX, int iCY, int x, int y, int3
iLen = x*2;
x = iCX - x; y += iCY;
x2 = x + iLen;
if (y < 0 || y >= pBBEP->height)
if (y < 0 || y >= pBBEP->height) {
pBBEP->last_error = BBEP_ERROR_BAD_PARAMETER;
return; // completely off the screen
}
if (x < 0) x = 0;
if (x2 >= pBBEP->width) x2 = pBBEP->width-1;
bbepDrawLine(pBBEP, x, y, x2, y, ucColor);
@@ -1374,11 +1426,16 @@ void bbepEllipse(BBEPDISP *pBBEP, int iCenterX, int iCenterY, int32_t iRadiusX,
int32_t iXFrac, iYFrac;
int iRadius, iDelta, x, y;
if (pBBEP == NULL || (pBBEP->ucScreen == NULL && !bFilled))
if (pBBEP == NULL) return;
if (pBBEP->ucScreen == NULL && !bFilled) {
pBBEP->last_error = BBEP_ERROR_BAD_PARAMETER;
return; // must have back buffer defined for outline mode
}
if (iRadiusX <= 0 || iRadiusY <= 0) return; // invalid radii
if (iRadiusX <= 0 || iRadiusY <= 0) {
pBBEP->last_error = BBEP_ERROR_BAD_PARAMETER;
return; // invalid radii
}
if (iRadiusX > iRadiusY) {// use X as the primary radius
iRadius = iRadiusX;
iXFrac = 65536;
@@ -1404,7 +1461,6 @@ void bbepEllipse(BBEPDISP *pBBEP, int iCenterX, int iCenterY, int32_t iRadiusX,
//
// Draw an outline or filled rectangle
//
//
void bbepRectangle(BBEPDISP *pBBEP, int x1, int y1, int x2, int y2, uint8_t ucColor, uint8_t bFilled)
{
uint8_t *d, ucMask, ucMask2;
@@ -1421,11 +1477,15 @@ void bbepRectangle(BBEPDISP *pBBEP, int x1, int y1, int x2, int y2, uint8_t ucCo
}
}
if (pBBEP == NULL)
if (pBBEP == NULL) {
return; // invalid - must have BBEPDISP structure
}
if (x1 < 0 || y1 < 0 || x2 < 0 || y2 < 0 ||
x1 >= pBBEP->width || y1 >= pBBEP->height || x2 >= pBBEP->width || y2 >= pBBEP->height) return; // invalid coordinates
x1 >= pBBEP->width || y1 >= pBBEP->height || x2 >= pBBEP->width || y2 >= pBBEP->height) {
pBBEP->last_error = BBEP_ERROR_BAD_PARAMETER;
return; // invalid coordinates
}
iPitch = pBBEP->width;
// Make sure that X1/Y1 is above and to the left of X2/Y2
// swap coordinates as needed to make this true
+5 -1
View File
@@ -397,7 +397,7 @@ void BBEPAPER::getTextBounds(const char *string, int16_t x, int16_t y, int16_t *
{
if (_bbep.pFont) {
int width, top, bottom;
bbepGetStringBox((BB_FONT *)_bbep.pFont, string, &width, &top, &bottom);
bbepGetStringBox(&_bbep, (BB_FONT *)_bbep.pFont, string, &width, &top, &bottom);
*x1 = x;
*w = width;
*y1 = y + top;
@@ -503,4 +503,8 @@ void BBEPAPER::fillRoundRect(int x, int y, int w, int h,
bbepRoundRect(&_bbep, x, y, w, h, r, color, 1);
}
int BBEPAPER::getLastError(void)
{
return _bbep.last_error;
}
#endif // __cplusplus
+4 -1
View File
@@ -41,6 +41,7 @@ enum {
BBEP_ERROR_BAD_DATA,
BBEP_ERROR_NOT_SUPPORTED,
BBEP_ERROR_NO_MEMORY,
BBEP_ERROR_OUT_OF_BOUNDS,
BBEP_ERROR_COUNT
};
@@ -110,6 +111,7 @@ enum {
EPD37_240x416, // GDEY037T03
EPD213_104x212, // InkyPHAT 2.13 black and white
EPD75_800x480, // GDEY075T7
EPD29_128x296, // Pimoroni Badger2040
EPD_PANEL_COUNT
};
#ifdef FUTURE
@@ -249,7 +251,7 @@ enum {
typedef struct bbepstruct
{
uint8_t wrap, type, chip_type;
uint8_t wrap, type, chip_type, last_error;
uint8_t *ucScreen;
int iCursorX, iCursorY;
int width, height, native_width, native_height;
@@ -301,6 +303,7 @@ class BBEPAPER
uint32_t capabilities();
void setRotation(int iAngle);
int getRotation(void);
int getLastError(void);
void drawRoundRect(int x, int y, int w, int h,
int r, uint8_t color);
void fillRoundRect(int x, int y, int w, int h,