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

add:新增Air780EHX系列搭配AirLCD_1000使用LCD核心库开发和按键操控demo

江访 1 месяц назад
Родитель
Сommit
21a4442adb

BIN
module/Air8000/demo/accessory_board/AirLCD_1000/lcd/font_drv/customer_font_24.bin


+ 16 - 0
module/Air8000/demo/accessory_board/AirLCD_1000/lcd/font_drv/customer_font_drv.lua

@@ -0,0 +1,16 @@
+--[[ 
+说明:
+customer_font_drv是用户外部自定义外部点阵字体驱动功能模块,因为不需要进行初始化,所以本文件没有任何实质代码,只在此处描述在项目中如何使用。
+自定义字体制作说明可以参考lcd核心库自定义字体制作说明:https://docs.openluat.com/osapi/core/lcd/#_6
+1、通过链接 https://gitee.com/Dozingfiretruck/u8g2_font_tool 下载字体文件制作工具
+2、制作字体
+   - 将.ttf和.otf格式字体加载到制作工具内
+   - 选择自定义,输入需要生成的字体内容,调用自定义文字显示接口只能显示所输入的内容,其他内容需要切换支持的字体
+   - 选择其他,则会按苏哦选编码格式生成对应的字体
+   - 设置字体大小,生成合宙lcd核心库可加载的.bin格式的字体文件
+3、使用lcd.setFontFile(font)接口设置
+   - 其中font为字体文件路径
+   - 若将生成的字体文件命名为customer_font_24.bin 并通过luatools工具同代码一起烧录到脚本分区,则设置接口为lcd.setFontFile("/luadb/customer_font_24.bin")
+   - 若将生成的字体文件命名为customer_font_24.bin 并通过luatools工具同固件和代码一起烧录到文件系统,则设置接口为lcd.setFontFile("/customer_font_24.bin")
+4、使用lcd.drawStr(x,y,str,fg_color)接口显示具体内容
+]]

+ 49 - 0
module/Air8000/demo/accessory_board/AirLCD_1000/lcd/font_drv/gtfont_drv.lua

@@ -0,0 +1,49 @@
+--[[
+@module  gtfont_drv
+@summary GTFont矢量字库驱动模块
+@version 1.0
+@date    2025.12.3
+@author  江访
+@usage
+本模块为GTFont矢量字库驱动功能模块,主要功能包括:
+1、初始化AirFONTS_1000矢量字库小板的SPI接口;
+2、配置SPI通信参数和设备对象;
+3、初始化矢量字库核心功能;
+
+
+说明:
+1、gtfont核心库演示demo,是使用gtfont核心库来驱动合宙AirFONTS_1000矢量字库小板
+2、在主程序mian.lua中require "gtfont_drv"即可执行加载本demo内的演示代码
+3、通过使用gtfont_drv.init()对合宙AirFONTS_1000矢量字库小板进行初始化
+4、通过使用 lcd.drawGtfontUtf8Gray(str,size,gray,x,y)接口在lcd屏幕上灰度显示 UTF8 字符串,支持10-192号字体
+-- 在main.lua中require本模块即可自动初始化
+require "gtfont_drv"
+]]
+
+--[[
+初始化AirFONTS_1000矢量字库小板;
+配置SPI接口和矢量字库;
+
+@api init()
+@summary 初始化AirFONTS_1000矢量字库小板
+@return bool 成功返回true,失败返回false
+@usage
+
+]]
+local function init()
+    --创建一个SPI设备对象
+    gtfont_spi = spi.deviceSetup(1 , 12, 0, 0, 8, 20*1000*1000, spi.MSB, 1, 0)
+    log.error("AirFONTS_1000.init", "spi.deviceSetup", type(gtfont_spi))
+    --检查SPI设备对象是否创建成功
+    if type(gtfont_spi) ~= "userdata" then
+        log.error("AirFONTS_1000.init", "spi.deviceSetup error", type(gtfont_spi))
+    end
+
+    --初始化矢量字库
+    if not gtfont.init(gtfont_spi) then
+        log.error("gtfont_drv.init", "gtfont_drv.init error")
+    end
+
+end
+
+init()

+ 1 - 0
module/Air8000/demo/accessory_board/AirLCD_1000/lcd/font_drv/hzfont_drv.lua

@@ -0,0 +1 @@
+-- hzfont 是合宙开发的一个内置矢量字体库,目前正在开发中

BIN
module/Air8000/demo/accessory_board/AirLCD_1000/lcd/images/logo.jpg


+ 52 - 0
module/Air8000/demo/accessory_board/AirLCD_1000/lcd/lcd_drv/exlcd_drv.lua

@@ -0,0 +1,52 @@
+--[[
+@module  exlcd_drv
+@summary 扩展LCD显示驱动模块,基于exlcd扩展库
+@version 1.0
+@date    2025.12.3
+@author  江访
+@usage
+本模块为扩展LCD显示驱动功能模块,主要功能包括:
+1、初始化AirLCD_1000扩展LCD显示;
+2、配置显示缓冲区和自动刷新设置;
+
+对外接口:
+1、exlcd_drv.init():初始化扩展LCD显示驱动
+如果需要实现背光亮度调节,参考exlcd扩展库中的exlcd.set_bl(level)进行设置
+]]
+
+local exlcd = require "exlcd"
+
+local exlcd_drv = {}
+
+--[[
+初始化扩展LCD显示驱动;
+
+@api exlcd_drv.init()
+@summary 配置并初始化AirLCD_1000扩展LCD显示
+@return boolean 初始化成功返回true,失败返回false
+
+@usage
+-- 初始化扩展LCD显示
+local result = exlcd_drv.init({})
+if result then
+    log.info("扩展LCD初始化成功")
+else
+    log.error("扩展LCD初始化失败")
+end
+]]
+
+function exlcd_drv.init()
+    local result = exlcd.init({lcd_model = "AirLCD_1000"})
+
+    log.info("exlcd.init", result)
+
+    if result then
+        -- 显示设置
+        lcd.setupBuff(nil, true)
+        lcd.autoFlush(false)
+    end
+
+    return result
+end
+
+return exlcd_drv

+ 80 - 0
module/Air8000/demo/accessory_board/AirLCD_1000/lcd/lcd_drv/lcd_drv.lua

@@ -0,0 +1,80 @@
+--[[
+@module  lcd_drv
+@summary LCD显示驱动模块,基于lcd核心库
+@version 1.0
+@date    2025.12.3
+@author  江访
+@usage
+本模块为LCD显示驱动功能模块,主要功能包括:
+1、初始化AirLCD_1000 显示IC ST7796;
+2、配置LCD显示参数和显示缓冲区;
+3、支持多种屏幕方向和分辨率设置;
+
+对外接口:
+1、lcd_drv.init():初始化LCD显示驱动
+]]
+
+
+local lcd_drv = {}
+
+--[[
+初始化LCD显示驱动;
+
+@api lcd_drv.init()
+@summary 配置并初始化ST7796 LCD控制器
+@return boolean 初始化成功返回true,失败返回false
+
+@usage
+-- 初始化LCD显示
+local result = lcd_drv.init()
+if result then
+    log.info("LCD初始化成功")
+else
+    log.error("LCD初始化失败")
+end
+]]
+
+function lcd_drv.init()
+    local result = lcd.init("st7796",
+        {
+            pin_rst = 36,                          -- 复位引脚
+            pin_pwr = 1,                           -- 背光控制引脚GPIO的ID号
+            port = lcd.HWID_0,                     -- 驱动端口
+            -- pin_dc = 0xFF,                      -- lcd数据/命令选择引脚GPIO ID号,使用lcd 专用 SPI 接口 lcd.HWID_0不需要填此参数,使用通用SPI接口需要赋值
+            direction = 0,                         -- lcd屏幕方向 0:0° 1:90° 2:180° 3:270°,屏幕方向和分辨率保存一致
+            w = 320,                               -- lcd 水平分辨率
+            h = 480,                               -- lcd 竖直分辨率
+            xoffset = 0,                           -- x偏移(不同屏幕ic 不同屏幕方向会有差异)
+            yoffset = 0,                           -- y偏移(不同屏幕ic 不同屏幕方向会有差异)
+            sleepcmd = 0X10,                       -- 睡眠命令,默认0X10
+            wakecmd = 0X11,                        -- 唤醒命令,默认0X11
+            -- bus_speed = 50*1000*1000,                            -- SPI总线速度,不填默认50M,若速率要求更高需要进行设置
+            -- interface_mode = lcd.WIRE_4_BIT_8_INTERFACE_I,       -- lcd模式,默认lcd.WIRE_4_BIT_8_INTERFACE_I
+            -- direction0 = {0x36,0x00},                            -- 0°方向的命令,(不同屏幕ic会有差异)
+            -- direction90 = {0x36,0x60},                           -- 90°方向的命令,(不同屏幕ic会有差异)
+            -- direction180 ={0x36,0xc0} ,                          -- 180°方向的命令,(不同屏幕ic会有差异)
+            -- direction270 = {0x36,0xA0},                          -- 270°方向的命令,(不同屏幕ic会有差异)
+            -- hbp = nil,                                           -- 水平后廊
+            -- hspw = nil,                                          -- 水平同步脉冲宽度
+            -- hfp = 0,                                             -- 水平前廊
+            -- vbp = 0,                                             -- 垂直后廊
+            -- vspw = 0,                                            -- 垂直同步脉冲宽度
+            -- vfp = 0,                                             -- 垂直前廊
+            -- initcmd = nil,                                       -- 自定义屏幕初始化命令表
+            -- flush_rate = nil,                                    -- 刷新率
+            -- spi_dev = nil,                                       -- spi设备,当port = "device"时有效,当port ≠ "device"时可不填或者填nil
+            -- init_in_service = false,                             -- 允许初始化在lcd service里运行,在后台初始化LCD,默认是false,Air8000/G/W/T/A、Air780EHM/EGH/EHV 支持填true,可加快初始化速度,默认SPI总线速度80M
+        })
+
+    log.info("lcd.init", result)
+
+    if result then
+        -- 显示设置
+        lcd.setupBuff(nil, true)
+        lcd.autoFlush(false)
+    end
+
+    return result
+end
+
+return lcd_drv

