diff --git a/examples/images_and_icons/images_and_icons.ino b/examples/images_and_icons/images_and_icons.ino index 488911c..ebda916 100644 --- a/examples/images_and_icons/images_and_icons.ino +++ b/examples/images_and_icons/images_and_icons.ino @@ -5,25 +5,19 @@ #include #include "bomb.h" // uncompressed 40x40 image #include "bart.h" // compressed 128x64 image +#include "smiley.h" // 100x100 compressed image BBEPAPER bbep(EP295_128x296); -// Mike Rankin's C3 e-ink PCB -//#define PIN_DC 3 -//#define PIN_BUSY 1 -//#define PIN_RST 10 -//#define PIN_CS 7 -//#define PIN_MOSI 6 -//#define PIN_SCK 4 -#define PIN_DC 16 -#define PIN_BUSY 15 -#define PIN_RST 14 -#define PIN_CS 10 -#define PIN_MOSI MOSI -#define PIN_SCK SCK +#define CS_PIN 2 +#define DC_PIN 3 +#define RESET_PIN 5 +#define BUSY_PIN 4 +#define CLK_PIN 1 +#define MOSI_PIN 0 void setup() { - bbep.initIO(PIN_DC, PIN_RST, PIN_BUSY, PIN_CS, PIN_MOSI, PIN_SCK, 8000000); + bbep.initIO(DC_PIN, RESET_PIN, BUSY_PIN, CS_PIN, MOSI_PIN, CLK_PIN, 8000000); // Do everything with no local buffer bbep.fillScreen(BBEP_WHITE); bbep.setCursor(0,4); // start a few pixels away from the top edge @@ -41,6 +35,22 @@ void setup() } bbep.refresh(REFRESH_FULL); bbep.wait(); + delay(3000); + // Scaled drawing requires a back buffer + bbep.allocBuffer(); + bbep.setRotation(270); + bbep.fillScreen(BBEP_WHITE); + bbep.setFont(FONT_12x16); + bbep.setCursor(0,0); + bbep.print("Scaled G5 needs RAM"); + float f = 0.5; + for (int i=0; i<5; i++) { + bbep.loadG5Image(smiley, (int)(i*50), 16+(int)(i*12.5*f), BBEP_TRANSPARENT, BBEP_BLACK, f); + f += 0.25; + } + bbep.writePlane(); + bbep.refresh(REFRESH_FULL); + bbep.wait(); bbep.sleep(DEEP_SLEEP); } diff --git a/src/bb_ep_gfx.inl b/src/bb_ep_gfx.inl index 92472db..52403fc 100644 --- a/src/bb_ep_gfx.inl +++ b/src/bb_ep_gfx.inl @@ -505,18 +505,30 @@ void InvertBytes(uint8_t *pData, uint8_t bLen) // draw the 1's bits as the FG color and leave // the background (0 pixels) unchanged - aka transparent. // -int bbepLoadG5(BBEPDISP *pBBEP, const uint8_t *pG5, int x, int y, int iFG, int iBG) +int bbepLoadG5(BBEPDISP *pBBEP, const uint8_t *pG5, int x, int y, int iFG, int iBG, float fScale) { - uint16_t rc, tx, ty, cx, cy, size; + uint16_t rc, tx, ty, cx, cy, dx, dy, size; + int width, height; BB_BITMAP *pbbb; - - if (pBBEP == NULL || pG5 == NULL) return BBEP_ERROR_BAD_PARAMETER; - iFG = pBBEP->pColorLookup[iFG & 0xf]; // translate the color for this display type - iBG = pBBEP->pColorLookup[iBG & 0xf]; + uint32_t u32Frac, u32XAcc, u32YAcc; // integer fraction vars + + if (pBBEP == NULL || pG5 == NULL || fScale < 0.01) return BBEP_ERROR_BAD_PARAMETER; + if (iFG != BBEP_TRANSPARENT) { + iFG = pBBEP->pColorLookup[iFG & 0xf]; // translate the color for this display type + } + if (iBG != BBEP_TRANSPARENT) { + iBG = pBBEP->pColorLookup[iBG & 0xf]; + } pbbb = (BB_BITMAP *)pG5; if (pgm_read_word(&pbbb->u16Marker) != BB_BITMAP_MARKER) return BBEP_ERROR_BAD_DATA; + u32Frac = (uint32_t)(65536.0f / fScale); // calculate the fraction to advance the destination x/y cx = pgm_read_word(&pbbb->width); cy = pgm_read_word(&pbbb->height); + width = pBBEP->width; + height = pBBEP->height; + // Calculate scaled destination size + dx = (int)(fScale * (float)cx); + dy = (int)(fScale * (float)cy); size = pgm_read_word(&pbbb->size); if (iFG == -1) iFG = BBEP_WHITE; if (iBG == -1) iBG = BBEP_BLACK; @@ -525,10 +537,16 @@ int bbepLoadG5(BBEPDISP *pBBEP, const uint8_t *pG5, int x, int y, int iFG, int i if (!pBBEP->ucScreen) { // no back buffer bbepSetAddrWindow(pBBEP, x, y, cx+(x&7), cy); bbepStartWrite(pBBEP, pBBEP->iPlane); // get ready to write + dy = cy; // scaling is only supported on internal framebuffers + u32Frac = 65536; // force to 1.0 scale } - for (ty=y; tyheight; ty++) { + u32YAcc = 65536; // force first line to get decoded + for (ty=y; ty= 65536) { // advance to next source line + g5_decode_line(&g5dec, u8Cache); + u32YAcc -= 65536; + } if (!pBBEP->ucScreen) { if (x & 7) { // need to shift it over by 1-7 bits uint8_t *d = s = u8Cache, uc1, uc0; // last shifted byte @@ -553,13 +571,11 @@ 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=x; txpfnSetPixelFast)(pBBEP, tx, ty, (uint8_t)iFG); @@ -567,10 +583,19 @@ int bbepLoadG5(BBEPDISP *pBBEP, const uint8_t *pG5, int x, int y, int iFG, int i if (iBG != BBEP_TRANSPARENT) (*pBBEP->pfnSetPixelFast)(pBBEP, tx, ty, (uint8_t)iBG); } - src_mask >>= 1; + u32XAcc += u32Frac; + while (u32XAcc >= 65536) { + u32XAcc -= 65536; // whole source pixel horizontal movement + src_mask >>= 1; + if (src_mask == 0) { // need to load the next byte + u8 = *s++; + src_mask = 0x80; + } + } } // for tx #endif // NO_RAM } + u32YAcc += u32Frac; } // for y return BBEP_SUCCESS; } /* bbepLoadG5() */ diff --git a/src/bb_epaper.cpp b/src/bb_epaper.cpp index c3364a8..28e0495 100644 --- a/src/bb_epaper.cpp +++ b/src/bb_epaper.cpp @@ -223,9 +223,9 @@ void BBEPAPER::setCursor(int x, int y) _bbep.iCursorY = y; } /* setCursor() */ -int BBEPAPER::loadG5Image(const uint8_t *pG5, int x, int y, int iFG, int iBG) +int BBEPAPER::loadG5Image(const uint8_t *pG5, int x, int y, int iFG, int iBG, float fScale) { - return bbepLoadG5(&_bbep, pG5, x, y, iFG, iBG); + return bbepLoadG5(&_bbep, pG5, x, y, iFG, iBG, fScale); } /* loadG5Image() */ int BBEPAPER::loadBMP(const uint8_t *pBMP, int x, int y, int iFG, int iBG) diff --git a/src/bb_epaper.h b/src/bb_epaper.h index 98d214d..5bfdaa0 100644 --- a/src/bb_epaper.h +++ b/src/bb_epaper.h @@ -447,7 +447,7 @@ class BBEPAPER void setCursor(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); - int loadG5Image(const uint8_t *pG5, int x, int y, int iFG, int iBG); + int loadG5Image(const uint8_t *pG5, int x, int y, int iFG, int iBG, float fScale = 1.0f); void setFont(int iFont); void setFont(const void *pFont); void drawLine(int x1, int y1, int x2, int y2, int iColor);