概述

这里描述 DBDT 程序主控层状态机设计和编码实现方式。本状态机是主控层程序的核心。程序的几乎所有功能代码都是通过事件触发状态机的状态迁移(transition)操作实现。

文档标识约定

接口类型和标识:
* 外部系统到 =>主控API标识为S1;
* 主控到 => 业务API标识为S2;
* 业务 => 波形API标识为S3;
* 主控 => 硬件模块API标识为S4。

状态机说明

状态(state)和状态变迁(transition):
* [*] 为初始状态,根据初始化后是否需要切换到其它状态,命名为 Initial 或 Initting。
* 复合(composite)状态本身是抽象(abstract)的(可以定义通用的 ENTRY / EXIT 事件处理),任何时候状态机都会处于某个叶子节点状态。最终叶子节点状态名使用父状态名 + "_" 前缀。
* <<choice>> 定义的分支选择类型 state 作为 transition 处理,并非实际状态。
* 所有 transition 均为同步(sync)短暂(transient)原子(atomic)执行模式。所有向外部接口发送消息或调用接口操作均位于transition里。所有异步(async)操作均使用消息和多种状态处理。
* 暂定:⇒ 开头的 transition 表示该 state 的 ENTRY (setup)系统事件,执行 init 初始化并切换到工作状态。

编码实现说明

