263 lines
10 KiB
Markdown
263 lines
10 KiB
Markdown
# XYParser 数据流与接口时序说明
|
|
|
|
## 接口时序图
|
|
|
|
### 3.1 64导初始化连接阶段
|
|
|
|
```mermaid
|
|
%%{init: {'theme': 'default', 'sequence': {'diagramMarginX': 80, 'diagramMarginY': 30, 'actorMargin': 80, 'width': 220, 'height': 80, 'messageMargin': 35}}}%%
|
|
sequenceDiagram
|
|
participant Dev as 64导EEG采集设备
|
|
participant Host as 上位机
|
|
participant Lib as XYParser库
|
|
|
|
Dev-->>Host: 设备连接成功
|
|
Host->>Lib: parser64 = XYParser_CreateParser(64)
|
|
Host->>Lib: XYParser_SetAdcParams(parser64, 4.5, 6.0)
|
|
Host->>Lib: XYParser_SetSampleRate(parser64, 250)
|
|
Host->>Lib: XYParser_SetBypassChecksum(parser64, 1)
|
|
Host->>Lib: gain_cmd_size = XYParser_Get64GainSampleRateCommandSize()
|
|
Lib-->>Host: gain_cmd_size
|
|
Host->>Lib: gain_cmd_bytes = XYParser_Serialize64GainSampleRateCommand(6, 250, gain_cmd_buf, gain_cmd_size)
|
|
Lib-->>Host: gain_cmd_bytes
|
|
Host->>Dev: 下发采样率250、增益6命令
|
|
```
|
|
|
|
### 3.2 64导阻抗阶段
|
|
|
|
```mermaid
|
|
%%{init: {'theme': 'default', 'sequence': {'diagramMarginX': 80, 'diagramMarginY': 30, 'actorMargin': 80, 'width': 220, 'height': 80, 'messageMargin': 35}}}%%
|
|
sequenceDiagram
|
|
participant Dev as 64导EEG采集设备
|
|
participant Host as 上位机
|
|
participant Lib as XYParser库
|
|
|
|
Host->>Lib: XYParser_SetImpedanceDetection(parser64, 1)
|
|
Host->>Lib: impedance_gain_cmd_size = XYParser_Get64GainSampleRateCommandSize()
|
|
Lib-->>Host: impedance_gain_cmd_size
|
|
Host->>Lib: impedance_gain_cmd_bytes = XYParser_Serialize64GainSampleRateCommand(24, 250, impedance_gain_cmd_buf, impedance_gain_cmd_size)
|
|
Lib-->>Host: impedance_gain_cmd_bytes
|
|
Host->>Dev: 下发采样率250、增益24命令
|
|
Host->>Lib: impedance_cmd_size = XYParser_Get64ImpedanceCommandSize()
|
|
Lib-->>Host: impedance_cmd_size
|
|
Host->>Lib: open_impedance_bytes = XYParser_Serialize64ImpedanceCommand(1, impedance_cmd_buf, impedance_cmd_size)
|
|
Lib-->>Host: open_impedance_bytes
|
|
Host->>Dev: 下发阻抗开启命令
|
|
|
|
loop 持续获取阻抗
|
|
Dev-->>Host: 原始EEG字节流
|
|
Host->>Lib: frame_count = XYParser_Feed(parser64, raw_data, raw_size, frame_summaries, max_frames)
|
|
Lib-->>Host: frame_count + frame_summaries
|
|
Host->>Lib: impedance_count = XYParser_ReadImpedance(parser64, impedance_summaries, max_impedance)
|
|
Lib-->>Host: impedance_count + impedance_summaries
|
|
end
|
|
|
|
Host->>Lib: close_impedance_bytes = XYParser_Serialize64ImpedanceCommand(0, impedance_cmd_buf, impedance_cmd_size)
|
|
Lib-->>Host: close_impedance_bytes
|
|
Host->>Dev: 下发阻抗关闭命令
|
|
Host->>Lib: restore_gain_cmd_size = XYParser_Get64GainSampleRateCommandSize()
|
|
Lib-->>Host: restore_gain_cmd_size
|
|
Host->>Lib: restore_gain_cmd_bytes = XYParser_Serialize64GainSampleRateCommand(6, 250, restore_gain_cmd_buf, restore_gain_cmd_size)
|
|
Lib-->>Host: restore_gain_cmd_bytes
|
|
Host->>Dev: 下发采样率250、增益6命令
|
|
Host->>Lib: XYParser_SetImpedanceDetection(parser64, 0)
|
|
```
|
|
|
|
### 3.3 64导算法阶段
|
|
|
|
```mermaid
|
|
%%{init: {'theme': 'default', 'sequence': {'diagramMarginX': 80, 'diagramMarginY': 30, 'actorMargin': 80, 'width': 220, 'height': 80, 'messageMargin': 35}}}%%
|
|
sequenceDiagram
|
|
participant Dev as 64导EEG采集设备
|
|
participant Host as 上位机
|
|
participant Lib as XYParser库
|
|
participant Algo as 算法
|
|
|
|
Host->>Lib: XYParser_SetWelchDetection(parser64, 1)
|
|
|
|
loop 持续采集
|
|
Dev-->>Host: 原始EEG字节流
|
|
Host->>Lib: frame_count = XYParser_Feed(parser64, raw_data, raw_size, frame_summaries, max_frames)
|
|
Lib-->>Host: frame_count + frame_summaries
|
|
Host->>Lib: value_count = XYParser_GetAlgorithmDataValueCount()
|
|
Lib-->>Host: value_count
|
|
Host->>Lib: ok = XYParser_ConvertSampleFramesToAlgorithmData(frame_summary, algorithm_input_data)
|
|
Lib-->>Host: ok + algorithm_input_data
|
|
Host->>Algo: 输入算法数据 algorithm_input_data
|
|
Algo-->>Host: 算法输出数据 algorithm_output_bytes
|
|
Host->>Lib: alg_frame_count = XYParser_FeedAlgorithmData(parser64, algorithm_output_bytes, algorithm_output_size, algorithm_frames, max_algorithm_frames)
|
|
Lib-->>Host: alg_frame_count + algorithm_frames
|
|
Host->>Lib: welch_count = XYParser_ReadWelch(parser64, welch_summaries, max_welch)
|
|
Lib-->>Host: welch_count + welch_summaries
|
|
end
|
|
|
|
opt 结束时处理尾数据
|
|
Host->>Lib: flushed = XYParser_FlushAlgorithmData(parser64, tail_frame_summary)
|
|
Lib-->>Host: flushed + tail_frame_summary
|
|
Host->>Lib: welch_count = XYParser_ReadWelch(parser64, welch_summaries, max_welch)
|
|
Lib-->>Host: welch_count + welch_summaries
|
|
end
|
|
|
|
Host->>Lib: XYParser_DestroyParser(parser64)
|
|
```
|
|
|
|
### 3.4 64导训练打标阶段
|
|
|
|
```mermaid
|
|
%%{init: {'theme': 'default', 'sequence': {'diagramMarginX': 80, 'diagramMarginY': 30, 'actorMargin': 80, 'width': 220, 'height': 80, 'messageMargin': 35}}}%%
|
|
sequenceDiagram
|
|
participant Port as 64导EEG设备串口
|
|
participant Host as 上位机
|
|
participant Lib as XYParser库
|
|
participant Time as 时间
|
|
|
|
Host->>Lib: trigger_cmd_size = XYParser_GetTriggerCommandSize()
|
|
Lib-->>Host: trigger_cmd_size
|
|
Host->>Lib: train0_bytes = XYParser_SerializeTriggerCommand(XYPARSER_TRIGGER_TRAIN_0, trigger_cmd_buf, trigger_cmd_size)
|
|
Lib-->>Host: train0_bytes
|
|
Host->>Port: 发送 TRAIN_0 打标
|
|
Host->>Time: 开始训练计时
|
|
Time-->>Host: 训练时间到
|
|
Host->>Lib: train1_bytes = XYParser_SerializeTriggerCommand(XYPARSER_TRIGGER_TRAIN_1, trigger_cmd_buf, trigger_cmd_size)
|
|
Lib-->>Host: train1_bytes
|
|
Host->>Port: 发送 TRAIN_1 打标
|
|
```
|
|
|
|
### 3.5 8导初始化连接阶段
|
|
|
|
```mermaid
|
|
%%{init: {'theme': 'default', 'sequence': {'diagramMarginX': 80, 'diagramMarginY': 30, 'actorMargin': 80, 'width': 220, 'height': 80, 'messageMargin': 35}}}%%
|
|
sequenceDiagram
|
|
participant Dev as 8导EEG采集设备
|
|
participant Host as 上位机
|
|
participant Lib as XYParser库
|
|
|
|
Dev-->>Host: 设备连接成功
|
|
Host->>Lib: parser8 = XYParser_CreateParser(8)
|
|
Host->>Lib: XYParser_SetAdcParams(parser8, vref, gain)
|
|
Host->>Lib: XYParser_SetSampleRate(parser8, sample_rate)
|
|
Host->>Lib: XYParser_SetBypassChecksum(parser8, 1)
|
|
```
|
|
|
|
### 3.6 8导阻抗阶段
|
|
|
|
```mermaid
|
|
%%{init: {'theme': 'default', 'sequence': {'diagramMarginX': 80, 'diagramMarginY': 30, 'actorMargin': 80, 'width': 220, 'height': 80, 'messageMargin': 35}}}%%
|
|
sequenceDiagram
|
|
participant Dev as 8导EEG采集设备
|
|
participant Host as 上位机
|
|
participant Lib as XYParser库
|
|
|
|
Host->>Lib: XYParser_SetImpedanceDetection(parser8, 1)
|
|
Host->>Lib: impedance_cmd_size = XYParser_Get8ChImpedanceCommandSize()
|
|
Lib-->>Host: impedance_cmd_size
|
|
Host->>Lib: open_impedance_bytes = XYParser_Serialize8ChImpedanceCommand(1, impedance_cmd_buf, impedance_cmd_size)
|
|
Lib-->>Host: open_impedance_bytes
|
|
Host->>Dev: 下发阻抗开启命令
|
|
|
|
loop 持续获取阻抗
|
|
Dev-->>Host: 原始EEG字节流
|
|
Host->>Lib: frame_count = XYParser_Feed(parser8, raw_data, raw_size, frame8_summaries, max_frames)
|
|
Lib-->>Host: frame_count + frame8_summaries
|
|
Host->>Lib: impedance_count = XYParser_ReadImpedance(parser8, impedance_summaries, max_impedance)
|
|
Lib-->>Host: impedance_count + impedance_summaries
|
|
end
|
|
|
|
Host->>Lib: close_impedance_bytes = XYParser_Serialize8ChImpedanceCommand(0, impedance_cmd_buf, impedance_cmd_size)
|
|
Lib-->>Host: close_impedance_bytes
|
|
Host->>Dev: 下发阻抗关闭命令
|
|
Host->>Lib: XYParser_SetImpedanceDetection(parser8, 0)
|
|
```
|
|
|
|
### 3.7 8导算法阶段
|
|
|
|
```mermaid
|
|
%%{init: {'theme': 'default', 'sequence': {'diagramMarginX': 80, 'diagramMarginY': 30, 'actorMargin': 80, 'width': 220, 'height': 80, 'messageMargin': 35}}}%%
|
|
sequenceDiagram
|
|
participant Dev as 8导EEG采集设备
|
|
participant Host as 上位机
|
|
participant Lib as XYParser库
|
|
participant Algo as 算法
|
|
|
|
Host->>Lib: XYParser_SetWelchDetection(parser8, 1)
|
|
|
|
loop 持续采集
|
|
Dev-->>Host: 原始EEG字节流
|
|
Host->>Lib: frame_count = XYParser_Feed(parser8, raw_data, raw_size, frame8_summaries, max_frames)
|
|
Lib-->>Host: frame_count + frame8_summaries
|
|
Host->>Lib: converted = XYParser_Convert8ChFramesTo64Ch(frame8_summary, 1, frame64_summary, 1)
|
|
Lib-->>Host: converted + frame64_summary
|
|
Host->>Lib: value_count = XYParser_GetAlgorithmDataValueCount()
|
|
Lib-->>Host: value_count
|
|
Host->>Lib: ok = XYParser_ConvertSampleFramesToAlgorithmData(frame64_summary, algorithm_input_data)
|
|
Lib-->>Host: ok + algorithm_input_data
|
|
Host->>Algo: 输入算法数据 algorithm_input_data
|
|
Algo-->>Host: 算法输出数据 algorithm_output_bytes
|
|
Host->>Lib: alg_frame_count = XYParser_FeedAlgorithmData(parser8, algorithm_output_bytes, algorithm_output_size, algorithm_frames, max_algorithm_frames)
|
|
Lib-->>Host: alg_frame_count + algorithm_frames
|
|
Host->>Lib: welch_count = XYParser_ReadWelch(parser8, welch_summaries, max_welch)
|
|
Lib-->>Host: welch_count + welch_summaries
|
|
end
|
|
|
|
opt 结束时处理尾数据
|
|
Host->>Lib: flushed = XYParser_FlushAlgorithmData(parser8, tail_frame_summary)
|
|
Lib-->>Host: flushed + tail_frame_summary
|
|
Host->>Lib: welch_count = XYParser_ReadWelch(parser8, welch_summaries, max_welch)
|
|
Lib-->>Host: welch_count + welch_summaries
|
|
end
|
|
|
|
Host->>Lib: XYParser_DestroyParser(parser8)
|
|
```
|
|
|
|
### 3.8 8导转64导导联映射关系
|
|
|
|
8导 workflow 在送入算法前,会先调用 `XYParser_Convert8ChFramesTo64Ch` 将 8 导帧扩展为 64 导帧。
|
|
|
|
- 8 个输入通道按固定导联位置写入 64 导 summary
|
|
- 未覆盖到的其余 56 个 64 导导联全部补 `0`
|
|
- `trigger type` 和 `trigger index` 原样透传
|
|
|
|
映射图如下:
|
|
|
|
```text
|
|
8ch[0] -> PO5
|
|
8ch[1] -> POZ
|
|
8ch[2] -> PO6
|
|
8ch[3] -> PO7
|
|
8ch[4] -> O1
|
|
8ch[5] -> OZ
|
|
8ch[6] -> O2
|
|
8ch[7] -> PO8
|
|
others -> 0
|
|
```
|
|
|
|
也可以理解为下面这张对应表:
|
|
|
|
| 8导索引 | 8导写入到的64导导联 |
|
|
| --- | --- |
|
|
| 0 | PO5 |
|
|
| 1 | POZ |
|
|
| 2 | PO6 |
|
|
| 3 | PO7 |
|
|
| 4 | O1 |
|
|
| 5 | OZ |
|
|
| 6 | O2 |
|
|
| 7 | PO8 |
|
|
|
|
转换过程示意:
|
|
|
|
```text
|
|
XYParser_Feed(8导原始数据)
|
|
-> frame8_summary
|
|
-> XYParser_Convert8ChFramesTo64Ch
|
|
-> frame64_summary
|
|
-> XYParser_ConvertSampleFramesToAlgorithmData
|
|
-> algorithm_input_data
|
|
```
|
|
|
|
代码依据:
|
|
|
|
- `XYParser_Convert8ChFramesTo64Ch`
|
|
- `Convert8ChSummaryTo64ChSummary`
|
|
- 8导映射表 `k8ChLeadMap`
|