Просмотр исходного кода

Merge branch 'master' of https://gitee.com/openLuat/LuatOS

alienwalker 8 месяцев назад
Родитель
Сommit
84c472d2af
100 измененных файлов с 3285 добавлено и 235 удалено
  1. 6 2
      components/airlink/binding/luat_lib_airlink.c
  2. 7 0
      components/airlink/src/luat_airlink.c
  3. 4 2
      components/airlink/src/luat_airlink_linkdata.c
  4. 71 22
      components/airlink/src/task/luat_airlink_uart_task.c
  5. 4 0
      components/drv/src/luat_drv_bluetooth.c
  6. 1 2
      components/lcd/luat_lib_lcd_jpg.c
  7. 9 0
      components/lvgl/binding/luat_lib_lvgl_font.c
  8. 35 142
      components/lvgl/font/lv_font_gtfont.c
  9. 4 6
      components/lvgl/src/lv_widgets/lv_img.c
  10. 1 1
      components/lvgl8/porting/lv_port_indev.h
  11. 1 0
      components/lvgl8/src/draw/sw/lv_draw_sw_letter.c
  12. 1 1
      components/lvgl8/src/draw/swm341_dma2d/lv_gpu_swm341_dma2d.c
  13. 7 2
      components/lvgl8/src/extra/libs/png/lv_png.c
  14. 17 4
      components/lvgl8/src/extra/libs/sjpg/lv_sjpg.c
  15. 1 1
      components/lvgl8/src/extra/widgets/span/lv_span.c
  16. 35 25
      components/network/adapter_lwip2/net_lwip2.c
  17. 1 1
      components/network/adapter_lwip2/net_lwip2.h
  18. 4 0
      components/network/netdrv/include/luat_netdrv.h
  19. 1 1
      components/network/netdrv/src/ch390h_task.c
  20. 36 0
      components/network/netdrv/src/luat_netdrv.c
  21. 1 1
      components/network/netdrv/src/luat_netdrv_whale.c
  22. 18 11
      components/network/ulwip/src/ulwip_dhcp_client.c
  23. 1 1
      lua/src/lbaselib.c
  24. 52 0
      luat/demo/airlink/uart_http/main.lua
  25. 32 0
      luat/demo/airlink/uart_sdata/main.lua
  26. 29 3
      luat/demo/io/main.lua
  27. 5 7
      luat/demo/spi/air8000/spi_tf_wan/main.lua
  28. BIN
      module/Air780EHM&EHV&EGH/LuatOS多固件功能区别.png
  29. BIN
      module/Air780EHM&EHV&EGH/LuatOS多固件策略说明.png
  30. BIN
      module/Air780EHM&EHV&EGH/LuatOS扩展库简要说明.png
  31. 129 0
      module/Air780EHM&EHV&EGH/README.md
  32. 5 0
      module/Air780EHM&EHV&EGH/core/version.md
  33. 0 0
      module/Air780EHM&EHV&EGH/demo/CC/main.lua
  34. 0 0
      module/Air780EHM&EHV&EGH/demo/JT808/main.lua
  35. 0 0
      module/Air780EHM&EHV&EGH/demo/SPI/main.lua
  36. 650 0
      module/Air780EHM&EHV&EGH/demo/SPI/rc522.lua
  37. 0 0
      module/Air780EHM&EHV&EGH/demo/SPI/rc522_test.lua
  38. 0 0
      module/Air780EHM&EHV&EGH/demo/SPI/readme.md
  39. 0 0
      module/Air780EHM&EHV&EGH/demo/WebSocket/WebSocket-UART透传/main.lua
  40. 0 0
      module/Air780EHM&EHV&EGH/demo/WebSocket/WebSocket加密通讯/main.lua
  41. 0 0
      module/Air780EHM&EHV&EGH/demo/adc/main.lua
  42. 83 0
      module/Air780EHM&EHV&EGH/demo/adc/testAdc.lua
  43. 0 0
      module/Air780EHM&EHV&EGH/demo/airlbs/main.lua
  44. 0 0
      module/Air780EHM&EHV&EGH/demo/airtalk/airaudio.lua
  45. 0 0
      module/Air780EHM&EHV&EGH/demo/airtalk/main.lua
  46. 0 0
      module/Air780EHM&EHV&EGH/demo/airtalk/talk.lua
  47. 0 0
      module/Air780EHM&EHV&EGH/demo/apn/main.lua
  48. 0 0
      module/Air780EHM&EHV&EGH/demo/audio/1.mp3
  49. 0 0
      module/Air780EHM&EHV&EGH/demo/audio/main.lua
  50. 0 0
      module/Air780EHM&EHV&EGH/demo/bit/main.lua
  51. 0 0
      module/Air780EHM&EHV&EGH/demo/bit64/main.lua
  52. 115 0
      module/Air780EHM&EHV&EGH/demo/camera/spi_cam/bf30a2.lua
  53. 328 0
      module/Air780EHM&EHV&EGH/demo/camera/spi_cam/gc0310.lua
  54. 361 0
      module/Air780EHM&EHV&EGH/demo/camera/spi_cam/gc032a.lua
  55. 222 0
      module/Air780EHM&EHV&EGH/demo/camera/spi_cam/main.lua
  56. 73 0
      module/Air780EHM&EHV&EGH/demo/can/main.lua
  57. 0 0
      module/Air780EHM&EHV&EGH/demo/crypto/logo.jpg
  58. 0 0
      module/Air780EHM&EHV&EGH/demo/crypto/main.lua
  59. 0 0
      module/Air780EHM&EHV&EGH/demo/errDump/main.lua
  60. 51 0
      module/Air780EHM&EHV&EGH/demo/fastlz/fastlz_test.lua
  61. 65 0
      module/Air780EHM&EHV&EGH/demo/fastlz/main.lua
  62. 40 0
      module/Air780EHM&EHV&EGH/demo/fastlz/readme.md
  63. 0 0
      module/Air780EHM&EHV&EGH/demo/fastlz/test.txt
  64. 0 0
      module/Air780EHM&EHV&EGH/demo/fota2/main.lua
  65. 0 0
      module/Air780EHM&EHV&EGH/demo/fs/main.lua
  66. 0 0
      module/Air780EHM&EHV&EGH/demo/fskv/main.lua
  67. 0 0
      module/Air780EHM&EHV&EGH/demo/ftp/main.lua
  68. 38 0
      module/Air780EHM&EHV&EGH/demo/gpio/agpio_test.lua
  69. 43 0
      module/Air780EHM&EHV&EGH/demo/gpio/gpio_input_test.lua
  70. 36 0
      module/Air780EHM&EHV&EGH/demo/gpio/gpio_irq_count_test.lua
  71. 32 0
      module/Air780EHM&EHV&EGH/demo/gpio/gpio_irq_test.lua
  72. 41 0
      module/Air780EHM&EHV&EGH/demo/gpio/gpio_output_test.lua
  73. 40 0
      module/Air780EHM&EHV&EGH/demo/gpio/gpio_pullupdown_test.lua
  74. 36 0
      module/Air780EHM&EHV&EGH/demo/gpio/gpio_toggle_test.lua
  75. 83 0
      module/Air780EHM&EHV&EGH/demo/gpio/main.lua
  76. 67 0
      module/Air780EHM&EHV&EGH/demo/gpio/readme.md
  77. 0 0
      module/Air780EHM&EHV&EGH/demo/helloworld/main.lua
  78. 0 0
      module/Air780EHM&EHV&EGH/demo/hmeta/main.lua
  79. 0 0
      module/Air780EHM&EHV&EGH/demo/http/luatos_uploadFile.txt
  80. 0 0
      module/Air780EHM&EHV&EGH/demo/http/main.lua
  81. 41 0
      module/Air780EHM&EHV&EGH/demo/i2c-aht10/main.lua
  82. 70 0
      module/Air780EHM&EHV&EGH/demo/i2c-sht20/hw_i2c_sht20_test.lua
  83. 70 0
      module/Air780EHM&EHV&EGH/demo/i2c-sht20/main.lua
  84. 52 0
      module/Air780EHM&EHV&EGH/demo/i2c-sht20/pins_Air780EGH.json
  85. 59 0
      module/Air780EHM&EHV&EGH/demo/i2c-sht20/readme.md
  86. 71 0
      module/Air780EHM&EHV&EGH/demo/i2c-sht20/soft_i2c_sht20_test.lua
  87. 0 0
      module/Air780EHM&EHV&EGH/demo/i2c/aht10_test.lua
  88. 0 0
      module/Air780EHM&EHV&EGH/demo/i2c/main.lua
  89. 0 0
      module/Air780EHM&EHV&EGH/demo/i2c/readme.md
  90. 0 0
      module/Air780EHM&EHV&EGH/demo/iconv/main.lua
  91. 0 0
      module/Air780EHM&EHV&EGH/demo/iotcloud/aliyun/示例1 一型一密(免预注册,但需要是企业版实例平台)方式连接云平台/main.lua
  92. 0 0
      module/Air780EHM&EHV&EGH/demo/iotcloud/aliyun/示例2 一型一密(预注册)方式连接云平台/main.lua
  93. 0 0
      module/Air780EHM&EHV&EGH/demo/iotcloud/aliyun/示例3 一机一密方式连接云平台/main.lua
  94. 0 0
      module/Air780EHM&EHV&EGH/demo/iotcloud/baiduiot/main.lua
  95. 0 0
      module/Air780EHM&EHV&EGH/demo/iotcloud/huaweiiot/main.lua
  96. 0 0
      module/Air780EHM&EHV&EGH/demo/iotcloud/onenet/main.lua
  97. 0 0
      module/Air780EHM&EHV&EGH/demo/iotcloud/tencentiot/main.lua
  98. 0 0
      module/Air780EHM&EHV&EGH/demo/iotcloud/tlink/main.lua
  99. 0 0
      module/Air780EHM&EHV&EGH/demo/iotcloud/tuyaiot/示例1 一机一密/main.lua
  100. 0 0
      module/Air780EHM&EHV&EGH/demo/json/main.lua

+ 6 - 2
components/airlink/binding/luat_lib_airlink.c

@@ -70,10 +70,14 @@ static int l_airlink_start(lua_State *L) {
         // 临时入口,先写死
         LLOGD("启动AirLink从机模式");
     }
-    else {
-        // 临时入口,先写死
+        else if(id == 1)
+    {
         LLOGD("启动AirLink主机模式");
     }
+    else if(id == 2)
+    {
+        LLOGD("启动AirLink UART模式");
+    }
     luat_airlink_task_start();
     luat_airlink_start(id);
     return 0;

+ 7 - 0
components/airlink/src/luat_airlink.c

@@ -29,6 +29,7 @@ luat_rtos_queue_t airlink_ippkg_queue;
 extern int luat_airlink_start_slave(void);
 extern int luat_airlink_start_master(void);
 extern void luat_airlink_start_uart(void);
+extern luat_airlink_dev_info_t g_airlink_ext_dev_info;
 luat_airlink_newdata_notify_cb g_airlink_newdata_notify_cb;
 luat_airlink_spi_conf_t g_airlink_spi_conf;
 airlink_statistic_t g_airlink_statistic;
@@ -549,3 +550,9 @@ int luat_airlink_has_wifi(void) {
     }
     return 0;
 }
+
+uint32_t luat_airlink_sversion(void) {
+    uint32_t version = 0;
+    memcpy(&version, g_airlink_ext_dev_info.wifi.version, 4);
+    return version;
+}

+ 4 - 2
components/airlink/src/luat_airlink_linkdata.c

@@ -37,7 +37,6 @@ __USER_FUNC_IN_RAM__ airlink_link_data_t* luat_airlink_data_unpack(uint8_t *buff
             link = (airlink_link_data_t*)(buff + i);
             tlen = link->len;
             crc16 = link->crc16;
-            // LLOGD("找到magic, 且数据长度为 %d", tlen);
             if (tlen > 0 && tlen + 4 + i + 4 <= len)
             {
                 // 计算crc16
@@ -50,6 +49,7 @@ __USER_FUNC_IN_RAM__ airlink_link_data_t* luat_airlink_data_unpack(uint8_t *buff
                 else
                 {
                     LLOGD("crc16校验失败 %d %d", crc16_data, crc16);
+                    link = NULL;
                 }
             }
             else
@@ -58,6 +58,7 @@ __USER_FUNC_IN_RAM__ airlink_link_data_t* luat_airlink_data_unpack(uint8_t *buff
             }
         }
     }
+
     return NULL;
 }
 
