lcd/apa102: Add putarea() support for faster rendering

This commit is contained in:
Alan Carvalho de Assis
2022-07-19 17:40:31 -03:00
committed by Xiang Xiao
parent b10658653b
commit 9587e4a85e
+93 -41
View File
@@ -159,6 +159,10 @@ struct apa102_dev_s
static int apa102_putrun(FAR struct lcd_dev_s *dev, fb_coord_t row, static int apa102_putrun(FAR struct lcd_dev_s *dev, fb_coord_t row,
fb_coord_t col, FAR const uint8_t *buffer, fb_coord_t col, FAR const uint8_t *buffer,
size_t npixels); size_t npixels);
static int apa102_putarea(FAR struct lcd_dev_s *dev,
fb_coord_t row_start, fb_coord_t row_end,
fb_coord_t col_start, fb_coord_t col_end,
FAR const uint8_t *buffer);
static int apa102_getrun(FAR struct lcd_dev_s *dev, fb_coord_t row, static int apa102_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);
@@ -215,7 +219,7 @@ static const struct fb_videoinfo_s g_videoinfo =
static const struct lcd_planeinfo_s g_planeinfo = static const struct lcd_planeinfo_s g_planeinfo =
{ {
apa102_putrun, /* Put a run into LCD memory */ apa102_putrun, /* Put a run into LCD memory */
NULL, /* No putarea function */ apa102_putarea, /* Put a run into LCD memory */
apa102_getrun, /* Get a run from LCD memory */ apa102_getrun, /* Get a run from LCD memory */
NULL, /* No getarea function */ NULL, /* No getarea function */
NULL, /* No redraw function */ NULL, /* No redraw function */
@@ -347,6 +351,47 @@ static inline void apa102_write32(FAR struct apa102_dev_s *priv,
SPI_LOCK(priv->spi, false); SPI_LOCK(priv->spi, false);
} }
/****************************************************************************
* Name: apa102_refresh
*
* Description:
* Send converted framebuffer to the APA102 LED Matrix
*
****************************************************************************/
static inline void apa102_refresh(FAR struct apa102_dev_s *priv)
{
int i;
/* Confirm that SPI is configured correctly */
apa102_configspi(priv->spi);
/* Send a start of frame */
apa102_write32(priv, APA102_START_FRAME);
/* Send all LEDs values in the matrix */
for (i = 0; i < (APA102_XRES * APA102_YRES); i++)
{
uint32_t *led = (uint32_t *) &priv->fb[i];
/* Then transfer 4 bytes per LED */
apa102_write32(priv, (uint32_t) (*led | APA102_HEADER_FRAME));
}
/* Send an end of frame */
apa102_write32(priv, APA102_END_FRAME);
for (i = 0; i < (1 + APA102_XRES * APA102_YRES / 32); i++)
{
apa102_write32(priv, 0);
}
}
/**************************************************************************** /****************************************************************************
* Name: apa102_putrun * Name: apa102_putrun
* *
@@ -401,33 +446,58 @@ static int apa102_putrun(FAR struct lcd_dev_s *dev, fb_coord_t row,
priv->fb[(row * APA102_XRES) + col + i] = rgb565_apa102(*ptr++); priv->fb[(row * APA102_XRES) + col + i] = rgb565_apa102(*ptr++);
} }
/* Confirm that SPI is configured correctly */ /* Update the display with converted data */
apa102_configspi(priv->spi); apa102_refresh(priv);
/* Send a start of frame */ return OK;
apa102_write32(priv, APA102_START_FRAME);
/* Send all LEDs values in the matrix */
for (i = 0; i < (APA102_XRES * APA102_YRES); i++)
{
uint32_t *led = (uint32_t *) &priv->fb[i];
/* Then transfer 4 bytes per LED */
apa102_write32(priv, (uint32_t) (*led | APA102_HEADER_FRAME));
} }
/* Send an end of frame */ /****************************************************************************
* Name: apa102_putarea
*
* Description:
* This method can be used to write a partial area to the LCD:
*
* dev - The lcd device
* row_start - Starting row to write to (range: 0 <= row < yres)
* row_end - Ending row to write to (range: row_start <= row < yres)
* col_start - Starting column to write to (range: 0 <= col <= xres)
* col_end - Ending column to write to
* (range: col_start <= col_end < xres)
* buffer - The buffer containing the area to be written to the LCD
*
****************************************************************************/
apa102_write32(priv, APA102_END_FRAME); static int apa102_putarea(FAR struct lcd_dev_s *dev,
fb_coord_t row_start, fb_coord_t row_end,
for (i = 0; i < (1 + APA102_XRES * APA102_YRES / 32); i++) fb_coord_t col_start, fb_coord_t col_end,
FAR const uint8_t *buffer)
{ {
apa102_write32(priv, 0); FAR struct apa102_dev_s *priv = (FAR struct apa102_dev_s *)dev;
FAR uint16_t *src = (FAR uint16_t *)buffer;
int i;
int j;
ginfo("row_start: %d row_end: %d col_start: %d col_end: %d\n",
row_start, row_end, col_start, col_end);
DEBUGASSERT(buffer && ((uintptr_t)buffer & 1) == 0);
/* Convert RGB565 to APA102 LED values */
for (i = row_start; i <= row_end; i++)
{
for (j = col_start; j <= col_end; j++)
{
priv->fb[(i * APA102_XRES) + j] =
rgb565_apa102(*(src + (i * APA102_XRES) + j));
} }
}
/* Update the display with converted data */
apa102_refresh(priv);
return OK; return OK;
} }
@@ -611,27 +681,9 @@ static inline void up_clear(FAR struct apa102_dev_s *priv)
memset(priv->fb, APA102_BLACK, 4 * APA102_FBSIZE); memset(priv->fb, APA102_BLACK, 4 * APA102_FBSIZE);
/* Send a start of frame */ /* Update the display with framebuffer data */
apa102_write32(priv, APA102_START_FRAME); apa102_refresh(priv);
/* Clear all LEDs values in the matrix */
for (i = 0; i < (APA102_XRES * APA102_YRES); i++)
{
/* Then transfer 4 bytes per LED */
apa102_write32(priv, (uint32_t) (APA102_BLACK | APA102_HEADER_FRAME));
}
/* Send an end of frame */
apa102_write32(priv, APA102_END_FRAME);
for (i = 0; i < (1 + APA102_XRES * APA102_YRES / 32); i++)
{
apa102_write32(priv, 0);
}
} }
/**************************************************************************** /****************************************************************************