ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

IronOS 用户界面(UI)架构解析:logic/drawing 双层模式机、屏幕类型与渲染管线

IronOS 用户界面(UI)架构解析:logic/drawing 双层模式机、屏幕类型与渲染管线 嵌入式固件硬件开发智能硬件【免费下载链接】IronOSOpen Source Soldering Iron firmware项目地址https://gitcode.com/gh_mirrors/ir/IronOS点击查看免费下载导读本文以 UI 目录 README 为骨架深入剖析 IronOS开源焊台固件的用户界面如何被拆分为logic模式逻辑与drawing屏幕绘制两个半区并进一步按屏幕类型128×32、96×16细分绘制实现。读者将理解每个 UI 模式的状态机组织方式、guiContext上下文与 scratch 状态的设计意图、渲染循环与转场动画的工作机制以及各模式对应的逻辑文件与绘制文件如何协作为二次开发、移植新焊台或调试 UI 行为提供可直接对照源码的实战指引。一、整体架构UI 的两个半区IronOS 的用户界面位于 source/Core/Threads/UI整个 UI 被刻意拆分为两个半区halflogic文件夹存放实现每个模式逻辑的.cpp文件负责处理按键事件button events与任何业务逻辑。它回答这个模式该做什么、按键按下后去哪个模式。drawing文件夹存放仅负责屏幕绘制的.cpp文件回答这个模式在屏幕上画什么。绘制文件进一步按**屏幕类型screen types**细分。对应地drawing下存在两个屏幕类型子目录mono_128x32面向 128×32 单色 OLED如 Miniware TS100/TS80 系列、Sequre 部分机型mono_96x16面向 96×16 单色 OLED如 Pinecil、MHP30 等。两个子目录拥有同名同签名的绘制函数例如draw_homescreen_detailed.cpp、draw_soldering_power_status.cpp、pre_render_assets.cpp等通过编译期宏OLED_128x32/OLED_96x16选择实现。屏幕类型宏在各自 BSP 的 configuration.h 中定义例如Miniware/configuration.h#define OLED_128x32 1、#define OLED_96x16 1Pinecil/configuration.h#define OLED_96x16 1MHP30/configuration.h#define OLED_96x16 1Sequre/configuration.h#define OLED_128x32 1。所有绘制函数通过统一的头文件 ui_drawing.hpp 暴露接口逻辑层只依赖该接口不关心实际屏幕尺寸——这是两层解耦的关键。二、逻辑层模式机与按键状态2.1 所有模式共用一个OperatingMode状态枚举逻辑层的心脏是 OperatingModes.h 中定义的OperatingMode枚举它覆盖了 IronOS 的全部 UI 状态枚举值含义StartupLogo显示启动 LogoCJCCalibration冷端CJC校准StartupWarnings启动检查与警告InitialisationDone首次启动进入主界面前的特殊过渡态允许跳转到其他启动态HomeScreen主界面作为进入其他模式的发射台Soldering主焊接模式SolderingProfile跟随温度曲线焊接如回流焊 reflowSleeping睡眠态保持较低睡眠温度Hibernating休眠态加热器完全关闭直至唤醒SettingsMenu设置菜单DebugMenuReadout调试信息TemperatureAdjust目标温度调整UsbPDDebugUSB-PD 调试信息ThermalRunaway热失控警告这些模式分别由逻辑文件实现主界面在 HomeScreen.cpp、焊接在 Soldering.cpp、曲线焊接在 SolderingProfile.cpp、睡眠在 Sleep.cpp、设置菜单在 SettingsMenu.cpp、调试菜单在 DebugMenu.cpp、温度调整在 TemperatureAdjust.cpp、启动警告在 ShowStartupWarnings.cpp另有 CJC 校准 CJC.cpp 与三个 USB-PD 调试实现USBPDDebug_FUSB.cpp、USBPDDebug_FS2711.cpp、USBPDDebug_HUSB238.cpp。2.2 按键状态机ButtonState按键输入由 Buttons.hpp 中的ButtonState枚举描述BUTTON_NONE 0, /* 无按键 / 低于滤波时间 */ BUTTON_F_SHORT 1, /* 前键front短按 */ BUTTON_B_SHORT 2, /* 后键back短按 */ BUTTON_F_LONG 4, /* 前键长按持续按住 */ BUTTON_B_LONG 8, /* 后键长按 */ BUTTON_BOTH 16, /* 同时按下两键按下并释放 */ BUTTON_BOTH_LONG 32, /* 两键同时长按 */注意其中注释的语义Pressed 表示完整的按下释放脉冲__/holding 表示按键保持低电平超过滤波时间。所有逻辑文件都围绕这 7 种按键状态编写switch分支。例如主界面 HomeScreen.cpp 中BUTTON_F_SHORT→ 进入Soldering若烙铁头未断开BUTTON_B_SHORT→ 进入SettingsMenuBUTTON_F_LONG→ 进入SolderingProfile开启PROFILE_SUPPORT时BUTTON_B_LONG→ 进入DebugMenuReadout。2.3 上下文与 scratch 状态guiContext每个模式函数都以(const ButtonState buttons, guiContext *cxt)为签名返回下一个OperatingMode。guiContext定义于 OperatingModes.h承担跨渲染帧的状态保持struct guiContext { TickType_t viewEnterTime; // 进入该视图的 tick 时间 OperatingMode previousMode; // 上一个模式 TransitionAnimation transitionMode;// 转场动画方向 struct scratch { // 跨重绘保留、模式切换时清空的草稿状态 uint16_t state1, state2, state5, state6; uint32_t state3, state4, state7; } scratch_state; };设计意图非常明确与 GUIRendering.md 中类即时模式渲染理念一致函数应尽量把状态收敛到 context 结构里保持状态使用扁平化。这样外部事件可以改变状态状态也可经 BLE 等外部控制接口读写。各模式把scratch_state的不同字段当作局部变量使用例如焊接模式 Soldering.cpp 中state1 按键锁定状态0 未锁定已释放1 未锁定2 已锁定3 已锁定已释放state2 升压boost模式state3 蜂鸣器定时器设置菜单 SettingsMenu.cpp 中state1 根菜单条目、state2 子菜单条目、state3/state4 自动重复加速定时、state5 当前菜单长度缓存、state6 是否正在渲染帮助文本温度调整 TemperatureAdjust.cpp 中state1 等待释放标志、state2/state3 自动重复加速。scratch_state在模式切换时会被整体清零见下文渲染循环因此它天然不适合承载需要跨模式保留的数据——跨模式数据应放全局变量或设置项。三、绘制层按屏幕类型细分的绘制函数3.1 统一接口绘制层通过 ui_drawing.hpp 暴露以下核心接口均为void或bool返回只画屏不改状态void ui_draw_warning_undervoltage(void); void ui_draw_power_source_icon(void); void ui_draw_tip_temperature(bool symbol, const FontStyle font); bool warnUser(const char *warning, const ButtonState buttons); void ui_draw_cjc_sampling(const uint8_t num_dots); void ui_draw_debug_menu(const uint8_t item_number); void ui_draw_homescreen_detailed(TemperatureType_t tipTemp); void ui_draw_homescreen_simplified(TemperatureType_t tipTemp); void ui_pre_render_assets(void); void ui_draw_soldering_power_status(bool boost_mode_on); void ui_draw_soldering_basic_status(bool boostModeOn); void ui_draw_soldering_detailed_sleep(TemperatureType_t tipTemp); void ui_draw_soldering_basic_sleep(TemperatureType_t tipTemp); void ui_draw_soldering_profile_advanced(...); void ui_draw_temperature_change(void); void ui_draw_usb_pd_debug_state(...); void ui_draw_usb_pd_debug_pdo(...); void printVoltage(void);从函数命名可看出绘制层遵循两条轴线详细/简化视图detailed/simplified由DetailedIDLE、DetailedSoldering设置项控制与模式主界面/焊接/睡眠/温度调整/调试等。3.2 以主界面为例同一函数两种屏幕类型ui_draw_homescreen_detailed在 mono_128x32/draw_homescreen_detailed.cpp 与 mono_96x16/draw_homescreen_detailed.cpp 各有一份实现都通过#ifdef OLED_128x32/#ifdef OLED_96x16保护。两者逻辑一致差异在布局常量128×32 版大号12×24温度数字垂直居中靠一侧另一侧两行 SMALL8×16状态行设定温度、输入电压断头tip disconnected时在对应侧绘制disconnectedTip位图并显示电压xTaskGetTickCount() % 1000 300控制CoolingTempBlink的 300ms 灭/700ms 亮闪烁96×16 版单行布局温度与电压分居左右两侧同样处理断头与闪烁。两个版本都考虑OLED::getRotation()来左右翻转布局适应左右手持握。绘制前会先通过ui_pre_render_assets见 mono_128x32/pre_render_assets.cpp把位图预翻转存入 RAM避免每帧实时镜像。3.3 焊接状态的两种视图焊接时根据DetailedSoldering设置选择详细视图draw_soldering_power_status.cpp大号温度 功率取自x10WattHistory.average()超过 99.9W 时去掉小数位保持 5 格宽度 输入电压基础视图draw_soldering_basic_status.cpp温度、设定值、电源类型图标与电压等更紧凑的信息。焊接逻辑 Soldering.cpp 在调用绘制前完成全部决策根据state2boost选择目标温度SolderingTemp或BoostTemp并按TemperatureInF转换误差 ±10℃ 内判定收敛触发蜂鸣器与LED_HOT否则LED_HEATING随后依次检查checkExitSoldering()欠压退出、shouldBeSleeping()、heaterThermalRunawayCounter 8热失控后才把剩余按键交给handleSolderingButtons。四、渲染循环与转场动画4.1 GUI 线程类即时模式渲染UI 在 FreeRTOS 的 GUI 线程中运行入口是 GUIThread.cpp 的startGUITaskL215-L243。启动时依次完成翻译准备prepareTranslations、OLED 初始化、亮度/反色/旋转设置、ui_pre_render_assets预渲染资源随后进入for(;;)主循环以vTaskDelayUntil(startRender, TICKS_100MS * 4 / 10)维持约 20–25 FPS。核心渲染函数是guiRenderLoopL144-L193每帧流程调用guiHandleDraw()完成一次屏幕绘制若返回的模式与当前模式不同则记录viewEnterTime、previousMode清零scratch_state并切换模式若context.transitionMode非None则切换到 OLED 次级帧缓冲再渲染一帧新视图然后按动画类型transitionScrollDown/transitionSecondaryFramebuffer在两缓冲间转场最后OLED::refresh()输出。guiHandleDrawL44-L143是模式机的分发中心先读取按键状态依据温度/灵敏度决定屏幕亮灭与状态 LED睡眠判定逻辑见 shouldDeviceSleep.cpp再以switch(currentOperatingMode)把当前模式分发给对应的逻辑函数drawHomeScreen、gui_solderingMode、gui_SolderingSleepingMode、gui_solderingTempAdjust、showDebugMenu、performCJCC、gui_SettingsMenu、showPDDebug、showWarnings等。4.2 转场动画与方向语义转场方向定义于 OperatingModes.h 的TransitionAnimation枚举None/Right/Left/Down/Up。其方向感用于强化菜单导航的空间隐喻。GUI 线程只实现了Left、Right、Down三种动画Up尚未实现但枚举已预留。方向约定可参考 GUIRendering.md 中的示意图主界面向下 → 调试菜单焊接/曲线焊接模式 ← 主界面 ← 设置主菜单 ← 设置子菜单设置子菜单之间纵向滚动Down。实际代码中的用法示例主界面按后键短按进入设置菜单时设TransitionAnimation::RightHomeScreen.cpp设置菜单返回时设TransitionAnimation::Left进入子菜单用Right退出用LeftSettingsMenu.cpp主界面进入调试菜单用DownHomeScreen.cpp调试菜单返回用UpDebugMenu.cpp。在详细视图模式DetailedIDLE DetailedSoldering下部分转场会被抑制为None因为布局已足够相似、无需动画。转场得以实现的前提是逻辑函数先渲染当前屏幕再返回新状态保证切换前帧缓冲中有完整的旧视图随后分发层自动再渲染一帧新视图到次级缓冲并完成过渡见 GUIThread.cpp。五、关键模式逐个拆解5.1 设置菜单最复杂的 UI 代码SettingsMenu.cpp 自述为最复杂的 GUI 代码采用两级菜单结构主菜单分类→ 子菜单设置项。其数据驱动核心是menuitem结构数组rootSettingsMenu与subSettingsMenus定义于 settingsGUI.hpp每个条目含绘制回调、可见性回调、增量处理回调及多语言短描述/长描述索引。关键机制帮助文本render_menu在按键静止超过 3 秒HELP_TEXT_TIMEOUT_TICKS TICKS_SECOND * 3后从设置项视图自动切换为滚动显示该设置的长描述drawScrollingText滚动指示器getMenuLength遍历菜单计算可见条目数隐藏条目不计入indicatorHeight OLED_HEIGHT / menuLength计算指示条高度末项或闪烁节拍时隐藏/闪烁SettingsMenu.cpp自动重复与加速长按前/后键时autoRepeatAcceleration按PRESS_ACCEL_STEP递增、受PRESS_ACCEL_INTERVAL_MAX/MIN钳制实现越按越快的数值滚动按键交换ReverseButtonSettings开启时在进入分支前交换前后键语义L200-L219保存时机翻过主菜单末尾draw nullptr或双键退出时调用saveSettings()持久化设置。5.2 焊接模式setpoint、蜂鸣与安全退出焊接主逻辑 Soldering.cpp 的状态机完整注释L94-L107概括了交互流程短按任意键 → 温度调整屏TemperatureAdjust长按前键 → 升压模式临时切换 PID 目标温度到BoostTemp长按后键 / 双键 → 退出回主界面双键长按 → 按键锁定/解锁锁定逻辑由state1与LockingMode设置项控制。温度收敛检测L124-L140目标与实际温差落入 ±10℃ 即视为收敛触发一次 1/3 秒蜂鸣并点亮LED_HOT否则LED_HEATING。安全出口依次为欠压退出checkExitSoldering内部调用 checkUndervoltage.cpp 的checkForUnderVoltage在 DC 供电且电压低于lookupVoltageLevel()时把currentTempTargetDegC归零并绘制ui_draw_warning_undervoltage、关机判定shouldShutdown见 shouldDeviceShutdown.cpp超时或后键长按触发、睡眠判定与热失控保护heaterThermalRunawayCounter 8。5.3 温度调整带约束的增量步进TemperatureAdjust.cpp 进入时先关闭加热器currentTempTargetDegC 0并等待用户松开按键waitForRelease后才响应输入。增量来源短按TempChangeShortStep长按TempChangeLongStep配合自动重复加速ReverseButtonTempChangeEnabled开启时对delta取反。新值会按增量取整newTemp (newTemp / delta) * delta并钳制在MIN_TEMP_C ~ MAX_TEMP_C或华氏MIN_TEMP_F ~ MAX_TEMP_F范围内然后写回SolderingTemp设置。3 秒无操作或双键退出退出前saveSettings()。5.4 曲线焊接回流焊分阶段温度斜坡SolderingProfile.cpp 实现分段温度曲线阶段 0 为预热目标ProfilePreheatTemp、速率ProfilePreheatSpeed随后依次执行ProfilePhase1..5的 {温度, 持续时间}全部完成后进入冷却段速率ProfileCooldownSpeed烙铁头低于 55℃ 时蜂鸣并返回主界面。相位完成条件为达到目标温度且时间达标L71斜坡目标按每 tick 温度增量 相时长/(温差)线性插值L128-L141。绘制时详细视图调用ui_draw_soldering_profile_advanced显示当前相位、剩余时间与目标温度并叠加功率状态。5.5 睡眠/休眠与启动警告Sleep.cpp 统一处理Sleeping与Hibernating前者把目标温度降到min(SleepTemp, SolderingTemp)后者完全关闭加热currentTempTargetDegC 0shouldBeSleeping()恢复时返回previousModeShowStartupWarnings.cpp 用state1作为警告序号依次检查设置被重置settingsWereReset、设备防伪校验、加速度计缺失AccelMissingWarningCounter计数小于 2 时提示、PD 控制器缺失FUSB/HUB238/FS2711 三种实现按POW_PD_EXT宏选择探测全部通过后进入StartupLogo。六、如何定位与扩展 UI 代码对开发者而言UI 相关改动遵循清晰的分工改逻辑进入 logic 对应模式文件如焊接Soldering.cpp、主界面HomeScreen.cpp修改按键处理、状态转移、目标温度等决策改画面进入 drawing/mono_128x32 或 drawing/mono_96x16 修改同名绘制函数且必须两个屏幕类型同步维护同名函数、同一签名新增模式在 OperatingModes.h 增加枚举值在 GUIThread.cpp 的switch分发中加入分支并在 ui_drawing.hpp 声明新的绘制接口后到两个 drawing 子目录实现跨状态数据优先放入guiContext.scratch_state模式内保留或全局变量跨模式模式切换时scratch_state会被清零转场动画在返回新模式前设置cxt-transitionMode为Left/Right/DownUp枚举已预留但动画未实现见 GUIRendering.md。整体架构可用一句话概括逻辑层决定去往何方绘制层决定画成何样GUI 线程以类即时模式每帧重绘并驱动转场guiContext在两者之间传递状态。理解这一分工后无论是修 bug、加功能还是移植到新屏幕尺寸的焊台都能在 source/Core/Threads/UI 目录下快速定位到正确文件。赞分享嵌入式固件硬件开发智能硬件【免费下载链接】IronOSOpen Source Soldering Iron firmware项目地址https://gitcode.com/gh_mirrors/ir/IronOS点击查看免费下载相关推荐Open3D多线程渲染架构RenderToBuffer与离屏渲染技术Open3D多线程渲染架构RenderToBuffer与离屏渲染技术 离屏渲染技术概述 离屏渲染Offscreen Rendering是Open3D可视化计算机视觉图形学3D渲染科学计算OpenRocket 架构深度解析JPMS 双模块设计、仿真引擎与 3D 渲染管线OpenRocket 架构深度解析JPMS 双模块设计、仿真引擎与 3D 渲染管线 OpenRocket 是一款基于 Java 与 Swing 的模型火箭气动桌面应用科学计算3D渲染OpenUI AgentInterface 深度解析复合式 Agent 聊天界面组件的架构、插槽 API 与渲染管线OpenUI AgentInterface 深度解析复合式 Agent 聊天界面组件的架构、插槽 API 与渲染管线 OpenUIThe Open Stan上一篇专业级AMD Ryzen硬件调试工具5大核心功能实战优化指南下一篇AlienFX Tools500KB轻量级工具彻底取代臃肿的Alienware Command Center创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表