drivers: display: Added windowing for SSD1673

Added support to the SSD1673 dipslay for partially writing the display

Signed-off-by: Jan Van Winkel <jan.van_winkel@dxplore.eu>
This commit is contained in:
Jan Van Winkel 2018-11-30 23:00:33 +01:00 committed by Anas Nashif
commit cbbea99eb5

View file

@ -30,6 +30,8 @@ LOG_MODULE_REGISTER(ssd1673);
#define SSD1673_PANEL_FIRST_GATE 0 #define SSD1673_PANEL_FIRST_GATE 0
#define SSD1673_PANEL_LAST_GATE 249 #define SSD1673_PANEL_LAST_GATE 249
#define SSD1673_PIXELS_PER_BYTE 8
struct ssd1673_data { struct ssd1673_data {
struct device *reset; struct device *reset;
struct device *dc; struct device *dc;
@ -205,11 +207,11 @@ static int ssd1673_write(const struct device *dev, const u16_t x,
const void *buf) const void *buf)
{ {
struct ssd1673_data *driver = dev->driver_data; struct ssd1673_data *driver = dev->driver_data;
u8_t cmd = SSD1673_CMD_WRITE_RAM;
u8_t dummy_page[SSD1673_RAM_YRES];
struct spi_buf sbuf = {.buf = &cmd, .len = 1};
struct spi_buf_set buf_set = {.buffers = &sbuf, .count = 1};
int err; int err;
u8_t x_start;
u8_t x_end;
u8_t y_start;
u8_t y_end;
if (desc->pitch < desc->width) { if (desc->pitch < desc->width) {
LOG_ERR("Pitch is smaller then width"); LOG_ERR("Pitch is smaller then width");
@ -226,95 +228,69 @@ static int ssd1673_write(const struct device *dev, const u16_t x,
return -ENOTSUP; return -ENOTSUP;
} }
if (x != 0 && y != 0) { if ((y + desc->height) > EPD_PANEL_HEIGHT) {
LOG_ERR("Unsupported origin"); LOG_ERR("Buffer out of bounds (height)");
return -ENOTSUP; return -EINVAL;
} }
if ((x + desc->width) > EPD_PANEL_WIDTH) {
LOG_ERR("Buffer out of bounds (width)");
return -EINVAL;
}
ssd1673_busy_wait(driver); if ((desc->height % EPD_PANEL_NUMOF_ROWS_PER_PAGE) != 0) {
memset(dummy_page, 0xff, sizeof(dummy_page)); LOG_ERR("Buffer height not multiple of %d",
EPD_PANEL_NUMOF_ROWS_PER_PAGE);
return -EINVAL;
}
if ((y % EPD_PANEL_NUMOF_ROWS_PER_PAGE) != 0) {
LOG_ERR("Y coordinate not multiple of %d",
EPD_PANEL_NUMOF_ROWS_PER_PAGE);
return -EINVAL;
}
switch (driver->scan_mode) { switch (driver->scan_mode) {
case SSD1673_DATA_ENTRY_XIYDY: case SSD1673_DATA_ENTRY_XIYDY:
err = ssd1673_set_ram_param(driver, x_start = y / SSD1673_PIXELS_PER_BYTE;
SSD1673_PANEL_FIRST_PAGE, x_end = (y + desc->height - 1) / SSD1673_PIXELS_PER_BYTE;
SSD1673_PANEL_LAST_PAGE + 1, y_start = (x + desc->width - 1);
SSD1673_PANEL_LAST_GATE, y_end = x;
SSD1673_PANEL_FIRST_GATE);
if (err < 0) {
return err;
}
err = ssd1673_set_ram_ptr(driver,
SSD1673_PANEL_FIRST_PAGE,
SSD1673_PANEL_LAST_GATE);
if (err < 0) {
return err;
}
break; break;
case SSD1673_DATA_ENTRY_XDYIY: case SSD1673_DATA_ENTRY_XDYIY:
err = ssd1673_set_ram_param(driver, x_start = (EPD_PANEL_HEIGHT - 1 - y) / SSD1673_PIXELS_PER_BYTE;
SSD1673_PANEL_LAST_PAGE + 1, x_end = (EPD_PANEL_HEIGHT - 1 - (y + desc->height - 1)) /
SSD1673_PANEL_FIRST_PAGE, SSD1673_PIXELS_PER_BYTE;
SSD1673_PANEL_FIRST_GATE, y_start = x;
SSD1673_PANEL_LAST_GATE); y_end = (x + desc->width - 1);
if (err < 0) {
return err;
}
err = ssd1673_set_ram_ptr(driver,
SSD1673_PANEL_LAST_PAGE + 1,
SSD1673_PANEL_FIRST_GATE);
if (err < 0) {
return err;
}
break; break;
default: default:
return -EINVAL; return -EINVAL;
} }
ssd1673_busy_wait(driver);
err = ssd1673_write_cmd(driver, SSD1673_CMD_ENTRY_MODE, err = ssd1673_write_cmd(driver, SSD1673_CMD_ENTRY_MODE,
&driver->scan_mode, sizeof(driver->scan_mode)); &driver->scan_mode, sizeof(driver->scan_mode));
if (err < 0) { if (err < 0) {
return err; return err;
} }
gpio_pin_write(driver->dc, DT_SSD1673_DC_PIN, 0); err = ssd1673_set_ram_param(driver, x_start, x_end, y_start, y_end);
err = spi_write(driver->spi_dev, &driver->spi_config, &buf_set);
if (err < 0) { if (err < 0) {
return err; return err;
} }
gpio_pin_write(driver->dc, DT_SSD1673_DC_PIN, 1); err = ssd1673_set_ram_ptr(driver, x_start, y_start);
/* clear unusable page */
if (driver->scan_mode == SSD1673_DATA_ENTRY_XDYIY) {
sbuf.buf = dummy_page;
sbuf.len = sizeof(dummy_page);
err = spi_write(driver->spi_dev, &driver->spi_config, &buf_set);
if (err < 0) {
return err;
}
}
sbuf.buf = (u8_t *)buf;
sbuf.len = desc->buf_size;
err = spi_write(driver->spi_dev, &driver->spi_config, &buf_set);
if (err < 0) { if (err < 0) {
return err; return err;
} }
/* clear unusable page */ err = ssd1673_write_cmd(driver, SSD1673_CMD_WRITE_RAM, (u8_t *)buf,
if (driver->scan_mode == SSD1673_DATA_ENTRY_XIYDY) { desc->buf_size);
sbuf.buf = dummy_page; if (err < 0) {
sbuf.len = sizeof(dummy_page); return err;
err = spi_write(driver->spi_dev, &driver->spi_config, &buf_set);
if (err < 0) {
return err;
}
} }
return ssd1673_update_display(dev); return ssd1673_update_display(dev);