K01视频通话提交
authorp15692025051 <846603105@qq.com>
Fri, 24 Nov 2023 10:22:24 +0000 (18:22 +0800)
committerp15692025051 <846603105@qq.com>
Fri, 24 Nov 2023 10:22:24 +0000 (18:22 +0800)
2.sdk/Helios_SDK/services/microPython/ports/quectel/core/source/camera_preview.c
2.sdk/Helios_SDK/services/microPython/ports/quectel/core/source/modVideoCall_juphoon.c
2.sdk/Helios_SDK/services/microPython/ports/quectel/core/source/modlvgl.c
2.sdk/project/K01/sdk/system/platform/ASR_1606/boards/EG810MCN_GA_VOLTE/config/mpconfigboard.h

index 402be02..e42e971 100644 (file)
@@ -43,7 +43,11 @@ WHEN         WHO                     WHAT,WHERE,WHY
 #if MICROPY_QPY_CAMERA_CAMPREVIEW
 
 #include "helios_camera.h"
+#include "lvgl.h"
+#include "jpeg_operation.h"
+#include "helios_debug.h"
 
+#define HELIOS_CAMERA_LOG(msg, ...)      custom_log("CAMERA", msg, ##__VA_ARGS__)
 
 #define OPEN_PREVIEW_AND_DECODE 1
 const mp_obj_type_t camera_preview_type;
