Lv_draw_dsc_base_t - compliation error

Hi,
I am trying to create a coloured Table.
I found an example that uses lv_draw_dsc_base_t base_dsc = draw_task->draw_dsc; in a call back, I have tried compiling but continue to get the following error
Compilation error: invalid conversion from 'void
’ to ‘lv_draw_dsc_base_t*’ [-fpermissive]
Am I missing an include file or a #define in the config file? I am not sure where to start looking. I am using V9.1 on an ESP32 16MB custom board with a DFR0665, so everything is as I expect it to be excpet this issse.
Any advise would be greatly appreciated.
Kind Regards
Paul

Welcome Paul,

Please share your code if possible. In LVGL v9.1, the way draw event callbacks are handled has changed slightly, this may be part of the issue. Previously someone here had a similar question, see my answer there: Custom cell-draw in lv_table V9 - #2 by Tinus

Hope this helps somewhat but without seeing your code I cannot draw any conclusions on what’s wrong, seems like you are missing a typecast somewhere.

Hi,

As requested, here is my complete code

#include <lvgl.h>
#include <TFT_eSPI.h>

//copied from Arduino/libraries/lvgl/src/drivers/display/tft_espi/lv_tft_espi.cpp
typedef struct {
   TFT_eSPI * tft;
} lv_tft_espi_t;

const int screenHeight = TFT_HEIGHT; //320;
const int screenWidth = TFT_WIDTH;   //240;
const int bufSize = screenWidth*screenHeight/10 * LV_COLOR_DEPTH/8;
uint32_t buf[bufSize];  //screen buffer for TFT_eSPI

lv_display_t* disp;

static int16_t panel_padding        = 4;
static int16_t panel_border_width   = 2;
static int16_t panel_width          = screenWidth;
static int16_t panel_child_width    = (panel_width - ((panel_padding * 2) + (panel_border_width * 4)));
static int16_t button_panel_height  = 50;
static int16_t grid_panel_height    = screenHeight - button_panel_height - 15;
static int16_t ButW = ((panel_width - ((panel_padding * 2) + (panel_border_width * 4))) / 3);
static int16_t ButH = (button_panel_height - ((panel_padding * 2) + (panel_border_width * 3)));
unsigned long lastTickMillis = 0;

static lv_style_t style_menu_button;
static lv_style_t style_button;
static lv_style_t style_button_pressed;
static lv_style_t style_Button_panel;
static lv_style_t my_table_style;

#define LVGL_VER String(lv_version_major()) + "." + String(lv_version_minor()) + "." + String(lv_version_patch())
String text = "LVGL " + LVGL_VER + "\nand TFT_eSPI " + TFT_ESPI_VERSION;

#define SCREEN_ROTATION 2 // set the screen rotation
TFT_eSPI tft_touch = TFT_eSPI(screenWidth, screenHeight);

static lv_color_t darken(const lv_color_filter_dsc_t * dsc, lv_color_t color, lv_opa_t opa) {
  LV_UNUSED(dsc);
  return lv_color_darken(color, opa);
}

static void BtnA_event_cb(lv_event_t * e) {
  lv_event_code_t code = lv_event_get_code(e);
  lv_obj_t * BtnA = (lv_obj_t*) lv_event_get_target(e);
  lv_obj_t * BtnA_label = lv_obj_get_child(BtnA, 0);

  if(code == LV_EVENT_PRESSED) {
    lv_label_set_text(BtnA_label, "A_on");
  }
  else if(code == LV_EVENT_RELEASED) {
    lv_label_set_text(BtnA_label, "Menu");
  }
}

static void BtnB_event_cb(lv_event_t * e) {
  lv_event_code_t code = lv_event_get_code(e);
  lv_obj_t * BtnB = (lv_obj_t*) lv_event_get_target(e);
  lv_obj_t * BtnB_label = lv_obj_get_child(BtnB, 0);

  if(code == LV_EVENT_PRESSED) {
    lv_label_set_text(BtnB_label, "B_on");
  }
  else if(code == LV_EVENT_RELEASED) {
    lv_label_set_text(BtnB_label, "Pg Up");
  }
}

static void BtnC_event_cb(lv_event_t * e) {
  lv_event_code_t code = lv_event_get_code(e);
  lv_obj_t * BtnC = (lv_obj_t*) lv_event_get_target(e);
  lv_obj_t * BtnC_label = lv_obj_get_child(BtnC, 0);

  if(code == LV_EVENT_PRESSED) {
    lv_label_set_text(BtnC_label, "C_on");
  }
  else if(code == LV_EVENT_RELEASED) {
    lv_label_set_text(BtnC_label, "Pg Dn");
  }
}

