diff --git a/include/libwebsockets/lws-display.h b/include/libwebsockets/lws-display.h index 203cfc57b..abe3440ac 100644 --- a/include/libwebsockets/lws-display.h +++ b/include/libwebsockets/lws-display.h @@ -1,7 +1,7 @@ /* * lws abstract display * - * Copyright (C) 2019 - 2020 Andy Green + * Copyright (C) 2019 - 2022 Andy Green * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to @@ -25,9 +25,61 @@ #if !defined(__LWS_DISPLAY_H__) #define __LWS_DISPLAY_H__ -#include - +typedef int16_t lws_display_list_coord_t; typedef uint16_t lws_display_scalar; +typedef uint16_t lws_display_rotation_t; +typedef uint32_t lws_display_colour_t; +typedef uint16_t lws_display_palette_idx_t; + +typedef struct lws_box { + lws_fx_t x; + lws_fx_t y; + lws_fx_t w; + lws_fx_t h; +} lws_box_t; + +struct lws_display_state; +struct lws_display; + +typedef enum { + LWSSURF_TRUECOLOR32, + LWSSURF_565, + LWSSURF_PALETTE, +} lws_surface_type_t; + +typedef struct lws_surface_info { + lws_fx_t wh_px[2]; + lws_fx_t wh_mm[2]; + const lws_display_colour_t *palette; + size_t palette_depth; + lws_surface_type_t type; + char greyscale; /* line: 0 = RGBA, 1 = YA */ +} lws_surface_info_t; + +typedef struct lws_greyscale_error { + int16_t rgb[1]; +} lws_greyscale_error_t; + +typedef struct lws_colour_error { + int16_t rgb[3]; +} lws_colour_error_t; + +typedef union { + lws_greyscale_error_t grey; /* when ic->greyscale set */ + lws_colour_error_t colour; /* when ic->greyscale == 0 */ +} lws_surface_error_t; + +LWS_VISIBLE LWS_EXTERN void +lws_surface_set_px(const lws_surface_info_t *ic, uint8_t *line, int x, + const lws_display_colour_t *c); + +LWS_VISIBLE LWS_EXTERN lws_display_palette_idx_t +lws_display_palettize_grey(const struct lws_surface_info *ic, lws_display_colour_t c, + lws_greyscale_error_t *ectx); + +LWS_VISIBLE LWS_EXTERN lws_display_palette_idx_t +lws_display_palettize_col(const struct lws_surface_info *ic, lws_display_colour_t c, + lws_colour_error_t *ectx); /* * This is embedded in the actual display implementation object at the top, @@ -41,26 +93,23 @@ typedef uint16_t lws_display_scalar; */ typedef struct lws_display { - int (*init)(const struct lws_display *disp); + int (*init)(struct lws_display_state *lds); const lws_pwm_ops_t *bl_pwm_ops; - int (*contrast)(const struct lws_display *disp, uint8_t contrast); - int (*blit)(const struct lws_display *disp, const uint8_t *src, - lws_display_scalar x, lws_display_scalar y, - lws_display_scalar w, lws_display_scalar h); - int (*power)(const struct lws_display *disp, int state); + int (*contrast)(struct lws_display_state *lds, uint8_t contrast); + int (*blit)(struct lws_display_state *lds, const uint8_t *src, + lws_box_t *box); + int (*power)(struct lws_display_state *lds, int state); const lws_led_sequence_def_t *bl_active; const lws_led_sequence_def_t *bl_dim; const lws_led_sequence_def_t *bl_transition; + const char *name; void *variant; int bl_index; - lws_display_scalar w; - /**< display surface width in pixels */ - lws_display_scalar h; - /**< display surface height in pixels */ + lws_surface_info_t ic; uint8_t latency_wake_ms; /**< ms required after wake from sleep before display usable again... @@ -86,6 +135,8 @@ typedef struct lws_display_state { const lws_display_t *disp; struct lws_context *ctx; + void *priv; /* subclass driver alloc'd priv */ + int autodim_ms; int off_ms; diff --git a/include/libwebsockets/lws-ili9341-spi.h b/include/libwebsockets/lws-ili9341-spi.h index 70a361a44..3b7f6ab40 100644 --- a/include/libwebsockets/lws-ili9341-spi.h +++ b/include/libwebsockets/lws-ili9341-spi.h @@ -1,7 +1,7 @@ /* * lws abstract display implementation for ili9341 on spi * - * Copyright (C) 2019 - 2020 Andy Green + * Copyright (C) 2019 - 2022 Andy Green * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to @@ -39,13 +39,12 @@ typedef struct lws_display_ili9341 { } lws_display_ili9341_t; int -lws_display_ili9341_spi_init(const struct lws_display *disp); +lws_display_ili9341_spi_init(lws_display_state_t *lds); int -lws_display_ili9341_spi_blit(const struct lws_display *disp, const uint8_t *src, - lws_display_scalar x, lws_display_scalar y, - lws_display_scalar w, lws_display_scalar h); +lws_display_ili9341_spi_blit(lws_display_state_t *lds, const uint8_t *src, + lws_box_t *box); int -lws_display_ili9341_spi_power(const struct lws_display *disp, int state); +lws_display_ili9341_spi_power(lws_display_state_t *lds, int state); #define lws_display_ili9341_ops \ .init = lws_display_ili9341_spi_init, \ diff --git a/include/libwebsockets/lws-ssd1306-i2c.h b/include/libwebsockets/lws-ssd1306-i2c.h index 8b2f6e37e..256ef19e7 100644 --- a/include/libwebsockets/lws-ssd1306-i2c.h +++ b/include/libwebsockets/lws-ssd1306-i2c.h @@ -46,15 +46,14 @@ typedef struct lws_display_ssd1306 { } lws_display_ssd1306_t; int -lws_display_ssd1306_i2c_init(const struct lws_display *disp); +lws_display_ssd1306_i2c_init(lws_display_state_t *lds); int -lws_display_ssd1306_i2c_contrast(const struct lws_display *disp, uint8_t b); +lws_display_ssd1306_i2c_contrast(lws_display_state_t *lds, uint8_t b); int -lws_display_ssd1306_i2c_blit(const struct lws_display *disp, const uint8_t *src, - lws_display_scalar x, lws_display_scalar y, - lws_display_scalar w, lws_display_scalar h); +lws_display_ssd1306_i2c_blit(lws_display_state_t *lds, const uint8_t *src, + lws_box_t *box); int -lws_display_ssd1306_i2c_power(const struct lws_display *disp, int state); +lws_display_ssd1306_i2c_power(lws_display_state_t *lds, int state); #define lws_display_ssd1306_ops \ .init = lws_display_ssd1306_i2c_init, \ diff --git a/lib/drivers/display/ili9341-spi.c b/lib/drivers/display/ili9341-spi.c index 1d01be32e..70852c1cc 100644 --- a/lib/drivers/display/ili9341-spi.c +++ b/lib/drivers/display/ili9341-spi.c @@ -59,9 +59,9 @@ static uint8_t ili9341_320x240_init[] = { }; int -lws_display_ili9341_spi_init(const struct lws_display *disp) +lws_display_ili9341_spi_init(lws_display_state_t *lds) { - const lws_display_ili9341_t *ili = (const lws_display_ili9341_t *)disp; + const lws_display_ili9341_t *ili = (const lws_display_ili9341_t *)lds->disp; lws_spi_desc_t desc; size_t pos = 0; uint8_t u[8]; @@ -114,17 +114,17 @@ lws_display_ili9341_spi_init(const struct lws_display *disp) /* backlight handled by PWM */ int -lws_display_ili9341_spi_brightness(const struct lws_display *disp, uint8_t b) +lws_display_ili9341_spi_brightness(lws_display_state_t *lds, uint8_t b) { return 0; } int -lws_display_ili9341_spi_blit(const struct lws_display *disp, const uint8_t *src, - lws_display_scalar x, lws_display_scalar y, - lws_display_scalar w, lws_display_scalar h) +lws_display_ili9341_spi_blit(lws_display_state_t *lds, const uint8_t *src, + lws_box_t *box) { - const lws_display_ili9341_t *ili = (const lws_display_ili9341_t *)disp; + const lws_display_ili9341_t *ili = (const lws_display_ili9341_t *)lds->disp; + lws_display_list_coord_t h, y; lws_spi_desc_t desc; uint8_t u[5]; @@ -137,14 +137,17 @@ lws_display_ili9341_spi_blit(const struct lws_display *disp, const uint8_t *src, * Blit a line at a time */ + h = box->h.whole; + y = box->y.whole; + while (h--) { u[0] = ILI9341_CASET; desc.data = &u[1]; - u[1] = x; - u[2] = x; - u[3] = w >> 8; - u[4] = w & 0xff; + u[1] = box->x.whole; + u[2] = box->x.whole; + u[3] = box->w.whole >> 8; + u[4] = box->w.whole & 0xff; desc.count_write = 4; ili->spi->queue(ili->spi, &desc); @@ -158,9 +161,9 @@ lws_display_ili9341_spi_blit(const struct lws_display *disp, const uint8_t *src, u[0] = ILI9341_RAMWR; desc.data = src; - desc.count_write = w * 2; + desc.count_write = box->w.whole * 2; ili->spi->queue(ili->spi, &desc); - src += w * 2; + src += box->w.whole * 2; y++; } @@ -168,10 +171,10 @@ lws_display_ili9341_spi_blit(const struct lws_display *disp, const uint8_t *src, } int -lws_display_ili9341_spi_power(const struct lws_display *disp, int state) +lws_display_ili9341_spi_power(lws_display_state_t *lds, int state) { - const lws_display_ili9341_t *ili = (const lws_display_ili9341_t *)disp; + const lws_display_ili9341_t *ili = (const lws_display_ili9341_t *)lds->disp; lws_spi_desc_t desc; uint8_t u[1]; diff --git a/lib/drivers/display/lws-display.c b/lib/drivers/display/lws-display.c index 28d0c97f6..1a4112fa0 100644 --- a/lib/drivers/display/lws-display.c +++ b/lib/drivers/display/lws-display.c @@ -1,7 +1,7 @@ /* * lws abstract display * - * Copyright (C) 2019 - 2020 Andy Green + * Copyright (C) 2019 - 2022 Andy Green * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to @@ -22,7 +22,7 @@ * IN THE SOFTWARE. */ -#include +#include static void sul_autodim_cb(lws_sorted_usec_list_t *sul) @@ -85,7 +85,7 @@ lws_display_state_init(lws_display_state_t *lds, struct lws_context *ctx, lws_led_transition(lds->bl_lcs, "backlight", &lws_pwmseq_static_off, &lws_pwmseq_static_on); - disp->init(disp); + disp->init(lds); } void @@ -103,7 +103,7 @@ lws_display_state_active(lws_display_state_t *lds) if (lds->state == LWSDISPS_OFF) { /* power us up */ - lds->disp->power(lds->disp, 1); + lds->disp->power(lds, 1); lds->state = LWSDISPS_BECOMING_ACTIVE; waiting_ms = lds->disp->latency_wake_ms; } else { @@ -120,13 +120,274 @@ lws_display_state_active(lws_display_state_t *lds) if (waiting_ms >= 0) lws_sul_schedule(lds->ctx, 0, &lds->sul_autodim, sul_autodim_cb, waiting_ms * LWS_US_PER_MS); - } void lws_display_state_off(lws_display_state_t *lds) { - lds->disp->power(lds->disp, 0); + lds->disp->power(lds, 0); lws_sul_cancel(&lds->sul_autodim); lds->state = LWSDISPS_OFF; } + +int +lws_display_alloc_diffusion(const lws_surface_info_t *ic, lws_surface_error_t **se) +{ + size_t size, gsize = ic->greyscale ? sizeof(lws_greyscale_error_t) : + sizeof(lws_colour_error_t); + + if (*se) + return 0; + + /* defer creation of dlo's 2px-high dlo-width, 2 bytespp or 6 bytespp + * error diffusion buffer */ + + size = gsize * 2u * (unsigned int)(ic->wh_px[0].whole); + + lwsl_info("%s: alloc'd %u for width %d\n", __func__, (unsigned int)size, + (int)ic->wh_px[0].whole); + + se[0] = lws_zalloc(size, __func__); + if (!se[0]) + return 1; + + se[1] = (lws_surface_error_t *)(((uint8_t *)se[0]) + + ((size_t)ic->wh_px[0].whole * gsize)); + + return 0; +} + +static void +dist_err_grey(const lws_greyscale_error_t *in, lws_greyscale_error_t *out, + int sixteenths) +{ + out->rgb[0] = (int16_t)(out->rgb[0] + + (int16_t)((sixteenths * in->rgb[0]) / 16)); +} + +static void +dist_err_col(const lws_colour_error_t *in, lws_colour_error_t *out, + int sixteenths) +{ + out->rgb[0] = (int16_t)(out->rgb[0] + + (int16_t)((sixteenths * in->rgb[0]) / 16)); + out->rgb[1] = (int16_t)(out->rgb[1] + + (int16_t)((sixteenths * in->rgb[1]) / 16)); + out->rgb[2] = (int16_t)(out->rgb[2] + + (int16_t)((sixteenths * in->rgb[2]) / 16)); +} + +void +dist_err_floyd_steinberg_grey(int n, int width, lws_greyscale_error_t *gedl_this, + lws_greyscale_error_t *gedl_next) +{ + if (n != width - 1) { + dist_err_grey(&gedl_this[n], &gedl_this[n + 1], 7); + dist_err_grey(&gedl_this[n], &gedl_next[n + 1], 1); + } + if (n) + dist_err_grey(&gedl_this[n], &gedl_next[n - 1], 3); + + dist_err_grey(&gedl_this[n], &gedl_next[n], 5); + + gedl_this[n].rgb[0] = 0; +} + +void +dist_err_floyd_steinberg_col(int n, int width, lws_colour_error_t *edl_this, + lws_colour_error_t *edl_next) +{ + if (n != width - 1) { + dist_err_col(&edl_this[n], &edl_this[n + 1], 7); + dist_err_col(&edl_this[n], &edl_next[n + 1], 1); + } + if (n) + dist_err_col(&edl_this[n], &edl_next[n - 1], 3); + + dist_err_col(&edl_this[n], &edl_next[n], 5); + + edl_this[n].rgb[0] = 0; + edl_this[n].rgb[1] = 0; + edl_this[n].rgb[2] = 0; +} + +/* + * #include + * #include + * + * void + * main(void) + * { + * int n; + * + * for (n = 0; n < 256; n++) { + * double d = (double)n / 255.0; + * + * printf("0x%02X, ", (unsigned int)(pow(d, (2.2)) * 255)); + * } + * + * } + */ + +static const uint8_t gamma2_2[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, + 0x02, 0x02, 0x03, 0x03, 0x03, 0x03, 0x03, 0x04, + 0x04, 0x04, 0x04, 0x05, 0x05, 0x05, 0x05, 0x06, + 0x06, 0x06, 0x07, 0x07, 0x07, 0x08, 0x08, 0x08, + 0x09, 0x09, 0x09, 0x0A, 0x0A, 0x0A, 0x0B, 0x0B, + 0x0C, 0x0C, 0x0D, 0x0D, 0x0D, 0x0E, 0x0E, 0x0F, + 0x0F, 0x10, 0x10, 0x11, 0x11, 0x12, 0x12, 0x13, + 0x13, 0x14, 0x15, 0x15, 0x16, 0x16, 0x17, 0x17, + 0x18, 0x19, 0x19, 0x1A, 0x1B, 0x1B, 0x1C, 0x1D, + 0x1D, 0x1E, 0x1F, 0x1F, 0x20, 0x21, 0x21, 0x22, + 0x23, 0x24, 0x24, 0x25, 0x26, 0x27, 0x28, 0x28, + 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2D, 0x2E, 0x2F, + 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, + 0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, + 0x3F, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, + 0x48, 0x49, 0x4A, 0x4B, 0x4D, 0x4E, 0x4F, 0x50, + 0x51, 0x52, 0x54, 0x55, 0x56, 0x57, 0x58, 0x5A, + 0x5B, 0x5C, 0x5D, 0x5F, 0x60, 0x61, 0x63, 0x64, + 0x65, 0x67, 0x68, 0x69, 0x6B, 0x6C, 0x6D, 0x6F, + 0x70, 0x72, 0x73, 0x75, 0x76, 0x77, 0x79, 0x7A, + 0x7C, 0x7D, 0x7F, 0x80, 0x82, 0x83, 0x85, 0x87, + 0x88, 0x8A, 0x8B, 0x8D, 0x8E, 0x90, 0x92, 0x93, + 0x95, 0x97, 0x98, 0x9A, 0x9C, 0x9D, 0x9F, 0xA1, + 0xA2, 0xA4, 0xA6, 0xA8, 0xA9, 0xAB, 0xAD, 0xAF, + 0xB0, 0xB2, 0xB4, 0xB6, 0xB8, 0xBA, 0xBB, 0xBD, + 0xBF, 0xC1, 0xC3, 0xC5, 0xC7, 0xC9, 0xCB, 0xCD, + 0xCF, 0xD1, 0xD3, 0xD5, 0xD7, 0xD9, 0xDB, 0xDD, + 0xDF, 0xE1, 0xE3, 0xE5, 0xE7, 0xE9, 0xEB, 0xED, + 0xEF, 0xF1, 0xF4, 0xF6, 0xF8, 0xFA, 0xFC, 0xFF +}; + +lws_display_palette_idx_t +lws_display_palettize_grey(const lws_surface_info_t *ic, lws_display_colour_t c, + lws_greyscale_error_t *ectx) +{ + int best = 0x7fffffff, best_idx = 0, yd; + lws_colour_error_t da, d; + size_t n; + + /* put the most desirable colour (adjusted for existing error) in d */ + + d.rgb[0] = (int)gamma2_2[LWSDC_R(c)]; + da.rgb[0] = d.rgb[0] + ectx->rgb[0]; + yd = da.rgb[0]; + + /* + * Choose a palette colour considering the error diffusion adjustments + */ + + for (n = 0; n < ic->palette_depth; n++) { + lws_colour_error_t ea; + int sum, y; + + y = LWSDC_ALPHA(ic->palette[n]); + + ea.rgb[0] = (int16_t)((int)da.rgb[0] - (int)(LWSDC_R(ic->palette[n]))); + + sum = (ea.rgb[0] < 0 ? -ea.rgb[0] : ea.rgb[0]) + + ((yd > y ? (yd - y) * 1 : (y - yd) * 1)); + + if (sum < best) { + best_idx = (int)n; + best = sum; + } + } + + /* report the error between the unadjusted colour and what we chose */ + + ectx->rgb[0] = (int16_t)((int)da.rgb[0] - (int)(LWSDC_R(ic->palette[best_idx]))); + + return (lws_display_palette_idx_t)best_idx; +} +/* + * For error disffusion, it's better to use YUV and prioritize reducing error + * in Y (lumience) + */ +#if 0 +static void +rgb_to_yuv(uint8_t *yuv, const uint8_t *rgb) +{ + yuv[0] = 16 + ((257 * rgb[0]) / 1000) + ((504 * rgb[1]) / 1000) + + ((98 * rgb[2]) / 1000); + yuv[1] = 128 - ((148 * rgb[0]) / 1000) - ((291 * rgb[1]) / 1000) + + ((439 * rgb[2]) / 1000); + yuv[2] = 128 + ((439 * rgb[0]) / 1000) - ((368 * rgb[1]) / 1000) - + ((71 * rgb[2]) / 1000); +} + +static void +yuv_to_rgb(uint8_t *rgb, const uint8_t *_yuv) +{ + unsigned int yuv[3]; + + yuv[0] = _yuv[0] - 16; + yuv[1] = _yuv[1] - 128; + yuv[2] = _yuv[2] - 128; + + rgb[0] = ((1164 * yuv[0]) / 1000) + ((1596 * yuv[2]) / 1000); + rgb[1] = ((1164 * yuv[0]) / 1090) - ((392 * yuv[1]) / 1000) - + ((813 * yuv[2]) / 1000); + rgb[2] = ((1164 * yuv[0]) / 1000) + ((2017 * yuv[1]) / 1000); +} +#endif + +lws_display_palette_idx_t +lws_display_palettize_col(const lws_surface_info_t *ic, lws_display_colour_t c, + lws_colour_error_t *ectx) +{ + int best = 0x7fffffff, best_idx = 0, yd; + lws_colour_error_t da, d; + size_t n; + + /* put the most desirable colour (adjusted for existing error) in d */ + + d.rgb[0] = (int)gamma2_2[LWSDC_R(c)]; + da.rgb[0] = d.rgb[0] + ectx->rgb[0]; + yd = da.rgb[0]; + d.rgb[1] = (int)gamma2_2[LWSDC_G(c)]; + d.rgb[2] = (int)gamma2_2[LWSDC_B(c)]; + da.rgb[1] = d.rgb[1] + ectx->rgb[1]; + da.rgb[2] = d.rgb[2] + ectx->rgb[2]; + + yd = RGB_TO_Y(da.rgb[0], da.rgb[1], da.rgb[2]); + + /* + * Choose a palette colour considering the error diffusion adjustments + */ + + for (n = 0; n < ic->palette_depth; n++) { + lws_colour_error_t ea; + int sum, y; + + y = LWSDC_ALPHA(ic->palette[n]); + + ea.rgb[0] = (int16_t)((int)da.rgb[0] - (int)(LWSDC_R(ic->palette[n]))); + ea.rgb[1] = (int16_t)(da.rgb[1] - (int)(LWSDC_G(ic->palette[n]))); + ea.rgb[2] = (int16_t)(da.rgb[2] - (int)(LWSDC_B(ic->palette[n]))); + + sum = (ea.rgb[0] < 0 ? -ea.rgb[0] : ea.rgb[0]) + + (ea.rgb[1] < 0 ? -ea.rgb[1] : ea.rgb[1]) + + (ea.rgb[2] < 0 ? -ea.rgb[2] : ea.rgb[2]) + + (yd > y ? (yd - y) * 1 : (y - yd) * 1); + + if (sum < best) { + best_idx = (int)n; + best = sum; + } + } + + /* report the error between the adjusted colour and what we chose */ + + ectx->rgb[0] = (int16_t)((int)da.rgb[0] - (int)(LWSDC_R(ic->palette[best_idx]))); + ectx->rgb[1] = (int16_t)((int)da.rgb[1] - (int)(LWSDC_G(ic->palette[best_idx]))); + ectx->rgb[2] = (int16_t)((int)da.rgb[2] - (int)(LWSDC_B(ic->palette[best_idx]))); + + return (lws_display_palette_idx_t)best_idx; +} + diff --git a/lib/drivers/display/ssd1306-i2c.c b/lib/drivers/display/ssd1306-i2c.c index bfcb7558d..e0275f3e7 100644 --- a/lib/drivers/display/ssd1306-i2c.c +++ b/lib/drivers/display/ssd1306-i2c.c @@ -46,9 +46,9 @@ static uint8_t ssd1306_128x64_init[] = { }; int -lws_display_ssd1306_i2c_init(const struct lws_display *disp) +lws_display_ssd1306_i2c_init(lws_display_state_t *lds) { - const lws_display_ssd1306_t *si = (const lws_display_ssd1306_t *)disp; + const lws_display_ssd1306_t *si = (const lws_display_ssd1306_t *)lds->disp; si->i2c->init(si->i2c); @@ -72,9 +72,9 @@ lws_display_ssd1306_i2c_init(const struct lws_display *disp) } int -lws_display_ssd1306_i2c_contrast(const struct lws_display *disp, uint8_t b) +lws_display_ssd1306_i2c_contrast(lws_display_state_t *lds, uint8_t b) { - const lws_display_ssd1306_t *si = (const lws_display_ssd1306_t *)disp; + const lws_display_ssd1306_t *si = (const lws_display_ssd1306_t *)lds->disp; uint8_t ba[2]; ba[0] = SSD1306_SETCONTRAST; @@ -85,11 +85,11 @@ lws_display_ssd1306_i2c_contrast(const struct lws_display *disp, uint8_t b) } int -lws_display_ssd1306_i2c_blit(const struct lws_display *disp, const uint8_t *src, - lws_display_scalar x, lws_display_scalar y, - lws_display_scalar w, lws_display_scalar h) +lws_display_ssd1306_i2c_blit(lws_display_state_t *lds, const uint8_t *src, + lws_box_t *box) { - const lws_display_ssd1306_t *si = (const lws_display_ssd1306_t *)disp; + const lws_display_ssd1306_t *si = (const lws_display_ssd1306_t *)lds->disp; + lws_display_list_coord_t y = box->y.whole, h = box->h.whole; uint8_t ba[6]; int n, m; @@ -102,8 +102,8 @@ lws_display_ssd1306_i2c_blit(const struct lws_display *disp, const uint8_t *src, h = 8; ba[0] = SSD1306_COLUMNADDR; - ba[1] = x; - ba[2] = x + w - 1; + ba[1] = box->x.whole; + ba[2] = box->x.whole + box->w.whole - 1; ba[3] = SSD1306_PAGEADDR; ba[4] = y / 8; ba[5] = ba[4] + (h / 8) - 1; @@ -114,12 +114,12 @@ lws_display_ssd1306_i2c_blit(const struct lws_display *disp, const uint8_t *src, return 1; } - for (n = 0; n < (w * h) / 8;) { + for (n = 0; n < (box->w.whole * h) / 8;) { lws_bb_i2c_start(si->i2c); lws_bb_i2c_write(si->i2c, si->i2c7_address << 1); lws_bb_i2c_write(si->i2c, SSD1306_SETSTARTLINE | y); - for (m = 0; m < w; m++) + for (m = 0; m < box->w.whole; m++) lws_bb_i2c_write(si->i2c, src[n++]); lws_bb_i2c_stop(si->i2c); @@ -130,13 +130,13 @@ lws_display_ssd1306_i2c_blit(const struct lws_display *disp, const uint8_t *src, } int -lws_display_ssd1306_i2c_power(const struct lws_display *disp, int state) +lws_display_ssd1306_i2c_power(lws_display_state_t *lds, int state) { - const lws_display_ssd1306_t *si = (const lws_display_ssd1306_t *)disp; + const lws_display_ssd1306_t *si = (const lws_display_ssd1306_t *)lds->disp; if (!state) return lws_i2c_command(si->i2c, si->i2c7_address, SSD1306_DISPLAYOFF | !!state); - return lws_display_ssd1306_i2c_init(disp); + return lws_display_ssd1306_i2c_init(lds); } diff --git a/minimal-examples/embedded/esp32/esp-c3dev/main/devices.c b/minimal-examples/embedded/esp32/esp-c3dev/main/devices.c index 2d079d5e7..1a42a3899 100644 --- a/minimal-examples/embedded/esp32/esp-c3dev/main/devices.c +++ b/minimal-examples/embedded/esp32/esp-c3dev/main/devices.c @@ -1,7 +1,7 @@ /* * devices for ESP32 C3 dev board * - * Written in 2010-2021 by Andy Green + * Written in 2010-2022 by Andy Green * * This file is made available under the Creative Commons CC0 1.0 * Universal Public Domain Dedication. @@ -61,8 +61,10 @@ static const lws_pwm_ops_t pwm_ops = { static const lws_display_ssd1306_t disp = { .disp = { lws_display_ssd1306_ops, - .w = 128, - .h = 64 + .ic = { + .wh_px = { { 128,0 }, { 64,0 } }, + .wh_mm = { { 22,00000000 }, { 10,00000000 } }, + }, }, .i2c = (lws_i2c_ops_t *)&li2c, .gpio = &lws_gpio_plat, diff --git a/minimal-examples/embedded/esp32/esp-heltec-wb32/main/devices.c b/minimal-examples/embedded/esp32/esp-heltec-wb32/main/devices.c index da7cbe9c6..93781ceaf 100644 --- a/minimal-examples/embedded/esp32/esp-heltec-wb32/main/devices.c +++ b/minimal-examples/embedded/esp32/esp-heltec-wb32/main/devices.c @@ -1,7 +1,7 @@ /* * devices for ESP32 Heltec WB32 * - * Written in 2010-2020 by Andy Green + * Written in 2010-2022 by Andy Green * * This file is made available under the Creative Commons CC0 1.0 * Universal Public Domain Dedication. @@ -81,8 +81,10 @@ static const lws_pwm_ops_t pwm_ops = { static const lws_display_ssd1306_t disp = { .disp = { lws_display_ssd1306_ops, - .w = 128, - .h = 64 + .ic = { + .wh_px = { { 128,0 }, { 64,0 } }, + .wh_mm = { { 22,00000000 }, { 10,00000000 } }, + }, }, .i2c = (lws_i2c_ops_t *)&li2c, .gpio = &lws_gpio_plat, diff --git a/minimal-examples/embedded/esp32/esp-heltec-wb32/main/lws-minimal-esp32.c b/minimal-examples/embedded/esp32/esp-heltec-wb32/main/lws-minimal-esp32.c index a2499060c..efc8e6844 100644 --- a/minimal-examples/embedded/esp32/esp-heltec-wb32/main/lws-minimal-esp32.c +++ b/minimal-examples/embedded/esp32/esp-heltec-wb32/main/lws-minimal-esp32.c @@ -1,7 +1,7 @@ /* * lws-minimal-esp32 * - * Written in 2010-2020 by Andy Green + * Written in 2010-2022 by Andy Green * * This file is made available under the Creative Commons CC0 1.0 * Universal Public Domain Dedication. @@ -153,6 +153,7 @@ void app_main(void) { struct lws_context_creation_info *info; + lws_box_t box = { {0,0}, {0,0}, {128,0}, {64,0} }; lws_set_log_level(1024 | 15, NULL); @@ -196,7 +197,7 @@ app_main(void) /* put the logo on the OLED display */ - lds.disp->blit(lds.disp, img, 0, 0, 128, 64); + lds.disp->blit(&lds, img, &box); lws_display_state_active(&lds); /* the lws event loop */ diff --git a/minimal-examples/embedded/esp32/esp-wrover-kit/main/devices.c b/minimal-examples/embedded/esp32/esp-wrover-kit/main/devices.c index f27650f8a..c1c626980 100644 --- a/minimal-examples/embedded/esp32/esp-wrover-kit/main/devices.c +++ b/minimal-examples/embedded/esp32/esp-wrover-kit/main/devices.c @@ -1,7 +1,7 @@ /* * devices for ESP WROVER KIT * - * Written in 2010-2020 by Andy Green + * Written in 2010-2022 by Andy Green * * This file is made available under the Creative Commons CC0 1.0 * Universal Public Domain Dedication. @@ -143,8 +143,10 @@ static const lws_display_ili9341_t disp = { .bl_dim = &lws_pwmseq_static_half, .bl_transition = &lws_pwmseq_linear_wipe, .bl_index = 3, - .w = 320, - .h = 240, + .ic = { + .wh_px = { { 320,0 }, { 240,0 } }, + .wh_mm = { { 64,00000000 }, { 48,00000000 } }, + }, .latency_wake_ms = 150, }, .spi = (lws_spi_ops_t *)&lbspi, diff --git a/minimal-examples/embedded/esp32/esp-wrover-kit/main/lws-minimal-esp32.c b/minimal-examples/embedded/esp32/esp-wrover-kit/main/lws-minimal-esp32.c index 5843317b6..91cc40898 100644 --- a/minimal-examples/embedded/esp32/esp-wrover-kit/main/lws-minimal-esp32.c +++ b/minimal-examples/embedded/esp32/esp-wrover-kit/main/lws-minimal-esp32.c @@ -1,7 +1,7 @@ /* * lws-minimal-esp32 * - * Written in 2010-2020 by Andy Green + * Written in 2010-2022 by Andy Green * * This file is made available under the Creative Commons CC0 1.0 * Universal Public Domain Dedication. @@ -116,7 +116,7 @@ myss_state(void *userobj, void *sh, lws_ss_constate_t state, switch (state) { case LWSSSCS_CREATING: - lws_ss_client_connect(m->ss); + return lws_ss_client_connect(m->ss); break; default: break; @@ -183,6 +183,7 @@ void app_main(void) { struct lws_context_creation_info *info; + lws_box_t box = { {0,0}, {0,0}, {320,0}, {240,0} }; lws_set_log_level(1024 | 15, NULL); @@ -231,7 +232,7 @@ app_main(void) /* put the cat picture up there and enable the backlight */ - lds.disp->blit(lds.disp, logo, 0, 0, 320, 240); + lds.disp->blit(&lds, logo, &box); lws_display_state_active(&lds); /* the lws event loop */