@@ -61,7 +65,7 @@ typedef struct _preview_obj_t {
 
 static Helios_CAMConfig camconfig = {0};
 static preview_obj_t *preview_obj = NULL;
-
+static void helios_uv_table_init(void);
 
 STATIC mp_obj_t preview_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) 
 {
@@ -124,20 +128,134 @@ STATIC mp_obj_t preview_make_new(const mp_obj_type_t *type, size_t n_args, size_
        camconfig.lcdprewidth = lcdprewidth;
        camconfig.prebufcnt = prebufcnt;
        camconfig.decbufcnt = 1;
- 
+#if MICROPY_QPY_CAMERA_LVGL_PREVIEW
+       Helios_camera_scandecode_start();
+#endif 
     return MP_OBJ_FROM_PTR(self);
 }
 
 
+/****************************add by elian.wang**************************/
+#if MICROPY_QPY_CAMERA_LVGL_PREVIEW
+static Helios_MsgQ_t get_picture_q = 0;
+static Helios_Thread_t rgb565_decode_task_id = 0;
+uint16_t rgb_buffer[128*128] = {0};
+lv_obj_t *camera_img = NULL;
+
+
+
+lv_img_dsc_t camera_img_dsc;
+void rgb565_decode_handle(void * argv) {
+    uint8_t *buff_addr = NULL;
+    int ret = -1;
+
+    while (1) {
+        ret = Helios_MsgQ_Get(get_picture_q, (void *)&buff_addr, sizeof(uint32_t), HELIOS_WAIT_FOREVER);
+               if (ret != 0)
+               {
+                       HELIOS_CAMERA_LOG("interrupt handle thread failed to get queue\n");
+                       continue;
+               }
+
+               if (camera_img == NULL) {
+                       continue;
+               }
+               yuv420_nv12_to_rgb565_zoom_out((uint16_t*)rgb_buffer, camconfig.lcdprewidth, camconfig.lcdpreheight, (unsigned char *)buff_addr, camconfig.camwidth, camconfig.camheight);
+
+               camera_img_dsc.header.always_zero = 0;
+               camera_img_dsc.header.w = camconfig.lcdprewidth;
+               camera_img_dsc.header.h = camconfig.lcdpreheight;
+               camera_img_dsc.data_size = camconfig.lcdprewidth * camconfig.lcdpreheight * 2; // RGB565格式是2字节/像素
+               camera_img_dsc.header.cf = LV_IMG_CF_TRUE_COLOR;
+               camera_img_dsc.data = (uint8_t *)rgb_buffer;
+               lv_img_set_src(camera_img, &camera_img_dsc);
+       }
+}
+
+ void cam_decode(unsigned char* raw, int width, int height) {
+       Helios_MsgQ_Put(get_picture_q, (const void *)&raw, sizeof(uint32_t), HELIOS_NO_WAIT);
+ }
+
+
+typedef struct mp_lv_obj_t {
+    mp_obj_base_t base;
+    lv_obj_t *lv_obj;
+    lv_obj_t *callbacks;
+} mp_lv_obj_t;
+extern mp_int_t mp_lv_obj_get_buffer(mp_obj_t self_in, mp_buffer_info_t *bufinfo, mp_uint_t flags);
+STATIC mp_obj_t get_native_obj(mp_obj_t *mp_obj)
+{
+    if (!MP_OBJ_IS_OBJ(mp_obj)) return mp_obj;
+    const mp_obj_type_t *native_type = ((mp_obj_base_t*)mp_obj)->type;
+    if (native_type == NULL)
+        return NULL;
+    if (native_type->parent == NULL || 
+        (native_type->buffer_p.get_buffer == mp_lv_obj_get_buffer))
+       return mp_obj;
+    while (native_type->parent) native_type = native_type->parent;
+    return mp_obj_cast_to_native_base(mp_obj, MP_OBJ_FROM_PTR(native_type));
+}
+STATIC inline lv_obj_t *mp_to_lv(mp_obj_t *mp_obj)
+{
+    if (mp_obj == NULL || mp_obj == mp_const_none) return NULL;
+    mp_obj_t native_obj = get_native_obj(mp_obj);
+    if (mp_obj_get_type(native_obj)->buffer_p.get_buffer != mp_lv_obj_get_buffer)
+        return NULL;
+    mp_lv_obj_t *mp_lv_obj = MP_OBJ_TO_PTR(native_obj);
+    return mp_lv_obj->lv_obj;
+}
+
 
+STATIC mp_obj_t set_img(mp_obj_t self_in, mp_obj_t *mp_obj) {
+    lv_obj_t *obj = mp_to_lv(mp_obj);
 
+    if (obj) {
+        camera_img = obj;
+        return mp_obj_new_int(1);
+    } else {
+        return mp_obj_new_int(0);
+    }
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_2(set_img_obj, set_img);
 
+STATIC mp_obj_t remove_img(mp_obj_t self_in) {
+    camera_img = NULL;
+    return mp_obj_new_int(1);
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_1(remove_img_obj, remove_img);
+#endif
+/****************************end add********************************/
 
 STATIC mp_obj_t camera_open(mp_obj_t self_in)
 {
+#if MICROPY_QPY_CAMERA_LVGL_PREVIEW
+       camconfig.preview = 0;
+       camconfig.decode_pro = cam_decode;
+#else
        camconfig.preview = 1;
+#endif
        printf("open %d,%d,%d,%d,%d\n",camconfig.camheight,camconfig.camwidth,camconfig.lcdpreheight,camconfig.lcdprewidth,camconfig.prebufcnt);
-       int error =  Helios_camera_open(&camconfig);//ql_start_preview(data);
+       int error =  Helios_camera_open(&camconfig);
+
+#if MICROPY_QPY_CAMERA_LVGL_PREVIEW
+       Helios_ThreadAttr attr = {0};
+       if (get_picture_q == 0) {
+               get_picture_q = Helios_MsgQ_Create(1, sizeof(uint8_t));
+       }
+       if(rgb565_decode_task_id == 0)
+       {
+           attr.name = "rgb565_decode";
+        attr.stack_size = 1024*4;
+        attr.priority = 90;
+        attr.entry = rgb565_decode_handle;
+
+        rgb565_decode_task_id = Helios_Thread_Create(&attr);
+        if (0 == rgb565_decode_task_id)
+        {
+            mp_raise_ValueError("create interrupt handle task failed\n");
+        }
+       }
+#endif
 
        return mp_obj_new_int(error);
 }
@@ -162,13 +280,14 @@ STATIC mp_obj_t camera_preview_deinit(mp_obj_t self_in)
 }
 STATIC MP_DEFINE_CONST_FUN_OBJ_1(camera_preview__del__obj, camera_preview_deinit);
 
-
-
 STATIC const mp_rom_map_elem_t Preview_locals_dict_table[] = {
        { MP_ROM_QSTR(MP_QSTR___del__),         MP_ROM_PTR(&camera_preview__del__obj) },
     { MP_ROM_QSTR(MP_QSTR_open), MP_ROM_PTR(&camera_preview_open_obj) },
     { MP_ROM_QSTR(MP_QSTR_close), MP_ROM_PTR(&camera_preview_close_obj) },
-
+#if MICROPY_QPY_CAMERA_LVGL_PREVIEW
+       {MP_ROM_QSTR(MP_QSTR_set_img), MP_ROM_PTR(&set_img_obj)},
+    {MP_ROM_QSTR(MP_QSTR_remove_img), MP_ROM_PTR(&remove_img_obj)},
+#endif
 };
 STATIC MP_DEFINE_CONST_DICT(camPreview_locals_dict, Preview_locals_dict_table);
 
index c6f8a56..0a0a086 100644 (file)
 #include "helios_debug.h"
 
 #include "autoconf.h"
-
+#include "lvgl.h"
+#include <helios_lcd.h>
+#include <helios_pwm.h>
+#include <helios_gpio.h>
 
 //////////////////////////////////////////////////////////////////////////////
 
 
 #define HELIOS_JRTC_LOG(msg, ...)      custom_log("JRTC", msg, ##__VA_ARGS__)
 #define datacall_debug(fmt, ...)       custom_log(APP, fmt, ##__VA_ARGS__)
+static Helios_LCDInitStruct init_data = {0};
+#define XSTART_H 0xf0
+#define XSTART_L 0xf1
+#define YSTART_H 0xf2
+#define YSTART_L 0xf3
+#define XEND_H 0xE0
+#define XEND_L 0xE1
+#define YEND_H 0xE2
+#define YEND_L 0xE3
+#define XSTART 0xD0
+#define XEND 0xD1
+#define YSTART 0xD2
+#define YEND 0xD3
+#define PWM_FREQ        10000
+#define PWM_DUTY        0.2
 /** 通话错误值 */
 
 struct jrtc_t
@@ -109,6 +127,71 @@ static c_callback_t cb = {0};
 char *ticket_temp = NULL;
 char *roomid_temp = NULL;
 
+lv_obj_t *jrtc_img = NULL;
+lv_img_dsc_t img_dsc;
+int update_display(uint8_t *camera_buffer, int width, int height) {
+    img_dsc.header.always_zero = 0;
+    img_dsc.header.w = width;
+    img_dsc.header.h = height;
+    img_dsc.data_size = width * height * 2; // RGB565格式是2字节/像素
+    img_dsc.header.cf = LV_IMG_CF_TRUE_COLOR;
+    img_dsc.data = (uint8_t *)camera_buffer;
+
+    // 更新LVGL图像
+    if (jrtc_img) {
+        lv_img_set_src(jrtc_img, &img_dsc);
+        return 1;
+    }
+    return 0;
+}
+
+typedef struct mp_lv_obj_t {
+    mp_obj_base_t base;
+    lv_obj_t *lv_obj;
+    lv_obj_t *callbacks;
+} mp_lv_obj_t;
+extern mp_int_t mp_lv_obj_get_buffer(mp_obj_t self_in, mp_buffer_info_t *bufinfo, mp_uint_t flags);
+STATIC mp_obj_t get_native_obj(mp_obj_t *mp_obj)
+{
+    if (!MP_OBJ_IS_OBJ(mp_obj)) return mp_obj;
+    const mp_obj_type_t *native_type = ((mp_obj_base_t*)mp_obj)->type;
+    if (native_type == NULL)
+        return NULL;
+    if (native_type->parent == NULL || 
+        (native_type->buffer_p.get_buffer == mp_lv_obj_get_buffer))
+       return mp_obj;
+    while (native_type->parent) native_type = native_type->parent;
+    return mp_obj_cast_to_native_base(mp_obj, MP_OBJ_FROM_PTR(native_type));
+}
+
+STATIC inline lv_obj_t *mp_to_lv(mp_obj_t *mp_obj)
+{
+    if (mp_obj == NULL || mp_obj == mp_const_none) return NULL;
+    mp_obj_t native_obj = get_native_obj(mp_obj);
+    if (mp_obj_get_type(native_obj)->buffer_p.get_buffer != mp_lv_obj_get_buffer)
+        return NULL;
+    mp_lv_obj_t *mp_lv_obj = MP_OBJ_TO_PTR(native_obj);
+    return mp_lv_obj->lv_obj;
+}
+
+
+STATIC mp_obj_t set_img(mp_obj_t *mp_obj) {
+    lv_obj_t *obj = mp_to_lv(mp_obj);
+
+    if (obj) {
+        jrtc_img = obj;
+        return mp_obj_new_int(1);
+    } else {
+        return mp_obj_new_int(0);
+    }
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_1(set_img_obj, set_img);
+
+STATIC mp_obj_t remove_img(void) {
+    jrtc_img = NULL;
+    return mp_obj_new_int(1);
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_0(remove_img_obj, remove_img);
 
 void jrtc_handle(void * argv) {
     uint8_t open_state = 0;
@@ -122,17 +205,22 @@ void jrtc_handle(void * argv) {
                }
         if (open_state == 1) {
             if (jrtc_state(test) == JRTC_CLOSED) {
-                //jrtc_open(roomid_temp, ticket_temp, &recieve, &send);
-                // mp_get_buffer_raise(args[ARG_roomid], &roomid, MP_BUFFER_READ);
-                // mp_get_buffer_raise(args[ARG_ticket], &ticket, MP_BUFFER_READ);
-                HELIOS_JRTC_LOG("105\n");
+                //HELIOS_JRTC_LOG("105\n");
                 test = jrtc_open(roomid_temp, ticket_temp, &recieve, &send);
+                //lcd_init();
                 HELIOS_JRTC_LOG("107\n");
                 jrtc_activate(test, JRTC_AUDIO|JRTC_CAMERA);
                 // 等待对方视频对讲结束
                 while(jrtc_state(test) != JRTC_CLOSED)
                 {
-                    Helios_msleep(1000);
+                    struct jrtc_image_t* image;
+                    image = &recieve;
+                    if (image->get != image->put) {
+                        //Helios_LCD_Write(image->data, 0, 0, image->width - 1, image->height - 1);
+                        update_display(image->data, image->width, image->height);
+                        image->get = image->put;
+                    }
+                    Helios_msleep(20);
                 }
                 if (self_close_sta == 0) {
                     // 判断是对方挂断,产生回调
@@ -199,8 +287,6 @@ STATIC mp_obj_t mp_jrtc_config (size_t n_args, const mp_obj_t *args, mp_map_t *k
     static Helios_DataCallInfoStruct datacall_info = {0};
     Helios_DataCall_GetInfo(1, 0, &datacall_info);
     enum { ARG_appkey, ARG_uid, ARG_srvURL,  ARG_key};
-    //jrtc_image_t temp_image_config = {0};
-
     static const mp_arg_t allowed_args[] = 
     {
        { MP_QSTR_appkey,     MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
@@ -210,22 +296,11 @@ STATIC mp_obj_t mp_jrtc_config (size_t n_args, const mp_obj_t *args, mp_map_t *k
     };
     mp_arg_val_t vals[MP_ARRAY_SIZE(allowed_args)];
     mp_arg_parse_all(n_args , args , kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, vals);
-    //mp_buffer_info_t appkey, uid, srvURL, key;
-    // mp_get_buffer_raise(args[ARG_appkey], &appkey, MP_BUFFER_READ);
-    // mp_get_buffer_raise(args[ARG_uid], &uid, MP_BUFFER_READ);
-    // mp_get_buffer_raise(args[ARG_srvURL], &srvURL, MP_BUFFER_READ);
-    // mp_get_buffer_raise(args[ARG_key], &key, MP_BUFFER_READ);
 
     char *appkey_temp = (char *)mp_obj_str_get_str(vals[ARG_appkey].u_obj);
     char *uid_temp = (char *)mp_obj_str_get_str(vals[ARG_uid].u_obj);
     char *srvURL_temp = (char *)mp_obj_str_get_str(vals[ARG_srvURL].u_obj);
     char *key_temp = (char *)mp_obj_str_get_str(vals[ARG_key].u_obj);
-    // char *appkey_temp = (char *)mp_obj_str_get_str(ARG_appkey);
-    // char *uid_temp = (char *)mp_obj_str_get_str(ARG_uid);
-    // char *srvURL_temp = (char *)mp_obj_str_get_str(ARG_srvURL);
-    // char *key_temp = (char *)mp_obj_str_get_str(ARG_key);
-    // jrtc_config(appkey_temp, uid_temp, srvURL_temp, key_temp);
-    //jrtc_config(appkey.buf, uid.buf, srvURL.buf, key.buf);
 
     jrtc_config(appkey_temp, uid_temp, srvURL_temp, key_temp);
     _jrtc_net_info = &datacall_info;
@@ -254,8 +329,6 @@ STATIC mp_obj_t mp_jrtc_open (size_t n_args, const mp_obj_t *args, mp_map_t *kw_
     };
     mp_arg_val_t vals[MP_ARRAY_SIZE(allowed_args)];
     mp_arg_parse_all(n_args , args , kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, vals);
-    /*mp_get_buffer_raise(vals[ARG_roomid].u_obj, &roomid, MP_BUFFER_READ);
-    mp_get_buffer_raise(vals[ARG_ticket].u_obj, &ticket, MP_BUFFER_READ);*/
 
     roomid_temp = (char *)mp_obj_str_get_str(vals[ARG_roomid].u_obj);
     ticket_temp = (char *)mp_obj_str_get_str(vals[ARG_ticket].u_obj);
@@ -276,8 +349,6 @@ STATIC mp_obj_t mp_jrtc_open (size_t n_args, const mp_obj_t *args, mp_map_t *kw_
     uint8_t int_happen = 1;
     Helios_MsgQ_Put(int_happen_q, (const void *)&int_happen, sizeof(uint8_t), HELIOS_NO_WAIT);
     
-    //  ret = jrtc_open(roomid_temp, ticket_temp, &recieve, &send);
-    //  jrtc_activate(test, JRTC_AUDIO|JRTC_CAMERA);
     return mp_obj_new_int(ret);
 }
 STATIC MP_DEFINE_CONST_FUN_OBJ_KW(mp_jrtc_open_obj, 4, mp_jrtc_open);
@@ -329,6 +400,8 @@ STATIC const mp_rom_map_elem_t jrtc_globals_table[] = {
     {MP_ROM_QSTR(MP_QSTR_set_callback), MP_ROM_PTR(&mp_set_callback_obj)},
     {MP_ROM_QSTR(MP_QSTR_init), MP_ROM_PTR(&mp_jrtc_init_obj)},
     {MP_ROM_QSTR(MP_QSTR_config_server), MP_ROM_PTR(&mp_jrtc_config_server_obj)},
+    {MP_ROM_QSTR(MP_QSTR_set_img), MP_ROM_PTR(&set_img_obj)},
+    {MP_ROM_QSTR(MP_QSTR_remove_img), MP_ROM_PTR(&remove_img_obj)},
 };
 
 /* 把modjrtc_globals_table注册到 mp_module_modjrtc_globals里面去 */
@@ -342,5 +415,5 @@ const mp_obj_module_t mp_module_jrtc = {
     //.make_new = can_mcp2515_make_new, //添加的make new属性
     .globals = (mp_obj_dict_t*)&mp_module_jrtc_globals, //注册jrtc_locals_dict
 };
-#endif 
 
+#endif
\ No newline at end of file
index 57349af..d7b3915 100644 (file)
@@ -175,9 +175,9 @@ typedef struct mp_lv_struct_t
 STATIC const mp_lv_struct_t mp_lv_null_obj;
 
 #ifdef LV_OBJ_T
-STATIC mp_int_t mp_lv_obj_get_buffer(mp_obj_t self_in, mp_buffer_info_t *bufinfo, mp_uint_t flags);
+mp_int_t mp_lv_obj_get_buffer(mp_obj_t self_in, mp_buffer_info_t *bufinfo, mp_uint_t flags);
 #else
-STATIC mp_int_t mp_lv_obj_get_buffer(mp_obj_t self_in, mp_buffer_info_t *bufinfo, mp_uint_t flags){ return 0; }
+mp_int_t mp_lv_obj_get_buffer(mp_obj_t self_in, mp_buffer_info_t *bufinfo, mp_uint_t flags){ return 0; }
 #endif
 
 STATIC mp_obj_t get_native_obj(mp_obj_t *mp_obj)
@@ -338,7 +338,7 @@ STATIC mp_obj_t make_new(
 STATIC MP_DEFINE_CONST_FUN_OBJ_2(cast_obj_obj, cast_obj);
 STATIC MP_DEFINE_CONST_CLASSMETHOD_OBJ(cast_obj_class_method, MP_ROM_PTR(&cast_obj_obj));
 
-STATIC mp_int_t mp_lv_obj_get_buffer(mp_obj_t self_in, mp_buffer_info_t *bufinfo, mp_uint_t flags) {
+mp_int_t mp_lv_obj_get_buffer(mp_obj_t self_in, mp_buffer_info_t *bufinfo, mp_uint_t flags) {
     (void)flags;
     mp_lv_obj_t *self = MP_OBJ_TO_PTR(self_in);
 
@@ -458,6 +458,45 @@ STATIC mp_obj_t lv_struct_binary_op(mp_binary_op_t op, mp_obj_t lhs_in, mp_obj_t
     }
 }
 
+STATIC mp_obj_t lv_struct_subscr(mp_obj_t self_in, mp_obj_t index, mp_obj_t value)
+{
+    mp_lv_struct_t *self = mp_to_lv_struct(self_in);
+
+    if ((!self) || (!self->data))
+        return NULL;
+    if (!mp_obj_is_int(index)) {
+        nlr_raise(
+            mp_obj_new_exception_msg(
+                &mp_type_SyntaxError, MP_ERROR_TEXT("Subscript index must be an integer!")));
+    }
+
+    const mp_obj_type_t *type = mp_obj_get_type(self_in);
+    size_t element_size = get_lv_struct_size(type);
+    size_t element_index = mp_obj_get_int(index);
+    void *element_addr = (byte*)self->data + element_size*element_index;
+
+    if (value == MP_OBJ_NULL) {
+        memset(element_addr, 0, element_size);
+        return self_in;
+    }
+
+    mp_lv_struct_t *element_at_index = m_new_obj(mp_lv_struct_t);
+    *element_at_index = (mp_lv_struct_t){
+        .base = {type},
+        .data = element_addr
+    };
+
+    if (value != MP_OBJ_SENTINEL){
+        mp_lv_struct_t *other = mp_to_lv_struct(cast(value, type));
+        if ((!other) || (!other->data))
+            return NULL;
+        memcpy(element_at_index->data, other->data, element_size);
+    }
+
+    return MP_OBJ_FROM_PTR(element_at_index);
+}
+
+
 STATIC void *copy_buffer(const void *buffer, size_t size)
 {
     void *new_buffer = m_malloc(size);
@@ -19741,6 +19780,309 @@ STATIC const mp_lv_obj_type_t mp_lv_win_type = {
 };
 #endif    
 
+#ifdef CONFIG_LVGL_IME_PINYIN
+/* Reusing lv_keyboard_set_textarea for lv_ime_pinyin_set_keyboard */
+
+STATIC MP_DEFINE_CONST_LV_FUN_OBJ_VAR(mp_lv_ime_pinyin_set_keyboard_mpobj, 2, mp_lv_keyboard_set_textarea, lv_ime_pinyin_set_keyboard);
+
+
+/*
+ * lvgl LV_IME_PINYIN_MODE object definitions
+ */
+
+
+
+STATIC const mp_rom_map_elem_t mp_base_struct_locals_dict_table[] = {
+    { MP_ROM_QSTR(MP_QSTR___cast__), MP_ROM_PTR(&mp_lv_cast_class_method) },
+    { MP_ROM_QSTR(MP_QSTR___cast_instance__), MP_ROM_PTR(&mp_lv_cast_instance_obj) },
+    { MP_ROM_QSTR(MP_QSTR___dereference__), MP_ROM_PTR(&mp_lv_dereference_obj) },
+};
+
+STATIC MP_DEFINE_CONST_DICT(mp_base_struct_locals_dict, mp_base_struct_locals_dict_table);
+
+    
+
+STATIC const mp_rom_map_elem_t LV_IME_PINYIN_MODE_locals_dict_table[] = {
+    { MP_ROM_QSTR(MP_QSTR_K26), MP_ROM_PTR(MP_ROM_INT(LV_IME_PINYIN_MODE_K26)) },
+    { MP_ROM_QSTR(MP_QSTR_K9), MP_ROM_PTR(MP_ROM_INT(LV_IME_PINYIN_MODE_K9)) },
+//    { MP_ROM_QSTR(MP_QSTR_K9_NUMBER), MP_ROM_PTR(MP_ROM_INT(LV_IME_PINYIN_MODE_K9_NUMBER)) }
+};
+
+STATIC MP_DEFINE_CONST_DICT(LV_IME_PINYIN_MODE_locals_dict, LV_IME_PINYIN_MODE_locals_dict_table);
+
+STATIC void LV_IME_PINYIN_MODE_print(const mp_print_t *print,
+    mp_obj_t self_in,
+    mp_print_kind_t kind)
+{
+    mp_printf(print, "lvgl LV_IME_PINYIN_MODE");
+}
+
+
+
+STATIC const mp_lv_obj_type_t mp_lv_LV_IME_PINYIN_MODE_type = {
+    {
+        { &mp_type_type },
+        .name = MP_QSTR_LV_IME_PINYIN_MODE,
+        .print = LV_IME_PINYIN_MODE_print,
+        
+        
+        .attr = call_parent_methods,
+        .locals_dict = (mp_obj_dict_t*)&LV_IME_PINYIN_MODE_locals_dict,
+        
+        .parent = NULL
+    },
+#ifdef LV_OBJ_T
+    NULL
+#endif
+};
+
+STATIC const mp_obj_type_t mp_lv_base_struct_type = {
+    { &mp_type_type },
+    .name = MP_QSTR_Struct,
+    .binary_op = lv_struct_binary_op,
+    .subscr = lv_struct_subscr,
+    .locals_dict = (mp_obj_dict_t*)&mp_base_struct_locals_dict,
+    .buffer_p = { .get_buffer = mp_blob_get_buffer }
+};
+
+
+
+/*
+ * Struct lv_pinyin_dict_t
+ */
+
+STATIC inline const mp_obj_type_t *get_mp_lv_pinyin_dict_t_type();
+
+STATIC inline void* mp_write_ptr_lv_pinyin_dict_t(mp_obj_t self_in)
+{
+    mp_lv_struct_t *self = MP_OBJ_TO_PTR(cast(self_in, get_mp_lv_pinyin_dict_t_type()));
+    return (lv_pinyin_dict_t*)self->data;
+}
+
+#define mp_write_lv_pinyin_dict_t(struct_obj) *((lv_pinyin_dict_t*)mp_write_ptr_lv_pinyin_dict_t(struct_obj))
+
+STATIC inline mp_obj_t mp_read_ptr_lv_pinyin_dict_t(void *field)
+{
+    return lv_to_mp_struct(get_mp_lv_pinyin_dict_t_type(), field);
+}
+
+#define mp_read_lv_pinyin_dict_t(field) mp_read_ptr_lv_pinyin_dict_t(copy_buffer(&field, sizeof(lv_pinyin_dict_t)))
+#define mp_read_byref_lv_pinyin_dict_t(field) mp_read_ptr_lv_pinyin_dict_t(&field)
+
+STATIC void mp_lv_pinyin_dict_t_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest)
+{
+    mp_lv_struct_t *self = MP_OBJ_TO_PTR(self_in);
+    GENMPY_UNUSED lv_pinyin_dict_t *data = (lv_pinyin_dict_t*)self->data;
+
+    if (dest[0] == MP_OBJ_NULL) {
+        // load attribute
+        switch(attr)
+        {
+            case MP_QSTR_py: dest[0] = convert_to_str((void*)data->py); break; // converting from char *;
+            case MP_QSTR_py_mb: dest[0] = convert_to_str((void*)data->py_mb); break; // converting from char *;
+            default: call_parent_methods(self_in, attr, dest); // fallback to locals_dict lookup
+        }
+    } else {
+        if (dest[1])
+        {
+            // store attribute
+            switch(attr)
+            {
+                ;
+                default: return;
+            }
+
+            dest[0] = MP_OBJ_NULL; // indicate success
+        }
+    }
+}
+
+STATIC void mp_lv_pinyin_dict_t_print(const mp_print_t *print,
+    mp_obj_t self_in,
+    mp_print_kind_t kind)
+{
+    mp_printf(print, "struct lv_pinyin_dict_t");
+}
+
+STATIC const mp_obj_dict_t mp_lv_pinyin_dict_t_locals_dict;
+
+
+
+STATIC const mp_obj_type_t mp_lv_pinyin_dict_t_type = {
+    { &mp_type_type },
+    .name = MP_QSTR_lv_pinyin_dict_t,
+    .print = mp_lv_pinyin_dict_t_print,
+    .make_new = make_new_lv_struct,
+    .binary_op = lv_struct_binary_op,
+    .subscr = lv_struct_subscr,
+    .attr = mp_lv_pinyin_dict_t_attr,
+    .locals_dict = (mp_obj_dict_t*)&mp_lv_pinyin_dict_t_locals_dict,
+    .buffer_p = { .get_buffer = mp_blob_get_buffer },
+    .parent = &mp_lv_base_struct_type
+};
+
+STATIC inline const mp_obj_type_t *get_mp_lv_pinyin_dict_t_type()
+{
+    return &mp_lv_pinyin_dict_t_type;
+}
+    
+
+/*
+ * lvgl extension definition for:
+ * void lv_ime_pinyin_set_dict(lv_obj_t *obj, lv_pinyin_dict_t *dict)
+ */
+
+STATIC mp_obj_t mp_lv_ime_pinyin_set_dict(size_t mp_n_args, const mp_obj_t *mp_args, void *lv_func_ptr)
+{
+    lv_obj_t *obj = mp_to_lv(mp_args[0]);
+    lv_pinyin_dict_t *dict = mp_write_ptr_lv_pinyin_dict_t(mp_args[1]);
+    ((void (*)(lv_obj_t *, lv_pinyin_dict_t *))lv_func_ptr)(obj, dict);
+    return mp_const_none;
+}
+
+ 
+
+STATIC MP_DEFINE_CONST_LV_FUN_OBJ_VAR(mp_lv_ime_pinyin_set_dict_mpobj, 2, mp_lv_ime_pinyin_set_dict, lv_ime_pinyin_set_dict);
+    
+
+/*
+ * lvgl extension definition for:
+ * void lv_ime_pinyin_set_mode(lv_obj_t *obj, lv_ime_pinyin_mode_t mode)
+ */
+
+STATIC mp_obj_t mp_lv_ime_pinyin_set_mode(size_t mp_n_args, const mp_obj_t *mp_args, void *lv_func_ptr)
+{
+    lv_obj_t *obj = mp_to_lv(mp_args[0]);
+    lv_ime_pinyin_mode_t mode = (int)mp_obj_get_int(mp_args[1]);
+    ((void (*)(lv_obj_t *, lv_ime_pinyin_mode_t))lv_func_ptr)(obj, mode);
+    return mp_const_none;
+}
+
+ 
+
+STATIC MP_DEFINE_CONST_LV_FUN_OBJ_VAR(mp_lv_ime_pinyin_set_mode_mpobj, 2, mp_lv_ime_pinyin_set_mode, lv_ime_pinyin_set_mode);
+    
+/* Reusing lv_obj_create for lv_ime_pinyin_get_kb */
+
+STATIC MP_DEFINE_CONST_LV_FUN_OBJ_VAR(mp_lv_ime_pinyin_get_kb_mpobj, 1, mp_lv_obj_create, lv_ime_pinyin_get_kb);
+    
+/* Reusing lv_obj_create for lv_ime_pinyin_get_cand_panel */
+
+STATIC MP_DEFINE_CONST_LV_FUN_OBJ_VAR(mp_lv_ime_pinyin_get_cand_panel_mpobj, 1, mp_lv_obj_create, lv_ime_pinyin_get_cand_panel);
+
+STATIC MP_DEFINE_CONST_LV_FUN_OBJ_VAR(mp_lv_ime_pinyin_get_comb_panel_mpobj, 1, mp_lv_obj_create, lv_ime_pinyin_get_comb_panel);
+
+
+
+
+    
+
+/*
+ * lvgl extension definition for:
+ * lv_pinyin_dict_t *lv_ime_pinyin_get_dict(lv_obj_t *obj)
+ */
+
+STATIC mp_obj_t mp_lv_ime_pinyin_get_dict(size_t mp_n_args, const mp_obj_t *mp_args, void *lv_func_ptr)
+{
+    lv_obj_t *obj = mp_to_lv(mp_args[0]);
+    lv_pinyin_dict_t * _res = ((lv_pinyin_dict_t *(*)(lv_obj_t *))lv_func_ptr)(obj);
+    return mp_read_ptr_lv_pinyin_dict_t((void*)_res);
+}
+
+ 
+
+STATIC MP_DEFINE_CONST_LV_FUN_OBJ_VAR(mp_lv_ime_pinyin_get_dict_mpobj, 1, mp_lv_ime_pinyin_get_dict, lv_ime_pinyin_get_dict);
+    
+/* Reusing lv_obj_create for lv_ime_pinyin_create */
+
+STATIC MP_DEFINE_CONST_LV_FUN_OBJ_VAR(mp_lv_ime_pinyin_create_mpobj, 1, mp_lv_obj_create, lv_ime_pinyin_create);
+
+
+STATIC mp_obj_t mp_lv_ime_pinyin_set_sel_btn(size_t mp_n_args, const mp_obj_t *mp_args, void *lv_func_ptr)
+{
+    lv_obj_t *obj = mp_to_lv(mp_args[0]);
+    uint16_t btn_id = (uint16_t)mp_obj_get_int(mp_args[1]);
+    ((void (*)(lv_obj_t *, lv_ime_pinyin_mode_t))lv_func_ptr)(obj, btn_id);
+    return mp_const_none;
+}
+
+
+STATIC MP_DEFINE_CONST_LV_FUN_OBJ_VAR(mp_lv_ime_pinyin_set_btn_id_mpobj, 2, mp_lv_ime_pinyin_set_sel_btn, lv_ime_pinyin_set_btnID);
+
+
+
+STATIC mp_obj_t mp_lv_ime_pinyin_get_sel_btn(size_t mp_n_args, const mp_obj_t *mp_args, void *lv_func_ptr)
+{
+       (void)mp_n_args;
+    lv_obj_t *obj = mp_to_lv(mp_args[0]);
+       uint16_t _res = ((uint16_t (*)(const lv_obj_t *))lv_func_ptr)(obj);
+    return mp_obj_new_int_from_uint(_res);
+}
+
+
+STATIC MP_DEFINE_CONST_LV_FUN_OBJ_VAR(mp_lv_ime_pinyin_get_btn_id_mpobj, 1, mp_lv_ime_pinyin_get_sel_btn, lv_ime_pinyin_get_btnID);
+
+
+/*
+ * lvgl ime_pinyin object definitions
+ */
+    
+
+STATIC const mp_rom_map_elem_t ime_pinyin_locals_dict_table[] = {
+    { MP_ROM_QSTR(MP_QSTR_pinyin_set_keyboard), MP_ROM_PTR(&mp_lv_ime_pinyin_set_keyboard_mpobj) },
+    { MP_ROM_QSTR(MP_QSTR_pinyin_set_dict), MP_ROM_PTR(&mp_lv_ime_pinyin_set_dict_mpobj) },
+    { MP_ROM_QSTR(MP_QSTR_pinyin_set_mode), MP_ROM_PTR(&mp_lv_ime_pinyin_set_mode_mpobj) },
+    { MP_ROM_QSTR(MP_QSTR_pinyin_get_kb), MP_ROM_PTR(&mp_lv_ime_pinyin_get_kb_mpobj) },
+    { MP_ROM_QSTR(MP_QSTR_pinyin_get_cand_panel), MP_ROM_PTR(&mp_lv_ime_pinyin_get_cand_panel_mpobj) },
+       { MP_ROM_QSTR(MP_QSTR_pinyin_get_comb_panel), MP_ROM_PTR(&mp_lv_ime_pinyin_get_comb_panel_mpobj) },
+    { MP_ROM_QSTR(MP_QSTR_pinyin_get_dict), MP_ROM_PTR(&mp_lv_ime_pinyin_get_dict_mpobj) },
+    { MP_ROM_QSTR(MP_QSTR_pinyin_get_btn_id), MP_ROM_PTR(&mp_lv_ime_pinyin_get_btn_id_mpobj) },
+    { MP_ROM_QSTR(MP_QSTR_pinyin_set_btn_id), MP_ROM_PTR(&mp_lv_ime_pinyin_set_btn_id_mpobj) },
+    { MP_ROM_QSTR(MP_QSTR_PINYIN_MODE), MP_ROM_PTR(&mp_lv_LV_IME_PINYIN_MODE_type.mp_obj_type) }
+};
+
+STATIC MP_DEFINE_CONST_DICT(ime_pinyin_locals_dict, ime_pinyin_locals_dict_table);
+
+STATIC void ime_pinyin_print(const mp_print_t *print,
+    mp_obj_t self_in,
+    mp_print_kind_t kind)
+{
+    mp_printf(print, "lvgl ime_pinyin");
+}
+
+
+STATIC mp_obj_t ime_pinyin_make_new(
+    const mp_obj_type_t *type,
+    size_t n_args,
+    size_t n_kw,
+    const mp_obj_t *args)
+{
+    return make_new(&mp_lv_ime_pinyin_create_mpobj, type, n_args, n_kw, args);
+}
+
+extern const lv_obj_class_t lv_ime_pinyin_class;
+
+STATIC const mp_lv_obj_type_t mp_lv_ime_pinyin_type = {
+    {
+        { &mp_type_type },
+        .name = MP_QSTR_ime_pinyin,
+        .print = ime_pinyin_print,
+        .make_new = ime_pinyin_make_new,
+        .binary_op = mp_lv_obj_binary_op,
+        .attr = call_parent_methods,
+        .locals_dict = (mp_obj_dict_t*)&ime_pinyin_locals_dict,
+        .buffer_p = { .get_buffer = mp_lv_obj_get_buffer },
+        .parent = &mp_lv_obj_type.mp_obj_type
+    },
+#ifdef LV_OBJ_T
+    &lv_ime_pinyin_class
+#endif
+};
+   
+#endif
+
+
+
 /*
  * Struct lv_color_hsv_t
  */
@@ -21682,6 +22024,16 @@ STATIC const mp_lv_struct_t mp_lv_win_class = {
     (lv_obj_class_t*)&lv_win_class
 };
 #endif
+#ifdef CONFIG_LVGL_IME_PINYIN
+/*
+ * lvgl lv_ime_pinyin_class global definitions
+ */
+    
+STATIC const mp_lv_struct_t mp_lv_ime_pinyin_class = {
+    { &mp_lv_obj_class_t_type },
+    (lv_obj_class_t*)&lv_ime_pinyin_class
+};
+#endif
     
 #if LV_USE_COLORWHEEL
 /*