diff --git a/.gitignore b/.gitignore index f914f87..f6d3396 100644 --- a/.gitignore +++ b/.gitignore @@ -78,6 +78,9 @@ _build/ *.l2p *.iex +# Vscode config files +.vscode/ + # To explicitly override the above, define any exceptions here; e.g.: # !my_customized_scatter_file.sct diff --git a/EPD/EPD_driver.c b/EPD/EPD_driver.c index 937ca59..25967f6 100644 --- a/EPD/EPD_driver.c +++ b/EPD/EPD_driver.c @@ -187,20 +187,22 @@ void EPD_FillRAM(uint8_t cmd, uint8_t value, uint32_t len) { } } -void EPD_Reset(uint32_t value, uint16_t duration) { - digitalWrite(EPD_RST_PIN, value); +void EPD_Reset(bool status, uint16_t duration) { + digitalWrite(EPD_RST_PIN, status); delay(duration); - digitalWrite(EPD_RST_PIN, (value == LOW) ? HIGH : LOW); + digitalWrite(EPD_RST_PIN, status ? LOW : HIGH); delay(duration); - digitalWrite(EPD_RST_PIN, value); + digitalWrite(EPD_RST_PIN, status); delay(duration); } -void EPD_WaitBusy(uint32_t value, uint16_t timeout) { +bool EPD_ReadBusy(void) { return digitalRead(EPD_BUSY_PIN); } + +void EPD_WaitBusy(bool status, uint16_t timeout) { uint32_t led_status = digitalRead(EPD_LED_PIN); NRF_LOG_DEBUG("[EPD]: check busy\n"); - while (digitalRead(EPD_BUSY_PIN) == value) { + while (EPD_ReadBusy() == status) { if (timeout % 100 == 0) EPD_LED_Toggle(); delay(1); timeout--; @@ -303,10 +305,9 @@ extern epd_model_t epd_jd79665_750_bwry; extern epd_model_t epd_jd79665_583_bwry; static epd_model_t* epd_models[] = { - &epd_uc8176_420_bw, &epd_uc8176_420_bwr, &epd_uc8159_750_bw, &epd_uc8159_750_bwr, - &epd_uc8179_750_bw, &epd_uc8179_750_bwr, &epd_ssd1619_420_bwr, &epd_ssd1619_420_bw, - &epd_ssd1677_750_bwr, &epd_ssd1677_750_bw, &epd_jd79668_420_bwry, &epd_jd79665_750_bwry, - &epd_jd79665_583_bwry, + &epd_uc8176_420_bw, &epd_uc8176_420_bwr, &epd_uc8159_750_bw, &epd_uc8159_750_bwr, &epd_uc8179_750_bw, + &epd_uc8179_750_bwr, &epd_ssd1619_420_bwr, &epd_ssd1619_420_bw, &epd_ssd1677_750_bwr, &epd_ssd1677_750_bw, + &epd_jd79668_420_bwry, &epd_jd79665_750_bwry, &epd_jd79665_583_bwry, }; epd_model_t* epd_init(epd_model_id_t id) { diff --git a/EPD/EPD_driver.h b/EPD/EPD_driver.h index 8c7a82b..97e3904 100644 --- a/EPD/EPD_driver.h +++ b/EPD/EPD_driver.h @@ -9,17 +9,6 @@ #include "nrf_delay.h" #include "nrf_gpio.h" -// EPD driver IC types -typedef enum { - EPD_DRIVER_IC_UC8159 = 0x10, - EPD_DRIVER_IC_UC8176 = 0x11, - EPD_DRIVER_IC_UC8179 = 0x12, - EPD_DRIVER_IC_SSD1619 = 0x20, - EPD_DRIVER_IC_SSD1677 = 0x21, - EPD_DRIVER_IC_JD79668 = 0x30, - EPD_DRIVER_IC_JD79665 = 0x31, -} epd_driver_ic_t; - // UC81xx commands enum { UC81xx_PSR = 0x00, // Panel Setting @@ -121,36 +110,48 @@ enum { }; typedef enum { - BW = 1, - BWR = 2, - BWRY = 3, + COLOR_BW = 1, + COLOR_BWR = 2, + COLOR_BWRY = 3, } epd_color_t; +// EPD driver IC types +typedef enum { + DRV_IC_UC8159 = 0x10, + DRV_IC_UC8176 = 0x11, + DRV_IC_UC8179 = 0x12, + DRV_IC_SSD1619 = 0x20, + DRV_IC_SSD1677 = 0x21, + DRV_IC_JD79668 = 0x30, + DRV_IC_JD79665 = 0x31, +} epd_drv_ic_t; + // Do not change the existing IDs! typedef enum { - EPD_UC8176_420_BW = 1, - EPD_UC8176_420_BWR = 3, - EPD_SSD1619_420_BWR = 2, - EPD_SSD1619_420_BW = 4, - EPD_JD79668_420_BWRY = 5, - EPD_UC8179_750_BW = 6, - EPD_UC8179_750_BWR = 7, - EPD_UC8159_750_LOW_BW = 8, - EPD_UC8159_750_LOW_BWR = 9, - EPD_SSD1677_750_HD_BW = 10, - EPD_SSD1677_750_HD_BWR = 11, - EPD_JD79665_750_BWRY = 12, - EPD_JD79665_583_BWRY = 13, + UC8176_420_BW = 1, + UC8176_420_BWR = 3, + SSD1619_420_BWR = 2, + SSD1619_420_BW = 4, + JD79668_420_BWRY = 5, + UC8179_750_BW = 6, + UC8179_750_BWR = 7, + UC8159_750_LOW_BW = 8, + UC8159_750_LOW_BWR = 9, + SSD1677_750_HD_BW = 10, + SSD1677_750_HD_BWR = 11, + JD79665_750_BWRY = 12, + JD79665_583_BWRY = 13, } epd_model_id_t; struct epd_driver; typedef struct { - epd_model_id_t id; - epd_color_t color; - struct epd_driver* drv; - uint16_t width; - uint16_t height; + const epd_model_id_t id; + const epd_color_t color; + const struct epd_driver* drv; + const epd_drv_ic_t ic; + const uint16_t width; + const uint16_t height; } epd_model_t; /**@brief EPD driver structure. @@ -158,7 +159,6 @@ typedef struct { * @details This structure contains epd driver functions. */ typedef struct epd_driver { - epd_driver_ic_t ic; /**< EPD driver IC type */ void (*init)(epd_model_t* epd); /**< Initialize the e-Paper register */ void (*clear)(epd_model_t* epd, bool refresh); /**< Clear screen */ void (*write_image)(epd_model_t* epd, uint8_t* black, uint8_t* color, uint16_t x, uint16_t y, uint16_t w, @@ -167,6 +167,7 @@ typedef struct epd_driver { void (*refresh)(epd_model_t* epd); /**< Sends the image buffer in RAM to e-Paper and displays */ void (*sleep)(epd_model_t* epd); /**< Enter sleep mode */ int8_t (*read_temp)(epd_model_t* epd); /**< Read temperature from driver chip */ + bool (*read_busy)(epd_model_t* epd); /**< Read busy pin level */ } epd_driver_t; #define LOW (0x0) @@ -206,8 +207,9 @@ uint8_t EPD_ReadByte(void); EPD_WriteData(_data, sizeof(_data)); \ } while (0) void EPD_FillRAM(uint8_t cmd, uint8_t value, uint32_t len); -void EPD_Reset(uint32_t value, uint16_t duration); -void EPD_WaitBusy(uint32_t value, uint16_t timeout); +void EPD_Reset(bool status, uint16_t duration); +bool EPD_ReadBusy(void); +void EPD_WaitBusy(bool status, uint16_t timeout); // LED void EPD_LED_ON(void); diff --git a/EPD/SSD16xx.c b/EPD/SSD16xx.c index c6dde76..9afe3ef 100644 --- a/EPD/SSD16xx.c +++ b/EPD/SSD16xx.c @@ -1,7 +1,9 @@ #include "EPD_driver.h" #include "nrf_log.h" -static void SSD16xx_WaitBusy(uint16_t timeout) { EPD_WaitBusy(HIGH, timeout); } +bool SSD16xx_ReadBusy(epd_model_t* epd) { return EPD_ReadBusy(); } + +static void SSD16xx_WaitBusy(uint16_t timeout) { EPD_WaitBusy(true, timeout); } static void SSD16xx_Update(uint8_t seq) { EPD_Write(SSD16xx_DISP_CTRL2, seq); @@ -17,18 +19,20 @@ int8_t SSD16xx_Read_Temp(epd_model_t* epd) { static void _setPartialRamArea(epd_model_t* epd, uint16_t x, uint16_t y, uint16_t w, uint16_t h) { EPD_Write(SSD16xx_ENTRY_MODE, 0x03); // set ram entry mode: x increase, y increase - if (epd->drv->ic == EPD_DRIVER_IC_SSD1677) { - EPD_Write(SSD16xx_RAM_XPOS, x % 256, x / 256, (x + w - 1) % 256, (x + w - 1) / 256); - EPD_Write(SSD16xx_RAM_XCOUNT, x % 256, x / 256); - } else { - EPD_Write(SSD16xx_RAM_XPOS, x / 8, (x + w - 1) / 8); - EPD_Write(SSD16xx_RAM_YPOS, y % 256, y / 256, (y + h - 1) % 256, (y + h - 1) / 256); - EPD_Write(SSD16xx_RAM_XCOUNT, x / 8); + switch (epd->ic) { + case DRV_IC_SSD1677: + EPD_Write(SSD16xx_RAM_XPOS, x % 256, x / 256, (x + w - 1) % 256, (x + w - 1) / 256); + EPD_Write(SSD16xx_RAM_XCOUNT, x % 256, x / 256); + break; + default: + EPD_Write(SSD16xx_RAM_XPOS, x / 8, (x + w - 1) / 8); + EPD_Write(SSD16xx_RAM_YPOS, y % 256, y / 256, (y + h - 1) % 256, (y + h - 1) / 256); + EPD_Write(SSD16xx_RAM_XCOUNT, x / 8); + break; } EPD_Write(SSD16xx_RAM_YPOS, y % 256, y / 256, (y + h - 1) % 256, (y + h - 1) / 256); EPD_Write(SSD16xx_RAM_YCOUNT, y % 256, y / 256); } - void SSD16xx_Dump_LUT(void) { uint8_t lut[128]; @@ -41,7 +45,7 @@ void SSD16xx_Dump_LUT(void) { } void SSD16xx_Init(epd_model_t* epd) { - EPD_Reset(HIGH, 10); + EPD_Reset(true, 10); EPD_WriteCmd(SSD16xx_SW_RESET); SSD16xx_WaitBusy(200); @@ -53,7 +57,7 @@ void SSD16xx_Init(epd_model_t* epd) { } static void SSD16xx_Refresh(epd_model_t* epd) { - EPD_Write(SSD16xx_DISP_CTRL1, epd->color == BWR ? 0x80 : 0x40, 0x00); + EPD_Write(SSD16xx_DISP_CTRL1, epd->color == COLOR_BWR ? 0x80 : 0x40, 0x00); NRF_LOG_DEBUG("[EPD]: refresh begin\n"); NRF_LOG_DEBUG("[EPD]: temperature: %d\n", SSD16xx_Read_Temp(epd)); @@ -64,7 +68,6 @@ static void SSD16xx_Refresh(epd_model_t* epd) { // SSD16xx_Dump_LUT(); _setPartialRamArea(epd, 0, 0, epd->width, epd->height); // DO NOT REMOVE! - SSD16xx_Update(0x83); // power off } void SSD16xx_Clear(epd_model_t* epd, bool refresh) { @@ -93,7 +96,7 @@ void SSD16xx_Write_Image(epd_model_t* epd, uint8_t* black, uint8_t* color, uint1 EPD_WriteCmd(SSD16xx_WRITE_RAM2); for (uint16_t i = 0; i < h; i++) { for (uint16_t j = 0; j < w / 8; j++) { - if (epd->color == BWR) + if (epd->color == COLOR_BWR) EPD_WriteByte(color ? color[j + i * wb] : 0xFF); else EPD_WriteByte(black[j + i * wb]); @@ -105,7 +108,7 @@ void SSD16xx_Write_Ram(epd_model_t* epd, uint8_t cfg, uint8_t* data, uint8_t len bool begin = (cfg >> 4) == 0x00; bool black = (cfg & 0x0F) == 0x0F; if (begin) { - if (epd->color == BWR) + if (epd->color == COLOR_BWR) EPD_WriteCmd(black ? SSD16xx_WRITE_RAM1 : SSD16xx_WRITE_RAM2); else EPD_WriteCmd(SSD16xx_WRITE_RAM1); @@ -118,19 +121,7 @@ void SSD16xx_Sleep(epd_model_t* epd) { delay(100); } -static epd_driver_t epd_drv_ssd1619 = { - .ic = EPD_DRIVER_IC_SSD1619, - .init = SSD16xx_Init, - .clear = SSD16xx_Clear, - .write_image = SSD16xx_Write_Image, - .write_ram = SSD16xx_Write_Ram, - .refresh = SSD16xx_Refresh, - .sleep = SSD16xx_Sleep, - .read_temp = SSD16xx_Read_Temp, -}; - -static epd_driver_t epd_drv_ssd1677 = { - .ic = EPD_DRIVER_IC_SSD1677, +static const epd_driver_t epd_drv_ssd16xx = { .init = SSD16xx_Init, .clear = SSD16xx_Clear, .write_image = SSD16xx_Write_Image, @@ -138,13 +129,14 @@ static epd_driver_t epd_drv_ssd1677 = { .refresh = SSD16xx_Refresh, .sleep = SSD16xx_Sleep, .read_temp = SSD16xx_Read_Temp, + .read_busy = SSD16xx_ReadBusy, }; // SSD1619 400x300 Black/White/Red -const epd_model_t epd_ssd1619_420_bwr = {EPD_SSD1619_420_BWR, BWR, &epd_drv_ssd1619, 400, 300}; +const epd_model_t epd_ssd1619_420_bwr = {SSD1619_420_BWR, COLOR_BWR, &epd_drv_ssd16xx, DRV_IC_SSD1619, 400, 300}; // SSD1619 400x300 Black/White -const epd_model_t epd_ssd1619_420_bw = {EPD_SSD1619_420_BW, BW, &epd_drv_ssd1619, 400, 300}; +const epd_model_t epd_ssd1619_420_bw = {SSD1619_420_BW, COLOR_BW, &epd_drv_ssd16xx, DRV_IC_SSD1619, 400, 300}; // SSD1677 880x528 Black/White/Red -const epd_model_t epd_ssd1677_750_bwr = {EPD_SSD1677_750_HD_BWR, BWR, &epd_drv_ssd1677, 880, 528}; +const epd_model_t epd_ssd1677_750_bwr = {SSD1677_750_HD_BWR, COLOR_BWR, &epd_drv_ssd16xx, DRV_IC_SSD1677, 880, 528}; // SSD1677 880x528 Black/White -const epd_model_t epd_ssd1677_750_bw = {EPD_SSD1677_750_HD_BW, BW, &epd_drv_ssd1677, 880, 528}; +const epd_model_t epd_ssd1677_750_bw = {SSD1677_750_HD_BW, COLOR_BW, &epd_drv_ssd16xx, DRV_IC_SSD1677, 880, 528}; diff --git a/EPD/UC81xx.c b/EPD/UC81xx.c index 5af65ca..02d6390 100644 --- a/EPD/UC81xx.c +++ b/EPD/UC81xx.c @@ -1,7 +1,9 @@ #include "EPD_driver.h" #include "nrf_log.h" -static void UC81xx_WaitBusy(uint16_t timeout) { EPD_WaitBusy(LOW, timeout); } +bool UC81xx_ReadBusy(epd_model_t* epd) { return EPD_ReadBusy() == false; } + +static void UC81xx_WaitBusy(uint16_t timeout) { EPD_WaitBusy(false, timeout); } static void UC81xx_PowerOn(epd_model_t* epd) { EPD_WriteCmd(UC81xx_PON); @@ -9,10 +11,8 @@ static void UC81xx_PowerOn(epd_model_t* epd) { } static void UC81xx_PowerOff(epd_model_t* epd) { - if (epd->drv->ic == EPD_DRIVER_IC_JD79665) - EPD_Write(UC81xx_POF, 0x00); - else - EPD_WriteCmd(UC81xx_POF); + EPD_WriteCmd(UC81xx_POF); + if (epd->color == COLOR_BWRY) EPD_WriteByte(0x00); UC81xx_WaitBusy(200); } @@ -24,40 +24,39 @@ int8_t UC81xx_Read_Temp(epd_model_t* epd) { } static void _setPartialRamArea(epd_model_t* epd, uint16_t x, uint16_t y, uint16_t w, uint16_t h) { - if (epd->drv->ic == EPD_DRIVER_IC_JD79668 || epd->drv->ic == EPD_DRIVER_IC_JD79665) { - EPD_Write(0x83, // partial window - x / 256, x % 256, (x + w - 1) / 256, (x + w - 1) % 256, y / 256, y % 256, (y + h - 1) / 256, - (y + h - 1) % 256, 0x01); - } else { - uint16_t xe = (x + w - 1) | 0x0007; // byte boundary inclusive (last byte) - uint16_t ye = y + h - 1; - x &= 0xFFF8; // byte boundary - EPD_Write(UC81xx_PTL, // partial window - x / 256, x % 256, xe / 256, xe % 256, y / 256, y % 256, ye / 256, ye % 256, 0x00); + switch (epd->ic) { + case DRV_IC_JD79668: + case DRV_IC_JD79665: + EPD_Write(0x83, // partial window + x / 256, x % 256, (x + w - 1) / 256, (x + w - 1) % 256, y / 256, y % 256, (y + h - 1) / 256, + (y + h - 1) % 256, 0x01); + break; + default: { + uint16_t xe = (x + w - 1) | 0x0007; // byte boundary inclusive (last byte) + uint16_t ye = y + h - 1; + x &= 0xFFF8; // byte boundary + EPD_Write(UC81xx_PTL, // partial window + x / 256, x % 256, xe / 256, xe % 256, y / 256, y % 256, ye / 256, ye % 256, 0x00); + } break; } } void UC81xx_Refresh(epd_model_t* epd) { NRF_LOG_DEBUG("[EPD]: refresh begin\n"); - if (epd->drv->ic != EPD_DRIVER_IC_JD79668 && epd->drv->ic != EPD_DRIVER_IC_JD79665) UC81xx_PowerOn(epd); _setPartialRamArea(epd, 0, 0, epd->width, epd->height); EPD_WriteCmd(UC81xx_DRF); - if (epd->drv->ic == EPD_DRIVER_IC_JD79668 || epd->drv->ic == EPD_DRIVER_IC_JD79665) { - EPD_WriteByte(0x00); - } + if (epd->color == COLOR_BWRY) EPD_WriteByte(0x00); delay(100); UC81xx_WaitBusy(30000); - if (epd->drv->ic != EPD_DRIVER_IC_JD79668 && epd->drv->ic != EPD_DRIVER_IC_JD79665) UC81xx_PowerOff(epd); NRF_LOG_DEBUG("[EPD]: refresh end\n"); } void UC81xx_Dump_OTP(epd_model_t* epd) { uint8_t data[128]; - UC81xx_PowerOn(epd); EPD_Write(UC81xx_ROTP, 0x00); NRF_LOG_DEBUG("=== OTP BEGIN ===\n"); @@ -66,118 +65,94 @@ void UC81xx_Dump_OTP(epd_model_t* epd) { NRF_LOG_HEXDUMP_DEBUG(data, sizeof(data)); } NRF_LOG_DEBUG("=== OTP END ===\n"); - - UC81xx_PowerOff(epd); } void UC81xx_Init(epd_model_t* epd) { - EPD_Reset(HIGH, 10); - - // UC81xx_Dump_OTP(epd); - - EPD_Write(UC81xx_PSR, epd->color == BWR ? 0x0F : 0x1F); - EPD_Write(UC81xx_CDI, epd->color == BWR ? 0x77 : 0x97); -} - -void UC8159_Init(epd_model_t* epd) { - EPD_Reset(HIGH, 10); - - EPD_Write(UC81xx_PWR, 0x37, 0x00); - EPD_Write(UC81xx_PSR, 0xCF, 0x08); - EPD_Write(UC81xx_PLL, 0x3A); - EPD_Write(UC81xx_VDCS, 0x28); - EPD_Write(UC81xx_BTST, 0xc7, 0xcc, 0x15); - EPD_Write(UC81xx_CDI, 0x77); - EPD_Write(UC81xx_TCON, 0x22); - EPD_Write(0x65, 0x00); // FLASH CONTROL - EPD_Write(0xe5, 0x03); // FLASH MODE - EPD_Write(UC81xx_TRES, epd->width >> 8, epd->width & 0xff, epd->height >> 8, epd->height & 0xff); -} - -void JD79668_Init(epd_model_t* epd) { - EPD_Reset(HIGH, 50); - - EPD_Write(0x4D, 0x78); - EPD_Write(UC81xx_PSR, 0x0F, 0x29); - EPD_Write(UC81xx_BTST, 0x0D, 0x12, 0x24, 0x25, 0x12, 0x29, 0x10); - EPD_Write(UC81xx_PLL, 0x08); - EPD_Write(UC81xx_CDI, 0x37); - EPD_Write(UC81xx_TRES, epd->width / 256, epd->width % 256, epd->height / 256, epd->height % 256); - - EPD_Write(0xAE, 0xCF); - EPD_Write(0xB0, 0x13); - EPD_Write(0xBD, 0x07); - EPD_Write(0xBE, 0xFE); - EPD_Write(0xE9, 0x01); - - UC81xx_PowerOn(epd); -} - -void JD79665_Init(epd_model_t* epd) { - EPD_Reset(HIGH, 50); - UC81xx_WaitBusy(1000); - - EPD_Write(0x4D, 0x78); - EPD_Write(UC81xx_PSR, 0x2F, 0x29); - EPD_Write(UC81xx_BTST, 0x0F, 0x8B, 0x93, 0xA1); - EPD_Write(UC81xx_TSE, 0x00); - EPD_Write(UC81xx_CDI, 0x37); - EPD_Write(UC81xx_TCON, 0x02, 0x02); - EPD_Write(UC81xx_TRES, epd->width / 256, epd->width % 256, epd->height / 256, epd->height % 256); - EPD_Write(0x62, 0x98, 0x98, 0x98, 0x75, 0xCA, 0xB2, 0x98, 0x7E); - - if (epd->id == EPD_JD79665_750_BWRY) { - EPD_Write(UC81xx_GSST, 0x00, 0x00, 0x00, 0x00); - } else { - EPD_Write(UC81xx_GSST, 0x00, 0x10, 0x00, 0x00); + EPD_Reset(true, 10); + switch (epd->ic) { + case DRV_IC_UC8159: + EPD_Write(UC81xx_PWR, 0x37, 0x00); + EPD_Write(UC81xx_PSR, 0xCF, 0x08); + EPD_Write(UC81xx_PLL, 0x3A); + EPD_Write(UC81xx_VDCS, 0x28); + EPD_Write(UC81xx_BTST, 0xc7, 0xcc, 0x15); + EPD_Write(UC81xx_CDI, 0x77); + EPD_Write(UC81xx_TCON, 0x22); + EPD_Write(0x65, 0x00); // FLASH CONTROL + EPD_Write(0xe5, 0x03); // FLASH MODE + EPD_Write(UC81xx_TRES, epd->width >> 8, epd->width & 0xff, epd->height >> 8, epd->height & 0xff); + break; + case DRV_IC_JD79668: + EPD_Write(0x4D, 0x78); + EPD_Write(UC81xx_PSR, 0x0F, 0x29); + EPD_Write(UC81xx_BTST, 0x0D, 0x12, 0x24, 0x25, 0x12, 0x29, 0x10); + EPD_Write(UC81xx_PLL, 0x08); + EPD_Write(UC81xx_CDI, 0x37); + EPD_Write(UC81xx_TRES, epd->width / 256, epd->width % 256, epd->height / 256, epd->height % 256); + EPD_Write(0xAE, 0xCF); + EPD_Write(0xB0, 0x13); + EPD_Write(0xBD, 0x07); + EPD_Write(0xBE, 0xFE); + EPD_Write(0xE9, 0x01); + break; + case DRV_IC_JD79665: + EPD_Write(0x4D, 0x78); + EPD_Write(UC81xx_PSR, 0x2F, 0x29); + EPD_Write(UC81xx_BTST, 0x0F, 0x8B, 0x93, 0xA1); + EPD_Write(UC81xx_TSE, 0x00); + EPD_Write(UC81xx_CDI, 0x37); + EPD_Write(UC81xx_TCON, 0x02, 0x02); + EPD_Write(UC81xx_TRES, epd->width / 256, epd->width % 256, epd->height / 256, epd->height % 256); + EPD_Write(0x62, 0x98, 0x98, 0x98, 0x75, 0xCA, 0xB2, 0x98, 0x7E); + if (epd->id == JD79665_750_BWRY) + EPD_Write(UC81xx_GSST, 0x00, 0x00, 0x00, 0x00); + else + EPD_Write(UC81xx_GSST, 0x00, 0x10, 0x00, 0x00); + EPD_Write(0xE7, 0x1C); + EPD_Write(UC81xx_PWS, 0x00); + EPD_Write(0xE9, 0x01); + EPD_Write(UC81xx_PLL, 0x08); + break; + default: + EPD_Write(UC81xx_PSR, epd->color == COLOR_BWR ? 0x0F : 0x1F); + EPD_Write(UC81xx_CDI, epd->color == COLOR_BWR ? 0x77 : 0x97); + break; } - - EPD_Write(0xE7, 0x1C); - EPD_Write(UC81xx_PWS, 0x00); - EPD_Write(0xE9, 0x01); - EPD_Write(UC81xx_PLL, 0x08); - UC81xx_PowerOn(epd); } void UC81xx_Clear(epd_model_t* epd, bool refresh) { - uint32_t ram_bytes = ((epd->width + 7) / 8) * epd->height; - - EPD_FillRAM(UC81xx_DTM1, 0xFF, ram_bytes); - EPD_FillRAM(UC81xx_DTM2, 0xFF, ram_bytes); - - if (refresh) UC81xx_Refresh(epd); -} - -void UC8159_Clear(epd_model_t* epd, bool refresh) { uint32_t wb = (epd->width + 7) / 8; - - EPD_WriteCmd(UC81xx_DTM1); - for (uint32_t j = 0; j < epd->height; j++) { - for (uint32_t i = 0; i < wb; i++) { - for (uint8_t k = 0; k < 4; k++) { - EPD_WriteByte(0x33); + switch (epd->ic) { + case DRV_IC_UC8159: + EPD_WriteCmd(UC81xx_DTM1); + for (uint32_t j = 0; j < epd->height; j++) { + for (uint32_t i = 0; i < wb; i++) { + for (uint8_t k = 0; k < 4; k++) { + EPD_WriteByte(0x33); + } + } } - } + break; + case DRV_IC_JD79668: + case DRV_IC_JD79665: + wb = (epd->width + 3) / 4; // 2bpp + EPD_WriteCmd(UC81xx_DTM1); + for (uint16_t i = 0; i < epd->height; i++) { + for (uint16_t j = 0; j < wb; j++) { + EPD_WriteByte(0x55); + } + } + break; + default: + EPD_FillRAM(UC81xx_DTM1, 0xFF, wb * epd->height); + EPD_FillRAM(UC81xx_DTM2, 0xFF, wb * epd->height); + break; } - if (refresh) UC81xx_Refresh(epd); } -void JD79668_Clear(epd_model_t* epd, bool refresh) { - uint16_t wb = (epd->width + 3) / 4; - - EPD_WriteCmd(UC81xx_DTM1); - for (uint16_t i = 0; i < epd->height; i++) { - for (uint16_t j = 0; j < wb; j++) { - EPD_WriteByte(0x55); - } - } - - if (refresh) UC81xx_Refresh(epd); -} - -void UC81xx_Write_Image(epd_model_t* epd, uint8_t* black, uint8_t* color, uint16_t x, uint16_t y, uint16_t w, +void UC8176_Write_Image(epd_model_t* epd, uint8_t* black, uint8_t* color, uint16_t x, uint16_t y, uint16_t w, uint16_t h) { uint16_t wb = (w + 7) / 8; // width bytes, bitmaps are padded x -= x % 8; // byte boundary @@ -186,7 +161,7 @@ void UC81xx_Write_Image(epd_model_t* epd, uint8_t* black, uint8_t* color, uint16 EPD_WriteCmd(UC81xx_PTIN); // partial in _setPartialRamArea(epd, x, y, w, h); - if (epd->color == BWR) { + if (epd->color == COLOR_BWR) { EPD_WriteCmd(UC81xx_DTM1); for (uint16_t i = 0; i < h; i++) { for (uint16_t j = 0; j < w / 8; j++) EPD_WriteByte(black ? black[j + i * wb] : 0xFF); @@ -195,7 +170,7 @@ void UC81xx_Write_Image(epd_model_t* epd, uint8_t* black, uint8_t* color, uint16 EPD_WriteCmd(UC81xx_DTM2); for (uint16_t i = 0; i < h; i++) { for (uint16_t j = 0; j < w / 8; j++) { - if (epd->color == BWR) + if (epd->color == COLOR_BWR) EPD_WriteByte(color ? color[j + i * wb] : 0xFF); else EPD_WriteByte(black[j + i * wb]); @@ -269,23 +244,42 @@ void JD79668_Write_Image(epd_model_t* epd, uint8_t* black, uint8_t* color, uint1 } } +void UC81xx_Write_Image(epd_model_t* epd, uint8_t* black, uint8_t* color, uint16_t x, uint16_t y, uint16_t w, + uint16_t h) { + switch (epd->ic) { + case DRV_IC_UC8159: + UC8159_Write_Image(epd, black, color, x, y, w, h); + break; + case DRV_IC_JD79668: + case DRV_IC_JD79665: + JD79668_Write_Image(epd, black, color, x, y, w, h); + break; + default: + UC8176_Write_Image(epd, black, color, x, y, w, h); + break; + } +} + void UC81xx_Write_Ram(epd_model_t* epd, uint8_t cfg, uint8_t* data, uint8_t len) { bool begin = (cfg >> 4) == 0x00; bool black = (cfg & 0x0F) == 0x0F; - if (begin) { - if (epd->color == BWR) - EPD_WriteCmd(black ? UC81xx_DTM1 : UC81xx_DTM2); - else - EPD_WriteCmd(UC81xx_DTM2); + switch (epd->ic) { + case DRV_IC_UC8159: + case DRV_IC_JD79665: + case DRV_IC_JD79668: + if (begin) EPD_WriteCmd(UC81xx_DTM1); + EPD_WriteData(data, len); + break; + default: + if (begin) { + if (epd->color == COLOR_BWR) + EPD_WriteCmd(black ? UC81xx_DTM1 : UC81xx_DTM2); + else + EPD_WriteCmd(UC81xx_DTM2); + } + EPD_WriteData(data, len); + break; } - EPD_WriteData(data, len); -} - -// Write native data to ram, format should be 2pp or above -void UC81xx_Write_Ram_Native(epd_model_t* epd, uint8_t cfg, uint8_t* data, uint8_t len) { - bool begin = (cfg >> 4) == 0x00; - if (begin) EPD_WriteCmd(UC81xx_DTM1); - EPD_WriteData(data, len); } void UC81xx_Sleep(epd_model_t* epd) { @@ -295,8 +289,7 @@ void UC81xx_Sleep(epd_model_t* epd) { } // Declare driver and models -static epd_driver_t epd_drv_uc8176 = { - .ic = EPD_DRIVER_IC_UC8176, +static const epd_driver_t epd_drv_uc81xx = { .init = UC81xx_Init, .clear = UC81xx_Clear, .write_image = UC81xx_Write_Image, @@ -304,67 +297,24 @@ static epd_driver_t epd_drv_uc8176 = { .refresh = UC81xx_Refresh, .sleep = UC81xx_Sleep, .read_temp = UC81xx_Read_Temp, -}; - -static epd_driver_t epd_drv_uc8159 = { - .ic = EPD_DRIVER_IC_UC8159, - .init = UC8159_Init, - .clear = UC8159_Clear, - .write_image = UC8159_Write_Image, - .write_ram = UC81xx_Write_Ram_Native, - .refresh = UC81xx_Refresh, - .sleep = UC81xx_Sleep, - .read_temp = UC81xx_Read_Temp, -}; - -static epd_driver_t epd_drv_uc8179 = { - .ic = EPD_DRIVER_IC_UC8179, - .init = UC81xx_Init, - .clear = UC81xx_Clear, - .write_image = UC81xx_Write_Image, - .write_ram = UC81xx_Write_Ram, - .refresh = UC81xx_Refresh, - .sleep = UC81xx_Sleep, - .read_temp = UC81xx_Read_Temp, -}; - -static epd_driver_t epd_drv_jd79668 = { - .ic = EPD_DRIVER_IC_JD79668, - .init = JD79668_Init, - .clear = JD79668_Clear, - .write_image = JD79668_Write_Image, - .write_ram = UC81xx_Write_Ram_Native, - .refresh = UC81xx_Refresh, - .sleep = UC81xx_Sleep, - .read_temp = UC81xx_Read_Temp, -}; - -static epd_driver_t epd_drv_jd79665 = { - .ic = EPD_DRIVER_IC_JD79665, - .init = JD79665_Init, - .clear = JD79668_Clear, - .write_image = JD79668_Write_Image, - .write_ram = UC81xx_Write_Ram_Native, - .refresh = UC81xx_Refresh, - .sleep = UC81xx_Sleep, - .read_temp = UC81xx_Read_Temp, + .read_busy = UC81xx_ReadBusy, }; // UC8176 400x300 Black/White -const epd_model_t epd_uc8176_420_bw = {EPD_UC8176_420_BW, BW, &epd_drv_uc8176, 400, 300}; +const epd_model_t epd_uc8176_420_bw = {UC8176_420_BW, COLOR_BW, &epd_drv_uc81xx, DRV_IC_UC8176, 400, 300}; // UC8176 400x300 Black/White/Red -const epd_model_t epd_uc8176_420_bwr = {EPD_UC8176_420_BWR, BWR, &epd_drv_uc8176, 400, 300}; +const epd_model_t epd_uc8176_420_bwr = {UC8176_420_BWR, COLOR_BWR, &epd_drv_uc81xx, DRV_IC_UC8176, 400, 300}; // UC8159 640x384 Black/White -const epd_model_t epd_uc8159_750_bw = {EPD_UC8159_750_LOW_BW, BW, &epd_drv_uc8159, 640, 384}; +const epd_model_t epd_uc8159_750_bw = {UC8159_750_LOW_BW, COLOR_BW, &epd_drv_uc81xx, DRV_IC_UC8159, 640, 384}; // UC8159 640x384 Black/White/Red -const epd_model_t epd_uc8159_750_bwr = {EPD_UC8159_750_LOW_BWR, BWR, &epd_drv_uc8159, 640, 384}; +const epd_model_t epd_uc8159_750_bwr = {UC8159_750_LOW_BWR, COLOR_BWR, &epd_drv_uc81xx, DRV_IC_UC8159, 640, 384}; // UC8179 800x480 Black/White/Red -const epd_model_t epd_uc8179_750_bw = {EPD_UC8179_750_BW, BW, &epd_drv_uc8179, 800, 480}; +const epd_model_t epd_uc8179_750_bw = {UC8179_750_BW, COLOR_BW, &epd_drv_uc81xx, DRV_IC_UC8179, 800, 480}; // UC8179 800x480 Black/White/Red -const epd_model_t epd_uc8179_750_bwr = {EPD_UC8179_750_BWR, BWR, &epd_drv_uc8179, 800, 480}; +const epd_model_t epd_uc8179_750_bwr = {UC8179_750_BWR, COLOR_BWR, &epd_drv_uc81xx, DRV_IC_UC8179, 800, 480}; // JD79668 400x300 Black/White/Red/Yellow -const epd_model_t epd_jd79668_420_bwry = {EPD_JD79668_420_BWRY, BWRY, &epd_drv_jd79668, 400, 300}; +const epd_model_t epd_jd79668_420_bwry = {JD79668_420_BWRY, COLOR_BWRY, &epd_drv_uc81xx, DRV_IC_JD79668, 400, 300}; // JD79665 800x480 Black/White/Red/Yellow -const epd_model_t epd_jd79665_750_bwry = {EPD_JD79665_750_BWRY, BWRY, &epd_drv_jd79665, 800, 480}; +const epd_model_t epd_jd79665_750_bwry = {JD79665_750_BWRY, COLOR_BWRY, &epd_drv_uc81xx, DRV_IC_JD79665, 800, 480}; // JD79665 648x480 Black/White/Red/Yellow -const epd_model_t epd_jd79665_583_bwry = {EPD_JD79665_583_BWRY, BWRY, &epd_drv_jd79665, 648, 480}; +const epd_model_t epd_jd79665_583_bwry = {JD79665_583_BWRY, COLOR_BWRY, &epd_drv_uc81xx, DRV_IC_JD79665, 648, 480};