New rules of triggering redrawing display.

New callback redraw in lcd_framebuffer.c
SSD1680 driver (e-ink display) changes.
This commit is contained in:
Adam Kaliszan 2022-07-04 09:14:51 +02:00 committed by Xiang Xiao
parent a4e867b8d4
commit 664d45dcba
3 changed files with 89 additions and 69 deletions

View File

@ -211,43 +211,52 @@ static int lcdfb_updateearea(FAR struct fb_vtable_s *vtable,
unsigned int pixperbyte = 8 / pinfo->bpp; unsigned int pixperbyte = 8 / pinfo->bpp;
startx &= ~(pixperbyte - 1); startx &= ~(pixperbyte - 1);
} }
}
if (pinfo->putarea != NULL)
{
/* Each Driver's callback function putarea may be optimized by checking
* if it is a full screen/full row mode or not.
* In case of full screen/row mode the memory layout of drivers memory
* and data provided to putarea function may be (or not, it depends of
* display and driver implementation) identical.
* Identical memory layout let us to use:
* - memcopy (if there is shadow buffer in driver implementation)
* - apply DMA channel to transfer data to driver memory.
*/
ret = pinfo->putarea(pinfo->dev, starty, endy, startx, endx, run);
if (ret < 0)
{
lcderr("Failed to update area");
return ret;
}
}
else
{
width = endx - startx + 1; width = endx - startx + 1;
/* Get the starting position in the framebuffer */ /* Get the starting position in the framebuffer */
run = priv->fbmem + starty * priv->stride; run = priv->fbmem + starty * priv->stride;
run += (startx * pinfo->bpp + 7) >> 3; run += (startx * pinfo->bpp + 7) >> 3;
}
/* Update the whole screen? */ for (row = starty; row <= endy; row++)
if (startx == 0 && endx == priv->xres - 1 &&
starty == 0 && endy == priv->yres - 1)
{
/* Yes, LCD driver support putarea callback? */
if (pinfo->putarea != NULL)
{ {
/* Yes, go the fast path */ ret = pinfo->putrun(pinfo->dev, row, startx, run, width);
if (ret < 0)
{
lcderr("Failed to update row");
return ret;
}
return pinfo->putarea(pinfo->dev, starty, endy, startx, endx, run); run += priv->stride;
} }
} }
for (row = starty; row <= endy; row++) if (pinfo->redraw != NULL)
{ {
/* REVISIT: Some LCD hardware certain alignment requirements on DMA pinfo->redraw(pinfo->dev);
* memory.
*/
ret = pinfo->putrun(pinfo->dev, row, startx, run, width);
if (ret < 0)
{
return ret;
}
run += priv->stride;
} }
return OK; return OK;

View File