+ 113 - 0
module/Air8000/demo/accessory_board/AirLCD_1000/lcd/main.lua

@@ -0,0 +1,113 @@
+--[[
+@module  main
+@summary LuatOS用户应用脚本文件入口,总体调度应用逻辑
+@version 1.0
+@date    2025.12.3
+@author  江访
+@usage
+本demo演示的核心功能为:
+本demo演示的核心功能为:
+1、LCD显示屏驱动初始化,支持多种LCD驱动模式;
+2、按键驱动初始化,支持BOOT键和PWR键操作;
+3、字库驱动管理,支持外部矢量字库、内部软件矢量字库和外部自定义点阵字库;
+4、用户界面主循环,实现多页面切换和按键事件处理;
+5、系统看门狗配置,确保系统稳定运行;
+
+更多说明参考本目录下的readme.md文件
+]]
+
+--[[
+必须定义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进行远程升级,根据自己项目的需求,自定义格式即可
+]]
+
+-- main.lua - 程序入口文件
+
+-- 定义项目名称和版本号
+PROJECT = "ui_demo" -- 项目名称
+VERSION = "001.000.000"    -- 版本号
+
+-- 在日志中打印项目名和项目版本号
+log.info("ui_demo", PROJECT, VERSION)
+
+-- 设置日志输出风格为样式2(建议调试时开启)
+-- log.style(2)
+
+-- 如果内核固件支持wdt看门狗功能,此处对看门狗进行初始化和定时喂狗处理
+-- 如果脚本程序死循环卡死,就会无法及时喂狗,最终会自动重启
+if wdt then
+    --配置喂狗超时时间为9秒钟
+    wdt.init(9000)
+    --启动一个循环定时器,每隔3秒钟喂一次狗
+    sys.timerLoopStart(wdt.feed, 3000)
+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)
+
+
+-- 加载显示屏驱动管理功能模块,有以下两种:
+-- 1、使用lcd核心库驱动的lcd_drv.lua
+-- 2、使用exlcd扩展库驱动的exlcd_drv.lua
+-- 根据自己的需求,启用两者中的任何一种都可以
+-- 也可以不启用任何一种,不使用显示屏功能
+lcd_drv = require "lcd_drv"
+-- lcd_drv = require "exlcd_drv"
+
+
+-- 加载按键驱动管理功能模块
+key_drv = require "key_drv"
+
+
+-- 加载字库驱动管理功能模块,有以下三种:
+-- 1、使用gtfont核心库驱动AirFONTS_1000矢量字库配件板的gtfont_drv.lua
+-- 2、使用hzfont核心库驱动内核固件中支持的软件矢量字库的hzfont_drv.lua(正在开发中,后续补充)
+-- 3、使用自定义字体
+-- 根据自己的需求,启用三者中的任何几种都可以
+-- 也可以不启用任何一种,只使用内核固件中自带的点阵字库
+require "gtfont_drv"
+-- require "hzfont_drv"
+-- 使用外部自定义字体不需要require "customer_font_drv",可以参照customer_font_drv.lua内的使用说明进行创建和加载字体文件
+
+
+
+-- 加载输入法驱动管理功能模块(正在开发中,后续补充)
+
+
+-- 加载lcd核心库实现的用户界面功能模块
+-- 实现多页面切换、按键事件分发和界面渲染功能
+-- 包含主页、lcd核心库功能演示页、GTFont演示页和自定义字体演示页
+require "ui_main"
+
+
+-- 用户代码已结束
+-- 结尾总是这一句
+sys.run()
+-- sys.run()之后不要加任何语句!!!!!因为添加的任何语句都不会被执行

+ 229 - 0
module/Air8000/demo/accessory_board/AirLCD_1000/lcd/readme.md

