mirror of
https://github.com/usetrmnl/bb_epaper.git
synced 2026-04-29 13:43:26 -07:00
added S3 ULP example
This commit is contained in:
+87
-210
@@ -10,19 +10,14 @@
|
|||||||
#define DISABLED 3
|
#define DISABLED 3
|
||||||
|
|
||||||
#define PROGMEM
|
#define PROGMEM
|
||||||
|
#define memcpy_P memcpy
|
||||||
|
#define pgm_read_byte(a) *(uint8_t *)a
|
||||||
|
|
||||||
#define HIGH 1
|
#define HIGH 1
|
||||||
#define LOW 0
|
#define LOW 0
|
||||||
#define PIN_SDA 6
|
#define PIN_SDA 6
|
||||||
#define PIN_SCL 7
|
#define PIN_SCL 7
|
||||||
|
|
||||||
// Pinout for the LilyGo mini-epaper S3
|
|
||||||
#define PIN_BUSY 10
|
|
||||||
#define PIN_RST 11
|
|
||||||
#define PIN_DC 12
|
|
||||||
#define PIN_CS 13
|
|
||||||
#define PIN_SCK 14
|
|
||||||
#define PIN_MOSI 15
|
|
||||||
|
|
||||||
// Pinout for my custom ESP32-S3 circuit
|
// Pinout for my custom ESP32-S3 circuit
|
||||||
//#define PIN_BUSY 12
|
//#define PIN_BUSY 12
|
||||||
//#define PIN_RST 7
|
//#define PIN_RST 7
|
||||||
@@ -34,6 +29,19 @@
|
|||||||
// CPU cycles per bit
|
// CPU cycles per bit
|
||||||
#define I2C_DELAY 40
|
#define I2C_DELAY 40
|
||||||
|
|
||||||
|
void delayMicroseconds(long l)
|
||||||
|
{
|
||||||
|
l *= 40;
|
||||||
|
while (l) {
|
||||||
|
__asm__ __volatile__ ("nop");
|
||||||
|
l--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void delay(long l)
|
||||||
|
{
|
||||||
|
delayMicroseconds(l*1000);
|
||||||
|
}
|
||||||
|
|
||||||
void digitalWrite(int iPin, int iState) {
|
void digitalWrite(int iPin, int iState) {
|
||||||
ulp_riscv_gpio_output_level(iPin, iState);
|
ulp_riscv_gpio_output_level(iPin, iState);
|
||||||
}
|
}
|
||||||
@@ -61,39 +69,94 @@ int digitalRead(int iPin)
|
|||||||
{
|
{
|
||||||
return (int)ulp_riscv_gpio_get_level(iPin);
|
return (int)ulp_riscv_gpio_get_level(iPin);
|
||||||
} /* digitalRead() */
|
} /* digitalRead() */
|
||||||
|
//
|
||||||
|
// De-initialize the GPIO pins
|
||||||
|
//
|
||||||
|
void bbepDeInitIO(BBEPDISP *pBBEP)
|
||||||
|
{
|
||||||
|
pinMode(pBBEP->iDCPin, DISABLED);
|
||||||
|
pinMode(pBBEP->iCSPin, DISABLED);
|
||||||
|
pinMode(pBBEP->iRSTPin, DISABLED);
|
||||||
|
pinMode(pBBEP->iBUSYPin, DISABLED);
|
||||||
|
pinMode(pBBEP->iMOSIPin, DISABLED);
|
||||||
|
pinMode(pBBEP->iCLKPin, DISABLED);
|
||||||
|
} /* bbepDeInitIO() */
|
||||||
|
//
|
||||||
|
// Initialize the GPIO pins and SPI for use by bb_epaper
|
||||||
|
//
|
||||||
|
void bbepInitIO(BBEPDISP *pBBEP, uint8_t u8DC, uint8_t u8RST, uint8_t u8BUSY, uint8_t u8CS, uint8_t u8MOSI, uint8_t u8SCK, uint32_t u32Speed)
|
||||||
|
{
|
||||||
|
(void)u32Speed; // irrelevant for the ULP
|
||||||
|
pBBEP->iDCPin = u8DC;
|
||||||
|
pBBEP->iCSPin = u8CS;
|
||||||
|
pBBEP->iMOSIPin = u8MOSI;
|
||||||
|
pBBEP->iCLKPin = u8SCK;
|
||||||
|
pBBEP->iRSTPin = u8RST;
|
||||||
|
pBBEP->iBUSYPin = u8BUSY;
|
||||||
|
|
||||||
|
pinMode(pBBEP->iDCPin, OUTPUT);
|
||||||
|
pinMode(pBBEP->iRSTPin, OUTPUT);
|
||||||
|
digitalWrite(pBBEP->iRSTPin, LOW);
|
||||||
|
delay(100);
|
||||||
|
digitalWrite(pBBEP->iRSTPin, HIGH);
|
||||||
|
delay(100);
|
||||||
|
if (pBBEP->iBUSYPin != 0xff) {
|
||||||
|
pinMode(pBBEP->iBUSYPin, INPUT);
|
||||||
|
}
|
||||||
|
pinMode(pBBEP->iCSPin, OUTPUT);
|
||||||
|
pinMode(pBBEP->iMOSIPin, OUTPUT);
|
||||||
|
pinMode(pBBEP->iCLKPin, OUTPUT);
|
||||||
|
digitalWrite(pBBEP->iCSPin, HIGH); // we have to manually control the CS pin
|
||||||
|
} /* bbepInitIO() */
|
||||||
|
|
||||||
//
|
//
|
||||||
// Bit Bang SPI
|
// Bit Bang SPI
|
||||||
//
|
//
|
||||||
void SPIWriteByte(uint8_t uc)
|
void SPIWriteByte(BBEPDISP *pBBEP, uint8_t uc)
|
||||||
{
|
{
|
||||||
|
uint8_t u8MOSI = pBBEP->iMOSIPin;
|
||||||
|
uint8_t u8SCK = pBBEP->iCLKPin;
|
||||||
|
|
||||||
if (uc == 0 || uc == 0xff) { // special case
|
if (uc == 0 || uc == 0xff) { // special case
|
||||||
ulp_riscv_gpio_output_level(PIN_MOSI, (uc & 1));
|
ulp_riscv_gpio_output_level(u8MOSI, (uc & 1));
|
||||||
for (int i=0; i<8; i++) {
|
for (int i=0; i<8; i++) {
|
||||||
ulp_riscv_gpio_output_level(PIN_SCK, 1); // no delays needed since it runs at a slow clock
|
ulp_riscv_gpio_output_level(u8SCK, 1); // no delays needed since it runs at a slow clock
|
||||||
ulp_riscv_gpio_output_level(PIN_SCK, 0);
|
ulp_riscv_gpio_output_level(u8SCK, 0);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
for (int i=0; i<8; i++) {
|
for (int i=0; i<8; i++) {
|
||||||
ulp_riscv_gpio_output_level(PIN_MOSI, (uc & 0x80)); // msb first
|
ulp_riscv_gpio_output_level(u8MOSI, (uc & 0x80)); // msb first
|
||||||
ulp_riscv_gpio_output_level(PIN_SCK, 1); // no delays needed since it runs at a slow clock
|
ulp_riscv_gpio_output_level(u8SCK, 1); // no delays needed since it runs at a slow clock
|
||||||
uc <<= 1;
|
uc <<= 1;
|
||||||
ulp_riscv_gpio_output_level(PIN_SCK, 0);
|
ulp_riscv_gpio_output_level(u8SCK, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} /* SPIWriteByte() */
|
} /* SPIWriteByte() */
|
||||||
|
|
||||||
void delayMicroseconds(long l)
|
void bbepWriteCmd(BBEPDISP *pBBEP, uint8_t ucCMD)
|
||||||
|
{
|
||||||
|
digitalWrite(pBBEP->iDCPin, LOW);
|
||||||
|
digitalWrite(pBBEP->iCSPin, LOW);
|
||||||
|
SPIWriteByte(pBBEP, ucCMD);
|
||||||
|
digitalWrite(pBBEP->iDCPin, HIGH);
|
||||||
|
digitalWrite(pBBEP->iCSPin, HIGH);
|
||||||
|
} /* bbepWriteCmd() */
|
||||||
|
|
||||||
|
void bbepWriteData(BBEPDISP *pBBEP, uint8_t *pData, int iLen)
|
||||||
{
|
{
|
||||||
l *= 40;
|
digitalWrite(pBBEP->iCSPin, LOW);
|
||||||
while (l) {
|
for (int i=0; i<iLen; i++) {
|
||||||
__asm__ __volatile__ ("nop");
|
SPIWriteByte(pBBEP, pData[i]);
|
||||||
l--;
|
|
||||||
}
|
}
|
||||||
|
digitalWrite(pBBEP->iCSPin, HIGH);
|
||||||
}
|
}
|
||||||
void _delay(long l)
|
|
||||||
{
|
void bbepCMD2(BBEPDISP *pBBEP, uint8_t cmd, uint8_t param)
|
||||||
delayMicroseconds(l*1000);
|
{
|
||||||
}
|
bbepWriteCmd(pBBEP, cmd);
|
||||||
|
bbepWriteData(pBBEP, ¶m, 1);
|
||||||
|
} /* bbepCMD2() */
|
||||||
|
|
||||||
void mymemcpy(void *d, void *s, size_t iLen)
|
void mymemcpy(void *d, void *s, size_t iLen)
|
||||||
{
|
{
|
||||||
uint8_t *d8 = (uint8_t *)d;
|
uint8_t *d8 = (uint8_t *)d;
|
||||||
@@ -168,191 +231,5 @@ int i2str(char *pDest, int iVal)
|
|||||||
*d++ = 0; // terminator
|
*d++ = 0; // terminator
|
||||||
return (int)(d - pDest - 1); // string length
|
return (int)(d - pDest - 1); // string length
|
||||||
} /* i2str() */
|
} /* i2str() */
|
||||||
//
|
|
||||||
// Need to bit-bang I2C
|
|
||||||
//
|
|
||||||
uint8_t SDA_READ(void)
|
|
||||||
{
|
|
||||||
return ulp_riscv_gpio_get_level(PIN_SDA);
|
|
||||||
}
|
|
||||||
void SDA_HIGH(void)
|
|
||||||
{
|
|
||||||
ulp_riscv_gpio_output_disable(PIN_SDA);
|
|
||||||
ulp_riscv_gpio_input_enable(PIN_SDA);
|
|
||||||
}
|
|
||||||
void SDA_LOW(void)
|
|
||||||
{
|
|
||||||
ulp_riscv_gpio_input_disable(PIN_SDA);
|
|
||||||
ulp_riscv_gpio_output_enable(PIN_SDA);
|
|
||||||
ulp_riscv_gpio_output_level(PIN_SDA, 0);
|
|
||||||
}
|
|
||||||
void SCL_HIGH(void)
|
|
||||||
{
|
|
||||||
ulp_riscv_gpio_output_disable(PIN_SCL);
|
|
||||||
ulp_riscv_gpio_input_enable(PIN_SCL);
|
|
||||||
}
|
|
||||||
void SCL_LOW(void)
|
|
||||||
{
|
|
||||||
ulp_riscv_gpio_input_disable(PIN_SCL);
|
|
||||||
ulp_riscv_gpio_output_enable(PIN_SCL);
|
|
||||||
ulp_riscv_gpio_output_level(PIN_SDA, 0);
|
|
||||||
}
|
|
||||||
// Transmit a byte and read the ack bit
|
|
||||||
// if we get a NACK (negative acknowledge) return 0
|
|
||||||
// otherwise return 1 for success
|
|
||||||
//
|
|
||||||
|
|
||||||
int i2cByteOut(uint8_t b)
|
|
||||||
{
|
|
||||||
uint8_t i, ack;
|
|
||||||
|
|
||||||
for (i=0; i<8; i++) {
|
|
||||||
// my_sleep_us(iDelay);
|
|
||||||
if (b & 0x80)
|
|
||||||
SDA_HIGH(); // set data line to 1
|
|
||||||
else
|
|
||||||
SDA_LOW(); // set data line to 0
|
|
||||||
b <<= 1;
|
|
||||||
// my_sleep_us(iDelay);
|
|
||||||
SCL_HIGH(); // clock high (slave latches data)
|
|
||||||
ulp_riscv_delay_cycles(I2C_DELAY);
|
|
||||||
SCL_LOW(); // clock low
|
|
||||||
ulp_riscv_delay_cycles(I2C_DELAY);
|
|
||||||
} // for i
|
|
||||||
//my_sleep_us(iDelay);
|
|
||||||
// read ack bit
|
|
||||||
SDA_HIGH(); // set data line for reading
|
|
||||||
//my_sleep_us(iDelay);
|
|
||||||
SCL_HIGH(); // clock line high
|
|
||||||
ulp_riscv_delay_cycles(I2C_DELAY); // DEBUG - delay/2
|
|
||||||
ack = SDA_READ();
|
|
||||||
//my_sleep_us(iDelay);
|
|
||||||
SCL_LOW(); // clock low
|
|
||||||
ulp_riscv_delay_cycles(I2C_DELAY); // DEBUG - delay/2
|
|
||||||
SDA_LOW(); // data low
|
|
||||||
return (ack == 0); // a low ACK bit means success
|
|
||||||
} /* i2cByteOut() */
|
|
||||||
//
|
|
||||||
// Receive a byte and read the ack bit
|
|
||||||
// if we get a NACK (negative acknowledge) return 0
|
|
||||||
// otherwise return 1 for success
|
|
||||||
//
|
|
||||||
uint8_t i2cByteIn(uint8_t bLast)
|
|
||||||
{
|
|
||||||
uint8_t i;
|
|
||||||
uint8_t b = 0;
|
|
||||||
|
|
||||||
SDA_HIGH(); // set data line as input
|
|
||||||
for (i=0; i<8; i++)
|
|
||||||
{
|
|
||||||
ulp_riscv_delay_cycles(I2C_DELAY); // wait for data to settle
|
|
||||||
SCL_HIGH(); // clock high (slave latches data)
|
|
||||||
ulp_riscv_delay_cycles(I2C_DELAY);
|
|
||||||
b <<= 1;
|
|
||||||
if (SDA_READ() != 0) // read the data bit
|
|
||||||
b |= 1; // set data bit
|
|
||||||
SCL_LOW(); // clock low
|
|
||||||
} // for i
|
|
||||||
if (bLast)
|
|
||||||
SDA_HIGH(); // last byte sends a NACK
|
|
||||||
else
|
|
||||||
SDA_LOW();
|
|
||||||
// my_sleep_us(iDelay);
|
|
||||||
SCL_HIGH(); // clock high
|
|
||||||
ulp_riscv_delay_cycles(I2C_DELAY);
|
|
||||||
SCL_LOW(); // clock low to send ack
|
|
||||||
ulp_riscv_delay_cycles(I2C_DELAY);
|
|
||||||
// SDA_HIGH();
|
|
||||||
SDA_LOW(); // data low
|
|
||||||
return b;
|
|
||||||
} /* i2cByteIn() */
|
|
||||||
//
|
|
||||||
// Send I2C STOP condition
|
|
||||||
//
|
|
||||||
void i2cEnd(void)
|
|
||||||
{
|
|
||||||
SDA_LOW(); // data line low
|
|
||||||
ulp_riscv_delay_cycles(I2C_DELAY);
|
|
||||||
SCL_HIGH(); // clock high
|
|
||||||
ulp_riscv_delay_cycles(I2C_DELAY);
|
|
||||||
SDA_HIGH(); // data high
|
|
||||||
ulp_riscv_delay_cycles(I2C_DELAY);
|
|
||||||
} /* i2cEnd() */
|
|
||||||
|
|
||||||
int i2cBegin(uint8_t addr, uint8_t bRead)
|
|
||||||
{
|
|
||||||
int rc;
|
|
||||||
// SCL_HIGH();
|
|
||||||
// my_sleep_us(iDelay);
|
|
||||||
SDA_LOW(); // data line low first
|
|
||||||
ulp_riscv_delay_cycles(I2C_DELAY);
|
|
||||||
SCL_LOW(); // then clock line low is a START signal
|
|
||||||
addr <<= 1;
|
|
||||||
if (bRead)
|
|
||||||
addr++; // set read bit
|
|
||||||
rc = i2cByteOut(addr); // send the slave address and R/W bit
|
|
||||||
return rc;
|
|
||||||
} /* i2cBegin() */
|
|
||||||
void I2CWrite(uint8_t addr, uint8_t *pData, int iLen)
|
|
||||||
{
|
|
||||||
uint8_t b;
|
|
||||||
int rc;
|
|
||||||
|
|
||||||
i2cBegin(addr, 0);
|
|
||||||
rc = 1;
|
|
||||||
while (iLen && rc == 1)
|
|
||||||
{
|
|
||||||
b = *pData++;
|
|
||||||
rc = i2cByteOut(b);
|
|
||||||
if (rc == 1) // success
|
|
||||||
{
|
|
||||||
iLen--;
|
|
||||||
}
|
|
||||||
} // for each byte
|
|
||||||
i2cEnd();
|
|
||||||
//return (rc == 1) ? (iOldLen - iLen) : 0; // 0 indicates bad ack from sending a byte
|
|
||||||
} /* I2CWrite() */
|
|
||||||
int I2CRead(uint8_t addr, uint8_t *pData, int iLen)
|
|
||||||
{
|
|
||||||
i2cBegin(addr, 1);
|
|
||||||
while (iLen--)
|
|
||||||
{
|
|
||||||
*pData++ = i2cByteIn(iLen == 0);
|
|
||||||
} // for each byte
|
|
||||||
i2cEnd();
|
|
||||||
return 1;
|
|
||||||
} /* I2CRead() */
|
|
||||||
|
|
||||||
int I2CTest(uint8_t addr)
|
|
||||||
{
|
|
||||||
int response = 0;
|
|
||||||
|
|
||||||
if (i2cBegin(addr, 0)) // try to write to the given address
|
|
||||||
{
|
|
||||||
response = 1;
|
|
||||||
}
|
|
||||||
i2cEnd();
|
|
||||||
return response;
|
|
||||||
} /* I2CTest() */
|
|
||||||
|
|
||||||
void I2CInit(void)
|
|
||||||
{
|
|
||||||
pinMode(PIN_SDA, INPUT_PULLUP);
|
|
||||||
pinMode(PIN_SCL, INPUT_PULLUP);
|
|
||||||
}
|
|
||||||
void I2CDeInit(void)
|
|
||||||
{
|
|
||||||
pinMode(PIN_SDA, DISABLED);
|
|
||||||
pinMode(PIN_SCL, DISABLED);
|
|
||||||
}
|
|
||||||
//
|
|
||||||
// Read N bytes starting at a specific I2C internal register
|
|
||||||
// returns 1 for success, 0 for error
|
|
||||||
//
|
|
||||||
void I2CReadRegister(uint8_t iAddr, uint8_t u8Register, uint8_t *pData, int iLen)
|
|
||||||
{
|
|
||||||
I2CWrite(iAddr, &u8Register, 1);
|
|
||||||
I2CRead(iAddr, pData, iLen);
|
|
||||||
} /* I2CReadRegister() */
|
|
||||||
|
|
||||||
#endif // __ULP_IO__
|
#endif // __ULP_IO__
|
||||||
|
|||||||
+8
-24
@@ -23,8 +23,15 @@
|
|||||||
//
|
//
|
||||||
// Initialize the GPIO pins and SPI for use by bb_eink
|
// Initialize the GPIO pins and SPI for use by bb_eink
|
||||||
//
|
//
|
||||||
void bbepInitIO(BBEPDISP *pBBEP, uint32_t u32Speed)
|
void bbepInitIO(BBEPDISP *pBBEP, uint8_t u8DC, uint8_t u8RST, uint8_t u8BUSY, uint8_t u8CS, uint8_t u8MOSI, uint8_t u8SCK, uint32_t u32Speed)
|
||||||
{
|
{
|
||||||
|
pBBEP->iDCPin = u8DC;
|
||||||
|
pBBEP->iCSPin = u8CS;
|
||||||
|
pBBEP->iMOSIPin = u8MOSI;
|
||||||
|
pBBEP->iCLKPin = u8SCK;
|
||||||
|
pBBEP->iRSTPin = u8RST;
|
||||||
|
pBBEP->iBUSYPin = u8BUSY;
|
||||||
|
|
||||||
pinMode(pBBEP->iDCPin, OUTPUT);
|
pinMode(pBBEP->iDCPin, OUTPUT);
|
||||||
pinMode(pBBEP->iRSTPin, OUTPUT);
|
pinMode(pBBEP->iRSTPin, OUTPUT);
|
||||||
digitalWrite(pBBEP->iRSTPin, LOW);
|
digitalWrite(pBBEP->iRSTPin, LOW);
|
||||||
@@ -46,29 +53,6 @@ void bbepInitIO(BBEPDISP *pBBEP, uint32_t u32Speed)
|
|||||||
SPI.endTransaction(); // N.B. - if you call beginTransaction() again without a matching endTransaction(), it will hang on ESP32
|
SPI.endTransaction(); // N.B. - if you call beginTransaction() again without a matching endTransaction(), it will hang on ESP32
|
||||||
} /* bbepInitIO() */
|
} /* bbepInitIO() */
|
||||||
//
|
//
|
||||||
// Toggle the reset line to wake up the eink from deep sleep
|
|
||||||
//
|
|
||||||
void bbepWakeUp(BBEPDISP *pBBEP)
|
|
||||||
{
|
|
||||||
digitalWrite(pBBEP->iRSTPin, LOW);
|
|
||||||
delay(10);
|
|
||||||
digitalWrite(pBBEP->iRSTPin, HIGH);
|
|
||||||
delay(10);
|
|
||||||
} /* bbepWakeUp() */
|
|
||||||
//
|
|
||||||
// Wait for the busy status line to show idle
|
|
||||||
// The polarity of the busy signal is reversed on the UC81xx compared
|
|
||||||
// to the SSD16xx controllers
|
|
||||||
//
|
|
||||||
void bbepWaitBusy(BBEPDISP *pBBEP)
|
|
||||||
{
|
|
||||||
uint8_t busy_idle = (pBBEP->chip_type == BBEP_CHIP_UC81xx) ? HIGH : LOW;
|
|
||||||
delay(1); // some panels need a short delay before testing the BUSY line
|
|
||||||
while (1) {
|
|
||||||
if (digitalRead(pBBEP->iBUSYPin) == busy_idle) break;
|
|
||||||
}
|
|
||||||
} /* bbepWaitBusy() */
|
|
||||||
//
|
|
||||||
// Convenience function to write a command byte along with a data
|
// Convenience function to write a command byte along with a data
|
||||||
// byte (it's single parameter)
|
// byte (it's single parameter)
|
||||||
//
|
//
|
||||||
|
|||||||
@@ -971,6 +971,7 @@ const EPD_PANEL panelDefs[] PROGMEM = {
|
|||||||
{240, 416, epd37_init_sequence_full, NULL, epd37_init_sequence_part, 0, BBEP_CHIP_UC81xx}, // EPD37_240x416
|
{240, 416, epd37_init_sequence_full, NULL, epd37_init_sequence_part, 0, BBEP_CHIP_UC81xx}, // EPD37_240x416
|
||||||
{176, 264, epd27_ws_init_sequence_full, NULL, NULL, BBEP_CS_EVERY_BYTE, BBEP_CHIP_UC81xx}, // EPD27_176x264 Waveshare 2.7" e-paper HAT
|
{176, 264, epd27_ws_init_sequence_full, NULL, NULL, BBEP_CS_EVERY_BYTE, BBEP_CHIP_UC81xx}, // EPD27_176x264 Waveshare 2.7" e-paper HAT
|
||||||
};
|
};
|
||||||
|
|
||||||
int bbepSetPanelType(BBEPDISP *pBBEP, int iPanel)
|
int bbepSetPanelType(BBEPDISP *pBBEP, int iPanel)
|
||||||
{
|
{
|
||||||
if (pBBEP == NULL || iPanel <= EPD_PANEL_UNDEFINED || iPanel >= EPD_PANEL_COUNT)
|
if (pBBEP == NULL || iPanel <= EPD_PANEL_UNDEFINED || iPanel >= EPD_PANEL_COUNT)
|
||||||
@@ -988,6 +989,30 @@ int bbepSetPanelType(BBEPDISP *pBBEP, int iPanel)
|
|||||||
return BBEP_SUCCESS;
|
return BBEP_SUCCESS;
|
||||||
} /* bbepSetPanelType() */
|
} /* bbepSetPanelType() */
|
||||||
|
|
||||||
|
//
|
||||||
|
// Toggle the reset line to wake up the eink from deep sleep
|
||||||
|
//
|
||||||
|
void bbepWakeUp(BBEPDISP *pBBEP)
|
||||||
|
{
|
||||||
|
digitalWrite(pBBEP->iRSTPin, LOW);
|
||||||
|
delay(10);
|
||||||
|
digitalWrite(pBBEP->iRSTPin, HIGH);
|
||||||
|
delay(10);
|
||||||
|
} /* bbepWakeUp() */
|
||||||
|
//
|
||||||
|
// Wait for the busy status line to show idle
|
||||||
|
// The polarity of the busy signal is reversed on the UC81xx compared
|
||||||
|
// to the SSD16xx controllers
|
||||||
|
//
|
||||||
|
void bbepWaitBusy(BBEPDISP *pBBEP)
|
||||||
|
{
|
||||||
|
uint8_t busy_idle = (pBBEP->chip_type == BBEP_CHIP_UC81xx) ? HIGH : LOW;
|
||||||
|
delay(1); // some panels need a short delay before testing the BUSY line
|
||||||
|
while (1) {
|
||||||
|
if (digitalRead(pBBEP->iBUSYPin) == busy_idle) break;
|
||||||
|
}
|
||||||
|
} /* bbepWaitBusy() */
|
||||||
|
|
||||||
void bbepSetAddrWindow(BBEPDISP *pBBEP, int x, int y, int cx, int cy)
|
void bbepSetAddrWindow(BBEPDISP *pBBEP, int x, int y, int cx, int cy)
|
||||||
{
|
{
|
||||||
uint8_t uc[12];
|
uint8_t uc[12];
|
||||||
|
|||||||
+21
-7
@@ -14,6 +14,9 @@
|
|||||||
//
|
//
|
||||||
// bb_ei_gfx.inl - graphics functions
|
// bb_ei_gfx.inl - graphics functions
|
||||||
//
|
//
|
||||||
|
// For constrained CPU environments, the NO_RAM macro will be defined
|
||||||
|
// to reduce codespace used by each of the functions
|
||||||
|
//
|
||||||
#ifndef __BB_EP_GFX__
|
#ifndef __BB_EP_GFX__
|
||||||
#define __BB_EP_GFX__
|
#define __BB_EP_GFX__
|
||||||
#include "Group5.h"
|
#include "Group5.h"
|
||||||
@@ -621,15 +624,17 @@ uint8_t *pBits, u8CMD1, u8CMD2, u8CMD, u8EndMask;
|
|||||||
c -= pFont->first; // first char of font defined
|
c -= pFont->first; // first char of font defined
|
||||||
pGlyph = &pFont->glyphs[c]; // glyph info for this character
|
pGlyph = &pFont->glyphs[c]; // glyph info for this character
|
||||||
if (pGlyph->width > 1) { // skip this if drawing a space
|
if (pGlyph->width > 1) { // skip this if drawing a space
|
||||||
dx = x + pGlyph->xOffset; // offset from character UL to start drawing
|
|
||||||
dy = y + pGlyph->yOffset;
|
|
||||||
s = pBits + pGlyph->bitmapOffset; // start of compressed bitmap data
|
s = pBits + pGlyph->bitmapOffset; // start of compressed bitmap data
|
||||||
if (pFont->rotation == 0 || pFont->rotation == 180) {
|
if (pFont->rotation == 0 || pFont->rotation == 180) {
|
||||||
h = pGlyph->height;
|
h = pGlyph->height;
|
||||||
w = pGlyph->width;
|
w = pGlyph->width;
|
||||||
|
dx = x + pGlyph->xOffset; // offset from character UL to start drawing
|
||||||
|
dy = y + pGlyph->yOffset;
|
||||||
} else { // rotated
|
} else { // rotated
|
||||||
w = pGlyph->height;
|
w = pGlyph->height;
|
||||||
h = pGlyph->width;
|
h = pGlyph->width;
|
||||||
|
dx = x + pGlyph->yOffset; // offset from character UL to start drawing
|
||||||
|
dy = y + pGlyph->xOffset;
|
||||||
}
|
}
|
||||||
if ((dy + h) > pBBEP->native_height) { // trim it
|
if ((dy + h) > pBBEP->native_height) { // trim it
|
||||||
h = pBBEP->native_height - dy;
|
h = pBBEP->native_height - dy;
|
||||||
@@ -644,6 +649,7 @@ uint8_t *pBits, u8CMD1, u8CMD2, u8CMD, u8EndMask;
|
|||||||
rc = g5_decode_init(&g5dec, w, h, s, ty);
|
rc = g5_decode_init(&g5dec, w, h, s, ty);
|
||||||
if (rc != G5_SUCCESS) return; // corrupt data?
|
if (rc != G5_SUCCESS) return; // corrupt data?
|
||||||
if (pBBEP->ucScreen) { // backbuffer, draw pixels
|
if (pBBEP->ucScreen) { // backbuffer, draw pixels
|
||||||
|
#ifndef NO_RAM
|
||||||
for (ty=dy; ty<end_y && ty < pBBEP->native_height; ty++) {
|
for (ty=dy; ty<end_y && ty < pBBEP->native_height; ty++) {
|
||||||
uint8_t u8, u8Count;
|
uint8_t u8, u8Count;
|
||||||
g5_decode_line(&g5dec, u8Cache);
|
g5_decode_line(&g5dec, u8Cache);
|
||||||
@@ -662,6 +668,7 @@ uint8_t *pBits, u8CMD1, u8CMD2, u8CMD, u8EndMask;
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif // NO_RAM
|
||||||
} else { // draw directly into EPD memory
|
} else { // draw directly into EPD memory
|
||||||
// set the memory window for this character
|
// set the memory window for this character
|
||||||
iSrcPitch = (w+7)/8;
|
iSrcPitch = (w+7)/8;
|
||||||
@@ -751,10 +758,6 @@ uint8_t u8Temp[128];
|
|||||||
if (iSize == FONT_8x8) // 8x8 font
|
if (iSize == FONT_8x8) // 8x8 font
|
||||||
{
|
{
|
||||||
i = 0;
|
i = 0;
|
||||||
if (!pBBEP->ucScreen) { // bufferless mode, rotate the coordinate system to fit the situation
|
|
||||||
// bbepSetAddrWindow(pBBEP, √, pBBEP->iCursorX, 8, pBBEP->native_height-pBBEP->iCursorX);
|
|
||||||
// bbepWriteCmd(pBBEP, ucCMD1); // write to "new" plane
|
|
||||||
}
|
|
||||||
while (pBBEP->iCursorX < pBBEP->width && szMsg[i] != 0 && pBBEP->iCursorY < pBBEP->height)
|
while (pBBEP->iCursorX < pBBEP->width && szMsg[i] != 0 && pBBEP->iCursorY < pBBEP->height)
|
||||||
{
|
{
|
||||||
c = (unsigned char)szMsg[i];
|
c = (unsigned char)szMsg[i];
|
||||||
@@ -772,7 +775,9 @@ uint8_t u8Temp[128];
|
|||||||
bbepWriteCmd(pBBEP, ucCMD); // write to "new" plane
|
bbepWriteCmd(pBBEP, ucCMD); // write to "new" plane
|
||||||
bbepWriteData(pBBEP, u8Temp, iLen);
|
bbepWriteData(pBBEP, u8Temp, iLen);
|
||||||
} else { // draw in memory
|
} else { // draw in memory
|
||||||
|
#ifndef NO_RAM
|
||||||
// DEBUG
|
// DEBUG
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
pBBEP->iCursorX += iLen;
|
pBBEP->iCursorX += iLen;
|
||||||
if (pBBEP->iCursorX >= pBBEP->width-7 && pBBEP->wrap) { // word wrap enabled?
|
if (pBBEP->iCursorX >= pBBEP->width-7 && pBBEP->wrap) { // word wrap enabled?
|
||||||
@@ -905,7 +910,9 @@ uint8_t u8Temp[128];
|
|||||||
bbepWriteCmd(pBBEP, ucCMD); // write to "new" plane
|
bbepWriteCmd(pBBEP, ucCMD); // write to "new" plane
|
||||||
bbepWriteData(pBBEP, &u8Temp[18], iLen);
|
bbepWriteData(pBBEP, &u8Temp[18], iLen);
|
||||||
} else { // write to RAM
|
} else { // write to RAM
|
||||||
|
#ifndef NO_RAM
|
||||||
// DEBUG
|
// DEBUG
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
pBBEP->iCursorX += iLen;
|
pBBEP->iCursorX += iLen;
|
||||||
if (pBBEP->iCursorX >= pBBEP->width-11 && pBBEP->wrap) // word wrap enabled?
|
if (pBBEP->iCursorX >= pBBEP->width-11 && pBBEP->wrap) // word wrap enabled?
|
||||||
@@ -936,7 +943,9 @@ uint8_t u8Temp[128];
|
|||||||
bbepWriteCmd(pBBEP, ucCMD); // write to "new" plane
|
bbepWriteCmd(pBBEP, ucCMD); // write to "new" plane
|
||||||
bbepWriteData(pBBEP, u8Temp, iLen);
|
bbepWriteData(pBBEP, u8Temp, iLen);
|
||||||
} else { // write to RAM
|
} else { // write to RAM
|
||||||
|
#ifndef NO_RAM
|
||||||
// DEBUG
|
// DEBUG
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
pBBEP->iCursorX += iLen;
|
pBBEP->iCursorX += iLen;
|
||||||
if (pBBEP->iCursorX >= pBBEP->width-5 && pBBEP->wrap) // word wrap enabled?
|
if (pBBEP->iCursorX >= pBBEP->width-5 && pBBEP->wrap) // word wrap enabled?
|
||||||
@@ -981,8 +990,10 @@ int miny, maxy;
|
|||||||
|
|
||||||
void bbepAllocBuffer(BBEPDISP *pBBEP)
|
void bbepAllocBuffer(BBEPDISP *pBBEP)
|
||||||
{
|
{
|
||||||
|
#ifndef NO_RAM
|
||||||
pBBEP->ucScreen = (uint8_t *)malloc(pBBEP->width * ((pBBEP->height+7)>>3));
|
pBBEP->ucScreen = (uint8_t *)malloc(pBBEP->width * ((pBBEP->height+7)>>3));
|
||||||
pBBEP->iScreenOffset = 0;
|
pBBEP->iScreenOffset = 0;
|
||||||
|
#endif
|
||||||
} /* obdAllocBuffer() */
|
} /* obdAllocBuffer() */
|
||||||
|
|
||||||
void bbepDrawLine(BBEPDISP *pBBEP, int x1, int y1, int x2, int y2, uint8_t ucColor)
|
void bbepDrawLine(BBEPDISP *pBBEP, int x1, int y1, int x2, int y2, uint8_t ucColor)
|
||||||
@@ -1334,6 +1345,7 @@ void bbepRectangle(BBEPDISP *pBBEP, int x1, int y1, int x2, int y2, uint8_t ucCo
|
|||||||
}
|
}
|
||||||
if (bFilled)
|
if (bFilled)
|
||||||
{
|
{
|
||||||
|
#ifndef NO_RAM
|
||||||
if (pBBEP->ucScreen) { // has a buffer to fill
|
if (pBBEP->ucScreen) { // has a buffer to fill
|
||||||
int x, y, iMiddle;
|
int x, y, iMiddle;
|
||||||
iMiddle = (y2 >> 3) - (y1 >> 3);
|
iMiddle = (y2 >> 3) - (y1 >> 3);
|
||||||
@@ -1367,7 +1379,9 @@ void bbepRectangle(BBEPDISP *pBBEP, int x1, int y1, int x2, int y2, uint8_t ucCo
|
|||||||
*d++ &= ~ucMask;
|
*d++ &= ~ucMask;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else { // no buffer
|
} else
|
||||||
|
#endif // NO_RAM
|
||||||
|
{ // no buffer
|
||||||
int cx, cy, iPitch;
|
int cx, cy, iPitch;
|
||||||
cx = x2-x1+1;
|
cx = x2-x1+1;
|
||||||
iPitch = (cx+7)/8;
|
iPitch = (cx+7)/8;
|
||||||
|
|||||||
+1
-7
@@ -63,13 +63,7 @@ void BBEPAPER::setAddrWindow(int x, int y, int w, int h)
|
|||||||
#ifdef ARDUINO
|
#ifdef ARDUINO
|
||||||
void BBEPAPER::initIO(int iDC, int iReset, int iBusy, int iCS, int iMOSI, int iSCLK, uint32_t u32Speed)
|
void BBEPAPER::initIO(int iDC, int iReset, int iBusy, int iCS, int iMOSI, int iSCLK, uint32_t u32Speed)
|
||||||
{
|
{
|
||||||
_bbep.iCSPin = iCS;
|
bbepInitIO(&_bbep, iDC, iReset, iBusy, iCS, iMOSI, iSCLK, u32Speed);
|
||||||
_bbep.iMOSIPin = iMOSI;
|
|
||||||
_bbep.iCLKPin = iSCLK;
|
|
||||||
_bbep.iDCPin = iDC;
|
|
||||||
_bbep.iRSTPin = iReset;
|
|
||||||
_bbep.iBUSYPin = iBusy;
|
|
||||||
bbepInitIO(&_bbep, u32Speed);
|
|
||||||
bbepWakeUp(&_bbep);
|
bbepWakeUp(&_bbep);
|
||||||
bbepSendCMDSequence(&_bbep, _bbep.pInitFull);
|
bbepSendCMDSequence(&_bbep, _bbep.pInitFull);
|
||||||
} /* initIO() */
|
} /* initIO() */
|
||||||
|
|||||||
Reference in New Issue
Block a user