{"id":18301394,"url":"https://github.com/lvgl/lv_binding_berry","last_synced_at":"2025-04-05T14:30:52.580Z","repository":{"id":39305580,"uuid":"463251891","full_name":"lvgl/lv_binding_berry","owner":"lvgl","description":"Binding to Berry language","archived":false,"fork":false,"pushed_at":"2022-06-17T20:41:45.000Z","size":121,"stargazers_count":8,"open_issues_count":1,"forks_count":3,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-04-03T13:45:55.780Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"C","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/lvgl.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2022-02-24T18:05:14.000Z","updated_at":"2025-02-13T18:57:05.000Z","dependencies_parsed_at":"2022-09-01T08:01:17.348Z","dependency_job_id":null,"html_url":"https://github.com/lvgl/lv_binding_berry","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lvgl%2Flv_binding_berry","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lvgl%2Flv_binding_berry/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lvgl%2Flv_binding_berry/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lvgl%2Flv_binding_berry/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/lvgl","download_url":"https://codeload.github.com/lvgl/lv_binding_berry/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247352307,"owners_count":20925246,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-11-05T15:15:55.126Z","updated_at":"2025-04-05T14:30:52.138Z","avatar_url":"https://github.com/lvgl.png","language":"C","funding_links":[],"categories":[],"sub_categories":[],"readme":"# LVGL + Berry\n\nThis repo contains a full binding of LVGL to the Berry language. This project is similar to the Micropython+lvgl project in its spirit, and provides easy to use scripting for lvgl on embedded devices. It is used by the Tasmota open-source project for ESP32 based devices. \n\n**Supported version**: LVGL 8.2.0\n\n## Why use LVGL + Berry\n\nLVGL + Berry mapping provides an easy-to-use programming language on top of LVGL powerful APIs. This is ideal for rapid scripting as well as production applications. The Berry mapping comes from the open-source [Tasmota](https://tasmota.github.io/docs/) project for ESP32 based devices, and leverages a vivid ecosystem.\n\n![lvgl_info](https://user-images.githubusercontent.com/49731213/153846806-2571f872-f85f-4f31-becb-b6bebc10a324.png)\n\nQuickstart with this short tutorial [LVGL in less than 10 minutes with Tasmota](https://tasmota.github.io/docs/LVGL_in_10_minutes/).\n\n[Berry](https://github.com/berry-lang/berry) is an ultra-lightweight dynamically typed embedded scripting language. It is designed for lower-performance embedded devices. The interpreter of Berry includes a one-pass compiler and register-based VM, all the code is written in ANSI C99. Berry offers a syntax very similar to Python, and is inspired from LUA VM.\n\n\n## Quickstart\n\nLet's start with a simple example:\n\n```\n#- start LVGL and init environment (can be called multiple times) -#\nlv.start()\n\nhres = lv.get_hor_res()       # horizontal resolution of default display\nvres = lv.get_ver_res()       # vertical resolution of default display\n\nscr = lv.scr_act()            # default screen object\n\n#- Background with a gradient from black #000000 (bottom) to dark blue #0000A0 (top) -#\nscr.set_style_bg_color(lv.color(0x0000A0), lv.PART_MAIN | lv.STATE_DEFAULT)\nscr.set_style_bg_grad_color(lv.color(0x000000), lv.PART_MAIN | lv.STATE_DEFAULT)\nscr.set_style_bg_grad_dir(lv.GRAD_DIR_VER, lv.PART_MAIN | lv.STATE_DEFAULT)\n```\n\nLet's add a label:\n\n```\nt = lv.label(scr)\nt.set_style_text_color(lv.color(0xFFFFFF), lv.PART_MAIN | lv.STATE_DEFAULT)\nt.set_text(\"Hello LVGL + Berry!\")\nt.set_align(lv.ALIGN_TOP_MID)\n```\n\nLet's add a style for buttons:\n\n```\n#- create a style for the buttons -#\nbtn_style = lv.style()\nbtn_style.set_radius(10)                        # radius of rounded corners\nbtn_style.set_bg_opa(lv.OPA_COVER)              # 100% background opacity\nbtn_style.set_bg_color(lv.color(0x1fa3ec))      # background color #1FA3EC (Tasmota Blue)\nbtn_style.set_border_color(lv.color(0x0000FF))  # border color #0000FF\nbtn_style.set_text_color(lv.color(0xFFFFFF))    # text color white #FFFFFF\n```\n\nLet's add a single button with using a symbol:\n\n```\nhome_btn = lv.btn(scr)                            # center button\nhome_btn.set_size(80, 30)\nhome_btn.add_style(btn_style, lv.PART_MAIN | lv.STATE_DEFAULT)\nhome_btn.set_align(lv.ALIGN_BOTTOM_MID)\nhome_label = lv.label(home_btn)\nhome_label.set_text(lv.SYMBOL_HOME)                 # set text as Home icon\nhome_label.center()\n```\n\n\nLet's now add a colorwheel widget:\n\n```\ncolw = lv.colorwheel(scr, false)\ncolw.set_size(100, 100)\ncolw.set_pos(20,30)\n```\n\n![LVGL_Berry](https://user-images.githubusercontent.com/49731213/153846625-52855e95-b1a2-4a68-a495-1759f490794e.png)\n\n\nAs a general rule:\n\n- calls to general APIs are mapped to module `lv`. E.g. `lv_get_hor_res()` translates to \n- enums are also mapped to module `lv`\n- widgets constructors are classes in module `lv`\n- calls to widgets are object methods (skip the first argument which is implicit)\n\n\nC call|Berry call\n:---|:---\n`lv_get_hor_res()`|`lv.get_hor_res()`\n`LV_ALIGN_BOTTOM_MID`|`lv.ALIGN_BOTTOM_MID`\n`lv_colorwheel_create(scr, false)`|`lv.colorwheel(scr, false)` or `lv.lv_colorwheel(scr, false)`\n`lv_obj_set_size(colw, 100, 100)`|`colw.set_size(100, 100)`\n\n## Supported features\n\nlv_berry provides an object-oriented interface for LVGL, and covers over 99% of LVGL's APIs, noticeably:\n\n- access to almost all LVGL APIs (over 1000+ calls)\n- automatic type checking and type conversion based on `C` headers\n- access to all `C` ENUMs constants (500+)\n- full support for C callbacks in Berry\n- full support for LVGL internal memory structures\n- ability to create pure Berry custom widgets and custom classes\n- supports only 16 bits display (swapped or not)\n\nWhat is currently not supported (but could be if there is demand):\n\n- multi-screen devices (no support in Tasmota anyways)\n- bidirectional text support\n- LVGL tasks (Berry has its own task system)\n- non-16 bits display\n\n## Type system\n\n### Widgets classes\n\nAlthough LVGL is C code and is not formally object oriented, LVGL widget follow an inheritance model. Each widget is a virtual subclass of `lv_obj` structure.\n\nBerry builds an actual Object Oriented class system, with a base class `lv_obj` and subclasses.\n\nThe class names supported are defined in `convert.py` and are currently standard widgets:\n\n```\n'lv_arc', 'lv_bar', 'lv_btn', 'lv_btnmatrix', 'lv_canvas', 'lv_checkbox', 'lv_dropdown', 'lv_img', 'lv_label', 'lv_line', 'lv_roller', 'lv_slider', 'lv_switch', 'lv_table', 'lv_textarea'\n```\n\nAnd extra widgets:\n\n```\n'lv_chart', 'lv_colorwheel', 'lv_imgbtn', 'lv_led', 'lv_meter', 'lv_msgbox', 'lv_spinbox', 'lv_spinner'\n```\n\nAdditional 'special' classes are (they do not inherit from `lv_obj`):\n\n```\n'lv_obj', 'lv_group', 'lv_style', 'lv_indev', 'lv_disp'\n```\n\n### Colors\n\nAn exception for LVGL colors, they are defined as 32 bits RGB values as follows, and not based on their C representation:\n\n```C\nCOLOR_WHITE=0xFFFFFF\nCOLOR_SILVER=0xC0C0C0\nCOLOR_GRAY=0x808080\nCOLOR_BLACK=0x000000\nCOLOR_RED=0xFF0000\nCOLOR_MAROON=0x800000\nCOLOR_YELLOW=0xFFFF00\nCOLOR_OLIVE=0x808000\nCOLOR_LIME=0x00FF00\nCOLOR_GREEN=0x008000\nCOLOR_CYAN=0x00FFFF\nCOLOR_AQUA=0x00FFFF\nCOLOR_TEAL=0x008080\nCOLOR_BLUE=0x0000FF\nCOLOR_NAVY=0x000080\nCOLOR_MAGENTA=0xFF00FF\nCOLOR_PURPLE=0x800080\n```\n\nExample: `lv.COLOR_RED`\n\n`lv_color` is a simple class that maps RGB 32 bits colors (as 32 bits int) to the internal representation of colors (usually 16 bits).\n\nDon't be surprised that getting back a value is the 16 bits color converted to 32 bits - rounding errors may occur:\n\n```\n[Berry Console]\n\u003e c = lv_color(0x808080)\n\u003e c\nlv_color(0xff838183 - native:0x1084)\n```\n\nNote:\n\n- 0xff838183 - is the 32 bits color, with alpha channel (opaque)\n- 0x1084 - is the native internal representation as 16 bits color with swapped bytes\n\n## Build system\n\nMore details about the mapping are provided in [Tasmota LVGL Internals](https://tasmota.github.io/docs/LVGL_Internals/)\n\n`lv_berry` uses a semi-automated parsing of lvgl's `C` headers to generate the Berry mapping. The process is automated, but may require small parser adjustments with new versions.\n\nThis module relies on [berry_mapping](https://github.com/berry-lang/berry_mapping) module to automate the mapping of C functions.\n\n**Phase 1: Parse LVGL source**\n\nThis first phase parses most C headers from the LVGL source tree and generates two files:\n\n- `mapping/lv_enum.h` containing all the `enum` values from LVGL (constants)\n- `mapping/lv_funcs.h` containing all the functions of the LVGL API normalized to 1 function per line, and with cleaned argument signature.\n\n```\n(`cd` in folder tools)\n\n❯ python3 preprocessor.py\n(no output)\n```\n\n**Phase 2: Generate automatic Berry mapping**\n\nFrom the two files created in the previous step, all the requires C files are created for the Berry mapping.\n\n```\n(`cd`in folder tools)\n\n\u003e python3 convert.py\n| callback types['lv_group_focus_cb', 'lv_event_cb', 'lv_constructor_cb', 'lv_layout_update_cb', 'lv_obj_tree_walk_cb', 'lv_theme_apply_cb', 'lv_color_filter_cb', 'lv_anim_path_cb']\n```\n\nThe output should look as above, and indicates the C function that have been ignored (if any) if their return type is listed above. It also lists the callback types supported.\n\n\n**Phase 3: Generate the Berry pre-compiled stubs**\n\nThis phase is specific to Berry pre-compiled modules and classes.\n\n```\n(berry)\n\n\u003e python3 tools/pycoc/main.py -o generate src default ../berry_mapping/src ../lv_berry/src ../lv_berry/generate -c default/berry_conf.h\n(no output)\n```\n\n**Phase 4: compile Tasmota using platform.io as usual**\n\n## Future projects\n\nThere is an on-going project to provide [OpenHASP](https://openhasp.haswitchplate.com/) emulation using LVGL+Berry. This will provide a super-easy to use JSON graphical description of UI interfaces, with no or very low knowledge of LVGL APIs.\n\nStay tuned!\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flvgl%2Flv_binding_berry","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Flvgl%2Flv_binding_berry","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flvgl%2Flv_binding_berry/lists"}