@@ -0,0 +1,229 @@
+# LCD、按键与字体演示系统
+
+## 一、功能模块介绍
+
+### 1.1 核心主程序模块
+1. **main.lua** - 主程序入口,负责系统初始化和任务调度
+2. **ui_main.lua** - 用户界面主控模块,管理页面切换和事件分发
+
+### 1.2 显示页面模块
+3. **home_page.lua** - 主页模块,提供应用入口和导航功能
+4. **lcd_page.lua** - LCD图形绘制演示模块
+5. **gtfont_page.lua** - GTFont矢量字体演示模块
+6. **customer_font_page.lua** - 自定义字体演示模块
+
+### 1.3 驱动模块
+7. **lcd_drv.lua** - LCD显示驱动模块,基于lcd核心库,lcd_drv和exlcd_drv二选一使用
+8. **exlcd_drv.lua** - LCD显示驱动模块,基于exlcd扩展库,lcd_drv和exlcd_drv二选一使用
+9. **key_drv.lua** - 按键驱动模块,管理BOOT键和PWR键
+10. **gtfont_drv.lua** - GTFont矢量字库驱动模块
+11. **customer_font_drv.lua** - 自定义外部字体驱动功能模块
+12. **hzfont_drv.lua** - 合宙软件矢量字库(开发中)
+    - gtfont_drv、customer_font_drv、hzfont_drv
+    - 可以都不启用
+    - 可以仅启用一种
+    - 可以启用任意两种
+    - 可以全部启用
+
+## 二、按键消息介绍
+
+1. **"KEY_EVENT"** - 按键事件消息,包含按键类型和状态
+   - boot键事件:`boot_down`(按下)、`boot_up`(释放)
+   - pwr键事件:`pwr_down`(按下)、`pwr_up`(释放)
+   - 按键功能定义:
+     - 主页:boot键(按下)选择/切换选项,pwr键(按下)确认
+     - GTFont页面:boot键(按下)切换模式,pwr键(按下)返回
+     - LCD页面:pwr键(按下)返回,boot键无功能
+     - 自定义字体页面:pwr键(按下)返回,boot键无功能
+
+## 三、显示效果
+
+<table>
+<tr>
+<td>主页<br/></td><td>lcd核心库页面<br/></td><td>gtfont页面<br/></td><td>自定义字体页面<br/></td></tr>
+<tr>
+<td rowspan="2"><img src="https://docs.openluat.com/cdn/image/Air780EHV_AirLCD_1000_AirFONTS_1000演示主页.png" width="80" /><br/></td><td rowspan="2"><img src="https://docs.openluat.com/cdn/image/Air780EHMLCD演示2.png" width="80" /><br/></td><td><img src="https://docs.openluat.com/cdn/image/Air780EHMLCD演3.png" width="80" /><br/></td><td rowspan="2"><img src="https://docs.openluat.com/cdn/image/Air780EHMLCD演示5.jpg" width="80" /><br/></td></tr>
+<tr>
+<td><img src="https://docs.openluat.com/cdn/image/Air780EHMLCD演示4.jpg" width="80" /><br/></td></tr>
+</table>
+
+
+### 4.1 LCD图形绘制演示
+1. **基本图形绘制** - 展示点、线、矩形、圆形等基本图形绘制功能
+2. **图片显示** - 支持外部图片文件显示
+3. **二维码生成** - 动态生成并显示二维码
+4. **xbm格式位图示例** - 显示16*16 xbm点阵
+5. **中文、英文字体示例** - 显示12号中文字体和英文字体
+
+### 4.2 GTFont矢量字体演示
+1. **矢量字体显示** - 使用AirFONTS_1000矢量字库小板显示平滑字体
+2. **字体大小切换** - 支持10-192号字体大小动态变化
+3. **灰度模式** - 支持灰度显示模式,字体边缘更平滑
+4. **多颜色显示** - 支持多种颜色字体显示
+
+### 4.3 自定义字体演示
+1. **外部字体加载** - 支持加载外部自定义字体文件
+2. **多颜色文字** - 支持不同颜色的文字显示
+
+### 4.4 按键交互功能
+1. **页面导航** - 支持多页面之间的切换
+2. **按钮响应** - 按键的点击响应功能
+3. **模式切换** - 支持gtfont切换灰度/常规显示
+
+## 五、演示硬件环境
+
+### 5.1 硬件清单
+
+- Air8000核心板 × 1
+- AirLCD_1000 配件板 × 1
+- GTFont 矢量字库,使用的是 AirFONTS_1000 配件板 × 1
+- 母对母杜邦线 × 17,杜邦线太长的话,会出现 spi 通信不稳定的现象;
+- TYPE-C 数据线 × 1
+- Air8000核心板和 AirLCD_1000 配件板以及 AirFONTS_1000 配件板的硬件接线方式为
+
+  - Air8000核心板通过 TYPE-C USB 口供电(核心板背面的开关拨到 USB ON 一端,正面开关拨到 供电 一端),此种供电方式下,VBAT和VDD-EXT 引脚为 3.3V,可以直接给 AirLCD_1000 配件板和 AirFONTS_1000 配件板供电;
+  - 为了演示方便,所以 Air8000核心板上电后直接通过 VBAT 引脚给 AirLCD_1000 配件板供电,通过复用VDD_EXT引脚给 AirFONTS_1000 配件板供电;
+  - 客户在设计实际项目时,一般来说,需要通过一个 GPIO 来控制 LDO 给配件板供电,这样可以灵活地控制配件板的供电,可以使项目的整体功耗降到最低;
+
+### 5.2 接线配置
+
+#### 5.2.1 LCD 显示屏接线
+
+<table>
+<tr> <td>Air8000核心板</td><td>AirLCD_1010配件板</td></tr>
+<tr> <td>LCD_CLK</td><td>SCLK/CLK</td></tr>
+<tr> <td>LCD_CS</td><td>CS</td></tr>
+<tr> <td>LCD_RST</td><td>RES/RST</td></tr>
+<tr> <td>LCD_SDA</td><td>SDA/MOS</td></tr>
+<tr> <td>LCD_RS</td><td>DC/RS</td></tr>
+<tr> <td>GPIO1</td><td>BLK</td></tr>
+<tr> <td>VBAT</td><td>VCC</td></tr>
+<tr> <td>GND</td><td>GND</td></tr>
+</table>
+
+#### 5.2.2 GTFont 字库接线
+
+<table>
+<tr> <td>Air8000核心板</td><td>AirFONTS_1000配件板</td></tr>
+<tr> <td>SPI0_CS</td><td>CS</td></tr>
+<tr> <td>SPI0_MISO</td><td>MISO</td></tr>
+<tr> <td>SPI0_MOSI</td><td>MOSI</td></tr>
+<tr> <td>SPI0_CLK</td><td>CLK</td></tr>
+<tr> <td>VDD_EXT</td><td>VCC</td></tr>
+<tr> <td>GND</td><td>GND</td></tr>
+</table>
+
+#### 5.2.3 接线图
+![](https://docs.openLuat.com/cdn/image/Air8000核心板_AirLCD_1000_AirFONTS_1000接线图.jpg)
+![](https://docs.openLuat.com/cdn/image/Air8000引脚定义背面图.png)
+
+## 六、演示软件环境
+
+### 6.1 开发工具
+
+- [Luatools 下载调试工具](https://docs.openluat.com/air8000/luatos/common/download/) - 固件烧录和代码调试
+
+### 6.2 内核固件
+
+- [点击下载 Air8000 系列最新版本内核固件](https://docs.openluat.com/air8000/luatos/firmware/)
+
+
+### 6.3 字体文件
+- 自定义字体文件:`customer_font_24.bin`(和lua脚本文件一起烧录,会自动放置在`/luadb/`目录下)
+- 演示图片文件:`logo.jpg`(和lua脚本文件一起烧录,会自动放置在`/luadb/`目录下)
+- [点击查看自定义字体生成和使用说明](https://docs.openluat.com/osapi/core/lcd/?h=lcd#_6)
+
+
+## 七、演示核心步骤
+
+### 7.1 硬件准备
+1. 按照硬件接线表连接所有设备
+2. 确保电源连接正确,通过TYPE-C USB口供电
+3. 检查所有接线无误,避免短路
+
+### 7.2 软件配置
+在`main.lua`中选择加载对应的驱动模块:
+
+```lua
+-- 加载显示屏驱动管理功能模块,有以下两种:
+-- 1、使用lcd核心库驱动的lcd_drv.lua
+-- 2、使用exlcd扩展库驱动的exlcd_drv.lua
+-- 根据自己的需求,启用两者中的任何一种都可以
+-- 也可以不启用任何一种,不使用显示屏功能
+-- lcd_drv = require "lcd_drv"
+lcd_drv = require "exlcd_drv"
+
+
+-- 加载按键驱动管理功能模块
+key_drv = require "key_drv"
+
+
+-- 加载字库驱动管理功能模块,有以下三种:
+-- 1、使用gtfont核心库驱动AirFONTS_1000矢量字库配件板的gtfont_drv.lua
+-- 2、使用hzfont核心库驱动内核固件中支持的软件矢量字库的hzfont_drv.lua(正在开发中,后续补充)
+-- 3、使用自定义字体
+-- 根据自己的需求,启用三者中的任何几种都可以
+-- 也可以不启用任何一种,只使用内核固件中自带的点阵字库
+require "gtfont_drv"
+-- require "hzfont_drv"
+-- 使用外部自定义字体不需要require "customer_font_drv",可以参照customer_font_drv.lua内的使用说明进行创建和加载字体文件
+
+
+
+-- 加载输入法驱动管理功能模块(正在开发中,后续补充)
+
+
+-- 加载lcd核心库实现的用户界面功能模块
+-- 实现多页面切换、按键事件分发和界面渲染功能
+-- 包含主页、lcd核心库功能演示页、GTFont演示页和自定义字体演示页
+require "ui_main"
+```
+
+### 7.3 软件烧录
+1. 使用Luatools烧录最新内核固件
+2. 下载并烧录本项目所有脚本文件
+3. 将字体文件和图片文件随脚本文件一起烧录到脚本分区
+4. 烧录成功后设备自动重启后开始运行
+
+### 7.4 功能测试
+
+#### 7.4.1 主页面操作
+1. 设备启动后显示主页面,包含三个功能按钮
+2. 查看系统功能概览信息
+3. 使用boot键切换选择,pwr键进入对应演示页面
+
+#### 7.4.2 LCD演示页面
+1. 查看基本图形绘制示例(点、线、矩形、圆形)
+2. 查看图片显示区域(显示logo图片)
+3. 查看二维码区域(合宙文档二维码)
+4. 查看位图和字体示例
+5. 按pwr键返回主页
+
+#### 7.4.3 GTFont演示页面
+1. 计时阶段,gtfont说明显示
+2. 字体大小变化阶段,查看10-192号字体动态变化
+3. 按boot键切换"灰度/常规"模式
+4. 查看多颜色字体显示效果
+5. 按pwr键返回主页
+
+#### 7.4.4 自定义字体页面
+1. 查看外部字体文件显示效果
+2. 查看多颜色文字显示(红色、绿色、蓝色)
+3. 查看字体使用说明和接口信息
+4. 按pwr键返回主页
+
+### 7.5 预期效果
+
+- **主页面**:正常显示,使用boot键切换选项,pwr键确认
+- **LCD演示页面**:图形绘制清晰,图片和二维码显示正常,颜色示例完整,pwr键返回
+- **GTFont演示页面**:字体显示平滑,字号切换流畅,boot键切换模式,pwr键返回
+- **自定义字体页面**:外部字体加载正确,多颜色文字显示正常,pwr键返回
+- **按键交互**:所有按键操作响应及时准确,页面切换流畅
+
+### 7.6 故障排除
+
+1. **显示异常**:检查LCD接线是否正确,确认电源供电稳定
+2. **按键无响应**:检查参数是否配置正确,确认按键驱动初始化成功
+3. **字体显示异常**:检查SPI接线(如使用GTFont),确认字体文件路径正确
+4. **图片无法显示**:确认图片文件已正确烧录到指定路径
+5. **系统卡顿**:检查内存使用情况,适当调整刷新频率

+ 70 - 0
module/Air8000/demo/accessory_board/AirLCD_1000/lcd/tp_key_drv/key_drv.lua

@@ -0,0 +1,70 @@
+--[[
+@module  key_drv
+@summary 按键驱动模块
+@version 1.0
+@date    2025.12.3
+@author  江访
+@usage
+本文件为按键驱动功能模块,核心业务逻辑为:
+1、初始化BOOT键和PWR键的GPIO;
+2、配置按键事件的中断处理函数;
+3、实现按键防抖功能,防止误触发;
+4、对外发布按键消息;
+
+本文件的对外接口有1个:
+1、key_drv.init():初始化按键驱动;
+]]
+
+local key_drv = {}
+
+-- 按键定义
+local key_boot = 0           -- GPIO0按键(BOOT键)
+local key_pwr = gpio.PWR_KEY -- 电源按键
+
+
+-- 按键事件处理函数
+local function handle_boot_key(val)
+    -- print("key_boot", val)
+    if val == 1 then
+        sys.publish("KEY_EVENT", "boot_down")
+    else
+        sys.publish("KEY_EVENT", "boot_up")
+    end
+end
+
+local function handle_pwr_key(val)
+    -- print("key_pwr", val)
+    if val == 1 then
+        sys.publish("KEY_EVENT", "pwr_up")
+    else
+        sys.publish("KEY_EVENT", "pwr_down")
+    end
+end
+
+--[[
+初始化按键GPIO;
+配置BOOT键和PWR键的GPIO中断;
+
+@api key_drv.init()
+@summary 配置BOOT键和PWR键的GPIO中断
+@return bool 初始化只会返回true
+
+@usage
+local result = key_drv.init()
+if result then
+    log.info("按键驱动初始化成功")
+end
+]]
+function key_drv.init()
+    gpio.setup(key_boot, handle_boot_key, gpio.PULLDOWN, gpio.BOTH)
+    gpio.debounce(key_boot, 50, 0)     -- 防抖,防止频繁触发
+
+    gpio.setup(key_pwr, handle_pwr_key, gpio.PULLUP, gpio.BOTH)
+    gpio.debounce(key_pwr, 50, 0)     -- 防抖,防止频繁触发
+
+    log.info("key_drv", "按键初始化完成")
+    return true
+end
+
+key_drv.init()
+return key_drv

+ 117 - 0
module/Air8000/demo/accessory_board/AirLCD_1000/lcd/ui/customer_font_page.lua

@@ -0,0 +1,117 @@
+--[[
+@module  customer_font_page
+@summary 自定义字体演示模块
+@version 1.0
+@date    2025.12.3
+@author  江访
+@usage
+本模块为自定义字体演示功能模块,主要功能包括:
+1、展示外部自定义字体文件的加载和显示功能;
+2、提供多颜色文字显示效果;
+3、显示字体使用说明和接口信息;
+
+按键功能:
+- PWR键:返回主页
+- BOOT键:无功能
+
+对外接口:
+1、customer_font_page.draw():绘制自定义字体演示页面
+2、customer_font_page.handle_key():处理自定义字体页面按键事件
+3、customer_font_page.on_leave():页面离开时恢复系统字体
+]]
+
+local customer_font_page = {}
+
+--[[
+绘制自定义字体演示页面;
+绘制自定义字体演示页面的所有UI元素和字体内容;
+
+@api customer_font_page.draw()
+@summary 绘制自定义字体演示页面的所有UI元素和字体内容
+@return nil
+
+@usage
+-- 在UI主循环中调用
+customer_font_page.draw()
+]]
+function customer_font_page.draw()
+    lcd.clear()
+    lcd.setFont(lcd.font_opposansm12_chinese)
+
+    -- 设置默认颜色
+    lcd.setColor(0xFFFF, 0x0000)
+
+    -- 显示标题(使用系统字体)
+    lcd.drawStr(106, 20, "自定义点阵字体演示", 0x0000)
+    
+    -- 显示操作提示
+    lcd.drawStr(20, 40, "按PWR键返回主页", 0x0000)
+
+    -- 设置自定义字体文件
+    lcd.setFontFile("/luadb/customer_font_24.bin")
+
+    lcd.drawStr(112, 160, "上海合宙", 0xF800) -- 红色
+    lcd.drawStr(120, 200, "LuatOS", 0x07E0) -- 绿色
+    lcd.drawStr(100, 240, "演示demo", 0x001F) -- 蓝色
+
+    -- 恢复系统字体显示说明
+    lcd.setFont(lcd.font_opposansm12_chinese)
+    lcd.setColor(0xFFFF, 0x0000)
+
+    -- 显示说明信息
+    lcd.drawStr(20, 320, "- 字体路径: /luadb/customer_font_24.bin", 0x0000)
+    -- 显示使用说明
+    lcd.drawStr(20, 340, "使用接口:", 0x0000)
+    lcd.drawStr(20, 360, "lcd.setFontFile(字体路径)", 0x0000)
+    lcd.drawStr(20, 380, "lcd.drawStr(x, y,文本)", 0x0000)
+    
+    -- 显示当前操作状态
+    lcd.drawStr(20, 420, "当前页面: 自定义字体演示", 0x0000)
+end
+
+--[[
+处理按键事件;
+根据按键类型执行相应的操作;
+
+@api customer_font_page.handle_key(key_type, switch_page)
+@summary 处理自定义字体页面按键事件
+@string key_type 按键类型
+@valid_values "pwr_up"
+@function switch_page 页面切换回调函数
+@return bool 事件处理成功返回true,否则返回false
+
+@usage
+-- 在UI主循环中调用
+local handled = customer_font_page.handle_key("pwr_up", switch_page)
+]]
+function customer_font_page.handle_key(key_type, switch_page)
+    log.info("customer_font_page.handle_key", "key_type:", key_type)
+    
+    if key_type == "pwr_up" then
+        -- PWR键:返回首页
+        switch_page("home")
+        return true
+    end
+    -- BOOT键无功能
+    return false
+end
+
+--[[
+页面离开时恢复系统字体;
+恢复系统默认字体设置;
+
+@api customer_font_page.on_leave()
+@summary 恢复系统默认字体设置
+@return nil
+
+@usage
+-- 在页面切换时调用
+customer_font_page.on_leave()
+]]
+function customer_font_page.on_leave()
+    -- 恢复使用12号中文字体
+    lcd.setFont(lcd.font_opposansm12_chinese)
+    log.info("customer_font_page", "已恢复系统字体")
+end
+
+return customer_font_page

+ 391 - 0
module/Air8000/demo/accessory_board/AirLCD_1000/lcd/ui/gtfont_page.lua

@@ -0,0 +1,391 @@
+--[[
+@module  gtfont_page
+@summary GTFont矢量字体演示模块
+@version 1.0
+@date    2025.12.3
+@author  江访
+@usage
+本模块为GTFont矢量字体演示功能模块,主要功能包括:
+1、展示AirFONTS_1000矢量字库小板的字体显示功能;
+2、支持10-192号字体大小动态变化演示;
+3、支持灰度模式和常规模式切换;
+4、提供倒计时和字体大小变化两种演示阶段;
+
+按键功能:
+- BOOT键:切换灰度/常规模式
+- PWR键:返回主页
+
+对外接口:
+1、gtfont_page.draw():绘制GTFont演示页面
+2、gtfont_page.handle_key():处理GTFont页面按键事件
+3、gtfont_page.on_enter():页面进入时状态重置
+4、gtfont_page.on_leave():页面离开时恢复系统刷新率
+]]
+
+local gtfont_page = {}
+
+-- 按钮区域定义
+local back_button = { x1 = 10, y1 = 10, x2 = 80, y2 = 50 }
+local switch_button = { x1 = 220, y1 = 10, x2 = 310, y2 = 50 }
+
+-- 字体显示状态
+local font_demo_state = {
+    use_gray = true,                   -- 默认为灰度模式
+    demo_phase = 1,                    -- 演示阶段
+    last_update = 0,
+    update_interval = 1000,            -- 倒计时更新间隔
+    font_update_interval = 20,         -- 字体更新间隔
+    countdown = 18,                     -- 倒计时
+    current_size = 16,                 -- 当前字体大小
+    color_phase = 1,                   -- 颜色阶段
+}
+
+--[[
+绘制开关按钮;
+绘制灰度/常规模式切换按钮;
+
+@api draw_switch_button()
+@summary 绘制灰度/常规模式切换按钮
+@return nil
+
+@usage
+-- 在draw函数中调用
+draw_switch_button()
+]]
+local function draw_switch_button()
+    -- 按钮背景
+    lcd.fill(switch_button.x1, switch_button.y1, switch_button.x2, switch_button.y2, 0xC618)
+
+    -- 开关指示器
+    if font_demo_state.use_gray then
+        -- 灰度模式,左边填充
+        lcd.fill(switch_button.x1, switch_button.y1,
+            switch_button.x1 + (switch_button.x2 - switch_button.x1) / 2,
+            switch_button.y2, 0x07E0)
+    else
+        -- 常规模式,右边填充
+        lcd.fill(switch_button.x1 + (switch_button.x2 - switch_button.x1) / 2,
+            switch_button.y1, switch_button.x2, switch_button.y2, 0x07E0)
+    end
+
+    -- 按钮文字
+    lcd.setColor(0xFFFF, 0x0000)
+    lcd.setFont(lcd.font_opposansm12_chinese)
+    lcd.drawStr(switch_button.x1 + 10, switch_button.y1 + 25, "灰度", 0x0000)
+    lcd.drawStr(switch_button.x1 + (switch_button.x2 - switch_button.x1) / 2 + 10,
+        switch_button.y1 + 25, "常规", 0x0000)
+end
+
+--[[
+绘制返回按钮;
+绘制返回主页按钮;
+
+@api draw_back_button()
+@summary 绘制返回主页按钮
+@return nil
+
+@usage
+-- 在draw函数中调用
+draw_back_button()
+]]
+local function draw_back_button()
+    lcd.fill(back_button.x1, back_button.y1, back_button.x2, back_button.y2, 0xC618)
+    lcd.setColor(0xFFFF, 0x0000)
+    lcd.setFont(lcd.font_opposansm12_chinese)
+    lcd.drawStr(back_button.x1 + 25, back_button.y1 + 25, "返回", 0x0000)
+end
+
+--[[
+绘制倒计时阶段;
+绘制第一阶段倒计时演示内容;
+
+@api draw_countdown_phase()
+@summary 绘制倒计时阶段演示内容
+@return bool 是否完成倒计时
+
+@usage
+-- 在draw_font_demo函数中调用
+local finished = draw_countdown_phase()
+]]
+local function draw_countdown_phase()
+    local _, current_time = mcu.ticks2(1)
+    
+    if current_time - font_demo_state.last_update > font_demo_state.update_interval then
+        font_demo_state.countdown = font_demo_state.countdown - 1
+        font_demo_state.last_update = current_time
+        
+        if font_demo_state.countdown <= 0 then
+            font_demo_state.demo_phase = 2
+            font_demo_state.current_size = 16
+            font_demo_state.color_phase = 1
+            font_demo_state.last_update = current_time
+            return true
+        end
+    end
+    
+    -- 设置背景色为白色,文字的前景色为黑色
+    lcd.setColor(0xFFFF, 0x0000)
+    if font_demo_state.use_gray then
+        lcd.drawGtfontUtf8Gray("AirFONTS_1000配件板", 24, 2, 50, 70)
+    else
+        lcd.drawGtfontUtf8("AirFONTS_1000配件板", 24, 50, 70)
+    end
+
+    -- 设置背景色为白色,文字的前景色为红色
+    lcd.setColor(0xFFFF, 0xF800)
+    if font_demo_state.use_gray then
+        lcd.drawGtfontUtf8Gray("支持10到192号的黑体字体", 24, 2, 40, 111)
+    else
+        lcd.drawGtfontUtf8("支持10到192号的黑体字体", 24, 40, 111)
+    end
+
+    -- 设置背景色为白色,文字的前景色为绿色
+    lcd.setColor(0xFFFF, 0x07E0)
+    if font_demo_state.use_gray then
+        lcd.drawGtfontUtf8Gray("支持GBK中文和ASCII码字符集", 20, 2, 35, 152)
+    else
+        lcd.drawGtfontUtf8("支持GBK中文和ASCII码字符集", 20, 35, 152)
+    end
+
+    -- 设置背景色为白色,文字的前景色为蓝色
+    lcd.setColor(0xFFFF, 0x001F)
+    if font_demo_state.use_gray then
+        lcd.drawGtfontUtf8Gray("支持灰度显示,字体边缘更平滑", 20, 2, 35, 193)
+    else
+        lcd.drawGtfontUtf8("支持灰度显示,字体边缘更平滑", 20, 35, 193)
+    end
+
+    -- 倒计时
+    lcd.setColor(0xFFFF, 0x0000)
+    if font_demo_state.use_gray then
+        lcd.drawGtfontUtf8Gray("倒计时 : " .. font_demo_state.countdown, 24, 2, 100, 233)
+    else
+        lcd.drawGtfontUtf8("倒计时 : " .. font_demo_state.countdown, 24, 100, 233)
+    end
+    
+    return false
+end
+
+--[[
+绘制字体大小变化阶段;
+绘制第二阶段字体大小变化演示内容;
+
+@api draw_font_size_phase()
+@summary 绘制字体大小变化阶段演示内容
+@return bool 是否完成所有阶段
+
+@usage
+-- 在draw_font_demo函数中调用
+local finished = draw_font_size_phase()
+]]
+local function draw_font_size_phase()
+    local _, current_time = mcu.ticks2(1)
+    
+    if current_time - font_demo_state.last_update > font_demo_state.font_update_interval then
+        font_demo_state.current_size = font_demo_state.current_size + 1
+        font_demo_state.last_update = current_time
+    end
+    
+    -- 根据颜色阶段设置颜色
+    if font_demo_state.color_phase == 1 then
+        lcd.setColor(0xFFFF, 0x0000) -- 黑色
+    elseif font_demo_state.color_phase == 2 then
+        lcd.setColor(0xFFFF, 0xF800) -- 红色
+    elseif font_demo_state.color_phase == 3 then
+        lcd.setColor(0xFFFF, 0x07E0) -- 绿色
+    else
+        lcd.setColor(0xFFFF, 0x001F) -- 蓝色
+    end
+    
+    -- 根据颜色阶段和字体大小显示不同内容
+    if font_demo_state.color_phase == 1 then
+        if font_demo_state.current_size <= 64 then
+            if font_demo_state.use_gray then
+                lcd.drawGtfontUtf8Gray(font_demo_state.current_size .. "号:合宙AirFONTS_1000", 
+                                      font_demo_state.current_size, 4, 10, 100)
+            else
+                lcd.drawGtfontUtf8(font_demo_state.current_size .. "号:合宙AirFONTS_1000", 
+                                  font_demo_state.current_size, 10, 100)
+            end
+        else
+            font_demo_state.color_phase = 2
+            font_demo_state.current_size = 65
+        end
+    elseif font_demo_state.color_phase == 2 then
+        if font_demo_state.current_size <= 96 then
+            if font_demo_state.use_gray then
+                lcd.drawGtfontUtf8Gray(font_demo_state.current_size .. "号", 
+                                      font_demo_state.current_size, 4, 10, 100)
+                lcd.drawGtfontUtf8Gray("AirFONTS_1000", 
+                                      font_demo_state.current_size, 4, 10, 100 + font_demo_state.current_size + 5)
+            else
+                lcd.drawGtfontUtf8(font_demo_state.current_size .. "号", 
+                                  font_demo_state.current_size, 10, 100)
+                lcd.drawGtfontUtf8("AirFONTS_1000", 
+                                  font_demo_state.current_size, 10, 100 + font_demo_state.current_size + 5)
+            end
+        else
+            font_demo_state.color_phase = 3
+            font_demo_state.current_size = 97
+        end
+    elseif font_demo_state.color_phase == 3 then
+        if font_demo_state.current_size <= 128 then
+            if font_demo_state.use_gray then
+                lcd.drawGtfontUtf8Gray(font_demo_state.current_size .. "号", 
+                                      font_demo_state.current_size, 4, 10, 50)
+                lcd.drawGtfontUtf8Gray("合宙", 
+                                      font_demo_state.current_size, 4, 10, 50 + font_demo_state.current_size + 5)
+            else
+                lcd.drawGtfontUtf8(font_demo_state.current_size .. "号", 
+                                  font_demo_state.current_size, 10, 50)
+                lcd.drawGtfontUtf8("合宙", 
+                                  font_demo_state.current_size, 10, 50 + font_demo_state.current_size + 5)
+            end
+        else
+            font_demo_state.color_phase = 4
+            font_demo_state.current_size = 129
+        end
+    else
+        if font_demo_state.current_size <= 192 then
+            -- 矢量字体大小目前不能到180号,常规字体可到192号
+            -- if font_demo_state.use_gray then
+            --     lcd.drawGtfontUtf8Gray(font_demo_state.current_size .. "号", 
+            --                           font_demo_state.current_size, 4, 10, 50)
+            --     lcd.drawGtfontUtf8Gray("合宙", 
+            --                           font_demo_state.current_size, 4, 10, 50 + font_demo_state.current_size + 5)
+            -- else
+                lcd.drawGtfontUtf8(font_demo_state.current_size .. "号", 
+                                  font_demo_state.current_size, 10, 50)
+                lcd.drawGtfontUtf8("合宙", 
+                                  font_demo_state.current_size, 10, 50 + font_demo_state.current_size + 5)
+            -- end
+        else
+            -- 所有阶段完成,重置
+            font_demo_state.demo_phase = 1
+            font_demo_state.countdown = 5
+            font_demo_state.color_phase = 1
+            font_demo_state.current_size = 16
+            return true
+        end
+    end
+    
+    return false
+end
+
+--[[
+绘制字体演示内容;
+根据演示阶段调用不同的绘制函数;
+
+@api draw_font_demo()
+@summary 绘制字体演示内容
+@return nil
+
+@usage
+-- 在draw函数中调用
+draw_font_demo()
+]]
+local function draw_font_demo()
+    -- 根据演示阶段调用不同的绘制函数
+    if font_demo_state.demo_phase == 1 then
+        draw_countdown_phase()
+    else
+        draw_font_size_phase()
+    end
+end
+
+--[[
+绘制GTFont演示页面;
+绘制GTFont演示页面的所有UI元素和字体演示内容;
+
+@api gtfont_page.draw()
+@summary 绘制GTFont演示页面的所有UI元素和字体演示内容
+@return nil
+
+@usage
+-- 在UI主循环中调用
+gtfont_page.draw()
+]]
+function gtfont_page.draw()
+    lcd.clear()
+    -- 绘制按钮区域
+    draw_back_button()
+    draw_switch_button()
+
+    -- 绘制字体演示内容
+    draw_font_demo()
+
+    lcd.flush()
+end
+
+--[[
+处理按键事件;
+根据按键类型执行相应的操作;
+
+@api gtfont_page.handle_key(key_type, switch_page)
+@summary 处理GTFont页面按键事件
+@string key_type 按键类型
+@valid_values "boot_up", "pwr_up"
+@function switch_page 页面切换回调函数
+@return bool 事件处理成功返回true,否则返回false
+
+@usage
+-- 在UI主循环中调用
+local handled = gtfont_page.handle_key("boot_up", switch_page)
+]]
+function gtfont_page.handle_key(key_type, switch_page)
+    log.info("gtfont_page.handle_key", "key_type:", key_type)
+    
+    if key_type == "boot_up" then
+        -- BOOT键:切换灰度模式
+        font_demo_state.use_gray = not font_demo_state.use_gray
+        log.info("gtfont_page", "切换灰度模式:", font_demo_state.use_gray)
+        return true
+    elseif key_type == "pwr_up" then
+        -- PWR键:返回首页
+        switch_page("home")
+        return true
+    end
+    return false
+end
+
+--[[
+页面进入时重置状态;
+重置字体演示状态到初始值;
+
+@api gtfont_page.on_enter()
+@summary 重置字体演示状态到初始值
+@return nil
+
+@usage
+-- 在页面切换时调用
+gtfont_page.on_enter()
+]]
+function gtfont_page.on_enter()
+    font_demo_state.use_gray = true -- 默认灰度模式
+    font_demo_state.demo_phase = 1
+    font_demo_state.countdown = 18
+    font_demo_state.current_size = 16
+    font_demo_state.color_phase = 1
+    local _, ms_l = mcu.ticks2(1)
+    font_demo_state.last_update = ms_l
+    frame_time = 20 -- 进入时改成20ms刷新一次
+end
+
+--[[
+页面离开时恢复系统刷新率;
+恢复刷新率到默认值;
+
+@api gtfont_page.on_leave()
+@summary 恢复刷新率
+@return nil
+
+@usage
+-- 在页面切换时调用
+gtfont_page.on_leave()
+]]
+function gtfont_page.on_leave()
+    -- 恢复恢复20S刷新一次
+    frame_time = 20*1000
+end
+
+return gtfont_page

+ 179 - 0
module/Air8000/demo/accessory_board/AirLCD_1000/lcd/ui/home_page.lua

@@ -0,0 +1,179 @@
+--[[
+@module  home_page
+@summary 主页模块,提供应用入口和导航功能
+@version 1.0
+@date    2025.12.3
+@author  江访
+@usage
+本模块为主页模块,主要功能包括:
+1、提供应用入口和导航功能;
+2、显示系统标题和操作提示;
+3、管理三个功能按钮的选中状态;
+4、处理主页面的按键事件;
+
+对外接口:
+1、home_page.draw():绘制主页面所有UI元素,包括选中指示
+2、home_page.handle_key():处理主页面按键事件
+3、home_page.on_enter():页面进入时重置选中状态
+4、home_page.on_leave():页面离开时执行清理操作
+]]
+
+local home_page = {}
+
+
+-- 按钮区域定义
+local buttons = {
+    {name = "lcd", text = "lcd核心库演示", x1 = 10, y1 = 350, x2 = 100, y2 = 420, color = 0x001F},
+    {name = "gtfont", text = "矢量字体芯片", x1 = 115, y1 = 350, x2 = 205, y2 = 420, color = 0xF800},
+    {name = "customer_font", text = "自定义字体", x1 = 220, y1 = 350, x2 = 310, y2 = 420, color = 0x07E0}
+}
+
+-- 当前选中项索引
+local selected_index = 1
+
+local title = "合宙lcd演示系统"
+local content1 = "本页面使用的是系统内置的12号中文点阵字体"
+local hint = "boot键:选择 pwr键:确认"
+
+--[[
+绘制光标指示
+@local
+@return nil
+]]
+local function draw_cursor()
+    local btn = buttons[selected_index]
+    
+    -- 在选中按钮周围绘制矩形光标
+    lcd.drawRectangle(btn.x1 - 2, btn.y1 - 2, btn.x2 + 2, btn.y2 + 2, 0x3186)  -- 蓝色外框
+    lcd.drawRectangle(btn.x1 - 1, btn.y1 - 1, btn.x2 + 1, btn.y2 + 1, 0x0000)  -- 黑色内框
+end
+
+--[[
+绘制主页界面;
+绘制主页面所有UI元素,包括选中指示;
+
+@api home_page.draw()
+@summary 绘制主页面所有UI元素,包括选中指示
+@return nil
+
+@usage
+-- 在UI主循环中调用
+home_page.draw()
+]]
+function home_page.draw()
+    lcd.clear()
+    lcd.setColor(0xFFFF, 0x0000)
+    lcd.setFont(lcd.font_opposansm12_chinese)
+
+    -- 显示标题
+    lcd.drawStr(106, 30, title, 0x0000)
+
+    -- 显示说明文字
+    lcd.drawStr(46, 48, content1, 0x0000)
+    lcd.drawStr(86, 66, hint, 0x0000)
+
+    -- 绘制所有按钮
+    for i, btn in ipairs(buttons) do
+        local color = btn.color
+        if i == selected_index then
+            -- 选中状态:颜色稍微变亮
+            color = color + 0x0842
+        end
+        
+        lcd.fill(btn.x1, btn.y1, btn.x2, btn.y2, color)
+        
+        -- 根据按钮调整文字位置
+        if btn.name == "lcd" then
+            lcd.drawStr(btn.x1 + 5, btn.y1 + 30, "lcd核心库演示", 0xFFFF)
+        elseif btn.name == "gtfont" then
+            lcd.drawStr(btn.x1 + 28, btn.y1 + 20, "外部", 0xFFFF)
+            lcd.drawStr(btn.x1 + 4, btn.y1 + 40, "矢量字体芯片", 0xFFFF)
+        elseif btn.name == "customer_font" then
+            lcd.drawStr(btn.x1 + 15, btn.y1 + 30, "自定义字体", 0xFFFF)
+        end
+    end
+
+    -- 绘制光标指示
+    draw_cursor()
+end
+
+--[[
+处理主页按键事件;
+根据按键类型执行相应的操作;
+
+@api home_page.handle_key(key_type, switch_page)
+@summary 处理主页按键事件
+@string key_type 按键类型
+@valid_values "confirm", "next", "prev", "back"
+@function switch_page 页面切换回调函数
+@return bool 事件处理成功返回true,否则返回false
+
+@usage
+-- 在UI主循环中调用
+local handled = home_page.handle_key("next", switch_page)
+]]
+function home_page.handle_key(key_type, switch_page)
+    log.info("home_page.handle_key", "key_type:", key_type, "selected_index:", selected_index)
+    
+    if key_type == "confirm" then
+        -- 确认键:切换到选中的页面
+        local btn = buttons[selected_index]
+        switch_page(btn.name)
+        return true
+    elseif key_type == "right" or key_type == "next" then
+        -- 向右/下一个
+        selected_index = selected_index % #buttons + 1
+        return true
+    elseif key_type == "left" or key_type == "prev" then
+        -- 向左/上一个
+        selected_index = (selected_index - 2) % #buttons + 1
+        return true
+    elseif key_type == "back" then
+        -- 返回键:可以执行其他操作或提示
+        return false
+    end
+    return false
+end
+
+--[[
+页面进入时重置选中状态;
+重置选中状态为第一个按钮;
+
+@api home_page.on_enter()
+@summary 重置选中状态
+@return nil
+
+@usage
+-- 在页面切换时调用
+home_page.on_enter()
+]]
+function home_page.on_enter()
+    selected_index = 1  -- 默认选中第一个
+end
+
+--[[
+获取当前选中项信息;
+用于调试或状态查询;
+
+@api home_page.get_selected_info()
+@summary 获取当前选中项信息
+@return table 包含选中项信息的表
+@field index number 当前选中项的索引
+@field name string 当前选中项的名称
+@field text string 当前选中项的显示文本
+
+@usage
+-- 获取当前选中项信息
+local info = home_page.get_selected_info()
+log.info("当前选中", info.name, info.text)
+]]
+function home_page.get_selected_info()
+    local btn = buttons[selected_index]
+    return {
+        index = selected_index,
+        name = btn.name,
+        text = btn.text
+    }
+end
+
+return home_page

+ 177 - 0
module/Air8000/demo/accessory_board/AirLCD_1000/lcd/ui/lcd_page.lua

@@ -0,0 +1,177 @@
+--[[
+@module  lcd_page
+@summary LCD图形绘制演示模块
+@version 1.0
+@date    2025.12.3
+@author  江访
+@usage
+本模块为LCD图形绘制演示功能模块,主要功能包括:
+1、展示LCD核心库的基本图形绘制功能;
+2、演示点、线、矩形、圆形等基本图形绘制;
+3、显示图片和二维码生成功能;
+4、提供颜色示例展示;
+
+按键功能:
+- PWR键:返回主页
+- BOOT键:无功能
+
+对外接口:
+1、lcd_page.draw():绘制LCD演示页面
+2、lcd_page.handle_key():处理LCD页面按键事件
+]]
+
+local lcd_page = {}
+
+-- 按钮区域定义
+local back_button = { x1 = 10, y1 = 10, x2 = 80, y2 = 50 }
+
+--[[
+绘制LCD演示页面;
+绘制LCD演示页面的所有图形和UI元素;
+
+@api lcd_page.draw()
+@summary 绘制LCD演示页面的所有图形和UI元素
+@return nil
+
+@usage
+-- 在UI主循环中调用
+lcd_page.draw()
+]]
+function lcd_page.draw()
+    lcd.clear()
+    lcd.setFont(lcd.font_opposansm12_chinese)
+
+    -- 绘制返回按钮
+    lcd.fill(back_button.x1, back_button.y1, back_button.x2, back_button.y2, 0xC618)
+    lcd.setColor(0x07E0, 0x0000)
+    lcd.drawStr(35, 35, "返回", 0x0000)
+    -- 设置默认颜色
+    lcd.setColor(0xFFFF, 0x0000)
+
+    -- 显示标题
+    lcd.drawStr(120, 33, "LCD核心库演示", 0x0000)
+    lcd.drawLine(20, 55, 300, 55, 0x8410)
+
+    -- === 第一区域:基本图形 ===
+    lcd.drawStr(20, 75, "基本图形绘制:", 0x0000)
+
+    -- 绘制点
+    lcd.drawStr(30, 98, "点:", 0x0000)
+    lcd.drawPoint(55, 98, 0xFCC0)
+    lcd.drawPoint(65, 98, 0x07E0)
+    lcd.drawPoint(75, 98, 0x001F)
+
+    -- 绘制线
+    lcd.drawStr(30, 125, "线:", 0x0000)
+    lcd.drawLine(55, 113, 115, 113, 0xFCC0)
+    lcd.drawLine(55, 118, 115, 123, 0x07E0)
+    lcd.drawLine(55, 123, 115, 118, 0x001F)
+
+    -- 绘制矩形(预留右侧空间)
+    lcd.drawStr(30, 160, "矩形:", 0x0000)
+    lcd.drawRectangle(65, 138, 105, 163, 0x7296)
+    lcd.fill(120, 138, 160, 163, 0x07E0)
+
+    -- 绘制圆(预留右侧空间)
+    lcd.drawStr(30, 200, "圆形:", 0x0000)
+    lcd.drawCircle(90, 193, 15, 0x001F)
+    lcd.drawCircle(130, 193, 15, 0xFCC0)
+
+    lcd.drawLine(170, 70, 170, 300, 0x8410) -- 垂直分隔线
+
+    -- === 第二区域:图片和二维码 ===
+    lcd.drawStr(180, 75, "图片/二维码:", 0x0000)
+
+    -- 图片显示区域 (80x80)
+    lcd.drawStr(180, 100, "LOGO:", 0x0000)
+    lcd.drawRectangle(180, 110, 270, 200, 0x0000) 
+    lcd.showImage(185, 115, "/luadb/logo.jpg")  
+
+    -- 二维码区域 (80x80)
+    lcd.drawStr(180, 215, "二维码:", 0x0000)
+    lcd.drawRectangle(180, 225, 270, 308, 0x0000)
+    lcd.drawQrcode(185, 226, "https://docs.openluat.com/air8000/", 80)
+
+    lcd.drawLine(20, 325, 300, 325, 0x8410)
+
+    -- === 第三区域:位图 ===
+    lcd.drawLine(20, 235, 160, 235, 0x8410)
+
+    -- 位图区域
+    lcd.setFont(lcd.font_opposansm12_chinese)
+    lcd.drawStr(20, 255, "位图示例:", 0x0000)
+
+    -- 绘制位图
+    local x_start = 30
+    local y_start = 265
+    lcd.drawXbm(x_start, y_start, 16, 16, string.char(
+        0x00, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x3F, 0x80, 0x00,
+        0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0xFE, 0x7F, 0x00, 0x00))
+
+    lcd.drawXbm(x_start + 20, y_start, 16, 16, string.char(
+        0x00, 0x00, 0x80, 0x00, 0xC4, 0x7F, 0x28, 0x00, 0x10, 0x00, 0xD0, 0x3F, 0x42, 0x20, 0x44, 0x22,
+        0x40, 0x24, 0xF0, 0xFF, 0x24, 0x20, 0x24, 0x22, 0x24, 0x20, 0xE2, 0x7F, 0x02, 0x20, 0x02, 0x1E))
+
+    lcd.drawXbm(x_start, y_start + 20, 16, 16, string.char(
+        0x00, 0x00, 0x00, 0x01, 0x80, 0x01, 0x40, 0x02, 0x20, 0x04, 0x18, 0x18, 0xF4, 0x6F, 0x02, 0x00,
+        0x00, 0x00, 0xF8, 0x1F, 0x08, 0x10, 0x08, 0x10, 0x08, 0x10, 0x08, 0x10, 0xF8, 0x1F, 0x08, 0x10))
+
+    lcd.drawXbm(x_start + 20, y_start + 20, 16, 16, string.char(
+        0x00, 0x00, 0x80, 0x00, 0x00, 0x01, 0xFE, 0x7F, 0x02, 0x40, 0x02, 0x40, 0x00, 0x01, 0xFC, 0x3F,
+        0x04, 0x21, 0x04, 0x21, 0xFC, 0x3F, 0x04, 0x21, 0x04, 0x21, 0x04, 0x21, 0xFC, 0x3F, 0x04, 0x20))
+
+    -- === 第四区域:字体 ===
+    lcd.drawStr(20, 345, "中英文字体示例:", 0x0000)
+
+    -- 中文字体
+    lcd.setFont(lcd.font_opposansm12_chinese)
+    lcd.drawStr(20, 368, "中文字体ABC123", 0x0000)
+
+    -- 英文字体
+    local font_y = 388
+    lcd.setFont(lcd.font_opposansm12)
+    lcd.drawStr(20, font_y, "12px: ABCabc123", 0x0000)
+    font_y = font_y + 18
+
+    lcd.setFont(lcd.font_opposansm16)
+    lcd.drawStr(20, font_y, "16px: ABCabc123", 0x0000)
+    font_y = font_y + 22
+
+    lcd.setFont(lcd.font_opposansm20)
+    lcd.drawStr(20, font_y, "20px: ABCabc123", 0x0000)
+    font_y = font_y + 26
+
+    lcd.setFont(lcd.font_opposansm24)
+    lcd.drawStr(20, font_y, "24px: ABCabc123", 0x0000)
+
+    lcd.drawLine(20, 470, 300, 470, 0x8410)
+end
+
+--[[
+处理按键事件;
+根据按键类型执行相应的操作;
+
+@api lcd_page.handle_key(key_type, switch_page)
+@summary 处理LCD页面按键事件
+@string key_type 按键类型
+@valid_values "pwr_up"
+@function switch_page 页面切换回调函数
+@return bool 事件处理成功返回true,否则返回false
+
+@usage
+-- 在UI主循环中调用
+local handled = lcd_page.handle_key("pwr_up", switch_page)
+]]
+function lcd_page.handle_key(key_type, switch_page)
+    log.info("lcd_page.handle_key", "key_type:", key_type)
+    
+    if key_type == "pwr_up" then
+        -- PWR键:返回首页
+        switch_page("home")
+        return true
+    end
+    -- BOOT键无功能
+    return false
+end
+
+return lcd_page

+ 186 - 0
module/Air8000/demo/accessory_board/AirLCD_1000/lcd/ui/ui_main.lua

@@ -0,0 +1,186 @@
+--[[
+@module  ui_main
+@summary 用户界面主控模块,负责页面管理和事件分发
+@version 1.0
+@date    2025.12.3
+@author  江访
+本模块为用户界面主控模块,主要功能包括:
+1、管理页面切换和事件分发;
+2、处理按键事件并调用对应页面的处理函数;
+3、协调各页面之间的状态转移;
+4、控制界面刷新频率;
+
+对外接口:
+1、ui_main():用户界面主任务,初始化显示和按键驱动,启动UI主循环
+]]
+
+-- 加载子页面
+local home_page = require "home_page"
+local lcd_page = require "lcd_page"
+local gtfont_page = require "gtfont_page"
+local customer_font_page = require "customer_font_page"
+
+-- 当前页面状态
+local current_page = "home"
+local last_page = ""
+frame_time = 20 * 1000
+
+--[[
+切换页面;
+从当前页面切换到目标页面;
+
+@api switch_page(new_page)
+@summary 执行页面切换操作
+@string new_page 目标页面名称
+@valid_values "home", "lcd", "gtfont", "customer_font"
+@return nil
+
+@usage
+-- 切换到主页
+switch_page("home")
+
+-- 切换到LCD演示页面
+switch_page("lcd")
+]]
+local function switch_page(new_page)
+    log.info("switch_page", "从", current_page, "切换到", new_page)
+    
+    -- 调用旧页面的退出函数(如果存在)
+    if current_page == "home" and home_page.on_leave then
+        home_page.on_leave()
+    elseif current_page == "lcd" and lcd_page.on_leave then
+        lcd_page.on_leave()
+    elseif current_page == "gtfont" and gtfont_page.on_leave then
+        gtfont_page.on_leave()
+    elseif current_page == "customer_font" and customer_font_page.on_leave then
+        customer_font_page.on_leave()
+    end
+
+    last_page = current_page
+    current_page = new_page
+
+    -- 调用新页面的进入函数(如果存在)
+    if new_page == "home" and home_page.on_enter then
+        home_page.on_enter()
+    elseif new_page == "lcd" and lcd_page.on_enter then
+        lcd_page.on_enter()
+    elseif new_page == "gtfont" and gtfont_page.on_enter then
+        gtfont_page.on_enter()
+    elseif new_page == "customer_font" and customer_font_page.on_enter then
+        customer_font_page.on_enter()
+    end
+
+    log.info("ui_main", "已切换到页面:", current_page)
+end
+
+--[[
+处理按键事件;
+根据按键类型和当前页面调用对应的处理函数;
+
+@api handle_key_event(key_event)
+@summary 处理按键事件并分发到对应页面
+@string key_event 按键事件类型
+@valid_values "boot_up", "pwr_up"
+@return bool 事件处理成功返回true,否则返回false
+
+@usage
+-- 在ui_main任务中调用
+local handled = handle_key_event("boot_up")
+]]
+local function handle_key_event(key_event)
+    log.info("按键事件", "event:", key_event, "当前页面:", current_page)
+    
+    -- 只在按键释放时处理(防止重复触发)
+    if key_event == "boot_up" then
+        -- BOOT键:在主页作为方向键,在gtfont页面切换模式
+        if current_page == "home" then
+            -- 主页:向右移动光标
+            return home_page.handle_key("next", switch_page)
+        elseif current_page == "gtfont" then
+            -- GTFont页面:切换灰度模式
+            if gtfont_page.handle_key then
+                return gtfont_page.handle_key("boot_up", switch_page)
+            end
+        end
+        -- 其他页面BOOT键无功能
+        return false
+    elseif key_event == "pwr_up" then
+        -- PWR键:确认/返回功能
+        if current_page == "home" then
+            return home_page.handle_key("confirm", switch_page)
+        elseif current_page == "lcd" then
+            -- LCD页面:返回首页
+            if lcd_page.handle_key then
+                return lcd_page.handle_key("pwr_up", switch_page)
+            end
+        elseif current_page == "gtfont" then
+            -- GTFont页面:返回首页
+            if gtfont_page.handle_key then
+                return gtfont_page.handle_key("pwr_up", switch_page)
+            end
+        elseif current_page == "customer_font" then
+            -- 自定义字体页面:返回首页
+            if customer_font_page.handle_key then
+                return customer_font_page.handle_key("pwr_up", switch_page)
+            end
+        end
+    end
+    
+    return false
+end
+
+--[[
+用户界面主任务;
+初始化显示和按键驱动,启动UI主循环;
+
+@api ui_main()
+@summary 初始化显示和按键驱动,启动UI主循环
+@return nil
+
+@usage
+-- 在主程序中通过sys.taskInit调用
+sys.taskInit(ui_main)
+]]
+local function ui_main()
+    if not lcd_drv.init() then
+        log.error("ui_main", "显示初始化失败")
+        return
+    end
+
+    -- 初始化按键驱动
+    if not key_drv.init() then
+        log.error("ui_main", "按键驱动初始化失败")
+        return
+    end
+
+    -- 默认使用系统自带的12号中文字体
+    lcd.setFont(lcd.font_opposansm12_chinese)
+
+    -- 调用主页的进入函数
+    if home_page.on_enter then
+        home_page.on_enter()
+    end
+
+    while true do
+        -- 根据当前页面绘制内容
+        if current_page == "home" then
+            home_page.draw()
+        elseif current_page == "lcd" then
+            lcd_page.draw()
+        elseif current_page == "gtfont" then
+            gtfont_page.draw()
+        elseif current_page == "customer_font" then
+            customer_font_page.draw()
+        end
+
+        lcd.flush()
+
+        -- 等待按键事件
+        local result, key_event = sys.waitUntil("KEY_EVENT", frame_time)
+        if result then
+            handle_key_event(key_event)
+        end
+    end
+end
+
+sys.taskInit(ui_main)