端到端数据流¶
本文从应用数据出发, 追踪一个数据包从发送端到接收端经过的完整处理链路, 涵盖 MAC 层封装、信道编码、调制成型、空口传输、接收解调和数据恢复的全过程。
全局视图¶
flowchart LR
subgraph TX["发送端"]
A1["应用数据"] --> A2["QoS管理"]
A2 --> A3["MAC封帧"]
A3 --> A4["信道编码"]
A4 --> A5["调制成型"]
end
subgraph CH["空口"]
B["无线信道"]
end
subgraph RX["接收端"]
C1["解调滤波"] --> C2["信道解码"]
C2 --> C3["MAC解帧"]
C3 --> C4["QoS管理"]
C4 --> C5["应用数据"]
end
A5 --> B --> C1
发射流水线¶
第一步: QoS 决策¶
SleNode.transmit() 首先调用 QosManager.prepare_tx(), 从优先级队列中取出待发送数据:
五级优先级队列: CONTROL > REALTIME > HIGH > NORMAL > LOW
流控检查: 发送窗口是否有信用额度
HARQ 检查: 是否有需要重传的码块
第二步: 帧加密 (可选)¶
如果链路已开启加密, 调用 FrameCryptoContext.encrypt():
计算 IV:
compute_iv(iv_base, sync_or_link_id, frame_type)构建 CCM nonce:
build_ccm_nonce_async(flag, payload_count, direction, iv, data_len), 取 B0[1:14] 作为 13 字节 nonceAES-CCM 加密:
aes_ccm_encrypt(session_key, nonce, plaintext, aad, mic_len)→ 密文 + MICpayload_count 递增
第三步: MAC 封帧¶
数据被封装为 AsyncDataFrame:
┌────────────┬─────────────┬──────────┬──────────┐
│ 分段标志 │ 数据长度 │ 保留 │ 载荷 │
│ 2 bit │ 11 bit │ 3 bit │ N 字节 │
└────────────┴─────────────┴──────────┴──────────┘
如果数据超过最大 PDU 长度, 按 FIRST / MIDDLE / LAST 分段。
第四步: 信道编码 (tx_chain)¶
mac_to_iq() 将 MAC 字节转换为比特流, 构建控制信息, 然后调用 tx_chain():
头部编码 (encode_head)¶
控制信息比特 (28 或 44 位) 经过:
Polar 编码: 按可靠性序列选择信息位位置, 冻结位填零, 蝶形运算生成码字
加扰: 7 位 Galois LFSR (\(x^7 + x^4 + 1\)), 异或每个比特
载荷编码 (encode_payload)¶
用户数据比特经过:
CRC 附加: 计算 CRC-24 或 CRC-32, 附加到数据尾部
码块分割: 当编码后比特数超过 Polar 码最大母码长度时, 将数据拆分为多个码块
Polar 编码: 每个码块独立 Polar 编码, 按 MCS 指定的码率
加扰: 与头部使用相同的 LFSR, 异或每个码字比特
第五步: 帧组装¶
编码后的比特按帧结构组装:
┌──────────┬──────────┬──────────┬──────────┬──────────┐
│ 前导码 │ 同步序列 │ 头部 │ 载荷 │ (导频) │
│ m序列 │ SyncWord │ Polar码字│ Polar码字│ 定期插入 │
└──────────┴──────────┴──────────┴──────────┴──────────┘
前导码: m 序列, 不同帧类型使用不同长度 (FT1: 32 bit, FT2: 64 sym, FT3: 62 sym, FT4: 126 sym)
同步序列: 由 PID 生成, 用于帧同步检测
导频: 按
pilot_interval周期性插入已知符号, 用于信道估计
第六步: 调制成型¶
FT1 (GFSK): 高斯频移键控, BT = 0.5, 直接调制为瞬时频率变化
FT2-FT4 (PSK): 相移键控 (BPSK/QPSK/8PSK), 先映射星座点, 再经 RRC 脉冲成型滤波 (滚降系数 \(\beta = 0.4\))
输出为复数基带 IQ 信号。
第七步: 射频发送¶
仿真模式: IQ 直接进入信道模型
USRP 模式: IQ 通过
SLETransceiver发送到 USRP E310 硬件, 上变频到 2.4 GHz 频段
空口传输¶
信道效应¶
数据经过无线信道时受到:
多径衰落: Rayleigh/Rician 衰落, 多径时延扩展
频率偏移: 本振不匹配导致的载波频偏
多普勒扩展: 相对运动引起的时变信道
噪声: 高斯白噪声 (AWGN)
多用户干扰: 其他设备同频信号干扰
跳频¶
发射和接收两端按相同的跳频序列在 2402-2480 MHz 频段内切换信道, 每个时隙跳到不同频点, 改善频率分集增益并降低窄带干扰影响。
接收流水线¶
第一步: 射频接收¶
USRP 模式: 硬件下变频, ADC 采样得到基带 IQ
仿真模式: 从信道模型输出获取 IQ 信号
第二步: 匹配滤波¶
FT1 (GFSK): GFSK 解调器直接提取瞬时频率
FT2-FT4 (PSK): RRC 匹配滤波, 最大化信噪比, 然后降至 1 样本/符号
第三步: 帧同步 (frame_sync)¶
滑动互相关检测同步序列:
根据帧类型生成同步参考序列
计算接收信号与参考序列的互相关
峰值超过均值 2 倍时判定同步成功, 返回帧起始位置
第四步: 帧结构解析¶
symbols_to_data_bits() 根据帧配置参数拆分各段:
跳过前导码和同步序列
提取头部符号 (固定长度)
提取载荷符号 (长度由头部指示或预知)
移除导频符号
第五步: 头部解码 (decode_head)¶
解扰: 相同的 LFSR 异或恢复原始码字
Polar 解码: SC (逐次消除) 解码, 恢复控制信息比特
CRC-12 校验: 验证头部完整性
第六步: 载荷解码 (decode_payload)¶
解扰: LFSR 异或
Polar 解码: 每个码块独立解码
码块重组: 多个码块合并为完整数据
CRC 校验: CRC-24 或 CRC-32 验证数据完整性
第七步: MAC 解帧¶
比特流转换为字节:
bits_to_bytes()解析
AsyncDataFrame: 提取分段标志和载荷分段重组: 如有分段, 按序号拼接
第八步: 帧解密 (可选)¶
调用 FrameCryptoContext.decrypt():
用与发送端相同的参数构建 nonce
AES-CCM 解密并验证 MIC
payload_count 递增
MIC 验证失败则丢弃
第九步: QoS 反馈¶
ARQ: 发送 ACK/NACK
HARQ: 反馈 TB 或 CBG 粒度的确认
流控: 更新信用额度
质量跟踪: 更新帧错误率统计, 推荐 MCS
MAC-PHY 适配层¶
phy.mac_interface 模块是 MAC 和 PHY 之间的桥接:
函数 |
方向 |
说明 |
|---|---|---|
|
TX |
MAC 字节 → IQ 信号 |
|
RX |
IQ 信号 → MAC 字节 |
|
TX |
信令对象 → IQ |
|
RX |
IQ → 信令对象 |
|
工具 |
字节 → 比特 (MSB) |
|
工具 |
比特 → 字节 |
SleNode 集成¶
SleNode 是将所有功能集成到一个实体的节点类:
SleNode
├── TxConfig 发射配置
├── QosManager QoS 管理 (ARQ/HARQ/流控)
├── LinkManager 链路状态机 (8 状态)
├── FreqTable 跳频表
├── PowerController 功率控制
├── ScheduleManager 时序调度
├── FrameCryptoContext 帧加密上下文
├── ChannelModel 仿真信道 (可选)
└── SLETransceiver USRP 收发器 (可选)
数据流路径:
发送:
send(data)→ 入队 →transmit()→ QoS → 加密 → MAC → PHY → IQ → 空口接收: 空口 → IQ →
receive()→ PHY → MAC → 解密 → QoS 反馈 →on_data_received()