Text looks garbled

Description

The text on the label is garbled as soon as it is refreshed.

What MCU/Processor/Board and compiler are you using?

Nucleo-F401RE
1.8" SPI LCD TFT 128x160 ST7735
System Workbench for STM32

What do you want to achieve?

I want to know why the text is garbled.

What have you tried so far?

I can drive the screen. Text appears at first smoothly.

Code to reproduce

static lv_style_t style0_bar_1;
static lv_style_t style0_label_1;
static lv_style_t style0_label_2;

void my_task(lv_task_t * task);

void demo_create(void)
{
    lv_obj_t *parent = lv_disp_get_scr_act(NULL);
    lv_task_t * task = lv_task_create(my_task, 500, LV_TASK_PRIO_MID, 0);

#ifdef LV_USE_BAR
    lv_style_copy(&style0_bar_1, &lv_style_pretty);
    style0_bar_1.body.grad_color = lv_color_hex(0xaaff00);
    style0_bar_1.body.radius = 10;
    style0_bar_1.body.border.color = lv_color_hex(0xff0000);
    style0_bar_1.body.shadow.width = 2;

    bar_1 = lv_bar_create(parent, NULL);
    lv_obj_set_pos(bar_1, 15, 34);
    lv_obj_set_size(bar_1, 126, 24);
    lv_bar_set_value(bar_1, 50, LV_ANIM_ON);
    lv_bar_set_style(bar_1, LV_BAR_STYLE_BG, &style0_bar_1);
#endif // LV_USE_BAR

#ifdef LV_USE_LABEL
    lv_style_copy(&style0_label_1, &lv_style_transp);
    style0_label_1.text.color = lv_color_hex(0x303030);
    style0_label_1.text.sel_color = lv_color_hex(0x5596d8);
    style0_label_1.text.font = &lv_font_roboto_16;
    style0_label_1.text.letter_space = 0;
    style0_label_1.text.line_space = 2;
    style0_label_1.text.opa = 255;

    label_1 = lv_label_create(parent, NULL);
    lv_label_set_text(label_1, "Fan:");
    lv_obj_set_pos(label_1, 45, 69);
    lv_obj_set_size(label_1, 31, 19);
    lv_label_set_style(label_1, LV_LABEL_STYLE_MAIN, &style0_label_1);
#endif // LV_USE_LABEL

#ifdef LV_USE_LABEL
    lv_style_copy(&style0_label_2, &lv_style_transp);
    style0_label_2.text.color = lv_color_hex(0x303030);
    style0_label_2.text.sel_color = lv_color_hex(0x5596d8);
    style0_label_2.text.font = &lv_font_roboto_16;
    style0_label_2.text.letter_space = 0;
    style0_label_2.text.line_space = 2;
    style0_label_2.text.opa = 255;

    label_2 = lv_label_create(parent, NULL);
    lv_label_set_text(label_2, "0");
    lv_obj_set_pos(label_2, 84, 69);
    lv_obj_set_size(label_2, 9, 19);
    lv_label_set_style(label_2, LV_LABEL_STYLE_MAIN, &style0_label_2);
#endif // LV_USE_LABEL
}

void my_task(lv_task_t * task)
{
    lv_label_set_text(label_2, "20");
}

Screenshot and/or video

Looks like an issue with your display driver. Perhaps you are flushing one extra column/row?

static void tft_flush(lv_disp_drv_t * drv, const lv_area_t * area, lv_color_t * color_p)
{
     /*Return if the area is out the screen*/
     if(area->x2 < 0) return;
     if(area->y2 < 0) return;
     if(area->x1 > TFT_HOR_RES - 1) return;
     if(area->y1 > TFT_VER_RES - 1) return;

     uint32_t x=0, y=0;
     for(y=area->y1;y<=area->y2;y++)
     {
         for(x=area->x1;x<area->x2;x++)
         {
             ST7735_DrawPixel(x, y, color_p->full);
             color_p++;
         }
     }

     lv_disp_flush_ready(disp);
 }

I called the lv_tick_inc(1); every 1 millisecond.

while (1)
{
  lv_task_handler();
  HAL_Delay(10);
}

My TFT Init function

void tft_init(void)
{
   ST7735_Init();
   ST7735_FillScreen(ST7735_BLACK);
   static lv_disp_buf_t disp_buf_1;
   static lv_color_t buf1_1[LV_HOR_RES_MAX * 1];                      /*A buffer for 10 rows*/
   lv_disp_buf_init(&disp_buf_1, buf1_1, NULL, LV_HOR_RES_MAX * 1);   /*Initialize the display buffer*/

   /*-----------------------------------
   * Register the display in LittlevGL
   *----------------------------------*/

   lv_disp_drv_t disp_drv;                         /*Descriptor of a display driver*/
   lv_disp_drv_init(&disp_drv);                    /*Basic initialization*/

   /*Set up the functions to access to your display*/

   /*Set the resolution of the display*/
   disp_drv.hor_res = 160;
   disp_drv.ver_res = 128;

   /*Used to copy the buffer's content to the display*/
   disp_drv.flush_cb = tft_flush;

   /*Set a display buffer*/
   disp_drv.buffer = &disp_buf_1;

   /*Finally register the driver*/
   disp = lv_disp_drv_register(&disp_drv);
}

Wouldn’t it be “y < area->y2” instead of “y <= area->y2” ?

1 Like

I solved my problem with changing signs. Thank you @Baldhead

for(y=area->y1;y<=area->y2;y++)
{
    for(x=area->x1;x<=area->x2;x++)
    {
         ST7735_DrawPixel(x, y, color_p->full);
         color_p++;
    }
}