mirror of
https://github.com/usetrmnl/bb_epaper.git
synced 2026-04-29 13:43:26 -07:00
Added support for CrowPanel 2.13 & 2.9, more compatibility with other display library APIs
This commit is contained in:
@@ -4,7 +4,7 @@ CC = gcc
|
||||
CFLAGS = -Wall -I/usr/local/include/freetype2 -I/usr/include/freetype2 -I/usr/include -I/opt/homebrew/include/freetype2
|
||||
LIBS = -L/opt/homebrew/lib -lfreetype
|
||||
|
||||
fontconvert: main.c
|
||||
fontconvert: main.c ../src/Group5.h
|
||||
$(CC) $(CFLAGS) main.c $(LIBS) -o fontconvert
|
||||
strip fontconvert
|
||||
|
||||
|
||||
+84
-48
@@ -91,12 +91,15 @@ int RotateBitmap(int iAngle, uint8_t *pSrc, int iWidth, int iHeight, int iSrcPit
|
||||
//
|
||||
// Create the comments and const array boilerplate for the hex data bytes
|
||||
//
|
||||
void StartHexFile(FILE *f, int iLen, const char *fname)
|
||||
void StartHexFile(FILE *f, int iLen, const char *fname, int size, int first, int last)
|
||||
{
|
||||
int i, j;
|
||||
char szTemp[256];
|
||||
fprintf(f, "//\n// Created with fontconvert, written by Larry Bank\n");
|
||||
fprintf(f, "// Point size: %d, first: %d, last: %d\n", size, first, last);
|
||||
fprintf(f, "// compressed font data size = %d bytes\n//\n", iLen);
|
||||
fprintf(f, "// for non-Arduino builds...\n#ifndef PROGMEM\n#define PROGMEM\n#endif\n");
|
||||
|
||||
strcpy(szTemp, fname);
|
||||
i = strlen(szTemp);
|
||||
if (szTemp[i-2] == '.') szTemp[i-2] = 0; // get the leaf name for the data
|
||||
@@ -106,7 +109,7 @@ void StartHexFile(FILE *f, int iLen, const char *fname)
|
||||
j--;
|
||||
}
|
||||
if (szTemp[j] == '/') j++;
|
||||
fprintf(f, "const uint8_t %s[] = {\n", &szTemp[j]);
|
||||
fprintf(f, "const uint8_t %s[] PROGMEM = {\n", &szTemp[j]);
|
||||
} /* StartHexFile() */
|
||||
//
|
||||
// Add N bytes of hex data to the output
|
||||
@@ -162,8 +165,12 @@ int main(int argc, char *argv[])
|
||||
FT_Bitmap *bitmap;
|
||||
FT_BitmapGlyphRec *g;
|
||||
// BitBank Font structures
|
||||
int bSmallFont = 0; // indicates if we're creating a normal or small font file
|
||||
BB_GLYPH *pGlyphs;
|
||||
BB_GLYPH_SMALL *pSmallGlyphs;
|
||||
BB_FONT bbff;
|
||||
BB_FONT_SMALL bbf2;
|
||||
|
||||
int bHFile; // flag indicating if the output will be a .H file of hex data
|
||||
|
||||
if (argc < 4) {
|
||||
@@ -171,6 +178,7 @@ int main(int argc, char *argv[])
|
||||
return 1;
|
||||
}
|
||||
size = atoi(argv[3]);
|
||||
bSmallFont = (size < 60); // Glyph info can fit in signed 8-bit values
|
||||
pTemp = (uint8_t *)argv[2] + strlen(argv[2]) - 1;
|
||||
bHFile = (pTemp[0] == 'H' || pTemp[0] == 'h'); // output an H file?
|
||||
|
||||
@@ -191,10 +199,18 @@ int main(int argc, char *argv[])
|
||||
printf("Something went wrong - the starting character comes after the ending character. Try again...\n");
|
||||
return 1;
|
||||
}
|
||||
pGlyphs = (BB_GLYPH *)malloc((last - first + 1) * sizeof(BB_GLYPH));
|
||||
if (!pGlyphs) {
|
||||
printf("Error allocating memory for glyph data\n");
|
||||
return 1;
|
||||
if (bSmallFont) {
|
||||
pSmallGlyphs = (BB_GLYPH_SMALL *)malloc((last - first + 1) * sizeof(BB_GLYPH_SMALL));
|
||||
if (!pSmallGlyphs) {
|
||||
printf("Error allocating memory for glyph data\n");
|
||||
return 1;
|
||||
}
|
||||
} else {
|
||||
pGlyphs = (BB_GLYPH *)malloc((last - first + 1) * sizeof(BB_GLYPH));
|
||||
if (!pGlyphs) {
|
||||
printf("Error allocating memory for glyph data\n");
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
pBitmap = (uint8_t *)malloc(OUTBUF_SIZE); // Enough to hold the output
|
||||
pTemp = (uint8_t *)malloc(OUTBUF_SIZE); // for rotated bitmaps
|
||||
@@ -259,27 +275,21 @@ int main(int argc, char *argv[])
|
||||
bitmap = &face->glyph->bitmap;
|
||||
g = (FT_BitmapGlyphRec *)glyph;
|
||||
|
||||
// Minimal font and per-glyph information is stored to
|
||||
// reduce flash space requirements. Glyph bitmaps are
|
||||
// fully bit-packed; no per-scanline pad, though end of
|
||||
// each character may be padded to next byte boundary
|
||||
// when needed. 16-bit offset means 64K max for bitmaps,
|
||||
// code currently doesn't check for overflow. (Doesn't
|
||||
// check that size & offsets are within bounds either for
|
||||
// that matter...please convert fonts responsibly.)
|
||||
|
||||
// Check that the requested font size fits within the limits
|
||||
// of the 8-bit member variables
|
||||
if (bitmap->width > 255 || (face->glyph->advance.x>>6) > 255) {
|
||||
printf("The requested size is too large to fit in the BB_GLYPH member vars\nEither request a smaller size or change the member variables to be 16-bits\n");
|
||||
return -1;
|
||||
if (bSmallFont) {
|
||||
pSmallGlyphs[index].bitmapOffset = iOffset;
|
||||
pSmallGlyphs[index].width = bitmap->width;
|
||||
pSmallGlyphs[index].height = bitmap->rows;
|
||||
pSmallGlyphs[index].xAdvance = face->glyph->advance.x >> 6;
|
||||
pSmallGlyphs[index].xOffset = g->left;
|
||||
pSmallGlyphs[index].yOffset = 1 - g->top;
|
||||
} else {
|
||||
pGlyphs[index].bitmapOffset = iOffset;
|
||||
pGlyphs[index].width = bitmap->width;
|
||||
pGlyphs[index].height = bitmap->rows;
|
||||
pGlyphs[index].xAdvance = face->glyph->advance.x >> 6;
|
||||
pGlyphs[index].xOffset = g->left;
|
||||
pGlyphs[index].yOffset = 1 - g->top;
|
||||
}
|
||||
pGlyphs[index].bitmapOffset = iOffset;
|
||||
pGlyphs[index].width = bitmap->width;
|
||||
pGlyphs[index].height = bitmap->rows;
|
||||
pGlyphs[index].xAdvance = face->glyph->advance.x >> 6;
|
||||
pGlyphs[index].xOffset = g->left;
|
||||
pGlyphs[index].yOffset = 1 - g->top;
|
||||
s = bitmap->buffer;
|
||||
iPitch = bitmap->pitch;
|
||||
if (iRotation != 0) {
|
||||
@@ -308,29 +318,55 @@ int main(int argc, char *argv[])
|
||||
return 1;
|
||||
}
|
||||
// Write the file header
|
||||
bbff.u16Marker = BB_FONT_MARKER;
|
||||
bbff.first = first;
|
||||
bbff.last = last;
|
||||
bbff.rotation = iRotation; // save rotation angle
|
||||
if (face->size->metrics.height == 0) {
|
||||
// No face height info, assume fixed width and get from a glyph.
|
||||
bbff.height = pGlyphs[0].height;
|
||||
if (bSmallFont) {
|
||||
bbf2.u16Marker = BB_FONT_MARKER_SMALL;
|
||||
bbf2.first = first;
|
||||
bbf2.last = last;
|
||||
bbf2.rotation = iRotation; // save rotation angle
|
||||
if (face->size->metrics.height == 0) {
|
||||
// No face height info, assume fixed width and get from a glyph.
|
||||
bbf2.height = pGlyphs[0].height;
|
||||
} else {
|
||||
bbf2.height = (face->size->metrics.height >> 6);
|
||||
}
|
||||
iLen = sizeof(bbf2) + (last-first+1)*sizeof(BB_GLYPH_SMALL) + iOffset;
|
||||
if (bHFile) { // create an H file of hex values
|
||||
StartHexFile(fOut, iLen, argv[2], size, first, last);
|
||||
AddHexBytes(fOut, &bbf2, sizeof(bbf2), 0);
|
||||
AddHexBytes(fOut, pSmallGlyphs, (last-first+1) * sizeof(BB_GLYPH_SMALL), 0);
|
||||
AddHexBytes(fOut, pBitmap, iOffset, 1);
|
||||
} else {
|
||||
fwrite(&bbf2, 1, sizeof(bbf2), fOut);
|
||||
// Write the glyph table
|
||||
fwrite(pSmallGlyphs, (last-first+1), sizeof(BB_GLYPH_SMALL), fOut);
|
||||
// Write the compressed bitmap data
|
||||
fwrite(pBitmap, 1, iOffset, fOut);
|
||||
}
|
||||
} else {
|
||||
bbff.height = (face->size->metrics.height >> 6);
|
||||
}
|
||||
iLen = sizeof(bbff) + (last-first+1)*sizeof(BB_GLYPH) + iOffset;
|
||||
if (bHFile) { // create an H file of hex values
|
||||
StartHexFile(fOut, iLen, argv[2]);
|
||||
AddHexBytes(fOut, &bbff, sizeof(bbff), 0);
|
||||
AddHexBytes(fOut, pGlyphs, (last-first+1) * sizeof(BB_GLYPH), 0);
|
||||
AddHexBytes(fOut, pBitmap, iOffset, 1);
|
||||
} else {
|
||||
fwrite(&bbff, 1, sizeof(bbff), fOut);
|
||||
// Write the glyph table
|
||||
fwrite(pGlyphs, (last-first+1), sizeof(BB_GLYPH), fOut);
|
||||
// Write the compressed bitmap data
|
||||
fwrite(pBitmap, 1, iOffset, fOut);
|
||||
}
|
||||
bbff.u16Marker = BB_FONT_MARKER;
|
||||
bbff.first = first;
|
||||
bbff.last = last;
|
||||
bbff.rotation = iRotation; // save rotation angle
|
||||
if (face->size->metrics.height == 0) {
|
||||
// No face height info, assume fixed width and get from a glyph.
|
||||
bbff.height = pGlyphs[0].height;
|
||||
} else {
|
||||
bbff.height = (face->size->metrics.height >> 6);
|
||||
}
|
||||
iLen = sizeof(bbff) + (last-first+1)*sizeof(BB_GLYPH) + iOffset;
|
||||
if (bHFile) { // create an H file of hex values
|
||||
StartHexFile(fOut, iLen, argv[2], size, first, last);
|
||||
AddHexBytes(fOut, &bbff, sizeof(bbff), 0);
|
||||
AddHexBytes(fOut, pGlyphs, (last-first+1) * sizeof(BB_GLYPH), 0);
|
||||
AddHexBytes(fOut, pBitmap, iOffset, 1);
|
||||
} else {
|
||||
fwrite(&bbff, 1, sizeof(bbff), fOut);
|
||||
// Write the glyph table
|
||||
fwrite(pGlyphs, (last-first+1), sizeof(BB_GLYPH), fOut);
|
||||
// Write the compressed bitmap data
|
||||
fwrite(pBitmap, 1, iOffset, fOut);
|
||||
}
|
||||
} // large fonts
|
||||
fflush(fOut);
|
||||
fclose(fOut); // done!
|
||||
FT_Done_FreeType(library);
|
||||
|
||||
+40
-13
@@ -12,14 +12,18 @@
|
||||
// Written by Larry Bank
|
||||
// Copyright (c) 2024 BitBank Software, Inc.
|
||||
//
|
||||
// Use of this software is governed by the Business Source License
|
||||
// included in the file ./LICENSE.
|
||||
//
|
||||
// As of the Change Date specified in that file, in accordance with
|
||||
// the Business Source License, use of this software will be governed
|
||||
// by the Apache License, Version 2.0, included in the file
|
||||
// ./APL.txt.
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//===========================================================================
|
||||
//
|
||||
|
||||
// The name "Group5" is derived from the CCITT Group4 standard
|
||||
// This code is based on a lot of the good ideas from CCITT T.6
|
||||
// for FAX image compression, but modified to work in a very
|
||||
@@ -111,13 +115,13 @@ inline uint32_t TIFFMOTOLONG(uint8_t *p)
|
||||
// G5 Encoder
|
||||
//
|
||||
|
||||
typedef struct pil_buffered_bits
|
||||
typedef struct g5_buffered_bits
|
||||
{
|
||||
unsigned char *pBuf; // buffer pointer
|
||||
uint32_t ulBits; // buffered bits
|
||||
uint32_t ulBitOff; // current bit offset
|
||||
uint32_t ulDataSize; // available data
|
||||
} BUFFERED_BITS;
|
||||
} G5_BUFFERED_BITS;
|
||||
|
||||
//
|
||||
// Encoder state
|
||||
@@ -131,7 +135,7 @@ typedef struct g5_enc_image_tag
|
||||
int iDataSize; // generated output size
|
||||
uint8_t *pOutBuf;
|
||||
int16_t *pCur, *pRef; // pointers to swap current and reference lines
|
||||
BUFFERED_BITS bb;
|
||||
G5_BUFFERED_BITS bb;
|
||||
int16_t CurFlips[MAX_IMAGE_FLIPS];
|
||||
int16_t RefFlips[MAX_IMAGE_FLIPS];
|
||||
} G5ENCIMAGE;
|
||||
@@ -139,20 +143,33 @@ typedef struct g5_enc_image_tag
|
||||
// 16-bit marker at the start of a BB_FONT file
|
||||
// (BitBank FontFile)
|
||||
#define BB_FONT_MARKER 0xBBFF
|
||||
#define BB_FONT_MARKER_SMALL 0xBBF2
|
||||
|
||||
// 16-bit marker at the start of a BB_BITMAP file
|
||||
// (BitBank BitmapFile)
|
||||
#define BB_BITMAP_MARKER 0xBBBF
|
||||
|
||||
// Font info per character (glyph)
|
||||
// Font info per large character (glyph)
|
||||
typedef struct {
|
||||
uint16_t bitmapOffset; // Offset to compressed bitmap data for this glyph (starting from the end of the BB_GLYPH[] array)
|
||||
uint8_t width; // bitmap width in pixels
|
||||
uint8_t xAdvance; // total width in pixels (bitmap + padding)
|
||||
uint16_t width; // bitmap width in pixels
|
||||
uint16_t xAdvance; // total width in pixels (bitmap + padding)
|
||||
uint16_t height; // bitmap height in pixels
|
||||
int16_t xOffset; // left padding to upper left corner
|
||||
int16_t yOffset; // padding from baseline to upper left corner (usually negative)
|
||||
} BB_GLYPH;
|
||||
|
||||
// Font info per small character (glyph)
|
||||
typedef struct bbg_small {
|
||||
uint16_t bitmapOffset; // Offset to compressed bitmap data for this glyph (starting from the end of the BB_GLYPH[] array)
|
||||
uint8_t width; // bitmap width in pixels
|
||||
uint8_t xAdvance; // total width in pixels (bitmap + padding)
|
||||
uint8_t height; // bitmap height in pixels
|
||||
int8_t xOffset; // left padding to upper left corner
|
||||
int8_t yOffset; // padding from baseline to upper left corner (usually negative)
|
||||
int8_t struct_padding; // pad the structure to 8 bytes to prevent alignment problems on different target compilers/settings
|
||||
} BB_GLYPH_SMALL;
|
||||
|
||||
// This structure is stored at the beginning of a BB_FONT file
|
||||
typedef struct {
|
||||
uint16_t u16Marker; // 16-bit Marker defining a BB_FONT file
|
||||
@@ -163,6 +180,16 @@ typedef struct {
|
||||
BB_GLYPH glyphs[]; // Array of glyphs (one for each char)
|
||||
} BB_FONT;
|
||||
|
||||
// This structure is stored at the beginning of a BB_FONT_SMALL file
|
||||
typedef struct {
|
||||
uint16_t u16Marker; // 16-bit Marker defining a BB_FONT_SMALL file
|
||||
uint16_t first; // first char (ASCII value)
|
||||
uint16_t last; // last char (ASCII value)
|
||||
uint16_t height; // total height of font
|
||||
uint32_t rotation; // store this as 32-bits to not have a struct packing problem
|
||||
BB_GLYPH_SMALL glyphs[]; // Array of glyphs (one for each char)
|
||||
} BB_FONT_SMALL;
|
||||
|
||||
// This structure defines the start of a compressed bitmap file
|
||||
typedef struct {
|
||||
uint16_t u16Marker; // 16-bit marker defining a BB_BITMAP file
|
||||
|
||||
+6
-2
@@ -64,10 +64,14 @@ void bbepInitIO(BBEPDISP *pBBEP, uint8_t u8DC, uint8_t u8RST, uint8_t u8BUSY, ui
|
||||
SPI.begin(); // other architectures have fixed SPI pins
|
||||
#endif
|
||||
SPI.beginTransaction(SPISettings(u32Speed, MSBFIRST, SPI_MODE0));
|
||||
#ifdef ARDUINO_ARCH_ESP32
|
||||
// For NRF52, you have to leave an 'open' transaction
|
||||
SPI.endTransaction(); // N.B. - if you call beginTransaction() again without a matching endTransaction(), it will hang on ESP32
|
||||
#endif
|
||||
pBBEP->is_awake = 1;
|
||||
// Before we can start sending pixels, many panels need to know the display resolution
|
||||
bbepSendCMDSequence(pBBEP, pBBEP->pInitFull);
|
||||
if (pBBEP->iFlags & BBEP_7COLOR) { // need to send before you can send it data
|
||||
pBBEP->is_awake = 1;
|
||||
bbepSendCMDSequence(pBBEP, pBBEP->pInitFull);
|
||||
if (pBBEP->iFlags & BBEP_SPLIT_BUFFER) {
|
||||
// Send the same sequence to the second controller
|
||||
pBBEP->iCSPin = pBBEP->iCS2Pin;
|
||||
|
||||
+719
-56
File diff suppressed because it is too large
Load Diff
+210
-27
@@ -25,7 +25,7 @@
|
||||
static G5DECIMAGE g5dec;
|
||||
// forward declarations
|
||||
void InvertBytes(uint8_t *pData, uint8_t bLen);
|
||||
|
||||
void bbepUnicodeString(const char *szMsg, uint8_t *szExtMsg);
|
||||
const uint8_t ucFont[]PROGMEM = {
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x5f,0x5f,0x06,0x00,
|
||||
0x00,0x07,0x07,0x00,0x07,0x07,0x00,0x14,0x7f,0x7f,0x14,0x7f,0x7f,0x14,
|
||||
@@ -174,6 +174,77 @@ const uint8_t ucSmallFont[] PROGMEM = {
|
||||
0x00,0x41,0x41,0x3e,0x08,
|
||||
0x02,0x01,0x02,0x01,0x00,
|
||||
0x3c,0x26,0x23,0x26,0x3c};
|
||||
//
|
||||
// Get the size of text in a custom font area
|
||||
//
|
||||
void bbepGetStringBox(BBEPDISP *pBBEP, const char *szMsg, BB_RECT *pRect)
|
||||
{
|
||||
int cx = 0;
|
||||
unsigned int c, i = 0;
|
||||
BB_FONT *pBBF;
|
||||
BB_FONT_SMALL *pBBFS;
|
||||
BB_GLYPH *pGlyph;
|
||||
BB_GLYPH_SMALL *pSmallGlyph;
|
||||
int miny, maxy;
|
||||
uint8_t szExtMsg[80];
|
||||
|
||||
miny = 4000; maxy = 0;
|
||||
if (pBBEP == NULL || pRect == NULL || szMsg == NULL) return; // bad pointers
|
||||
|
||||
if (pBBEP->pFont == NULL) { // built-in font
|
||||
miny = 0;
|
||||
switch (pBBEP->iFont) {
|
||||
case FONT_6x8:
|
||||
cx = 6;
|
||||
maxy = 8;
|
||||
break;
|
||||
case FONT_8x8:
|
||||
cx = 8;
|
||||
maxy = 8;
|
||||
break;
|
||||
case FONT_12x16:
|
||||
cx = 12;
|
||||
maxy = 16;
|
||||
break;
|
||||
case FONT_16x16:
|
||||
cx = 16;
|
||||
maxy = 16;
|
||||
break;
|
||||
}
|
||||
cx *= strlen(szMsg);
|
||||
} else { // proportional fonts
|
||||
bbepUnicodeString(szMsg, szExtMsg); // convert to extended ASCII
|
||||
if (pgm_read_word(pBBEP->pFont) == BB_FONT_MARKER) {
|
||||
pBBF = (BB_FONT *)pBBEP->pFont; pBBFS = NULL;
|
||||
} else { // small font
|
||||
pBBFS = (BB_FONT_SMALL *)pBBEP->pFont; pBBF = NULL;
|
||||
}
|
||||
while (szExtMsg[i]) {
|
||||
c = szExtMsg[i++];
|
||||
if (pBBF) { // big font
|
||||
if (c < pgm_read_byte(&pBBF->first) || c > pgm_read_byte(&pBBF->last)) // undefined character
|
||||
continue; // skip it
|
||||
c -= pgm_read_byte(&pBBF->first); // first char of font defined
|
||||
pGlyph = &pBBF->glyphs[c];
|
||||
cx += pgm_read_word(&pGlyph->xAdvance);
|
||||
if ((int16_t)pgm_read_word(&pGlyph->yOffset) < miny) miny = pgm_read_word(&pGlyph->yOffset);
|
||||
if (pgm_read_word(&pGlyph->height)+(int16_t)pgm_read_word(&pGlyph->yOffset) > maxy) maxy = pgm_read_word(&pGlyph->height)+(int16_t)pgm_read_word(&pGlyph->yOffset);
|
||||
} else { // small font
|
||||
if (c < pgm_read_byte(&pBBFS->first) || c > pgm_read_byte(&pBBFS->last)) // undefined character
|
||||
continue; // skip it
|
||||
c -= pgm_read_byte(&pBBFS->first); // first char of font defined
|
||||
pSmallGlyph = &pBBFS->glyphs[c];
|
||||
cx += pgm_read_byte(&pSmallGlyph->xAdvance);
|
||||
if ((int8_t)pgm_read_byte(&pSmallGlyph->yOffset) < miny) miny = (int8_t)pgm_read_byte(&pSmallGlyph->yOffset);
|
||||
if (pgm_read_byte(&pSmallGlyph->height)+(int8_t)pgm_read_byte(&pSmallGlyph->yOffset) > maxy) maxy = pgm_read_byte(&pSmallGlyph->height)+(int8_t)pgm_read_byte(&pSmallGlyph->yOffset);
|
||||
} // small
|
||||
}
|
||||
} // prop fonts
|
||||
pRect->w = cx;
|
||||
pRect->x = pBBEP->iCursorX;
|
||||
pRect->y = pBBEP->iCursorY + miny;
|
||||
pRect->h = maxy - miny + 1;
|
||||
} /* bbepGetStringBox() */
|
||||
|
||||
//
|
||||
// Draw a sprite of any size in any position
|
||||
@@ -327,6 +398,61 @@ BBEPDISP *pBBEP = (BBEPDISP *)pb;
|
||||
pBBEP->ucScreen[i] = u8;
|
||||
} /* bbepSetPixelFast4Clr() */
|
||||
|
||||
int bbepSetPixel4Gray(void *pb, int x, int y, unsigned char ucColor)
|
||||
{
|
||||
int i;
|
||||
int iPitch, iSize;
|
||||
BBEPDISP *pBBEP = (BBEPDISP *)pb;
|
||||
const uint8_t u8Mask = 0x80 >> (x & 7);
|
||||
|
||||
// only available for local buffer operations
|
||||
if (!pBBEP || !pBBEP->ucScreen) return BBEP_ERROR_BAD_PARAMETER;
|
||||
ucColor = pBBEP->pColorLookup[ucColor & 0xf]; // translate the color for this display type
|
||||
|
||||
iPitch = (pBBEP->width+7)>>3;
|
||||
iSize = ((pBBEP->native_width+7)>>3) * pBBEP->native_height;
|
||||
|
||||
i = (x >> 3) + (y * iPitch);
|
||||
if (x < 0 || x >= pBBEP->width || i < 0 || i > iSize-1) { // off the screen
|
||||
pBBEP->last_error = BBEP_ERROR_BAD_PARAMETER;
|
||||
return BBEP_ERROR_BAD_PARAMETER;
|
||||
}
|
||||
if (ucColor & 1) { // first plane
|
||||
pBBEP->ucScreen[i] |= u8Mask;
|
||||
} else {
|
||||
pBBEP->ucScreen[i] &= ~u8Mask;
|
||||
}
|
||||
if (ucColor & 2) { // second plane
|
||||
pBBEP->ucScreen[iSize + i] |= u8Mask;
|
||||
} else {
|
||||
pBBEP->ucScreen[iSize + i] &= ~u8Mask;
|
||||
}
|
||||
return BBEP_SUCCESS;
|
||||
} /* bbepSetPixel4Gray() */
|
||||
|
||||
void bbepSetPixelFast4Gray(void *pb, int x, int y, unsigned char ucColor)
|
||||
{
|
||||
int i;
|
||||
int iPitch, iSize;
|
||||
BBEPDISP *pBBEP = (BBEPDISP *)pb;
|
||||
const uint8_t u8Mask = 0x80 >> (x & 7);
|
||||
|
||||
iPitch = (pBBEP->width+7)>>3;
|
||||
iSize = ((pBBEP->native_width+7)>>3) * pBBEP->native_height;
|
||||
i = (x >> 3) + (y * iPitch);
|
||||
|
||||
if (ucColor & 1) { // first plane
|
||||
pBBEP->ucScreen[i] |= u8Mask;
|
||||
} else {
|
||||
pBBEP->ucScreen[i] &= ~u8Mask;
|
||||
}
|
||||
if (ucColor & 2) { // second plane
|
||||
pBBEP->ucScreen[iSize + i] |= u8Mask;
|
||||
} else {
|
||||
pBBEP->ucScreen[iSize + i] &= ~u8Mask;
|
||||
}
|
||||
} /* bbepSetPixelFast4Gray() */
|
||||
|
||||
int bbepSetPixel3Clr(void *pb, int x, int y, unsigned char ucColor)
|
||||
{
|
||||
int i;
|
||||
@@ -959,13 +1085,16 @@ uint16_t u16CP; // 16-bit codepoint encoded by the multi-byte sequence
|
||||
//
|
||||
// Draw a string of BB_FONT characters directly into the EPD framebuffer
|
||||
//
|
||||
int bbepWriteStringCustom(BBEPDISP *pBBEP, BB_FONT *pFont, int x, int y, char *szMsg, int iColor, uint8_t iPlane)
|
||||
int bbepWriteStringCustom(BBEPDISP *pBBEP, void *pFont, int x, int y, char *szMsg, int iColor, uint8_t iPlane)
|
||||
{
|
||||
int rc, i, h, w, j, end_y, dx, dy, tx, ty, tw, iSrcPitch, iPitch, iBG;
|
||||
signed int n;
|
||||
unsigned int c, bInvert = 0;
|
||||
uint8_t *s, uc0, uc1;
|
||||
BB_FONT *pBBF;
|
||||
BB_FONT_SMALL *pBBFS;
|
||||
BB_GLYPH *pGlyph;
|
||||
BB_GLYPH_SMALL *pSmallGlyph;
|
||||
uint8_t *pBits, u8CMD1, u8CMD2, u8CMD, u8EndMask;
|
||||
uint8_t szExtMsg[256]; // translated extended ASCII message text
|
||||
uint8_t first, last;
|
||||
@@ -975,6 +1104,15 @@ int bbepWriteStringCustom(BBEPDISP *pBBEP, BB_FONT *pFont, int x, int y, char *s
|
||||
pBBEP->last_error = BBEP_ERROR_BAD_PARAMETER;
|
||||
return BBEP_ERROR_BAD_PARAMETER; // invalid param
|
||||
}
|
||||
// Determine if we're using a small or large font
|
||||
if (pgm_read_word(pFont) == BB_FONT_MARKER) {
|
||||
pBBF = (BB_FONT *)pFont;
|
||||
pBBFS = NULL;
|
||||
} else {
|
||||
pBBFS = (BB_FONT_SMALL *)pFont;
|
||||
pBBF = NULL;
|
||||
}
|
||||
|
||||
if (iColor != BBEP_TRANSPARENT) {
|
||||
iColor = pBBEP->pColorLookup[iColor & 0xf]; // translate the color for this display type
|
||||
}
|
||||
@@ -992,8 +1130,13 @@ int bbepWriteStringCustom(BBEPDISP *pBBEP, BB_FONT *pFont, int x, int y, char *s
|
||||
x = pBBEP->iCursorX;
|
||||
if (y == -1)
|
||||
y = pBBEP->iCursorY;
|
||||
first = pgm_read_byte(&pFont->first);
|
||||
last = pgm_read_byte(&pFont->last);
|
||||
if (pBBF) {
|
||||
first = pgm_read_byte(&pBBF->first);
|
||||
last = pgm_read_byte(&pBBF->last);
|
||||
} else {
|
||||
first = pgm_read_byte(&pBBFS->first);
|
||||
last = pgm_read_byte(&pBBFS->last);
|
||||
}
|
||||
if (x == CENTER_X) { // center the string on the e-paper
|
||||
dx = i = 0;
|
||||
while (szExtMsg[i]) {
|
||||
@@ -1001,37 +1144,67 @@ int bbepWriteStringCustom(BBEPDISP *pBBEP, BB_FONT *pFont, int x, int y, char *s
|
||||
if (c < first || c > last) // undefined character
|
||||
continue; // skip it
|
||||
c -= first; // first char of font defined
|
||||
pGlyph = &pFont->glyphs[c]; // glyph info for this character
|
||||
dx += pgm_read_byte(&pGlyph->xAdvance);
|
||||
if (pBBF) {
|
||||
pGlyph = &pBBF->glyphs[c]; // glyph info for this character
|
||||
dx += pgm_read_word(&pGlyph->xAdvance);
|
||||
} else { // small font
|
||||
pSmallGlyph = &pBBFS->glyphs[c]; // glyph info for this character
|
||||
dx += pgm_read_byte(&pSmallGlyph->xAdvance);
|
||||
}
|
||||
}
|
||||
x = (pBBEP->width - dx)/2;
|
||||
if (x < 0) x = 0;
|
||||
}
|
||||
// Point to the start of the compressed data
|
||||
pBits = (uint8_t *)pFont;
|
||||
pBits += sizeof(BB_FONT);
|
||||
pBits += (last - first + 1) * sizeof(BB_GLYPH);
|
||||
if (pBBF) {
|
||||
pBits = (uint8_t *)pBBF;
|
||||
pBits += sizeof(BB_FONT);
|
||||
pBits += (last - first + 1) * sizeof(BB_GLYPH);
|
||||
} else {
|
||||
pBits = (uint8_t *)pBBFS;
|
||||
pBits += sizeof(BB_FONT_SMALL);
|
||||
pBits += (last - first + 1) * sizeof(BB_GLYPH_SMALL);
|
||||
}
|
||||
i = 0;
|
||||
while (szExtMsg[i] && x < pBBEP->width && y < pBBEP->height) {
|
||||
int16_t xOffset, yOffset;
|
||||
uint32_t u32Offset, u32Rot, xAdvance;
|
||||
c = szExtMsg[i++];
|
||||
if (c < first || c > last) // undefined character
|
||||
continue; // skip it
|
||||
c -= first; // first char of font defined
|
||||
pGlyph = &pFont->glyphs[c]; // glyph info for this character
|
||||
if (pgm_read_byte(&pGlyph->width) > 1) { // skip this if drawing a space
|
||||
s = pBits + pgm_read_word(&pGlyph->bitmapOffset); // start of compressed bitmap data
|
||||
if (pgm_read_dword(&pFont->rotation) == 0 || pgm_read_dword(&pFont->rotation) == 180) {
|
||||
h = pgm_read_word(&pGlyph->height);
|
||||
w = pgm_read_byte(&pGlyph->width);
|
||||
dx = x + (int16_t)pgm_read_word(&pGlyph->xOffset); // offset from character UL to start drawing
|
||||
dy = y + (int16_t)pgm_read_word(&pGlyph->yOffset);
|
||||
if (pBBF) {
|
||||
pGlyph = &pBBF->glyphs[c]; // glyph info for this character
|
||||
w = pgm_read_word(&pGlyph->width);
|
||||
h = pgm_read_word(&pGlyph->height);
|
||||
u32Offset = pgm_read_word(&pGlyph->bitmapOffset);
|
||||
u32Rot = pgm_read_dword(&pBBF->rotation);
|
||||
xAdvance = pgm_read_word(&pGlyph->xAdvance);
|
||||
xOffset = (int16_t)pgm_read_word(&pGlyph->xOffset);
|
||||
yOffset = (int16_t)pgm_read_word(&pGlyph->yOffset);
|
||||
} else { // small font
|
||||
pSmallGlyph = &pBBFS->glyphs[c]; // glyph info for this character
|
||||
w = pgm_read_byte(&pSmallGlyph->width);
|
||||
h = pgm_read_byte(&pSmallGlyph->height);
|
||||
u32Offset = pgm_read_word(&pSmallGlyph->bitmapOffset);
|
||||
u32Rot = pgm_read_dword(&pBBFS->rotation);
|
||||
xAdvance = pgm_read_byte(&pSmallGlyph->xAdvance);
|
||||
xOffset = (int8_t)pgm_read_byte(&pSmallGlyph->xOffset);
|
||||
yOffset = (int8_t)pgm_read_byte(&pSmallGlyph->yOffset);
|
||||
}
|
||||
if (w > 1) { // skip this if drawing a space
|
||||
s = pBits + u32Offset; // start of compressed bitmap data
|
||||
if (u32Rot == 0 || u32Rot == 180) {
|
||||
dx = x + xOffset; // offset from character UL to start drawing
|
||||
dy = y + yOffset;
|
||||
} else { // rotated
|
||||
w = pgm_read_word(&pGlyph->height);
|
||||
h = pgm_read_byte(&pGlyph->width);
|
||||
n = (int16_t)pgm_read_word(&pGlyph->yOffset); // offset from character UL to start drawing
|
||||
dx = w; // swap height/width
|
||||
w = h;
|
||||
h = dx;
|
||||
n = yOffset; // offset from character UL to start drawing
|
||||
dx = x;
|
||||
if (-n < w) dx -= (w+n); // since we draw from the baseline
|
||||
dy = y + (int16_t)pgm_read_word(&pGlyph->xOffset);
|
||||
dy = y + xOffset;
|
||||
}
|
||||
if ((dy + h) > pBBEP->height) { // trim it
|
||||
h = pBBEP->height - dy;
|
||||
@@ -1041,7 +1214,11 @@ int bbepWriteStringCustom(BBEPDISP *pBBEP, BB_FONT *pFont, int x, int y, char *s
|
||||
u8EndMask <<= (8-(w & 7));
|
||||
}
|
||||
end_y = dy + h;
|
||||
ty = (pgm_read_word(&pGlyph[1].bitmapOffset) - (intptr_t)(s - pBits)); // compressed size
|
||||
if (pBBF) {
|
||||
ty = (pgm_read_word(&pGlyph[1].bitmapOffset) - (intptr_t)(s - pBits)); // compressed size
|
||||
} else {
|
||||
ty = (pgm_read_word(&pSmallGlyph[1].bitmapOffset) - (intptr_t)(s - pBits)); // compressed size
|
||||
}
|
||||
if (ty < 0 || ty > 4096) ty = 4096; // DEBUG
|
||||
rc = g5_decode_init(&g5dec, w, h, s, ty);
|
||||
if (rc != G5_SUCCESS) {
|
||||
@@ -1101,6 +1278,9 @@ int bbepWriteStringCustom(BBEPDISP *pBBEP, BB_FONT *pFont, int x, int y, char *s
|
||||
else if (iColor == BBEP_RED && (pBBEP->iFlags & BBEP_3COLOR)) {
|
||||
u8CMD = u8CMD2; // second plane is red (inverted)
|
||||
}
|
||||
if (!(pBBEP->iFlags & BBEP_3COLOR) && pBBEP->iPlane == 1) {
|
||||
u8CMD = u8CMD2; // set second plane for partial updates
|
||||
}
|
||||
bbepWriteCmd(pBBEP, u8CMD); // memory write command
|
||||
for (ty=dy; ty<end_y && rc == G5_SUCCESS && ty < pBBEP->native_height; ty++) {
|
||||
rc = g5_decode_line(&g5dec, u8Cache);
|
||||
@@ -1124,10 +1304,10 @@ int bbepWriteStringCustom(BBEPDISP *pBBEP, BB_FONT *pFont, int x, int y, char *s
|
||||
} // for y
|
||||
}
|
||||
} // if not drawing a space
|
||||
if (pgm_read_dword(&pFont->rotation) == 0 || pgm_read_dword(&pFont->rotation) == 180) {
|
||||
x += pgm_read_byte(&pGlyph->xAdvance); // width of this character
|
||||
if (u32Rot == 0 || u32Rot == 180) {
|
||||
x += xAdvance; // width of this character
|
||||
} else {
|
||||
y += pgm_read_byte(&pGlyph->xAdvance);
|
||||
y += xAdvance;
|
||||
}
|
||||
} // while drawing characters
|
||||
pBBEP->iCursorX = x;
|
||||
@@ -1611,7 +1791,7 @@ void bbepGetStringBox(BBEPDISP *pBBEP, BB_FONT *pFont, const char *szMsg, int *w
|
||||
*bottom = maxy;
|
||||
} /* bbepGetStringBox() */
|
||||
|
||||
int bbepAllocBuffer(BBEPDISP *pBBEP)
|
||||
int bbepAllocBuffer(BBEPDISP *pBBEP, int bDoubleSize)
|
||||
{
|
||||
#ifndef NO_RAM
|
||||
int iSize;
|
||||
@@ -1619,7 +1799,10 @@ int bbepAllocBuffer(BBEPDISP *pBBEP)
|
||||
iSize = (pBBEP->native_width >> 1) * pBBEP->native_height;
|
||||
} else { // B/W or B/W/R or B/W/R/Y
|
||||
iSize = ((pBBEP->native_width+7)>>3) * pBBEP->native_height;
|
||||
iSize *= 2; // 2 bit planes
|
||||
if (bDoubleSize) {
|
||||
iSize *= 2; // 2 bit planes
|
||||
pBBEP->iFlags |= BBEP_HAS_SECOND_PLANE;
|
||||
}
|
||||
}
|
||||
#if defined (HAL_ESP32_HAL_H_) && !defined(__riscv)
|
||||
if (iSize > 98000) { // need to use PSRAM
|
||||
|
||||
+96
-28
@@ -65,6 +65,54 @@ void BBEPAPER::setAddrWindow(int x, int y, int w, int h)
|
||||
bbepSetAddrWindow(&_bbep, x, y, w, h);
|
||||
}
|
||||
|
||||
int BBEPAPER::begin(int iProduct)
|
||||
{
|
||||
int rc = BBEP_ERROR_BAD_PARAMETER;
|
||||
|
||||
switch (iProduct) {
|
||||
case EPD_LILYGO_S3_MINI: // DC:12 CS:13 RST: 11 BUSY: 10 SCK: 14 MOSI: 15
|
||||
if (setPanelType(EP102_80x128) == BBEP_SUCCESS) {
|
||||
initIO(12, 11, 10, 13, 15, 14, 8000000);
|
||||
return BBEP_SUCCESS;
|
||||
}
|
||||
break;
|
||||
case EPD_BADGER2040: // DC:20 CS:17 RST:21 BUSY: 26 PWR: 10
|
||||
if (setPanelType(EP29_128x296) == BBEP_SUCCESS) {
|
||||
initIO(20, 21, 26, 17, -1, -1, 12000000);
|
||||
setRotation(270);
|
||||
pinMode(10, OUTPUT);
|
||||
digitalWrite(10, HIGH); // keep power turned on
|
||||
return BBEP_SUCCESS;
|
||||
}
|
||||
break;
|
||||
case EPD_TRMNL_OG: // DC:5 CS:6 RST:10 BUSY:4 MOSI:8 SCK:7
|
||||
if (setPanelType(EP75_800x480) == BBEP_SUCCESS) {
|
||||
initIO(5, 10, 4, 6, 8, 7, 10000000);
|
||||
return BBEP_SUCCESS;
|
||||
}
|
||||
break;
|
||||
case EPD_CROWPANEL29: // DC:46 CS:45 RST:47 BUSY:48 MOSI:11 SCK:12
|
||||
pinMode(7, OUTPUT);
|
||||
digitalWrite(7, HIGH); // screen power on
|
||||
if (setPanelType(EP29Z_128x296) == BBEP_SUCCESS) {
|
||||
initIO(46, 47, 48, 45, 11, 12, 12000000);
|
||||
setRotation(270);
|
||||
return BBEP_SUCCESS;
|
||||
}
|
||||
break;
|
||||
case EPD_CROWPANEL213:
|
||||
pinMode(7, OUTPUT);
|
||||
digitalWrite(7, HIGH); // screen power on
|
||||
if (setPanelType(EP213Z_122x250) == BBEP_SUCCESS) {
|
||||
initIO(13, 10, 9, 14, 11, 12, 12000000);
|
||||
setRotation(270);
|
||||
return BBEP_SUCCESS;
|
||||
}
|
||||
break;
|
||||
} // switch on product type
|
||||
return rc;
|
||||
} /* begin() */
|
||||
|
||||
int BBEPAPER::setPanelType(int iPanel)
|
||||
{
|
||||
return bbepSetPanelType(&_bbep, iPanel);
|
||||
@@ -91,11 +139,11 @@ void BBEPAPER::initIO(int iDC, int iReset, int iBusy, int iCS, int iSPIChannel,
|
||||
bbepInitIO(&_bbep, u32Speed);
|
||||
} /* initIO() */
|
||||
#endif
|
||||
int BBEPAPER::writePlane(int iPlane)
|
||||
int BBEPAPER::writePlane(int iPlane, bool bInvert)
|
||||
{
|
||||
long l = millis();
|
||||
int rc;
|
||||
rc = bbepWritePlane(&_bbep, iPlane);
|
||||
rc = bbepWritePlane(&_bbep, iPlane, (int)bInvert);
|
||||
_bbep.iDataTime = (int)(millis() - l);
|
||||
return rc;
|
||||
} /* writePlane() */
|
||||
@@ -144,11 +192,15 @@ void BBEPAPER::backupPlane(void)
|
||||
memcpy(&_bbep.ucScreen[iSize], _bbep.ucScreen, iSize);
|
||||
}
|
||||
}
|
||||
int BBEPAPER::allocBuffer(void)
|
||||
int BBEPAPER::allocBuffer(bool bSecondPlane)
|
||||
{
|
||||
return bbepAllocBuffer(&_bbep);
|
||||
return bbepAllocBuffer(&_bbep, (int)bSecondPlane);
|
||||
} /* allocBuffer() */
|
||||
|
||||
uint8_t * BBEPAPER::getCache(void)
|
||||
{
|
||||
return u8Cache;
|
||||
}
|
||||
void * BBEPAPER::getBuffer(void)
|
||||
{
|
||||
return (void *)_bbep.ucScreen;
|
||||
@@ -211,10 +263,6 @@ bool BBEPAPER::hasPartialRefresh()
|
||||
|
||||
void BBEPAPER::setTextColor(int iFG, int iBG)
|
||||
{
|
||||
if ((_bbep.iFlags & (BBEP_3COLOR | BBEP_4COLOR | BBEP_7COLOR)) == 0) {
|
||||
if (iFG == BBEP_RED || iFG == BBEP_YELLOW) iFG = BBEP_BLACK; // can't set red color
|
||||
if (iBG == BBEP_RED || iFG == BBEP_YELLOW) iBG = BBEP_BLACK;
|
||||
}
|
||||
_bbep.iFG = iFG;
|
||||
_bbep.iBG = (iBG == -1) ? iFG : iBG;
|
||||
} /* setTextColor() */
|
||||
@@ -419,22 +467,49 @@ static uint8_t u8Unicode0, u8Unicode1;
|
||||
bbepWriteString(&_bbep, -1, -1, szTemp, _bbep.iFont, _bbep.iFG, _bbep.iBG);
|
||||
}
|
||||
} else { // Custom font
|
||||
BB_FONT *pBBF = (BB_FONT *)_bbep.pFont;
|
||||
BB_FONT *pBBF;
|
||||
BB_FONT_SMALL *pBBFS;
|
||||
BB_GLYPH *pGlyph;
|
||||
BB_GLYPH_SMALL *pSmallGlyph;
|
||||
int first, last;
|
||||
if (pgm_read_word(_bbep.pFont) == BB_FONT_MARKER) {
|
||||
pBBF = (BB_FONT *)_bbep.pFont; pBBFS = NULL;
|
||||
first = pgm_read_byte(&pBBF->first);
|
||||
last = pgm_read_byte(&pBBF->last);
|
||||
} else { // small font
|
||||
pBBFS = (BB_FONT_SMALL *)_bbep.pFont; pBBF = NULL;
|
||||
first = pgm_read_byte(&pBBFS->first);
|
||||
last = pgm_read_byte(&pBBFS->last);
|
||||
}
|
||||
if (c == '\n') {
|
||||
_bbep.iCursorX = 0;
|
||||
_bbep.iCursorY += pBBF->height;
|
||||
if (pBBF) {
|
||||
_bbep.iCursorY += pBBF->height;
|
||||
} else {
|
||||
_bbep.iCursorY += pBBFS->height;
|
||||
}
|
||||
} else if (c != '\r') {
|
||||
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?
|
||||
w += pBBG->xOffset;
|
||||
if (c >= first && c <= last) {
|
||||
if (pBBF) {
|
||||
pGlyph = &pBBF->glyphs[c - first];
|
||||
w = pgm_read_word(&pGlyph->width);
|
||||
h = pgm_read_word(&pGlyph->height);
|
||||
} else { // small font
|
||||
pSmallGlyph = &pBBFS->glyphs[c - first];
|
||||
w = pgm_read_word(&pSmallGlyph->width);
|
||||
h = pgm_read_word(&pSmallGlyph->height);
|
||||
}
|
||||
if (w > 0 && h > 0) { // Is there an associated bitmap?
|
||||
if (pBBF) {
|
||||
w += (int16_t)pgm_read_word(&pGlyph->xOffset);
|
||||
} else {
|
||||
w += (int8_t)pgm_read_byte(&pSmallGlyph->xOffset);
|
||||
}
|
||||
if (_bbep.wrap && (_bbep.iCursorX + w) > _bbep.width) {
|
||||
_bbep.iCursorX = 0;
|
||||
_bbep.iCursorY += h;
|
||||
}
|
||||
bbepWriteStringCustom(&_bbep, (BB_FONT *)_bbep.pFont, -1, -1, szTemp, _bbep.iFG, _bbep.iPlane);
|
||||
bbepWriteStringCustom(&_bbep, _bbep.pFont, -1, -1, szTemp, _bbep.iFG, _bbep.iPlane);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -455,21 +530,14 @@ int16_t BBEPAPER::getCursorY(void)
|
||||
{
|
||||
return _bbep.iCursorY;
|
||||
}
|
||||
void BBEPAPER::getTextBounds(const char *string, int16_t x, int16_t y, int16_t *x1, int16_t *y1, uint16_t *w, uint16_t *h)
|
||||
void BBEPAPER::getStringBox(const char *string, BB_RECT *pRect)
|
||||
{
|
||||
if (_bbep.pFont) {
|
||||
int width, top, bottom;
|
||||
bbepGetStringBox(&_bbep, (BB_FONT *)_bbep.pFont, string, &width, &top, &bottom);
|
||||
*x1 = x;
|
||||
*w = width;
|
||||
*y1 = y + top;
|
||||
*h = (bottom - top + 1);
|
||||
}
|
||||
bbepGetStringBox(&_bbep, (char *)string, pRect);
|
||||
}
|
||||
#ifdef ARDUINO
|
||||
void BBEPAPER::getTextBounds(const String &str, int16_t x, int16_t y, int16_t *x1, int16_t *y1, uint16_t *w, uint16_t *h)
|
||||
void BBEPAPER::getStringBox(const String &str, BB_RECT *pRect)
|
||||
{
|
||||
getTextBounds(str.c_str(), x, y, x1, y1, w, h);
|
||||
bbepGetStringBox(&_bbep, str.c_str(), pRect);
|
||||
}
|
||||
#endif
|
||||
int BBEPAPER::dataTime(void)
|
||||
|
||||
+42
-5
@@ -45,6 +45,15 @@ enum {
|
||||
BBEP_ERROR_COUNT
|
||||
};
|
||||
|
||||
#ifndef __ONEBITDISPLAY__
|
||||
typedef struct {
|
||||
int x;
|
||||
int y;
|
||||
int w;
|
||||
int h;
|
||||
} BB_RECT;
|
||||
#endif
|
||||
|
||||
#define LIGHT_SLEEP 0
|
||||
#define DEEP_SLEEP 1
|
||||
|
||||
@@ -74,7 +83,9 @@ enum {
|
||||
PLANE_0=0,
|
||||
PLANE_1,
|
||||
PLANE_BOTH,
|
||||
PLANE_DUPLICATE // duplicate 0 to both 0 and 1
|
||||
PLANE_DUPLICATE, // duplicate 0 to both 0 and 1
|
||||
PLANE_0_TO_1, // send plane 0 to plane 1 memory
|
||||
PLANE_FALSE_DIFF, // use 'partial' mode to force all pixels to update
|
||||
};
|
||||
#ifndef __ONEBITDISPLAY__
|
||||
// 5 possible font sizes: 8x8, 16x32, 6x8, 12x16 (stretched from 6x8 with smoothing), 16x16 (stretched from 8x8)
|
||||
@@ -103,6 +114,17 @@ typedef struct epd_panel {
|
||||
const uint8_t *pColorLookup; // color translation table
|
||||
} EPD_PANEL;
|
||||
|
||||
// Products with built-in SPI EPDs
|
||||
enum {
|
||||
EPD_PRODUCT_UNDEFINED=0,
|
||||
EPD_BADGER2040,
|
||||
EPD_LILYGO_S3_MINI,
|
||||
EPD_TRMNL_OG,
|
||||
EPD_CROWPANEL29,
|
||||
EPD_CROWPANEL213,
|
||||
EPD_PRODUCT_COUNT
|
||||
};
|
||||
|
||||
// Display types
|
||||
enum {
|
||||
EP_PANEL_UNDEFINED=0,
|
||||
@@ -124,7 +146,10 @@ enum {
|
||||
EP37_240x416, // GDEY037T03
|
||||
EP213_104x212, // InkyPHAT 2.13 black and white
|
||||
EP75_800x480, // GDEY075T7
|
||||
EP75_800x480_4GRAY, // GDEW075T7 in 4 grayscale mode
|
||||
EP75_800x480_4GRAY_OLD, // GDEY075T7 in 4 grayscale mode
|
||||
EP29_128x296, // Pimoroni Badger2040
|
||||
EP29_128x296_4GRAY, // Pimoroni Badger2040
|
||||
EP213R_122x250, // Inky phat 2.13 B/W/R
|
||||
EP154_200x200, // waveshare
|
||||
EP154B_200x200, // DEPG01540BN
|
||||
@@ -140,10 +165,14 @@ enum {
|
||||
EP583R_600x448, // 4-bits per pixel needs different support
|
||||
EP75R_800x480, // Waveshare 800x480 3-color
|
||||
EP426_800x480, // Waveshare 4.26" B/W 800x480
|
||||
EP426_800x480_4GRAY, // Waveshare 4.26" 800x480 2-bit grayscale mode
|
||||
EP29R2_128x296, // Adafruit 2.9" 128x296 Tricolor FeatherWing
|
||||
EP41_640x400, // EInk ED040TC1 SPI UC81xx
|
||||
EP81_SPECTRA_1024x576, // Spectra 8.1" 1024x576 6-colors
|
||||
EP7_960x640, // ED070EC1
|
||||
EP213R2_122x250, // UC8151 3-color
|
||||
EP29Z_128x296, // SSD1680 (CrowPanel 2.9")
|
||||
EP213Z_122x250, // SSD1680 (CrowPanel 2.13")
|
||||
EP_PANEL_COUNT
|
||||
};
|
||||
#ifdef FUTURE
|
||||
@@ -183,6 +212,7 @@ enum {
|
||||
#define BBEP_PARTIAL2 0x0080
|
||||
#define BBEP_4BPP_DATA 0x0100
|
||||
#define BBEP_SPLIT_BUFFER 0x0200
|
||||
#define BBEP_HAS_SECOND_PLANE 0x0400
|
||||
|
||||
#define BBEP_BLACK 0
|
||||
#define BBEP_WHITE 1
|
||||
@@ -410,30 +440,37 @@ class BBEPAPER
|
||||
#endif // __LINUX__
|
||||
{
|
||||
public:
|
||||
BBEPAPER(void) { memset(&_bbep, 0, sizeof(_bbep)); }
|
||||
BBEPAPER(int iPanel);
|
||||
int createVirtual(int iWidth, int iHeight, int iFlags);
|
||||
void setAddrWindow(int x, int y, int w, int h);
|
||||
int setPanelType(int iPanel);
|
||||
int begin(int iProduct);
|
||||
void setCS2(uint8_t cs);
|
||||
bool hasFastRefresh();
|
||||
bool hasPartialRefresh();
|
||||
#ifndef __LINUX__
|
||||
#ifdef ARDUINO
|
||||
#ifdef SCK
|
||||
void initIO(int iDC, int iReset, int iBusy, int iCS = SS, int iMOSI = MOSI, int iSCLK = SCK, uint32_t u32Speed = 8000000);
|
||||
#else // no SCK/MOSI default pins
|
||||
void initIO(int iDC, int iReset, int iBusy, int iCS, int iMOSI, int iSCLK, uint32_t u32Speed = 8000000);
|
||||
#endif
|
||||
#else // esp-idf?
|
||||
void initIO(int iDC, int iReset, int iBusy, int iCS, int iMOSI, int iSCLK, uint32_t u32Speed);
|
||||
#endif // ARDUINO
|
||||
#else // __LINUX__
|
||||
void initIO(int iDC, int iReset, int iBusy, int iCS, int iSPIChannel, uint32_t u32Speed = 8000000);
|
||||
#endif
|
||||
int writePlane(int iPlane = PLANE_BOTH);
|
||||
int writePlane(int iPlane = PLANE_BOTH, bool bInvert = false);
|
||||
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);
|
||||
int allocBuffer(bool bSecondPlane = true);
|
||||
void * getBuffer(void);
|
||||
uint8_t * getCache(void);
|
||||
void freeBuffer(void);
|
||||
uint32_t capabilities();
|
||||
void setRotation(int iAngle);
|
||||
@@ -460,9 +497,9 @@ class BBEPAPER
|
||||
int16_t getCursorX(void);
|
||||
int16_t getCursorY(void);
|
||||
int testPanelType(void);
|
||||
void getTextBounds(const char *string, int16_t x, int16_t y, int16_t *x1, int16_t *y1, uint16_t *w, uint16_t *h);
|
||||
void getStringBox(const char *string, BB_RECT *pRect);
|
||||
#ifdef ARDUINO
|
||||
void getTextBounds(const String &str, int16_t x, int16_t y, int16_t *x1, int16_t *y1, uint16_t *w, uint16_t *h);
|
||||
void getStringBox(const String &str, BB_RECT *pRect);
|
||||
#endif
|
||||
int dataTime();
|
||||
int opTime();
|
||||
|
||||
+11
-6
@@ -5,13 +5,18 @@
|
||||
// Written by Larry Bank
|
||||
// Copyright (c) 2024 BitBank Software, Inc.
|
||||
//
|
||||
// Use of this software is governed by the Business Source License
|
||||
// included in the file ./LICENSE.
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//===========================================================================
|
||||
//
|
||||
// As of the Change Date specified in that file, in accordance with
|
||||
// the Business Source License, use of this software will be governed
|
||||
// by the Apache License, Version 2.0, included in the file
|
||||
// ./APL.txt.
|
||||
|
||||
#include "Group5.h"
|
||||
|
||||
/*
|
||||
|
||||
+21
-14
@@ -5,13 +5,18 @@
|
||||
// Written by Larry Bank
|
||||
// Copyright (c) 2024 BitBank Software, Inc.
|
||||
//
|
||||
// Use of this software is governed by the Business Source License
|
||||
// included in the file ./LICENSE.
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//===========================================================================
|
||||
//
|
||||
// As of the Change Date specified in that file, in accordance with
|
||||
// the Business Source License, use of this software will be governed
|
||||
// by the Apache License, Version 2.0, included in the file
|
||||
// ./APL.txt.
|
||||
|
||||
#include "Group5.h"
|
||||
|
||||
/* Number of consecutive 1 bits in a byte from MSB to LSB */
|
||||
@@ -45,7 +50,7 @@ static const uint8_t vtable[14] =
|
||||
2,7}; /* V(3) = 0000010 */
|
||||
|
||||
|
||||
static void G5ENCInsertCode(BUFFERED_BITS *bb, BIGUINT ulCode, int iLen)
|
||||
static void G5ENCInsertCode(G5_BUFFERED_BITS *bb, BIGUINT ulCode, int iLen)
|
||||
{
|
||||
if ((bb->ulBitOff + iLen) > REGISTER_WIDTH) { // need to write data
|
||||
bb->ulBits |= (ulCode >> (bb->ulBitOff + iLen - REGISTER_WIDTH)); // partial bits on first word
|
||||
@@ -61,7 +66,7 @@ static void G5ENCInsertCode(BUFFERED_BITS *bb, BIGUINT ulCode, int iLen)
|
||||
//
|
||||
// Flush any buffered bits to the output
|
||||
//
|
||||
static void G5ENCFlushBits(BUFFERED_BITS *bb)
|
||||
static void G5ENCFlushBits(G5_BUFFERED_BITS *bb)
|
||||
{
|
||||
while (bb->ulBitOff >= 8)
|
||||
{
|
||||
@@ -69,9 +74,11 @@ static void G5ENCFlushBits(BUFFERED_BITS *bb)
|
||||
bb->ulBits <<= 8;
|
||||
bb->ulBitOff -= 8;
|
||||
}
|
||||
*bb->pBuf++ = (unsigned char) (bb->ulBits >> (REGISTER_WIDTH - 8));
|
||||
bb->ulBitOff = 0;
|
||||
bb->ulBits = 0;
|
||||
if (bb->ulBitOff) { // partial byte?
|
||||
*bb->pBuf++ = (unsigned char) (bb->ulBits >> (REGISTER_WIDTH - 8));
|
||||
}
|
||||
bb->ulBitOff = 0;
|
||||
bb->ulBits = 0;
|
||||
} /* G5ENCFlushBits() */
|
||||
//
|
||||
// Initialize the compressor
|
||||
@@ -198,13 +205,13 @@ int xsize, iErr, iHighWater;
|
||||
int iCur, iRef, iLen;
|
||||
int iHLen; // number of bits for long horizontal codes
|
||||
int16_t *CurFlips, *RefFlips;
|
||||
BUFFERED_BITS bb;
|
||||
G5_BUFFERED_BITS bb;
|
||||
|
||||
if (pImage == NULL || pPixels == NULL)
|
||||
return G5_INVALID_PARAMETER;
|
||||
iHighWater = pImage->iOutSize - 32;
|
||||
iHLen = 32 - __builtin_clz(pImage->iWidth);
|
||||
memcpy(&bb, &pImage->bb, sizeof(BUFFERED_BITS)); // keep local copy
|
||||
memcpy(&bb, &pImage->bb, sizeof(G5_BUFFERED_BITS)); // keep local copy
|
||||
CurFlips = pImage->pCur;
|
||||
RefFlips = pImage->pRef;
|
||||
xsize = pImage->iWidth; /* For performance reasons */
|
||||
@@ -283,7 +290,7 @@ BUFFERED_BITS bb;
|
||||
if (pImage->y == pImage->iHeight-1) { // last line of image
|
||||
G5ENCFlushBits(&bb); // output the final buffered bits
|
||||
// wrap up final output
|
||||
pImage->iDataSize = (int)(bb.pBuf-pImage->pOutBuf);
|
||||
pImage->iDataSize = 1 + (int)(bb.pBuf-pImage->pOutBuf);
|
||||
iErr = G5_ENCODE_COMPLETE;
|
||||
}
|
||||
pImage->pCur = RefFlips; // swap current and reference lines
|
||||
|
||||
Reference in New Issue
Block a user