Description
I have interface mip memory LCD with lvgl (LPM013M126C). But the frame rate is really slow, i want to know if you have a better idea for interface this display. Maybe with the round function callback?
What MCU/Processor/Board and compiler are you using?
STM32L496, STMCubeIDE
What do you want to achieve?
Get a better frame rate, optimize my flush function.
What have you tried so far?
I have a working driver with or without DMA but the frame rate is still slow.
Code to reproduce
void lv_init(void)
{
static lv_disp_draw_buf_t disp_buf;
static lv_color_t
buf1[LV_VER_RES_MAX*LV_HOR_RES_MAX / 10 ];
lv_disp_draw_buf_init( &disp_buf, buf1, NULL, LV_VER_RES_MAX * LV_HOR_RES_MAX / 10 );
static lv_disp_drv_t disp_drv;
lv_disp_drv_init( &disp_drv );
disp_drv.hor_res = LV_HOR_RES_MAX;
disp_drv.ver_res = LV_VER_RES_MAX;
disp_drv.flush_cb = lv_port_flush;
disp_drv.set_px_cb = lv_port_set_px;
disp_drv.rounder_cb = lv_port_rounder_cb;
disp_drv.draw_buf = &disp_buf;
lv_disp_drv_register(&disp_drv);
}
void lv_port_flush(lv_disp_drv_t * disp_drv, const lv_area_t * area, lv_color_t * color_p)
{
int row = area->y1; // select the row
int address = ( unsigned int )row + area->x1 / 2; // select the address in the column
char *buffer;
int linelen = ( area->x2 - area->x1 ) / 2;
buffer = ( char * )color_p;
lpm013m126a_WriteMultipleLines(buffer, address, (area->y2 - area->y1 + 1), linelen);
lv_disp_flush_ready(disp_drv);
}
void lpm013m126a_WriteMultipleLines(char* line_cmd, int firstLine, int linesNb, int linelen)
{
int32_t j;
if( ( firstLine < 0 )||
( firstLine + linesNb > LV_VER_RES_MAX ) ) {
/* out of device size */
return;
}
lpm013m16a_StartUpdate();
for(uint8_t line = firstLine; line < (firstLine + linesNb); line+=lcd_cmd_line)
{
lpm013m16a_Cmd( line + 1 ); // Gate line address (8 bits = 10bits - 2 dummy bits of address)
for( j = 0 ; j < (LV_HOR_RES_MAX/2) ; j++ ) {
if( j >= (LV_HOR_RES_MAX/2) ) {
/* out of device size */
break;
}
lpm013m16a_Cmd(line_cmd[j]); // data (n x 2 x 4 bits)
}
for( ; j < (LV_HOR_RES_MAX/2) ; j++ ) {
/* padding to device size */
lpm013m16a_Cmd( 0x00 );
}
lpm013m16a_Cmd( 0x00 ); // dummy (6bits + 2 dummy bits of address)
line_cmd += linelen+1;
}
lpm013m16a_Cmd( 0x00 ); // dummy (8bits)
lpm013m16a_StopUpdate();
}
void lpm013m16a_Cmd(uint8_t data)
{
/* Add data the the transmit buffer */
my_fb[y_fill_act] = data;
/* Increase counter */
y_fill_act++;
}
void lpm013m16a_StartUpdate( void )
{
/* reset buffer to 0 */
memset( my_fb, 0, y_fill_act );
/* Reset buffer counter to 0 */
y_fill_act = 0;
lpm013m16a_Cmd( LCD_CMD_UPDATE );
}
uint8_t lpm013m16a_StopUpdate(void)
{
GpioWrite( &LcdNss, 1 );
HAL_SPI_Transmit( &lcdSpi, my_fb, y_fill_act, 4000 );
GpioWrite( &LcdNss, 0 );
}
static void lv_port_set_px(lv_disp_drv_t * disp_drv, uint8_t * buf, lv_coord_t buf_w, lv_coord_t x, lv_coord_t y, lv_color_t color, lv_opa_t opa)
{
buf += buf_w/2 * y;
buf += x/2;
uint8_t color4Bit = (( lv_color_to8( color ) & (1<<7) ) >> 4 ) | // keep Red LSB shifted from bit-7 to bit-3
(( lv_color_to8( color ) & (1<<4) ) >> 2 ) | // keep Green LSB shifted from bit-4 to bit-2
(( lv_color_to8( color ) & (1<<1) ) ) ; // keep Blue LSB shifted from bit-1 to bit-1
if( ( x % 2 ) == 0 )
{
(*buf) = 0; // Clean the pair of pixel --> TODO : Risk of artefact if accessing only an impair pixel
(*buf) |= (color4Bit << 4 ); // set color bits to 4 MSB
}
else
{
(*buf) |= (color4Bit ); // set color bits to 4 LSB
}
}
static void lv_port_rounder_cb( lv_disp_drv_t * disp_drv, lv_area_t * area )
{
/* Round area to a whole line */
area->x1 = 0;
area->x2 = LV_HOR_RES_MAX - 1;
}