@ -126,33 +126,38 @@ struct ssd1680_dev_s
/* Libc extension */ /* Libc extension */
FAR void *bitscpy_ds(FAR void *dest, int dest_offset, FAR const void *src, static FAR void *bitscpy_ds(FAR void *dest, int dest_offset,
size_t nbits); FAR const void *src, size_t nbits);
FAR void *bitscpy_ss(FAR void *dest, FAR const void *src, int src_offset, static FAR void *bitscpy_ss(FAR void *dest, FAR const void *src,
size_t nbits); int src_offset, size_t nbits);
/* LCD Data Transfer Methods */ /* LCD Data Transfer Methods */
static int ssd1680_busy_wait(FAR struct ssd1680_dev_s *priv); static int ssd1680_busy_wait(FAR struct ssd1680_dev_s *priv);
static void ssd1680_snd_cmd_with_data0(FAR struct ssd1680_dev_s *priv, static void ssd1680_snd_cmd_with_data0(FAR struct ssd1680_dev_s *priv,
uint8_t cmd); uint8_t cmd);
static void ssd1680_snd_cmd_with_data1(FAR struct ssd1680_dev_s *priv, static void ssd1680_snd_cmd_with_data1(FAR struct ssd1680_dev_s *priv,
uint8_t cmd, uint8_t dta1); uint8_t cmd, uint8_t dta1);
static void ssd1680_snd_cmd_with_data2(FAR struct ssd1680_dev_s *priv, static void ssd1680_snd_cmd_with_data2(FAR struct ssd1680_dev_s *priv,
uint8_t cmd, uint8_t dta1, uint8_t dta2); uint8_t cmd, uint8_t dta1,
uint8_t dta2);
static void ssd1680_snd_cmd_with_data3(FAR struct ssd1680_dev_s *priv, static void ssd1680_snd_cmd_with_data3(FAR struct ssd1680_dev_s *priv,
uint8_t cmd, uint8_t dta1, uint8_t dta2, uint8_t dta3); uint8_t cmd, uint8_t dta1,
uint8_t dta2, uint8_t dta3);
static void ssd1680_snd_cmd_with_data4(FAR struct ssd1680_dev_s *priv, static void ssd1680_snd_cmd_with_data4(FAR struct ssd1680_dev_s *priv,
uint8_t cmd, uint8_t dta1, uint8_t dta2, uint8_t dta3, uint8_t dta4); uint8_t cmd, uint8_t dta1,
uint8_t dta2, uint8_t dta3,
uint8_t dta4);
static void ssd1680_snd_cmd_with_data(FAR struct ssd1680_dev_s *priv, static void ssd1680_snd_cmd_with_data(FAR struct ssd1680_dev_s *priv,
uint8_t cmd, const uint8_t *dta, int dta_len); uint8_t cmd, const uint8_t *dta,
int dta_len);
#if !defined(CONFIG_LCD_PORTRAIT) && !defined(CONFIG_LCD_RPORTRAIT) #if !defined(CONFIG_LCD_PORTRAIT) && !defined(CONFIG_LCD_RPORTRAIT)
# if SSD1680_DEV_BPP == 1 # if SSD1680_DEV_BPP == 1
@ -179,6 +184,8 @@ static int ssd1680_getrun(FAR struct lcd_dev_s *dev, fb_coord_t row,
fb_coord_t col, FAR uint8_t *buffer, fb_coord_t col, FAR uint8_t *buffer,
size_t npixels); size_t npixels);
static int ssd1680_redraw(FAR struct lcd_dev_s *dev);
/* LCD Configuration */ /* LCD Configuration */
static int ssd1680_getvideoinfo(FAR struct lcd_dev_s *dev, static int ssd1680_getvideoinfo(FAR struct lcd_dev_s *dev,
@ -207,7 +214,7 @@ static int ssd1680_setpower(struct lcd_dev_s *dev, int power);
static int ssd1680_configuredisplay(struct ssd1680_dev_s *priv); static int ssd1680_configuredisplay(struct ssd1680_dev_s *priv);
static int ssd1680_redraw_display(struct ssd1680_dev_s *priv); static int ssd1680_redraw_display(struct ssd1680_dev_s *priv);
static int ssd1680_update_row(struct ssd1680_dev_s *priv, int row); static int ssd1680_update_row(struct ssd1680_dev_s *priv, int row);
static int ssd1680_update_all(struct ssd1680_dev_s *priv); static int ssd1680_update_all_and_redraw(struct ssd1680_dev_s *priv);
/**************************************************************************** /****************************************************************************
* Private Data * Private Data
@ -244,6 +251,7 @@ static const struct lcd_planeinfo_s g_planeinfo =
.putarea = NULL, /* Not need to implement */ .putarea = NULL, /* Not need to implement */
.getrun = ssd1680_getrun, /* Read content of shadow memory */ .getrun = ssd1680_getrun, /* Read content of shadow memory */
.getarea = NULL, /* Not need to implement */ .getarea = NULL, /* Not need to implement */
.redraw = ssd1680_redraw, /* Update drivers memory and redraw */
.buffer = (FAR uint8_t *)g_runbuffer, /* Run scratch buffer */ .buffer = (FAR uint8_t *)g_runbuffer, /* Run scratch buffer */
.bpp = SSD1680_DEV_BPP, /* Bits-per-pixel */ .bpp = SSD1680_DEV_BPP, /* Bits-per-pixel */
}; };
@ -331,16 +339,6 @@ static int ssd1680_putrun(FAR struct lcd_dev_s *dev, fb_coord_t row,
{ {
FAR struct ssd1680_dev_s *priv = (FAR struct ssd1680_dev_s *)dev; FAR struct ssd1680_dev_s *priv = (FAR struct ssd1680_dev_s *)dev;
/* TODO Special IOCTL function in lcd_framebuf has to be implemented.
* Those function would call ssd1680_putrun with npixels = 0
*/
if (npixels == 0)
{
ssd1680_redraw_display(priv);
return OK;
}
uint8_t *dst = priv->shadow_fb + uint8_t *dst = priv->shadow_fb +
row * SSD1680_DEV_ROWSIZE + (col >> SSD1680_PDF); row * SSD1680_DEV_ROWSIZE + (col >> SSD1680_PDF);
@ -350,17 +348,6 @@ static int ssd1680_putrun(FAR struct lcd_dev_s *dev, fb_coord_t row,
bitscpy_ds(dst, dst_start_bitshift, buffer, npixels); bitscpy_ds(dst, dst_start_bitshift, buffer, npixels);
/* Write data to memory of display driver */
ssd1680_update_row(priv, row);
/* TODO Remove it after IOCTL refresh implementation */
if (row == SSD1680_DEV_FB_YRES / 2)
{
ssd1680_redraw_display(priv);
}
return OK; return OK;
} }
@ -385,7 +372,6 @@ static int ssd1680_getrun(FAR struct lcd_dev_s *dev, fb_coord_t row,
fb_coord_t col, FAR uint8_t *buffer, fb_coord_t col, FAR uint8_t *buffer,
size_t npixels) size_t npixels)
{ {
lcdinfo("(%d, %d, %d)\n", row, col, npixels);
FAR struct ssd1680_dev_s *priv = (FAR struct ssd1680_dev_s *)dev; FAR struct ssd1680_dev_s *priv = (FAR struct ssd1680_dev_s *)dev;
bitscpy_ss(buffer, bitscpy_ss(buffer,
@ -396,6 +382,12 @@ static int ssd1680_getrun(FAR struct lcd_dev_s *dev, fb_coord_t row,
return OK; return OK;
} }
static int ssd1680_redraw(FAR struct lcd_dev_s *dev)
{
FAR struct ssd1680_dev_s *priv = (FAR struct ssd1680_dev_s *)dev;
return ssd1680_update_all_and_redraw(priv);
}
/**************************************************************************** /****************************************************************************
* Name: ssd1680_getvideoinfo * Name: ssd1680_getvideoinfo
* *
@ -529,17 +521,18 @@ static int ssd1680_setpower(FAR struct lcd_dev_s *dev, int power)
ret = ssd1680_configuredisplay(priv); ret = ssd1680_configuredisplay(priv);
if (ret != OK) if (ret != OK)
{ {
lcderr("Failed to configure display\n");
return ret; return ret;
} }
/* Draw the framebuffer */ /* Draw the framebuffer */
ret = ssd1680_update_all(priv); ret = ssd1680_update_all_and_redraw(priv);
} if (ret != OK)
{
if (ret < 0) lcderr("Failed to update and redraw\n");
{ return ret;
return ret; }
} }
priv->on = true; priv->on = true;
@ -722,10 +715,11 @@ static int ssd1680_configuredisplay(struct ssd1680_dev_s *priv)
} }
/**************************************************************************** /****************************************************************************
* Name: ssd1680_update_all * Name: ssd1680_update_all_and_redraw
* *
* Description: * Description:
* Redraw full framebuffer to display * Copy content of shadow buffer to drivers memory.
* Redraws the display
* *
* Input Parameters: * Input Parameters:
* priv - Reference to private driver structure * priv - Reference to private driver structure
@ -738,7 +732,7 @@ static int ssd1680_configuredisplay(struct ssd1680_dev_s *priv)
* *
****************************************************************************/ ****************************************************************************/
static int ssd1680_update_all(struct ssd1680_dev_s *priv) static int ssd1680_update_all_and_redraw(struct ssd1680_dev_s *priv)
{ {
int row; int row;
for (row = 0; row < SSD1680_DEV_FB_YRES; row++) for (row = 0; row < SSD1680_DEV_FB_YRES; row++)
@ -752,6 +746,8 @@ static int ssd1680_update_all(struct ssd1680_dev_s *priv)
static int ssd1680_redraw_display(struct ssd1680_dev_s *priv) static int ssd1680_redraw_display(struct ssd1680_dev_s *priv)
{ {
/* Synchronize shadow buffer with drivers memory */
int ret; int ret;
/* Step 15: /* Step 15:
* Set control register 2. * Set control register 2.
@ -1312,8 +1308,8 @@ FAR struct lcd_dev_s *ssd1680_initialize(FAR struct spi_dev_s *dev,
return &priv->dev; return &priv->dev;
} }
FAR void *bitscpy_ds(FAR void *dest, int dest_offset, FAR const void *src, static FAR void *bitscpy_ds(FAR void *dest, int dest_offset,
size_t nbits) FAR const void *src, size_t nbits)
{ {
FAR unsigned char *pout = (FAR unsigned char *)dest; FAR unsigned char *pout = (FAR unsigned char *)dest;
FAR unsigned char *pin = (FAR unsigned char *)src; FAR unsigned char *pin = (FAR unsigned char *)src;
@ -1371,8 +1367,8 @@ FAR void *bitscpy_ds(FAR void *dest, int dest_offset, FAR const void *src,
return dest; return dest;
} }
FAR void *bitscpy_ss(FAR void *dest, FAR const void *src, int src_offset, static FAR void *bitscpy_ss(FAR void *dest, FAR const void *src,
size_t nbits) int src_offset, size_t nbits)
{ {
FAR unsigned char *pout = (FAR unsigned char *)dest; FAR unsigned char *pout = (FAR unsigned char *)dest;
FAR unsigned char *pin = (FAR unsigned char *)src; FAR unsigned char *pin = (FAR unsigned char *)src;

View File

@ -123,6 +123,21 @@ struct lcd_planeinfo_s
fb_coord_t row_end, fb_coord_t col_start, fb_coord_t row_end, fb_coord_t col_start,
fb_coord_t col_end, FAR uint8_t *buffer); fb_coord_t col_end, FAR uint8_t *buffer);
/* This method can be used to redraw display's content.
*
* dev - LCD interface to redraw its memory content
*
* NOTE: In case of non e-ink dispalys redrawing is cheap and can be done
* after each memory modification. Redrawing e-ink display is time and
* energy consuming.
* In order to avoid such operation (time and energy consumption) we can
* implement callback function putrun without redrawing the screen.
* Function putrun is called many times unless the function putarea is
* implemented.
*/
int (*redraw)(FAR struct lcd_dev_s *dev);
/* Plane color characteristics ********************************************/ /* Plane color characteristics ********************************************/
/* This is working memory allocated by the LCD driver for each LCD device /* This is working memory allocated by the LCD driver for each LCD device