Files
BR_YKC/4G/tools/resource/soc_script/v2025.12.31.22/lib/extp.lua
2026-03-31 15:46:04 +08:00

431 lines
14 KiB
Lua
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
-- extp.lua - 触摸系统模块
--[[
@module extp
@summary 触摸系统拓展库
@version 1.1.1
@date 2025.11.20
@author 江访
@usage
本文件为触摸系统拓展库,核心业务逻辑为:
1、初始化触摸设备支持多种触摸芯片
2、处理原始触摸数据并解析为各种手势事件
3、通过统一消息接口发布触摸事件
4、提供消息发布控制功能
5、提供滑动和长按阈值配置功能
支持的触摸事件类型包括:
RAW_DATA、TOUCH_DOWN、MOVE_X、MOVE_Y、SWIPE_LEFT、SWIPE_RIGHT、
SWIPE_UP、SWIPE_DOWN、SINGLE_TAP、LONG_PRESS
本文件的对外接口有5个
1、extp.init(param):触摸设备初始化函数
2、extp.set_publish_enabled(msg_type, enabled):设置消息发布状态
3、extp.get_publish_enable(msg_type):获取消息发布状态
4、extp.set_swipe_threshold(threshold):设置滑动判定阈值
5、extp.set_long_press_threshold(threshold):设置长按判定阈值
所有触摸事件均通过sys.publish("BASE_TOUCH_EVENT", event_type, ...)发布
]]
local extp = {}
-- 触摸状态变量
local state = "IDLE" -- 当前状态IDLE(空闲), DOWN(按下), MOVE(移动)
local touch_down_x = 0 -- 按下时的X坐标
local touch_down_y = 0 -- 按下时的Y坐标
local touch_down_time = 0 -- 按下时的时间戳
local swipe_threshold = 45 -- 滑动判定阈值(像素)
local long_press_threshold = 500 -- 长按判定阈值(毫秒)
local swipe_direction = nil -- 滑动方向用于MOVE状态
-- 消息发布控制表,默认全部打开
local publish_control = {
RAW_DATA = false, -- 原始触摸数据
TOUCH_DOWN = false, -- 按下事件
MOVE_X = false, -- 水平移动
MOVE_Y = false, -- 垂直移动
SWIPE_LEFT = false, -- 向左滑动
SWIPE_RIGHT = false, -- 向右滑动
SWIPE_UP = false, -- 向上滑动
SWIPE_DOWN = false, -- 向下滑动
SINGLE_TAP = true, -- 单击
LONG_PRESS = true -- 长按
}
-- 定义支持的触摸芯片配置
local tp_configs = {
cst820 = { i2c_speed = i2c.FAST, tp_model = "cst820" },
gt9157 = { i2c_speed = i2c.FAST, tp_model = "gt9157" },
cst9220 = { i2c_speed = i2c.SLOW, tp_model = "cst9220" },
jd9261t = { i2c_speed = i2c.FAST, tp_model = "jd9261t" },
gt911 = { i2c_speed = i2c.SLOW, tp_model = "gt911" },
AirLCD_1010 = { i2c_speed = i2c.SLOW, tp_model = "gt911" },
Air780EHM_LCD_4 = { i2c_speed = i2c.SLOW, tp_model = "gt911" },
AirLCD_1020 = { i2c_speed = i2c.SLOW, tp_model = "gt911" }
}
-- 特殊型号的默认配置
local special_tp_configs = {
Air780EHM_LCD_4 = {
i2c_id = 1,
pin_rst = 1,
pin_int = 22
},
AirLCD_1010 = {
i2c_id = 0,
pin_rst = 20,
pin_int = gpio.WAKEUP0
},
AirLCD_1020 = {
i2c_id = i2c.createSoft(0, 1),
pin_rst = 28,
pin_int = 7
}
}
--[[
设置消息发布状态
@api extp.set_publish_enabled(msg_type, enabled)
@string msg_type 消息类型,支持"ALL"或具体事件类型
@bool enabled 是否启用发布
@return bool 操作成功返回true失败返回false
@usage
-- 启用单击事件
extp.set_publish_enabled("SINGLE_TAP", true)
-- 禁用所有消息发布
extp.set_publish_enabled("ALL", false)
]]
function extp.set_publish_enabled(msg_type, enabled)
if msg_type == "ALL" then
for k, _ in pairs(publish_control) do
publish_control[k] = enabled
end
log.info("extp", "所有消息发布", enabled and "启用" or "禁用")
return true
elseif publish_control[msg_type] ~= nil then
publish_control[msg_type] = enabled
log.info("extp", msg_type, "消息发布", enabled and "启用" or "禁用")
return true
else
log.error("extp", "未知的消息类型:", msg_type)
return false
end
end
--[[
获取消息发布状态
@api extp.get_publish_enable(msg_type)
@string msg_type 消息类型,"ALL"或具体事件类型
@return bool|table 发布状态或所有状态表
@usage
-- 获取单击事件状态
local enabled = extp.get_publish_enable("SINGLE_TAP")
-- 获取所有状态
local all_status = extp.get_publish_enable("ALL")
]]
function extp.get_publish_enable(msg_type)
if msg_type == "ALL" then
-- 返回完整的发布控制表
return publish_control
elseif publish_control[msg_type] ~= nil then
return publish_control[msg_type]
else
log.error("extp", "未知的消息类型:", msg_type)
return nil
end
end
--[[
设置滑动判定阈值
@api extp.set_swipe_threshold(threshold)
@number threshold 滑动判定阈值(像素)
@return bool 设置成功返回true失败返回false
@usage
-- 设置滑动阈值为50像素
extp.set_swipe_threshold(50)
]]
function extp.set_swipe_threshold(threshold)
if type(threshold) == "number" and threshold > 0 then
swipe_threshold = threshold
log.info("extp", "滑动判定阈值设置为:", threshold)
return true
else
log.error("extp", "无效的滑动阈值:", threshold)
return false
end
end
--[[
设置长按判定阈值
@api extp.set_long_press_threshold(threshold)
@number threshold 长按判定阈值(毫秒)
@return bool 设置成功返回true失败返回false
@usage
-- 设置长按阈值为800毫秒
extp.set_long_press_threshold(800)
]]
function extp.set_long_press_threshold(threshold)
if type(threshold) == "number" and threshold > 0 then
long_press_threshold = threshold
log.info("extp", "长按判定阈值设置为:", threshold)
return true
else
log.error("extp", "无效的长按阈值:", threshold)
return false
end
end
-- 触摸回调函数
-- 参数: tp_device-触摸设备对象, tp_data-触摸数据
local function tp_callback(tp_device, tp_data)
-- 发布原始数据
if publish_control.RAW_DATA then
sys.publish("BASE_TOUCH_EVENT", "RAW_DATA", tp_device, tp_data)
end
if type(tp_data[1]) ~= "table" then return end
local event_type = tp_data[1].event
local x = tp_data[1].x
local y = tp_data[1].y
-- 获取高精度时间戳
local _, ms_l = mcu.ticks2(1)
-- 使用系统时间戳或触摸数据中的时间戳
local timestamp = ms_l or tp_data[1].timestamp
if not event_type then return end
if event_type == 2 then -- 抬手事件
if state == "DOWN" or state == "MOVE" then
local moveX = x - touch_down_x
local moveY = y - touch_down_y
if moveX < -swipe_threshold then
if publish_control.SWIPE_LEFT then
sys.publish("BASE_TOUCH_EVENT", "SWIPE_LEFT", moveX, 0)
end
elseif moveX > swipe_threshold then
if publish_control.SWIPE_RIGHT then
sys.publish("BASE_TOUCH_EVENT", "SWIPE_RIGHT", moveX, 0)
end
elseif moveY < -swipe_threshold then
if publish_control.SWIPE_UP then
sys.publish("BASE_TOUCH_EVENT", "SWIPE_UP", 0, moveY)
end
elseif moveY > swipe_threshold then
if publish_control.SWIPE_DOWN then
sys.publish("BASE_TOUCH_EVENT", "SWIPE_DOWN", 0, moveY)
end
else
-- 计算按下时间
local press_time = timestamp - touch_down_time
-- 判断是单击还是长按
if press_time < long_press_threshold then
if publish_control.SINGLE_TAP then
sys.publish("BASE_TOUCH_EVENT", "SINGLE_TAP", touch_down_x, touch_down_y)
end
else
if publish_control.LONG_PRESS then
sys.publish("BASE_TOUCH_EVENT", "LONG_PRESS", touch_down_x, touch_down_y)
end
end
end
state = "IDLE"
end
elseif event_type == 1 or event_type == 3 then -- 按下或移动事件
if state == "IDLE" and event_type == 1 then
-- 从空闲状态接收到按下事件
state = "DOWN"
touch_down_x = x
touch_down_y = y
touch_down_time = timestamp
swipe_direction = nil
-- 发布按下事件
if publish_control.TOUCH_DOWN then
sys.publish("BASE_TOUCH_EVENT", "TOUCH_DOWN", x, y)
end
elseif state == "DOWN" and event_type == 3 then
-- 在按下状态下接收到移动事件
if math.abs(x - touch_down_x) >= swipe_threshold or math.abs(y - touch_down_y) >= swipe_threshold then
state = "MOVE"
-- 确定滑动方向
if math.abs(x - touch_down_x) > math.abs(y - touch_down_y) then
-- 水平滑动
if x - touch_down_x < 0 then
swipe_direction = "LEFT"
else
swipe_direction = "RIGHT"
end
else
-- 垂直滑动
if y - touch_down_y < 0 then
swipe_direction = "UP"
else
swipe_direction = "DOWN"
end
end
end
elseif state == "MOVE" and event_type == 3 then
-- 在移动状态下接收到移动事件
-- 根据滑动方向发布相应的移动事件
if swipe_direction == "LEFT" or swipe_direction == "RIGHT" then
-- 水平滑动发布MOVE_X事件
if publish_control.MOVE_X then
sys.publish("BASE_TOUCH_EVENT", "MOVE_X", x - touch_down_x, 0)
end
else
-- 垂直滑动发布MOVE_Y事件
if publish_control.MOVE_Y then
sys.publish("BASE_TOUCH_EVENT", "MOVE_Y", 0, y - touch_down_y)
end
end
end
end
end
--[[
初始化触摸设备
@api extp.init(param)
@table param 触摸芯片配置参数参考库的说明及demo用法
@return bool 初始化成功返回true失败返回false
@usage
-- 基础触摸初始化
extp.init({
tp_model = "gt911",
i2c_id = 0,
pin_rst = 20,
pin_int = 21
})
-- 使用预定义配置
extp.init({tp_model = "AirLCD_1010"})
-- 带屏幕尺寸的初始化
extp.init({
tp_model = "gt911",
i2c_id = 0,
pin_rst = 20,
pin_int = 21,
w = 480,
h = 320
})
]]
function extp.init(param)
if type(param) ~= "table" then
log.error("extp", "参数必须为表")
return false
end
-- 检查必要参数
if not param.tp_model then
log.error("extp", "缺少必要参数: tp_model")
return false
end
local tp_model = param.tp_model
-- 检查是否支持该型号
local config = tp_configs[tp_model]
if not config then
log.error("extp", "不支持的触摸型号:", tp_model)
return false
end
-- 特殊型号参数处理
local final_param = {}
final_param.tp_model = tp_model
-- 处理特殊型号的默认配置
if special_tp_configs[tp_model] then
local default_config = special_tp_configs[tp_model]
if tp_model == "Air780EHM_LCD_4" then
-- Air780EHM_LCD_4: 强制使用默认配置,忽略传入的其他参数
final_param.i2c_id = default_config.i2c_id
final_param.pin_rst = default_config.pin_rst
final_param.pin_int = default_config.pin_int
log.info("extp", "Air780EHM_LCD_4使用固定配置")
else
-- AirLCD_1010 和 AirLCD_1020: 使用传入参数,如果未传入则使用默认配置
final_param.i2c_id = param.i2c_id or default_config.i2c_id
final_param.pin_rst = param.pin_rst or default_config.pin_rst
final_param.pin_int = param.pin_int or default_config.pin_int
-- 记录使用的配置来源
if param.i2c_id then
log.info("extp", tp_model, "使用传入的i2c_id")
else
log.info("extp", tp_model, "使用默认i2c_id")
end
if param.pin_rst then
log.info("extp", tp_model, "使用传入的pin_rst")
else
log.info("extp", tp_model, "使用默认pin_rst")
end
if param.pin_int then
log.info("extp", tp_model, "使用传入的pin_int")
else
log.info("extp", tp_model, "使用默认pin_int")
end
end
else
-- 其他型号:直接使用传入参数
final_param.i2c_id = param.i2c_id
final_param.pin_rst = param.pin_rst
final_param.pin_int = param.pin_int
end
local tp_i2c_id, tp_pin_rst, tp_pin_int = final_param.i2c_id, final_param.pin_rst or 255, final_param.pin_int
-- 构建tp.init的参数表增加w和h可选参数
local tp_init_params = {
port = tp_i2c_id,
pin_rst = tp_pin_rst,
pin_int = tp_pin_int
}
-- 如果传入了w和h参数则添加到参数表中
if param.w then
tp_init_params.w = param.w
log.info("extp", "设置屏幕宽度:", param.w)
end
if param.h then
tp_init_params.h = param.h
log.info("extp", "设置屏幕高度:", param.h)
end
-- 统一初始化流程
if type(tp_i2c_id) ~= "userdata" and config.i2c_speed ~= nil then
i2c.setup(tp_i2c_id, config.i2c_speed)
end
-- 使用包含w和h参数的table调用tp.init
local tp_device = tp.init(config.tp_model, tp_init_params, tp_callback)
if tp_device ~= nil then return true end
if tp_device == nil then
-- 如果第一次初始化失败尝试不带pin_rst的初始化
tp_init_params.pin_rst = 255
local tp_device = tp.init(config.tp_model, tp_init_params, tp_callback)
if tp_device ~= nil then return true end
end
-- 若硬件触摸初始化失败尝试PC触摸回退
log.warn("extp", "触摸初始化失败尝试PC触摸回退")
local ok_pc, dev_pc = pcall(tp.init, "pc", { port = 0 }, tp_callback)
if ok_pc and dev_pc then
log.info("extp", "PC触摸回退成功")
return true
end
log.error("extp", "PC触摸回退失败")
return false
end
return extp