First working version

This commit is contained in:
Laurence Bank
2024-09-13 22:32:07 +01:00
parent 873585bd94
commit 9f6cfa612b
5 changed files with 629 additions and 5378 deletions
+111 -3247
View File
File diff suppressed because it is too large Load Diff
+324 -1583
View File
File diff suppressed because it is too large Load Diff
+62 -9
View File
@@ -22,45 +22,98 @@
void bbeiInitIO(BBEIDISP *pBBEI, uint32_t u32Speed)
{
iDCPin, iMOSIPin, iCLKPin, iCSPin, iRSTPin, iBUSYPin
pinMode(pBBEI->iDCPin, OUTPUT);
if (pBBEI->iRSTPin != 0xff) {
pinMode(pBBEI->iRSTPin, OUTPUT);
digitalWrite(pBBEI->iRSTPin, LOW);
delay(100);
digitalWrite(pBBEI->iRSTPin, HIGH);
delay(1000);
}
pinMode(pBBEI->iRSTPin, OUTPUT);
digitalWrite(pBBEI->iRSTPin, LOW);
delay(100);
digitalWrite(pBBEI->iRSTPin, HIGH);
delay(100);
if (pBBEI->iBUSYPin != 0xff) {
pinMode(pBBEI->iBUSYPin, INPUT);
}
pBBEI->iSpeed = u32Speed;
#ifdef ARDUINO_ARCH_ESP32
SPI.begin(pBBEI->iCLKPin, -1, pBBEI->iMOSIPin, pBBEI->iCSPin);
#else
pinMode(pBBEI->iCSPin, OUTPUT);
digitalWrite(pBBEI->iCSPin, HIGH); // we have to manually control the CS pin
SPI.begin(); // other architectures have fixed SPI pins
#endif
SPI.beginTransaction(SPISettings(u32Speed, MSBFIRST, SPI_MODE0));
SPI.endTransaction(); // N.B. - if you call beginTransaction() again without a matching endTransaction(), it will hang on ESP32
} /* bbeiInitIO() */
void bbeiWakeUp(BBEIDISP *pBBEI)
{
digitalWrite(pBBEI->iRSTPin, LOW);
delay(10);
digitalWrite(pBBEI->iRSTPin, HIGH);
delay(10);
} /* bbeiWakeUp() */
void bbeiWaitBusy(BBEIDISP *pBBEI)
{
uint8_t busy_idle = (pBBEI->chip_type == BBEI_CHIP_UC81xx) ? HIGH : LOW;
while (1) {
if (digitalRead(pBBEI->iBUSYPin) == busy_idle) break;
}
} /* bbeiWaitBusy() */
void bbeiCMD2(BBEIDISP *pBBEI, uint8_t cmd1, uint8_t cmd2)
{
digitalWrite(pBBEI->iDCPin, LOW);
#ifndef ARDUINO_ARCH_ESP32
digitalWrite(pBBEI->iCSPin, LOW);
#endif
SPI.transfer(cmd1);
SPI.transfer(cmd2);
digitalWrite(pBBEI->iDCPin, HIGH); // leave data mode as the default
#ifndef ARDUINO_ARCH_ESP32
digitalWrite(pBBEI->iCSPin, HIGH);
#endif
} /* bbeiCMD2() */
void bbeiWriteCmd(BBEIDISP *pBBEI, uint8_t cmd)
{
digitalWrite(pBBEI->iDCPin, LOW);
#ifndef ARDUINO_ARCH_ESP32
digitalWrite(pBBEI->iCSPin, LOW);
#endif
SPI.transfer(cmd);
digitalWrite(pBBEI->iDCPin, HIGH); // leave data mode as the default
#ifndef ARDUINO_ARCH_ESP32
digitalWrite(pBBEI->iCSPin, HIGH);
#endif
} /* bbeiWriteCmd() */
void bbeiSleep(BBEIDISP *pBBEI, int bDeep)
{
if (pBBEI->chip_type == BBEI_CHIP_UC81xx) {
bbeiCMD2(pBBEI, UC8151_CDI, 0x17); // border floating
bbeiWriteCmd(pBBEI, UC8151_POFF); // power off
bbeiWaitBusy(pBBEI);
if (bDeep) {
bbeiCMD2(pBBEI, UC8151_DSLP, 0xa5); // deep sleep
}
} else {
bbeiCMD2(pBBEI, SSD1608_DEEP_SLEEP, (bDeep) ? 0x02 : 0x01); // deep sleep mode 1 keeps RAM, mode 2 loses RAM
return;
}
} /* bbeiSleep() */
void bbeiWriteData(BBEIDISP *pBBEI, uint8_t *pData, int iLen)
{
#ifdef ARDUINO_ARCH_ESP32
SPI.transferBytes(pData, NULL, iLen);
#else
digitalWrite(pBBEI->iCSPin, LOW);
SPI.transfer(pData, iLen);
digitalWrite(pBBEI->iCSPin, HIGH);
#endif
} /* bbeiWriteData() */
#else // LINUX
#endif // ARDUINO
#endif // ARDUINO / LINUX
#endif // __BB_EI_IO__
+77 -221
View File
@@ -32,18 +32,20 @@ void delay(int);
#else // Arduino
#endif // _LINUX_
#include "bb_eink.h"
#include "bb_ei_io.inl" // I/O (non-portable) code is in here
#include "bb_ei.inl" // All of the display interface code is in here
#include "bb_ei_gfx.inl" // drawing code
#ifdef __cplusplus
//
// C++ Class implementation
//
uint32_t BBEINK::getRefreshTime(void)
{
return _bbei.iTimeout;
}
//uint32_t BBEINK::getRefreshTime(void)
//{
// return _bbei.iTimeout;
//}
void BBEINK::setPosition(int x, int y, int w, int h)
{
@@ -53,38 +55,41 @@ int BBEINK::setPanelType(int iPanel)
{
return bbeiSetPanelType(&_bbei, iPanel);
}
void BBEINK::initIO(int iCS, int iMOSI, int iSCLK, int iDC, int iReset, int iBusy, uint32_t u32Speed)
void BBEINK::initIO(int iDC, int iReset, int iBusy, int iCS, int iMOSI, int iSCLK, uint32_t u32Speed)
{
_bbei.iCSPin = iCS;
_bbei.iMOSIPin = iMOSI;
_bbei.iCLKPin = iSCLK;
_bbei.iDCPin = iDC;
_bbei.iRSTPin = iReset;
_bbei.iBusyPin = iBusy;
_bbei.iBUSYPin = iBusy;
bbeiInitIO(&_bbei, u32Speed);
} /* initIO() */
int BBEINK::getFlags(void)
int BBEINK::writePlane(int iPlane)
{
return _bbei.iFlags;
}
return bbeiWritePlane(&_bbei, iPlane);
} /* writePlane() */
void BBEINK::setFlags(int iFlags)
int BBEINK::refresh(int iMode, bool bWait)
{
_bbei.iFlags = iFlags;
_bbei.invert = iFlags & OBD_INVERTED;
_bbei.flip = iFlags & OBD_FLIP180;
}
int rc;
rc = bbeiRefresh(&_bbei, iMode);
if (rc == BBEI_SUCCESS && bWait) {
bbeiWaitBusy(&_bbei);
}
return rc;
} /* refresh() */
void BBEINK::setContrast(uint8_t ucContrast)
{
obdSetContrast(&_bbei, ucContrast);
}
//int BBEINK::getFlags(void)
//{
// return _bbei.iFlags;
//}
int BBEINK::I2Cbegin(int iType, int iAddr, int32_t iSpeed)
{
return obdI2CInit(&_bbei, iType, iAddr, _bbei.flip, _bbei.invert, !_bbei.bBitBang, _bbei.iSDAPin, _bbei.iSCLPin, _bbei.iRSTPin, iSpeed);
} /* I2Cbegin() */
//void BBEINK::setFlags(int iFlags)
//{
// _bbei.iFlags = iFlags;
//}
void BBEINK::setBuffer(uint8_t *pBuffer)
{
@@ -93,23 +98,16 @@ void BBEINK::setBuffer(uint8_t *pBuffer)
int BBEINK::allocBuffer(void)
{
int iSize = _bbei.width * ((_bbei.height+7)>>3);
if (_bbei.iFlags & (OBD_3COLOR | OBD_4COLOR) || _bbei.chip_type == OBD_CHIP_UC8151)
iSize *= 2; // 2 bit planes
int iSize = ((_bbei.width+7)>>3) * _bbei.height;
// if (_bbei.iFlags & (BBEI_3COLOR | BBEI_4COLOR) || _bbei.chip_type == BBEI_CHIP_UC81xx)
// iSize *= 2; // 2 bit planes
_bbei.ucScreen = (uint8_t *)malloc(iSize);
if (_bbei.ucScreen != NULL) {
_bbei.render = false; // draw into RAM only
memset(_bbei.ucScreen, 0xff, iSize);
return OBD_SUCCESS;
return BBEI_SUCCESS;
}
return OBD_ERROR_NO_MEMORY; // failed
return BBEI_ERROR_NO_MEMORY; // failed
} /* allocBuffer() */
uint32_t BBEINK::capabilities(void)
{
return _bbei.iFlags;
}
void * BBEINK::getBuffer(void)
{
return (void *)_bbei.ucScreen;
@@ -123,29 +121,34 @@ void BBEINK::freeBuffer(void)
}
} /* freeBuffer() */
void BBEINK::setScroll(bool bScroll)
uint32_t BBEINK::capabilities(void)
{
_bbei.bScroll = bScroll;
return _bbei.iFlags;
}
void BBEINK::setRotation(int iRotation)
{
obdSetRotation(&_bbei, iRotation);
// obdSetRotation(&_bbei, iRotation);
} /* setRotation() */
void BBEINK::fillScreen(int iColor)
int BBEINK::getRotation(void)
{
obdFill(&_bbei, iColor, (_bbei.ucScreen == NULL));
return _bbei.iOrientation;
}
void BBEINK::fillScreen(int iColor, int iPlane)
{
bbeiFill(&_bbei, iColor, iPlane);
} /* fillScreen() */
void BBEINK::drawRect(int16_t x, int16_t y, int16_t w, int16_t h, uint16_t color)
{
obdRectangle(&_bbei, x, y, x+w-1, y+h-1, color, 0);
bbeiRectangle(&_bbei, x, y, x+w-1, y+h-1, color, 0);
} /* drawRect() */
void BBEINK::fillRect(int16_t x, int16_t y, int16_t w, int16_t h, uint16_t color)
{
obdRectangle(&_bbei, x, y, x+w-1, y+h-1, color, 1);
bbeiRectangle(&_bbei, x, y, x+w-1, y+h-1, color, 1);
} /* fillRect() */
void BBEINK::setTextWrap(bool bWrap)
@@ -155,11 +158,11 @@ void BBEINK::setTextWrap(bool bWrap)
void BBEINK::setTextColor(int iFG, int iBG)
{
if (iFG > OBD_RED) iFG = OBD_BLACK;
if (iBG > OBD_RED) iBG = OBD_BLACK;
if ((_bbei.iFlags & (OBD_3COLOR | OBD_4COLOR)) == 0) {
if (iFG == OBD_RED) iFG = OBD_BLACK; // can't set red color
if (iBG == OBD_RED) iBG = OBD_BLACK;
if (iFG > BBEI_RED) iFG = BBEI_BLACK;
if (iBG > BBEI_RED) iBG = BBEI_BLACK;
if ((_bbei.iFlags & (BBEI_3COLOR | BBEI_4COLOR)) == 0) {
if (iFG == BBEI_RED) iFG = BBEI_BLACK; // can't set red color
if (iBG == BBEI_RED) iBG = BBEI_BLACK;
}
_bbei.iFG = iFG;
_bbei.iBG = (iBG == -1) ? iFG : iBG;
@@ -175,77 +178,30 @@ void BBEINK::setCursor(int x, int y)
int BBEINK::loadBMP(const uint8_t *pBMP, int x, int y, int iFG, int iBG)
{
return obdLoadBMP(&_bbei, pBMP, x, y, iFG, iBG);
return bbeiLoadBMP(&_bbei, pBMP, x, y, iFG, iBG);
} /* loadBMP() */
int BBEINK::drawEPDGFX(int x, int y, int cx, int cy, uint8_t *pPlane0, uint8_t *pPlane1)
{
return obdDrawEPDGFX(&_bbei, x, y, cx, cy, pPlane0, pPlane1);
} /* drawEPDGFX() */
int BBEINK::loadBMP3(const uint8_t *pBMP, int x, int y)
{
return obdLoadBMP3(&_bbei, pBMP, x, y);
return bbeiLoadBMP3(&_bbei, pBMP, x, y);
} /* loadBMP3() */
void BBEINK::setFont(int iFont)
{
_bbei.iFont = iFont;
_bbei.pFreeFont = NULL;
// _bbei.pFreeFont = NULL;
} /* setFont() */
void BBEINK::setTextSize(uint8_t s)
{
_bbei.u32FontScaleX = _bbei.u32FontScaleY = 256 * s;
_bbei.iFont = -1;
_bbei.pFreeFont = NULL;
}
void BBEINK::setTextSize(uint8_t sx, uint8_t sy)
{
_bbei.u32FontScaleX = 256 * sx;
_bbei.u32FontScaleY = 256 * sy;
_bbei.iFont = -1;
_bbei.pFreeFont = NULL;
}
int BBEINK::scrollBuffer(int iStartCol, int iEndCol, int iStartRow, int iEndRow, int bUp)
{
return obdScrollBuffer(&_bbei, iStartCol, iEndCol, iStartRow, iEndRow, bUp);
} /* scrollBuffer() */
void BBEINK::setFreeFont(const GFXfont *pFont)
{
_bbei.pFreeFont = (GFXfont *)pFont;
} /* setFreeFont() */
//void BBEINK::setFreeFont(const GFXfont *pFont)
//{
// _bbei.pFreeFont = (GFXfont *)pFont;
//} /* setFreeFont() */
void BBEINK::drawLine(int x1, int y1, int x2, int y2, int iColor)
{
obdDrawLine(&_bbei, x1, y1, x2, y2, iColor, 1);
bbeiDrawLine(&_bbei, x1, y1, x2, y2, iColor);
} /* drawLine() */
inline GFXglyph *pgm_read_glyph_ptr(const GFXfont *gfxFont, uint8_t c) {
#ifdef __AVR__
return &(((GFXglyph *)pgm_read_ptr(&gfxFont->glyph))[c]);
#else
// expression in __AVR__ section may generate "dereferencing type-punned
// pointer will break strict-aliasing rules" warning In fact, on other
// platforms (such as STM32) there is no need to do this pointer magic as
// program memory may be read in a usual way So expression may be simplified
return gfxFont->glyph + c;
#endif //__AVR__
}
void obdScroll1Line(OBDISP *pOBD, int iAmount)
{
int y, iLines;
if (pOBD == NULL || pOBD->ucScreen == NULL)
return;
iLines = (pOBD->height+7)>>3;
for (y=0; y<iLines-iAmount; y+=iAmount) {
memcpy(&pOBD->ucScreen[y*pOBD->width], &pOBD->ucScreen[(y+iAmount)*pOBD->width], pOBD->width*iAmount);
}
memset(&pOBD->ucScreen[(iLines-iAmount) * pOBD->width], (char)pOBD->iBG, pOBD->width*iAmount);
} /* obdScroll1Line() */
#ifdef _LINUX_
void BBEINK::print(const string &str)
{
@@ -349,6 +305,7 @@ char ucTemp[4];
//
#ifndef __AVR__
size_t BBEINK::write(uint8_t c) {
#ifdef FUTURE
char szTemp[2]; // used to draw 1 character at a time to the C methods
int w, h;
@@ -414,18 +371,19 @@ int w, h;
_bbei.iCursorX = 0;
_bbei.iCursorY += h;
}
obdWriteStringCustom(&_bbei, _bbei.pFreeFont, -1, -1, szTemp, _bbei.iFG);
bbeiWriteStringCustom(&_bbei, _bbei.pFreeFont, -1, -1, szTemp, _bbei.iFG);
}
}
}
}
#endif // FUTURE
return 1;
} /* write() */
#endif // !__AVR__
void BBEINK::drawPixel(int16_t x, int16_t y, uint16_t color)
void BBEINK::drawPixel(int16_t x, int16_t y, uint8_t color)
{
obdSetPixel(&_bbei, x, y, color, _bbei.render);
bbeiSetPixel(&_bbei, x, y, color);
}
int16_t BBEINK::getCursorX(void)
{
@@ -435,33 +393,16 @@ int16_t BBEINK::getCursorY(void)
{
return _bbei.iCursorY;
}
uint8_t BBEINK::getRotation(void)
{
return _bbei.iOrientation;
}
void BBEINK::wake(void)
{
if (_bbei.type >= EPD42_400x300) {
EPDWakeUp(&_bbei, 1);
}
}
void BBEINK::sleep(int bDeep)
{
if (_bbei.type >= EPD42_400x300) {
EPDSleep(&_bbei, bDeep);
}
}
void BBEINK::getTextBounds(const char *string, int16_t x, int16_t y, int16_t *x1, int16_t *y1, uint16_t *w, uint16_t *h)
{
if (_bbei.pFreeFont) {
int width, top, bottom;
obdGetStringBox(_bbei.pFreeFont, (char *)string, &width, &top, &bottom);
*x1 = x;
*w = width;
*y1 = y + top;
*h = (bottom - top + 1);
}
// if (_bbei.pFreeFont) {
// int width, top, bottom;
// obdGetStringBox(_bbei.pFreeFont, (char *)string, &width, &top, &bottom);
// *x1 = x;
// *w = width;
// *y1 = y + top;
// *h = (bottom - top + 1);
// }
}
void BBEINK::getTextBounds(const String &str, int16_t x, int16_t y, int16_t *x1, int16_t *y1, uint16_t *w, uint16_t *h)
{
@@ -483,114 +424,29 @@ int16_t BBEINK::height(void)
{
return _bbei.height;
}
void BBEINK::drawSprite(uint8_t *pSprite, int cx, int cy, int iPitch, int x, int y, uint8_t iPriority)
{
obdDrawSprite(&_bbei, pSprite, cx, cy, iPitch, x, y, iPriority);
}
int BBEINK::drawGFX(uint8_t *pSrc, int iSrcCol, int iSrcRow, int iDestCol, int iDestRow, int iWidth, int iHeight, int iSrcPitch)
{
return obdDrawGFX(&_bbei, pSrc, iSrcCol, iSrcRow, iDestCol, iDestRow, iWidth, iHeight, iSrcPitch);
} /* drawGFX() */
void BBEINK::drawTile(const uint8_t *pTile, int x, int y, int iRotation, int bInvert, int bRender)
{
obdDrawTile(&_bbei, pTile, x, y, iRotation, bInvert, bRender);
}
void BBEINK::drawCircle(int32_t x, int32_t y, int32_t r, uint32_t color)
{
obdEllipse(&_bbei, x, y, r, r, color, 0);
bbeiEllipse(&_bbei, x, y, r, r, color, 0);
}
void BBEINK::fillCircle(int32_t x, int32_t y, int32_t r, uint32_t color)
{
obdEllipse(&_bbei, x, y, r, r, color, 1);
bbeiEllipse(&_bbei, x, y, r, r, color, 1);
}
void BBEINK::drawEllipse(int16_t x, int16_t y, int32_t rx, int32_t ry, uint16_t color)
{
obdEllipse(&_bbei, x, y, rx, ry, color, 0);
bbeiEllipse(&_bbei, x, y, rx, ry, color, 0);
}
void BBEINK::fillEllipse(int16_t x, int16_t y, int32_t rx, int32_t ry, uint16_t color)
{
obdEllipse(&_bbei, x, y, rx, ry, color, 1);
}
void BBEINK::setPosition(int x, int y, int w, int h)
{
if (_bbei.type >= EPD42_400x300)
EPDSetPosition(&_bbei, x, y, w, h);
else
obdSetPosition(&_bbei, x, y, 1);
} /* setPosition() */
void BBEINK::writeRaw(uint8_t *pData, int iLen)
{
RawWrite(&_bbei, pData, iLen);
bbeiEllipse(&_bbei, x, y, rx, ry, color, 1);
}
void BBEINK::writeCommand(uint8_t ucCMD)
void BBEINK::sleep(int bDeep)
{
obdWriteCommand(&_bbei, ucCMD);
bbeiSleep(&_bbei, bDeep);
}
void BBEINK::pushPixels(uint8_t *pPixels, int iCount)
{
RawWriteData(&_bbei, pPixels, iCount);
} /* pushPixels() */
void BBEINK::pushImage(int x, int y, int w, int h, uint16_t *pixels)
{
// DEBUG
(void)x; (void)y; (void)w; (void)h; (void)pixels;
}
void BBEINK::displayLines(int iStartLine, int iLineCount)
{
obdWriteLCDLines(&_bbei, iStartLine, iLineCount);
} /* displayLines() */
int BBEINK::display(bool bRefresh, bool bWait, bool bFast)
{
return obdDumpBuffer(&_bbei, NULL, bRefresh, bWait, bFast);
}
void BBEINK::wait(bool bQuick)
{
EPDWaitBusy(&_bbei, bQuick);
}
int BBEINK::displayPartial()
{
if (_bbei.type >= EPD42_400x300 && (_bbei.iFlags & OBD_HAS_PARTIAL_UPDATE)) {
return EPDDumpPartial(&_bbei, NULL, 0, 0, _bbei.width, _bbei.height);
}
return OBD_ERROR_NOT_SUPPORTED;
}
int BBEINK::displayPartial(int x, int y, int w, int h, uint8_t *pBuffer)
{
if (_bbei.type >= EPD42_400x300 && (_bbei.iFlags & OBD_HAS_PARTIAL_UPDATE)) {
return obdDumpPartial(&_bbei, x, y, w, h, pBuffer);
} else {
return OBD_ERROR_NOT_SUPPORTED;
}
}
void BBEINK::drawString(const char *pText, int x, int y)
{
setCursor(x,y);
if (_bbei.pFreeFont != NULL)
obdWriteStringCustom(&_bbei, _bbei.pFreeFont, x, y, (char *)pText, _bbei.iFG);
else
obdWriteString(&_bbei, 0, x, y, (char *)pText, _bbei.iFont, _bbei.iFG, 1);
} /* drawString() */
void BBEINK::drawString(String text, int x, int y)
{
drawString(text.c_str(), x, y);
} /* drawString() */
void BBEINK::backlight(int bOn)
{
obdBacklight(&_bbei, bOn);
}
OBDISP * BBEINK::getOBD()
{
return &_bbei;
}
void BBEINK::setRender(bool bRAMOnly)
{
_bbei.render = !bRAMOnly;
bbeiWaitBusy(&_bbei);
}
#endif // __cplusplus
+55 -318
View File
@@ -16,11 +16,9 @@
#ifndef __BB_EINK__
#define __BB_EINK__
#ifndef MEMORY_ONLY
#include <BitBang_I2C.h>
#endif
#ifdef _LINUX_
#ifdef ARDUINO
#include <Arduino.h>
#else // _LINUX_
// for Print support
#define DEC 10
#define HEX 16
@@ -42,6 +40,9 @@ enum {
BBEI_ERROR_COUNT
};
#define LIGHT_SLEEP 0
#define DEEP_SLEEP 1
// Display refresh modes
enum {
REFRESH_FULL=0,
@@ -56,6 +57,13 @@ enum {
BBEI_CHIP_COUNT
};
// enum for writing local framebuffer to EPD memory plane(s)
enum {
PLANE_0=0,
PLANE_1,
PLANE_BOTH,
PLANE_DUPLICATE // duplicate 0 to both 0 and 1
};
// 5 possible font sizes: 8x8, 16x32, 6x8, 12x16 (stretched from 6x8 with smoothing), 16x16 (stretched from 8x8)
enum {
FONT_6x8 = 0,
@@ -72,9 +80,9 @@ enum {
typedef struct epd_panel {
uint16_t width;
uint16_t height;
uint8_t *pInitFull;
uint8_t *pInitFast;
uint8_t *pInitPart;
const uint8_t *pInitFull;
const uint8_t *pInitFast;
const uint8_t *pInitPart;
uint8_t flags;
uint8_t chip_type;
} EPD_PANEL;
@@ -90,7 +98,8 @@ enum {
EPD295_128x296, // harvested from Solum 2.9" BW ESLs
EPD266_152x296, // GDEY0266T90
EPD102_80x128, // GDEW0102T4
EPD27B_176x264 // GDEY027T91
EPD27B_176x264, // GDEY027T91
EPD_PANEL_COUNT
};
#ifdef FUTURE
EPD42_4GRAY_400x300, // WFT0420CZ15
@@ -154,7 +163,7 @@ enum {
#define BBEI_GRAY3 3
// (UC81xx commands)
enum reg_uc81xx {
enum {
UC8151_PSR = 0x00,
UC8151_PWR = 0x01,
UC8151_POFF = 0x02,
@@ -198,7 +207,7 @@ enum reg_uc81xx {
UC8151_TSSET = 0xe5
};
enum reg_ssd16xx {
enum {
SSD1608_DRIVER_CONTROL = 0x01,
SSD1608_GATE_VOLTAGE = 0x03,
SSD1608_SOURCE_VOLTAGE = 0x04,
@@ -238,10 +247,7 @@ enum reg_ssd16xx {
typedef struct bbeistruct
{
#ifndef MEMORY_ONLY
BBI2C bbi2c;
#endif
uint8_t wrap, flip, invert, type, render, can_flip, chip_type;
uint8_t wrap, type, chip_type;
uint8_t *ucScreen;
int iCursorX, iCursorY;
int width, height, native_width, native_height;
@@ -249,12 +255,11 @@ int iScreenOffset, iOrientation;
int iFG, iBG; //current color
int iFont, iFlags;
int iDataTime, iOpTime; // time in milliseconds for data transmission and operation
uint32_t u32FontScaleX, u32FontScaleY;
uint32_t iSpeed;
uint32_t iTimeout; // for e-ink panels
uint8_t iDCPin, iMOSIPin, iCLKPin, iCSPin, iRSTPin, iBUSYPin;
uint8_t x_offset, y_offset; // memory offsets
uint8_t bBitBang;
uint8_t bBitBang, iPlane;
const uint8_t *pInitFull; // full update init sequence
const uint8_t *pInitFast; // fast update init sequence
const uint8_t *pInitPart; // partial update init sequence
@@ -274,55 +279,59 @@ class BBEINK
#endif // _LINUX_
{
public:
BBEINK() { memset(&_bbei, 0, sizeof(_bbei)); _bbei.iFG = BBEI_BLACK; _bbei.render = 1; _bbei.type = EPD_UNDEFINED;}
void initIO(int iCS, int iMOSI, int iSCLK, int iDC, int iReset=-1, int iBusy=-1, uint32_t u32Speed = 8000000);
int setPanelType(int iPanel);
uint32_t capabilities();
int16_t height(void);
int16_t width(void);
BBEINK() { memset(&_bbei, 0, sizeof(_bbei)); _bbei.iFG = BBEI_BLACK; _bbei.type = EPD_PANEL_UNDEFINED;}
void setPosition(int x, int y, int w, int h);
void sleep(int bDeep);
void wait(bool bQuick = false);
int dataTime();
int opTime();
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);
int refresh(int iMode, bool bWait = true);
void setBuffer(uint8_t *pBuffer);
int allocBuffer(void);
void * getBuffer(void);
void setBuffer(uint8_t *pBuffer);
void freeBuffer(void);
void fillScreen(int iColor);
uint32_t capabilities();
void setRotation(int iAngle);
int getRotation(void);
void fillScreen(int iColor, int iPlane = PLANE_DUPLICATE);
void drawRect(int16_t x, int16_t y, int16_t w, int16_t h, uint16_t color);
void fillRect(int16_t x, int16_t y, int16_t w, int16_t h, uint16_t color);
void setTextWrap(bool bWrap);
void setTextColor(int iFG, int iBG = -1);
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);
void setFont(int iFont);
void drawLine(int x1, int y1, int x2, int y2, int iColor);
void drawPixel(int16_t x, int16_t y, uint8_t color);
int16_t getCursorX(void);
int16_t getCursorY(void);
void setCursor(int x, int y);
void setPlane(int iPlane);
void drawRect(int16_t x, int16_t y, int16_t w, int16_t h, uint16_t color);
void getTextBounds(const char *string, int16_t x, int16_t y, int16_t *x1, int16_t *y1, uint16_t *w, uint16_t *h);
void getTextBounds(const String &str, int16_t x, int16_t y, int16_t *x1, int16_t *y1, uint16_t *w, uint16_t *h);
int dataTime();
int opTime();
int16_t height(void);
int16_t width(void);
void drawCircle(int32_t x, int32_t y, int32_t r, uint32_t color);
void fillCircle(int32_t x, int32_t y, int32_t r, uint32_t color);
void drawEllipse(int16_t x, int16_t y, int32_t rx, int32_t ry, uint16_t color);
void fillEllipse(int16_t x, int16_t y, int32_t rx, int32_t ry, uint16_t color);
int drawGFX(uint8_t *pSrc, int iSrcCol, int iSrcRow, int iDestCol, int iDestRow, int iWidth, int iHeight, int iSrcPitch);
void drawPixel(int16_t x, int16_t y, uint16_t color);
void sleep(int bDeep);
void wait(bool bQuick = false);
#ifdef FUTURE
void setPlane(int iPlane);
void drawSprite(uint8_t *pSprite, int cx, int cy, int iPitch, int x, int y, uint8_t iPriority);
void drawTile(const uint8_t *pTile, int x, int y, int iRotation, int bInvert, int bRender);
void setTextColor(int iFG, int iBG = -1);
int refresh(int iMode);
int drawEPDGFX(int x, int y, int cx, int cy, uint8_t *pPlane0, uint8_t *pPlane1);
int loadBMP(const uint8_t *pBMP, int x, int y, int iFG, int iBG);
int loadBMP3(const uint8_t *pBMP, int x, int y);
void getTextBounds(const char *string, int16_t x, int16_t y, int16_t *x1, int16_t *y1, uint16_t *w, uint16_t *h);
void getTextBounds(const String &str, int16_t x, int16_t y, int16_t *x1, int16_t *y1, uint16_t *w, uint16_t *h);
void setTextWrap(bool bWrap);
void setFont(int iFont);
void setFreeFont(const BB_FONT *pFont);
// int drawGFX(int x, int y, int cx, int cy, uint8_t *pPlane0, uint8_t *pPlane1);
// void setFreeFont(const BB_FONT *pFont);
void pushBytes(uint8_t *pByte, int iCount);
void writeCommand(uint8_t ucCMD);
void writeRaw(uint8_t *pData, int iLen);
void pushImage(int x, int y, int w, int h, uint16_t *pixels);
void drawString(const char *pText, int x, int y);
void drawString(String text, int x, int y);
void drawLine(int x1, int y1, int x2, int y2, int iColor);
#endif // FUTURE
#ifdef _LINUX_
void print(const char *pString);
void println(const char *pString);
@@ -342,11 +351,6 @@ class BBEINK
}; // class BBEINK
#endif // __cplusplus
// Make the Linux library interface C instead of C++
#if defined(_LINUX_) && defined(__cplusplus)
extern "C" {
#endif
#if !defined(BITBANK_LCD_MODES)
#define BITBANK_LCD_MODES
typedef enum
@@ -356,272 +360,5 @@ typedef enum
} DC_MODE;
#endif
void EPDFill(OBDISP *pOBD, uint8_t ucCMD, uint8_t ucPattern);
void EPDSetPosition(OBDISP *pOBD, int x, int y, int cx, int cy);
//
// Create a virtual display of any size
// The memory buffer must be provided at the time of creation
//
void obdCreateVirtualDisplay(OBDISP *pOBD, int width, int height, uint8_t *buffer);
//
// Draw the contents of a memory buffer onto a display
// The sub-window will be clipped if it specifies too large an area
// for the destination display. The source OBDISP structure must have
// a valid back buffer defined
// The top and bottom destination edges will be drawn on byte boundaries (8 rows)
// The source top/bot edges can be on pixel boundaries
//
void obdDumpWindow(OBDISP *pOBDSrc, OBDISP *pOBDDest, int srcx, int srcy, int destx, int desty, int width, int height);
//
// Write one of more lines to a Sharp memory LCD
//
void obdWriteLCDLines(OBDISP *pOBD, int iStart, int iCount);
//
// Initializes the display controller into "page mode" on I2C
// If SDAPin and SCLPin are not -1, then bit bang I2C on those pins
// Otherwise use the Wire library.
// If you don't need to use a separate reset pin, set it to -1
//
int obdI2CInit(OBDISP *pOBD, int iType, int iAddr, int bFlip, int bInvert, int bWire, int iSDAPin, int iSCLPin, int iResetPin, int32_t iSpeed);
//
// Initialize an SPI version of the display
//
void obdSPIInit(OBDISP *pOBD, int iType, int iDC, int iCS, int iReset, int iMOSI, int iCLK, int iLED, int bFlip, int bInvert, int iBitBang, int32_t iSpeed);
//
// Set the drawing direction in 90 degree increments
//
void obdSetRotation(OBDISP *pOBD, int iRotation);
//
// Set the memory configuration to display the pixels at 0 or 180 degrees (flipped)
// pass true (1) to flip 180, false (0) to set to 0
void obdSetFlip(OBDISP *pOBD, int iOnOff);
//
// Provide or revoke a back buffer for your OLED graphics
// This allows you to manage the RAM used by ss_oled on tiny
// embedded platforms like the ATmega series
// Pass NULL to revoke the buffer. Make sure you provide a buffer
// large enough for your display (e.g. 128x64 needs 1K - 1024 bytes)
//
void obdSetBackBuffer(OBDISP *pOBD, uint8_t *pBuffer);
void obdAllocBuffer(OBDISP *pOBD);
//
// Sets the brightness (0=off, 255=brightest)
//
void obdSetContrast(OBDISP *pOBD, unsigned char ucContrast);
//
// Load a 1-bpp Windows bitmap
// Pass the pointer to the beginning of the BMP file
// First pass version assumes a full screen bitmap
//
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)
// e-paper displays
// It does a 'best match' of the colors to
// B/W/R
//
int obdLoadBMP3(OBDISP *pOBD, const uint8_t *pBMP, int dx, int dy);
//
// Power up/down the display
// useful for low power situations
//
void obdPower(OBDISP *pOBD, int bOn);
//
// Set the current cursor position
// The column represents the pixel column (0-127)
// The row represents the text row (0-7)
//
void obdSetCursor(OBDISP *pOBD, int x, int y);
//
// Turn text wrap on or off for the obdWriteString() function
//
void obdSetTextWrap(OBDISP *pOBD, int bWrap);
//
// Advance to the next line
//
void obdNextLine(OBDISP *pOBD);
//
// Draw a string of normal (8x8), small (6x8) or large (16x32) characters
// At the given col+row with the given scroll offset. The scroll offset allows you to
// horizontally scroll text which does not fit on the width of the display. The offset
// represents the pixels to skip when drawing the text. An offset of 0 starts at the beginning
// of the text.
// The system remembers where the last text was written (the cursor position)
// To continue writing from the last position, set the x,y values to -1
// The text can optionally wrap around to the next line by calling oledSetTextWrap(true);
// otherwise text which would go off the right edge will not be drawn and the cursor will
// be left "off screen" until set to a new position explicitly
//
// Returns 0 for success, -1 for invalid parameter
//
int obdWriteString(OBDISP *pOBD, int iScrollX, int x, int y, char *szMsg, int iSize, int iColor, int bRender);
//
// Draw a string with a fractional scale in both dimensions
// the scale is a 16-bit integer with and 8-bit fraction and 8-bit mantissa
// To draw at 1x scale, set the scale factor to 256. To draw at 2x, use 512
// The output must be drawn into a memory buffer, not directly to the display
// The string can be drawn in one of 4 rotations (ROT_0, ROT_90, ROT_180, ROT_270)
//
int obdScaledString(OBDISP *pOBD, int x, int y, char *szMsg, int iSize, int iColor, int iXScale, int iYScale, int iRotation);
//
// Draw a string in a proportional font you supply
// Requires a back buffer
//
int obdWriteStringCustom(OBDISP *pOBD, GFXfont *pFont, int x, int y, char *szMsg, uint8_t ucColor);
//
// Get the width of text in a custom font
//
void obdGetStringBox(GFXfont *pFont, char *szMsg, int *width, int *top, int *bottom);
//
// Fill the frame buffer with a byte pattern
// e.g. all off (0x00) or all on (0xff)
//
void obdFill(OBDISP *pOBD, unsigned char ucData, int bRender);
//
// Set (or clear) an individual pixel
// The local copy of the frame buffer is used to avoid
// reading data from the display controller
// (which isn't possible in most configurations)
// This function needs the USE_BACKBUFFER macro to be defined
// otherwise, new pixels will erase old pixels within the same byte
//
int obdSetPixel(OBDISP *pOBD, int x, int y, unsigned char ucColor, int bRender);
//
// Dump a portion of the screen
// optional buffer pointer if no back buffer
//
int obdDumpPartial(OBDISP *pOBD, int startx, int starty, int width, int height, uint8_t *pBuffer);
//
// Dump an entire custom buffer to the display
// useful for custom animation effects
//
int obdDumpBuffer(OBDISP *pOBD, uint8_t *pBuffer, int bRefresh, int bWait, int bFast);
//
// Render a window of pixels from a provided buffer or the library's internal buffer
// to the display. The row values refer to byte rows, not pixel rows due to the memory
// layout of OLEDs. Pass a src pointer of NULL to use the internal backing buffer
// returns 0 for success, -1 for invalid parameter
//
int obdDrawGFX(OBDISP *pOBD, uint8_t *pSrc, int iSrcCol, int iSrcRow, int iDestCol, int iDestRow, int iWidth, int iHeight, int iSrcPitch);
//
// Set the current custom font pointers for playing back
// bytewise commands
//
void obdSetCustomFont(OBDISP *pOBD, GFXfont *pFont, uint8_t ucFont);
//
// Execute a set of bytewise command bytes
// and execute the drawing instructions on the current display/buffer
// Optionally render on backbuffer or physical display
//
void obdExecCommands(uint8_t *pData, int iLen, OBDISP *pOBD, int bRender);
//
// Return the number of bytes accumulated as commands
//
int obdGetCommandLen(OBDISP *pOBD);
//
// Draw a line between 2 points
//
void obdDrawLine(OBDISP *pOBD, int x1, int y1, int x2, int y2, uint8_t ucColor, int bRender);
//
// Play a frame of animation data
// The animation data is assumed to be encoded for a full frame of the display
// Given the pointer to the start of the compressed data,
// it returns the pointer to the start of the next frame
// Frame rate control is up to the calling program to manage
// When it finishes the last frame, it will start again from the beginning
//
uint8_t * obdPlayAnimFrame(OBDISP *pOBD, uint8_t *pAnimation, uint8_t *pCurrent, int iLen);
void obdWriteCommand(OBDISP *pOBD, unsigned char c);
void obdSetPosition(OBDISP *pOBD, int x, int y, int bRender);
void obdWriteDataBlock(OBDISP *pOBD, unsigned char *ucBuf, int iLen, int bRender);
void RawWriteData(OBDISP *pOBD, unsigned char *ucBuf, int iLen);
//
// Scroll the internal buffer by 1 scanline (up/down)
// width is in pixels, lines is group of 8 rows
// Returns 0 for success, -1 for invalid parameter
//
int obdScrollBuffer(OBDISP *pOBD, int iStartCol, int iEndCol, int iStartRow, int iEndRow, int bUp);
//
// Draw a sprite of any size in any position
// If it goes beyond the left/right or top/bottom edges
// it's trimmed to show the valid parts
// This function requires a back buffer to be defined
// The priority color (0 or 1) determines which color is painted
// when a 1 is encountered in the source image.
// e.g. when 0, the input bitmap acts like a mask to clear
// the destination where bits are set.
//
void obdDrawSprite(OBDISP *pOBD, uint8_t *pSprite, int cx, int cy, int iPitch, int x, int y, uint8_t iPriority);
//
// Draw 1 or 2 planes of raw image into a specific spot
// in e-paper memory
//
int obdDrawEPDGFX(OBDISP *pOBD, int x, int y, int cx, int cy, uint8_t *pPlane0, uint8_t *pPlane1);
//
// Draw a 16x16 tile in any of 4 rotated positions
// Assumes input image is laid out like "normal" graphics with
// the MSB on the left and 2 bytes per line
// On AVR, the source image is assumed to be in FLASH memory
// The function can draw the tile on byte boundaries, so the x value
// can be from 0 to 112 and y can be from 0 to 6
//
void obdDrawTile(OBDISP *pOBD, const uint8_t *pTile, int x, int y, int iRotation, int bInvert, int bRender);
//
// Draw an outline or filled ellipse
//
void obdEllipse(OBDISP *pOBD, int iCenterX, int iCenterY, int32_t iRadiusX, int32_t iRadiusY, uint8_t ucColor, uint8_t bFilled);
//
// Draw an outline or filled rectangle
//
void obdRectangle(OBDISP *pOBD, int x1, int y1, int x2, int y2, uint8_t ucColor, uint8_t bFilled);
//
// Turn the LCD backlight on or off
//
void obdBacklight(OBDISP *pODB, int bOn);
//
// Menu functions
//
// Initialize the simple menu structure
//
int obdMenuInit(OBDISP *pOBD, SIMPLEMENU *sm, char **pText, int iFontSize, int bCenter, int btnUp, int btnDn, int btnEnter, int iPressedState, int bIsRotary);
//
// Erase the display and show the given menu
//
void obdMenuShow(SIMPLEMENU *sm, int iItem);
//
// Set a callback function to return custom info/status
// for each menu item
//
void obdMenuSetCallback(SIMPLEMENU *sm, SIMPLECALLBACK pfnCallBack);
//
// Display the text of a single menu item
// optionally erases what's under it to prevent left-over text when the length changes
//
void obdMenuShowItem(OBDISP *pOBD, int x, int y, char *szText, int bInvert, int bErase, int iFontSize, int bRender);
//
// Change the menu index incrementally
// redraws the minimum amount of screen to show the new info
// (this prevents flicker/flash and saves battery life)
// returns the new menu index
//
int obdMenuDelta(SIMPLEMENU *sm, int iDelta);
//
// With the given setup, check for button presses
// and act accordingly
// returns -1 for normal interactions and the menu item index if the user presses the ENTER button
//
int obdMenuRun(SIMPLEMENU *sm);
#if defined(_LINUX_) && defined(__cplusplus)
}
#endif // _LINUX_
#endif // __ONEBITDISPLAY__
#endif // __BB_EINK__