@@ -75,8 +76,9 @@ __USER_FUNC_IN_RAM__ void luat_airlink_data_pack(uint8_t *buff, size_t len, uint
     data->len = len;
     data->pkgid = next_pkg_id++;
     memset(&data->flags, 0, sizeof(data->flags));
-    memcpy(data->data, buff, len);
 
+
+    memcpy(data->data, buff, len);
     if (g_airlink_link_data_cb) {
         g_airlink_link_data_cb(data);
     }

+ 71 - 22
components/airlink/src/task/luat_airlink_uart_task.c

@@ -30,31 +30,31 @@
 extern airlink_statistic_t g_airlink_statistic;
 extern uint32_t g_airlink_pause;
 
-// static uint8_t start;
-// static uint8_t slave_rdy;
-static uint8_t thread_rdy;
 static luat_rtos_task_handle g_uart_task;
-static uint8_t basic_info[256];
 static luat_rtos_queue_t evt_queue;
 extern luat_airlink_irq_ctx_t g_airlink_irq_ctx;
 
-
 __USER_FUNC_IN_RAM__ static void on_newdata_notify(void)
 {
     luat_event_t evt = {.id = 3};
     luat_rtos_queue_send(evt_queue, &evt, sizeof(evt), 0);
 }
 
-static void uart_cb(uint8_t *data, size_t len) {
-    // nop
+static void uart_cb(int uart_id, uint32_t data_len) {
+    luat_event_t evt = {.id = 2};
+    luat_rtos_queue_send(evt_queue, &evt, sizeof(evt), 0);
 }
 
 static void uart_gpio_setup(void)
 {
+    int ret = 0;
     if (g_airlink_spi_conf.uart_id == 0) {
         g_airlink_spi_conf.uart_id = 1;
     }
-    luat_uart_ctrl(g_airlink_spi_conf.uart_id, LUAT_UART_SET_RECV_CALLBACK, uart_cb);
+    ret = luat_uart_ctrl(g_airlink_spi_conf.uart_id, LUAT_UART_SET_RECV_CALLBACK, uart_cb);
+    if (ret) {
+        LLOGW("luat_uart_ctrl ret:%d", ret);
+    }
 }
 
 __USER_FUNC_IN_RAM__ static void record_statistic(luat_event_t event)
@@ -78,9 +78,6 @@ __USER_FUNC_IN_RAM__ static void record_statistic(luat_event_t event)
 static uint8_t *s_txbuff;
 static uint8_t *s_rxbuff;
 static airlink_link_data_t s_link;
-static uint64_t warn_slave_no_ready = 0;
-static uint64_t tnow = 0;
-static uint8_t slave_is_irq_ready = 0;
 
 __USER_FUNC_IN_RAM__ static void on_link_data_notify(airlink_link_data_t* link) {
     memset(&link->flags, 0, sizeof(uint32_t));
@@ -91,7 +88,30 @@ __USER_FUNC_IN_RAM__ static void on_link_data_notify(airlink_link_data_t* link)
 }
 
 static void on_uart_data_in(uint8_t* buff, size_t len) {
-
+    // TODO 要处理分包, 连包的情况
+    // TODO 不能假设开头和结尾就一定是0x7E, 要查找, 要缓存
+    // 收到数据后去除帧头帧尾和魔数,遇到0x7E/0x7D 要转义
+    uint8_t* receive_data = buff;
+    size_t receive_len = len-2;
+    memcpy(receive_data, buff+1, receive_len);//去帧头帧尾
+    for(int i = 0; i < receive_len; i++)
+    {
+        if(receive_data[i] == 0x7D && receive_data[i + 1] == 0x02) {
+            receive_data[i] = 0x7E;
+            receive_len--;
+        }
+        else if(receive_data[i] == 0x7D && receive_data[i + 1] == 0x01) {
+            receive_data[i] = 0x7D;
+            receive_len--;
+        }
+    }
+    airlink_link_data_t *link = luat_airlink_data_unpack(receive_data, receive_len);
+    if (link == NULL) {
+        LLOGE("luat_airlink_data_unpack failed len %d", receive_len);
+        return;
+    }
+    LLOGD("luat_airlink data unpacked, len: %d, data: %p", link->len, link->data);
+    luat_airlink_on_data_recv(link->data, link->len);
 }
 
 __USER_FUNC_IN_RAM__ static void uart_task(void *param)
@@ -104,33 +124,40 @@ __USER_FUNC_IN_RAM__ static void uart_task(void *param)
     int uart_id;
     luat_rtos_task_sleep(5); // 等5ms
     uart_gpio_setup();
-    thread_rdy = 1;
     g_airlink_newdata_notify_cb = on_newdata_notify;
     g_airlink_link_data_cb = on_link_data_notify;
-    uint8_t pbuff[2048] = {0};
+    // 单个link data的长度最大是1600字节,极端情况下所有数据都要转义,那就是3200字节,所以这里预留4K
+    uint8_t *pbuff = luat_heap_malloc(4*1024);
     while (1)
     {
         uart_id = g_airlink_spi_conf.uart_id;
+        // LLOGD("uart_task:uart_id:%d", uart_id);
         while (1) {
             ret = luat_uart_read(uart_id, (char *)s_rxbuff, TEST_BUFF_SIZE);
+            // LLOGD("uart_task:uart read buff len:%d", ret);
             if (ret <= 0) {
                 break;
             }
             else {
-                LLOGD("收到uart数据长度 %d", ret);
-                // TODO 推送数据, 并解析处理
+                // LLOGD("收到uart数据长度 %d", ret);
+                // 推送数据, 并解析处理
                 on_uart_data_in(s_rxbuff, ret);
             }
         }
-        ret = luat_rtos_queue_recv(evt_queue, &event, sizeof(luat_event_t), 60*1000);
-        if (ret == 0) {
+        event.id = 0;
+        ret = luat_rtos_queue_recv(evt_queue, &event, sizeof(luat_event_t), 15*1000);//在evt_queue队列中复制数据到指定缓冲区event,阻塞等待60s
+        //LLOGD("收到airlink数据事件 ret:%d, id:%d", ret, event.id);
+        record_statistic(event);
+        while (1) {
             // 有数据, 要处理了
             item.len = 0;
-            luat_airlink_cmd_recv_simple(&item);
+            luat_airlink_cmd_recv_simple(&item);//从(发送)队列里取出数据存在item中
+            //LLOGD("队列数据长度:%d, cmd:%p", item.len, item.cmd);
             if (item.len > 0 && item.cmd != NULL)
             {
                 // 0x7E 开始, 0x7D 结束, 遇到 0x7E/0x7D 要转义
                 luat_airlink_data_pack((uint8_t*)item.cmd, item.len, pbuff);
+                // int temp_len = sizeof(pbuff)/sizeof(pbuff[0]);
                 s_txbuff[0] = 0x7E;
                 offset = 1;
                 ptr = (uint8_t*)pbuff;
@@ -139,33 +166,55 @@ __USER_FUNC_IN_RAM__ static void uart_task(void *param)
                     if (ptr[i] == 0x7E) {
                         s_txbuff[offset++] = 0x7D;
                         s_txbuff[offset++] = 0x02;
+                        if(i < item.len + sizeof(airlink_link_data_t) - 1)  i++;
+                        else 
+                        {
+                            break;
+                        }
                     }
                     else if (ptr[i] == 0x7D) {
                         s_txbuff[offset++] = 0x7D;
                         s_txbuff[offset++] = 0x01;
+                        if(i < item.len + sizeof(airlink_link_data_t) - 1)  i++;
+                        else 
+                        {
+                            break;
+                        }
                     }
                     {
                         s_txbuff[offset++] = ptr[i];
                     }
                 }
                 s_txbuff[offset++] = 0x7E;
+                //LLOGD("发送数据长度:%d, cmd:%p", offset, item.cmd);
                 luat_uart_write(uart_id, (const char *)s_txbuff, offset);
             }
+            else {
+                break; // 没有数据了, 退出循环
+            }
         }
     }
 }
 
 void luat_airlink_start_uart(void)
 {
+    int ret = 0;
     if (g_uart_task != NULL)
     {
-        LLOGE("SPI主机任务已经启动过了!!!");
+        // TODO 支持多个UART?
+        LLOGE("UART任务已经启动过了!!! uart %d", g_airlink_spi_conf.uart_id);
         return;
     }
 
     s_txbuff = luat_heap_opt_malloc(AIRLINK_MEM_TYPE, TEST_BUFF_SIZE);
     s_rxbuff = luat_heap_opt_malloc(AIRLINK_MEM_TYPE, TEST_BUFF_SIZE);
 
-    luat_rtos_queue_create(&evt_queue, 4 * 1024, sizeof(luat_event_t));
-    luat_rtos_task_create(&g_uart_task, 8 * 1024, 50, "uart", uart_task, NULL, 0);
+    ret = luat_rtos_queue_create(&evt_queue, 4 * 1024, sizeof(luat_event_t));
+    if (ret) {
+        LLOGW("创建evt_queue ret:%d", ret);
+    }
+    ret = luat_rtos_task_create(&g_uart_task, 8 * 1024, 50, "uart", uart_task, NULL, 0);
+    if (ret) {
+        LLOGW("创建uart_task ret:%d", ret);
+    }
 }

+ 4 - 0
components/drv/src/luat_drv_bluetooth.c

@@ -12,6 +12,10 @@
 #define LLOGD(...) 
 
 int luat_drv_bluetooth_init(luat_bluetooth_t* luat_bluetooth) {
+    if (luat_airlink_sversion() < 10) {
+        LLOGE("wifi fw version too low, need >= 10");
+        return -1;
+    }
     return luat_airlink_drv_bluetooth_init(luat_bluetooth);
 }
 

+ 1 - 2
components/lcd/luat_lib_lcd_jpg.c

@@ -25,7 +25,6 @@
 
 extern luat_color_t BACK_COLOR , FORE_COLOR ;
 
-extern const luat_lcd_opts_t lcd_opts_custom;
 extern luat_lcd_conf_t *lcd_dft_conf;
 extern void lcd_auto_flush(luat_lcd_conf_t *conf);
 
@@ -77,7 +76,7 @@ static int lcd_out_func (JDEC* jd, void* bitmap, JRECT* rect){
     return 1;    /* Continue to decompress */
 }
 
-int lcd_draw_jpeg(luat_lcd_conf_t* conf, const char* path, int16_t x, int16_t y){
+LUAT_WEAK int lcd_draw_jpeg(luat_lcd_conf_t* conf, const char* path, int16_t x, int16_t y){
     JRESULT res;      /* Result code of TJpgDec API */
     JDEC jdec;        /* Decompression object */
     void *work;       /* Pointer to the decompressor work area */

+ 9 - 0
components/lvgl/binding/luat_lib_lvgl_font.c

@@ -109,6 +109,15 @@ int luat_lv_font_load(lua_State *L) {
         #ifdef LUAT_USE_GTFONT
             luat_spi_device_t *spi = lua_touserdata(L, 1);
             uint8_t size = luaL_optinteger(L, 2, 16);
+            if (size&1){
+                LLOGE("size not support odd");
+                size++;
+            }
+            if (size<16||size>192){
+                LLOGE("size not support");
+                return 0;
+            }
+            
             uint8_t bpp = luaL_optinteger(L, 3, 4);
 
             if (size>=16 && size<34) bpp = 4;

+ 35 - 142
components/lvgl/font/lv_font_gtfont.c

@@ -4,87 +4,22 @@
 
 #include "luat_gtfont.h"
 
-typedef struct
-{
-    int life;
-    uint16_t code;
-    uint16_t dot;
-    char data[1];
-} gt_font_char_t;
-
-typedef struct
-{
-    uint16_t i;
-    gt_font_char_t **chars;
-} gt_font_cache_t;
+#define LUAT_LOG_TAG "lvgl_gtfont"
+#include "luat_log.h"
 
-typedef struct
-{
+typedef struct{
     uint8_t sty_zh;
     uint8_t sty_en;
     uint16_t size;
     uint16_t bpp;
     uint16_t thickness;
-    gt_font_cache_t *cache;
-    uint16_t adv_w[94];
     uint16_t code;
     uint32_t dot;
-    unsigned char buf[1];
+    unsigned char buf[0];
 } gt_font_param_t;
 
-gt_font_char_t **gt_font_cache_open(gt_font_param_t *param, uint16_t code) {
-    if (param->cache == NULL)
-        return NULL;
-
-    gt_font_char_t *cached_char = NULL;
-    gt_font_cache_t *cache = param->cache;
-    gt_font_char_t **chars = cache->chars;
-
-    int i = 0;
-    for (i = 0; i < cache->i && chars[i] != NULL; ++i)
-    {
-        if(chars[i]->life > (INT32_MIN + 1)) {
-            chars[i]->life -= 1;
-        }
-    }
-
-    for(i = 0; i < cache->i && chars[i] != NULL; i++) {
-        if(chars[i]->code == code) {
-            cached_char = chars[i];
-            cached_char->life += 1;
-            if(cached_char->life > 1000) cached_char->life = 1000;
-            break;
-        }
-    }
-
-    if (cached_char || i < cache->i) return &chars[i];
-
-    i = 0;
-    for(int j = 1; j < cache->i; j++) {
-        if(cache->chars[j]->life < chars[i]->life) {
-            i = j;
-        }
-    }
-
-    chars[i]->life = 0;
-    chars[i]->code = 0;
-
-    return &chars[i];
-}
-
 static void gt_font_get(gt_font_param_t *param, uint16_t code) {
-    if (param->code == code)
-        return;
-
-    gt_font_char_t *vc = NULL;
-    gt_font_char_t **cached_char = gt_font_cache_open(param, code);
-    if (cached_char != NULL && (vc = *cached_char) != NULL && vc->code == code) {
-        param->code = code;
-        param->dot = vc->dot;
-        int size = ((param->dot + 7) / 8 * 8) * param->size * param->bpp / 8;
-        memcpy(param->buf, vc->data, size);
-        return;
-    }
+    if (param->code == code) return;
 
     uint8_t sty = param->sty_zh;
     if (code >= 0x20 && code <= 0x7e)
@@ -98,20 +33,10 @@ static void gt_font_get(gt_font_param_t *param, uint16_t code) {
     param->dot = dot / param->bpp;
 
     Gray_Process(param->buf, param->dot, param->size, param->bpp);
-
-    if (cached_char != NULL) {
-        int size = ((param->dot + 7) / 8 * 8) * param->size * param->bpp / 8;
-        vc = lv_mem_realloc(vc, sizeof(gt_font_char_t) + size);
-        vc->dot = param->dot;
-        vc->code = code;
-        vc->life = 0;
-        memcpy(vc->data, param->buf, size);
-
-        *cached_char = vc;
-    }
+    // LLOGD("dot:%d param->dot:%d aram->size:%d param->bpp:%d",dot,param->dot,param->size, param->bpp);
 }
 
-int get_font_adv_w(uint8_t *buf, int width, int height, int bpp) {
+static int get_font_adv_w(uint8_t *buf, int width, int height, int bpp) {
     uint8_t *p = buf;
     uint16_t w = width, h = height;
     uint32_t i = 0, j = 0, x = 0, y = 0;
@@ -136,24 +61,17 @@ int get_font_adv_w(uint8_t *buf, int width, int height, int bpp) {
             }
         }
     }
-
     return adv_w + 1;
 }
 
 static inline uint16_t gt_font_get_adv_w(gt_font_param_t *param, uint16_t code) {
     uint16_t adv_w = param->size;
-
+    gt_font_get(param, code);
     if (code >= 0x21 && code <= 0x7e) {
-        int i = code - 0x21;
-        // if (param->adv_w[i] == 0xFFFF) {
-            gt_font_get(param, code);
-            param->adv_w[i] = get_font_adv_w(param->buf, param->dot, param->size, param->bpp);
-        // }
-        adv_w = param->adv_w[i];
+        adv_w = get_font_adv_w(param->buf, param->dot, param->size, param->bpp);
     } else if (code == 0x20) {
         adv_w = param->size / 2;
     }
-
     return adv_w;
 }
 
@@ -162,19 +80,19 @@ static bool gt_font_get_glyph_dsc(const struct _lv_font_struct *font, lv_font_gl
     uint16_t code = gt_unicode2gb18030(letter);
 
     dsc_out->adv_w = gt_font_get_adv_w(param, code);
-    dsc_out->box_w = ((param->code == code ? param->dot : param->size) + 7) / 8 * 8;
+    dsc_out->box_w = (param->dot + 7) / 8 * 8;
+    // LLOGD("adv_w:%d box_w:%d",dsc_out->adv_w,dsc_out->box_w);
     dsc_out->box_h = param->size;
     dsc_out->ofs_x = 0;
     dsc_out->ofs_y = 0;
-    dsc_out->bpp   = param->bpp;
+    dsc_out->bpp  = param->bpp;
 
     return true;
 }
 
 static uint8_t *gt_font_get_glyph_bitmap(const struct _lv_font_struct *font, uint32_t letter) {
     gt_font_param_t *param = font->dsc;
-    uint16_t code = gt_unicode2gb18030(letter);
-    gt_font_get(param, code);
+    gt_font_get(param, gt_unicode2gb18030(letter));
     return param->buf;
 }
 
@@ -185,47 +103,30 @@ bool lv_font_is_gt(lv_font_t *font) {
 }
 
 lv_font_t *lv_font_new_gt(uint8_t sty_zh, uint8_t sty_en, uint8_t size, uint8_t bpp, uint16_t thickness, uint8_t cache_size) {
-    lv_font_t *font = NULL;
-    do {
-        font = lv_mem_alloc(sizeof(lv_font_t));
-        if (!font) break;
-
-        memset(font, 0, sizeof(lv_font_t));
-        font->get_glyph_dsc = gt_font_get_glyph_dsc;
-        font->get_glyph_bitmap = gt_font_get_glyph_bitmap;
-        font->line_height = size;
-
-        int malloc_size = size * bpp * size * bpp;
-        gt_font_param_t *param = lv_mem_alloc(sizeof(gt_font_param_t) + malloc_size);
-        if (!param) break;
-
-        memset(param, 0, sizeof(*param));
-        font->dsc = param;
-        memset(param->adv_w, 0xFF, sizeof(param->adv_w));
-        param->sty_zh = sty_zh;
-        param->sty_en = sty_en;
-        param->size = size;
-        param->bpp = bpp;
-        param->thickness = thickness;
-        if (cache_size != 0) {
-            gt_font_cache_t *cache = lv_mem_alloc(sizeof(gt_font_cache_t));
-            if (!cache) break;
-
-            memset(cache, 0, sizeof(*cache));
-            param->cache = cache;
-            cache->i = cache_size;
-            cache->chars = lv_mem_alloc(cache_size * sizeof(gt_font_char_t *));
-            if (!cache->chars) break;
-
-            memset(cache->chars, 0, cache_size * sizeof(gt_font_char_t *));
-        }
-
-        return font;
+    lv_font_t *font = lv_mem_alloc(sizeof(lv_font_t));
+    if (!font) return NULL;
+
+    memset(font, 0, sizeof(lv_font_t));
+    font->get_glyph_dsc = gt_font_get_glyph_dsc;
+    font->get_glyph_bitmap = gt_font_get_glyph_bitmap;
+    font->line_height = size;
+
+    int malloc_size = size * bpp * size * bpp;
+    gt_font_param_t *param = lv_mem_alloc(sizeof(gt_font_param_t) + malloc_size);
+    if (!param) {
+        lv_font_del_gt(font);
+        return NULL;
+    }
 
-    } while (0);
+    memset(param, 0, sizeof(*param));
+    font->dsc = param;
+    param->sty_zh = sty_zh;
+    param->sty_en = sty_en;
+    param->size = size;
+    param->bpp = bpp;
+    param->thickness = thickness;
 
-    lv_font_del_gt(font);
-    return NULL;
+    return font;
 }
 
 void lv_font_del_gt(lv_font_t *font) {
@@ -235,14 +136,6 @@ void lv_font_del_gt(lv_font_t *font) {
         return;
     }
     gt_font_param_t *param = font->dsc;
-    if (param->cache) {
-        gt_font_char_t **chars = param->cache->chars;
-        for (int i = 0; i < param->cache->i; ++i) {
-            if (chars[i]) lv_mem_free(chars[i]);
-        }
-        if (param->cache->chars) lv_mem_free(param->cache->chars);
-        lv_mem_free(param->cache);
-    }
     lv_mem_free(param);
     lv_mem_free(font);
 }

+ 4 - 6
components/lvgl/src/lv_widgets/lv_img.c

@@ -261,8 +261,6 @@ void lv_img_set_offset_x(lv_obj_t * img, lv_coord_t x)
 
     lv_img_ext_t * ext = lv_obj_get_ext_attr(img);
 
-    x = x % ext->w;
-
     ext->offset.x = x;
     lv_obj_invalidate(img);
 }
@@ -279,8 +277,6 @@ void lv_img_set_offset_y(lv_obj_t * img, lv_coord_t y)
 
     lv_img_ext_t * ext = lv_obj_get_ext_attr(img);
 
-    y = y % ext->h;
-
     ext->offset.y = y;
     lv_obj_invalidate(img);
 }
@@ -683,8 +679,10 @@ static lv_design_res_t lv_img_design(lv_obj_t * img, const lv_area_t * clip_area
             lv_area_t zoomed_coords;
             lv_obj_get_coords(img, &zoomed_coords);
 
-            zoomed_coords.x1 += (int32_t)((int32_t)ext->offset.x * zoom_final) >> 8;
-            zoomed_coords.y1 += (int32_t)((int32_t)ext->offset.y * zoom_final) >> 8;
+            int32_t offset_x = (int32_t)ext->offset.x % ext->w;
+            int32_t offset_y = (int32_t)ext->offset.y % ext->h;
+            zoomed_coords.x1 += (int32_t)(offset_x * zoom_final) >> 8;
+            zoomed_coords.y1 += (int32_t)(offset_y * zoom_final) >> 8;
             zoomed_coords.x2 = zoomed_coords.x1 + ((int32_t)((int32_t)(obj_w - 1) * zoom_final) >> 8);
             zoomed_coords.y2 = zoomed_coords.y1 + ((int32_t)((int32_t)(obj_h - 1) * zoom_final) >> 8);
 

+ 1 - 1
components/lvgl8/porting/lv_port_indev.h

@@ -22,7 +22,7 @@ extern "C" {
 #else
 #include "../lvgl.h"
 #endif
-
+#include "luat_tp.h"
 /*********************
  *      DEFINES
  *********************/

+ 1 - 0
components/lvgl8/src/draw/sw/lv_draw_sw_letter.c

@@ -186,6 +186,7 @@ static void LV_ATTRIBUTE_FAST_MEM draw_letter_normal(lv_draw_ctx_t * draw_ctx, c
         img_dsc.zoom = LV_IMG_ZOOM_NONE;
         img_dsc.opa = dsc->opa;
         img_dsc.blend_mode = dsc->blend_mode;
+        lv_img_cache_invalidate_src(map_p);
         lv_draw_img(draw_ctx, &img_dsc, &fill_area, map_p);
         return;
     }

+ 1 - 1
components/lvgl8/src/draw/swm341_dma2d/lv_gpu_swm341_dma2d.c

@@ -204,7 +204,7 @@ static void lv_draw_swm341_dma2d_blend_map(lv_color_t * dest_buf, const lv_area_
         DMA2D->L[DMA2D_LAYER_FG].OR = src_stride - dest_w;
         DMA2D->L[DMA2D_LAYER_FG].PFCCR = (LV_DMA2D_COLOR_FORMAT << DMA2D_PFCCR_CFMT_Pos)
                                          /*alpha mode 2, replace with foreground * alpha value*/
-                                         | (2 << DAM2D_PFCCR_AMODE_Pos)
+                                         | (2 << DMA2D_PFCCR_AMODE_Pos)
                                          /*alpha value*/
                                          | (opa << DMA2D_PFCCR_ALPHA_Pos);
 

+ 7 - 2
components/lvgl8/src/extra/libs/png/lv_png.c

@@ -16,6 +16,11 @@
 /*********************
  *      DEFINES
  *********************/
+#ifdef LODEPNG_COMPILE_ALLOCATORS
+    #define lv_png_free(ptr) lv_mem_free((ptr))
+#else
+    #define lv_png_free(ptr) lodepng_free((ptr))
+#endif
 
 /**********************
  *      TYPEDEFS
@@ -172,10 +177,10 @@ static lv_res_t decoder_open(lv_img_decoder_t * decoder, lv_img_decoder_dsc_t *
 
             /*Decode the loaded image in ARGB8888 */
             error = lodepng_decode32(&img_data, &png_width, &png_height, png_data, png_data_size);
-            lv_mem_free(png_data); /*Free the loaded file*/
+            lv_png_free(png_data); /*Free the loaded file*/
             if(error) {
                 if(img_data != NULL) {
-                    lv_mem_free(img_data);
+                    lv_png_free(img_data);
                 }
                 LV_LOG_WARN("error %" LV_PRIu32 ": %s\n", error, lodepng_error_text(error));
                 return LV_RES_INV;

+ 17 - 4
components/lvgl8/src/extra/libs/sjpg/lv_sjpg.c

@@ -872,6 +872,7 @@ static void decoder_close(lv_img_decoder_t * decoder, lv_img_decoder_dsc_t * dsc
                 lv_fs_close(&(sjpeg->io.lv_file));
             }
             lv_sjpg_cleanup(sjpeg);
+            dsc->user_data = NULL;
             break;
 
         case LV_IMG_SRC_VARIABLE:
@@ -892,11 +893,23 @@ static int is_jpg(const uint8_t * raw_data, size_t len)
 
 static void lv_sjpg_free(SJPEG * sjpeg)
 {
-    if(sjpeg->frame_cache) lv_mem_free(sjpeg->frame_cache);
+    if(sjpeg->frame_cache) {
+        lv_mem_free(sjpeg->frame_cache);
+        sjpeg->frame_cache = NULL;
+    }
     if(sjpeg->frame_base_array) lv_mem_free(sjpeg->frame_base_array);
-    if(sjpeg->frame_base_offset) lv_mem_free(sjpeg->frame_base_offset);
-    if(sjpeg->tjpeg_jd) lv_mem_free(sjpeg->tjpeg_jd);
-    if(sjpeg->workb) lv_mem_free(sjpeg->workb);
+    if(sjpeg->frame_base_offset) {
+        lv_mem_free(sjpeg->frame_base_offset);
+        sjpeg->frame_base_offset = NULL;
+    }
+    if(sjpeg->tjpeg_jd) {
+        lv_mem_free(sjpeg->tjpeg_jd);
+        sjpeg->tjpeg_jd = NULL;
+    }
+    if(sjpeg->workb) {
+        lv_mem_free(sjpeg->workb);
+        sjpeg->workb = NULL;
+    }
 }
 
 static void lv_sjpg_cleanup(SJPEG * sjpeg)

+ 1 - 1
components/lvgl8/src/extra/widgets/span/lv_span.c

@@ -609,7 +609,7 @@ static bool lv_txt_get_snippet(const char * txt, const lv_font_t * font,
     uint32_t ofs = _lv_txt_get_next_line(txt, font, letter_space, max_width, use_width, flag);
     *end_ofs = ofs;
 
-    if(txt[ofs] == '\0' && *use_width < max_width) {
+    if(txt[ofs] == '\0' && *use_width < max_width && !(ofs && (txt[ofs - 1] == '\n' || txt[ofs - 1] == '\r'))) {
         return false;
     }
     else {

+ 35 - 25
components/network/adapter_lwip2/net_lwip2.c

@@ -97,16 +97,20 @@ void net_lwip2_set_netif(uint8_t adapter_index, struct netif *netif) {
 	if (adapter_index >= NW_ADAPTER_INDEX_LWIP_NETIF_QTY) {
 		return; // 超范围了
 	}
-	if (prvlwip_inited == 0) {
+	if (0 == prvlwip_inited) {
 		prvlwip_inited = 1;
 		net_lwip2_init(adapter_index);
-		dns_init_client(&prvlwip.dns_client);
 		#ifdef LUAT_USE_NETDRV_LWIP_ARP
 		prvlwip.arp_timer = platform_create_timer(net_lwip_arp_timer_cb, (void *)NULL, NULL);
 		platform_start_timer(prvlwip.arp_timer, 1000, 1);
 		#endif
 	}
-	if (prvlwip.dns_udp[adapter_index] == NULL) {
+	if (NULL == prvlwip.dns_client[adapter_index]) {
+		prvlwip.dns_client[adapter_index] = luat_heap_malloc(sizeof(dns_client_t));
+		// memset(prvlwip.dns_client[adapter_index], 0, sizeof(dns_client_t));
+		dns_init_client(prvlwip.dns_client[adapter_index]);
+	}
+	if (NULL == prvlwip.dns_udp[adapter_index]) {
 		prvlwip.dns_udp[adapter_index] = udp_new();
 		prvlwip.dns_udp[adapter_index]->recv = net_lwip2_dns_recv_cb;
 		prvlwip.dns_udp[adapter_index]->recv_arg = adapter_index;
@@ -505,22 +509,22 @@ static err_t net_lwip2_dns_recv_cb(void *arg, struct udp_pcb *pcb, struct pbuf *
 		OS_InitBuffer(&msg_buf, p->tot_len);
 		pbuf_copy_partial(p, msg_buf.Data, p->tot_len, 0);
 		pbuf_free(p);
-		dns_run(&prvlwip.dns_client, &msg_buf, NULL, &i);
+		dns_run(prvlwip.dns_client[adapter_index], &msg_buf, NULL, &i);
 		OS_DeInitBuffer(&msg_buf);
-		llist_traversal(&prvlwip.dns_client.require_head, net_lwip2_dns_check_result, NULL);
+		llist_traversal(&prvlwip.dns_client[adapter_index]->require_head, net_lwip2_dns_check_result, NULL);
 		{
-			dns_run(&prvlwip.dns_client, NULL, &tx_msg_buf, &i);
+			dns_run(prvlwip.dns_client[adapter_index], NULL, &tx_msg_buf, &i);
 			if (tx_msg_buf.Pos && NULL != tx_msg_buf.Data)
 			{
 				out_p = pbuf_alloc(PBUF_TRANSPORT, tx_msg_buf.Pos, PBUF_RAM);
 				if (out_p && NULL != tx_msg_buf.Data)
 				{
 					pbuf_take(p, tx_msg_buf.Data, tx_msg_buf.Pos);
-					prvlwip.dns_udp[adapter_index]->local_ip = prvlwip.lwip_netif[adapter_index]->ip_addr;
-					ipaddr_ntoa_r(&prvlwip.dns_client.dns_server[i], ip_string, sizeof(ip_string));
+					memcpy(&prvlwip.dns_udp[adapter_index]->local_ip, &prvlwip.lwip_netif[adapter_index]->ip_addr, sizeof(ip_addr_t));
+					ipaddr_ntoa_r(&prvlwip.dns_client[adapter_index]->dns_server[i], ip_string, sizeof(ip_string));
 					ipaddr_ntoa_r(&prvlwip.dns_udp[adapter_index]->local_ip, ipstr2, sizeof(ipstr2));
 					LLOGD("dns udp sendto %s:%d from %s", ip_string, DNS_SERVER_PORT, ipstr2);
-					ret = udp_sendto_if(prvlwip.dns_udp[adapter_index], out_p, &prvlwip.dns_client.dns_server[i], DNS_SERVER_PORT, prvlwip.lwip_netif[adapter_index]);
+					ret = udp_sendto_if(prvlwip.dns_udp[adapter_index], out_p, &prvlwip.dns_client[adapter_index]->dns_server[i], DNS_SERVER_PORT, prvlwip.lwip_netif[adapter_index]);
 					if (ret) {
 						LLOGE("dns udp sendto %s:%d ret %d", ip_string, DNS_SERVER_PORT, ret);
 					}
@@ -529,11 +533,11 @@ static err_t net_lwip2_dns_recv_cb(void *arg, struct udp_pcb *pcb, struct pbuf *
 					pbuf_free(out_p);
 				}
 				OS_DeInitBuffer(&tx_msg_buf);
-				llist_traversal(&prvlwip.dns_client.require_head, net_lwip2_dns_check_result, NULL);
+				llist_traversal(&prvlwip.dns_client[adapter_index]->require_head, net_lwip2_dns_check_result, NULL);
 			}
 		}
 	}
-	if (!prvlwip.dns_client.is_run && prvlwip.dns_timer[adapter_index])
+	if (!prvlwip.dns_client[adapter_index]->is_run && prvlwip.dns_timer[adapter_index])
 	{
 		platform_stop_timer(prvlwip.dns_timer[adapter_index]);
 	}
@@ -547,9 +551,11 @@ static void net_lwip2_dns_tx_next(uint8_t adapter_index, Buffer_Struct *tx_msg_b
 	struct pbuf *p = NULL;
 	char ipstr[64] = {0};
 	char ipstr2[64] = {0};
-	dns_run(&prvlwip.dns_client, NULL, tx_msg_buf, &i);
+	dns_run(prvlwip.dns_client[adapter_index], NULL, tx_msg_buf, &i);
 	char ip_string[64] = {0};
-	ipaddr_ntoa_r(&prvlwip.dns_client.dns_server[i], ip_string, sizeof(ip_string));
+	// LLOGI("net_lwip2_dns_tx_next %d %p", adapter_index, prvlwip.dns_client[adapter_index]);
+	ipaddr_ntoa_r(&prvlwip.dns_client[adapter_index]->dns_server[i], ip_string, sizeof(ip_string));
+	LLOGD("adatper %d dns server %s", adapter_index, ip_string);
 	if (tx_msg_buf->Pos && NULL != tx_msg_buf->Data) {
 		p = pbuf_alloc(PBUF_TRANSPORT, tx_msg_buf->Pos, PBUF_RAM);
 		if (p == NULL) {
@@ -557,11 +563,11 @@ static void net_lwip2_dns_tx_next(uint8_t adapter_index, Buffer_Struct *tx_msg_b
 		}
 		else {
 			pbuf_take(p, tx_msg_buf->Data, tx_msg_buf->Pos);
-			prvlwip.dns_udp[adapter_index]->local_ip = prvlwip.lwip_netif[adapter_index]->ip_addr;
+			memcpy(&prvlwip.dns_udp[adapter_index]->local_ip, &prvlwip.lwip_netif[adapter_index]->ip_addr, sizeof(ip_addr_t));
 			ipaddr_ntoa_r(&prvlwip.dns_udp[adapter_index]->local_ip, ipstr2, sizeof(ipstr2));
-			ipaddr_ntoa_r(&prvlwip.dns_client.dns_server[i], ipstr, sizeof(ipstr));
+			ipaddr_ntoa_r(&prvlwip.dns_client[adapter_index]->dns_server[i], ipstr, sizeof(ipstr));
 			LLOGD("dns udp sendto %s:%d from %s", ipstr, DNS_SERVER_PORT, ipstr2);
-			err = udp_sendto_if(prvlwip.dns_udp[adapter_index], p, &prvlwip.dns_client.dns_server[i], DNS_SERVER_PORT, prvlwip.lwip_netif[adapter_index]);
+			err = udp_sendto_if(prvlwip.dns_udp[adapter_index], p, &prvlwip.dns_client[adapter_index]->dns_server[i], DNS_SERVER_PORT, prvlwip.lwip_netif[adapter_index]);
 			pbuf_free(p);
 			if (err) {
 				LLOGE("dns udp sendto %s:%d from %s ret %d", ipstr, DNS_SERVER_PORT, ipstr2,  err);
@@ -569,10 +575,10 @@ static void net_lwip2_dns_tx_next(uint8_t adapter_index, Buffer_Struct *tx_msg_b
 		}
 	}
 	OS_DeInitBuffer(tx_msg_buf);
-	if (prvlwip.dns_client.new_result)
+	if (prvlwip.dns_client[adapter_index]->new_result)
 	{
-		llist_traversal(&prvlwip.dns_client.require_head, net_lwip2_dns_check_result, NULL);
-		prvlwip.dns_client.new_result = 0;
+		llist_traversal(&prvlwip.dns_client[adapter_index]->require_head, net_lwip2_dns_check_result, NULL);
+		prvlwip.dns_client[adapter_index]->new_result = 0;
 	}
 
 }
@@ -694,7 +700,10 @@ static void net_lwip2_task(void *param)
 					{
 						pbuf_take(out_p, p->data, p->len);
 						error = udp_sendto_if(prvlwip.socket[socket_id].pcb.udp, out_p, &p->ip, p->port, prvlwip.lwip_netif[adapter_index]);
-						// LLOGD("udp_sendto ret %d", error);
+						if (error) {
+							ipaddr_ntoa_r(&p->ip, ip_string, sizeof(ip_string));
+							LLOGI("udp_sendto_if err %d %s:%d", error, ip_string, p->port);
+						}
 						pbuf_free(out_p);
 					}
 					else
@@ -722,7 +731,7 @@ static void net_lwip2_task(void *param)
 	case EV_LWIP_DNS_TIMER:
 #ifdef LUAT_USE_DNS
 		net_lwip2_dns_tx_next(adapter_index, &tx_msg_buf);
-		if (!prvlwip.dns_client.is_run && prvlwip.dns_timer[adapter_index])
+		if (!prvlwip.dns_client[adapter_index]->is_run && prvlwip.dns_timer[adapter_index])
 		{
 			platform_stop_timer(prvlwip.dns_timer[adapter_index]);
 		}
@@ -820,11 +829,11 @@ static void net_lwip2_task(void *param)
 	case EV_LWIP_SOCKET_DNS:
 	case EV_LWIP_SOCKET_DNS_IPV6:
 		// LLOGD("event dns query");
-		if (!prvlwip.dns_client.is_run && prvlwip.dns_timer[adapter_index])
+		if (!prvlwip.dns_client[adapter_index]->is_run && prvlwip.dns_timer[adapter_index])
 		{
 			platform_start_timer(prvlwip.dns_timer[adapter_index], 1000, 1);
 		}
-		dns_require_ipv6(&prvlwip.dns_client, event.Param1, event.Param2, event.Param3, (event.ID - EV_LWIP_SOCKET_DNS));
+		dns_require_ipv6(prvlwip.dns_client[adapter_index], event.Param1, event.Param2, event.Param3, (event.ID - EV_LWIP_SOCKET_DNS));
 		// LLOGD("event dns query 2");
 		net_lwip2_dns_tx_next(adapter_index, &tx_msg_buf);
 		// LLOGD("event dns query 3");
@@ -1469,8 +1478,9 @@ static int net_lwip2_set_dns_server(uint8_t server_index, luat_ip_addr_t *ip, vo
 	uint8_t adapter_index = (uint32_t)user_data;
 	if (adapter_index >= NW_ADAPTER_INDEX_LWIP_NETIF_QTY) return -1;
 	if (server_index >= MAX_DNS_SERVER) return -1;
-	prvlwip.dns_client.dns_server[server_index] = *ip;
-	prvlwip.dns_client.is_static_dns[server_index] = 1;
+	if (prvlwip.dns_client[adapter_index] == NULL) return -1;
+	prvlwip.dns_client[adapter_index]->dns_server[server_index] = *ip;
+	prvlwip.dns_client[adapter_index]->is_static_dns[server_index] = 1;
 	return 0;
 }
 

+ 1 - 1
components/network/adapter_lwip2/net_lwip2.h

@@ -31,7 +31,7 @@ typedef struct
 typedef struct
 {
 	uint64_t socket_tag;
-	dns_client_t dns_client;
+	dns_client_t *dns_client[NW_ADAPTER_INDEX_LWIP_NETIF_QTY];
 	socket_ctrl_t socket[MAX_SOCK_NUM];
 	ip_addr_t ec618_ipv6;
 	struct netif *lwip_netif[NW_ADAPTER_INDEX_LWIP_NETIF_QTY];

+ 4 - 0
components/network/netdrv/include/luat_netdrv.h

@@ -110,6 +110,10 @@ void luat_netdrv_print_tm(const char * tag);
 
 void luat_netdrv_debug_set(int id, int enable);
 
+void luat_netdrv_netif_set_down(struct netif* netif);
+
+void luat_netdrv_netif_set_link_down(struct netif* netif);
+
 extern uint32_t g_netdrv_debug_enable;
 
 #endif

+ 1 - 1
components/network/netdrv/src/ch390h_task.c

@@ -331,7 +331,7 @@ static int task_loop_one(ch390h_t* ch, luat_ch390h_cstring_t* cs) {
         luat_ch390h_set_rx(ch, 1);
         if (netif_is_link_up(ch->netif)) {
             LLOGI("link is down %d %d", ch->spiid, ch->cspin);
-            netif_set_link_down(ch->netif);
+            luat_netdrv_netif_set_link_down(ch->netif);
             ulwip_netif_ip_event(&ch->ulwip);
             if (ch->dhcp) {
                 // 停止dhcp定时器

+ 36 - 0
components/network/netdrv/src/luat_netdrv.c

@@ -276,3 +276,39 @@ err_t luat_netdrv_netif_input_main(struct pbuf *p, struct netif *inp)
     return ip_input(p, inp);
 }
 
+void luat_netdrv_netif_set_down(struct netif* netif) {
+    if (netif == NULL) {
+        return;
+    }
+    netif_set_down(netif);
+    #if LWIP_IPV4 && LWIP_ARP
+    #ifdef LUAT_USE_NETDRV_LWIP_ARP
+    if (netif->flags & NETIF_FLAG_ETHARP) {
+        luat_netdrv_etharp_cleanup_netif(netif);
+    }
+    #endif
+    #endif /* LWIP_IPV4 && LWIP_ARP */
+
+    #if LWIP_IPV6
+    nd6_cleanup_netif(netif);
+    #endif /* LWIP_IPV6 */
+}
+
+void luat_netdrv_netif_set_link_down(struct netif* netif) {
+    if (netif == NULL) {
+        return;
+    }
+    netif_set_link_down(netif);
+    #if LWIP_IPV4 && LWIP_ARP
+    #ifdef LUAT_USE_NETDRV_LWIP_ARP
+    if (netif->flags & NETIF_FLAG_ETHARP) {
+        extern void luat_netdrv_etharp_cleanup_netif(struct netif *netif);
+        luat_netdrv_etharp_cleanup_netif(netif);
+    }
+    #endif
+    #endif /* LWIP_IPV4 && LWIP_ARP */
+
+    #if LWIP_IPV6
+    nd6_cleanup_netif(netif);
+    #endif /* LWIP_IPV6 */
+}

+ 1 - 1
components/network/netdrv/src/luat_netdrv_whale.c

@@ -197,7 +197,7 @@ static void _luat_netdrv_whale_ipevent(tmpptr_t* ptr) {
         }
     }
     else {
-        netif_set_down(drv->netif);
+        luat_netdrv_netif_set_down(drv->netif);
         if (cfg->dhcp) {
             // LLOGD("dhcp停止");
             ip_addr_set_ip4_u32(&cfg->ulwip.netif->ip_addr, 0);

+ 18 - 11
components/network/ulwip/src/ulwip_dhcp_client.c

@@ -32,6 +32,10 @@ static int ulwip_dhcp_client_run(ulwip_ctx_t* ctx, char* rxbuff, size_t len) {
 
     if (!netif_is_up(netif) || !netif_is_link_up(netif)) {
         LLOGD("网卡未就绪,不发送dhcp请求 %d", ctx->adapter_index);
+        if (rxbuff) {
+            luat_heap_free(rxbuff);
+            rxbuff = NULL;
+        }
         return 0;
     }
 
@@ -105,12 +109,10 @@ static int ulwip_dhcp_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p, const
     }
     LLOGD("收到DHCP数据包(len=%d)", p->tot_len);
     u16_t total_len = p->tot_len;
-    // ulwip_ctx_t *ctx = (ulwip_ctx_t *)arg;
     char* ptr = luat_heap_malloc(total_len);
     if (!ptr) {
         return ERR_OK;
     }
-    size_t offset = 0;
     pbuf_copy_partial(p, ptr, total_len, 0);
 
     // 解析DHCP数据包中的mac地址
@@ -120,6 +122,7 @@ static int ulwip_dhcp_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p, const
     u16_t ip_header_length = IP_IS_V6(addr) ? 40 : 20;
     u16_t udp_header_length = 8;
     ulwip_ctx_t* ctx = NULL;
+    u16_t max_dhcp_packet_len;
 
     // 收到DHCP数据包, 需要逐个ctx查一遍, 对照xid
     for (size_t i = 0; i < NW_ADAPTER_INDEX_LWIP_NETIF_QTY; i++)
@@ -129,14 +132,6 @@ static int ulwip_dhcp_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p, const
             continue;
         }
 
-        // 检查数据包长度是否足够
-        // max_dhcp packetlen = mtu - ip_head - udp_head
-        u16_t max_dhcp_packet_len = ctx->netif->mtu - ip_header_length - udp_header_length;
-        if (total_len > max_dhcp_packet_len) {
-            LLOGE("DHCP包长度超过最大值 %d", max_dhcp_packet_len);
-            return ERR_OK;
-        }
-
         // 获取网络接口的mac地址
         struct netif *netif = ctx->netif;
         uint8_t *local_mac = netif->hwaddr;
@@ -144,12 +139,24 @@ static int ulwip_dhcp_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p, const
         // LLOGD("mac %02X:%02X:%02X:%02X:%02X:%02X", local_mac[0], local_mac[1], local_mac[2], local_mac[3], local_mac[4], local_mac[5]);
         // LLOGD("received_mac %02X:%02X:%02X:%02X:%02X:%02X", received_mac[0], received_mac[1], received_mac[2], received_mac[3], received_mac[4], received_mac[5]);
         // 比较mac地址
-        if (memcmp(local_mac, received_mac, 6) == 0) {
+        if (0 == memcmp(local_mac, received_mac, 6)) {
             // 如果找到匹配的网络接口
+            // 先检查数据包长度是否足够
+            max_dhcp_packet_len = ctx->netif->mtu - ip_header_length - udp_header_length;
+            if (total_len > max_dhcp_packet_len) {
+                LLOGE("dhcp pkg too large %d mtu %d len %d", ctx->adapter_index, ctx->netif->mtu, max_dhcp_packet_len);
+                break;
+            }
+            // 注意, ulwip_dhcp_client_run是会释放ptr的, 所以不能在这里释放
             ulwip_dhcp_client_run(ctx, ptr, total_len);
+            ptr = NULL; // 防止重复释放
             break;
         }
     }
+    if (ptr) {
+        luat_heap_free(ptr);
+        ptr = NULL;
+    }
     return ERR_OK;
 }
 

+ 1 - 1
lua/src/lbaselib.c

@@ -47,7 +47,7 @@ static void luat_debug_print(int index, const char* str, size_t slen, int eof) {
     return;
   }
   if (index > 1) {
-    dbuff.buff[dbuff.offset++] = '\t';
+    dbuff.buff[dbuff.offset++] = ' ';
   }
   if (dbuff.offset + slen >= 512) {
     dbuff.buff[dbuff.offset] = 0x00;

+ 52 - 0
luat/demo/airlink/uart_http/main.lua

@@ -0,0 +1,52 @@
+
+-- LuaTools需要PROJECT和VERSION这两个信息
+PROJECT = "airlink_uart"
+VERSION = "1.0.1"
+
+is_gw = false -- 是否是网关模式
+
+sys.taskInit(function()
+    log.info("airlink", "Starting airlink with UART task")
+    -- 首先, 初始化uart1, 115200波特率 8N1
+    uart.setup(1, 115200)
+    -- 初始化airlink
+    airlink.init()
+    -- 注册网卡
+    netdrv.setup(socket.LWIP_USER0, netdrv.WHALE)
+    -- 启动airlink uart任务
+    airlink.start(2)
+
+    -- 网关模式下, ip设置为.1, 对端设置为.2
+    if is_gw then
+        netdrv.ipv4(socket.LWIP_USER0, "192.168.111.1", "255.255.255.0", "192.168.111.2")
+    else
+        netdrv.ipv4(socket.LWIP_USER0, "192.168.111.2", "255.255.255.0", "192.168.111.1")
+    end
+end)
+
+sys.taskInit(function()
+    -- sys.waitUntil("IP_READY")
+    sys.wait(3000)
+    if is_gw then
+        log.info("airlink", "Gateway mode")
+        while netdrv.ready(socket.LWIP_USER0) == false do
+            sys.wait(100)
+        end
+        netdrv.napt(socket.LWIP_GP)
+        return
+    else
+        log.info("airlink", "Client mode")
+    end
+    while 1 do
+        sys.wait(500)
+        local code, headers, body = http.request("GET", "https://httpbin.air32.cn/bytes/2048", nil, nil, {adapter=socket.LWIP_USER0,timeout=3000}).wait()
+        log.info("http", code, body and #body)
+        -- log.info("lua", rtos.meminfo())
+        -- log.info("sys", rtos.meminfo("sys"))
+    end
+end)
+
+-- 用户代码已结束---------------------------------------------
+-- 结尾总是这一句
+sys.run()
+-- sys.run()之后后面不要加任何语句!!!!!

+ 32 - 0
luat/demo/airlink/uart_sdata/main.lua

@@ -0,0 +1,32 @@
+
+-- LuaTools需要PROJECT和VERSION这两个信息
+PROJECT = "airlink_uart"
+VERSION = "1.0.1"
+
+sys.taskInit(function()
+    log.info("airlink", "Starting airlink with UART task")
+    -- 首先, 初始化uart1, 115200波特率 8N1
+    uart.setup(1, 115200)
+    -- 初始化airlink
+    airlink.init()
+    -- 启动airlink uart任务
+    airlink.start(2)
+
+    while 1 do
+        -- 发送给对端设备
+        local data = rtos.bsp() .. " " .. os.date() .. " " .. (mobile and mobile.imei() or "")
+        log.info("发送数据给对端设备", data, "当前airlink状态", airlink.ready())
+        airlink.sdata(data)
+        -- airlink.test(1000) -- 要测试高速连续发送的情况
+        sys.wait(1000)
+    end
+end)
+
+sys.subscribe("AIRLINK_SDATA", function(data)
+    log.info("收到AIRLINK_SDATA!!", data)
+end)
+
+-- 用户代码已结束---------------------------------------------
+-- 结尾总是这一句
+sys.run()
+-- sys.run()之后后面不要加任何语句!!!!!

+ 29 - 3
luat/demo/io/main.lua

@@ -14,7 +14,9 @@ if wdt then
 end
 
 
--- Lua IO 操作测试 Demo
+
+local function io_test()
+    -- Lua IO 操作测试 Demo
 log.info("io_test", "开始测试IO模块功能")
 
 -- 1. 测试文件存在性检查
@@ -74,7 +76,12 @@ end
 -- 8. 测试目录操作
 local testDir = "/test_dir"
 log.info("io_test", "创建目录:", io.mkdir(testDir))
-log.info("io_test", "目录存在:", io.exists(testDir))
+sys.wait(1000)
+
+local ret, data = io.lsdir(testDir)
+if ret then
+log.info("io_test", "目标目录存在", json.encode(data))
+end
 
 -- 在目录中创建几个测试文件
 io.writeFile(testDir.."/file1.txt", "测试文件1")
@@ -94,8 +101,24 @@ local mountPoints = io.lsmount()
 log.info("io_test", "挂载点列表:", json.encode(mountPoints))
 
 -- 11. 测试删除目录
+
+log.info("io_test","删除目录前先删除目录下的文件,否则非空目录删除会失败")
+
+log.info("io_test","删除测试文件1",os.remove(testDir.."/file1.txt"))
+log.info("io_test","删除测试文件2",os.remove(testDir.."/file2.txt"))
+log.info("io_test","删除测试文件3",os.remove(testDir.."/file3.txt"))
+
+
 log.info("io_test", "删除目录:", io.rmdir(testDir))
-log.info("io_test", "目录删除后存在:", io.exists(testDir))
+
+
+local ret, data = io.lsdir(testDir)
+if ret then
+log.info("io_test", "目录删除后存在:", json.encode(data))
+else
+log.info("io_test", "目录删除后不存在")
+
+end
 
 -- 12. 测试文件系统格式化(通常不执行,因为会清空数据)
 --[[
@@ -106,6 +129,9 @@ log.info("io_test", "格式化文件系统:", formatOk, err)
 -- 清理测试文件
 os.remove(testFile)
 log.info("io_test", "测试完成,已清理测试文件")
+end
+
+sys.taskInit(io_test)
 
 -- 用户代码已结束---------------------------------------------
 -- 结尾总是这一句

+ 5 - 7
luat/demo/spi/air8000/spi_tf_wan/main.lua

@@ -23,9 +23,9 @@ local rtos_bsp = rtos.bsp()
 local USE_CH390 = true  -- 使用ch390时,设置为true,否则为false
 local SPI_SPEED = 25600000
 
-if USE_CH390 then
-    gpio.setup(140, 1, gpio.PULLUP)  -- 打开ch390供电
-end
+-- if USE_CH390 then
+--     gpio.setup(140, 1, gpio.PULLUP)  -- 打开ch390供电
+-- end
 
 -- spi_id,pin_cs
 local function fatfs_spi_pin()     
@@ -34,7 +34,8 @@ end
 
 -- TF卡和WAN口初始化函数
 local function tf_wan_init()
-    sys.wait(1000)
+    gpio.setup(140, 1, gpio.PULLUP)  -- 打开ch390供电
+    sys.wait(1000)                   -- 延迟1秒让ch390 稳定后再挂载TF卡
     
     -- #################################################
     -- 首先初始化TF卡
@@ -130,9 +131,6 @@ local function tf_wan_init()
     -- #################################################
     log.info("tf_wan", "开始初始化WAN口")
     sys.wait(500)
-    log.info("ch390", "打开LDO供电")
-    gpio.setup(140, 1, gpio.PULLUP)     --打开ch390供电
-    sys.wait(6000)
 
     -- 初始化指定netdrv设备,
     -- socket.LWIP_ETH 网络适配器编号

BIN
module/Air780EHM&EHV&EGH/LuatOS多固件功能区别.png


BIN
module/Air780EHM&EHV&EGH/LuatOS多固件策略说明.png


BIN
module/Air780EHM&EHV&EGH/LuatOS扩展库简要说明.png


+ 129 - 0
module/Air780EHM&EHV&EGH/README.md

@@ -0,0 +1,129 @@
+# LuatOS-Air780EHM/Air780EHV/Air780EGH
+
+## 介绍
+
+本代码库 是 合宙 Air780EHM/EHV/EGH 模组的代码中心, 包括演示代码demo, 案例代码project等
+
+如需查阅文档, 请访问合宙文档中心的[文档中心](https://docs.openluat.com/)
+
+## 目录说明
+
+* demo  [演示代码](demo/)
+* project  [案例代码](project/)
+
+## 固件说明
+
+1. Air780EPM 只有1种32位固件,没有64位固件;
+
+2. Air780EHM,Air780EHV,Air780EGH 当前有22种固件,32位和64位各11种;
+
+3. 关于差分升级的相关说明;
+
+差分升级只能在同类固件之间进行,
+
+固件1 只能差分升级为固件1,
+
+固件2 只能差分升级为固件2,
+
+固件X 只能差分升级为固件X。
+
+![输入图片说明](LuatOS%E5%A4%9A%E5%9B%BA%E4%BB%B6%E7%AD%96%E7%95%A5%E8%AF%B4%E6%98%8E.png)
+![输入图片说明](LuatOS%E5%A4%9A%E5%9B%BA%E4%BB%B6%E5%8A%9F%E8%83%BD%E5%8C%BA%E5%88%AB.png)
+![输入图片说明](LuatOS%E6%89%A9%E5%B1%95%E5%BA%93%E7%AE%80%E8%A6%81%E8%AF%B4%E6%98%8E.png)
+
+## demo使用指南
+
+[**JT808**]:本demo演示使用string.pack与unpack函数,实现JT808 终端注册协议数据生成与解析,适用于车辆定位和监控系统。
+
+[**Websocket**]:本demo演示使用websocket协议,实现LuatOS与Web服务器的通信,适用于实时数据传输和双向通信场景。
+
+[**adc**]:本demo演示LuatOS的ADC功能,用于模拟信号的读取,适用于传感器数据采集等场景。
+
+[**airlbs**]:本demo演示LuatOS的LBS功能,包括多基站定位和WIFI定位,适用于位置服务开发。
+
+[**bit**]:本demo演示LuatOS的bit操作功能,适用于需要进行位级操作的场景。
+
+[**bit64**]:本demo演示LuatOS的64位bit操作功能,适用于需要进行大范围位级操作的场景。
+
+[**camera/spi_cam**]:本demo演示LuatOS的SPI摄像头功能,适用于需要集成摄像头进行图像采集的设备。
+
+[**can**]:本demo演示LuatOS的CAN总线通信功能,适用于汽车电子和工业自动化等场景。
+
+[**crypto**]:本demo演示LuatOS的加密功能,包括哈希、对称加密和非对称加密等,适用于需要进行数据加密和解密的场景。
+
+[**errdump**]:本demo演示LuatOS的错误信息转储功能,适用于设备调试和错误分析。
+
+[**fota2**]:本demo演示LuatOS的FOTA(空中下载)功能,包括固件更新等,适用于设备远程升级和维护。
+
+[**fs**]:本demo演示LuatOS的文件系统功能,包括文件读写等,适用于需要进行文件存储和操作的场景。
+
+[**gpio**]:本demo演示LuatOS的GPIO功能,包括数字输入输出等,适用于需要进行硬件控制的场景。
+
+[**helloworld**]:本demo演示LuatOS的基本运行环境,通过输出“Hello, World!”来验证开发环境是否搭建成功。
+
+[**hmeta**]:本demo演示LuatOS的硬件信息查询功能,适用于获取设备硬件相关信息。
+
+[**http**]:本demo演示LuatOS的HTTP协议功能,包括网页请求和文件下载等,适用于需要进行网络通信的场景。
+
+[**i2c-sht20**]:本demo演示LuatOS的I2C通信功能,通过SHT20温湿度传感器来读取温度和湿度信息。
+
+[**iconv**]:本demo演示LuatOS的字符编码转换功能,适用于需要进行字符编码转换的场景。
+
+[**iotcloud**]:本demo演示LuatOS与物联网云平台的通信,包括设备连接、数据上传和云服务调用等。
+
+[**json**]:本demo演示LuatOS的JSON数据解析和生成功能,适用于需要进行JSON格式数据处理的场景。
+
+[**lbsloc2**]:本demo演示LuatOS的LBS定位功能,适用于需要进行精准位置定位的场景。
+
+[**lcd**]:本demo演示LuatOS的LCD显示功能,适用于需要进行图形界面显示的设备。
+
+[**log**]:本demo演示LuatOS的日志记录功能,适用于需要进行日志记录和分析的场景。
+
+[**lowpower**]:本demo演示LuatOS的低功耗模式功能,适用于需要进行设备功耗优化的场景。
+
+[**miniz**]:本demo演示LuatOS的压缩和解压缩功能,适用于需要进行数据压缩和解压缩的场景。
+
+[**mobile**]:本demo演示LuatOS的移动网络功能,包括蜂窝网络连接、数据传输等,适用于需要进行移动网络通信的场景。
+
+[**mqtt**]:本demo演示LuatOS的MQTT协议功能,适用于物联网场景下的消息发布和订阅。
+
+[**netdrv/ch390**]:本demo演示LuatOS与CH390芯片的网络驱动功能,适用于USB转网口的设备。
+
+[**ntp**]:本demo演示LuatOS的NTP网络时间同步功能,适用于需要进行时间同步的场景。
+
+[**onewire**]:本demo演示LuatOS的1-Wire协议功能,适用于连接单总线设备如DS18B20温度传感器等。
+
+[**openai/deepseek**]:本demo演示LuatOS如何集成OpenAI的DeepSeek服务,适用于需要进行深度学习推理的场景。
+
+[**pack**]:本demo演示LuatOS的数据打包和解包功能,适用于需要进行数据格式转换的场景。
+
+[**protobuf**]:本demo演示LuatOS的protobuf数据解析和生成功能,适用于需要进行protobuf格式数据处理的场景。
+
+[**pwm**]:本demo演示LuatOS的PWM功能,适用于需要进行脉冲宽度调制的场景。
+
+[**sms**]:本demo演示LuatOS的短信收发功能,适用于嵌入式设备需要进行短信通信的场景。
+
+[**spi**]:本demo演示LuatOS的SPI通信功能,适用于需要进行SPI通信的场景。
+
+[**string**]:本demo演示LuatOS的字符串操作功能,包括字符串拼接、分割、查找等,适用于需要进行字符串处理的场景。
+
+[**tcp**]:本demo演示LuatOS的TCP协议功能,适用于需要进行TCP通信的场景。
+
+[**timer**]:本demo演示LuatOS的定时器功能,包括单次定时器和周期定时器,适用于需要定时执行任务的场景。
+
+[**uart**]:本demo演示LuatOS的UART串口通信功能,适用于需要进行串口通信的场景。
+
+[**udp**]:本demo演示LuatOS的UDP协议功能,适用于需要进行UDP通信的场景。
+
+[**wdt**]:本demo演示LuatOS的看门狗定时器功能,适用于需要进行设备监控和自动复位的场景。
+
+[**wlan/wifiscan**]:本demo演示LuatOS的Wi-Fi扫描功能,适用于需要搜索和连接Wi-Fi网络的场景。
+
+## 授权协议
+
+[MIT License](LICENSE)
+
+```lua
+print("感谢您使用LuatOS ^_^")
+print("Thank you for using LuatOS ^_^")
+```

+ 5 - 0
module/Air780EHM&EHV&EGH/core/version.md

@@ -0,0 +1,5 @@
+[Air780EHM底层固件Core下载链接](https://docs.openluat.com/air780epm/luatos/firmware/version/)
+
+[Air780EHV底层固件Core下载链接](https://docs.openluat.com/air780ehv/luatos/firmware/version/)
+
+[Air780EGH底层固件Core下载链接](https://docs.openluat.com/air780egh/luatos/firmware/version/)

+ 0 - 0
module/Air780EHV/demo/CC/main.lua → module/Air780EHM&EHV&EGH/demo/CC/main.lua


+ 0 - 0
module/Air780EHV/demo/JT808/main.lua → module/Air780EHM&EHV&EGH/demo/JT808/main.lua


+ 0 - 0
module/Air780EHV/demo/SPI/main.lua → module/Air780EHM&EHV&EGH/demo/SPI/main.lua


+ 650 - 0
module/Air780EHM&EHV&EGH/demo/SPI/rc522.lua

@@ -0,0 +1,650 @@
+--[[
+@module rc522
+@summary rc522 非接触式读写卡驱动
+@version 1.0
+@date    2022.06.14
+@author  Dozingfiretruck
+@usage
+--注意:因使用了sys.wait()所有api需要在协程中使用
+-- 用法实例
+local rc522 = require "rc522"
+sys.taskInit(function()
+    spi_rc522 = spi.setup(0,nil,0,0,8,10*1000*1000,spi.MSB,1,0)
+    rc522.init(0,pin.PB04,pin.PB01)
+    wdata = {0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}
+    while 1 do
+        rc522.write_datablock(8,wdata)
+        for i=0,63 do
+            local a,b = rc522.read_datablock(i)
+            if a then
+                print("read",i,b:toHex())
+            end
+        end
+        sys.wait(500)
+    end
+end)
+]]
+
+
+local rc522 = {}
+
+local sys = require "sys"
+
+local rc522_spi,rc522_rst,rc522_irq,rc522_cs
+
+---器件所用地址
+local rc522_idle              =       0x00   --取消当前命令
+local rc522_authent           =       0x0E   --验证密钥
+local rc522_receive           =       0x08   --接收数据
+local rc522_transmit          =       0x04   --发送数据
+local rc522_transceive        =       0x0C   --发送并接收数据
+local rc522_resetphase        =       0x0F   --复位
+local rc522_calccrc           =       0x03   --CRC计算
+
+--Mifare_One卡片命令字
+rc522.reqidl                 =       0x26   --寻天线区内未进入休眠状态
+rc522.reqall                 =       0x52   --寻天线区内全部卡
+local rc522_anticoll1        =       0x93   --防冲撞
+local rc522_anticoll2        =       0x95   --防冲撞
+local rc522_authent1a        =       0x60   --验证A密钥
+local rc522_authent1b        =       0x61   --验证B密钥
+local rc522_read             =       0x30   --读块
+local rc522_write            =       0xA0   --写块
+local rc522_decrement        =       0xC0   --扣款
+local rc522_increment        =       0xC1   --充值
+local rc522_restore          =       0xC2   --调块数据到缓冲区
+local rc522_transfer         =       0xB0   --保存缓冲区中数据
+local rc522_halt             =       0x50   --休眠
+
+--MF522寄存器定义
+-- PAGE 0
+local rc522_rfu00            =       0x00 --保留为将来之用    
+local rc522_com_mand         =       0x01 --启动和停止命令的执行      
+local rc522_com_ie           =       0x02 --中断请求传递的使能和禁能控制位      
+local rc522_divl_en          =       0x03 --中断请求传递的使能和禁能控制位      
+local rc522_com_irq          =       0x04 --包含中断请求标志      
+local rc522_div_irq          =       0x05 --包含中断请求标志  
+local rc522_error            =       0x06 --错误标志,指示执行的上个命令的错误状态      
+local rc522_status1          =       0x07 --包含通信的状态标志      
+local rc522_status2          =       0x08 --包含接收器和发送器的状态标志      
+local rc522_fifo_data        =       0x09 --64 字节 FIFO 缓冲区的输入和输出  
+local rc522_fifo_level       =       0x0A --指示 FIFO 中存储的字节数  
+local rc522_water_level      =       0x0B --定义 FIFO 下溢和上溢报警的 FIFO 深度  
+local rc522_control          =       0x0C --不同的控制寄存器  
+local rc522_bit_framing      =       0x0D --面向位的帧的调节  
+local rc522_coll             =       0x0E --RF 接口上检测到的第一个位冲突的位的位置  
+local rc522_rfu0f            =       0x0F --保留为将来之用  
+-- PAGE 1     
+local RFU10                  =       0x10 --保留为将来之用
+local rc522_mode             =       0x11 --定义发送和接收的常用模式
+local rc522_tx_mode          =       0x12 --定义发送过程的数据传输速率
+local rc522_rx_mode          =       0x13 --定义接收过程中的数据传输速率
+local rc522_tx_control       =       0x14 --控制天线驱动器管脚 TX1 和 TX2 的逻辑特性
+local rc522_tx_ayto          =       0x15 --控制天线驱动器的设置
+local rc522_tx_sel           =       0x16 --选择天线驱动器的内部源
+local rc522_rx_sel           =       0x17 --选择内部的接收器设置
+local rc522_rx_threshold     =       0x18 --选择位译码器的阈值
+local rc522_demod            =       0x19 --定义解调器的设置
+local rc522_rfu1a            =       0x1A --保留为将来之用
+local rc522_rfu1b            =       0x1B --保留为将来之用
+local rc522_mifare           =       0x1C --控制 ISO 14443/MIFARE 模式中 106kbit/s 的通信
+local rc522_rfu1d            =       0x1D --保留为将来之用
+local rc522_rfu1e            =       0x1E --保留为将来之用
+local rc522_serial_speed     =       0x1F --选择串行 UART 接口的速率
+-- PAGE 2    
+local rc522_rfu20            =       0x20 --保留为将来之用  
+local rc522_crcresult_m      =       0x21 --显示 CRC 计算的实际 MSB 值
+local rc522_crcresult_l      =       0x22 --显示 CRC 计算的实际 LSB 值
+local rc522_rfu23            =       0x23 --保留为将来之用
+local rc522_mod_width        =       0x24 --控制 ModWidth 的设置
+local rc522_rfu25            =       0x25 --保留为将来之用
+local rc522_rfcfg            =       0x26 --配置接收器增益
+local rc522_gsn              =       0x27 --选择天线驱动器管脚 TX1 和 TX2 的调制电导
+local rc522_cwgscfg          =       0x28 --选择天线驱动器管脚 TX1 和 TX2 的调制电导
+local rc522_modgscfg         =       0x29 --选择天线驱动器管脚 TX1 和 TX2 的调制电导
+local rc522_tmode            =       0x2A --定义内部定时器的设置
+local rc522_tprescaler       =       0x2B --定义内部定时器的设置
+local rc522_tpreload_h       =       0x2C --描述 16 位长的定时器重装值
+local rc522_tpreload_l       =       0x2D --描述 16 位长的定时器重装值
+local rc522_tcounter_value_h =       0x2E --描述 16 位长的定时器重装值
+local rc522_tcounter_value_l =       0x2F --描述 16 位长的定时器重装值
+-- PAGE 3      
+local rc522_rfu30            =       0x30 --保留为将来之用
+local rc522_testsel1         =       0x31 --常用测试信号的配置
+local rc522_testsel2         =       0x32 --常用测试信号的配置和 PRBS 控制
+local rc522_testpin_en       =       0x33 --D1-D7 输出驱动器的使能管脚(注:仅用于串行接口)
+local rc522_testpin_value    =       0x34 --定义 D1-D7 用作 I/O 总线时的值
+local rc522_testbus          =       0x35 --显示内部测试总线的状态
+local rc522_autotest         =       0x36 --控制数字自测试
+local rc522_version          =       0x37 --显示版本
+local rc522_analogtest       =       0x38 --控制管脚 AUX1 和 AUX2
+local rc522_testadc1         =       0x39 --定义 TestDAC1 的测试值  
+local rc522_testadc2         =       0x3A --定义 TestDAC2 的测试值   
+local rc522_testadc          =       0x3B --显示 ADC I 和 Q 通道的实际值   
+local rc522_rfu3c            =       0x3C --保留用于产品测试   
+local rc522_rfu3d            =       0x3D --保留用于产品测试   
+local rc522_rfu3e            =       0x3E --保留用于产品测试   
+local rc522_rfu3f		     =       0x3F --保留用于产品测试
+
+local Key_A = string.char(0xff,0xff,0xff,0xff,0xff,0xff)
+local Key_B = string.char(0xff,0xff,0xff,0xff,0xff,0xff)
+
+--[[
+写rc522寄存器
+@api rc522.set_bit_mask(address, value)
+@number address 地址
+@number value    值
+@usage
+write_rawrc(rc522_bit_framing,0x07)
+]]
+local function write_rawrc(address, value)
+    rc522_cs(0)
+    local data = string.char((address<<1)&0x7E) .. string.char(value)
+    spi.send(rc522_spi, data)
+    -- rc522_spi:send(data)
+    rc522_cs(1)
+end
+
+--[[
+读rc522寄存器
+@api rc522.read_rawrc(address)
+@number address 地址
+@return number 寄存器值
+@usage
+local n = read_rawrc(rc522_com_irq) 
+]]
+local function read_rawrc(address)
+    rc522_cs(0)
+    local data = string.char(((address<<1)&0x7E)|0x80)
+    spi.send(rc522_spi, data)
+    local val = spi.recv(rc522_spi,1)
+    -- rc522_spi:send(data)
+    -- local val = rc522_spi:recv(1)
+    rc522_cs(1)
+    return string.byte(val)
+end
+
+--[[
+对rc522寄存器置位
+@api rc522.set_bit_mask(address, mask)
+@number address 地址
+@number mask    置位值
+@usage
+rc522.set_bit_mask (rc522_fifo_level, 0x80)	
+]]
+function rc522.set_bit_mask(address, mask)
+    local current = read_rawrc(address)
+    write_rawrc(address, bit.bor(current, mask))
+end
+
+--[[
+对rc522寄存器清位
+@api rc522.clear_bit_mask(address, mask)
+@number address 地址
+@number mask    清位值
+@usage
+rc522.clear_bit_mask(rc522_com_irq, 0x80 )
+]]
+function rc522.clear_bit_mask(address, mask)
+    local current = read_rawrc(address)
+    write_rawrc(address, bit.band(current, bit.bnot(mask)))
+end
+
+--[[ 
+命令通讯
+@api rc522.command(command,data)
+@number command 
+@number data 
+@return status data len 结果,返回数据,收到的位长度
+@usage
+rc522.version()
+]]
+function rc522.command(command,data)
+    local out_data = {}
+    local len = 0
+    local status = false
+    local Irq_en  = 0x00
+    local waitfor = 0x00
+    local last_bits,n,l
+    if command==rc522_authent then
+        Irq_en   = 0x12;		
+        waitfor = 0x10;		
+    elseif command==rc522_transceive then 
+        Irq_en   = 0x77;		
+        waitfor = 0x30;		
+    end
+    write_rawrc(0x02, bit.bor(Irq_en, 0x80))
+    rc522.clear_bit_mask(rc522_com_irq, 0x80 )
+    write_rawrc (rc522_com_mand, rc522_idle)	 
+    rc522.set_bit_mask (rc522_fifo_level, 0x80)	
+    for i=1,#data do
+        write_rawrc(rc522_fifo_data, data[i])
+    end
+    write_rawrc(rc522_com_mand,command )	
+    if ( command == rc522_transceive )then
+        rc522.set_bit_mask(rc522_bit_framing,0x80)
+    end
+    l = 12;
+    while true do
+        sys.wait(1)
+        n = read_rawrc(rc522_com_irq) 
+        l = l - 1
+        if  not ((l ~= 0) and (bit.band(n, 0x01) == 0) and (bit.band(n, waitfor) == 0)) then
+            break
+        end
+    end
+    rc522.clear_bit_mask(rc522_bit_framing, 0x80 )
+    if (l ~= 0)then 
+        if bit.band(read_rawrc(rc522_error), 0x1B) == 0x00 then
+            status = true
+            if bit.band(n,Irq_en,0x01)~=0then			
+                status = false
+            end   
+            if (command == rc522_transceive )then
+                n = read_rawrc(rc522_fifo_level)
+                last_bits = bit.band(read_rawrc(rc522_control),0x07)	
+                if last_bits ~= 0 then
+                    len = (n - 1) * 8 + last_bits  
+                else
+                    len = n * 8  
+                end
+                if n == 0 then	
+                    n = 1  
+                end  
+                for i=1, n do
+                    out_data [ i ] = read_rawrc(rc522_fifo_data)
+                end 
+            end
+        end   
+    else
+        status = false
+    end
+    rc522.set_bit_mask (rc522_control,0x80 )
+    write_rawrc(rc522_com_mand,rc522_idle )
+    return status,out_data,len 
+end
+
+--[[ 
+防冲撞
+@api rc522.anticoll(id)
+@string id 卡片序列号,4字节
+@return status uid 结果,uid
+@usage
+local status,uid = rc522.anticoll(array_id)
+]]
+function rc522.anticoll(id)
+    local check = 0
+    local uid
+    rc522.clear_bit_mask(rc522_status2,0x08)
+    write_rawrc( rc522_bit_framing, 0x00);
+    rc522.clear_bit_mask (rc522_coll, 0x80);			  
+    local status, back_data = rc522.command(rc522_transceive,{0x93,0x20})
+    if back_data and #back_data >= 5 then		            
+        for i=1,4 do
+            check = bit.bxor(check,back_data[i])
+        end
+        if check ~= back_data[5] then
+            status = false;
+        end   			
+        uid = string.char(table.unpack(back_data,1,4))	
+    end
+    rc522.clear_bit_mask( rc522_coll, 0x80 )
+    return status,uid;		
+end
+
+--[[ 
+crc计算
+@api calculate_crc(data)
+@table data 数据
+@return table crc值
+@usage
+local crc = calculate_crc(buff)
+]]
+local function calculate_crc(data)
+    local ret_data = {}
+    rc522.clear_bit_mask(rc522_div_irq, 0x04)
+    write_rawrc(rc522_com_mand, rc522_idle) 
+    rc522.set_bit_mask (rc522_fifo_level,0x80 ) 
+    for i=1,#data do
+        write_rawrc(rc522_fifo_data, data[i])
+    end
+    write_rawrc(rc522_com_mand, rc522_calccrc) 
+    local i = 0xFF
+    while true do
+        local n = read_rawrc(0x05)
+        i = i - 1
+        if not ((i ~= 0) and not (n&0x04)) then
+            break
+        end
+    end
+    ret_data[1] = read_rawrc(0x22)
+    ret_data[2] = read_rawrc(0x21)
+    return ret_data
+end
+
+--[[ 
+验证卡片密码
+@api authstate(mode, addr,key,uid )
+@number mode 模式
+@number addr 地址
+@string key 密码
+@string uid uid
+@return bool 结果
+@usage
+status = authstate(rc522_authent1b, addr,Key_B,uid )
+]]
+local function authstate( mode, addr,key,uid )
+    local buff = {}
+    buff[1] = mode
+    buff[2] = addr
+    for i=1,6 do
+        buff[i+2]=key:byte(i)
+    end
+    for i=1,4 do
+        buff[i+8]=uid:byte(i)
+    end
+    local status, back_data = rc522.command(rc522_authent,buff)
+    if status == true and (read_rawrc(rc522_status2)& 0x08) ~= 0 then
+        return true
+    end
+    return false	
+end
+
+--[[ 
+写数据到M1卡一块
+@api rc522.write(addr, data)
+@number addr 块地址(0-63)M1卡总共有16个扇区(每个扇区有:3个数据块+1个控制块),共64个块
+@table data 数据
+@return bool 结果
+@usage
+rc522.write(addr, data)
+]]
+function rc522.write(addr, data)
+    local buff = {}
+    buff[1] = rc522_write;
+    buff[2] = addr;
+    local crc = calculate_crc(buff)
+    buff[3] = crc[1]
+    buff[4] = crc[2]
+    local status, back_data, back_bits = rc522.command(rc522_transceive,buff)
+    if status == true and back_bits == 4 and (back_data[1]& 0x0F)==0x0A then
+        local buf_w = {}
+        for i=0, 16 do
+            table.insert(buf_w, data[i])
+        end
+        local crc = calculate_crc(buf_w)
+        table.insert(buf_w, crc[1])
+        table.insert(buf_w, crc[2])
+        status, back_data, back_bits = rc522.command(rc522_transceive,buf_w)
+        if status == true and back_bits == 4 and (back_data[1]& 0x0F)==0x0A then
+            return status;
+        end
+    end
+    return status;		
+end
+
+--[[ 
+写数据到M1卡一块
+@api rc522.read(addr)
+@number addr 块地址(0-63)M1卡总共有16个扇区(每个扇区有:3个数据块+1个控制块),共64个块
+@return bool,string 结果,数据
+@usage
+rc522.read(addr, data)
+]]
+local function read(addr)
+    local buff = {}
+    buff[1] = rc522_read;
+    buff[2] = addr;
+    local crc = calculate_crc(buff)
+    buff[3] = crc[1]
+    buff[4] = crc[2]
+    local status, back_data, back_bits = rc522.command(rc522_transceive,buff)
+    if status == true and back_bits == 0x90 then
+        local data = string.char(table.unpack(back_data,1,16))
+        return status,data
+    end
+    return false
+end
+
+--[[ 
+rc522 硬件版本
+@api rc522.version()
+@return number 硬件版本
+@usage
+rc522.version()
+]]
+function rc522.version()
+    return read_rawrc(rc522_version)
+end
+
+--[[ 
+rc522 命令卡片进入休眠状态
+@api rc522.halt()
+@return bool 结果
+@usage
+rc522.halt()
+]]
+function rc522.halt()
+    local buff = {}
+    buff[1] = rc522_halt;
+    buff[2] = 0;
+    local crc = calculate_crc(buff)
+    buff[3] = crc[1]
+    buff[4] = crc[2]
+    local status = rc522.command(rc522_transceive,buff)
+    return status
+end
+
+--[[ 
+rc522 复位
+@api rc522.reset()
+@usage
+rc522.reset()
+]]
+function rc522.reset()
+    rc522_rst(1)
+    rc522_rst(0)
+    rc522_rst(1)
+    write_rawrc(rc522_com_mand, 0x0f)
+    write_rawrc(rc522_mode, 0x3D)        
+    write_rawrc(rc522_tpreload_l, 30)       
+    write_rawrc(rc522_tpreload_h, 0)			
+    write_rawrc(rc522_tmode, 0x8D)			
+    write_rawrc(rc522_tprescaler, 0x3E)	
+    write_rawrc(rc522_tx_ayto, 0x40)		
+end
+
+--[[ 
+开启天线 
+@api rc522.antenna_on()
+@usage
+rc522.antenna_on()
+]]
+function rc522.antenna_on()
+    local uc = read_rawrc( rc522_tx_control )
+    if (( uc & 0x03 )==0 ) then
+        rc522.set_bit_mask(rc522_tx_control, 0x03)
+    end
+end
+
+--[[ 
+关闭天线 
+@api rc522.antenna_on()
+@usage
+rc522.antenna_on()
+]]
+function rc522.antenna_off()
+    rc522.clear_bit_mask( rc522_tx_control, 0x03 )
+end
+
+--[[ 
+设置rc522工作方式为ISO14443_A
+@api rc522_config_isotype()
+@usage
+rc522_config_isotype()
+]]
+local function rc522_config_isotype()
+    rc522.clear_bit_mask(rc522_status2, 0x08)
+    write_rawrc(rc522_mode, 0x3D)
+    write_rawrc(rc522_rx_sel, 0x86)
+    write_rawrc(rc522_rfcfg, 0x7F)
+    write_rawrc(rc522_tpreload_l, 30)
+    write_rawrc(rc522_tpreload_h, 0)
+    write_rawrc(rc522_tmode, 0x8D)
+    write_rawrc(rc522_tprescaler, 0x3E)
+    rc522.antenna_on()
+end
+
+--[[
+rc522 寻卡
+@api rc522.request(req_code)
+@number req_code rc522.reqidl 寻天线区内未进入休眠状态 rc522.reqall 寻天线区内全部卡
+@return bool tagtype 结果,卡类型 
+@usage
+status,array_id = rc522.request(rc522.reqall)
+]]
+function rc522.request(req_code)
+    rc522.clear_bit_mask(rc522_status2,0x08)
+    write_rawrc(rc522_bit_framing,0x07)
+    rc522.set_bit_mask(rc522_tx_control,0x03)
+    local tagtype
+    local status, back_data, back_bits = rc522.command(rc522_transceive,{req_code})
+    if status == true and back_bits == 0x10 then
+        tagtype = string.char(table.unpack(back_data,1,2))
+        return status, tagtype
+    end
+    return false
+end
+
+--[[
+选定卡片
+@api rc522.select(id)
+@number id 卡片序列号,4字节
+@return bool 结果 
+@usage
+status = rc522.select(id)
+]]
+function rc522.select(id)
+    if not id then
+        return false
+    end
+    local buff = {}
+    buff[1]=rc522_anticoll1
+    buff[2]=0x70
+    buff[7]=0
+    for i=1,4 do
+        buff[i+2]=id:byte(i)
+        buff[7]= bit.bxor(buff[7],id:byte(i))
+    end
+    local crc = calculate_crc(buff)
+    buff[8]=crc[1]
+    buff[9]=crc[2]
+    rc522.clear_bit_mask( rc522_status2, 0x08 )
+    local status, back_data, back_bits = rc522.command(rc522_transceive,buff)
+    if status == true and back_bits == 0x18 then
+        return true
+    end
+    return false	
+end
+
+--[[
+按照rc522操作流程写入16字节数据到块
+@api rc522.write_datablock(addr,data)
+@number addr 任意块地址.M1卡总共有16个扇区(每个扇区有:3个数据块+1个控制块),共64个块
+@table data 指向要写入的数据,必须为16个字符
+@return bool 结果 
+@usage
+rc522.write_datablock(addr,data)
+]]
+function rc522.write_datablock(addr,data)
+    if #data ~= 16 then
+        return false
+    end
+    local status,array_id = rc522.request(rc522.reqall)
+    if  status ~= true then
+        status,array_id = rc522.request(rc522.reqall)
+    end
+    if status == true then
+        local status,uid = rc522.anticoll(array_id)
+        if not uid then
+            return false
+        end
+        if status == true and uid then
+            rc522.select(uid)
+            status = authstate( rc522_authent1b, addr,Key_B,uid )
+            if status == true then
+                status = rc522.write(addr,data)
+                rc522.halt()
+                return status
+            end
+        end
+    end
+    return false
+end
+
+--[[
+按照rc522操作流程读取块
+@api rc522.read_datablock(addr)
+@number addr 任意块地址.M1卡总共有16个扇区(每个扇区有:3个数据块+1个控制块),共64个块
+@return bool string 结果 数据
+@usage
+    for i=0,63 do
+        local a,b = rc522.read_datablock(i)
+        if a then
+            print("read",i,b:toHex())
+        end
+    end
+]]
+function rc522.read_datablock(addr)
+    local status,array_id = rc522.request(rc522.reqall)
+    if  status ~= true then
+        status,array_id = rc522.request(rc522.reqall)
+    end
+    if status == true then
+        local status,uid = rc522.anticoll(array_id)
+        if status == true and uid then
+            rc522.select(uid)
+            status = authstate( rc522_authent1b, addr,Key_B,uid )
+            if status == true then
+                local status,data = read(addr)
+                if status == true then
+                    return true, data
+                end
+                rc522.halt()
+            end
+        end
+    end
+    return false
+end
+
+--[[
+rc522 初始化
+@api rc522.init(spi_id, cs, rst)
+@number spi_id spi端口号
+@number cs      cs引脚
+@number rst     rst引脚
+@return bool 初始化结果
+@usage
+spi_rc522 = spi.setup(0,nil,0,0,8,10*1000*1000,spi.MSB,1,1)
+rc522.init(0,pin.PB04,pin.PB01)
+]]
+function rc522.init(spi_id,cs,rst)
+    rc522_spi = spi_id
+    rc522_cs = gpio.setup(cs, 0, gpio.PULLUP) 
+    rc522_cs(1)
+    rc522_rst = gpio.setup(rst, 0, gpio.PULLUP) 
+    rc522_rst(1)
+    rc522.reset()
+    rc522_config_isotype()
+    log.debug("rc522.version",rc522.version())
+    return true
+end
+
+function rc522.test()
+
+end
+
+return rc522
+
+
+

+ 0 - 0
module/Air780EHV/demo/SPI/rc522_test.lua → module/Air780EHM&EHV&EGH/demo/SPI/rc522_test.lua


+ 0 - 0
module/Air780EHV/demo/SPI/readme.md → module/Air780EHM&EHV&EGH/demo/SPI/readme.md


+ 0 - 0
module/Air780EHV/demo/WebSocket/WebSocket-UART透传/main.lua → module/Air780EHM&EHV&EGH/demo/WebSocket/WebSocket-UART透传/main.lua


+ 0 - 0
module/Air780EHV/demo/WebSocket/WebSocket加密通讯/main.lua → module/Air780EHM&EHV&EGH/demo/WebSocket/WebSocket加密通讯/main.lua


+ 0 - 0
module/Air780EHV/demo/adc/main.lua → module/Air780EHM&EHV&EGH/demo/adc/main.lua


+ 83 - 0
module/Air780EHM&EHV&EGH/demo/adc/testAdc.lua

@@ -0,0 +1,83 @@
+
+--[[
+1. Air101,Air103 模块上的ADC0脚-PA1, 0~2.4v,不要超过范围使用!!!
+2. Air101,Air103模块上的ADC1脚-PA4, 0~2.4v,不要超过范围使用!!!
+3. Air103 模块上的ADC2脚-PA2, 0~2.4v,不要超过范围使用!!! 
+4. Air103 模块上的ADC3脚-PA3, 0~2.4v,不要超过范围使用!!! 
+5. Air101,Air103 adc.CH_CPU 为内部温度 ,adc.CH_VBAT为VBAT
+6. Air105 adc参考电压是1.88V,所有通道一致,
+7. Air105内部分压没有隔离措施,在开启内部分压后,量程有所变化,具体看寄存器手册,1~5分压后能测到3.6,6通道能接近5V,但是不能直接测5V,可以测4.2V 0通道是始终开启无法关闭分压。
+8. Air780E内部ADC接口为12bits 外部直流分压为0-3.4V
+9. Air780E内部具有2个ADC接口,ADC0 -- AIO3 ADC1 -- AIO4 
+10. 特殊通道, CPU内部温度Temp -- adc.CH_CPU 主供电脚电压 VBAT -- adc.CH_VBAT
+11. 设置分压(adc.setRange)要在adc.open之前设置,否则无效!!
+]]
+
+local testAdc = {}
+
+function adc_pin()
+    --开发板ADC编号
+    -- 默认不开启分压,范围是0-1.1v精度高
+    -- 开启分压后,外部输入最大不可超过3.3V
+    -- 设置分压要在adc.open之前设置,否则无效!!
+    -- adc.setRange(adc.ADC_RANGE_MAX)
+    return 0,1,255,255,adc.CH_CPU ,adc.CH_VBAT
+end
+local adc_pin_0,adc_pin_1,adc_pin_2,adc_pin_3,adc_pin_temp,adc_pin_vbat=adc_pin()
+
+
+function testAdc.dotest()
+    if adc_pin_0 and adc_pin_0 ~= 255 then adc.open(adc_pin_0) end
+    if adc_pin_1 and adc_pin_1 ~= 255 then adc.open(adc_pin_1) end
+    if adc_pin_2 and adc_pin_2 ~= 255 then adc.open(adc_pin_2) end
+    if adc_pin_3 and adc_pin_3 ~= 255 then adc.open(adc_pin_3) end
+    if adc_pin_temp and adc_pin_temp ~= 255 then adc.open(adc_pin_temp) end
+    if adc_pin_vbat and adc_pin_vbat ~= 255 then adc.open(adc_pin_vbat) end
+
+    if adc_pin_0 and adc_pin_0 ~= 255 and mcu and mcu.ticks then
+        sys.wait(1000)
+        log.info("开始读取ADC")
+        local ms_start = mcu.ticks()
+        for i = 1, 100, 1 do
+            adc.get(adc_pin_0)
+        end
+        local ms_end = mcu.ticks()
+        log.info("结束读取ADC")
+        log.info("adc", "读取耗时", "100次", ms_end - ms_start, "ms", "单次", (ms_end - ms_start) // 100, "ms")
+    end
+
+    -- 下面是循环打印, 接地不打印0也是正常现象
+    -- ADC的精度都不会太高, 若需要高精度ADC, 建议额外添加adc芯片
+    while true do
+        if adc_pin_0 and adc_pin_0 ~= 255 then
+            log.debug("adc", "adc" .. tostring(adc_pin_0), adc.get(adc_pin_0)) -- 若adc.get报nil, 改成adc.read
+        end
+        if adc_pin_1 and adc_pin_1 ~= 255 then
+            log.debug("adc", "adc" .. tostring(adc_pin_1), adc.get(adc_pin_1))
+        end
+        if adc_pin_2 and adc_pin_2 ~= 255 then
+            log.debug("adc", "adc" .. tostring(adc_pin_2), adc.get(adc_pin_2))
+        end
+        if adc_pin_3 and adc_pin_3 ~= 255 then
+            log.debug("adc", "adc" .. tostring(adc_pin_3), adc.get(adc_pin_3))
+        end
+        if adc_pin_temp and adc_pin_temp ~= 255 then
+            log.debug("adc", "CPU TEMP", adc.get(adc_pin_temp))
+        end
+        if adc_pin_vbat and adc_pin_vbat ~= 255 then
+            log.debug("adc", "VBAT", adc.get(adc_pin_vbat))
+        end
+        sys.wait(1000)
+    end
+
+    -- 若不再读取, 可关掉adc, 降低功耗, 非必须
+    if adc_pin_0 and adc_pin_0 ~= 255 then adc.close(adc_pin_0) end
+    if adc_pin_1 and adc_pin_1 ~= 255 then adc.close(adc_pin_1) end
+    if adc_pin_2 and adc_pin_2 ~= 255 then adc.close(adc_pin_2) end
+    if adc_pin_3 and adc_pin_3 ~= 255 then adc.close(adc_pin_3) end
+    if adc_pin_temp and adc_pin_temp ~= 255 then adc.close(adc_pin_temp) end
+    if adc_pin_vbat and adc_pin_vbat ~= 255 then adc.close(adc_pin_vbat) end
+
+end
+
+return testAdc

+ 0 - 0
module/Air780EHV/demo/airlbs/main.lua → module/Air780EHM&EHV&EGH/demo/airlbs/main.lua


+ 0 - 0
module/Air780EHV/demo/airtalk/airaudio.lua → module/Air780EHM&EHV&EGH/demo/airtalk/airaudio.lua


+ 0 - 0
module/Air780EHV/demo/airtalk/main.lua → module/Air780EHM&EHV&EGH/demo/airtalk/main.lua


+ 0 - 0
module/Air780EHV/demo/airtalk/talk.lua → module/Air780EHM&EHV&EGH/demo/airtalk/talk.lua


+ 0 - 0
module/Air780EHV/demo/apn/main.lua → module/Air780EHM&EHV&EGH/demo/apn/main.lua


+ 0 - 0
module/Air780EHV/demo/audio/1.mp3 → module/Air780EHM&EHV&EGH/demo/audio/1.mp3


+ 0 - 0
module/Air780EHV/demo/audio/main.lua → module/Air780EHM&EHV&EGH/demo/audio/main.lua


+ 0 - 0
module/Air780EHV/demo/bit/main.lua → module/Air780EHM&EHV&EGH/demo/bit/main.lua


+ 0 - 0
module/Air780EHV/demo/bit64/main.lua → module/Air780EHM&EHV&EGH/demo/bit64/main.lua


+ 115 - 0
module/Air780EHM&EHV&EGH/demo/camera/spi_cam/bf30a2.lua

@@ -0,0 +1,115 @@
+
+local reg_table = {
+	{0xf2,0x01},
+	{0xcf,0xb0},
+	{0x12,0x20},
+	{0x15,0x80},
+	{0x6b,0x71},
+	{0x00,0x40},
+	{0x04,0x00},
+	{0x06,0x26},
+	{0x08,0x07},
+	{0x1c,0x12},
+	{0x20,0x20},
+	{0x21,0x20},
+	{0x34,0x02},
+	{0x35,0x02},
+	{0x36,0x21},
+	{0x37,0x13},
+	{0xca,0x23},
+	{0xcb,0x22},
+	{0xcc,0x89},
+	{0xcd,0x4c},
+	{0xce,0x6b},
+	{0xa0,0x8e},
+	{0x01,0x1b},
+	{0x02,0x1d},
+	{0x13,0x08},
+	{0x87,0x13},
+	{0x8b,0x08},
+	{0x70,0x17},
+	{0x71,0x43},
+	{0x72,0x0a},
+	{0x73,0x62},
+	{0x74,0xa2},
+	{0x75,0xbf},
+	{0x76,0x00},
+	{0x77,0xcc},
+	{0x40,0x32},
+	{0x41,0x28},
+	{0x42,0x26},
+	{0x43,0x1d},
+	{0x44,0x1a},
+	{0x45,0x14},
+	{0x46,0x11},
+	{0x47,0x0f},
+	{0x48,0x0e},
+	{0x49,0x0d},
+	{0x4B,0x0c},
+	{0x4C,0x0b},
+	{0x4E,0x0a},
+	{0x4F,0x09},
+	{0x50,0x09},
+	{0x24,0x30},
+	{0x25,0x36},
+	{0x80,0x00},
+	{0x81,0x20},
+	{0x82,0x40},
+	{0x83,0x30},
+	{0x84,0x50},
+	{0x85,0x30},
+	{0x86,0xd8},
+	{0x89,0x45},
+	{0x8a,0x33},
+	{0x8f,0x81},
+	{0x91,0xff},
+	{0x92,0x08},
+	{0x94,0x82},
+	{0x95,0xfd},
+	{0x9a,0x20},
+	{0x9e,0xbc},
+	{0xf0,0x87},
+	{0x51,0x06},
+	{0x52,0x25},
+	{0x53,0x2b},
+	{0x54,0x0f},
+	{0x57,0x2a},
+	{0x58,0x22},
+	{0x59,0x2c},
+	{0x23,0x33},
+	{0xa1,0x93},
+	{0xa2,0x0f},
+	{0xa3,0x2a},
+	{0xa4,0x08},
+	{0xa5,0x26},
+	{0xa7,0x80},
+	{0xa8,0x80},
+	{0xa9,0x1e},
+	{0xaa,0x19},
+	{0xab,0x18},
+	{0xae,0x50},
+	{0xaf,0x04},
+	{0xc8,0x10},
+	{0xc9,0x15},
+	{0xd3,0x0c},
+	{0xd4,0x16},
+	{0xee,0x06},
+	{0xef,0x04},
+	{0x55,0x34},
+	{0x56,0x9c},
+	{0xb1,0x98},
+	{0xb2,0x98},
+	{0xb3,0xc4},
+	{0xb4,0x0c},
+	{0xa0,0x8f},
+	{0x13,0x07},
+}
+
+function bf30a2Init(cspiId,i2cId,speed,scanMode,onlyY)
+	local id = camera.init(cspiId,speed,0,0,1,0,0,onlyY,scanMode,240,320)
+	for i=1,#reg_table do
+		i2c.send(i2cId,0x6e,reg_table[i],1)
+	end
+	camera.start(id)
+	return id
+end

+ 328 - 0
module/Air780EHM&EHV&EGH/demo/camera/spi_cam/gc0310.lua

@@ -0,0 +1,328 @@
+local reg_table = {
+        {0xfe, 0xf0},
+        {0xfe, 0xf0},
+        {0xfe, 0x00},
+        {0xfc, 0x16}, 
+        {0xfc, 0x16}, 
+        {0xf2, 0x07}, 
+        {0xf3, 0x83}, 
+        {0xf5, 0x07}, 
+        {0xf7, 0x88}, 
+        {0xf8, 0x00}, 
+        {0xf9, 0x4f}, 
+        {0xfa, 0x11}, 
+        {0xfc, 0xce},
+        {0xfd, 0x00},
+
+        {0x00, 0x2f},
+        {0x01, 0x0f},
+        {0x02, 0x04},
+        {0x03, 0x02},
+        {0x04, 0x12},
+        {0x09, 0x00},
+        {0x0a, 0x00},
+        {0x0b, 0x00},
+        {0x0c, 0x04},
+        {0x0d, 0x01},
+        {0x0e, 0xe8},
+        {0x0f, 0x02},
+        {0x10, 0x88},
+        {0x16, 0x00},
+        {0x17, 0x14},
+        {0x18, 0x1a},
+        {0x19, 0x14},
+        {0x1b, 0x48},
+        {0x1c, 0x6c},
+        {0x1e, 0x6b},
+        {0x1f, 0x28},
+        {0x20, 0x8b},
+        {0x21, 0x49},
+        {0x22, 0xd0},
+        {0x23, 0x04},
+        {0x24, 0xff},
+        {0x34, 0x20},
+
+        {0x26, 0x23}, 
+        {0x28, 0xff}, 
+        {0x29, 0x00}, 
+        {0x32, 0x04},
+        {0x33, 0x10}, 
+        {0x37, 0x20}, 
+        {0x38, 0x10},
+        {0x47, 0x80}, 
+        {0x4e, 0x66}, 
+        {0xa8, 0x02}, 
+        {0xa9, 0x80},
+
+        {0x40, 0xff},
+        {0x41, 0x21}, 
+        {0x42, 0xcf}, 
+        {0x44, 0x00},
+        {0x45, 0xa0},
+        {0x46, 0x02}, 
+        {0x4a, 0x11},
+        {0x4b, 0x01},
+        {0x4c, 0x20}, 
+        {0x4d, 0x05}, 
+        {0x4f, 0x01},
+        {0x50, 0x01}, 
+        {0x55, 0x01}, 
+        {0x56, 0xe0},
+        {0x57, 0x02}, 
+        {0x58, 0x80},
+
+        {0x70, 0x70},
+        {0x5a, 0x84},
+        {0x5b, 0xc9},
+        {0x5c, 0xed},
+        {0x77, 0x74},
+        {0x78, 0x40},
+        {0x79, 0x5f},
+
+        {0x82, 0x14},
+        {0x83, 0x0b},
+        {0x89, 0xf0},
+
+        {0x8f, 0xaa},
+        {0x90, 0x8c},
+        {0x91, 0x90},
+        {0x92, 0x03},
+        {0x93, 0x03},
+        {0x94, 0x05},
+        {0x95, 0x65},
+        {0x96, 0xf0},
+
+        {0xfe, 0x00},
+        {0x9a, 0x20},
+        {0x9b, 0x80},
+        {0x9c, 0x40},
+        {0x9d, 0x80},
+        {0xa1, 0x30},
+        {0xa2, 0x32},
+        {0xa4, 0x30}, 
+        {0xa5, 0x30}, 
+        {0xaa, 0x10}, 
+        {0xac, 0x22},
+
+        {0xfe, 0x00},
+        {0xbf, 0x08},
+        {0xc0, 0x16},
+        {0xc1, 0x28},
+        {0xc2, 0x41},
+        {0xc3, 0x5a},
+        {0xc4, 0x6c},
+        {0xc5, 0x7a},
+        {0xc6, 0x96},
+        {0xc7, 0xac},
+        {0xc8, 0xbc},
+        {0xc9, 0xc9},
+        {0xca, 0xd3},
+        {0xcb, 0xdd},
+        {0xcc, 0xe5},
+        {0xcd, 0xf1},
+        {0xce, 0xfa},
+        {0xcf, 0xff},
+
+        {0xd0, 0x40},
+        {0xd1, 0x34},
+        {0xd2, 0x34},
+        {0xd3, 0x40},
+        {0xd6, 0xf2},
+        {0xd7, 0x1b},
+        {0xd8, 0x18},
+        {0xdd, 0x03},
+
+        {0xfe, 0x01},
+        {0x05, 0x30},
+        {0x06, 0x75},
+        {0x07, 0x40},
+        {0x08, 0xb0},
+        {0x0a, 0xc5},
+        {0x0b, 0x11},
+        {0x0c, 0x00},
+        {0x12, 0x52},
+        {0x13, 0x38},
+        {0x18, 0x95},
+        {0x19, 0x96},
+        {0x1f, 0x20},
+        {0x20, 0xc0},
+        {0x3e, 0x40},
+        {0x3f, 0x57},
+        {0x40, 0x7d},
+        {0x03, 0x60},
+        {0x44, 0x00},
+
+        {0xfe, 0x01},
+        {0x1c, 0x91},
+        {0x21, 0x15},
+        {0x50, 0x80},
+        {0x56, 0x04},
+        {0x59, 0x08},
+        {0x5b, 0x02},
+        {0x61, 0x8d},
+        {0x62, 0xa7},
+        {0x63, 0xd0},
+        {0x65, 0x06},
+        {0x66, 0x06},
+        {0x67, 0x84},
+        {0x69, 0x08},
+        {0x6a, 0x25},
+        {0x6b, 0x01},
+        {0x6c, 0x00},
+        {0x6d, 0x02},
+        {0x6e, 0xf0},
+        {0x6f, 0x80},
+        {0x76, 0x80},
+        {0x78, 0xaf},
+        {0x79, 0x75},
+        {0x7a, 0x40},
+        {0x7b, 0x50},
+        {0x7c, 0x0c},
+        {0x90, 0xc9}, 
+        {0x91, 0xbe},
+        {0x92, 0xe2},
+        {0x93, 0xc9},
+        {0x95, 0x1b},
+        {0x96, 0xe2},
+        {0x97, 0x49},
+        {0x98, 0x1b},
+        {0x9a, 0x49},
+        {0x9b, 0x1b},
+        {0x9c, 0xc3},
+        {0x9d, 0x49},
+        {0x9f, 0xc7},
+        {0xa0, 0xc8},
+        {0xa1, 0x00},
+        {0xa2, 0x00},
+        {0x86, 0x00},
+        {0x87, 0x00},
+        {0x88, 0x00},
+        {0x89, 0x00},
+        {0xa4, 0xb9},
+        {0xa5, 0xa0},
+        {0xa6, 0xba},
+        {0xa7, 0x92},
+        {0xa9, 0xba},
+        {0xaa, 0x80},
+        {0xab, 0x9d},
+        {0xac, 0x7f},
+        {0xae, 0xbb},
+        {0xaf, 0x9d},
+        {0xb0, 0xc8},
+        {0xb1, 0x97},
+        {0xb3, 0xb7},
+        {0xb4, 0x7f},
+        {0xb5, 0x00},
+        {0xb6, 0x00},
+        {0x8b, 0x00},
+        {0x8c, 0x00},
+        {0x8d, 0x00},
+        {0x8e, 0x00},
+        {0x94, 0x55},
+        {0x99, 0xa6},
+        {0x9e, 0xaa},
+        {0xa3, 0x0a},
+        {0x8a, 0x00},
+        {0xa8, 0x55},
+        {0xad, 0x55},
+        {0xb2, 0x55},
+        {0xb7, 0x05},
+        {0x8f, 0x00},
+        {0xb8, 0xcb},
+        {0xb9, 0x9b},
+
+        {0xfe, 0x01},
+        {0xd0, 0x38}, 
+        {0xd1, 0x00},
+        {0xd2, 0x02},
+        {0xd3, 0x04},
+        {0xd4, 0x38},
+        {0xd5, 0x12},
+        {0xd6, 0x30},
+        {0xd7, 0x00},
+        {0xd8, 0x0a},
+        {0xd9, 0x16},
+        {0xda, 0x39},
+        {0xdb, 0xf8},
+
+        {0xfe, 0x01},
+        {0xc1, 0x3c},
+        {0xc2, 0x50},
+        {0xc3, 0x00},
+        {0xc4, 0x40},
+        {0xc5, 0x30},
+        {0xc6, 0x30},
+        {0xc7, 0x10},
+        {0xc8, 0x00},
+        {0xc9, 0x00},
+        {0xdc, 0x20},
+        {0xdd, 0x10},
+        {0xdf, 0x00},
+        {0xde, 0x00},
+
+        {0x01, 0x10},
+        {0x0b, 0x31}, 
+        {0x0e, 0x50},
+        {0x0f, 0x0f},
+        {0x10, 0x6e},
+        {0x12, 0xa0},
+        {0x15, 0x60},
+        {0x16, 0x60},
+        {0x17, 0xe0},
+
+        {0xcc, 0x0c}, 
+        {0xcd, 0x10},
+        {0xce, 0xa0},
+        {0xcf, 0xe6},
+
+    
+        {0x45, 0xf7},
+        {0x46, 0xff}, 
+        {0x47, 0x15},
+        {0x48, 0x03}, 
+        {0x4f, 0x60}, 
+  
+        {0xfe, 0x00},
+        {0x05, 0x01},
+        {0x06, 0x32}, 
+        {0x07, 0x00},
+        {0x08, 0x0c}, 
+        {0xfe, 0x01},
+        {0x25, 0x00}, 
+        {0x26, 0x3c},
+        {0x27, 0x01}, 
+        {0x28, 0xdc},
+        {0x29, 0x01}, 
+        {0x2a, 0xe0},
+        {0x2b, 0x01}, 
+        {0x2c, 0xe0},
+        {0x2d, 0x01}, 
+        {0x2e, 0xe0},
+        {0x3c, 0x20},
+
+	--SPI配置
+	{0xfe, 0x03},
+	{0x52, 0xa2},
+	{0x53, 0x24}, 
+	{0x54, 0x20},
+	{0x55, 0x00},
+	{0x59, 0x1f}, 
+	{0x5a, 0x00},
+	{0x5b, 0x80},
+	{0x5c, 0x02},
+	{0x5d, 0xe0},
+	{0x5e, 0x01},
+	{0x51, 0x03},
+	{0x64, 0x04},
+	{0xfe, 0x00},
+	{0x44, 0x02},
+}
+
+function gc0310Init(cspiId,i2cId,speed,scanMode,onlyY)
+	local id = camera.init(cspiId,speed,1,1,2,1,0x00010101,onlyY,scanMode,640,480)
+	for i=1,#reg_table do
+		i2c.send(i2cId,0x21,reg_table[i],1)
+	end
+	camera.start(id)
+	return id
+end

+ 361 - 0
module/Air780EHM&EHV&EGH/demo/camera/spi_cam/gc032a.lua

@@ -0,0 +1,361 @@
+local reg_table = {
+   {0xf3, 0x83}, 
+   {0xf5, 0x08},
+   {0xf7, 0x01},
+   {0xf8, 0x01}, 
+   {0xf9, 0x4e},
+   {0xfa, 0x00},
+   {0xfc, 0x02},
+   {0xfe, 0x02},
+   {0x81, 0x03},
+
+   {0xfe, 0x00},
+   {0x77, 0x64},
+   {0x78, 0x40},
+   {0x79, 0x60},
+
+   {0xfe, 0x00},
+   {0x03, 0x01},
+   {0x04, 0xcb},
+   {0x05, 0x01},
+   {0x06, 0xb2},
+   {0x07, 0x00},
+   {0x08, 0x10},
+
+   {0x0a, 0x00},
+   {0x0c, 0x00},
+   {0x0d, 0x01},
+   {0x0e, 0xe8},
+   {0x0f, 0x02},
+   {0x10, 0x88},
+
+   {0x17, 0x54},
+   {0x19, 0x08},
+   {0x1a, 0x0a},
+   {0x1f, 0x40},
+   {0x20, 0x30},
+   {0x2e, 0x80},
+   {0x2f, 0x2b},
+   {0x30, 0x1a},
+   {0xfe, 0x02},
+   {0x03, 0x02},
+   {0x05, 0xd7},
+   {0x06, 0x60},
+   {0x08, 0x80},
+   {0x12, 0x89},
+
+
+   {0xfe, 0x03},
+   {0x52, 0xba}, 
+   {0x53, 0x24},
+   {0x54, 0x20},
+   {0x55, 0x00},
+   {0x59, 0x1f}, 
+   {0x5a, 0x00}, 
+   {0x5b, 0x80},
+   {0x5c, 0x02},
+   {0x5d, 0xe0},
+   {0x5e, 0x01},
+   {0x51, 0x03},
+   {0x64, 0x04},
+   {0xfe, 0x00},
+
+
+   {0xfe, 0x00},
+   {0x18, 0x02},
+   {0xfe, 0x02},
+   {0x40, 0x22},
+   {0x45, 0x00},
+   {0x46, 0x00},
+   {0x49, 0x20},
+   {0x4b, 0x3c},
+   {0x50, 0x20},
+   {0x42, 0x10},
+
+
+   {0xfe, 0x01},
+   {0x0a, 0xc5},
+   {0x45, 0x00},
+   {0xfe, 0x00},
+   {0x40, 0xff},
+   {0x41, 0x25},
+   {0x42, 0xef},
+   {0x43, 0x10},
+   {0x44, 0x83}, 
+   {0x46, 0x22},
+   {0x49, 0x03},
+   {0x52, 0x02},
+   {0x54, 0x00},
+   {0xfe, 0x02},
+   {0x22, 0xf6},
+
+
+   {0xfe, 0x01},
+   {0xc1, 0x38},
+   {0xc2, 0x4c},
+   {0xc3, 0x00},
+   {0xc4, 0x2c},
+   {0xc5, 0x24},
+   {0xc6, 0x18},
+   {0xc7, 0x28},
+   {0xc8, 0x11},
+   {0xc9, 0x15},
+   {0xca, 0x20},
+   {0xdc, 0x7a},
+   {0xdd, 0xa0},
+   {0xde, 0x80},
+   {0xdf, 0x88},
+
+
+   {0xfe, 0x01},
+   {0x50, 0xc1},
+   {0x56, 0x34},
+   {0x58, 0x04},
+   {0x65, 0x06},
+   {0x66, 0x0f},
+   {0x67, 0x04},
+   {0x69, 0x20},
+   {0x6a, 0x40},
+   {0x6b, 0x81},
+   {0x6d, 0x12},
+   {0x6e, 0xc0},
+   {0x7b, 0x2a},
+   {0x7c, 0x0c},
+   {0xfe, 0x01},
+   {0x90, 0xe3},
+   {0x91, 0xc2},
+   {0x92, 0xff},
+   {0x93, 0xe3},
+   {0x95, 0x1c},
+   {0x96, 0xff},
+   {0x97, 0x44},
+   {0x98, 0x1c},
+   {0x9a, 0x44},
+   {0x9b, 0x1c},
+   {0x9c, 0x64},
+   {0x9d, 0x44},
+   {0x9f, 0x71},
+   {0xa0, 0x64},
+   {0xa1, 0x00},
+   {0xa2, 0x00},
+   {0x86, 0x00},
+   {0x87, 0x00},
+   {0x88, 0x00},
+   {0x89, 0x00},
+   {0xa4, 0xc2},
+   {0xa5, 0x9b},
+   {0xa6, 0xc8},
+   {0xa7, 0x92},
+   {0xa9, 0xc9},
+   {0xaa, 0x96},
+   {0xab, 0xa9},
+   {0xac, 0x99},
+   {0xae, 0xce},
+   {0xaf, 0xa9},
+   {0xb0, 0xcf},
+   {0xb1, 0x9d},
+   {0xb3, 0xcf},
+   {0xb4, 0xac},
+   {0xb5, 0x00},
+   {0xb6, 0x00},
+   {0x8b, 0x00},
+   {0x8c, 0x00},
+   {0x8d, 0x00},
+   {0x8e, 0x00},
+   {0x94, 0x55},
+   {0x99, 0xa6},
+   {0x9e, 0xaa},
+   {0xa3, 0x0a},
+   {0x8a, 0x00},
+   {0xa8, 0x55},
+   {0xad, 0x55},
+   {0xb2, 0x55},
+   {0xb7, 0x05},
+   {0x8f, 0x00},
+   {0xb8, 0xc7},
+   {0xb9, 0xa0},
+
+   {0xfe, 0x01},
+   {0xd0, 0x40},
+   {0xd1, 0x00},
+   {0xd2, 0x00},
+   {0xd3, 0xfa},
+   {0xd4, 0x4a},
+   {0xd5, 0x02},
+
+   {0xd6, 0x44},
+   {0xd7, 0xfa},
+   {0xd8, 0x04},
+   {0xd9, 0x08},
+   {0xda, 0x5c},
+   {0xdb, 0x02},
+   {0xfe, 0x00},
+
+
+   {0xfe, 0x00},
+   {0xba, 0x00},
+   {0xbb, 0x04},
+   {0xbc, 0x0a},
+   {0xbd, 0x0e},
+   {0xbe, 0x22},
+   {0xbf, 0x30},
+   {0xc0, 0x3d},
+   {0xc1, 0x4a},
+   {0xc2, 0x5d},
+   {0xc3, 0x6b},
+   {0xc4, 0x7a},
+   {0xc5, 0x85},
+   {0xc6, 0x90},
+   {0xc7, 0xa5},
+   {0xc8, 0xb5},
+   {0xc9, 0xc2},
+   {0xca, 0xcc},
+   {0xcb, 0xd5},
+   {0xcc, 0xde},
+   {0xcd, 0xea},
+   {0xce, 0xf5},
+   {0xcf, 0xff},
+
+
+   {0xfe, 0x00},
+   {0x5a, 0x08},
+   {0x5b, 0x0f},
+   {0x5c, 0x15},
+   {0x5d, 0x1c},
+   {0x5e, 0x28},
+   {0x5f, 0x36},
+   {0x60, 0x45},
+   {0x61, 0x51},
+   {0x62, 0x6a},
+   {0x63, 0x7d},
+   {0x64, 0x8d},
+   {0x65, 0x98},
+   {0x66, 0xa2},
+   {0x67, 0xb5},
+   {0x68, 0xc3},
+   {0x69, 0xcd},
+   {0x6a, 0xd4},
+   {0x6b, 0xdc},
+   {0x6c, 0xe3},
+   {0x6d, 0xf0},
+   {0x6e, 0xf9},
+   {0x6f, 0xff},
+
+
+   {0xfe, 0x00},
+   {0x70, 0x50},
+
+
+   {0xfe, 0x00},
+   {0x4f, 0x01},
+   {0xfe, 0x01},
+   {0x0c, 0x01},
+   {0x0d, 0x00}, 
+   {0x12, 0xa0},
+   {0x13, 0x38},
+   {0x1f, 0x40},
+   {0x20, 0x40},
+   {0x23, 0x0a},
+   {0x26, 0x9a},
+   {0x3e, 0x20},
+   {0x3f, 0x2d},
+   {0x40, 0x40},
+   {0x41, 0x5b},
+   {0x42, 0x82},
+   {0x43, 0xb7},
+   {0x04, 0x0a},
+   {0x02, 0x79},
+   {0x03, 0xc0},
+
+  
+   {0xfe, 0x01},
+   {0xcc, 0x08},
+   {0xcd, 0x08},
+   {0xce, 0xa4},
+   {0xcf, 0xec},
+
+ 
+   {0xfe, 0x00},
+   {0x81, 0xb8},
+   {0x82, 0x04},
+   {0x83, 0x10},
+   {0x84, 0x01},
+   {0x86, 0x50},
+   {0x87, 0x18},
+   {0x88, 0x10},
+   {0x89, 0x70},
+   {0x8a, 0x20},
+   {0x8b, 0x10},
+   {0x8c, 0x08},
+   {0x8d, 0x0a},
+
+
+   {0xfe, 0x00},
+   {0x8f, 0xaa},
+   {0x90, 0x1c},
+   {0x91, 0x52},
+   {0x92, 0x03},
+   {0x93, 0x03},
+   {0x94, 0x08},
+   {0x95, 0x6a},
+   {0x97, 0x00},
+   {0x98, 0x00},
+
+ 
+   {0xfe, 0x00},
+   {0x9a, 0x30},
+   {0x9b, 0x50},
+   {0xa1, 0x30},
+   {0xa2, 0x66},
+   {0xa4, 0x28},
+   {0xa5, 0x30},
+   {0xaa, 0x28},
+   {0xac, 0x32},
+
+  
+   {0xfe, 0x00},
+   {0xd1, 0x3f},
+   {0xd2, 0x3f},
+   {0xd3, 0x38},
+   {0xd6, 0xf4},
+   {0xd7, 0x1d},
+   {0xdd, 0x72},
+   {0xde, 0x84},
+
+   {0xfe, 0x00},
+   {0x05, 0x01},
+   {0x06, 0xad},
+   {0x07, 0x00},
+   {0x08, 0x10},
+
+   {0xfe, 0x01},
+   {0x25, 0x00},
+   {0x26, 0x4d},
+
+   {0x27, 0x01},
+   {0x28, 0xce}, 
+   {0x29, 0x01},
+   {0x2a, 0xce}, 
+   {0x2b, 0x01},
+   {0x2c, 0xce}, 
+   {0x2d, 0x01},
+   {0x2e, 0xce}, 
+   {0x2f, 0x01},
+   {0x30, 0xce}, 
+   {0x31, 0x01},
+   {0x32, 0xce}, 
+   {0x33, 0x01},
+   {0x34, 0xce}, 
+   {0x3c, 0x10}, 
+   {0xfe, 0x00},
+   {0x44, 0x03},
+}
+
+function gc032aInit(cspiId,i2cId,speed,scanMode,onlyY)
+	local id = camera.init(cspiId,speed,1,1,2,1,0x00010101,onlyY,scanMode,640,480)
+	for i=1,#reg_table do
+		i2c.send(i2cId,0x21,reg_table[i],1)
+	end
+	camera.start(id)
+	return id
+end

+ 222 - 0
module/Air780EHM&EHV&EGH/demo/camera/spi_cam/main.lua

@@ -0,0 +1,222 @@
+PROJECT = "camera_30W_480_320_demo"
+VERSION = "4.0.0"
+-- 实际使用时选1个就行
+-- require "bf30a2"
+require "gc032a"
+-- require "gc0310"
+sys = require("sys")
+log.style(1)
+
+
+pm.ioVol(pm.IOVOL_ALL_GPIO, 3000)
+
+
+
+gpio.setup(2,1)--GPIO2打开给camera_3.3V供电
+
+-- 注意:V1.2的开发板需要打开GPIO28,V1.3的开发板需要打开GPIO29
+-- gpio.setup(28, 1) -- GPIO28打开给lcd电源供电 
+gpio.setup(29, 1) -- GPIO29打开给lcd电源供电 
+
+gpio.setup(14, nil)
+gpio.setup(15, nil)
+
+local SCAN_MODE = 0 -- 写1演示扫码(使用摄像头对二维码、条形码或其他类型的图案进行扫描和识别)
+local scan_pause = true -- 扫码启动与停止标志位
+local getRawStart = false
+local RAW_MODE = 0 -- 写1演示获取原始图像
+-- SCAN_MODE和RAW_MODE都没有写1就是拍照
+
+------------------------------------
+------------ 初始化 LCD ------------
+------------------------------------
+-- 根据不同的BSP返回不同的值
+-- spi_id,pin_reset,pin_dc,pin_cs,bl
+local function lcd_pin()
+    local rtos_bsp = rtos.bsp()
+    if string.find(rtos_bsp,"780EPM") then
+        return lcd.HWID_0, 36, 0xff, 0xff, 0xff -- 注意:EC718P有硬件lcd驱动接口, 无需使用spi,当然spi驱动也支持
+    else
+        log.info("main", "没找到合适的cat.1芯片",rtos_bsp)
+        return
+    end
+end
+local spi_id, pin_reset, pin_dc, pin_cs, bl = lcd_pin()
+if spi_id ~= lcd.HWID_0 then
+    spi_lcd = spi.deviceSetup(spi_id, pin_cs, 0, 0, 8, 20 * 1000 * 1000, spi.MSB, 1, 0)
+    port = "device"
+else
+    port = spi_id
+end
+
+
+lcd.init("st7796", {
+    port = port,
+    pin_dc = pin_dc,
+    pin_pwr = bl,
+    pin_rst = pin_reset,
+    direction = 0,
+    -- direction0 = 0x00,
+    w = 320,
+    h = 480,
+    xoffset = 0,
+    yoffset = 0,
+    sleepcmd = 0x10,
+    wakecmd = 0x11,
+})
+
+------------------------------------
+------------ 初始化串口 -------------
+------------------------------------
+local uartid = uart.VUART_0 -- 根据实际设备选取不同的uartid
+-- 初始化
+local result = uart.setup(uartid, -- 串口id
+600000, -- 波特率
+8, -- 数据位
+1 -- 停止位
+)
+
+------------------------------------
+----------- 初始化摄像头 -----------
+------------------------------------
+camera.on(0, "scanned", function(id, str)
+    if type(str) == 'string' then -- 如果是扫码模式(使用摄像头对二维码、条形码或其他类型的图案进行扫描和识别)
+        log.info("扫码结果", str)
+    elseif str == false then -- 如果摄像头没有正常工作
+        log.error("摄像头没有数据")
+    else -- 如果摄像头正常工作,并且不是扫码模式
+        log.info("摄像头数据", str)
+        sys.publish("capture done", true)
+    end
+end) -- 注册 camera 0 的 "scanned" 事件
+
+------------------------------------
+-------- 注册 boot 按键中断 ---------
+------------------------------------
+local function press_key()
+    log.info("boot press")
+    sys.publish("PRESS", true)
+end
+gpio.setup(0, press_key, gpio.PULLDOWN, gpio.RISING)
+gpio.debounce(0, 100, 1)
+local rawbuff, err
+if RAW_MODE ~= 1 then
+    -- 如果 RAW_MODE 不等于 1,创建一个大小为 60KB 的缓冲区
+    rawbuff, err = zbuff.create(60 * 1024, 0, zbuff.HEAP_AUTO)
+else
+    -- 如果 RAW_MODE 等于 1
+    rawbuff, err = zbuff.create(640 * 480 * 2, 0, zbuff.HEAP_AUTO) -- 创建一个大小为 640x480 像素,每个像素占用 2 字节的缓冲区,适用于 gc032a 摄像头
+    -- local rawbuff = zbuff.create(240 * 320 * 2, zbuff.HEAP_AUTO)  -- 创建一个大小为 240x320 像素,每个像素占用 2 字节的缓冲区,适用于 bf302a 摄像头
+end
+if rawbuff == nil then
+    log.info(err)
+end
+
+--------------------------------------------------
+---- 将文件系统中存储的jpg文件通过串口发送给电脑 ----
+--------------------------------------------------
+local function sendFile()
+    sys.taskInit(function()
+        local fileHandle = io.open("/testCamera.jpg","rb")
+        -- log.info("文件大小",fileHandle)
+        if not fileHandle then
+            log.error("打开文件失败")
+            return            
+        else
+            log.info("文件打开成功,文件大小为",io.fileSize("/testCamera.jpg"))
+        end
+
+        while true do
+            local data = fileHandle:read(1460)
+            -- log.info("data我看看",data)
+            if not data then break end
+            log.info("虚拟uart发送数据",uart.write(uartid, data))
+            sys.wait(10)
+            -- sys.waitUntil("UART_SENT2MCU_OK")
+        end
+        fileHandle:close()
+
+        os.remove("/testCamera.jpg") -- 删除文件
+    end)
+end
+
+sys.taskInit(function()
+    log.info("摄像头启动")
+
+    -- 初始化摄像头
+    local cspiId, i2cId = 1, 1 -- spi的id和摄像头的id
+    local camera_id
+    i2c.setup(i2cId, i2c.FAST) -- I2C1设置为快速模式,不开启上拉
+    gpio.setup(5, 0) -- 将 GPIO5 下拉,用于 SPI 片选信号
+    -- camera_id = bf30a2Init(cspiId,i2cId,25500000,SCAN_MODE,SCAN_MODE)
+    -- camera_id = gc0310Init(cspiId, i2cId, 25500000, SCAN_MODE, SCAN_MODE)
+    camera_id = gc032aInit(cspiId,i2cId,24000000,SCAN_MODE,SCAN_MODE) -- 通过 I2C1 配置摄像头,SPI1 时钟频率为 24 MHz
+    camera.stop(camera_id) -- 暂停摄像头捕获数据。仅停止了图像捕获,未影响预览功能。
+    camera.preview(camera_id, true) -- 打开LCD预览功能(直接将摄像头数据输出到LCD)
+
+    log.info("按下boot开始测试")
+    -- 总内存大小,单位字节;当前已使用的内存大小,单位字节;历史最高已使用的内存大小,单位字节
+    log.info(rtos.meminfo("sys")) -- 打印系统内存信息
+    log.info(rtos.meminfo("psram")) -- 打印PSRAM内存信息
+    while 1 do
+        result, data = sys.waitUntil("PRESS", 30 * 1000) -- 等待 "PRESS" 事件 30 秒(等待boot按键被按下)
+        if result == true and data == true then -- 如果 30 秒内检测到 "PRESS" 事件往下执行
+            if SCAN_MODE == 1 then
+                if scan_pause then
+                    log.info("启动扫码")
+                    -- camera_id = gc0310Init(cspiId,i2cId,25500000,SCAN_MODE,SCAN_MODE)
+                    camera.start(camera_id)
+                    scan_pause = false
+                    sys.wait(200)
+                    log.info(rtos.meminfo("sys"))
+                    log.info(rtos.meminfo("psram"))
+                else
+                    log.info("停止扫码")
+                    -- camera.close(camera_id)	--完全关闭摄像头才用这个
+                    camera.stop(camera_id)
+                    scan_pause = true
+                    sys.wait(200)
+                    log.info(rtos.meminfo("sys"))
+                    log.info(rtos.meminfo("psram"))
+                end
+            elseif RAW_MODE == 1 then -- 摄像头捕获原始数据
+                if getRawStart == false then
+                    getRawStart = true
+                    log.debug("摄像头首次捕获原始图像")
+                    camera.startRaw(camera_id, 640, 480, rawbuff) -- gc032a
+                    -- camera.startRaw(camera_id,240,320,rawbuff) --bf302a
+                else
+                    log.debug("摄像头继续捕获原始图像")
+                    camera.getRaw(camera_id)
+                end
+                result, data = sys.waitUntil("capture done", 30000)
+                log.info("摄像头捕获原始图像完成")
+                camera.stop(camera_id) -- 暂停摄像头捕获数据。仅停止了图像捕获,未影响预览功能。
+                log.info(rtos.meminfo("sys"))
+                log.info(rtos.meminfo("psram"))
+                -- uart.tx(uartid, rawbuff) --找个能保存数据的串口工具保存成文件就能在电脑上看了, 格式为JPG
+            else -- 拍照模式
+                log.debug("摄像头拍照")
+                -- camera_id = gc0310Init(cspiId,i2cId,25500000,SCAN_MODE,SCAN_MODE)
+                -- 将摄像头拍照的数据存入 "/testCamera.jpg" 文件中
+                -- jpeg压缩质量1最差,占用空间小,3最高,占用空间大,2和3需要非常多非常多的psram,尽量不要用
+                camera.capture(camera_id, "/testCamera.jpg", 1) -- 2和3需要非常多非常多的psram,尽量不要用
+                result, data = sys.waitUntil("capture done", 30000)
+                -- log.info(rawbuff:used())
+                -- camera.close(camera_id)	--完全关闭摄像头才用这个
+                camera.stop(camera_id) -- 暂停摄像头捕获数据。仅停止了图像捕获,未影响预览功能。
+                sendFile() -- 创建一个任务将摄像头数据通过串口发送到电脑
+                -- rawbuff:resize(60 * 1024)
+                -- log.info(rtos.meminfo("sys"))
+                -- log.info(rtos.meminfo("psram"))
+            end
+
+        end
+    end
+
+end)
+
+-- 用户代码已结束---------------------------------------------
+-- 结尾总是这一句
+sys.run()
+-- sys.run()之后后面不要加任何语句!!!!!

+ 73 - 0
module/Air780EHM&EHV&EGH/demo/can/main.lua

@@ -0,0 +1,73 @@
+PROJECT = "candemo"
+VERSION = "1.0.0"
+sys = require("sys")
+log.style(1)
+local SELF_TEST_FLAG = false --自测模式标识,写true就进行自收自发模式,写false就进行正常收发模式
+local node_a = true   -- A节点写true, B节点写false
+local can_id = 0
+local rx_id
+local tx_id
+local stb_pin = 28		-- stb引脚根据实际情况写,不用的话,也可以不写
+if node_a then          -- A/B节点区分,互相传输测试
+    rx_id = 0x12345678
+    tx_id = 0x12345677
+else
+    rx_id = 0x12345677
+    tx_id = 0x12345678
+end
+local test_cnt = 0
+local tx_buf = zbuff.create(8)  --创建zbuff
+local function can_cb(id, cb_type, param)
+    if cb_type == can.CB_MSG then
+        log.info("有新的消息")
+        local succ, id, id_type, rtr, data = can.rx(id)
+        while succ do
+            log.info(mcu.x32(id), #data, data:toHex())
+            succ, id, id_type, rtr, data = can.rx(id)
+        end
+    end
+    if cb_type == can.CB_TX then
+        if param then
+            log.info("发送成功")
+        else
+            log.info("发送失败")
+        end
+    end
+    if cb_type == can.CB_ERR then
+        log.info("CAN错误码", mcu.x32(param))
+    end
+    if cb_type == can.CB_STATE then
+        log.info("CAN新状态", param)
+    end
+end
+
+local function can_tx_test(data)
+    if node_a then
+        log.info("node a tx")
+    else
+        log.info("node b tx")
+    end
+	test_cnt = test_cnt + 1
+	if test_cnt > 8 then
+		test_cnt = 1
+	end
+	tx_buf:set(0,test_cnt)  --zbuff的类似于memset操作,类似于memset(&buff[start], num, len)
+	tx_buf:seek(test_cnt)   --zbuff设置光标位置(可能与当前指针位置有关;执行后指针会被设置到指定位置)
+    can.tx(can_id, tx_id, can.EXT, false, true, tx_buf)
+end
+-- can.debug(true)
+-- gpio.setup(stb_pin,0)   -- 配置STB引脚为输出低电平
+gpio.setup(stb_pin,1)	-- 如果开发板上STB信号有逻辑取反,则要配置成输出高电平
+can.init(can_id, 128)            -- 初始化CAN,参数为CAN ID,接收缓存消息数的最大值
+can.on(can_id, can_cb)            -- 注册CAN的回调函数
+can.timing(can_id, 1000000, 5, 4, 3, 2)     --CAN总线配置时序
+if SELF_TEST_FLAG then
+	can.node(can_id, tx_id, can.EXT)	-- 测试模式下,允许接收的ID和发送ID一致才会有新数据提醒
+	can.mode(can_id, can.MODE_TEST)     -- 如果只是自身测试硬件好坏,可以用测试模式来验证,如果发送成功就OK
+else
+	can.node(can_id, rx_id, can.EXT)
+	can.mode(can_id, can.MODE_NORMAL)   -- 一旦设置mode就开始正常工作了,此时不能再设置node,timing,filter等
+end
+
+sys.timerLoopStart(can_tx_test, 2000)
+sys.run()

+ 0 - 0
module/Air780EHV/demo/crypto/logo.jpg → module/Air780EHM&EHV&EGH/demo/crypto/logo.jpg


+ 0 - 0
module/Air780EHV/demo/crypto/main.lua → module/Air780EHM&EHV&EGH/demo/crypto/main.lua


+ 0 - 0
module/Air780EHV/demo/errDump/main.lua → module/Air780EHM&EHV&EGH/demo/errDump/main.lua


+ 51 - 0
module/Air780EHM&EHV&EGH/demo/fastlz/fastlz_test.lua

@@ -0,0 +1,51 @@
+--[[
+@module  fastlz_test
+@summary fastlz压缩与解压缩测试功能模块
+@version 1.0
+@date    2025.07.01
+@author  孟伟
+@usage
+使用Air780EHM演示压缩与解压缩的流程。
+]]
+
+function test_fastlz_func()
+    sys.wait(1000)
+    -- 原始数据
+    local originStr = io.readFile("/luadb/test.txt") or "q309pura;dsnf;asdouyf89q03fonaewofhaeop;fhiqp02398ryhai;ofinap983fyua0weo;ifhj3p908fhaes;iofaw789prhfaeiwop;fhaesp98fadsjklfhasklfsjask;flhadsfk"
+    local maxOut = #originStr
+    log.info("原始数据长度", #originStr)
+
+    -- 以压缩等级1 进行压缩
+    local L1 = fastlz.compress(originStr,1)
+    log.info("压缩等级1:压缩后的数据长度", #L1)
+
+    -- 解压
+    local dstr1 = fastlz.uncompress(L1,maxOut)
+    log.info("压缩等级1:解压后的的数据长度", #dstr1)
+    -- 判断解压后的数据是否与原始数据相同
+    if originStr == dstr1 then
+        log.info("压缩等级1:解压后的数据与原始数据相同")
+    else
+        log.info("压缩等级1:解压后的数据与原始数据不同")
+    end
+
+    sys.wait(1000)
+
+    -- 以压缩等级2 进行压缩
+    local L2 = fastlz.compress(originStr, 2)
+    log.info("压缩等级2:压缩后的数据长度", #L2)
+
+    -- 解压
+    local dstr2 = fastlz.uncompress(L2,maxOut)
+    log.info("压缩等级2:解压后的数据长度", #dstr2)
+
+    -- 判断解压后的数据是否与原始数据相同
+    if originStr == dstr2 then
+        log.info("压缩等级2:解压后的数据与原始数据相同")
+    else
+        log.info("压缩等级2:解压后的数据与原始数据不同")
+    end
+end
+--创建并且启动一个task
+--运行这个task的主函数test_fastlz_func
+sys.taskInit(test_fastlz_func)

+ 65 - 0
module/Air780EHM&EHV&EGH/demo/fastlz/main.lua

@@ -0,0 +1,65 @@
+--[[
+@module  main
+@summary LuatOS用户应用脚本文件入口,总体调度应用逻辑
+@version 1.0
+@date    2025.07.01
+@author  孟伟
+@usage
+本demo演示的功能为:
+实现使用Air780EHM来对文本/段落序列、原始像素数据序列或具有大量重复的任何其他数据块的快速压缩与解压缩。
+]]
+--[[
+必须定义PROJECT和VERSION变量,Luatools工具会用到这两个变量,远程升级功能也会用到这两个变量
+PROJECT:项目名,ascii string类型
+        可以随便定义,只要不使用,就行
+VERSION:项目版本号,ascii string类型
+        如果使用合宙iot.openluat.com进行远程升级,必须按照"XXX.YYY.ZZZ"三段格式定义:
+            X、Y、Z各表示1位数字,三个X表示的数字可以相同,也可以不同,同理三个Y和三个Z表示的数字也是可以相同,可以不同
+            因为历史原因,YYY这三位数字必须存在,但是没有任何用处,可以一直写为000
+        如果不使用合宙iot.openluat.com进行远程升级,根据自己项目的需求,自定义格式即可
+
+
+]]
+-- LuaTools需要PROJECT和VERSION这两个信息
+PROJECT = "FastLZ"
+VERSION = "001.000.000"
+
+--添加硬狗防止程序卡死
+if wdt then
+    wdt.init(9000)--初始化watchdog设置为9s
+    sys.timerLoopStart(wdt.feed, 3000)--3s喂一次狗
+end
+
+-- 如果内核固件支持errDump功能,此处进行配置,【强烈建议打开此处的注释】
+-- 因为此功能模块可以记录并且上传脚本在运行过程中出现的语法错误或者其他自定义的错误信息,可以初步分析一些设备运行异常的问题
+-- 以下代码是最基本的用法,更复杂的用法可以详细阅读API说明文档
+-- 启动errDump日志存储并且上传功能,600秒上传一次
+-- if errDump then
+--     errDump.config(true, 600)
+-- end
+
+
+-- 使用LuatOS开发的任何一个项目,都强烈建议使用远程升级FOTA功能
+-- 可以使用合宙的iot.openluat.com平台进行远程升级
+-- 也可以使用客户自己搭建的平台进行远程升级
+-- 远程升级的详细用法,可以参考fota的demo进行使用
+
+
+-- 启动一个循环定时器
+-- 每隔3秒钟打印一次总内存,实时的已使用内存,历史最高的已使用内存情况
+-- 方便分析内存使用是否有异常
+-- sys.timerLoopStart(function()
+--     log.info("mem.lua", rtos.meminfo())
+--     log.info("mem.sys", rtos.meminfo("sys"))
+-- end, 3000)
+
+
+--加载fastlz测试应用模块
+require "fastlz_test"
+
+
+
+-- 用户代码已结束---------------------------------------------
+-- 结尾总是这一句
+sys.run()
+-- sys.run()之后后面不要加任何语句!!!!!

+ 40 - 0
module/Air780EHM&EHV&EGH/demo/fastlz/readme.md

@@ -0,0 +1,40 @@
+
+## 演示功能概述
+
+将使用Air780EHM核心板,演示FastLZ的压缩与解压缩的使用方法,实现读取文件系统中的文件,并演示压缩与解压缩的代码实现。
+
+## 演示硬件环境
+
+1、Air780EHM核心板一块
+
+2、TYPE-C USB数据线一根
+
+3、Air780EHM核心板和数据线的硬件接线方式为
+
+- Air780EHM核心板通过TYPE-C USB口供电;(核心板USB旁边的开关拨到on一端)
+
+- TYPE-C USB数据线直接插到核心板的TYPE-C USB座子,另外一端连接电脑USB口;
+## 演示软件环境
+
+1、Luatools下载调试工具
+
+2、[Air780EHM V2007版本固件](https://gitee.com/openLuat/LuatOS/tree/master/module/Air780EHM/core)(理论上最新版本固件也可以,如果使用最新版本的固件不可以,可以烧录V2007固件对比验证)
+
+## 演示核心步骤
+
+1、搭建好硬件环境
+
+2、通过Luatools将demo与固件烧录到核心板中
+
+3、烧录好后,板子开机将会在Luatools上看到如下打印:
+
+```lua
+[2025-06-30 14:10:53.447][000000001.239] I/user.原始数据长度	14525
+[2025-06-30 14:10:53.469][000000001.241] I/user.压缩等级1:压缩后的数据长度	212
+[2025-06-30 14:10:53.484][000000001.242] I/user.压缩等级1:解压后的的数据长度	14525
+[2025-06-30 14:10:53.509][000000001.243] I/user.压缩等级1:解压后的数据与原始数据相同
+[2025-06-30 14:10:54.166][000000002.244] I/user.压缩等级2:压缩后的数据长度	114
+[2025-06-30 14:10:54.178][000000002.246] I/user.压缩等级2:解压后的数据长度	14525
+[2025-06-30 14:10:54.191][000000002.247] I/user.压缩等级2:解压后的数据与原始数据相同
+
+```

Разница между файлами не показана из-за своего большого размера
+ 0 - 0
module/Air780EHM&EHV&EGH/demo/fastlz/test.txt


+ 0 - 0
module/Air780EHV/demo/fota2/main.lua → module/Air780EHM&EHV&EGH/demo/fota2/main.lua


+ 0 - 0
module/Air780EHV/demo/fs/main.lua → module/Air780EHM&EHV&EGH/demo/fs/main.lua


+ 0 - 0
module/Air780EHV/demo/fskv/main.lua → module/Air780EHM&EHV&EGH/demo/fskv/main.lua


+ 0 - 0
module/Air780EHV/demo/ftp/main.lua → module/Air780EHM&EHV&EGH/demo/ftp/main.lua


+ 38 - 0
module/Air780EHM&EHV&EGH/demo/gpio/agpio_test.lua

@@ -0,0 +1,38 @@
+--[[
+@module  agpio_test
+@summary AGPIO测试模块
+@version 1.0
+@date    2025.07.01
+@author  Jensen
+@usage
+使用Air780EGH核心板测试对比AGPIO和普通GPIO进入休眠模式前后的区别
+本测试需测量核心板功耗,将板载USB旁边的开关拨到off一端,
+供电需通过Vbat外接合宙IOTpower或Air9000功耗分析仪的3.8V输出
+]]
+
+-- 定义AGPIO端口: GPIO27
+local agpio_number = 27
+-- 定义普通GPIO端口: GPIO01
+local normal_gpio_number = 1
+
+function test_agpio_func()
+
+    -- 配置AGPIO为输出模式,初始输出高电平
+    gpio.setup(agpio_number, 1)
+    -- 配置普通GPIO为输出模式,初始输出高电平
+    gpio.setup(normal_gpio_number, 1)
+    
+    sys.wait(16000)
+    -- 上电模式工作运行16s后关闭USB电源
+    pm.power(pm.USB, false)
+    -- 进入低功耗模式
+    pm.power(pm.WORK_MODE, 3)
+
+
+    -- 之后按rst键重新复位系统测试
+end
+
+
+--创建并且启动一个task
+--运行这个task的主函数 test_agpio_func
+sys.taskInit(test_agpio_func)

+ 43 - 0
module/Air780EHM&EHV&EGH/demo/gpio/gpio_input_test.lua

@@ -0,0 +1,43 @@
+--[[
+@module  gpio_input_test
+@summary GPIO输出测试模块
+@version 1.0
+@date    2025.07.01
+@author  Jensen
+@usage
+使用Air780EGH核心板测试GPIO输入功能,主要流程为获取指定IO口的输入电平,根据高电平状态,点亮外接LED灯;根据低电平状态,熄灭外接LED灯
+]]
+
+-- 配置外接LED灯的GPIO端口
+local led_io_number = 27
+
+-- 配置输入检测的GPIO端口
+local input_io_numble = 24
+
+function test_gpio_input_func()
+
+    local input_level
+    -- 配置LED GPIO为推挽输出模式,第二参数1表示初始为输出高电平
+    gpio.setup(led_io_number, 1)
+    -- 配置输入检测的GPIO为输入模式, 第二参数nil表示输入模式,第三参数nil表示浮空输入(未检测到电平时 电平状态不确定)
+    gpio.setup(input_io_numble, nil, nil)
+    -- 配置输入IO防抖动参数:50ms
+    gpio.debounce(input_io_numble, 50)
+    
+    while 1 do
+        -- 获取IO电平,并打印
+        input_level = gpio.get(input_io_numble) 
+        log.info("GPIO", "input level", input_level)
+        
+        -- 根据获取的电平来设置LED
+        gpio.set(led_io_number, input_level)
+        
+        -- 延时500ms,循环上面的流程
+        sys.wait(500)
+    end
+end
+
+
+--创建并且启动一个task
+--运行这个task的主函数 test_gpio_input_func
+sys.taskInit(test_gpio_input_func)

+ 36 - 0
module/Air780EHM&EHV&EGH/demo/gpio/gpio_irq_count_test.lua

@@ -0,0 +1,36 @@
+--[[
+@module  gpio_irq_test
+@summary GPIO中断计数测试模块
+@version 1.0
+@date    2025.07.01
+@author  Jensen
+@usage
+使用Air780EGH核心板测试GPIO中断计数功能,主要流程为配置指定PIN脚IO输出1KHz占空比50%的方波波形作为中断信号原,
+通过杜邦线连接到使能中断计数的IO管脚,定时统计中断触发的次数。
+]]
+
+
+-- 配置GPIO中断检测端口
+local irq_io_number = 24
+
+function test_gpio_irq_count_func()
+
+    -- PIN引脚16,配置PWM4输出波形,并作为信号源将其通过杜邦线连接到PIN引脚20(GPIO24)
+    -- 第一参数表示PWM channel4,第二参数表示频率为1000Hz,第三参数表示占空比为50%
+    pwm.open(4,1000,50)
+
+    -- 配置GPIO为中断计数模式, 第二参数为gpio.count表示中断计数模式,
+    gpio.setup(irq_io_number, gpio.count)
+    
+    --每隔1S统计一次中断触发的次数
+    while true do
+        sys.wait(1000)
+        log.info("irq cnt", gpio.count(irq_io_number))
+    end
+    
+end
+
+
+--创建并且启动一个task
+--运行这个task的主函数 test_gpio_irq_count_func
+sys.taskInit(test_gpio_irq_count_func)

+ 32 - 0
module/Air780EHM&EHV&EGH/demo/gpio/gpio_irq_test.lua

@@ -0,0 +1,32 @@
+--[[
+@module  gpio_irq_test
+@summary GPIO中断测试模块
+@version 1.0
+@date    2025.07.01
+@author  Jensen
+@usage
+使用Air780EGH核心板测试GPIO中断功能,主要流程为配置指定IO的触发模式,IO被触发时输出调试信息
+]]
+
+
+-- 配置GPIO中断检测端口
+local irq_io_number = 24
+
+function io_irq_handler(level, io_number)
+    log.info("gpio", io_number, "被触发", "level=", level)
+end
+
+function test_gpio_irq_func()
+
+    -- 配置GPIO为中断模式, 第二参数为function表示中断模式,
+    -- 第三参数表示内部上拉输入,第四参数表示下降沿触发中断
+    gpio.setup(irq_io_number, io_irq_handler, gpio.PULLUP, gpio.FALLING)
+    -- 配置输入IO防抖动参数:100ms
+    gpio.debounce(irq_io_number, 100)
+    
+end
+
+
+--创建并且启动一个task
+--运行这个task的主函数 test_gpio_irq_func
+sys.taskInit(test_gpio_irq_func)

+ 41 - 0
module/Air780EHM&EHV&EGH/demo/gpio/gpio_output_test.lua

@@ -0,0 +1,41 @@
+--[[
+@module  gpio_output_test
+@summary GPIO输出测试模块
+@version 1.0
+@date    2025.07.01
+@author  Jensen
+@usage
+使用Air780EGH核心板测试GPIO输出功能,主要流程为指定IO口外接LED灯,500ms输出高电平点亮LED,500ms输出低电平熄灭LED,循环执行这个流程
+]]
+
+-- 配置外接LED灯的GPIO端口
+local led_io_number = 27
+
+function test_gpio_output_func()
+    -- 定义运行计数器
+    local count = 0
+    
+    -- 配置GPIO为输出模式
+    gpio.setup(led_io_number, 1)
+    
+    while 1 do
+        -- 打印运行计数
+        log.info("GPIO", "Go Go Go", count, rtos.bsp())
+        
+        -- 点亮500ms
+        gpio.set(led_io_number, 1)
+        sys.wait(500)
+        
+        -- 熄灭500ms
+        gpio.set(led_io_number, 0)
+        sys.wait(500)
+        
+        -- 运行计数器累计加1
+        count = count + 1
+    end
+end
+
+
+--创建并且启动一个task
+--运行这个task的主函数 test_gpio_output_func
+sys.taskInit(test_gpio_output_func)

+ 40 - 0
module/Air780EHM&EHV&EGH/demo/gpio/gpio_pullupdown_test.lua

@@ -0,0 +1,40 @@
+--[[
+@module  gpio_pullupdown_test
+@summary GPIO输入的上拉下拉测试模块
+@version 1.0
+@date    2025.07.01
+@author  Jensen
+@usage
+使用Air780EGH核心板测试GPIO输入模式上拉和下拉模式的电平状态
+]]
+
+-- 定义输入上拉模式的端口GPIO7
+local gpio_pullup_number = 7
+-- 定义输入下拉模式的端口GPIO27
+local gpio_pulldown_number = 27
+
+function test_gpio_pullupdown_func()
+
+    -- 设置GPIO输入上拉模式
+    gpio.setup(gpio_pullup_number, nil, gpio.PULLUP)
+    -- 配置输入检测防抖50ms
+    gpio.debounce(gpio_pullup_number, 50)
+
+    -- 设置GPIO输入下拉模式
+    gpio.setup(gpio_pulldown_number, nil, gpio.PULLDOWN)
+    -- 配置输入检测防抖50ms
+    gpio.debounce(gpio_pulldown_number, 50)
+    
+    while 1 do
+        -- 打印获取端口当前的电平状态
+        log.info("GPIO",gpio_pullup_number,"电平",gpio.get(gpio_pullup_number))
+        log.info("GPIO",gpio_pulldown_number,"电平",gpio.get(gpio_pulldown_number))
+       
+        sys.wait(1000)
+    end
+end
+
+
+--创建并且启动一个task
+--运行这个task的主函数 test_gpio_pullupdown_func
+sys.taskInit(test_gpio_pullupdown_func)

+ 36 - 0
module/Air780EHM&EHV&EGH/demo/gpio/gpio_toggle_test.lua

@@ -0,0 +1,36 @@
+--[[
+@module  gpio_toggle_test
+@summary GPIO翻转测试模块
+@version 1.0
+@date    2025.07.01
+@author  Jensen
+@usage
+使用Air780EGH核心板测试GPIO的IO翻转时间,通过gpio.pulse输出指定脉冲变化的波形,使用示波器或逻辑分析仪来测量脉冲电平翻转的时间
+]]
+
+-- 配置输出pulse的GPIO端口
+local pulse_io_number = 27
+
+function test_gpio_toggle_func()
+
+    -- 配置GPIO为输出模式,初始输出低电平
+    gpio.setup(pulse_io_number, 0)
+    
+    while 1 do
+        -- 通过测试的GPIO27 输出指定的脉冲信号
+        -- 结合脉冲高低变化可以评估IO翻转时间,使用示波器或逻辑分析仪来测量电平翻转的时间
+        -- 第三参数表示输出8组电平变化,每组1或0表示高和低电平
+        -- 第二参数0xA9就是输出的电平高低状态,即 10101001
+        -- 第四参数表示每个电平的延时保持时间,0代表无延时
+        gpio.pulse(pulse_io_number, 0xA9, 8, 0)
+        
+        -- 打印运行打印信息
+        log.info("gpio----------->pulse")
+        sys.wait(100)
+    end
+end
+
+
+--创建并且启动一个task
+--运行这个task的主函数 test_gpio_toggle_func
+sys.taskInit(test_gpio_toggle_func)

+ 83 - 0
module/Air780EHM&EHV&EGH/demo/gpio/main.lua

@@ -0,0 +1,83 @@
+--[[
+@module  main
+@summary LuatOS用户应用脚本文件入口,总体调度应用逻辑
+@version 1.0
+@date    2025.07.01
+@author  Jensen
+@usage
+本demo演示的功能为:
+实现使用Air780EGH完成GPIO相关功能测试,包括GPIO的输入输出,中断检测/中断计数,翻转速度,上下拉测试与AGPIO测试
+]]
+--[[
+必须定义PROJECT和VERSION变量,Luatools工具会用到这两个变量,远程升级功能也会用到这两个变量
+PROJECT:项目名,ascii string类型
+        可以随便定义,只要不使用,就行
+VERSION:项目版本号,ascii string类型
+        如果使用合宙iot.openluat.com进行远程升级,必须按照"XXX.YYY.ZZZ"三段格式定义:
+            X、Y、Z各表示1位数字,三个X表示的数字可以相同,也可以不同,同理三个Y和三个Z表示的数字也是可以相同,可以不同
+            因为历史原因,YYY这三位数字必须存在,但是没有任何用处,可以一直写为000
+        如果不使用合宙iot.openluat.com进行远程升级,根据自己项目的需求,自定义格式即可
+
+
+]]
+-- LuaTools需要PROJECT和VERSION这两个信息
+PROJECT = "GPIO_TEST"
+VERSION = "001.000.000"
+
+--添加硬狗防止程序卡死
+if wdt then
+    wdt.init(9000)--初始化watchdog设置为9s
+    sys.timerLoopStart(wdt.feed, 3000)--3s喂一次狗
+end
+
+-- 如果内核固件支持errDump功能,此处进行配置,【强烈建议打开此处的注释】
+-- 因为此功能模块可以记录并且上传脚本在运行过程中出现的语法错误或者其他自定义的错误信息,可以初步分析一些设备运行异常的问题
+-- 以下代码是最基本的用法,更复杂的用法可以详细阅读API说明文档
+-- 启动errDump日志存储并且上传功能,600秒上传一次
+-- if errDump then
+--     errDump.config(true, 600)
+-- end
+
+
+-- 使用LuatOS开发的任何一个项目,都强烈建议使用远程升级FOTA功能
+-- 可以使用合宙的iot.openluat.com平台进行远程升级
+-- 也可以使用客户自己搭建的平台进行远程升级
+-- 远程升级的详细用法,可以参考fota的demo进行使用
+
+
+-- 启动一个循环定时器
+-- 每隔3秒钟打印一次总内存,实时的已使用内存,历史最高的已使用内存情况
+-- 方便分析内存使用是否有异常
+-- sys.timerLoopStart(function()
+--     log.info("mem.lua", rtos.meminfo())
+--     log.info("mem.sys", rtos.meminfo("sys"))
+-- end, 3000)
+
+
+-- 以下GPIO测试模块,测试时一次加载一个测试模块
+
+--GPIO输出测试
+require "gpio_output_test"
+
+--GPIO输入测试
+--require "gpio_input_test"
+
+--GPIO中断输入测试
+--require "gpio_irq_test"
+
+--GPIO中断计数测试
+--require "gpio_irq_count_test"
+
+--GPIO翻转速度测试
+--require "gpio_toggle_test"
+
+--GPIO上拉下拉测试
+--require "gpio_pullupdown_test"
+
+--AGPIO测试
+--require "agpio_test"
+
+-- 用户代码已结束---------------------------------------------
+-- 结尾总是这一句
+sys.run()
+-- sys.run()之后后面不要加任何语句!!!!!

+ 67 - 0
module/Air780EHM&EHV&EGH/demo/gpio/readme.md

@@ -0,0 +1,67 @@
+
+## 演示功能概述
+
+本demo使用Air780EGH核心板,演示GPIO接口功能测试,包括GPIO的输入输出,中断检测/中断计数,翻转速度,上下拉测试与AGPIO测试
+
+## 演示硬件环境
+
+1、Air780EHM核心板一块,TYPE-C USB数据线一根
+
+2、LED模块一个,独立按键模块一个,杜邦线若干
+
+3、合宙IOTpower 或 Air9000功耗分析仪 一台
+
+4、逻辑分析仪 或 示波器 一台
+
+5、万用表一台
+
+4、不同测试的引脚硬件连接介绍
+
+1)GPIO输出测试(gpio_output_test):(PIN16)GPIO27 外接LED模块
+
+2)GPIO输入测试(gpio_input_test): (PIN16)GPIO27 外接LED模块, (PIN20)GPIO24 杜邦线连接电源3.3V或GND
+
+3)GPIO中断输入测试(gpio_irq_test): (PIN20)GPIO24 杜邦线连接电源3.3V或GND
+
+4)GPIO中断计数测试(gpio_irq_count_test): (PIN16)PWM4 通过杜邦线与(PIN20)GPIO24相连接
+
+5)GPIO翻转速度测试(gpio_toggle_test): (PIN16)GPIO27 连接示波器或逻辑分析仪
+
+6)GPIO上拉下拉测试(gpio_pullupdown_test): (PIN56)GPIO07用于上拉输入,(PIN16)GPIO27用于下拉输入
+
+7)AGPIO测试(apio_test):  (PIN22)GPIO01, (PIN16)GPIO27 测试时分别连接示波器,核心板USB旁边的开关拨到off一端, Vbat连接合宙IOTpower或Air9000的"+", GND连接合宙IOTpower或Air9000的"-",合宙IOTpower或Air9000设置3.8V供电打开
+
+## 演示软件环境
+
+1、Luatools下载调试工具
+
+2、[Air780EHM V2007版本固件](https://docs.openluat.com/air780egh/luatos/firmware/version/)(理论上最新版本固件也可以,如果使用最新版本的固件不可以,可以烧录V2007固件对比验证)
+
+## 演示核心步骤
+
+1、搭建好硬件环境
+
+2、通过Luatools将demo与固件烧录到核心板中
+
+3、烧录好后,不同测试结果描述如下,具体详见相关文档 [Air780EGH GPIO](https://docs.openluat.com/air780egh/luatos/app/driver/gpio/)
+
+1)GPIO输出测试(gpio_output_test):LED模块500ms输出高电平点亮LED,500ms输出低电平熄灭LED,循环执行这个流程
+
+2)GPIO输入测试(gpio_input_test): 获取GPIO24电平状态,为高则LED点亮,为低则LED熄灭
+
+3)GPIO中断输入测试(gpio_irq_test): GPIO24杜邦线连接电源3.3V或GND,luatools中都会打印 "被触发" 的字段
+
+4)GPIO中断计数测试(gpio_irq_count_test): luatools中会打印测试结果
+
+> I/user irq count 2000  
+> I/user irq count 1999  
+> I/user irq count 2001  
+
+5)GPIO翻转速度测试(gpio_toggle_test): 逻辑分析仪或示波器测量(PIN16)GPIO27的IO高低电平变化 40-50ns左右
+
+6)GPIO上拉下拉测试(gpio_pullupdown_test): luatools中会打印测试结果
+
+> I/user GPIO  7 电平 1  
+> I/user GPIO  27 电平 0  
+
+7)AGPIO测试(apio_test):  正常工作模式,万用表测量(PIN22)GPIO01、(PIN16)GPIO27电平都为3.0V,进入低功耗模式时万用表测量(PIN22)GPIO01为0V, (PIN16)GPIO27保持3.0V不变

+ 0 - 0
module/Air780EHV/demo/helloworld/main.lua → module/Air780EHM&EHV&EGH/demo/helloworld/main.lua


+ 0 - 0
module/Air780EHV/demo/hmeta/main.lua → module/Air780EHM&EHV&EGH/demo/hmeta/main.lua


+ 0 - 0
module/Air780EHV/demo/http/luatos_uploadFile.txt → module/Air780EHM&EHV&EGH/demo/http/luatos_uploadFile.txt


+ 0 - 0
module/Air780EHV/demo/http/main.lua → module/Air780EHM&EHV&EGH/demo/http/main.lua


+ 41 - 0
module/Air780EHM&EHV&EGH/demo/i2c-aht10/main.lua

@@ -0,0 +1,41 @@
+
+-- LuaTools需要PROJECT和VERSION这两个信息
+PROJECT = "aht10demo"
+VERSION = "1.0.0"
+
+-- sys库是标配
+sys = require("sys")
+
+local aht10 = require "aht10"
+
+-- 接线
+--[[
+AHT10 --- 模块
+SDA   -   I2C_SDA
+SCL   -   I2C_SCL
+VCC   -   VDDIO
+GND   -   GND
+]]
+
+--电平设置为3.3v
+pm.ioVol(pm.IOVOL_ALL_GPIO, 3300)
+--设置gpio2输出,给camera_sda、camera_scl引脚提供上拉
+gpio.setup(2, 1)
+
+i2cid = 1
+i2c_speed = i2c.FAST
+
+sys.taskInit(function()
+    i2c.setup(i2cid,i2c_speed)
+    aht10.init(i2cid)--初始化,传入i2c_id
+    while 1 do
+        local aht10_data = aht10.get_data()
+        log.info("aht10_data", "aht10_data.RH:"..(aht10_data.RH*100).."%","aht10_data.T"..(aht10_data.T).."℃")
+        sys.wait(1000)
+    end
+end)
+
+-- 用户代码已结束---------------------------------------------
+-- 结尾总是这一句
+sys.run()
+-- sys.run()之后后面不要加任何语句!!!!!

+ 70 - 0
module/Air780EHM&EHV&EGH/demo/i2c-sht20/hw_i2c_sht20_test.lua

@@ -0,0 +1,70 @@
+--[[
+@module  hw_i2c_sht20_test
+@summary 硬件I2C读取SHT20测试
+@version 1.0
+@date    2025.07.01
+@author  Jensen
+@usage
+使用Air780EGH核心板通过硬件I2C去读取SHT20温湿度传感器的过程,并介绍luatos中I2C相关接口的用法。
+]]
+
+--[[
+SHT20 --- 模块
+SDA   -   I2C1_SDA PIN67
+SCL   -   I2C1_SCL PIN66
+VCC   -   3.3V
+GND   -   GND
+
+注意这里需要使用luatIO配置工具配置对应管脚功能,详见pins_Air780EGH.json
+]]
+
+
+-- 使用硬件I2C通道 1
+local i2c_hwid = 1
+
+--0100 0000  SHT20传感器七位地址
+local addr = 0x40
+    
+function test_hw_i2c_sht20_func()
+
+    local tmp,hum -- 原始数据
+    local temp,hump -- 真实值
+    
+    --初始化硬件I2C
+    local ret = i2c.setup(i2c_hwid)
+    log.info("i2c".. i2c_hwid, "hw i2c initial",  ret)
+    
+    while 1 do
+        --发送0xF3来查询温度
+        i2c.send(i2c_hwid, addr, string.char(0xF3)) 
+        sys.wait(100)
+        --读取传感器的温度值
+        tmp = i2c.recv(i2c_hwid, addr, 2)  
+        log.info("SHT20", "read tem data", tmp:toHex())
+        
+        --发送0xF5来查询湿度
+        i2c.send(i2c_hwid, addr, string.char(0xF5)) 
+        sys.wait(100)
+        --读取传感器湿度值
+        hum = i2c.recv(i2c_hwid, addr, 2) 
+        log.info("SHT20", "read hum data", hum:toHex())
+        
+        --提取一个按照大端字节序编码的16位无符号整数
+        local _,tval = pack.unpack(tmp,'>H') 
+        local _,hval = pack.unpack(hum,'>H')
+        --log.info("SHT20", "tval hval", tval,hval)
+        if tval and hval then
+            --按照传感器手册来计算对应的温湿度
+            temp = (((17572 * tval) >> 16) - 4685)/100
+            hump = (((12500 * hval) >> 16) - 600)/100
+            log.info("SHT20", "temp,humi",string.format("%.2f",temp),string.format("%.2f",hump))
+        end
+        
+        sys.wait(1000)
+    end
+end
+
+
+--创建并且启动一个task
+--运行这个task的主函数 test_hw_i2c_sht20_func
+sys.taskInit(test_hw_i2c_sht20_func)

+ 70 - 0
module/Air780EHM&EHV&EGH/demo/i2c-sht20/main.lua

@@ -0,0 +1,70 @@
+--[[
+@module  main
+@summary LuatOS用户应用脚本文件入口,总体调度应用逻辑
+@version 1.0
+@date    2025.07.01
+@author  Jensen
+@usage
+本demo演示的功能为:
+实现使用Air780EGH,分别通过硬件I2C和软件I2C测试读取SHT20传感器数据
+]]
+--[[
+必须定义PROJECT和VERSION变量,Luatools工具会用到这两个变量,远程升级功能也会用到这两个变量
+PROJECT:项目名,ascii string类型
+        可以随便定义,只要不使用,就行
+VERSION:项目版本号,ascii string类型
+        如果使用合宙iot.openluat.com进行远程升级,必须按照"XXX.YYY.ZZZ"三段格式定义:
+            X、Y、Z各表示1位数字,三个X表示的数字可以相同,也可以不同,同理三个Y和三个Z表示的数字也是可以相同,可以不同
+            因为历史原因,YYY这三位数字必须存在,但是没有任何用处,可以一直写为000
+        如果不使用合宙iot.openluat.com进行远程升级,根据自己项目的需求,自定义格式即可
+
+
+]]
+-- LuaTools需要PROJECT和VERSION这两个信息
+PROJECT = "I2C_SHT20_TEST"
+VERSION = "001.000.000"
+
+--添加硬狗防止程序卡死
+if wdt then
+    wdt.init(9000)--初始化watchdog设置为9s
+    sys.timerLoopStart(wdt.feed, 3000)--3s喂一次狗
+end
+
+-- 如果内核固件支持errDump功能,此处进行配置,【强烈建议打开此处的注释】
+-- 因为此功能模块可以记录并且上传脚本在运行过程中出现的语法错误或者其他自定义的错误信息,可以初步分析一些设备运行异常的问题
+-- 以下代码是最基本的用法,更复杂的用法可以详细阅读API说明文档
+-- 启动errDump日志存储并且上传功能,600秒上传一次
+-- if errDump then
+--     errDump.config(true, 600)
+-- end
+
+
+-- 使用LuatOS开发的任何一个项目,都强烈建议使用远程升级FOTA功能
+-- 可以使用合宙的iot.openluat.com平台进行远程升级
+-- 也可以使用客户自己搭建的平台进行远程升级
+-- 远程升级的详细用法,可以参考fota的demo进行使用
+
+
+-- 启动一个循环定时器
+-- 每隔3秒钟打印一次总内存,实时的已使用内存,历史最高的已使用内存情况
+-- 方便分析内存使用是否有异常
+-- sys.timerLoopStart(function()
+--     log.info("mem.lua", rtos.meminfo())
+--     log.info("mem.sys", rtos.meminfo("sys"))
+-- end, 3000)
+
+--电平设置为3.3v
+pm.ioVol(pm.IOVOL_ALL_GPIO, 3300)
+
+-- 以下测试模块,测试时一次加载一个测试模块
+
+-- 硬件I2C测试模块
+require "hw_i2c_sht20_test"
+-- 软件I2C测试模块
+--require "soft_i2c_sht20_test"
+
+
+-- 用户代码已结束---------------------------------------------
+-- 结尾总是这一句
+sys.run()
+-- sys.run()之后后面不要加任何语句!!!!!

+ 52 - 0
module/Air780EHM&EHV&EGH/demo/i2c-sht20/pins_Air780EGH.json

@@ -0,0 +1,52 @@
+{
+  "model": "Air780EGH",
+  "pins": [
+    [7, "PWR_KEY", ""],
+    [16, "GPIO27", ""],
+    [17, "UART1_RXD", ""],
+    [18, "UART1_TXD", ""],
+    [19, "GPIO22", ""],
+    [20, "PWM1", ""],
+    [22, "PWM0", ""],
+    [23, "ONEWIRE", ""],
+    [25, "CAN_TXD", ""],
+    [26, "PWM4", ""],
+    [28, "UART2_RXD", ""],
+    [29, "UART2_TXD", ""],
+    [30, "GPIO29", ""],
+    [31, "GPIO30", ""],
+    [32, "GPIO31", ""],
+    [33, "GPIO32", ""],
+    [38, "DBG_RXD", ""],
+    [39, "DBG_TXD", ""],
+    [49, "LCD_RST", ""],
+    [50, "LCD_SDA", ""],
+    [51, "LCD_RS", ""],
+    [52, "LCD_CS", ""],
+    [53, "LCD_CLK", ""],
+    [54, "CAM_MCLK", ""],
+    [55, "CAM_RX0", ""],
+    [56, "CAM_RX1", ""],
+    [57, "I2C0_SCL", "用于测试硬件I2C0-SCL"],
+    [58, "I2C0_SDA", "用于测试硬件I2C0-SDA"],
+    [61, "VBUS", ""],
+    [66, "I2C1_SDA", "用于测试硬件I2C1-SDA"],
+    [67, "I2C1_SCL", "用于测试硬件I2C1-SCL"],
+    [78, "GPIO28", ""],
+    [79, "USIM_DET", ""],
+    [80, "CAM_BCLK", ""],
+    [81, "CAM_CS", ""],
+    [82, "USB_BOOT", ""],
+    [83, "SPI0_CS", ""],
+    [84, "SPI0_MISO", ""],
+    [85, "SPI0_MOSI", ""],
+    [86, "SPI0_CLK", ""],
+    [97, "GPIO16", "用于测试软件I2C-SCL"],
+    [99, "GPIO23", ""],
+    [100, "GPIO17", "用于测试软件I2C-SDA"],
+    [101, "WAKEUP0", ""],
+    [102, "GPIO20", ""],
+    [106, "CAN_RXD", ""],
+    [107, "GPIO21", ""]
+  ]
+}

+ 59 - 0
module/Air780EHM&EHV&EGH/demo/i2c-sht20/readme.md

@@ -0,0 +1,59 @@
+
+## 演示功能概述
+
+本demo使用Air780EGH核心板,演示通过I2C协议接口来读取SHT20传感器数据,分别以硬件I2C和软件I2C的方式来做演示
+
+## 演示硬件环境
+
+1、Air780EHM核心板一块,TYPE-C USB数据线一根
+
+2、SHT20模块一个,杜邦线若干
+
+3、Air780EHM核心板和SHT20模块硬件连接
+
+硬件I2C测试连线:
+
+核心板                   SHT20模块
+GND              <--->  GND
+3.3V             <--->  3.3V
+(PIN67)I2C1_SCL  <--->  SCL
+(PIN66)I2C1_SDA  <--->  SDA
+
+软件I2C测试连线:
+
+核心板                   SHT20模块
+GND              <--->  GND
+3.3V             <--->  3.3V
+(PIN97)GPIO16    <--->  SCL
+(PIN100)GPIO17   <--->  SDA
+
+4、Air780EGH核心板通过TYPE-C USB口供电;(核心板USB旁边的开关拨到on一端)
+
+## 演示软件环境
+
+1、Luatools下载调试工具
+
+2、[Air780EGH 最新版本固件](https://docs.openluat.com/air780egh/luatos/firmware/version/)
+
+## 演示核心步骤
+
+1、搭建好硬件环境
+
+2、通过Luatools将demo与固件烧录到核心板中
+
+3、烧录好后,查看Luatools中打印的运行日志,具体详见相关文档 [Air780EGH I2C](https://docs.openluat.com/air780egh/luatos/app/driver/i2c/)
+
+硬件I2C通信成功日志如下所示:
+
+> I2C_MasterSetup 426:I2C1, Total 260 HCNT 113 LCNT 136  
+> I/user.i2c   initial 1  
+> I/user.SHT20 read tem data 70C8  4  
+> I/user.SHT20 read hum data A73A  4  
+> I/user.SHT20 temp,humi   30.56000    75.65000  
+
+软件I2C通信成功日志如下所示:
+
+> I/user.i2c    sw i2c initial    EI2C*: 0C7F7740
+> I/user.SHT20 read tem data 70C8  4  
+> I/user.SHT20 read hum data A73A  4  
+> I/user.SHT20 temp,humi   30.56000    75.65000

+ 71 - 0
module/Air780EHM&EHV&EGH/demo/i2c-sht20/soft_i2c_sht20_test.lua

@@ -0,0 +1,71 @@
+--[[
+@module  soft_i2c_sht20_test
+@summary 软件I2C读取SHT20测试
+@version 1.0
+@date    2025.07.01
+@author  Jensen
+@usage
+使用Air780EGH核心板通过软件I2C去读取SHT20温湿度传感器的过程,并介绍luatos中I2C相关接口的用法。
+]]
+
+--[[
+SHT20 --- 模块
+SDA   -   I2C_SDA GPIO17 PIN100
+SCL   -   I2C_SCL GPIO16 PIN97
+VCC   -   3.3V
+GND   -   GND
+
+注意这里需要使用luatIO配置工具配置对应管脚功能,详见pins_Air780EGH.json
+]]
+
+-- 定义软件I2C-SCL
+local io_scl = 16
+-- 定义软件I2C-SDA
+local io_sda = 17
+
+--0100 0000  SHT20传感器七位地址
+local addr = 0x40
+    
+function test_soft_i2c_sht20_func()
+
+    local tmp,hum -- 原始数据
+    local temp,hump -- 真实值
+    
+    --初始化软件I2C, 返回参数为软件I2C的实例,后续通过该实例来操作i2c的读写操作
+    local softI2C = i2c.createSoft(io_scl,io_sda)
+    log.info("i2c", "sw i2c initial",  softI2C)
+    
+    while 1 do
+        --发送0xF3来查询温度
+        i2c.send(softI2C, addr, string.char(0xF3)) 
+        sys.wait(100)
+        --读取传感器的温度值
+        tmp = i2c.recv(softI2C, addr, 2)  
+        log.info("SHT20", "read tem data", tmp:toHex())
+        
+        --发送0xF5来查询湿度
+        i2c.send(softI2C, addr, string.char(0xF5)) 
+        sys.wait(100)
+        --读取传感器湿度值
+        hum = i2c.recv(softI2C, addr, 2) 
+        log.info("SHT20", "read hum data", hum:toHex())
+        
+        --提取一个按照大端字节序编码的16位无符号整数
+        local _,tval = pack.unpack(tmp,'>H') 
+        local _,hval = pack.unpack(hum,'>H')
+        --log.info("SHT20", "tval hval", tval,hval)
+        if tval and hval then
+            --按照传感器手册来计算对应的温湿度
+            temp = (((17572 * tval) >> 16) - 4685)/100
+            hump = (((12500 * hval) >> 16) - 600)/100
+            log.info("SHT20", "temp,humi",string.format("%.2f",temp),string.format("%.2f",hump))
+        end
+        
+        sys.wait(1000)
+    end
+end
+
+
+--创建并且启动一个task
+--运行这个task的主函数 test_soft_i2c_sht20_func
+sys.taskInit(test_soft_i2c_sht20_func)

+ 0 - 0
module/Air780EHV/demo/i2c/aht10_test.lua → module/Air780EHM&EHV&EGH/demo/i2c/aht10_test.lua


+ 0 - 0
module/Air780EHV/demo/i2c/main.lua → module/Air780EHM&EHV&EGH/demo/i2c/main.lua


+ 0 - 0
module/Air780EHV/demo/i2c/readme.md → module/Air780EHM&EHV&EGH/demo/i2c/readme.md


+ 0 - 0
module/Air780EHV/demo/iconv/main.lua → module/Air780EHM&EHV&EGH/demo/iconv/main.lua


+ 0 - 0
module/Air780EHV/demo/iotcloud/aliyun/示例1 一型一密(免预注册,但需要是企业版实例平台)方式连接云平台/main.lua → module/Air780EHM&EHV&EGH/demo/iotcloud/aliyun/示例1 一型一密(免预注册,但需要是企业版实例平台)方式连接云平台/main.lua


+ 0 - 0
module/Air780EHV/demo/iotcloud/aliyun/示例2 一型一密(预注册)方式连接云平台/main.lua → module/Air780EHM&EHV&EGH/demo/iotcloud/aliyun/示例2 一型一密(预注册)方式连接云平台/main.lua


+ 0 - 0
module/Air780EHV/demo/iotcloud/aliyun/示例3 一机一密方式连接云平台/main.lua → module/Air780EHM&EHV&EGH/demo/iotcloud/aliyun/示例3 一机一密方式连接云平台/main.lua


+ 0 - 0
module/Air780EHV/demo/iotcloud/baiduiot/main.lua → module/Air780EHM&EHV&EGH/demo/iotcloud/baiduiot/main.lua


+ 0 - 0
module/Air780EHV/demo/iotcloud/huaweiiot/main.lua → module/Air780EHM&EHV&EGH/demo/iotcloud/huaweiiot/main.lua


+ 0 - 0
module/Air780EHV/demo/iotcloud/onenet/main.lua → module/Air780EHM&EHV&EGH/demo/iotcloud/onenet/main.lua


+ 0 - 0
module/Air780EHV/demo/iotcloud/tencentiot/main.lua → module/Air780EHM&EHV&EGH/demo/iotcloud/tencentiot/main.lua


+ 0 - 0
module/Air780EHV/demo/iotcloud/tlink/main.lua → module/Air780EHM&EHV&EGH/demo/iotcloud/tlink/main.lua


+ 0 - 0
module/Air780EHV/demo/iotcloud/tuyaiot/示例1 一机一密/main.lua → module/Air780EHM&EHV&EGH/demo/iotcloud/tuyaiot/示例1 一机一密/main.lua


+ 0 - 0
module/Air780EHV/demo/json/main.lua → module/Air780EHM&EHV&EGH/demo/json/main.lua


Некоторые файлы не были показаны из-за большого количества измененных файлов