refactor driver code

This commit is contained in:
Shuanglei Tao
2025-03-16 12:09:53 +08:00
parent 87f96ee938
commit 465af89793
11 changed files with 204 additions and 263 deletions

View File

@@ -28,7 +28,7 @@ void epd_config_init(epd_config_t *cfg)
}
}
void epd_config_load(epd_config_t *cfg)
void epd_config_read(epd_config_t *cfg)
{
fds_flash_record_t flash_record;
fds_record_desc_t record_desc;
@@ -54,21 +54,7 @@ void epd_config_load(epd_config_t *cfg)
fds_record_close(&record_desc);
}
void epd_config_clear(epd_config_t *cfg)
{
fds_record_desc_t record_desc;
fds_find_token_t ftok;
memset(&ftok, 0x00, sizeof(fds_find_token_t));
if (fds_record_find(CONFIG_FILE_ID, CONFIG_REC_KEY, &record_desc, &ftok) != NRF_SUCCESS) {
NRF_LOG_DEBUG("epd_config_clear: record not found\n");
return;
}
fds_record_delete(&record_desc);
}
void epd_config_save(epd_config_t *cfg)
void epd_config_write(epd_config_t *cfg)
{
ret_code_t ret;
fds_record_t record;
@@ -100,6 +86,20 @@ void epd_config_save(epd_config_t *cfg)
}
}
void epd_config_clear(epd_config_t *cfg)
{
fds_record_desc_t record_desc;
fds_find_token_t ftok;
memset(&ftok, 0x00, sizeof(fds_find_token_t));
if (fds_record_find(CONFIG_FILE_ID, CONFIG_REC_KEY, &record_desc, &ftok) != NRF_SUCCESS) {
NRF_LOG_DEBUG("epd_config_clear: record not found\n");
return;
}
fds_record_delete(&record_desc);
}
bool epd_config_empty(epd_config_t *cfg)
{
for (uint8_t i = 0; i < EPD_CONFIG_SIZE; i++) {

View File

@@ -22,9 +22,9 @@ typedef struct
#define EPD_CONFIG_EMPTY 0xFF
void epd_config_init(epd_config_t *cfg);
void epd_config_load(epd_config_t *cfg);
void epd_config_read(epd_config_t *cfg);
void epd_config_write(epd_config_t *cfg);
void epd_config_clear(epd_config_t *cfg);
void epd_config_save(epd_config_t *cfg);
bool epd_config_empty(epd_config_t *cfg);
#endif

View File

@@ -22,22 +22,18 @@
#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
// GPIO Pins
uint32_t EPD_MOSI_PIN = 5;
uint32_t EPD_SCLK_PIN = 8;
uint32_t EPD_CS_PIN = 9;
uint32_t EPD_DC_PIN = 10;
uint32_t EPD_RST_PIN = 11;
uint32_t EPD_BUSY_PIN = 12;
uint32_t EPD_BS_PIN = 13;
uint32_t EPD_EN_PIN = 0xFF;
uint32_t EPD_LED_PIN = 0xFF;
static uint32_t EPD_MOSI_PIN = 5;
static uint32_t EPD_SCLK_PIN = 8;
static uint32_t EPD_CS_PIN = 9;
static uint32_t EPD_DC_PIN = 10;
static uint32_t EPD_RST_PIN = 11;
static uint32_t EPD_BUSY_PIN = 12;
static uint32_t EPD_BS_PIN = 13;
static uint32_t EPD_EN_PIN = 0xFF;
static uint32_t EPD_LED_PIN = 0xFF;
// Display resolution
uint16_t EPD_WIDTH = 400;
uint16_t EPD_HEIGHT = 300;
// BWR mode
bool EPD_BWR_MODE = true;
// EPD model
static epd_model_t *EPD = NULL;
// Arduino like function wrappers
@@ -224,9 +220,11 @@ void EPD_Reset(uint32_t value, uint16_t duration)
void EPD_WaitBusy(uint32_t value, uint16_t timeout)
{
uint32_t led_status = digitalRead(EPD_LED_PIN);
NRF_LOG_DEBUG("[EPD]: check busy\n");
while (digitalRead(EPD_BUSY_PIN) == value) {
if (timeout % 100 == 0) EPD_LED_TOGGLE();
if (timeout % 100 == 0) EPD_LED_Toggle();
delay(1);
timeout--;
if (timeout == 0) {
@@ -235,9 +233,29 @@ void EPD_WaitBusy(uint32_t value, uint16_t timeout)
}
}
NRF_LOG_DEBUG("[EPD]: busy release\n");
// restore led status
if (led_status == LOW)
EPD_LED_ON();
else
EPD_LED_OFF();
}
// GPIO
void EPD_GPIO_Load(epd_config_t *cfg)
{
if (cfg == NULL) return;
EPD_MOSI_PIN = cfg->mosi_pin;
EPD_SCLK_PIN = cfg->sclk_pin;
EPD_CS_PIN = cfg->cs_pin;
EPD_DC_PIN = cfg->dc_pin;
EPD_RST_PIN = cfg->rst_pin;
EPD_BUSY_PIN = cfg->busy_pin;
EPD_BS_PIN = cfg->bs_pin;
EPD_EN_PIN = cfg->en_pin;
EPD_LED_PIN = cfg->led_pin;
}
void EPD_GPIO_Init(void)
{
pinMode(EPD_CS_PIN, OUTPUT);
@@ -253,16 +271,12 @@ void EPD_GPIO_Init(void)
pinMode(EPD_BS_PIN, OUTPUT);
digitalWrite(EPD_BS_PIN, LOW);
EPD_SPI_Init();
digitalWrite(EPD_DC_PIN, LOW);
digitalWrite(EPD_CS_PIN, LOW);
digitalWrite(EPD_RST_PIN, HIGH);
if (EPD_LED_PIN != 0xFF) {
if (EPD_LED_PIN != 0xFF)
pinMode(EPD_LED_PIN, OUTPUT);
EPD_LED_ON();
}
}
void EPD_GPIO_Uninit(void)
@@ -289,7 +303,7 @@ void EPD_LED_OFF(void)
digitalWrite(EPD_LED_PIN, HIGH);
}
void EPD_LED_TOGGLE(void)
void EPD_LED_Toggle(void)
{
if (EPD_LED_PIN != 0xFF)
nrf_gpio_pin_toggle(EPD_LED_PIN);
@@ -310,19 +324,19 @@ static epd_model_t *epd_models[] = {
&epd_uc8276_420_bwr,
};
static epd_model_t *epd_model_get(epd_model_id_t id)
epd_model_t *epd_get(void)
{
return EPD == NULL ? epd_models[0] : EPD;
}
epd_model_t *epd_init(epd_model_id_t id)
{
for (uint8_t i = 0; i < ARRAY_SIZE(epd_models); i++) {
if (epd_models[i]->id == id) {
return epd_models[i];
EPD = epd_models[i];
}
}
return epd_models[0];
}
epd_driver_t *epd_model_init(epd_model_id_t id)
{
epd_model_t *model = epd_model_get(id);
model->drv->init(model->res, model->bwr);
return model->drv;
if (EPD == NULL) EPD = epd_models[0];
EPD->drv->init();
return EPD;
}

View File

@@ -18,25 +18,17 @@
#include <stdbool.h>
#include <stdint.h>
#include <stdlib.h>
#include "EPD_config.h"
#define BIT(n) (1UL << (n))
// Display resolution
typedef enum
{
EPD_RES_400x300,
EPD_RES_320x300,
EPD_RES_320x240,
EPD_RES_200x300,
} epd_res_t;
/**@brief EPD driver structure.
*
* @details This structure contains epd driver functions.
*/
typedef struct
{
void (*init)(epd_res_t res, bool bwr); /**< Initialize the e-Paper register */
void (*init)(); /**< Initialize the e-Paper register */
void (*clear)(void); /**< Clear screen */
void (*write_image)(uint8_t *black, uint8_t *color, uint16_t x, uint16_t y, uint16_t w, uint16_t h); /**< write image */
void (*refresh)(void); /**< Sends the image buffer in RAM to e-Paper and displays */
@@ -58,25 +50,12 @@ typedef struct
{
epd_model_id_t id;
epd_driver_t *drv;
epd_res_t res;
uint16_t width;
uint16_t height;
bool bwr;
bool invert_color;
} epd_model_t;
extern uint32_t EPD_MOSI_PIN;
extern uint32_t EPD_SCLK_PIN;
extern uint32_t EPD_CS_PIN;
extern uint32_t EPD_DC_PIN;
extern uint32_t EPD_RST_PIN;
extern uint32_t EPD_BUSY_PIN;
extern uint32_t EPD_BS_PIN;
extern uint32_t EPD_EN_PIN;
extern uint32_t EPD_LED_PIN;
extern uint16_t EPD_WIDTH;
extern uint16_t EPD_HEIGHT;
extern bool EPD_BWR_MODE;
#define LOW (0x0)
#define HIGH (0x1)
@@ -92,6 +71,7 @@ uint32_t digitalRead(uint32_t pin);
void delay(uint32_t ms);
// GPIO
void EPD_GPIO_Load(epd_config_t *cfg);
void EPD_GPIO_Init(void);
void EPD_GPIO_Uninit(void);
@@ -115,8 +95,9 @@ void EPD_WaitBusy(uint32_t value, uint16_t timeout);
// lED
void EPD_LED_ON(void);
void EPD_LED_OFF(void);
void EPD_LED_TOGGLE(void);
void EPD_LED_Toggle(void);
epd_driver_t *epd_model_init(epd_model_id_t id);
epd_model_t *epd_get(void);
epd_model_t *epd_init(epd_model_id_t id);
#endif

View File

@@ -65,8 +65,8 @@ static void calendar_update(void * p_event_data, uint16_t event_size)
p_epd->calendar_mode = true;
epd_gpio_init();
epd_driver_t *drv = epd_model_init((epd_model_id_t)p_epd->config.model_id);
DrawCalendar(drv, event->timestamp);
epd_model_t *epd = epd_init((epd_model_id_t)p_epd->config.model_id);
DrawCalendar(epd, event->timestamp);
epd_gpio_uninit();
}
@@ -79,6 +79,7 @@ static void on_connect(ble_epd_t * p_epd, ble_evt_t * p_ble_evt)
{
p_epd->conn_handle = p_ble_evt->evt.gap_evt.conn_handle;
epd_gpio_init();
EPD_LED_ON();
}
/**@brief Function for handling the @ref BLE_GAP_EVT_DISCONNECTED event from the S110 SoftDevice.
@@ -90,6 +91,7 @@ static void on_disconnect(ble_epd_t * p_epd, ble_evt_t * p_ble_evt)
{
UNUSED_PARAMETER(p_ble_evt);
p_epd->conn_handle = BLE_CONN_HANDLE_INVALID;
EPD_LED_OFF();
epd_gpio_uninit();
}
@@ -108,19 +110,19 @@ static void epd_service_process(ble_epd_t * p_epd, uint8_t * p_data, uint16_t le
case EPD_CMD_SET_PINS:
if (length < 8) return;
EPD_GPIO_Uninit();
EPD_MOSI_PIN = p_epd->config.mosi_pin = p_data[1];
EPD_SCLK_PIN = p_epd->config.sclk_pin = p_data[2];
EPD_CS_PIN = p_epd->config.cs_pin = p_data[3];
EPD_DC_PIN = p_epd->config.dc_pin = p_data[4];
EPD_RST_PIN = p_epd->config.rst_pin = p_data[5];
EPD_BUSY_PIN = p_epd->config.busy_pin = p_data[6];
EPD_BS_PIN = p_epd->config.bs_pin = p_data[7];
p_epd->config.mosi_pin = p_data[1];
p_epd->config.sclk_pin = p_data[2];
p_epd->config.cs_pin = p_data[3];
p_epd->config.dc_pin = p_data[4];
p_epd->config.rst_pin = p_data[5];
p_epd->config.busy_pin = p_data[6];
p_epd->config.bs_pin = p_data[7];
if (length > 8)
EPD_EN_PIN = p_epd->config.en_pin = p_data[8];
epd_config_save(&p_epd->config);
p_epd->config.en_pin = p_data[8];
epd_config_write(&p_epd->config);
EPD_GPIO_Uninit();
EPD_GPIO_Load(&p_epd->config);
EPD_GPIO_Init();
break;
@@ -128,14 +130,14 @@ static void epd_service_process(ble_epd_t * p_epd, uint8_t * p_data, uint16_t le
uint8_t id = length > 1 ? p_data[1] : p_epd->config.model_id;
if (id != p_epd->config.model_id) {
p_epd->config.model_id = id;
epd_config_save(&p_epd->config);
epd_config_write(&p_epd->config);
}
p_epd->driver = epd_model_init((epd_model_id_t)id);
p_epd->epd = epd_init((epd_model_id_t)id);
} break;
case EPD_CMD_CLEAR:
p_epd->calendar_mode = false;
p_epd->driver->clear();
p_epd->epd->drv->clear();
break;
case EPD_CMD_SEND_COMMAND:
@@ -149,17 +151,17 @@ static void epd_service_process(ble_epd_t * p_epd, uint8_t * p_data, uint16_t le
case EPD_CMD_DISPLAY:
p_epd->calendar_mode = false;
p_epd->driver->refresh();
p_epd->epd->drv->refresh();
break;
case EPD_CMD_SLEEP:
p_epd->driver->sleep();
p_epd->epd->drv->sleep();
break;
case EPD_CMD_SET_CONFIG:
if (length < 2) return;
memcpy(&p_epd->config, &p_data[1], (length - 1 > EPD_CONFIG_SIZE) ? EPD_CONFIG_SIZE : length - 1);
epd_config_save(&p_epd->config);
epd_config_write(&p_epd->config);
break;
case EPD_CMD_CFG_ERASE:
@@ -282,37 +284,6 @@ static uint32_t epd_service_init(ble_epd_t * p_epd)
return characteristic_add(p_epd->service_handle, &add_char_params, &p_epd->char_handles);
}
static void ble_epd_config_load(ble_epd_t * p_epd)
{
// write default config
if (epd_config_empty(&p_epd->config))
{
uint8_t cfg[] = EPD_CFG_DEFAULT;
memcpy(&p_epd->config, cfg, sizeof(cfg));
epd_config_save(&p_epd->config);
}
// load config
EPD_MOSI_PIN = p_epd->config.mosi_pin;
EPD_SCLK_PIN = p_epd->config.sclk_pin;
EPD_CS_PIN = p_epd->config.cs_pin;
EPD_DC_PIN = p_epd->config.dc_pin;
EPD_RST_PIN = p_epd->config.rst_pin;
EPD_BUSY_PIN = p_epd->config.busy_pin;
EPD_BS_PIN = p_epd->config.bs_pin;
EPD_EN_PIN = p_epd->config.en_pin;
EPD_LED_PIN = p_epd->config.led_pin;
// blink LED on start
if (EPD_LED_PIN != EPD_CONFIG_EMPTY)
{
pinMode(EPD_LED_PIN, OUTPUT);
EPD_LED_ON();
delay(100);
EPD_LED_OFF();
}
}
void ble_epd_sleep_prepare(ble_epd_t * p_epd)
{
// Turn off led
@@ -335,8 +306,24 @@ uint32_t ble_epd_init(ble_epd_t * p_epd, epd_callback_t cmd_cb)
p_epd->is_notification_enabled = false;
epd_config_init(&p_epd->config);
epd_config_load(&p_epd->config);
ble_epd_config_load(p_epd);
epd_config_read(&p_epd->config);
// write default config
if (epd_config_empty(&p_epd->config))
{
uint8_t cfg[] = EPD_CFG_DEFAULT;
memcpy(&p_epd->config, cfg, sizeof(cfg));
epd_config_write(&p_epd->config);
}
// load config
EPD_GPIO_Load(&p_epd->config);
epd_gpio_init();
// blink LED on start
EPD_LED_ON();
delay(100);
EPD_LED_OFF();
// Add the service.
return epd_service_init(p_epd);

View File

@@ -82,7 +82,7 @@ typedef struct
uint16_t conn_handle; /**< Handle of the current connection (as provided by the SoftDevice). BLE_CONN_HANDLE_INVALID if not in a connection. */
uint16_t max_data_len; /**< Maximum length of data (in bytes) that can be transmitted to the peer */
bool is_notification_enabled; /**< Variable to indicate if the peer has enabled notification of the RX characteristic.*/
epd_driver_t *driver; /**< current EPD driver */
epd_model_t *epd; /**< current EPD model */
epd_config_t config; /**< EPD config */
epd_callback_t epd_cmd_cb; /**< EPD callback */
bool calendar_mode; /**< Calendar mode flag */

View File

@@ -42,47 +42,28 @@ void SSD1619_Force_Temp(int8_t value)
static void _setPartialRamArea(uint16_t x, uint16_t y, uint16_t w, uint16_t h)
{
EPD_WriteCommand(CMD_DATA_MODE); // set ram entry mode
EPD_WriteByte(0x03); // x increase, y increase
EPD_WriteCommand(CMD_RAM_XPOS);
EPD_WriteByte(x / 8);
EPD_WriteByte((x + w - 1) / 8);
EPD_WriteCommand(CMD_RAM_YPOS);
EPD_WriteByte(y % 256);
EPD_WriteByte(y / 256);
EPD_WriteByte((y + h - 1) % 256);
EPD_WriteByte((y + h - 1) / 256);
EPD_WriteCommand(CMD_RAM_XCOUNT);
EPD_WriteByte(x / 8);
EPD_WriteCommand(CMD_RAM_YCOUNT);
EPD_WriteByte(y % 256);
EPD_WriteByte(y / 256);
EPD_WriteCommand(CMD_DATA_MODE); // set ram entry mode
EPD_WriteByte(0x03); // x increase, y increase
EPD_WriteCommand(CMD_RAM_XPOS);
EPD_WriteByte(x / 8);
EPD_WriteByte((x + w - 1) / 8);
EPD_WriteCommand(CMD_RAM_YPOS);
EPD_WriteByte(y % 256);
EPD_WriteByte(y / 256);
EPD_WriteByte((y + h - 1) % 256);
EPD_WriteByte((y + h - 1) / 256);
EPD_WriteCommand(CMD_RAM_XCOUNT);
EPD_WriteByte(x / 8);
EPD_WriteCommand(CMD_RAM_YCOUNT);
EPD_WriteByte(y % 256);
EPD_WriteByte(y / 256);
}
void SSD1619_Init(epd_res_t res, bool bwr)
void SSD1619_Init()
{
EPD_BWR_MODE = bwr;
EPD_Reset(HIGH, 10);
epd_model_t *EPD = epd_get();
switch (res) {
case EPD_RES_320x300:
EPD_WIDTH = 320;
EPD_HEIGHT = 300;
break;
case EPD_RES_320x240:
EPD_WIDTH = 320;
EPD_HEIGHT = 240;
break;
case EPD_RES_200x300:
EPD_WIDTH = 200;
EPD_HEIGHT = 300;
break;
case EPD_RES_400x300:
default:
EPD_WIDTH = 400;
EPD_HEIGHT = 300;
break;
}
EPD_Reset(HIGH, 10);
EPD_WriteCommand(CMD_SW_RESET);
EPD_WaitBusy(HIGH, 200);
@@ -91,22 +72,13 @@ void SSD1619_Init(epd_res_t res, bool bwr)
EPD_WriteByte(0x54);
EPD_WriteCommand(CMD_DIGITAL_BLOCK_CTRL);
EPD_WriteByte(0x3B);
EPD_WriteCommand(CMD_VCOM_CTRL); // Reduce glitch under ACVCOM
EPD_WriteByte(0x04);
EPD_WriteByte(0x63);
EPD_WriteCommand(CMD_BOOSTER_CTRL);
EPD_WriteByte(0x8B);
EPD_WriteByte(0x9C);
EPD_WriteByte(0x96);
EPD_WriteByte(0x0F);
EPD_WriteCommand(CMD_DRIVER_CTRL);
EPD_WriteByte((EPD_HEIGHT - 1) % 256);
EPD_WriteByte((EPD_HEIGHT - 1) / 256);
EPD_WriteByte((EPD->height - 1) % 256);
EPD_WriteByte((EPD->height - 1) / 256);
EPD_WriteByte(0x00);
_setPartialRamArea(0, 0, EPD_WIDTH, EPD_HEIGHT);
_setPartialRamArea(0, 0, EPD->width, EPD->height);
EPD_WriteCommand(CMD_BORDER_CTRL);
EPD_WriteByte(0x01);
@@ -121,6 +93,8 @@ void SSD1619_Init(epd_res_t res, bool bwr)
static void SSD1619_Refresh(void)
{
epd_model_t *EPD = epd_get();
NRF_LOG_DEBUG("[EPD]: refresh begin\n");
NRF_LOG_DEBUG("[EPD]: temperature: %d\n", SSD1619_Read_Temp());
EPD_WriteCommand(CMD_DISP_CTRL2);
@@ -129,14 +103,16 @@ static void SSD1619_Refresh(void)
EPD_WaitBusy(HIGH, 30000);
NRF_LOG_DEBUG("[EPD]: refresh end\n");
_setPartialRamArea(0, 0, EPD_WIDTH, EPD_HEIGHT);
_setPartialRamArea(0, 0, EPD->width, EPD->height); // DO NOT REMOVE!
}
void SSD1619_Clear(void)
{
uint16_t Width = (EPD_WIDTH + 7) / 8;
uint16_t Height = EPD_HEIGHT;
epd_model_t *EPD = epd_get();
uint16_t Width = (EPD->width + 7) / 8;
uint16_t Height = EPD->height;
_setPartialRamArea(0, 0, EPD->width, EPD->height);
EPD_WriteCommand(CMD_WRITE_RAM1);
for (uint16_t j = 0; j < Height; j++) {
for (uint16_t i = 0; i < Width; i++) {
@@ -146,7 +122,7 @@ void SSD1619_Clear(void)
EPD_WriteCommand(CMD_WRITE_RAM2);
for (uint16_t j = 0; j < Height; j++) {
for (uint16_t i = 0; i < Width; i++) {
EPD_WriteByte(EPD_BWR_MODE ? 0x00 : 0xFF);
EPD_WriteByte(EPD->invert_color ? 0x00 : 0xFF);
}
}
@@ -155,10 +131,11 @@ void SSD1619_Clear(void)
void SSD1619_Write_Image(uint8_t *black, uint8_t *color, uint16_t x, uint16_t y, uint16_t w, uint16_t h)
{
epd_model_t *EPD = epd_get();
uint16_t wb = (w + 7) / 8; // width bytes, bitmaps are padded
x -= x % 8; // byte boundary
w = wb * 8; // byte boundary
if (x + w > EPD_WIDTH || y + h > EPD_HEIGHT) return;
if (x + w > EPD->width || y + h > EPD->height) return;
_setPartialRamArea(x, y, w, h);
EPD_WriteCommand(CMD_WRITE_RAM1);
for (uint16_t i = 0; i < h; i++) {
@@ -169,10 +146,12 @@ void SSD1619_Write_Image(uint8_t *black, uint8_t *color, uint16_t x, uint16_t y,
EPD_WriteCommand(CMD_WRITE_RAM2);
for (uint16_t i = 0; i < h; i++) {
for (uint16_t j = 0; j < w / 8; j++) {
if (EPD_BWR_MODE)
EPD_WriteByte(color ? ~color[j + i * wb] : 0x00);
else
if (EPD->bwr) {
uint8_t data = color ? color[j + i * wb] : 0xFF;
EPD_WriteByte(EPD->invert_color ? ~data : data);
} else {
EPD_WriteByte(black[j + i * wb]);
}
}
}
}
@@ -194,16 +173,22 @@ static epd_driver_t epd_drv_ssd1619 = {
.force_temp = SSD1619_Force_Temp,
};
// SSD1619 400x300 Black/White/Red
const epd_model_t epd_ssd1619_420_bwr = {
.id = EPD_SSD1619_420_BWR,
.drv = &epd_drv_ssd1619,
.res = EPD_RES_400x300,
.width = 400,
.height = 300,
.bwr = true,
.invert_color = true,
};
// SSD1619 400x300 Black/White
const epd_model_t epd_ssd1619_420_bw = {
.id = EPD_SSD1619_420_BW,
.drv = &epd_drv_ssd1619,
.res = EPD_RES_400x300,
.width = 400,
.height = 300,
.bwr = false,
.invert_color = false,
};

View File

@@ -104,40 +104,28 @@ void UC8176_Refresh(void)
function : Initialize the e-Paper register
parameter:
******************************************************************************/
void UC8176_Init(epd_res_t res, bool bwr)
void UC8176_Init()
{
EPD_BWR_MODE = bwr;
EPD_Reset(HIGH, 10);
epd_model_t *EPD = epd_get();
uint8_t psr = PSR_UD | PSR_SHL | PSR_SHD | PSR_RST;
if (!EPD_BWR_MODE) psr |= PSR_BWR;
switch (res) {
case EPD_RES_320x300:
EPD_WIDTH = 320;
EPD_HEIGHT = 300;
psr |= PSR_RES0;
break;
case EPD_RES_320x240:
EPD_WIDTH = 320;
EPD_HEIGHT = 240;
psr |= PSR_RES1;
break;
case EPD_RES_200x300:
EPD_WIDTH = 200;
EPD_HEIGHT = 300;
psr |= PSR_RES1 | PSR_RES0;
break;
case EPD_RES_400x300:
default:
EPD_WIDTH = 400;
EPD_HEIGHT = 300;
break;
if (!EPD->bwr) psr |= PSR_BWR;
if (EPD->width == 320 && EPD->height == 300) {
psr |= PSR_RES0;
} else if (EPD->width == 320 && EPD->height == 240) {
psr |= PSR_RES1;
} else if (EPD->width == 200 && EPD->height == 300) {
psr |= PSR_RES1 | PSR_RES0;
} else {
// default to 400x300
}
NRF_LOG_DEBUG("[EPD]: PSR=%02x\n", psr);
EPD_WriteCommand(CMD_PSR);
EPD_WriteByte(psr);
if (!EPD_BWR_MODE) {
if (!EPD->bwr) {
EPD_WriteCommand(CMD_CDI);
EPD_WriteByte(0x97);
}
@@ -145,8 +133,9 @@ void UC8176_Init(epd_res_t res, bool bwr)
static void UC8176_Write_RAM(uint8_t cmd, uint8_t value)
{
uint16_t Width = (EPD_WIDTH + 7) / 8;
uint16_t Height = EPD_HEIGHT;
epd_model_t *EPD = epd_get();
uint16_t Width = (EPD->width + 7) / 8;
uint16_t Height = EPD->height;
EPD_WriteCommand(cmd);
for (uint16_t j = 0; j < Height; j++) {
@@ -162,15 +151,9 @@ parameter:
******************************************************************************/
void UC8176_Clear(void)
{
epd_model_t *EPD = epd_get();
UC8176_Write_RAM(CMD_DTM1, 0xFF);
UC8176_Write_RAM(CMD_DTM2, 0xFF);
UC8176_Refresh();
}
void UC8276_Clear(void)
{
UC8176_Write_RAM(CMD_DTM1, 0xFF);
UC8176_Write_RAM(CMD_DTM2, 0x00);
UC8176_Write_RAM(CMD_DTM2, EPD->invert_color ? 0x00 : 0xFF);
UC8176_Refresh();
}
@@ -192,15 +175,16 @@ static void _setPartialRamArea(uint16_t x, uint16_t y, uint16_t w, uint16_t h)
EPD_WriteByte(0x01);
}
void UC8176_Write_Paritial(uint8_t *black, uint8_t *color, uint16_t x, uint16_t y, uint16_t w, uint16_t h, bool invertColor)
void UC8176_Write_Image(uint8_t *black, uint8_t *color, uint16_t x, uint16_t y, uint16_t w, uint16_t h)
{
epd_model_t *EPD = epd_get();
uint16_t wb = (w + 7) / 8; // width bytes, bitmaps are padded
x -= x % 8; // byte boundary
w = wb * 8; // byte boundary
if (x + w > EPD_WIDTH || y + h > EPD_HEIGHT) return;
if (x + w > EPD->width || y + h > EPD->height) return;
EPD_WriteCommand(CMD_PTIN); // partial in
_setPartialRamArea(x, y, w, h);
if (EPD_BWR_MODE) {
if (EPD->bwr) {
EPD_WriteCommand(CMD_DTM1);
for (uint16_t i = 0; i < h; i++) {
for (uint16_t j = 0; j < w / 8; j++) {
@@ -211,9 +195,9 @@ void UC8176_Write_Paritial(uint8_t *black, uint8_t *color, uint16_t x, uint16_t
EPD_WriteCommand(CMD_DTM2);
for (uint16_t i = 0; i < h; i++) {
for (uint16_t j = 0; j < w / 8; j++) {
if (EPD_BWR_MODE) {
if (EPD->bwr) {
uint8_t data = color ? color[j + i * wb] : 0xFF;
EPD_WriteByte(invertColor ? ~data : data);
EPD_WriteByte(EPD->invert_color ? ~data : data);
} else {
EPD_WriteByte(black[j + i * wb]);
}
@@ -222,16 +206,6 @@ void UC8176_Write_Paritial(uint8_t *black, uint8_t *color, uint16_t x, uint16_t
EPD_WriteCommand(CMD_PTOUT); // partial out
}
void UC8176_Write_Image(uint8_t *black, uint8_t *color, uint16_t x, uint16_t y, uint16_t w, uint16_t h)
{
UC8176_Write_Paritial(black, color, x, y, w, h, false);
}
void UC8276_Write_Image(uint8_t *black, uint8_t *color, uint16_t x, uint16_t y, uint16_t w, uint16_t h)
{
UC8176_Write_Paritial(black, color, x, y, w, h, true);
}
/******************************************************************************
function : Enter sleep mode
parameter:
@@ -255,33 +229,32 @@ static epd_driver_t epd_drv_uc8176 = {
.force_temp = UC8176_Force_Temp,
};
static epd_driver_t epd_drv_uc8276 = {
.init = UC8176_Init,
.clear = UC8276_Clear,
.write_image = UC8276_Write_Image,
.refresh = UC8176_Refresh,
.sleep = UC8176_Sleep,
.read_temp = UC8176_Read_Temp,
.force_temp = UC8176_Force_Temp,
};
// UC8176 400x300 Black/White
const epd_model_t epd_uc8176_420_bw = {
.id = EPD_UC8176_420_BW,
.drv = &epd_drv_uc8176,
.res = EPD_RES_400x300,
.width = 400,
.height = 300,
.bwr = false,
.invert_color = false,
};
// UC8176 400x300 Black/White/Red
const epd_model_t epd_uc8176_420_bwr = {
.id = EPD_UC8176_420_BWR,
.drv = &epd_drv_uc8176,
.res = EPD_RES_400x300,
.width = 400,
.height = 300,
.bwr = true,
.invert_color = false,
};
// UC8276 400x300 Black/White/Red
const epd_model_t epd_uc8276_420_bwr = {
.id = EPD_UC8276_420_BWR,
.drv = &epd_drv_uc8276,
.res = EPD_RES_400x300,
.drv = &epd_drv_uc8176,
.width = 400,
.height = 300,
.bwr = true,
.invert_color = true,
};

View File

@@ -68,7 +68,7 @@ static void DrawMonthDays(Adafruit_GFX *gfx, tm_t *tm, struct Lunar_Date *Lunar)
int16_t y = (monthDayRows > 5 ? 69 : 72) + (firstDayWeek + i) / 7 * (monthDayRows > 5 ? 39 : 48);
if (day == tm->tm_mday) {
GFX_fillCircle(gfx, x + 10, y + (monthDayRows > 5 ? 10 : 12), 20, GFX_RED);
GFX_fillCircle(gfx, x + 11, y + (monthDayRows > 5 ? 10 : 12), 20, GFX_RED);
GFX_setTextColor(gfx, GFX_WHITE, GFX_RED);
} else {
GFX_setTextColor(gfx, weekend ? GFX_RED : GFX_BLACK, GFX_WHITE);
@@ -96,7 +96,7 @@ static void DrawMonthDays(Adafruit_GFX *gfx, tm_t *tm, struct Lunar_Date *Lunar)
}
}
void DrawCalendar(epd_driver_t *driver, uint32_t timestamp)
void DrawCalendar(epd_model_t *epd, uint32_t timestamp)
{
tm_t tm = {0};
struct Lunar_Date Lunar;
@@ -105,10 +105,10 @@ void DrawCalendar(epd_driver_t *driver, uint32_t timestamp)
Adafruit_GFX gfx;
if (EPD_BWR_MODE)
GFX_begin_3c(&gfx, EPD_WIDTH, EPD_HEIGHT, PAGE_HEIGHT);
if (epd->bwr)
GFX_begin_3c(&gfx, epd->width, epd->height, PAGE_HEIGHT);
else
GFX_begin(&gfx, EPD_WIDTH, EPD_HEIGHT, PAGE_HEIGHT);
GFX_begin(&gfx, epd->width, epd->height, PAGE_HEIGHT);
GFX_firstPage(&gfx);
do {
@@ -118,11 +118,11 @@ void DrawCalendar(epd_driver_t *driver, uint32_t timestamp)
DrawDateHeader(&gfx, 10, 28, &tm, &Lunar);
DrawWeekHeader(&gfx, 10, 32);
DrawMonthDays(&gfx, &tm, &Lunar);
} while(GFX_nextPage(&gfx, driver->write_image));
} while(GFX_nextPage(&gfx, epd->drv->write_image));
GFX_end(&gfx);
NRF_LOG_DEBUG("display start\n");
driver->refresh();
epd->drv->refresh();
NRF_LOG_DEBUG("display end\n");
}

View File

@@ -4,6 +4,6 @@
#include <stdint.h>
#include "EPD_driver.h"
void DrawCalendar(epd_driver_t *driver, uint32_t timestamp);
void DrawCalendar(epd_model_t *epd, uint32_t timestamp);
#endif

View File

@@ -148,7 +148,8 @@ function getImageData(canvas, driver, mode) {
} else {
let data = canvas2bytes(canvas, 'bw');
if (mode.startsWith('bwr')) {
data.push(...canvas2bytes(canvas, 'red', driver === '02'));
const invert = (driver === '02') || (driver === '05');
data.push(...canvas2bytes(canvas, 'red', invert));
}
return data;
}