mirror of
https://github.com/warmcat/libwebsockets.git
synced 2025-03-09 00:00:04 +01:00
lws_display: improve apis to use display_state and frac
Adapt disp ops to use lws_display_state_t instead of the const disp object. Describe display area in pixels and mm using lws_fixed3232.
This commit is contained in:
parent
1d3ec6a3a1
commit
aa696773f0
11 changed files with 396 additions and 75 deletions
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
* lws abstract display
|
||||
*
|
||||
* Copyright (C) 2019 - 2020 Andy Green <andy@warmcat.com>
|
||||
* Copyright (C) 2019 - 2022 Andy Green <andy@warmcat.com>
|
||||
*
|
||||
* 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 <stdint.h>
|
||||
|
||||
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;
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
* lws abstract display implementation for ili9341 on spi
|
||||
*
|
||||
* Copyright (C) 2019 - 2020 Andy Green <andy@warmcat.com>
|
||||
* Copyright (C) 2019 - 2022 Andy Green <andy@warmcat.com>
|
||||
*
|
||||
* 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, \
|
||||
|
|
|
@ -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, \
|
||||
|
|
|
@ -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];
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
* lws abstract display
|
||||
*
|
||||
* Copyright (C) 2019 - 2020 Andy Green <andy@warmcat.com>
|
||||
* Copyright (C) 2019 - 2022 Andy Green <andy@warmcat.com>
|
||||
*
|
||||
* 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 <libwebsockets.h>
|
||||
#include <private-lib-core.h>
|
||||
|
||||
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 <stdio.h>
|
||||
* #include <math.h>
|
||||
*
|
||||
* 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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
* devices for ESP32 C3 dev board
|
||||
*
|
||||
* Written in 2010-2021 by Andy Green <andy@warmcat.com>
|
||||
* Written in 2010-2022 by Andy Green <andy@warmcat.com>
|
||||
*
|
||||
* 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,
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
* devices for ESP32 Heltec WB32
|
||||
*
|
||||
* Written in 2010-2020 by Andy Green <andy@warmcat.com>
|
||||
* Written in 2010-2022 by Andy Green <andy@warmcat.com>
|
||||
*
|
||||
* 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,
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
* lws-minimal-esp32
|
||||
*
|
||||
* Written in 2010-2020 by Andy Green <andy@warmcat.com>
|
||||
* Written in 2010-2022 by Andy Green <andy@warmcat.com>
|
||||
*
|
||||
* 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 */
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
* devices for ESP WROVER KIT
|
||||
*
|
||||
* Written in 2010-2020 by Andy Green <andy@warmcat.com>
|
||||
* Written in 2010-2022 by Andy Green <andy@warmcat.com>
|
||||
*
|
||||
* 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,
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
* lws-minimal-esp32
|
||||
*
|
||||
* Written in 2010-2020 by Andy Green <andy@warmcat.com>
|
||||
* Written in 2010-2022 by Andy Green <andy@warmcat.com>
|
||||
*
|
||||
* 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 */
|
||||
|
|
Loading…
Add table
Reference in a new issue