27 KiB
27 KiB
TactileIPC3D 架构说明
UML (Mermaid)
classDiagram
class AppBackend {
+bool lightMode
+string language
+bool connected
+SerialBackend* serial
+DataBackend* data
+int rangeMin
+int rangeMax
+QColor colorLow
+QColor colorMid
+QColor colorHigh
+setLightMode(bool)
+setLanguage(string)
+setRangeMin(int)
+setRangeMax(int)
+setColorLow(QColor)
+setColorMid(QColor)
+setColorHigh(QColor)
}
class SerialConfig {
+string portName
+int baudRate
+int dataBits
+int stopBits
+string parity
+uint8 deviceAddress
+DeviceMode mode
+int pollIntervalMs
}
class SensorRequest {
+uint8 functionCode
+uint32 startAddress
+uint16 dataLength
}
class SensorSpec {
+string model
+string version
+int rows
+int cols
+float pitch
+float dotRadius
+float rangeMin
+float rangeMax
}
class SerialBackend {
+string portName
+int baudRate
+int pollIntervalMs
+int deviceAddress
+string mode
+int requestFunction
+int requestStartAddress
+int requestLength
+string protocol
+bool connected
+open()
+close()
+requestOnce()
+feedBytes(bytes)
+setTransport(transport)
}
class GLWidget {
+setRange(int, int)
+setColorLow(QColor)
+setColorMid(QColor)
+setColorHigh(QColor)
+dotClicked(index, row, col, value)
}
class SerialManager {
+registerProtocol(name, bundle)
+setActiveProtocol(name)
+activeBundle()
}
class ISerialTransport {
<<interface>>
+open(config, error)
+close()
+writeBytes(data, error)
}
class QtSerialTransport {
+open(config, error)
+close()
+writeBytes(data, error)
}
class ISerialFormat {
<<interface>>
+tryParse(buffer, packet, error)
}
class ISerialCodec {
<<interface>>
+buildRequest(config, request)
+buildGetVersionRequest(config)
+buildGetSpecRequest(config)
}
class ISerialDecoder {
<<interface>>
+decodeFrame(packet, frame)
+decodeSpec(packet, spec)
}
class PiezoresistiveAFormat
class PiezoresistiveACodec
class PiezoresistiveADecoder
class DataBackend {
+ingestFrame(frame)
+clear()
+exportJson(path)
+exportCsv(path)
+importJson(path)
+importCsv(path)
+startPlayback(intervalMs)
+stopPlayback()
+setLiveRenderCallback(cb)
+setPlaybackRenderCallback(cb)
}
class DataFrame {
+string pts
+uint8 functionCode
+float[] data
}
class PacketQueue {
+push(packet)
+pop()
+clear()
+stop()
}
class FrameQueue {
+push(frame)
+pop()
+clear()
+stop()
}
class SerialReadThread {
+enqueueBytes(bytes)
+setParseFunc(func)
+start()
+stop()
}
class SerialDecodeThread {
+setDecodeFunc(func)
+start()
+stop()
}
class SerialSendWorker {
+setTransport(transport)
+setBuildRequestFunc(func)
+openTransport(config)
+closeTransport()
+requestOnce()
}
AppBackend --> SerialBackend
AppBackend --> DataBackend
AppBackend ..> GLWidget : render config
SerialBackend --> SerialConfig
SerialBackend --> SensorRequest
SerialBackend --> SensorSpec
SerialBackend --> SerialManager
SerialManager --> ISerialFormat
SerialManager --> ISerialCodec
SerialManager --> ISerialDecoder
ISerialFormat <|.. PiezoresistiveAFormat
ISerialCodec <|.. PiezoresistiveACodec
ISerialDecoder <|.. PiezoresistiveADecoder
ISerialTransport <|.. QtSerialTransport
SerialBackend --> DataFrame
DataBackend --> DataFrame
SerialBackend --> PacketQueue
SerialBackend --> FrameQueue
SerialBackend --> SerialReadThread
SerialBackend --> SerialDecodeThread
SerialBackend --> SerialSendWorker
SerialSendWorker --> ISerialTransport
SerialReadThread --> PacketQueue
SerialDecodeThread --> PacketQueue
SerialDecodeThread --> FrameQueue
说明:线程与队列已实现,队列溢出策略通过 TODO 注释预留后续扩展。
数据流/线程流程 (Mermaid)
flowchart LR
UI[QML 按钮/配置] -->|open/close| SB[SerialBackend]
SB -->|openTransport| SW[SerialSendWorker]
SW -->|open| TP[QtSerialTransport]
SW -->|slave 模式轮询| REQ[buildRequest]
REQ -->|writeBytes| TP
TP -->|bytesReceived| RT[SerialReadThread]
RT -->|tryParse| PKT[PacketQueue]
PKT --> DT[SerialDecodeThread]
DT -->|decodeFrame| FR[FrameQueue]
FR --> SB
SB -->|drainFrames| DB[DataBackend]
DB -->|liveCallback| GL[GLWidget]
DB -->|TODO| RP[RightPanel 可视化]
时序/函数调用 (Mermaid)
sequenceDiagram
participant UI as QML
participant SB as SerialBackend
participant SW as SerialSendWorker
participant TP as ISerialTransport
participant RT as SerialReadThread
participant DT as SerialDecodeThread
participant DB as DataBackend
participant GL as GLWidget
UI->>SB: open()
SB->>SW: openTransport(config)
SW->>TP: open(config)
Note over SW: slave 模式启动轮询定时器
SW->>SW: buildRequest()
SW->>TP: writeBytes(request)
TP-->>SW: bytesReceived(data)
SW-->>RT: enqueueBytes(data)
RT->>RT: tryParse(buffer)
RT-->>DT: PacketQueue.push(packet)
DT->>DT: decodeFrame(packet)
DT-->>SB: frameAvailable()
SB->>DB: ingestFrame(frame)
DB-->>GL: liveRenderCallback(frame)
配置流程 (Mermaid)
flowchart TD
UI[QML 设置参数] -->|setPortName/ setBaudRate/ setDeviceAddress/ setMode/ setPollIntervalMs| SB[SerialBackend]
UI -->|setRequestFunction/ setRequestStartAddress/ setRequestLength| SB
UI -->|setProtocol| SB
SB -->|syncSendConfig_| SW[SerialSendWorker.setConfig]
SB -->|syncSendRequest_| SW2[SerialSendWorker.setRequest]
SB -->|updateProtocolBindings_| RT[SerialReadThread.setParseFunc]
SB -->|updateProtocolBindings_| DT[SerialDecodeThread.setDecodeFunc]
SB -->|updateProtocolBindings_| SW3[SerialSendWorker.setBuildRequestFunc]
渲染/颜色映射流程 (Mermaid)
flowchart LR
UI[LeftPanel 颜色映射] -->|rangeMin/rangeMax<br/>colorLow/Mid/High| AB[AppBackend]
AB -->|rangeChanged/colorChanged| GL[GLWidget]
GL -->|uMinV/uMaxV/uColorLow/Mid/High| SH[dots.frag]
点阵凹陷渲染(Heightmap / Dented Surface)
目标
- 将
rows x cols点阵扩展到“长/宽各 100 倍”的显示分辨率(例如 12x7 -> 1200x700)。 - 数值越大,顶面越向内凹陷,且边缘与侧面跟随变形,保持整体感。
- 可在 OpenGL 视图内切换“普通点阵”和“凹陷热力图”两种渲染模式。
数据处理
- 传感器帧数据进入
GLWidget::submitValues()。 GLWidget::updateHeatmapData_()将values组装为CV_32F矩阵(rows x cols)。- 通过
GlobalHelper::transToMultiMatrix(...):- 低阈值清零 -> 归一化 -> 轻度模糊 -> resize 到
cols*100 x rows*100-> 再模糊。 - 仅输出“数据矩阵”,不再用于生成图像。
- 低阈值清零 -> 归一化 -> 轻度模糊 -> resize 到
- 将结果写入
m_heightValues,上传GL_R32F纹理。
凹陷算法
- 顶面位移(vertex shader):
t = clamp((v - min) / (max - min), 0..1)h = t * dentMaxz = baseZ + h(向内凹陷)
- 法线估算(fragment shader):
- 对 heightmap 相邻 texel 采样,计算梯度,再归一化为法线。
- 侧边联动:
initSkirtGeometry_()建立边界环。updateSkirtVertices_()采样边界高度,更新侧边顶点,使边缘与顶面同步下沉。
模式切换
GLWidget内部维护m_useHeatmap。- 使用
QPainter在 OpenGL 视图左上角绘制按钮(Dots / Heatmap)。 - 点击按钮切换渲染路径:
Dots:原点阵实例化圆点渲染。Heatmap:底面 + 侧边 + 顶面凹陷渲染。
UML (Mermaid)
classDiagram
class GLWidget {
+submitValues(values)
+setRange(min,max)
+setColorLow/Mid/High()
-updateHeatmapData_()
-uploadHeightTexture_()
-renderHeatmap_()
-renderSkirt_()
-renderBase_()
}
class GlobalHelper {
+transToMultiMatrix(raw,min,range,display,out)
}
class HeightTexture {
+GL_R32F
+width/height
}
class HeatmapMesh {
+VAO/VBO/IBO
+u,v grid
}
class SkirtMesh {
+border uv
+dynamic VBO
}
class Shaders {
+heatmap.vert/frag
+base.vert/frag
}
GLWidget --> GlobalHelper
GLWidget --> HeightTexture
GLWidget --> HeatmapMesh
GLWidget --> SkirtMesh
GLWidget --> Shaders
配置接口与步骤说明
- 设置协议:
SerialBackend::setProtocol(name):切换协议后调用updateProtocolBindings_(),更新ParseFunc/DecodeFunc/BuildRequestFunc。
- 设置串口配置(config):
SerialBackend::setPortName(name)SerialBackend::setBaudRate(rate)SerialBackend::setDeviceAddress(addr)(0-255)SerialBackend::setMode("master"/"slave")SerialBackend::setPollIntervalMs(intervalMs)(从站模式轮询周期)- 上述接口内部统一调用
syncSendConfig_(),将SerialConfig下发到SerialSendWorker::setConfig。
- 设置请求参数(request):
SerialBackend::setRequestFunction(func)SerialBackend::setRequestStartAddress(addr)SerialBackend::setRequestLength(len)- 上述接口内部调用
syncSendRequest_(),将SensorRequest下发到SerialSendWorker::setRequest。
- 设置解码/解析器:
SerialManager::registerProtocol(name, {codec, decoder, format})SerialBackend::setProtocol(name)触发updateProtocolBindings_():SerialReadThread::setParseFunc(format->tryParse)SerialDecodeThread::setDecodeFunc(decoder->decodeFrame)SerialSendWorker::setBuildRequestFunc(codec->buildRequest)
- 打开串口:
SerialBackend::open()->SerialSendWorker::openTransport(config),成功后在从站模式启动轮询发送。
- 渲染/颜色映射配置:
- QML 绑定
AppBackend::rangeMin/rangeMax与colorLow/Mid/High(LeftPanel中的颜色映射面板)。 setRangeMin/Max发出rangeChanged(min, max),由GLWidget::setRange同步到uMinV/uMaxV。setColorLow/Mid/High发出color*Changed,由GLWidget::setColor*同步到uColorLow/Mid/High。dots.frag归一化公式:value01 = clamp((v - min) / (max - min)),并用 low->mid->high 线性插值。
- QML 绑定
分层设计概述
- AppBackend:统一后端入口,驱动串口层与数据层,供 QML 直接绑定。
- 串口采集层:
Transport + Format + Codec + Decoder + Manager分层,独立于业务逻辑。 - 串口线程化:读取/解码/发送三线程 + Packet/Frame 队列,降低 UI 卡顿风险。
- 数据驱动层:负责帧缓存、数据导入导出与回放,提供渲染回调。
- 渲染配置层:
AppBackend提供范围/颜色参数,GLWidget将其转为 shader uniform 进行颜色映射。 - UI 层:
NavBar + LeftPanel + OpenGL View + RightPanel的 1+3 布局。
类接口与成员说明(C++)
AppBackend (src/backend.h)
- 作用:统一后端入口,串联
SerialBackend与DataBackend。 - 属性/接口:
lightMode/language/connected:UI 基础状态。serial()/data():暴露子系统实例给 QML。setLightMode(bool)/setLanguage(string)。rangeMin/rangeMax:颜色映射的数值范围。colorLow/colorMid/colorHigh:颜色映射的三个基准颜色。setRangeMin(int)/setRangeMax(int)/setColorLow(QColor)/setColorMid(QColor)/setColorHigh(QColor)。
- 成员变量:
m_serial:串口采集层对象。m_data:数据驱动层对象。m_lightMode/m_language:全局 UI 状态。m_rangeMin/m_rangeMax/m_colorLow/m_colorMid/m_colorHigh:颜色映射参数。
- 备注:串口连接成功后会清空历史数据缓存,避免旧数据残留。
rangeChanged(min, max)用于驱动GLWidget::setRange,颜色变更通过color*Changed同步。
SerialBackend (src/serial/serial_backend.h)
- 作用:串口采集层的统一控制器,负责协议选择、三线程调度与数据分发。
- 属性/接口:
portName/baudRate/deviceAddress/mode/pollIntervalMs:串口与模式配置。requestFunction/requestStartAddress/requestLength:请求参数。protocol/sensorModel/sensorGrid:协议与传感器规格占位。open()/close()/requestOnce()/feedBytes(bytes)。setTransport(transport):注入真实串口传输层。requestBuilt(bytes):输出原始请求帧,便于调试。
- 成员变量:
m_config:串口参数配置。m_request:请求参数。m_spec:传感器规格占位。m_manager:协议注册与切换。m_packetQueue/m_frameQueue:包/帧队列。m_readThread/m_decodeThread:读取与解码线程。m_sendWorker/m_sendThread:发送线程与 worker。m_frameCallback:解码后数据回调。
- 备注:通过
ParseFunc/DecodeFunc/BuildRequestFunc绑定协议实现,模拟 “find_decodec 后回调赋值”。
PacketQueue / FrameQueue (src/serial/serial_queue.h)
- 作用:线程安全的阻塞队列,用于 Packet/Frame 的跨线程传递。
- 接口:
push(item)/pop(item)/tryPop(item)/clear()/stop()/reset()setMaxSize(size):配置队列容量。
- 备注:队列溢出策略已通过 TODO 注释预留,后续可扩展为丢弃最新/阻塞等待。
SerialReadThread (src/serial/serial_threads.h)
- 作用:读取线程,接收原始字节流并根据
ParseFunc解析为 packet。 - 接口:
enqueueBytes(bytes):注入串口字节流。setParseFunc(func):绑定协议解析函数。start()/stop():线程控制。
SerialDecodeThread (src/serial/serial_threads.h)
- 作用:解码线程,从
PacketQueue解码 packet 并写入FrameQueue。 - 接口:
setDecodeFunc(func):绑定协议解码函数。start()/stop():线程控制。
SerialSendWorker (src/serial/serial_threads.h)
- 作用:发送线程 worker,负责请求编码与发送,并在从站模式下轮询。
- 接口:
setTransport(transport):注入传输层实例。setBuildRequestFunc(func):绑定请求编码函数。openTransport(config)/closeTransport():串口打开/关闭。requestOnce():触发一次请求发送。
SerialManager (src/serial/serial_manager.h)
- 作用:协议包管理器,注册
codec/decoder/format组合。 - 接口:
registerProtocol(name, bundle):注册协议。setActiveProtocol(name):切换协议。activeBundle():获取当前协议绑定。
- 成员变量:
m_protocols:协议字典。m_activeName:当前协议名。
协议插件化(plugins/decoders)
- 目标:每个协议作为独立 DLL 插件,可按需安装与动态加载。
- 关键接口:
IProtocolPlugin:暴露protocolName()/apiVersion()/createBundle()。ProtocolBundle:codec/decoder/format三件套。
- 加载流程:
SerialBackend启动时调用SerialManager::loadPlugins()。SerialManager扫描appDir/plugins/decoders目录,按平台过滤后缀(Windows:.dll)。- 校验
apiVersion,创建并注册协议 bundle。 - 通过
m_pluginLoaders保持插件常驻,避免对象失效。
插件 UML (Mermaid)
classDiagram
class IProtocolPlugin {
+protocolName()
+apiVersion()
+createBundle()
}
class ProtocolBundle {
+codec
+decoder
+format
}
class SerialManager {
+loadPlugins(dir)
+registerProtocol()
+setActiveProtocol()
}
class SerialBackend {
+initPlugins()
}
SerialBackend --> SerialManager
SerialManager --> IProtocolPlugin
IProtocolPlugin --> ProtocolBundle
ISerialTransport (src/serial/serial_transport.h)
- 作用:串口传输抽象层,屏蔽不同平台差异。
- 接口:
open(config, error)/close()/writeBytes(data, error)。
- 备注:实际接收数据通过
bytesReceived信号上报。 - 实现:
QtSerialTransport:基于QSerialPort的默认传输实现。- TODO:待实现内容(在传输层支持软/硬件流控配置)
ISerialFormat / ISerialCodec / ISerialDecoder
- 作用:协议拆分层,类比 FFmpeg 的
format/codec/decoder。 - ISerialFormat 接口:
tryParse(buffer, packet, error):从字节流中提取完整包。
- ISerialCodec 接口:
buildRequest(config, request):生成请求帧。buildGetVersionRequest(config):// TODO:待实现内容(构建获取版本号的请求帧)buildGetSpecRequest(config):// TODO:待实现内容(构建获取传感器规格的请求帧)
- ISerialDecoder 接口:
decodeFrame(packet, frame):解码回复帧。decodeSpec(packet, spec):// TODO:待实现内容(解析规格回复帧并填充 SensorSpec)
Piezoresistive A 协议 (src/serial/piezoresistive_a_protocol.*)
PiezoresistiveAFormat:包解析与 CRC-8/ITU 校验。PiezoresistiveACodec:构建请求帧。PiezoresistiveADecoder:解析回复帧为DataFrame。- 备注:数据以小端
uint16解析为 float,若协议变更可在此调整。
DataBackend (src/data_backend.h)
- 作用:数据驱动层,负责帧缓存、导入导出与回放。
- 接口:
ingestFrame(frame):实时采集数据入口。clear():清空缓存。exportJson(path)/exportCsv(path)。importJson(path)/importCsv(path)。startPlayback(intervalMs)/stopPlayback()。setLiveRenderCallback(cb)/setPlaybackRenderCallback(cb):渲染回调占位。
- 成员变量:
m_frames:帧数据容器。m_playbackTimer/m_playbackIndex:回放控制。
GLWidget (src/glwidget.h)
- 作用:OpenGL 渲染窗口,显示传感器点阵与背景。
- 接口:
setRange(int minV, int maxV):设置uMinV/uMaxV。setColorLow(QColor)/setColorMid(QColor)/setColorHigh(QColor):设置uColorLow/uColorMid/uColorHigh。
- 信号:
dotClicked(index, row, col, value):鼠标点击某个点时发出索引与数据值。
- 备注:
- 颜色映射在
dots.frag内完成,低/中/高三段线性插值。 - 拾取使用屏幕投影 + 半径阈值,便于 RightPanel 订阅点击事件做曲线展示。
- 颜色映射在
DataFrame (src/data_frame.h)
- 字段:
pts:yyyyMMddhhmmsszzz时间戳。functionCode:功能码。data:传感器数据。
SerialConfig / SensorRequest / SensorSpec (src/serial/serial_types.h)
SerialConfig:串口基础参数配置。SensorRequest:请求参数(功能码、起始地址、读取长度)。SensorSpec:传感器规格占位(型号/网格/量程等)。
协议结构说明(压阻 A 型)
- Request 起始符:
0x55AA(小端 ->AA 55)。 - Reply 起始符:
0x55AA(小端 ->AA 55)。 - 数据长度:从
data[4]到 payload 末尾(不含 CRC)。 - CRC:CRC-8/ITU(多项式 0x07,初始值 0x00)。
QML 层级与组件职责
总体布局(qml/content/App.qml)
- 顶部
NavBar:标题、连接状态、明暗切换、语言选择。 - 中部三栏:
- 左侧
LeftPanel:串口连接、采样参数、规格与显示控制。 - 中间 OpenGL 视图:由 C++
GLWidget挂载显示 3D 传感器数据,并提供点点击信号。 - 右侧
RightPanel:折线趋势、指标卡片、会话信息。
- 左侧
NavBar(qml/content/NavBar.qml)
- Title:软件名称显示。
- 连接指示:绿/红状态灯 + 文本。
Switch:Light/Dark 切换。ComboBox:语言选择。
LeftPanel(qml/content/LeftPanel.qml)
- 连接设置:
- COM 端口、波特率。
- 模式选择(主站/从站)。
- 设备地址输入(十六进制
0x01形式)。 - 采样周期(从站模式可用)。
- 采样参数:功能码、起始地址、读取长度。
- 传感器规格:协议名、型号、网格规格占位。
- 颜色映射:
- 数值范围(min/max)。
- 低/中/高三色选择(
ColorDialog)。
- 显示控制:显示网络/坐标轴、回放与导出入口。
RightPanel(qml/content/RightPanel.qml)
- Live Trend:折线趋势图示例。
- Metrics:峰值、RMS、均值、Delta 等指标卡片。
- Session:帧数、回放状态。
- LiveTrendCard:封装
SparklinePlot(C++ QQuickItem)用于趋势绘制,数据接入留有 TODO。
预留扩展(实现建议)
- 串口线程化已落地:
SerialReadThread读取字节流 ->PacketQueue。SerialDecodeThread解包/解码 ->FrameQueue。SerialSendWorker从站模式下定时发送请求。
- 队列溢出策略:
SerialQueue中已预留 TODO 注释,可扩展为阻塞等待或丢弃最新。 - 回调扩展:
DataBackend的渲染回调用于自定义 OpenGL/曲线刷新逻辑。
- 可视化接入:
main.cpp与qml/content/RightPanel.qml已标注 // TODO:待实现内容(将实时帧推送到右侧曲线/指标)。
- 协议扩展:
buildGetVersionRequest/buildGetSpecRequest/decodeSpec需实现,已保留 // TODO:待实现内容。
数据导出进度
- 已完成
DataBackend::exportJson(path)/exportCsv(path)已实现导出。DataBackend::importJson(path)/importCsv(path)已实现导入。qml/content/SaveAsExportDialog.qml提供路径、文件名、格式、方式选择,并通过saveTo(...)抛出导出参数。- 导出对话框以独立
Window方式呈现(ApplicationModal),避免在QQuickWidget内被裁剪。
- 待开发
- 将
saveTo与DataBackend导出接口打通,并补充失败提示。 - 覆盖/追加/压缩(zip)策略与文件存在检测流程。
xlsx导出实现与导出图标资源补齐(TODO)。
- 将
TODO 汇总
- 代码/界面
main.cpp:106将 frame 数据分发给右侧曲线/指标的 QML 接口。qml/content/RightPanel.qml:40用 DataBackend 输出的帧更新折线图/指标。src/serial/serial_queue.h:28指定队列溢出策略(丢弃最新/丢弃最旧/阻塞等待)。src/serial/serial_qt_transport.cpp:72根据 SerialConfig 扩展软件/硬件流控配置。src/serial/serial_codec.h:17构建获取版本号的请求帧。src/serial/serial_codec.h:19构建获取传感器规格的请求帧。src/serial/serial_decoder.h:18解析规格回复帧并填充 SensorSpec。src/serial/piezoresistive_a_protocol.cpp:126压阻 A 型版本号查询请求帧。src/serial/piezoresistive_a_protocol.cpp:132压阻 A 型规格查询请求帧。src/serial/piezoresistive_a_protocol.cpp:222解析压阻 A 型规格回复并写入 SensorSpec。
- 文档/流程图标注
docs/ARCHITECTURE.md:187队列溢出策略 TODO 预留说明。docs/ARCHITECTURE.md:205数据流图 RightPanel 可视化 TODO。docs/ARCHITECTURE.md:323队列溢出策略 TODO 备注。docs/ARCHITECTURE.md:363传输层软/硬件流控配置 TODO。docs/ARCHITECTURE.md:371buildGetVersionRequest TODO。docs/ARCHITECTURE.md:372buildGetSpecRequest TODO。docs/ARCHITECTURE.md:375decodeSpec TODO。docs/ARCHITECTURE.md:449LiveTrendCard 数据接入 TODO。docs/ARCHITECTURE.md:457SerialQueue 溢出策略 TODO。docs/ARCHITECTURE.md:461main.cpp/RightPanel.qml 实时帧推送 TODO。docs/ARCHITECTURE.md:463buildGetVersion/buildGetSpec/decodeSpec TODO。docs/ARCHITECTURE.md:520更新记录提及可视化 TODO。docs/ARCHITECTURE.md:522更新记录提及队列溢出 TODO。
- 测试/第三方
test/onlygl/stb_image.h:1276move stbi__convert_format to here.test/onlygl/stb_image.h:1302move stbi__convert_format16 to here.test/onlygl/stb_image.h:1303special case RGB-to-Y (and RGBA-to-YA) for 8-bit-to-16-bit case to keep more precision.test/onlygl/stb_image.h:5898tga_x_origin @TODO。test/onlygl/stb_image.h:5899tga_y_origin @TODO。
- 其他/说明
Prompt.md:60可视化部分流出 TODO。Prompt.md:72接口预留位置标注 TODO。Prompt.md:73文档和 TODO 说明。serial/doc/Doxyfile:603Doxygen TODO 列表说明。serial/doc/Doxyfile:607GENERATE_TODOLIST 开关。
更新记录
- 2026-01-20:协议解码插件化(DLL),SerialBackend 启动时动态加载
plugins/decoders,安装器支持按组件选择协议插件。 - 2026-01-11:新增
QtSerialTransport(QSerialPort传输实现)并设为默认传输;补齐点选拾取逻辑;新增数据流/时序图并补充可视化 TODO 说明。 - 2026-01-12:
LeftPanel新增颜色映射参数;AppBackend/GLWidget增加颜色与范围接口,shader 使用三色渐变映射数据值。 - 2026-01-11:补充串口配置流程图与配置接口说明(协议/参数/解码器绑定/打开流程)。
- 2026-01-05:新增串口三线程流水线(读/解码/发送)与 Packet/Frame 队列,更新协议起始符说明,补充队列溢出 TODO 与线程组件文档。
- 2026-01-05:CollapsiblePanel 组件改为跟随
backend.lightMode切换暗色主题配色。 - 2026-01-05:
QSplitter句柄配色跟随明暗模式并缩窄,消除 darkmode 下的白色缝隙。 - 2026-01-05:
QQuickWidgetclearColor 跟随明暗模式,避免面板圆角处漏出白底。 - 2026-01-05:
QQuickWidget在setSource后重设backend上下文属性,修复 QML 访问空指针报错。 - 2026-01-05:
QQuickWidget改为通过engine()->rootContext()注入backend,避免上下文被重建导致为空。 - 2026-01-05:改为每个
QQuickWidget引擎注入Backend上下文属性,避免多引擎使用单例导致的报错。 - 2026-01-05:调整
SerialSendWorker生命周期清理方式,避免跨线程 moveToThread 警告。 - 2026-01-06:多个
QQuickWidget共享同一个QQmlEngine,统一注入Backend/backend上下文属性以稳定访问。 - 2026-01-06:统一 QML 使用
backend上下文属性名称,避免大写标识被当成类型解析导致取值为空。 - 2026-01-06:为每个
QQuickWidget的rootContext()重复绑定backend,避免上下文被重建时丢失。 - 2026-01-06:
QQuickWidget改用QQmlComponent + QQmlContext创建根对象并setContent,确保backend上下文稳定注入。 - 2026-01-07:
GLWidget增加点阵点击拾取信号dotClicked,文档补充 OpenGL 交互说明。