diff --git a/EPD/EPD_config.c b/EPD/EPD_config.c index 281bb30..430e805 100644 --- a/EPD/EPD_config.c +++ b/EPD/EPD_config.c @@ -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++) { diff --git a/EPD/EPD_config.h b/EPD/EPD_config.h index d8044b2..0721b5d 100644 --- a/EPD/EPD_config.h +++ b/EPD/EPD_config.h @@ -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 diff --git a/EPD/EPD_driver.c b/EPD/EPD_driver.c index 25f0eff..bc0c1d8 100644 --- a/EPD/EPD_driver.c +++ b/EPD/EPD_driver.c @@ -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; } diff --git a/EPD/EPD_driver.h b/EPD/EPD_driver.h index e9117f4..6af2368 100644 --- a/EPD/EPD_driver.h +++ b/EPD/EPD_driver.h @@ -18,25 +18,17 @@ #include #include #include +#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 diff --git a/EPD/EPD_service.c b/EPD/EPD_service.c index cfe9947..9bd72cf 100644 --- a/EPD/EPD_service.c +++ b/EPD/EPD_service.c @@ -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); diff --git a/EPD/EPD_service.h b/EPD/EPD_service.h index f4d407a..ce9af3b 100644 --- a/EPD/EPD_service.h +++ b/EPD/EPD_service.h @@ -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 */ diff --git a/EPD/SSD1619.c b/EPD/SSD1619.c index b541237..c6ded14 100644 --- a/EPD/SSD1619.c +++ b/EPD/SSD1619.c @@ -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, }; diff --git a/EPD/UC8176.c b/EPD/UC8176.c index cbe7adb..b8afb01 100644 --- a/EPD/UC8176.c +++ b/EPD/UC8176.c @@ -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, }; diff --git a/GUI/Calendar.c b/GUI/Calendar.c index 4d89521..b9e1ca1 100644 --- a/GUI/Calendar.c +++ b/GUI/Calendar.c @@ -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"); } diff --git a/GUI/Calendar.h b/GUI/Calendar.h index bc1c21e..05f987d 100644 --- a/GUI/Calendar.h +++ b/GUI/Calendar.h @@ -4,6 +4,6 @@ #include #include "EPD_driver.h" -void DrawCalendar(epd_driver_t *driver, uint32_t timestamp); +void DrawCalendar(epd_model_t *epd, uint32_t timestamp); #endif diff --git a/html/js/main.js b/html/js/main.js index 57a0a32..1dfac9a 100644 --- a/html/js/main.js +++ b/html/js/main.js @@ -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; }