static void draw_event_cb(lv_event_t *event) {
  lv_draw_task_t * draw_task = lv_event_get_draw_task(event);
  lv_draw_dsc_base_t * base_dsc = draw_task->draw_dsc;...................Arduino IDE 2.3.2 Compilation error here 
*Compilation error: invalid conversion from 'void*' to 'lv_draw_dsc_base_t*' [-fpermissive]*

  if(base_dsc->part == LV_PART_ITEMS) {
    uint32_t row = base_dsc->id1;
    uint32_t col = base_dsc->id2;
///////////////////////////////////////////////////////////////////
//    if (draw_task->type == LV_DRAW_TASK_TYPE_LABEL) {
//      lv_draw_label_dsc_t* label_dsc = draw_task->draw_dsc;

//      switch (col) {
//        case TABLE_COLUMN_FIELD:
//          label_dsc->align = LV_TEXT_ALIGN_LEFT;
//        break;

//        case TABLE_COLUMN_VALUE:
//          label_dsc->align = LV_TEXT_ALIGN_RIGHT;
//        break;

//        case TABLE_COLUMN_UNIT:
//          label_dsc->align = LV_TEXT_ALIGN_LEFT;
//          label_dsc->color = lv_color_hex(TABLE_COL_UNIT);
//        break;

//        default:
//        break;
//      }
//    }
///////////////////////////////////////////////////////////////////
  }
}

static void style_init(void) {
  // Create a simple button style: https://docs.lvgl.io/master/overview/style.html
  lv_style_init(&style_button);
  lv_style_set_radius(&style_button, 10);
  // Color documentation: https://docs.lvgl.io/master/overview/color.html
  lv_style_set_bg_opa(&style_button, LV_OPA_COVER);  // Set the opacity
  lv_style_set_bg_color(&style_button, lv_palette_lighten(LV_PALETTE_LIGHT_BLUE, 4));  // Set the background color
  lv_style_set_bg_grad_color(&style_button, lv_palette_main(LV_PALETTE_LIGHT_BLUE));
  lv_style_set_bg_grad_dir(&style_button, LV_GRAD_DIR_VER);

  // Set the border color, opacity, width, shadow (width, offset and opacity)
  lv_style_set_border_color(&style_button, lv_palette_darken(LV_PALETTE_GREY, 4));
  lv_style_set_border_opa(&style_button, LV_OPA_80);
  lv_style_set_border_width(&style_button, 4);
  lv_style_set_shadow_width(&style_button, 10);
  lv_style_set_shadow_offset_y(&style_button, 5);
  lv_style_set_shadow_opa(&style_button, LV_OPA_60);

  // Set the text color
  lv_style_set_text_color(&style_button, lv_color_hex(0x181717));

  // Create a style for the button pressed state
  // Use a color filter to simply modify all colors in this state and apply a dark effect
  static lv_color_filter_dsc_t color_filter;
  lv_color_filter_dsc_init(&color_filter, darken);
  lv_style_init(&style_button_pressed);
  lv_style_set_color_filter_dsc(&style_button_pressed, &color_filter);
  lv_style_set_color_filter_opa(&style_button_pressed, LV_OPA_10);

  /*Create a Menu Button style. Change only some colors.*/
  lv_style_init(&style_menu_button);
  lv_style_set_bg_color(&style_menu_button, lv_palette_main(LV_PALETTE_GREEN));
  lv_style_set_bg_grad_color(&style_menu_button, lv_palette_lighten(LV_PALETTE_GREEN, 4));

  /*Create a Button Panel style.*/
  lv_style_init(&style_Button_panel);
  lv_style_set_radius(&style_Button_panel, 10);
  lv_style_set_bg_color(&style_Button_panel, lv_palette_lighten(LV_PALETTE_GREY, 3));
  lv_style_set_border_width(&style_Button_panel, panel_border_width);
  lv_style_set_border_color(&style_Button_panel, lv_palette_main(LV_PALETTE_GREY));
  lv_style_set_pad_all(&style_Button_panel, panel_padding);

  /*Create a Table style.*/
  lv_style_init(&my_table_style);
  lv_style_set_max_height(&my_table_style, 30);
  lv_style_set_min_width(&my_table_style, 60);
  lv_style_set_max_width(&my_table_style, 70);
  lv_style_set_pad_all(&my_table_style, 5);
  lv_style_set_text_align(&my_table_style, LV_TEXT_ALIGN_CENTER);
}

