mirror of
https://github.com/usetrmnl/bb_epaper.git
synced 2026-04-29 13:43:26 -07:00
Added initial support for dual-cable Spectra 6 display
This commit is contained in:
@@ -23,6 +23,17 @@
|
||||
// foreward references
|
||||
void bbepWakeUp(BBEPDISP *pBBEP);
|
||||
void bbepSendCMDSequence(BBEPDISP *pBBEP, const uint8_t *pSeq);
|
||||
//
|
||||
// Set the second CS pin for dual-controller displays
|
||||
//
|
||||
void bbepSetCS2(BBEPDISP *pBBEP, uint8_t cs)
|
||||
{
|
||||
pBBEP->iCS1Pin = pBBEP->iCSPin;
|
||||
pBBEP->iCS2Pin = cs;
|
||||
pinMode(cs, OUTPUT);
|
||||
digitalWrite(cs, HIGH); // disable second CS for now
|
||||
} /* bbepSetCS2() */
|
||||
|
||||
//
|
||||
// Initialize the GPIO pins and SPI for use by bb_eink
|
||||
//
|
||||
|
||||
+200
-6
@@ -53,7 +53,7 @@ const uint8_t u8Colors_7clr[16] = { // ACeP 7-color
|
||||
};
|
||||
|
||||
const uint8_t u8Colors_spectra[16] = { // Spectra 6
|
||||
BBEP_BLACK, BBEP_WHITE, BBEP_YELLOW, BBEP_RED, BBEP_BLACK, BBEP_BLUE, BBEP_GREEN, BBEP_BLACK,
|
||||
BBEP_BLACK, BBEP_WHITE, BBEP_YELLOW, BBEP_RED, 0x05, 0x06, BBEP_BLACK, BBEP_BLACK,
|
||||
BBEP_BLACK, BBEP_BLACK, BBEP_BLACK, BBEP_BLACK, BBEP_BLACK, BBEP_BLACK, BBEP_BLACK, BBEP_BLACK
|
||||
};
|
||||
|
||||
@@ -1417,6 +1417,27 @@ const uint8_t epd75r_init[] PROGMEM = {
|
||||
0
|
||||
};
|
||||
|
||||
const uint8_t epd41_init_sequence_full[] PROGMEM = {
|
||||
BUSY_WAIT,
|
||||
3, UC8151_PSR, 0x2f, 0x00,
|
||||
5, UC8151_PWR, 0x37, 0x00, 0x05, 0x05,
|
||||
2, UC8151_PFS, 0x00,
|
||||
4, UC8151_BTST, 0xc7, 0xc7, 0x1d,
|
||||
2, UC8151_PLL, 0x3c,
|
||||
2, UC8151_TSE, 0x00,
|
||||
2, UC8151_CDI, 0x37,
|
||||
2, UC8151_TCON, 0x22,
|
||||
5, UC8151_TRES, 0x02, 0x80, 0x01, 0x90,
|
||||
2, UC8151_PWS, 0xaa,
|
||||
// second set of commands from example (seems unnecessary)
|
||||
3, UC8151_PSR, 0x2f, 0x08,
|
||||
6, UC8151_PWR, 0x37, 0x00, 0x05, 0x05, 0x00,
|
||||
5, UC8151_TRES, 0x02, 0x80, 0x01, 0x90,
|
||||
1, UC8151_PON, // power on
|
||||
BUSY_WAIT,
|
||||
0x00
|
||||
};
|
||||
|
||||
const uint8_t epd583r_init[] PROGMEM = {
|
||||
0x03, 0x01, 0x37, 0x00, // power setting
|
||||
0x03, 0x00, 0xcf, 0x08, // panel setting
|
||||
@@ -1433,6 +1454,30 @@ const uint8_t epd583r_init[] PROGMEM = {
|
||||
0x00
|
||||
};
|
||||
|
||||
const uint8_t epd81c_init_full[] PROGMEM = {
|
||||
BUSY_WAIT,
|
||||
7, 0xaa, 0x49, 0x55, 0x20, 0x08, 0x09, 0x18,
|
||||
2, UC8151_PWR, 0x3f,
|
||||
3, UC8151_PSR, 0x5f, 0x69,
|
||||
BUSY_WAIT,
|
||||
5, 0x05, 0x40, 0x1f, 0x1f, 0x2c,
|
||||
5, 0x08, 0x6f, 0x1f, 0x1f, 0x22,
|
||||
5, UC8151_BTST, 0x6f, 0x1f, 0x16, 0x16,
|
||||
5, UC8151_PFS, 0x00, 0x54, 0x00, 0x44,
|
||||
3, UC8151_TCON, 0x02, 0x00,
|
||||
2, UC8151_PLL, 0x08,
|
||||
5, UC8151_TRES, 0x02, 0x00, 0x02, 0x40,
|
||||
BUSY_WAIT,
|
||||
2, UC8151_CDI, 0x3f,
|
||||
2, UC8151_PWS, 0x2f,
|
||||
2, UC8151_VDCS, 0x01,
|
||||
2, 0xe0, 0x01,
|
||||
5, UC8151_BTST, 0x6f, 0x1f, 0x16, 0x25,
|
||||
1, UC8151_PON,
|
||||
BUSY_WAIT,
|
||||
0x00
|
||||
};
|
||||
|
||||
#ifdef NO_RAM
|
||||
uint8_t u8Cache[128]; // buffer a single line of up to 1024 pixels
|
||||
#else // we need a larger cache for 4-bit panels
|
||||
@@ -1481,6 +1526,8 @@ const EPD_PANEL panelDefs[] PROGMEM = {
|
||||
{800, 480, 0, epd75r_init, NULL, NULL, BBEP_3COLOR | BBEP_RED_SWAPPED, BBEP_CHIP_UC81xx, u8Colors_3clr}, // EP75R_800x480, waveshare 7.5 800x480 B/W/R
|
||||
{480, 800, 0, epd426_init_full, epd426_init_fast, epd426_init_part, 0, BBEP_CHIP_SSD16xx, u8Colors_2clr},
|
||||
{128, 296, 0, epd29r2_init_sequence_full, NULL, NULL, BBEP_RED_SWAPPED | BBEP_3COLOR, BBEP_CHIP_UC81xx, u8Colors_3clr}, // EP29R2_128x296 Adafruit 2.9" 128x296 Tricolor FeatherWing
|
||||
{640, 400, 0, epd41_init_sequence_full, NULL, NULL, BBEP_4BPP_DATA, BBEP_CHIP_UC81xx, u8Colors_2clr}, // EP41_640x400 Eink ED040TC1
|
||||
{1024, 576, 0, epd81c_init_full, NULL, NULL, BBEP_SPLIT_BUFFER | BBEP_7COLOR, BBEP_CHIP_UC81xx, u8Colors_spectra}, // 8.1" 1024x576 dual cable Spectra 6 EP81_SPECTRA_1024x576
|
||||
};
|
||||
//
|
||||
// Set the e-paper panel type
|
||||
@@ -1816,6 +1863,16 @@ void bbepFill(BBEPDISP *pBBEP, unsigned char ucColor, int iPlane)
|
||||
if (ucColor == BBEP_WHITE) ucColor = 0xff;
|
||||
else if (ucColor == BBEP_BLACK) ucColor = 0;
|
||||
uc1 = uc2 = ucColor;
|
||||
if (pBBEP->iFlags & BBEP_4BPP_DATA) { // special case
|
||||
// EInk 4.1" 640x400 uses 4-bpp data for 1-bpp images
|
||||
uc1 = (ucColor == BBEP_WHITE) ? 0x00 : 0x11;
|
||||
memset(u8Cache, uc1, pBBEP->native_width/2);
|
||||
bbepWriteCmd(pBBEP, 0x10);
|
||||
for (y=0; y<pBBEP->native_height; y++) {
|
||||
bbepWriteData(pBBEP, u8Cache, pBBEP->native_width/2);
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (pBBEP->chip_type == BBEP_CHIP_UC81xx) {
|
||||
if (pBBEP->iFlags & (BBEP_RED_SWAPPED | BBEP_4COLOR)) {
|
||||
@@ -1857,6 +1914,12 @@ int bbepRefresh(BBEPDISP *pBBEP, int iMode)
|
||||
switch (iMode) {
|
||||
case REFRESH_FULL:
|
||||
bbepSendCMDSequence(pBBEP, pBBEP->pInitFull);
|
||||
if (pBBEP->iFlags & BBEP_SPLIT_BUFFER) {
|
||||
// Send the same sequence to the second controller
|
||||
pBBEP->iCSPin = pBBEP->iCS2Pin;
|
||||
bbepSendCMDSequence(pBBEP, pBBEP->pInitFull);
|
||||
pBBEP->iCSPin = pBBEP->iCS1Pin;
|
||||
}
|
||||
break;
|
||||
case REFRESH_FAST:
|
||||
if (!pBBEP->pInitFast)
|
||||
@@ -1873,7 +1936,13 @@ int bbepRefresh(BBEPDISP *pBBEP, int iMode)
|
||||
} // switch on mode
|
||||
if (pBBEP->chip_type == BBEP_CHIP_UC81xx) {
|
||||
if (pBBEP->iFlags & (BBEP_4COLOR | BBEP_7COLOR)) {
|
||||
bbepCMD2(pBBEP, 0x12, 0x00);
|
||||
bbepCMD2(pBBEP, UC8151_DRF, 0x00);
|
||||
if (pBBEP->iFlags & BBEP_SPLIT_BUFFER) {
|
||||
// Send the same sequence to the second controller
|
||||
pBBEP->iCSPin = pBBEP->iCS2Pin;
|
||||
bbepCMD2(pBBEP, UC8151_DRF, 0);
|
||||
pBBEP->iCSPin = pBBEP->iCS1Pin;
|
||||
}
|
||||
} else {
|
||||
bbepWriteCmd(pBBEP, UC8151_PTOU); // partial out (update the entire panel, not just the last memory window)
|
||||
bbepWriteCmd(pBBEP, UC8151_DRF);
|
||||
@@ -2037,6 +2106,84 @@ void bbepWriteImage4bppSpecial(BBEPDISP *pBBEP, uint8_t ucCMD)
|
||||
} // 270
|
||||
} /* bbepWriteImage4bppSpecial() */
|
||||
|
||||
// special case for panels with 2 controllers
|
||||
void bbepWriteImage4bppDual(BBEPDISP *pBBEP, uint8_t ucCMD)
|
||||
{
|
||||
int tx, ty, iPitch;
|
||||
uint8_t uc, *s, *d;
|
||||
|
||||
if (ucCMD) {
|
||||
pBBEP->iCSPin = pBBEP->iCS1Pin;
|
||||
bbepWriteCmd(pBBEP, ucCMD); // start write
|
||||
pBBEP->iCSPin = pBBEP->iCS2Pin;
|
||||
bbepWriteCmd(pBBEP, ucCMD);
|
||||
}
|
||||
if (pBBEP->iOrientation == 0) {
|
||||
iPitch = pBBEP->native_width / 2;
|
||||
s = pBBEP->ucScreen;
|
||||
for (ty=0; ty<pBBEP->height; ty++) {
|
||||
pBBEP->iCSPin = pBBEP->iCS1Pin;
|
||||
bbepWriteData(pBBEP, s, iPitch/2);
|
||||
pBBEP->iCSPin = pBBEP->iCS2Pin;
|
||||
bbepWriteData(pBBEP, &s[iPitch/2], iPitch/2);
|
||||
s += iPitch; // 2 pixels per byte
|
||||
} // for ty
|
||||
} else if (pBBEP->iOrientation == 180) {
|
||||
iPitch = pBBEP->native_width / 2;
|
||||
for (ty=pBBEP->height-1; ty>=0; ty--) {
|
||||
s = &pBBEP->ucScreen[(ty * iPitch) + iPitch - 1];
|
||||
// reverse the pixel direction
|
||||
for (tx=0; tx<pBBEP->native_width; tx+=2) {
|
||||
uc = *s--;
|
||||
uc = (uc >> 4) | (uc << 4); // swap nibbles
|
||||
u8Cache[tx/2] = uc;
|
||||
}
|
||||
pBBEP->iCSPin = pBBEP->iCS1Pin;
|
||||
bbepWriteData(pBBEP, u8Cache, iPitch/2);
|
||||
pBBEP->iCSPin = pBBEP->iCS2Pin;
|
||||
bbepWriteData(pBBEP, &u8Cache[iPitch/2], iPitch/2);
|
||||
} // for ty
|
||||
} else if (pBBEP->iOrientation == 90) {
|
||||
iPitch = pBBEP->native_height / 2;
|
||||
for (tx=0; tx<pBBEP->width; tx++) {
|
||||
d = u8Cache;
|
||||
for (ty=pBBEP->height-1; ty > 0; ty-=2) {
|
||||
s = &pBBEP->ucScreen[(tx>>1) + (ty * iPitch)];
|
||||
if (tx & 1) {
|
||||
uc = (s[0] << 4) | (s[-iPitch] & 0x0f);
|
||||
} else {
|
||||
uc = (s[0] & 0xf0) | (s[-iPitch] >> 4);
|
||||
}
|
||||
s -= iPitch*2;
|
||||
*d++ = uc; // store 4 pixels
|
||||
} // for ty
|
||||
pBBEP->iCSPin = pBBEP->iCS1Pin;
|
||||
bbepWriteData(pBBEP, u8Cache, pBBEP->height/4);
|
||||
pBBEP->iCSPin = pBBEP->iCS2Pin;
|
||||
bbepWriteData(pBBEP, &u8Cache[pBBEP->height/4], pBBEP->height/4);
|
||||
} // for tx
|
||||
} else if (pBBEP->iOrientation == 270) {
|
||||
iPitch = pBBEP->native_height / 2;
|
||||
for (tx=pBBEP->width-1; tx>= 0; tx--) {
|
||||
d = u8Cache;
|
||||
for (ty=0; ty < pBBEP->height; ty+=2) {
|
||||
s = &pBBEP->ucScreen[(tx>>1) + (ty * iPitch)];
|
||||
if (tx & 1) {
|
||||
uc = (s[0] << 4) | (s[iPitch] & 0x0f);
|
||||
} else {
|
||||
uc = (s[0] & 0xf0) | (s[iPitch] >> 4);
|
||||
}
|
||||
s += iPitch*2;
|
||||
*d++ = uc; // store 4 pixels
|
||||
} // for ty
|
||||
pBBEP->iCSPin = pBBEP->iCS1Pin;
|
||||
bbepWriteData(pBBEP, u8Cache, pBBEP->height/4);
|
||||
pBBEP->iCSPin = pBBEP->iCS2Pin;
|
||||
bbepWriteData(pBBEP, &u8Cache[pBBEP->height/4], pBBEP->height/4);
|
||||
} // for tx
|
||||
}
|
||||
} /* bbepWriteImage4bppDual() */
|
||||
|
||||
void bbepWriteImage4bpp(BBEPDISP *pBBEP, uint8_t ucCMD)
|
||||
{
|
||||
int tx, ty, iPitch;
|
||||
@@ -2169,7 +2316,46 @@ uint8_t *pBuffer;
|
||||
} /* bbepWriteImage2bpp() */
|
||||
|
||||
//
|
||||
// Write Image data (entire plane) from RAM to the e-paper
|
||||
// Write 1-bpp graphics to a display which wants to receive it as 4-bpp
|
||||
//
|
||||
static void bbepWriteImage1to4bpp(BBEPDISP *pBBEP, uint8_t ucCMD, uint8_t *pBuffer, int bInvert)
|
||||
{
|
||||
int tx, ty;
|
||||
uint8_t *s, *d, ucSrcMask, ucDstMask, uc;
|
||||
uint8_t ucInvert = 0;
|
||||
int iPitch;
|
||||
// lookup table to convert 2 bits into 8
|
||||
const uint8_t u8Lookup[4] = {0x00, 0x01, 0x10, 0x11};
|
||||
|
||||
iPitch = (pBBEP->width + 7) >> 3;
|
||||
if (bInvert) {
|
||||
ucInvert = 0xff; // red logic is inverted
|
||||
}
|
||||
if (ucCMD) {
|
||||
bbepWriteCmd(pBBEP, ucCMD); // start write
|
||||
}
|
||||
// Convert the bit direction and write the data to the EPD
|
||||
switch (pBBEP->iOrientation) {
|
||||
case 0:
|
||||
for (ty=0; ty<pBBEP->native_height; ty++) {
|
||||
d = u8Cache;
|
||||
s = &pBuffer[ty * iPitch];
|
||||
for (tx=0; tx<iPitch; tx++) {
|
||||
uc = *s++;
|
||||
*d++ = u8Lookup[uc >> 6];
|
||||
*d++ = u8Lookup[(uc >> 4) & 3];
|
||||
*d++ = u8Lookup[(uc >> 2) & 3];
|
||||
*d++ = u8Lookup[uc & 3];
|
||||
}
|
||||
if (ucInvert) InvertBytes(u8Cache, iPitch*4);
|
||||
bbepWriteData(pBBEP, u8Cache, iPitch*4);
|
||||
} // for ty
|
||||
break;
|
||||
} // switch
|
||||
} /* bbepWriteImage1to4bpp() */
|
||||
|
||||
//
|
||||
// Write Image data (1-bpp entire plane) from RAM to the e-paper
|
||||
// Rotate the pixels if necessary
|
||||
//
|
||||
static void bbepWriteImage(BBEPDISP *pBBEP, uint8_t ucCMD, uint8_t *pBuffer, int bInvert)
|
||||
@@ -2264,12 +2450,20 @@ int bbepWritePlane(BBEPDISP *pBBEP, int iPlane)
|
||||
}
|
||||
bbepSetAddrWindow(pBBEP, 0,0, pBBEP->native_width, pBBEP->native_height);
|
||||
|
||||
if (pBBEP->iFlags & BBEP_4BPP_DATA) { // special case for some 3-color panels
|
||||
bbepWriteImage4bppSpecial(pBBEP, 0x10);
|
||||
if (pBBEP->iFlags & BBEP_4BPP_DATA) { // special case for some 2 and 3-color panels
|
||||
if (pBBEP->iFlags & BBEP_3COLOR) {
|
||||
bbepWriteImage4bppSpecial(pBBEP, 0x10);
|
||||
} else {
|
||||
bbepWriteImage1to4bpp(pBBEP, 0x10, pBBEP->ucScreen, 0);
|
||||
}
|
||||
return BBEP_SUCCESS;
|
||||
}
|
||||
if (pBBEP->iFlags & BBEP_7COLOR) {
|
||||
bbepWriteImage4bpp(pBBEP, 0x10);
|
||||
if (pBBEP->iFlags & BBEP_SPLIT_BUFFER) { // dual cable EPD
|
||||
bbepWriteImage4bppDual(pBBEP, 0x10);
|
||||
} else {
|
||||
bbepWriteImage4bpp(pBBEP, 0x10);
|
||||
}
|
||||
return BBEP_SUCCESS;
|
||||
}
|
||||
if (pBBEP->iFlags & BBEP_4COLOR) { // 4-color only has 1 way to go
|
||||
|
||||
+5
-4
@@ -65,13 +65,16 @@ int BBEPAPER::setPanelType(int iPanel)
|
||||
{
|
||||
return bbepSetPanelType(&_bbep, iPanel);
|
||||
}
|
||||
// Special setup for dual-cable displays
|
||||
void BBEPAPER::setCS2(uint8_t cs)
|
||||
{
|
||||
bbepSetCS2(&_bbep, cs);
|
||||
}
|
||||
|
||||
#ifdef ARDUINO
|
||||
void BBEPAPER::initIO(int iDC, int iReset, int iBusy, int iCS, int iMOSI, int iSCLK, uint32_t u32Speed)
|
||||
{
|
||||
bbepInitIO(&_bbep, iDC, iReset, iBusy, iCS, iMOSI, iSCLK, u32Speed);
|
||||
// bbepWakeUp(&_bbep);
|
||||
// bbepSendCMDSequence(&_bbep, _bbep.pInitFull);
|
||||
} /* initIO() */
|
||||
#else // Linux
|
||||
void BBEPAPER::initIO(int iDC, int iReset, int iBusy, int iCS, int iSPIChannel, uint32_t u32Speed)
|
||||
@@ -82,8 +85,6 @@ void BBEPAPER::initIO(int iDC, int iReset, int iBusy, int iCS, int iSPIChannel,
|
||||
_bbep.iRSTPin = iReset;
|
||||
_bbep.iMOSIPin = iSPIChannel;
|
||||
bbepInitIO(&_bbep, u32Speed);
|
||||
bbepWakeUp(&_bbep);
|
||||
bbepSendCMDSequence(&_bbep, _bbep.pInitFull);
|
||||
} /* initIO() */
|
||||
#endif
|
||||
int BBEPAPER::writePlane(int iPlane)
|
||||
|
||||
@@ -141,6 +141,8 @@ enum {
|
||||
EP75R_800x480, // Waveshare 800x480 3-color
|
||||
EP426_480x800, // Waveshare 4.26" B/W 480x800
|
||||
EP29R2_128x296, // Adafruit 2.9" 128x296 Tricolor FeatherWing
|
||||
EP41_640x400, // EInk ED040TC1 SPI UC81xx
|
||||
EP81_SPECTRA_1024x576, // Spectra 8.1" 1024x576 6-colors
|
||||
EP_PANEL_COUNT
|
||||
};
|
||||
#ifdef FUTURE
|
||||
@@ -179,6 +181,7 @@ enum {
|
||||
#define BBEP_CS_EVERY_BYTE 0x0040
|
||||
#define BBEP_PARTIAL2 0x0080
|
||||
#define BBEP_4BPP_DATA 0x0100
|
||||
#define BBEP_SPLIT_BUFFER 0x0200
|
||||
|
||||
#define BBEP_BLACK 0
|
||||
#define BBEP_WHITE 1
|
||||
@@ -381,6 +384,7 @@ int iDataTime, iOpTime; // time in milliseconds for data transmission and operat
|
||||
uint32_t iSpeed;
|
||||
uint32_t iTimeout; // for e-paper panels
|
||||
uint8_t iDCPin, iMOSIPin, iCLKPin, iCSPin, iRSTPin, iBUSYPin;
|
||||
uint8_t iCS1Pin, iCS2Pin;
|
||||
uint8_t x_offset, y_offset; // memory offsets
|
||||
uint8_t is_awake, iPlane;
|
||||
const uint8_t *pColorLookup; // color translation table
|
||||
@@ -409,6 +413,7 @@ class BBEPAPER
|
||||
int createVirtual(int iWidth, int iHeight, int iFlags);
|
||||
void setAddrWindow(int x, int y, int w, int h);
|
||||
int setPanelType(int iPanel);
|
||||
void setCS2(uint8_t cs);
|
||||
bool hasFastRefresh();
|
||||
bool hasPartialRefresh();
|
||||
#ifdef ARDUINO
|
||||
|
||||
Reference in New Issue
Block a user