编码实现:
* 编码实现使用 [HSM](<https://github.com/howard-chan/HSM>) (Hierarchical State Machine) 模型。复合状态与其中的子状态是 hierarchical 从属关系。
* 如果某个状态只有一个来源状态,或者其所有来源状态transition里执行的操作相同或类似,则将这些 "setup" 操作放在目标状态的 ENTRY 系统事件里统一处理。
* 类似的,如果某个状态只有一个退出状态,或者其到所有退出状态transition里执行的操作相同或类似,则将这些 "teardown" 操作放在该状态的 EXIT 系统事件里统一处理。
* 说明:
  * setup: 某个状态的通用的初始操作。例如进入 Initing 状态时会向各业务层发送 init() 指令。
  * teardown: 某个状态的通用的卸载操作。例如进入 EXITING 状态时会向业务层发送终止发射流程指令。

超时(timeout)处理:
所有与外部接口和业务层的交互接口均为异步模式,即发送消息或调用接口后通过未来的消息获取回复和响应。系统会定期触发 TIMER 事件,各个状态的 handler 通过此事件处理超时异常。

Station state / 电台状态和模式

整个电台的所有工作模式和状态由单一状态机管理。定频、QALE等工作模式属于复合状态。工作模式的进入(Entry)和退出(Exit)通过接收到的 S1 0xFC工作模式设置命令里的与当前工作模式不同的工作模式指令驱动。

FIXED / 定频

stateDiagram-v2
  state received_work_mode_msg <<choice>>
  # 收到 S1 的 0xFC工作模式设置,保存所有信息到内存
  [*]--> received_work_mode_msg : 0xFC工作模式设置
  received_work_mode_msg  --> FIXED:模式=0(定频)
  received_work_mode_msg  --> QALE :模式=1
  state FIXED {
    # 调用 S2 S2_init_module 初始化定频模块参数
    [*] --> Initting : ⇒定频业务初始化:S2_init_module
   # 收到 S2 定频参数初始化完成消息。发送 S2_set_work_mode 工作模式设置 0 定频
    Initting --> WorkModeConfiging: 初始化完成:设置工作模式为定频
    # 收到工作模式设置完成消息, 调用S2 set_work_type 设置业务类型(模拟话/声码话/数据链)
    WorkModeConfiging--> WorkTypeConfiging: 工作模式设置完成:设置业务类型
    # 收到业务类型设置完成消息,调用S2各个工作参数设置接口(速率,明/密,密钥分区,带宽,呼叫地址,工作指令)
    WorkTypeConfiging --> WorkParamsConfiging : 业务类型设置完成:设置各参数
    # 收到0xFC切换业务类型,再次调用 set_work_type
    WorkTypeConfiging --> WorkTypeConfiging :0xFC切换业务类型
    state received_work_param_msg <<choice>>
    WorkParamsConfiging  --> WorkTypeConfiging :0xFC切换业务类型
    WorkParamsConfiging --> received_work_param_msg : 0xfc参数设置
    received_work_param_msg --> WorkParamsConfiging : 尚有参数未设置完成
    received_work_param_msg --> Running : 所有参数设置完成
    Running --> WorkTypeConfiging :0xFC切换业务类型
    Running --> WorkParamsConfiging :0xFC切换工作参数
  }
  # 0xFC 切换工作模式时,调用S2 set_send _control 终止发射流程
  FIXED--> FIXED_Exiting : 0xFC 切换工作模式:关闭发射流程
  # 收到发射流程关闭完成后,根据目标工作模式,进入相应模式的状态流程里。
  FIXED_Exiting --> QALE: 关闭成功:切换到目标工作模式

QALE / 快速自适应

stateDiagram-v2
  state received_work_mode_msg <<choice>>
  # 收到 S1 的 0xFC工作模式设置,保存所有信息到内存
  [*]--> received_work_mode_msg : 0xFC工作模式设置
  received_work_mode_msg  --> FIXED:模式=0(定频)
  received_work_mode_msg  --> QALE :模式=1
  state QALE {
    # 调用 S2 S2_init_module 初始化 QALE模块参数
    [*] --> Initting : ⇒QALE业务初始化:S2_init_module
    # 收到 S2 QALE 参数初始化完成消息。发送 S2_set_work_mode 工作模式设置 1 QALE
    Initting --> WorkModeConfiging: 初始化完成:设置工作模式为QALE
    # 收到工作模式设置完成消息, 调用S2 set_work_type 设置业务类型(模拟话/声码话/数据链)
    WorkModeConfiging--> WorkTypeConfiging: 工作模式设置完成:设置业务类型
    # 收到业务类型设置完成消息,调用S2各个工作参数设置接口(波道号,速率,明/密,密钥分区,带宽,QALE呼叫地址)
    WorkTypeConfiging --> WorkParamsConfiging : 业务类型设置完成:设置各参数
    # 收到0xFC切换业务类型,再次调用 set_work_type 
    WorkTypeConfiging --> WorkTypeConfiging :0xFC切换业务类型
    state received_work_param_msg <<choice>>
    WorkParamsConfiging  --> WorkTypeConfiging :0xFC切换业务类型
    WorkParamsConfiging --> received_work_param_msg : 0xfc参数设置
    received_work_param_msg --> WorkParamsConfiging : 尚有参数未设置完成
    state work_order_type <<choice>>
    received_work_param_msg --> work_order_type : 参数设置完成,根据工作指令类型
    # 所有参数设置完成,根据工作指令类型
    # 以下所有 transition 均向外部接口发送 0xDC 工作状态上报
    work_order_type --> Scanning: 1(扫描)
    # 工作指令为单呼或组呼:调用 S2_set_qale_link 开始建链
    work_order_type --> Linking : 2(单呼)/3(组呼):开始建链
    # 建链成功消息
    Linking--> Running : 建链成功
    Linking --> Scanning : 建链失败
    Linking--> Unlinking: 外部指令设置扫描模式(Unlink同时代表拆链和取消建链)
    #Linking--> WorkTypeConfiging :0xFC切换业务类型
    #Running --> WorkTypeConfiging :0xFC切换业务类型
    Running --> Unlinking : 0xFC(工作指令=1扫描),开始拆链
    # 拆链成功消息,向外部接口回复 0xDC 工作状态上报
    Unlinking --> Scanning : 拆链成功
    Scanning  --> Linking : 0xFC(工作指令=2/3)
    Scanning  --> Running : 被呼建链消息
    # 0xF3 本机地址加载:调用 set_work_self_address
    Running --> Running :0xF3
    Running --> Scanning : 被动拆链消息
    # 收到S2当前本机地址消息:更新内存,发送0xD3本地地址上报
    Running --> Running :本机地址消息
    Running --> WorkTypeConfiging :0xFC切换业务类型
    Running --> WorkParamsConfiging :0xFC切换工作参数
  }
  # 0xFC 切换工作模式时,调用S2 set_send _control 终止发射流程
  QALE --> QALE_Exiting : 0xFC 切换工作模式:关闭发射流程
  # 收到发射流程关闭完成后,根据目标工作模式,进入相应模式的状态流程里。
  QALE_Exiting --> FIXED : 关闭成功:切换到目标工作模式
  state FIXED

备注

* 暂未考虑失败、超时等异常情况。
* Scanning / Linking / Running / Unlinking 等工作模式下收到 0xFC 切换业务类型或工作参数的命令后,考虑有两种处理方式:
  a. 回退至 WorkTypeConfiging / WorkParamsConfiging 等状态。
  b. 不改变状态,直接调用S2的业务类型或参数更新接口。
* QALE 预调谐目前设计在初始化时由业务实现。

GROUP / 组网业务 (与 QALE 流程类似)

stateDiagram-v2
  state received_work_mode_msg <<choice>>
  # 收到 S1 的 0xFC工作模式设置,保存所有信息到内存
  [*]--> received_work_mode_msg : 0xFC工作模式设置
  received_work_mode_msg  --> FIXED:模式=0(定频)
  received_work_mode_msg  --> GROUP :模式=2
  state GROUP {
    [*] --> Initting : ⇒组网业务初始化:S2_init_module
    # 收到 S2 QALE 参数初始化完成消息。发送 S2_set_work_mode 工作模式设置 3 组网
    Initting --> WorkModeConfiging: 初始化完成:设置工作模式为组网
    # 收到工作模式设置完成消息, 调用S2 set_work_type 设置业务类型(模拟话/声码话/数据链)
    WorkModeConfiging--> WorkTypeConfiging: 工作模式设置完成:设置业务类型
    # 收到业务类型设置完成消息,调用S2各个工作参数设置接口(波道号,速率,明/密,密钥分区,带宽,QALE呼叫地址)
    WorkTypeConfiging --> WorkParamsConfiging : 业务类型设置完成:设置各参数
    state received_work_param_msg <<choice>>
    WorkParamsConfiging  --> WorkTypeConfiging :0xFC切换业务类型
    WorkParamsConfiging --> received_work_param_msg : 0xfc参数设置
    received_work_param_msg --> WorkParamsConfiging : 尚有参数未设置完成
    state work_order_type <<choice>>
    received_work_param_msg --> work_order_type : 参数设置完成,根据工作指令类型
    # 所有参数设置完成,根据工作指令类型
    # 以下所有 transition 均向外部接口发送 0xDC 工作状态上报
    work_order_type --> Scanning: 1(扫描)
    # 工作指令为单呼或组呼:调用 S2_set_qale_link 开始建链
    work_order_type --> Linking : 2(单呼)/3(组呼):开始建链
    # 建链成功消息
    Linking--> Running : 建链成功
    Linking --> Scanning : 建链失败
    #Linking--> WorkTypeConfiging :0xFC切换业务类型
    #Running --> WorkTypeConfiging :0xFC切换业务类型
    Running --> Unlinking : 0xFC(工作指令=1扫描),开始拆链
    # 拆链成功消息,向外部接口回复 0xDC 工作状态上报
    Unlinking --> Scanning : 拆链成功
    Scanning  --> Linking : 0xFC(工作指令=2/3)
    Scanning  --> Running : 被呼建链消息
    # 0xF3 本机地址加载:调用 set_work_self_address
    Running --> Running :0xF3
    Running --> Scanning : 被动拆链消息
    # 收到S2当前本机地址消息:更新内存,发送0xD3本地地址上报
    Running --> Running :本机地址消息
    Running --> WorkTypeConfiging :0xFC切换业务类型
    Running --> WorkParamsConfiging :0xFC切换工作参数
  }
 # 0xFC 切换工作模式时,调用S2 set_send _control 终止发射流程
  GROUP --> GROUP_Exiting : 0xFC 切换工作模式:关闭发射流程
  # 收到发射流程关闭完成后,根据目标工作模式,进入相应模式的状态流程里。
  GROUP_Exiting --> FIXED : 关闭成功:切换到目标工作模式

NET / 接入网

与 QALE 流程类似