void lv_create_main_gui(void) {
  // Initialize the style
  style_init();

  // Create Grid panel and use the new styles
  lv_obj_t *Grid_panel = lv_obj_create(lv_screen_active());
  lv_obj_set_size(Grid_panel, panel_width, grid_panel_height);
  lv_obj_add_style(Grid_panel, &style_Button_panel, 0);
  lv_obj_align(Grid_panel, LV_ALIGN_TOP_MID, 0, 0);

  lv_obj_t *SIOT_label = lv_label_create(Grid_panel);
  lv_obj_remove_style_all(SIOT_label);
  lv_label_set_text(SIOT_label, "SensorIoT");
  lv_obj_set_style_text_color(SIOT_label, lv_color_hex(0x181717), LV_PART_MAIN);
  lv_obj_set_style_text_font(SIOT_label, &lv_font_montserrat_24, LV_PART_MAIN);
  lv_obj_align(SIOT_label, LV_ALIGN_TOP_MID, 0, 0);

  lv_obj_t *Sensor_label = lv_label_create(Grid_panel);
  lv_obj_remove_style_all(Sensor_label);
  lv_label_set_text(Sensor_label, "Sensor Controller");
  lv_obj_set_style_text_color(Sensor_label, lv_palette_darken(LV_PALETTE_GREEN, 4), LV_PART_MAIN);
  lv_obj_set_style_text_font(Sensor_label, &lv_font_montserrat_18, LV_PART_MAIN);
  lv_obj_align(Sensor_label, LV_ALIGN_TOP_MID, 0, 24);

  lv_obj_t * table = lv_table_create(Grid_panel);
  lv_obj_add_style(table, &my_table_style, LV_PART_ITEMS);
  lv_table_set_column_count(table, 3);
  lv_obj_set_size(table, panel_child_width, 190);

  lv_table_set_col_width(table,0, ButW - 2);
  lv_table_set_col_width(table,1, ButW - 2);
  lv_table_set_col_width(table,2, ButW - 2);

  lv_table_set_cell_value(table, 0, 0, "NODE");
  lv_table_set_cell_value(table, 0, 1, "COMMS");
  lv_table_set_cell_value(table, 0, 2, "TX");

  for(int x = 1; x < 21; x++) {
    lv_table_set_cell_value(table, x, 0, "XXX");
    lv_table_set_cell_value(table, x, 1, "NULL");
    lv_table_set_cell_value(table, x, 2, "X");  // maybe highlight the row?
  }

  lv_obj_align(table, LV_ALIGN_TOP_MID, 0, 50);

//add an event callback to apply some custom drawing
  lv_obj_add_event_cb(table, draw_event_cb, LV_EVENT_DRAW_TASK_ADDED, NULL);
  lv_obj_add_flag(table, LV_OBJ_FLAG_SEND_DRAW_TASK_EVENTS);

// Create button panel and use the new styles
  lv_obj_t *Button_panel = lv_obj_create(lv_screen_active());
  lv_obj_set_size(Button_panel, panel_width, button_panel_height);
  lv_obj_add_style(Button_panel, &style_Button_panel, 0);
  lv_obj_align(Button_panel, LV_ALIGN_BOTTOM_MID, 0, -10);

  // Create button's and use the new styles
  lv_obj_t * BtnA = lv_button_create(Button_panel);
  lv_obj_remove_style_all(BtnA);
  lv_obj_set_size(BtnA, ButW, ButH);
  lv_obj_add_style(BtnA, &style_button, 0);
  lv_obj_add_style(BtnA, &style_menu_button, 0);
  lv_obj_add_style(BtnA, &style_button_pressed, LV_STATE_PRESSED);
  lv_obj_align(BtnA, LV_ALIGN_LEFT_MID, 0, 0);
  lv_obj_add_event_cb(BtnA, BtnA_event_cb, LV_EVENT_ALL, NULL);  // Assign a callback to the button

  lv_obj_t * BtnA_label = lv_label_create(BtnA);
  lv_label_set_text(BtnA_label, "Menu");
  lv_obj_center(BtnA_label);

  lv_obj_t * BtnB = lv_button_create(Button_panel);
  lv_obj_remove_style_all(BtnB);
  lv_obj_set_size(BtnB, ButW, ButH);
  lv_obj_add_style(BtnB, &style_button, 0);
  lv_obj_add_style(BtnB, &style_button_pressed, LV_STATE_PRESSED);
  lv_obj_align(BtnB, LV_ALIGN_CENTER, 0, 0);
  lv_obj_add_event_cb(BtnB, BtnB_event_cb, LV_EVENT_ALL, NULL);  // Assign a callback to the button

  lv_obj_t * BtnB_label = lv_label_create(BtnB);
  lv_label_set_text(BtnB_label, "Pg Up");
  lv_obj_center(BtnB_label);

  lv_obj_t * BtnC = lv_button_create(Button_panel);
  lv_obj_remove_style_all(BtnC);
  lv_obj_set_size(BtnC, ButW, ButH);
  lv_obj_add_style(BtnC, &style_button, 0);
  lv_obj_add_style(BtnC, &style_button_pressed, LV_STATE_PRESSED);
  lv_obj_align(BtnC, LV_ALIGN_RIGHT_MID, 0, 0);
  lv_obj_add_event_cb(BtnC, BtnC_event_cb, LV_EVENT_ALL, NULL);  // Assign a callback to the button

  lv_obj_t * BtnC_label = lv_label_create(BtnC);
  lv_label_set_text(BtnC_label, "Pg Dn");
  lv_obj_center(BtnC_label);
}

