tsb_wavein_page.lua 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526
  1. --[[
  2. @module tsb_wavein_page
  3. @summary 波形输入页面
  4. @version 1.0
  5. @date 2026.03.18
  6. @author 李一玮
  7. @usage
  8. 本文件是波形输入页面,展示波形数据和控制功能。
  9. ]]
  10. local tsb_wavein_page = {}
  11. -- 页面UI元素
  12. local main_container = nil
  13. local scroll_container = nil
  14. local chart_timer = nil -- 数据推送定时器ID
  15. local page_active = false -- 页面是否活跃,用于定时器安全
  16. local common_ui = require("tsb_common_page")
  17. local chart = nil -- 图表对象
  18. local freq_label = nil -- 频率显示标签
  19. local vmax_label = nil -- 电压最大值标签
  20. local vmin_label = nil -- 电压最小值标签
  21. local trigger_threshold_input = nil -- 触发阈值输入框
  22. local trigger_type_btn = nil -- 触发类型按钮
  23. local trigger_mode_btn = nil -- 触发方式按钮
  24. -- 控制参数
  25. local time_scale = "100ms" -- 时间档位
  26. local vertical_scale = "1V" -- 垂直档位
  27. local trigger_threshold = "0" -- 触发阈值
  28. local trigger_type = "上升沿" -- 触发类型:上升沿、下降沿、双边沿
  29. local trigger_mode = "自动" -- 触发方式:自动、普通、单次
  30. -- 创建数字键盘
  31. local function create_numeric_keyboard()
  32. return airui.keyboard({
  33. x = 0,
  34. y = 0,
  35. w = 480,
  36. h = 220,
  37. mode = "numeric",
  38. auto_hide = true,
  39. bg_color = 0xf1f1f1,
  40. on_commit = function()
  41. log.info("keyboard", "commit")
  42. end
  43. })
  44. end
  45. -- 创建UI
  46. function tsb_wavein_page.create_ui()
  47. main_container = airui.container({
  48. x = 0,
  49. y = 0,
  50. w = 480,
  51. h = 320,
  52. color = 0xF5F5F5,
  53. })
  54. --------------------- 标题栏 ------------------------
  55. local title_bar = airui.container({
  56. parent = main_container,
  57. x = 0,
  58. y = 0,
  59. w = 480,
  60. h = 30,
  61. color = 0xFFD93D,
  62. })
  63. airui.label({
  64. parent = title_bar,
  65. text = "波形输入",
  66. x = 200,
  67. y = 8,
  68. w = 80,
  69. h = 20,
  70. font_size = 16,
  71. color = 0xFFFFFF,
  72. })
  73. -- 标题栏公共信息展示
  74. common_ui.add_battery_display(title_bar)
  75. common_ui.create_back_button(title_bar, tsb_wavein_page.cleanup)
  76. ---------------------------------------------------
  77. -- 主容器
  78. scroll_container = airui.container({
  79. parent = main_container,
  80. x = 0,
  81. y = 30,
  82. w = 480,
  83. h = 270,
  84. color = 0xFFFFFF,
  85. })
  86. -- 图表区域(左上方)
  87. local chart_container = airui.container({
  88. parent = scroll_container,
  89. x = 10,
  90. y = 10,
  91. w = 320,
  92. h = 200,
  93. color = 0xFFFFFF,
  94. radius = 8,
  95. border_width = 1,
  96. border_color = 0xDDDDDD,
  97. })
  98. chart = airui.chart({
  99. parent = chart_container,
  100. x = 10,
  101. y = 10,
  102. w = 300,
  103. h = 180,
  104. y_min = 0,
  105. y_max = 100,
  106. point_count = 100, -- 增加点数以适应宽屏
  107. update_mode = "shift", -- 滚动模式
  108. line_color = 0x00b4ff,
  109. line_width = 2,
  110. hdiv = 5,
  111. vdiv = 4,
  112. })
  113. -- 预置一组初始值(平滑过渡)
  114. chart:set_values(1, {50, 52, 54, 56, 58, 60, 62, 64, 66, 68, 70, 68, 66, 64, 62, 60, 58, 56, 54, 52, 50, 48, 46, 44, 42, 40, 38, 36, 34, 32, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48, 50})
  115. -- 控制区域(右侧)
  116. local control_container = airui.container({
  117. parent = scroll_container,
  118. x = 340,
  119. y = 10,
  120. w = 130,
  121. h = 155,
  122. color = 0xFFFFFF,
  123. radius = 8,
  124. border_width = 1,
  125. border_color = 0xDDDDDD,
  126. })
  127. local control_y = 10
  128. -- 时间档位
  129. airui.label({
  130. parent = control_container,
  131. text = "时间档位",
  132. x = 10,
  133. y = control_y,
  134. w = 110,
  135. h = 20,
  136. font_size = 12,
  137. color = 0x333333,
  138. })
  139. airui.dropdown({
  140. parent = control_container,
  141. x = 10,
  142. y = control_y + 20,
  143. w = 100,
  144. h = 25,
  145. options = {"1s", "500ms", "200ms", "100ms", "50ms", "20ms", "10ms", "5ms", "2ms", "1ms", "500us"},
  146. default_index = 3, -- 默认100ms
  147. on_change = function(self, idx)
  148. local options = {"1s", "500ms", "200ms", "100ms", "50ms", "20ms", "10ms", "5ms", "2ms", "1ms", "500us"}
  149. time_scale = options[idx + 1]
  150. log.info("chart", "时间档位: " .. time_scale)
  151. end
  152. })
  153. control_y = control_y + 50
  154. -- 垂直档位
  155. airui.label({
  156. parent = control_container,
  157. text = "垂直档位",
  158. x = 10,
  159. y = control_y,
  160. w = 110,
  161. h = 20,
  162. font_size = 12,
  163. color = 0x333333,
  164. })
  165. airui.dropdown({
  166. parent = control_container,
  167. x = 10,
  168. y = control_y + 20,
  169. w = 100,
  170. h = 25,
  171. options = {"10V", "5V", "2V", "1V", "500mv", "200mv"},
  172. default_index = 3, -- 默认1V
  173. on_change = function(self, idx)
  174. local options = {"10V", "5V", "2V", "1V", "500mv", "200mv"}
  175. vertical_scale = options[idx + 1]
  176. log.info("chart", "垂直档位: " .. vertical_scale)
  177. end
  178. })
  179. control_y = control_y + 50
  180. -- 水平偏移
  181. airui.label({
  182. parent = control_container,
  183. text = "水平偏移",
  184. x = 10,
  185. y = control_y,
  186. w = 110,
  187. h = 20,
  188. font_size = 12,
  189. color = 0x333333,
  190. })
  191. local h_offset_container = airui.container({
  192. parent = control_container,
  193. x = 10,
  194. y = control_y + 20,
  195. w = 110,
  196. h = 25,
  197. color = 0xFFFFFF,
  198. radius = 4,
  199. })
  200. airui.button({
  201. parent = h_offset_container,
  202. text = "←",
  203. x = 5,
  204. y = 2,
  205. w = 40,
  206. h = 20,
  207. on_click = function()
  208. log.info("chart", "水平偏移左")
  209. end
  210. })
  211. airui.button({
  212. parent = h_offset_container,
  213. text = "→",
  214. x = 60,
  215. y = 2,
  216. w = 40,
  217. h = 20,
  218. on_click = function()
  219. log.info("chart", "水平偏移右")
  220. end
  221. })
  222. control_y = control_y + 50
  223. -- 垂直偏移
  224. airui.label({
  225. parent = control_container,
  226. text = "垂直偏移",
  227. x = 10,
  228. y = control_y,
  229. w = 110,
  230. h = 20,
  231. font_size = 12,
  232. color = 0x333333,
  233. })
  234. local v_offset_container = airui.container({
  235. parent = control_container,
  236. x = 10,
  237. y = control_y + 20,
  238. w = 110,
  239. h = 25,
  240. color = 0xFFFFFF,
  241. radius = 4,
  242. })
  243. airui.button({
  244. parent = v_offset_container,
  245. text = "↑",
  246. x = 5,
  247. y = 2,
  248. w = 40,
  249. h = 20,
  250. on_click = function()
  251. log.info("chart", "垂直偏移上")
  252. end
  253. })
  254. control_y = control_y + 35
  255. airui.button({
  256. parent = v_offset_container,
  257. text = "↓",
  258. x = 60,
  259. y = 2,
  260. w = 40,
  261. h = 20,
  262. on_click = function()
  263. log.info("chart", "垂直偏移下")
  264. end
  265. })
  266. -- 触发控制区域
  267. local trigger_container = airui.container({
  268. parent = scroll_container,
  269. x = 340,
  270. y = 170,
  271. w = 130,
  272. h = 90,
  273. color = 0xFFFFFF,
  274. radius = 8,
  275. border_width = 1,
  276. border_color = 0xDDDDDD,
  277. })
  278. -- 触发阈值
  279. airui.label({
  280. parent = trigger_container,
  281. text = "触发阈值",
  282. x = 10,
  283. y = 5,
  284. w = 60,
  285. h = 20,
  286. font_size = 12,
  287. color = 0x333333,
  288. })
  289. trigger_threshold_input = airui.textarea({
  290. parent = trigger_container,
  291. x = 10,
  292. y = 25,
  293. w = 70,
  294. h = 25,
  295. text = "500",
  296. max_len = 5,
  297. keyboard = create_numeric_keyboard()
  298. })
  299. airui.label({
  300. parent = trigger_container,
  301. text = "mv",
  302. x = 90,
  303. y = 30,
  304. w = 30,
  305. h = 20,
  306. font_size = 12,
  307. color = 0x333333,
  308. })
  309. -- 触发类型
  310. trigger_type_btn = airui.button({
  311. parent = trigger_container,
  312. text = "上升沿",
  313. x = 10,
  314. y = 55,
  315. w = 55,
  316. h = 25,
  317. font_size = 10,
  318. on_click = function(self)
  319. if trigger_type == "上升沿" then
  320. trigger_type = "下降沿"
  321. elseif trigger_type == "下降沿" then
  322. trigger_type = "双边沿"
  323. else
  324. trigger_type = "上升沿"
  325. end
  326. self:set_text(trigger_type)
  327. log.info("chart", "触发类型: " .. trigger_type)
  328. end
  329. })
  330. -- 触发方式
  331. trigger_mode_btn = airui.button({
  332. parent = trigger_container,
  333. text = "自动",
  334. x = 70,
  335. y = 55,
  336. w = 50,
  337. h = 25,
  338. font_size = 10,
  339. on_click = function(self)
  340. if trigger_mode == "自动" then
  341. trigger_mode = "普通"
  342. elseif trigger_mode == "普通" then
  343. trigger_mode = "单次"
  344. else
  345. trigger_mode = "自动"
  346. end
  347. self:set_text(trigger_mode)
  348. log.info("chart", "触发方式: " .. trigger_mode)
  349. end
  350. })
  351. -- 信息显示区域(图表下方)
  352. local info_container = airui.container({
  353. parent = scroll_container,
  354. x = 10,
  355. y = 220,
  356. w = 320,
  357. h = 40,
  358. color = 0xFFFFFF,
  359. radius = 8,
  360. border_width = 1,
  361. border_color = 0xDDDDDD,
  362. })
  363. airui.label({
  364. parent = info_container,
  365. text = "频率:",
  366. x = 5,
  367. y = 10,
  368. w = 40,
  369. h = 20,
  370. font_size = 13,
  371. color = 0x333333,
  372. })
  373. freq_label = airui.label({
  374. parent = info_container,
  375. text = "10.0 Hz",
  376. x = 40,
  377. y = 10,
  378. w = 60,
  379. h = 20,
  380. font_size = 13,
  381. color = 0x333333,
  382. })
  383. airui.label({
  384. parent = info_container,
  385. text = "V大:",
  386. x = 110,
  387. y = 10,
  388. w = 60,
  389. h = 20,
  390. font_size = 13,
  391. color = 0x333333,
  392. })
  393. vmax_label = airui.label({
  394. parent = info_container,
  395. text = "80.0 mV",
  396. x = 140,
  397. y = 10,
  398. w = 65,
  399. h = 20,
  400. font_size = 13,
  401. color = 0x333333,
  402. })
  403. airui.label({
  404. parent = info_container,
  405. text = "V小:",
  406. x = 220,
  407. y = 10,
  408. w = 80,
  409. h = 20,
  410. font_size = 13,
  411. color = 0x333333,
  412. })
  413. vmin_label = airui.label({
  414. parent = info_container,
  415. text = "20.0 mV",
  416. x = 250,
  417. y = 10,
  418. w = 65,
  419. h = 20,
  420. font_size = 13,
  421. color = 0x333333,
  422. })
  423. -- 底部信息
  424. common_ui.create_status_bar(main_container)
  425. end
  426. -- 定时器回调:模拟10Hz数据推送
  427. local function chart_timer_cb()
  428. if not page_active then
  429. return -- 页面已销毁,不再更新
  430. end
  431. -- 简单的正弦波模拟
  432. local tick = _G.__chart_tick or 0
  433. tick = tick + 1
  434. _G.__chart_tick = tick
  435. local base = 50 + 30 * math.sin(tick * 0.1)
  436. local noise = math.random(-3, 3)
  437. local value = math.floor(base + noise + 0.5)
  438. -- 限制范围
  439. if value < 0 then value = 0 end
  440. if value > 100 then value = 100 end
  441. if chart then
  442. chart:push(1, value)
  443. end
  444. -- 每50个周期更新一次信息显示
  445. if tick % 50 == 0 then
  446. if freq_label then
  447. freq_label:set_text("10.0 Hz")
  448. end
  449. if vmax_label then
  450. vmax_label:set_text("80.0 mV")
  451. end
  452. if vmin_label then
  453. vmin_label:set_text("20.0 mV")
  454. end
  455. log.info("chart", "running 10Hz, sample=", value)
  456. end
  457. end
  458. -- 初始化页面
  459. function tsb_wavein_page.init(params)
  460. tsb_wavein_page.create_ui()
  461. page_active = true
  462. -- 启动定时器(100ms = 10Hz)
  463. if chart_timer then
  464. sys.timerStop(chart_timer)
  465. end
  466. chart_timer = sys.timerLoopStart(chart_timer_cb, 100)
  467. end
  468. -- 清理页面
  469. function tsb_wavein_page.cleanup()
  470. page_active = false
  471. if chart_timer then
  472. sys.timerStop(chart_timer)
  473. chart_timer = nil
  474. end
  475. if main_container then
  476. main_container:destroy()
  477. main_container = nil
  478. scroll_container = nil
  479. chart = nil
  480. freq_label = nil
  481. vmax_label = nil
  482. vmin_label = nil
  483. trigger_threshold_input = nil
  484. trigger_type_btn = nil
  485. trigger_mode_btn = nil
  486. end
  487. end
  488. return tsb_wavein_page