From fd47406d1186c15dde3c8b235f4571c72e0b377e Mon Sep 17 00:00:00 2001 From: Stephan Hadinger Date: Fri, 24 Dec 2021 10:06:30 +0100 Subject: [PATCH] LVGL add support for lv_chart_series --- .../lv_berry/generate/be_lv_c_mapping.h | 3 + .../lv_berry/generate/be_lvgl_widgets_lib.c | 3 + .../lv_berry/src/be_lvgl_ctypes_definitions.c | 36 + .../lv_berry/src/embedded/ctypes.be | 623 ++++++++++++++++++ .../lv_berry/src/embedded}/lvgl_ctypes.be | 24 + lib/libesp32_lvgl/lv_berry/tools/convert.py | 2 + 6 files changed, 691 insertions(+) create mode 100644 lib/libesp32_lvgl/lv_berry/src/embedded/ctypes.be rename {tasmota/berry/modules => lib/libesp32_lvgl/lv_berry/src/embedded}/lvgl_ctypes.be (94%) diff --git a/lib/libesp32_lvgl/lv_berry/generate/be_lv_c_mapping.h b/lib/libesp32_lvgl/lv_berry/generate/be_lv_c_mapping.h index dd654f5f3..2fd213d96 100644 --- a/lib/libesp32_lvgl/lv_berry/generate/be_lv_c_mapping.h +++ b/lib/libesp32_lvgl/lv_berry/generate/be_lv_c_mapping.h @@ -503,10 +503,13 @@ const be_ntv_func_def_t lv_indev_func[] = { /* `lv_chart` methods */ #ifdef BE_LV_WIDGET_CHART const be_ntv_func_def_t lv_chart_func[] = { + { "add_cursor", (void*) &lv_chart_add_cursor, "lv.lv_chart_cursor", "(lv.lv_obj)(lv.lv_color)i" }, + { "add_series", (void*) &lv_chart_add_series, "lv.lv_chart_series", "(lv.lv_obj)(lv.lv_color)i" }, { "get_cursor_point", (void*) &lv_chart_get_cursor_point, "i", "(lv.lv_obj)(lv.lv_chart_cursor)" }, { "get_point_count", (void*) &lv_chart_get_point_count, "i", "(lv.lv_obj)" }, { "get_point_pos_by_id", (void*) &lv_chart_get_point_pos_by_id, "", "(lv.lv_obj)(lv.lv_chart_series)i(lv.lv_point)" }, { "get_pressed_point", (void*) &lv_chart_get_pressed_point, "i", "(lv.lv_obj)" }, + { "get_series_next", (void*) &lv_chart_get_series_next, "lv.lv_chart_series", "(lv.lv_obj)(lv.lv_chart_series)" }, { "get_type", (void*) &lv_chart_get_type, "i", "(lv.lv_obj)" }, { "get_x_start_point", (void*) &lv_chart_get_x_start_point, "i", "(lv.lv_obj)(lv.lv_chart_series)" }, { "get_zoom_x", (void*) &lv_chart_get_zoom_x, "i", "(lv.lv_obj)" }, diff --git a/lib/libesp32_lvgl/lv_berry/generate/be_lvgl_widgets_lib.c b/lib/libesp32_lvgl/lv_berry/generate/be_lvgl_widgets_lib.c index 1841dbabd..f4e11b099 100644 --- a/lib/libesp32_lvgl/lv_berry/generate/be_lvgl_widgets_lib.c +++ b/lib/libesp32_lvgl/lv_berry/generate/be_lvgl_widgets_lib.c @@ -518,10 +518,13 @@ extern int lvbe_chart_get_point_count(bvm *vm); extern int lvbe_chart_get_x_start_point(bvm *vm); extern int lvbe_chart_get_point_pos_by_id(bvm *vm); extern int lvbe_chart_refresh(bvm *vm); +extern int lvbe_chart_add_series(bvm *vm); extern int lvbe_chart_remove_series(bvm *vm); extern int lvbe_chart_hide_series(bvm *vm); extern int lvbe_chart_set_series_color(bvm *vm); extern int lvbe_chart_set_x_start_point(bvm *vm); +extern int lvbe_chart_get_series_next(bvm *vm); +extern int lvbe_chart_add_cursor(bvm *vm); extern int lvbe_chart_set_cursor_pos(bvm *vm); extern int lvbe_chart_set_cursor_point(bvm *vm); extern int lvbe_chart_get_cursor_point(bvm *vm); diff --git a/lib/libesp32_lvgl/lv_berry/src/be_lvgl_ctypes_definitions.c b/lib/libesp32_lvgl/lv_berry/src/be_lvgl_ctypes_definitions.c index e632ed6b2..1063a33eb 100644 --- a/lib/libesp32_lvgl/lv_berry/src/be_lvgl_ctypes_definitions.c +++ b/lib/libesp32_lvgl/lv_berry/src/be_lvgl_ctypes_definitions.c @@ -402,6 +402,36 @@ const be_ctypes_structure_t be_lv_meter_indicator_scale_lines = { { "width_mod", 16, 0, 0, ctypes_i16, 0 }, }}; +const be_ctypes_structure_t be_lv_chart_series = { + 13, /* size in bytes */ + 9, /* number of elements */ + be_ctypes_instance_mappings, + (const be_ctypes_structure_item_t[9]) { + { "color", 8, 0, 0, ctypes_u16, 1 }, + { "hidden", 12, 0, 1, ctypes_bf, 0 }, + { "start_point", 10, 0, 0, ctypes_u16, 0 }, + { "x_axis_sec", 12, 3, 1, ctypes_bf, 0 }, + { "x_ext_buf_assigned", 12, 1, 1, ctypes_bf, 0 }, + { "x_points", 0, 0, 0, ctypes_ptr32, 0 }, + { "y_axis_sec", 12, 4, 1, ctypes_bf, 0 }, + { "y_ext_buf_assigned", 12, 2, 1, ctypes_bf, 0 }, + { "y_points", 4, 0, 0, ctypes_ptr32, 0 }, +}}; + +const be_ctypes_structure_t be_lv_chart_cursor = { + 14, /* size in bytes */ + 7, /* number of elements */ + be_ctypes_instance_mappings, + (const be_ctypes_structure_item_t[7]) { + { "color", 6, 0, 0, ctypes_u16, 1 }, + { "dir", 12, 0, 0, ctypes_u8, 0 }, + { "point_id", 4, 0, 0, ctypes_u16, 0 }, + { "pos_set", 13, 0, 1, ctypes_bf, 0 }, + { "pos_x", 0, 0, 0, ctypes_i16, 0 }, + { "pos_y", 2, 0, 0, ctypes_i16, 0 }, + { "ser", 8, 0, 0, ctypes_ptr32, 0 }, +}}; + const be_ctypes_structure_t be_lv_obj_class = { 27, /* size in bytes */ 10, /* number of elements */ @@ -439,6 +469,8 @@ static const char * be_ctypes_instance_mappings[] = { }; static be_define_ctypes_class(lv_area, &be_lv_area, &be_class_ctypes, "lv_area"); +static be_define_ctypes_class(lv_chart_cursor, &be_lv_chart_cursor, &be_class_ctypes, "lv_chart_cursor"); +static be_define_ctypes_class(lv_chart_series, &be_lv_chart_series, &be_class_ctypes, "lv_chart_series"); static be_define_ctypes_class(lv_draw_img_dsc, &be_lv_draw_img_dsc, &be_class_ctypes, "lv_draw_img_dsc"); static be_define_ctypes_class(lv_draw_line_dsc, &be_lv_draw_line_dsc, &be_class_ctypes, "lv_draw_line_dsc"); static be_define_ctypes_class(lv_draw_mask_angle_param, &be_lv_draw_mask_angle_param, &be_class_ctypes, "lv_draw_mask_angle_param"); @@ -467,6 +499,8 @@ static be_define_ctypes_class(lv_sqrt_res, &be_lv_sqrt_res, &be_class_ctypes, "l void be_load_ctypes_lvgl_definitions_lib(bvm *vm) { ctypes_register_class(vm, &be_class_lv_area, &be_lv_area); + ctypes_register_class(vm, &be_class_lv_chart_cursor, &be_lv_chart_cursor); + ctypes_register_class(vm, &be_class_lv_chart_series, &be_lv_chart_series); ctypes_register_class(vm, &be_class_lv_draw_img_dsc, &be_lv_draw_img_dsc); ctypes_register_class(vm, &be_class_lv_draw_line_dsc, &be_lv_draw_line_dsc); ctypes_register_class(vm, &be_class_lv_draw_mask_angle_param, &be_lv_draw_mask_angle_param); @@ -496,6 +530,8 @@ void be_load_ctypes_lvgl_definitions_lib(bvm *vm) { be_ctypes_class_by_name_t be_ctypes_lvgl_classes[] = { { "lv_area", &be_class_lv_area }, + { "lv_chart_cursor", &be_class_lv_chart_cursor }, + { "lv_chart_series", &be_class_lv_chart_series }, { "lv_draw_img_dsc", &be_class_lv_draw_img_dsc }, { "lv_draw_line_dsc", &be_class_lv_draw_line_dsc }, { "lv_draw_mask_angle_param", &be_class_lv_draw_mask_angle_param }, diff --git a/lib/libesp32_lvgl/lv_berry/src/embedded/ctypes.be b/lib/libesp32_lvgl/lv_berry/src/embedded/ctypes.be new file mode 100644 index 000000000..6ed6226e8 --- /dev/null +++ b/lib/libesp32_lvgl/lv_berry/src/embedded/ctypes.be @@ -0,0 +1,623 @@ +#------------------------------------------------------------- +#- Ctypes for Berry +#- +#- Inspired from Python's ctypes structure +#-------------------------------------------------------------# +import string + +ctypes = module('ctypes') + +#------------------------------------------------------------- +#- Basic types for mapping +#- +#- ints of size 1/2/4 bytes (little endian by default) +#- usigned ints of size 1/2/4 bytes (little endian by default) +#- +#- (Big Endian are negative numbers) +#-------------------------------------------------------------# + +# default is little_endian +ctypes.i32 = 14 +ctypes.i16 = 12 +ctypes.i8 = 11 +ctypes.u32 = 4 +ctypes.u16 = 2 +ctypes.u8 = 1 + +# explicit little endian +ctypes.le_i32 = 14 +ctypes.le_i16 = 12 +ctypes.le_i8 = 11 +ctypes.le_u32 = 4 +ctypes.le_u16 = 2 +ctypes.le_u8 = 1 + +# big endian +ctypes.be_i32 = -14 +ctypes.be_i16 = -12 +ctypes.be_i8 = -11 +ctypes.be_u32 = -4 +ctypes.be_u16 = -2 +ctypes.be_u8 = -1 + +# floating point +ctypes.float = 5 +ctypes.double = 10 + +# pointer +ctypes.ptr32 = 9 +ctypes.ptr64 = -9 + +ctypes.bf_x = 0 # generic bitfield +# bitfields (always unsigned) +ctypes.bf_0 = 100 # serves as base +ctypes.bf_1 = 101 +ctypes.bf_2 = 102 +ctypes.bf_3 = 103 +ctypes.bf_4 = 104 +ctypes.bf_5 = 105 +ctypes.bf_6 = 106 +ctypes.bf_7 = 107 +ctypes.bf_8 = 108 +ctypes.bf_9 = 109 +ctypes.bf_10 = 110 +ctypes.bf_11 = 111 +ctypes.bf_12 = 112 +ctypes.bf_13 = 113 +ctypes.bf_14 = 114 +ctypes.bf_15 = 115 +ctypes.bf_16 = 116 + +ctypes.type_mapping = { + 14: "ctypes_i32", + 12: "ctypes_i16", + 11: "ctypes_i8", + 4: "ctypes_u32", + 2: "ctypes_u16", + 1: "ctypes_u8", + + -14:"ctypes_be_i32", # big endian + -12:"ctypes_be_i16", + -11:"ctypes_be_i8", + -4: "ctypes_be_u32", + -2: "ctypes_be_u16", + -1: "ctypes_be_u8", + + 5: "ctypes_float", + 10: "ctypes_double", + 9: "ctypes_ptr32", + -9: "ctypes_ptr64", + + 0: "ctypes_bf" # bitfield +} + +ctypes.type_to_str = def (type_num) + var type_name = ctypes.type_mapping.find(type_num) + if type_name == nil + return str(type_num) + end + return type_name +end + +def findinlist(l, x) + for i:0..size(l)-1 + if l[i] == x + return i + end + end +end + +#------------------------------------------------------------- +#- 'get_bits' function +#- +#- Reads a bit-field in a `bytes()` object +#- +#- Input: +#- b: bytes() object to read from +#- offset_bytes (int): byte offset in the bytes() object +#- offset_bits (int): bit number to start reading from (0 = LSB) +#- len_bits (int): how many bits to read +#- Output: +#- valuer (int) +#-------------------------------------------------------------# +ctypes.get_bits = def (b, offset_bytes, offset_bits, len_bits) + if !isinstance(b, bytes) raise "value_error", "first argument must be of type 'bytes'" end + if offset_bits < 0 || offset_bits > 7 raise "value_error", "offset_bits must be between 0 and 7" end + if len_bits <= 0 || len_bits > 32 raise "value_error", "length in bits must be between 0 and 32" end + var ret = 0 + + var bit_shift = 0 # bit number to write to + + while (len_bits > 0) + var block_bits = 8 - offset_bits # how many bits to read in the current block (block = byte) + if block_bits > len_bits block_bits = len_bits end + + var mask = ( (1<> offset_bits) << bit_shift) + + # move the input window + bit_shift += block_bits + len_bits -= block_bits + offset_bits = 0 # start at full next byte + offset_bytes += 1 + end + + return ret +end + +ctypes.sort = def (l) + # insertion sort + for i:1..size(l)-1 + var k = l[i] + var j = i + while (j > 0) && (l[j-1] > k) + l[j] = l[j-1] + j -= 1 + end + l[j] = k + end + return l +end + +#------------------------------------------------------------- +#- 'set_bits' function +#- +#- Writes a bit-field in a `bytes()` object +#- +#- Input: +#- b: bytes() object to write to +#- offset_bytes (int): byte offset in the bytes() object +#- offset_bits (int): bit number to start writing to (0 = LSB) +#- len_bits (int): how many bits to write +#- Output: +#- bytes() object modified (by reference) +#-------------------------------------------------------------# +ctypes.set_bits = def (b, offset_bytes, offset_bits, len_bits, val) + if !isinstance(b, bytes) raise "value_error", "first argument must be of type 'bytes'" end + if offset_bits < 0 || offset_bits > 7 raise "value_error", "offset_bits must be between 0 and 7" end + if len_bits <= 0 || len_bits > 32 raise "value_error", "length in bits must be between 0 and 32" end + + while (len_bits > 0) + var block_bits = 8 - offset_bits # how many bits to write in the current block (block = byte) + if block_bits > len_bits block_bits = len_bits end + + var mask_val = (1<>= block_bits + len_bits -= block_bits + offset_bits = 0 # start at full next byte + offset_bytes += 1 + end + return b +end + + +#- print the C types -#1 +ctypes.print_types = def () + print("/********************************************************************") + print(" * Generated code, don't edit") + print(" *******************************************************************/") + print() + print("static const char * be_ctypes_instance_mappings[]; /* forward definition */") + print() +end + +global_classes = [] # track the list of all classes and +global_mappings = [] # mapping to Berry classes, ex: lv_color + +ctypes.print_classes = def (module_name) + # print mappings + if size(global_mappings) > 7 + raise "internal_error", "too many mappings, 7 max" + end + print("static const char * be_ctypes_instance_mappings[] = {") + for n:global_mappings.iter() + print(string.format(" \"%s\",", n)) + end + print(" NULL") + print("};") + print() + + ctypes.sort(global_classes) + + for elt:global_classes + print(string.format("static be_define_ctypes_class(%s, &be_%s, &be_class_ctypes, \"%s\");", elt, elt, elt)) + end + + print() + print(string.format("void be_load_ctypes_%s_definitions_lib(bvm *vm) {", module_name)) + for elt:global_classes + print(string.format(" ctypes_register_class(vm, &be_class_%s, &be_%s);", elt, elt)) + end + print("}") + print() + print("be_ctypes_class_by_name_t be_ctypes_lvgl_classes[] = {") + for elt:global_classes + print(string.format(" { \"%s\", &be_class_%s },", elt, elt)) + end + print("};") + print("const size_t be_ctypes_lvgl_classes_size = sizeof(be_ctypes_lvgl_classes)/sizeof(be_ctypes_lvgl_classes[0]);") + print() + + print("/********************************************************************/") + print() +end + +#------------------------------------------------------------- +#- 'ctypes.structure' class +#- +#- Parses a ctypes structure descriptor and creates +#- a set of getters and setters +#- +#-------------------------------------------------------------# +class structure + var cur_offset # offset in bytes from buffer start + var bit_offset # are we intra-byte? + var get_closures # + var set_closures # + var size_bytes # size in bytes + var mapping # map to generate C binding + + # init world + def init(mapping, name) + self.cur_offset = 0 + self.bit_offset = 0 + self.size_bytes = 0 # overall size in bytes + self.get_closures = {} + self.set_closures = {} + self.mapping = {} + + # parse mapping + self.parse_mapping(mapping, name) + end + #- iteratively parse mapping + #- + #- if name is not nil, it also outputs a C structure for the mapping + #- + #-------------------------------------------------------------# + def parse_mapping(mapping, name) + for map_line: mapping + self.parse_line(map_line) + end + + # clear any outstanding bitfield + self.align(1) + self.size_bytes = self.cur_offset + + if name != nil + print(string.format("const be_ctypes_structure_t be_%s = {", name)) + print(string.format(" %i, /* size in bytes */", self.size_bytes)) + print(string.format(" %i, /* number of elements */", size(self.mapping))) + print(string.format(" be_ctypes_instance_mappings,")) + print(string.format(" (const be_ctypes_structure_item_t[%i]) {", size(self.mapping))) + # list keys for future binary search + var names = [] + for n:self.mapping.keys() names.push(n) end # convert to list + ctypes.sort(names) + for n:names + var args = self.mapping[n] + print(string.format(" { \"%s\", %i, %i, %i, %s, %i },", n, args[0], args[1], args[2], ctypes.type_to_str(args[3]), args[4])) + end + print("}};") + print() + + # retain class definition + global_classes.push(name) + end + end + + def size() + return self.size_bytes + end + + # parse a single line + def parse_line(map_line) + var type_obj = map_line[0] + var name = map_line[1] + var bits = 0 + if size(map_line) >= 3 bits = map_line[2] end + + if isinstance(type_obj, ctypes.structure) + # nested structure + self.nested(name, type_obj) + end + + var mapping_idx = 0 # mapping starts at 1 + if isinstance(type_obj, list) + # it may be a list to denote a mapping to an instance + var mapping_name = type_obj[1] + if findinlist(global_mappings, mapping_name) == nil + global_mappings.push(mapping_name) + end + mapping_idx = findinlist(global_mappings, mapping_name) + 1 + + type_obj = type_obj[0] # take the simple value of first element in the list + end + + if type(type_obj) == 'int' + # simple attibute + # TODO check actual type + if type_obj > ctypes.bf_0 + # bit field + self.get_bitfield_closure(name, type_obj - ctypes.bf_0, mapping_idx) + elif (type_obj == ctypes.ptr32) || (type_obj == ctypes.ptr64) + # pointer + self.get_ptr_closure(name, type_obj, mapping_idx) + elif (type_obj == ctypes.float) || (type_obj == ctypes.double) + # multi-bytes + self.get_float_closure(name, type_obj, mapping_idx) + else + # multi-bytes + self.get_int_closure(name, type_obj, mapping_idx) + end + end + end + + #- ensure alignment to 1/2/4 bytes -# + def align(n) + if n != 1 && n != 2 && n != 4 raise "value_error", "acceptable values are 1/2/4" end + + #- align to byte boundary if we're in a bitfield -# + if self.bit_offset != 0 + #- we are not byte aligned, let's re-aling -# + self.cur_offset += 1 + self.bit_offset = 0 + end + + #- check 2/4 bytes alignment -# + if self.cur_offset % n != 0 + # we are not aligned with current size + self.cur_offset += n - self.cur_offset % n + end + end + + def nested(name, type_obj) + var sub_size = type_obj.size() + if sub_size <= 0 raise "value_error", "empty sub-structure not supported" end + + # align to appropriate sub-size + var align_size = sub_size + if align_size == 3 || align_size > 4 align_size = 4 end + self.align(align_size) + + var offset = self.cur_offset # var for closure + + # include nested + for subname:type_obj.mapping.keys() + var val = type_obj.mapping[subname] + self.mapping[name+"_"+subname] = [val[0] + offset, val[1], val[2], val[3], val[4]] + end + # self.mapping[name] = [offset << 3, sub_size << 3] + + self.get_closures[name] = def (b, p) return ctypes.nested_buffer(type_obj, offset + p, b) end + # self.set_closures[name] = def (b, p, v) return ctypes.nested_buffer(type_obj, offset + p, b) end + + self.cur_offset += sub_size + end + + def get_int_closure(name, type, instance_mapping) # can be 1/2/4 + #- abs size -# + var size_in_bytes = type < 0 ? - type : type + var signed = size_in_bytes > 10 + var size_in_bytes_le_be = type % 10 # remove sign marker + size_in_bytes = size_in_bytes % 10 # remove sign marker + + self.align(size_in_bytes) # force alignment + var offset = self.cur_offset # prepare variable for capture in closure + + self.mapping[name] = [offset, 0, 0, type, instance_mapping] + + #- add closures -# + if signed + self.get_closures[name] = def (b, p) return b.geti(offset + p, size_in_bytes_le_be) end + else + self.get_closures[name] = def (b, p) return b.get(offset + p, size_in_bytes_le_be) end + end + self.set_closures[name] = def (b, p, v) return b.set(offset+ p, v, size_in_bytes_le_be) end + + self.cur_offset += size_in_bytes # next offset + end + + def get_ptr_closure(name, type, instance_mapping) # can be 1/2/4 + #- actual size -# + import introspect + var size_in_bytes = (type == ctypes.ptr32) ? 4 : 8 + + self.align(size_in_bytes) # force alignment + var offset = self.cur_offset # prepare variable for capture in closure + + self.mapping[name] = [offset, 0, 0, type, instance_mapping] + + #- add closures -# + # TODO no closure yet, anyways need to rethink closures, they are too heavy + # if signed + # self.get_closures[name] = def (b, p) return b.geti(offset + p, size_in_bytes_le_be) end + # else + # self.get_closures[name] = def (b, p) return b.get(offset + p, size_in_bytes_le_be) end + # end + # self.set_closures[name] = def (b, p, v) return b.set(offset+ p, v, size_in_bytes_le_be) end + + self.cur_offset += size_in_bytes # next offset + end + + def get_float_closure(name, type, instance_mapping) # can be 1/2/4 + #- actual size -# + var size_in_bytes = (type == ctypes.float) ? 4 : 8 + + self.align(size_in_bytes) # force alignment + var offset = self.cur_offset # prepare variable for capture in closure + + self.mapping[name] = [offset, 0, 0, type, instance_mapping] + + #- add closures -# + # TODO no closure yet, anyways need to rethink closures, they are too heavy + # if signed + # self.get_closures[name] = def (b, p) return b.geti(offset + p, size_in_bytes_le_be) end + # else + # self.get_closures[name] = def (b, p) return b.get(offset + p, size_in_bytes_le_be) end + # end + # self.set_closures[name] = def (b, p, v) return b.set(offset+ p, v, size_in_bytes_le_be) end + + self.cur_offset += size_in_bytes # next offset + end + + def get_bitfield_closure(name, size_in_bits, instance_mapping) # can be 1..32 + var cur_offset = self.cur_offset # prepare variable for capture in closure + var bit_offset = self.bit_offset + self.mapping[name] = [cur_offset, bit_offset, size_in_bits, 0, instance_mapping] + self.get_closures[name] = def (b, p) return ctypes.get_bits(b, cur_offset + p, bit_offset, size_in_bits) end + self.set_closures[name] = def (b, p, v) return ctypes.set_bits(b, cur_offset+ p, bit_offset, size_in_bits, v) end + + self.cur_offset += (self.bit_offset + size_in_bits) / 8 + self.bit_offset = (self.bit_offset + size_in_bits) % 8 + end +end + +ctypes.structure = structure + +#------------------------------------------------------------- +#- Structured buffer +#- +#- Inspired from Python's ctypes structure +#- +#- This class is a wrapper around `bytes()` object (actually a subclass) +#- providing virtual members mapped to the ctypes structure. +#- +#- Takes as argument a ctypes.structure and an optional bytes() object +#-------------------------------------------------------------# +class buffer : bytes + var _cs # ctypes_structure associated + + def init(cs, b) + if !isinstance(cs, ctypes.structure) raise "value_error", "first argument must be an instance of 'ctypes.structure'" end + self._cs = cs + var size = self._cs.size() # size in bytes of the structure + + super(self, bytes).init(size) # init bytes object with reserved size in memory + + if isinstance(b, bytes) + self..b + end + self.resize(size) # size once for all to the target size and complete with 00s + end + + # accessor for virtual member + def member(name) + return self._cs.get_closures[name](self, 0) + end + + # setter for virtual member + def setmember(name, value) + self._cs.set_closures[name](self, 0, value) + end +end +ctypes.buffer = buffer + +#------------------------------------------------------------- +#- Nested buffer +#- +#- Nested structures are just pointers to the master bytes() object +#-------------------------------------------------------------# +class nested_buffer + var _cs # ctypes.structure instance for this buffer + var _offset # offset un bytes() to the structure + var _bytes # reference to the overall buffer (by reference) + + def init(cs, offset, b) + if !isinstance(cs, ctypes.structure) raise "value_error", "first argument must be an instance of 'ctypes.structure'" end + if type(offset) != 'int' raise "value_error", "second argument must be of type 'int'" end + if !isinstance(b, bytes) raise "value_error", "third argument must be an instance of 'bytes'" end + self._cs = cs + self._offset = offset + self._bytes = b + end + + # accessor for virtual member + def member(name) + return self._cs.get_closures[name](self._bytes, self._offset) + end + + # setter for virtual member + def setmember(name, value) + self._cs.set_closures[name](self._bytes, self._offset, value) + end + + def tostring() + return self._bytes[self._offset..self._offset+self._cs.size()-1].tostring() + end +end +ctypes.nested_buffer = nested_buffer + + +return ctypes + +# ex = [ +# [ctypes.u32, "a"], +# [ctypes.u16, "b"], +# [ctypes.i8, "c"], +# [ctypes.i32, "d"], # should infer an empty byte +# ] + +# cs = ctypes.structure(ex) +# bb = ctypes.buffer(cs, bytes("aabb")) + +# fa = cp.get_int_closure('a', 4) +# fb = cp.get_int_closure('b', 2) +# fc = cp.get_int_closure('c', 1) +# fd = cp.get_int_closure('d', 4) + +# b = bytes("04030201AA55FFFF00010001") + +# cp.get_closures['a'](b) +# cp.get_closures['b'](b) +# cp.get_closures['c'](b) +# cp.get_closures['d'](b) + +# bb = ctypes_buffer(cp, b) + +# bb.a = 0x11223344 +# bb +# bb.a + + +# > bb = ctypes_buffer(cp, b) +# > bb.a +# 16909060 +# > bb.b +# 21930 +# > bb.c +# 255 +# > bb.d +# 16777472 +# > bb.e +# key_error: e +# stack traceback: +# : in native function +# stdin:11: in function `member` +# stdin:1: in function `main` + + +# > bb['a'] +# 16909060 +# > bb['b'] +# 21930 +# > bb['c'] +# 255 +# > bb['d'] +# 16777472 + +#- +> fa(b) +16909060 +> fb(b) +21930 +> fc(b) +255 +> fd(b) +16777472 + +-# diff --git a/tasmota/berry/modules/lvgl_ctypes.be b/lib/libesp32_lvgl/lv_berry/src/embedded/lvgl_ctypes.be similarity index 94% rename from tasmota/berry/modules/lvgl_ctypes.be rename to lib/libesp32_lvgl/lv_berry/src/embedded/lvgl_ctypes.be index ee1a0e226..ff9e75310 100644 --- a/tasmota/berry/modules/lvgl_ctypes.be +++ b/lib/libesp32_lvgl/lv_berry/src/embedded/lvgl_ctypes.be @@ -24,6 +24,7 @@ lv_text_decor = ctypes.u8 lv_font = ctypes.u32 lv_blend_mode = ctypes.u8 lv_draw_mask_line_side = ctypes.u8 +lv_dir = ctypes.u8 uint8_t_1 = ctypes.bf_1 uint8_t_2 = ctypes.bf_2 uint8_t_3 = ctypes.bf_3 @@ -335,6 +336,29 @@ lv_meter_indicator_scale_lines = [ # valid LVGL8 ] lv_meter_indicator_scale_lines = ctypes.structure(lv_meter_indicator_scale_lines, "lv_meter_indicator_scale_lines") +lv_chart_series = [ + [ptr, "x_points"], + [ptr, "y_points"], + [lv_color, "color"], + [uint16_t, "start_point"], + [uint8_t_1, "hidden"], + [uint8_t_1, "x_ext_buf_assigned"], + [uint8_t_1, "y_ext_buf_assigned"], + [uint8_t_1, "x_axis_sec"], + [uint8_t_1, "y_axis_sec"], +] +lv_chart_series = ctypes.structure(lv_chart_series, "lv_chart_series") + +lv_chart_cursor = [ + [lv_point, "pos"], + [uint16_t, "point_id"], + [lv_color, "color"], + [ptr, "ser"], + [lv_dir, "dir"], + [uint8_t_1, "pos_set"], +] +lv_chart_cursor = ctypes.structure(lv_chart_cursor, "lv_chart_cursor") + #- --------- class system --------- -# lv_obj_class_ptr = ptr lv_obj_ptr = ptr diff --git a/lib/libesp32_lvgl/lv_berry/tools/convert.py b/lib/libesp32_lvgl/lv_berry/tools/convert.py index 4b79e7834..e6bc5c3bb 100644 --- a/lib/libesp32_lvgl/lv_berry/tools/convert.py +++ b/lib/libesp32_lvgl/lv_berry/tools/convert.py @@ -111,6 +111,8 @@ return_types = { "lv_meter_scale_t *": "lv_meter_scale", "lv_meter_indicator_t *": "lv_meter_indicator", "lv_obj_class_t *": "lv_obj_class", + "lv_chart_series_t *": "lv_chart_series", + "lv_chart_cursor_t *": "lv_chart_cursor", "_lv_obj_t *": "lv_obj", "lv_obj_t *": "lv_obj",