ui_main.lua 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339
  1. --[[
  2. @module ui_main
  3. @summary 显示主模块
  4. @version 1.0
  5. @date 2025.12.11
  6. @author 江访
  7. @usage
  8. 本文件为显示主模块,核心业务逻辑为:
  9. 1、初始化ht1621液晶屏
  10. 2、显示时间或日期页面
  11. 3、处理按键切换页面
  12. 4、定时更新显示内容
  13. 5、冒号闪烁控制
  14. 本文件对外接口:无
  15. ]]
  16. -- 引入驱动模块
  17. local ht1621_drv = require "ht1621_drv"
  18. local key_drv = require "key_drv"
  19. -- 段码屏对象
  20. local seg = nil
  21. -- 当前显示页面:time或date
  22. local current_page = "time"
  23. -- 冒号状态:true为亮,false为灭
  24. local colon_state = true
  25. -- 冒号闪烁定时器ID
  26. local colon_timer = nil
  27. -- 定时更新定时器ID
  28. local update_timer = nil
  29. -- 数字段码表 (0-9)
  30. local digit_map = {
  31. [0] = 0xEB, -- 0
  32. [1] = 0x0A, -- 1
  33. [2] = 0xAD, -- 2
  34. [3] = 0x8F, -- 3
  35. [4] = 0x4E, -- 4
  36. [5] = 0xC7, -- 5
  37. [6] = 0xE7, -- 6
  38. [7] = 0x8A, -- 7
  39. [8] = 0xEF, -- 8
  40. [9] = 0xCF -- 9
  41. }
  42. -- 星期数字映射 (1-7)
  43. local week_map = {
  44. ["Monday"] = 1,
  45. ["Tuesday"] = 2,
  46. ["Wednesday"] = 3,
  47. ["Thursday"] = 4,
  48. ["Friday"] = 5,
  49. ["Saturday"] = 6,
  50. ["Sunday"] = 7
  51. }
  52. --[[
  53. 清屏函数
  54. @summary 清除所有显示
  55. ]]
  56. local function clear_display()
  57. if not seg then return end
  58. for i = 0, 11 do
  59. ht1621.data(seg, i, 0x00)
  60. end
  61. end
  62. --[[
  63. 显示单个数字到指定位置
  64. @param position number 显示位置 (0,2,4,6,8,10)
  65. @param num number 要显示的数字 (0-9)
  66. @param show_dp boolean 是否显示该位置的小数点
  67. ]]
  68. local function show_digit(position, num, show_dp)
  69. if not seg then return end
  70. if num < 0 or num > 9 then return end
  71. local value = digit_map[num]
  72. if show_dp then
  73. value = value | 0x10 -- 添加小数点
  74. end
  75. ht1621.data(seg, position, value)
  76. end
  77. --[[
  78. 显示时间页面
  79. @summary 显示时间和星期
  80. ]]
  81. local function show_time()
  82. if not seg then return end
  83. -- 清屏
  84. clear_display()
  85. -- 获取当前时间
  86. local now = os.date("*t")
  87. local hour_str = string.format("%02d", now.hour)
  88. local min_str = string.format("%02d", now.min)
  89. -- 获取星期数字 (1-7)
  90. local week_name = os.date("%A")
  91. local week_num = week_map[week_name] or 1
  92. -- 显示时间
  93. -- 位置1: 小时的十位 (位置0)
  94. show_digit(0, tonumber(string.sub(hour_str, 1, 1)), false)
  95. -- 位置2: 小时的个位 (位置2,带冒号)
  96. show_digit(2, tonumber(string.sub(hour_str, 2, 2)), colon_state)
  97. -- 位置3: 分钟的十位 (位置4)
  98. show_digit(4, tonumber(string.sub(min_str, 1, 1)), false)
  99. -- 位置4: 分钟的个位 (位置6)
  100. show_digit(6, tonumber(string.sub(min_str, 2, 2)), false)
  101. -- 位置6: 星期 (位置10,显示1-7)
  102. show_digit(10, week_num, false)
  103. -- 设置当前页面
  104. current_page = "time"
  105. log.info("ui_main", string.format("显示时间: %s:%s 星期%d", hour_str, min_str, week_num))
  106. end
  107. --[[
  108. 显示日期页面
  109. @summary 显示年月日
  110. ]]
  111. local function show_date()
  112. if not seg then return end
  113. -- 清屏
  114. clear_display()
  115. -- 获取当前日期
  116. local now = os.date("*t")
  117. local year_str = string.sub(tostring(now.year), 3, 4) -- 最后两位
  118. local month_str = string.format("%02d", now.month)
  119. local day_str = string.format("%02d", now.day)
  120. -- 显示日期
  121. -- 位置1: 年份的十位 (位置0)
  122. show_digit(0, tonumber(string.sub(year_str, 1, 1)), false)
  123. -- 位置2: 年份的个位 (位置2)
  124. show_digit(2, tonumber(string.sub(year_str, 2, 2)), false)
  125. -- 位置3: 月份的十位 (位置4)
  126. show_digit(4, tonumber(string.sub(month_str, 1, 1)), false)
  127. -- 位置4: 月份的个位 (位置6)
  128. show_digit(6, tonumber(string.sub(month_str, 2, 2)), false)
  129. -- 位置5: 日期的十位 (位置8)
  130. show_digit(8, tonumber(string.sub(day_str, 1, 1)), false)
  131. -- 位置6: 日期的个位 (位置10)
  132. show_digit(10, tonumber(string.sub(day_str, 2, 2)), false)
  133. -- 设置当前页面
  134. current_page = "date"
  135. log.info("ui_main", string.format("显示日期: %s-%s-%s", year_str, month_str, day_str))
  136. end
  137. --[[
  138. 设置冒号状态
  139. @param state boolean 冒号状态,true为亮,false为灭
  140. ]]
  141. local function set_colon_state(state)
  142. colon_state = state
  143. -- 如果当前显示的是时间页面,更新冒号显示
  144. if current_page == "time" then
  145. local now = os.date("*t")
  146. local hour_str = string.format("%02d", now.hour)
  147. show_digit(2, tonumber(string.sub(hour_str, 2, 2)), colon_state)
  148. end
  149. end
  150. --[[
  151. 冒号闪烁处理函数
  152. @summary 每秒钟切换冒号的亮灭状态
  153. ]]
  154. local function colon_blink_callback()
  155. local current_state = colon_state
  156. set_colon_state(not current_state)
  157. end
  158. --[[
  159. 启动冒号闪烁
  160. @summary 创建冒号闪烁定时器
  161. ]]
  162. local function start_colon_blink()
  163. if colon_timer then
  164. sys.timerStop(colon_timer)
  165. end
  166. colon_timer = sys.timerLoopStart(colon_blink_callback, 1000) -- 每1秒执行一次
  167. end
  168. --[[
  169. 停止冒号闪烁
  170. @summary 停止冒号闪烁定时器
  171. ]]
  172. local function stop_colon_blink()
  173. if colon_timer then
  174. sys.timerStop(colon_timer)
  175. colon_timer = nil
  176. end
  177. end
  178. --[[
  179. 定时更新显示内容
  180. @summary 每30秒检查并更新显示内容
  181. ]]
  182. local function periodic_update_callback()
  183. if current_page == "time" then
  184. show_time()
  185. else
  186. show_date()
  187. end
  188. log.info("ui_main", "定时更新显示内容")
  189. end
  190. --[[
  191. 启动定时更新
  192. @summary 创建定时更新定时器
  193. ]]
  194. local function start_periodic_update()
  195. if update_timer then
  196. sys.timerStop(update_timer)
  197. end
  198. update_timer = sys.timerLoopStart(periodic_update_callback, 30000) -- 每30秒执行一次
  199. end
  200. --[[
  201. 停止定时更新
  202. @summary 停止定时更新定时器
  203. ]]
  204. local function stop_periodic_update()
  205. if update_timer then
  206. sys.timerStop(update_timer)
  207. update_timer = nil
  208. end
  209. end
  210. --[[
  211. 切换显示页面
  212. @summary 在时间和日期页面之间切换
  213. ]]
  214. local function toggle_page()
  215. if current_page == "time" then
  216. show_date()
  217. -- 停止冒号闪烁
  218. stop_colon_blink()
  219. else
  220. show_time()
  221. -- 启动冒号闪烁
  222. start_colon_blink()
  223. end
  224. end
  225. --[[
  226. 按键事件处理回调
  227. @param key_event string 按键事件类型
  228. ]]
  229. local function key_event_callback(key_event)
  230. if key_event == "boot_down" then
  231. -- 切换显示页面
  232. toggle_page()
  233. log.info("ui_main", "按键切换页面")
  234. end
  235. end
  236. --[[
  237. 按键事件处理函数
  238. @summary 处理按键事件,切换显示页面
  239. ]]
  240. local function handle_key_event()
  241. sys.subscribe("KEY_EVENT", key_event_callback)
  242. end
  243. --[[
  244. 开机显示函数
  245. @summary 显示全8图案和所有特殊符号,持续1秒
  246. ]]
  247. local function show_boot_screen()
  248. if not seg then return end
  249. -- 显示全8图案和所有特殊符号,不同ht1621地址可能不同,此接口可用于测试
  250. ht1621.data(seg, 0, 0xEF | 0x10) -- 显示第一个8和电池图标
  251. ht1621.data(seg, 2, 0xEF | 0x10) -- 显示第二个8和冒号
  252. ht1621.data(seg, 4, 0xEF | 0x10) -- 显示第三个8和温度圆圈
  253. ht1621.data(seg, 6, 0xEF | 0x10) -- 显示第四个8和右下小数点
  254. ht1621.data(seg, 8, 0xEF | 0x10) -- 显示第五个8和右下小数点
  255. ht1621.data(seg, 10, 0xEF | 0x10) -- 显示第六个8和右下小数点
  256. log.info("ui_main", "显示开机画面")
  257. end
  258. --[[
  259. 主函数
  260. @summary 初始化所有组件并启动主逻辑
  261. ]]
  262. local function main()
  263. -- 初始化HT1621驱动,获取seg对象
  264. seg = ht1621_drv.init()
  265. if not seg then
  266. log.error("ui_main", "HT1621驱动初始化失败")
  267. return
  268. end
  269. -- 显示开机画面
  270. show_boot_screen()
  271. sys.wait(1000)
  272. -- 注册按键事件处理
  273. handle_key_event()
  274. -- 初始显示时间页面
  275. show_time()
  276. -- 启动冒号闪烁
  277. start_colon_blink()
  278. -- 启动定时更新
  279. start_periodic_update()
  280. -- 启动内存监控(可选,调试时开启)
  281. -- sys.timerLoopStart(monitor_memory, 3000)
  282. log.info("ui_main", "显示主模块初始化完成")
  283. end
  284. -- 运行主函数
  285. sys.taskInit(main)