/* LVGL calls it when a rendered image needs to copied to the display*/
void my_disp_flush( lv_display_t *disp, const lv_area_t *area, uint8_t * px_map)
{
  Serial.println("my_disp_flush");
    /*Copy `px map` to the `area`*/

    /*For example ("my_..." functions needs to be implemented by you)
    uint32_t w = lv_area_get_width(area);
    uint32_t h = lv_area_get_height(area);

    my_set_window(area->x1, area->y1, w, h);
    my_draw_bitmaps(px_map, w * h);
     */

    /*Call it to tell LVGL you are ready*/
    lv_disp_flush_ready(disp);
}

/*Read the touchpad*/
void my_touchpad_read( lv_indev_t * indev, lv_indev_data_t * data )
{
    uint16_t touchX, touchY;
    bool touched = tft_touch.getTouch( &touchX, &touchY, 600 );
    if( !touched )
    {
        data->state = LV_INDEV_STATE_REL;
    }
    else
    {
        data->state = LV_INDEV_STATE_PR;
        /*Set the coordinates*/
        data->point.x = touchX;
        data->point.y = touchY;

//        Serial.print( "Data x " );
//        Serial.print( touchX );

//        Serial.print( ", Data y " );
//        Serial.println( touchY );
    }
}

void setup()
{
  Serial.begin( 115200 ); /* prepare for possible serial debug */
  delay(1000);
  Serial.println(text);
  delay(1000);
  lv_init();

  tft_touch.begin();
  tft_touch.setRotation(SCREEN_ROTATION);

    #if SCREEN_ROTATION == 0
      uint16_t calData[5] = { 301, 3439, 420, 3484, 4 };
    #elif SCREEN_ROTATION == 1
      uint16_t calData[5] = { 430, 3454, 298, 3418, 7 };
    #elif SCREEN_ROTATION == 2
      uint16_t calData[5] = { 304, 3454, 420, 3457, 2 };
    #elif SCREEN_ROTATION == 3
      uint16_t calData[5] = { 439, 3463, 282, 3460, 1 };
    #endif  

  tft_touch.setTouch(calData);

  disp = lv_tft_espi_create(screenWidth, screenHeight, buf, sizeof(buf)); //this calls tft_begin()

  /*Initialize the (dummy) input device driver*/
  lv_indev_t * indev = lv_indev_create();
  lv_indev_set_type(indev, LV_INDEV_TYPE_POINTER); /*Touchpad should have POINTER type*/
  lv_indev_set_read_cb(indev, my_touchpad_read);

  lv_create_main_gui();

  lv_tft_espi_t* dsc = (lv_tft_espi_t *)lv_display_get_driver_data(disp); //get access to the TFT_eSPI object
  dsc->tft->setRotation(SCREEN_ROTATION);  //set the screen rotation
  Serial.println( "Setup done" );  
}

void loop()
{
  // LVGL Tick Interface
  unsigned int tickPeriod = millis() - lastTickMillis;
  lv_tick_inc(tickPeriod);
  lastTickMillis = millis();
  // LVGL Task Handler
  lv_task_handler();
}

Not sure I have done this correctly, sorry first time I have posted code.

Hi Paul,

I think you will just need to use a typecast here,
so:

lv_draw_dsc_base_t * base_dsc = (lv_draw_dsc_base_t*)draw_task->draw_dsc

Kind regards

Hi Tinus,

Thank you so much. My code now compiles. All your help is much appreciated.

Thank you again.

Kind Regards
Paul

1 Like