nearlink_sdr.common.mcs 源代码

"""编码调制表格与速率适配 -- TXS-10002-2025 标准 6.10.5 / 6.10.6

定义 MCS 索引到调制方式、编码速率的映射, 以及各编码速率下
不同码长对应的信息比特数 Kcb。
"""

from __future__ import annotations

__all__ = [
    "CODE_LENGTHS",
    "MCSEntry",
    "Modulation",
    "RateConfig",
    "get_kcb",
    "get_mcs",
]


from dataclasses import dataclass
from enum import IntEnum
from fractions import Fraction
from typing import NamedTuple


[文档] class Modulation(IntEnum): """调制方式""" BPSK = 1 QPSK = 2 PSK8 = 3
[文档] class MCSEntry(NamedTuple): """MCS 表条目""" index: int modulation: Modulation code_rate: Fraction spectral_efficiency: float bits_per_symbol: int # 每个调制符号承载的比特数
# 标准表22: 编码调制表格 MCS_TABLE: tuple[MCSEntry, ...] = ( MCSEntry(0, Modulation.BPSK, Fraction(1, 4), 0.250, 1), MCSEntry(1, Modulation.BPSK, Fraction(3, 8), 0.375, 1), MCSEntry(2, Modulation.QPSK, Fraction(1, 4), 0.500, 2), MCSEntry(3, Modulation.QPSK, Fraction(3, 8), 0.750, 2), MCSEntry(4, Modulation.QPSK, Fraction(1, 2), 1.000, 2), MCSEntry(5, Modulation.QPSK, Fraction(5, 8), 1.250, 2), MCSEntry(6, Modulation.QPSK, Fraction(3, 4), 1.500, 2), MCSEntry(7, Modulation.QPSK, Fraction(7, 8), 1.750, 2), MCSEntry(8, Modulation.QPSK, Fraction(1, 1), 2.000, 2), MCSEntry(9, Modulation.PSK8, Fraction(5, 8), 1.875, 3), MCSEntry(10, Modulation.PSK8, Fraction(3, 4), 2.250, 3), MCSEntry(11, Modulation.PSK8, Fraction(7, 8), 2.625, 3), MCSEntry(12, Modulation.PSK8, Fraction(1, 1), 3.000, 3), ) # MCS 索引 -> MCSEntry 快速查表 _MCS_MAP: dict[int, MCSEntry] = {e.index: e for e in MCS_TABLE}
[文档] def get_mcs(index: int) -> MCSEntry: """按索引获取 MCS 条目。""" if index not in _MCS_MAP: raise ValueError(f"无效 MCS 索引 {index}, 合法范围 0..12") return _MCS_MAP[index]
# ---------- 速率适配信息比特表 (6.10.6) ---------- # 码长列表 (降序) CODE_LENGTHS = (1024, 512, 256, 128, 64) # 标准表23: Kcb 第一表格 # key = 编码速率 (Fraction), value = {码长: Kcb} RATE_ADAPT_TABLE_1: dict[Fraction, dict[int, int]] = { Fraction(1, 4): {1024: 256, 512: 96, 256: 48, 128: 24, 64: 12}, Fraction(3, 8): {1024: 384, 512: 160, 256: 80, 128: 40, 64: 20}, Fraction(1, 2): {1024: 512, 512: 224, 256: 112, 128: 56, 64: 28}, Fraction(5, 8): {1024: 640, 512: 288, 256: 144, 128: 72, 64: 36}, Fraction(3, 4): {1024: 768, 512: 352, 256: 176, 128: 88, 64: 44}, Fraction(7, 8): {1024: 896, 512: 416, 256: 208, 128: 104, 64: 52}, } # 标准表24: Kcb 第二表格 (仅适用于 5/8, 3/4, 7/8) RATE_ADAPT_TABLE_2: dict[Fraction, dict[int, int]] = { Fraction(5, 8): {1024: 640, 512: 316, 256: 156, 128: 74, 64: 36}, Fraction(3, 4): {1024: 768, 512: 382, 256: 189, 128: 90, 64: 45}, Fraction(7, 8): {1024: 896, 512: 446, 256: 221, 128: 106, 64: 53}, }
[文档] def get_kcb(code_rate: Fraction, code_length: int, *, table: int = 1) -> int: """查询速率适配信息比特数 Kcb。 :param code_rate: 编码速率, 如 Fraction(1, 4)。 :type code_rate: Fraction :param code_length: 码长, 必须为 64, 128, 256, 512, 1024 之一。 :type code_length: int :param table: 1 = 第一表格 (表23), 2 = 第二表格 (表24)。 :type table: int :returns: 信息比特数 Kcb。 :rtype: int """ if code_length not in CODE_LENGTHS: raise ValueError(f"码长必须为 {CODE_LENGTHS} 之一, 收到 {code_length}") tbl = RATE_ADAPT_TABLE_1 if table == 1 else RATE_ADAPT_TABLE_2 if code_rate not in tbl: raise ValueError(f"编码速率 {code_rate} 在表{table}中不存在") return tbl[code_rate][code_length]
[文档] @dataclass class RateConfig: """速率配置: 从 MCS 索引导出完整的编码调制参数。""" mcs_index: int modulation: Modulation code_rate: Fraction bits_per_symbol: int spectral_efficiency: float
[文档] @classmethod def from_mcs(cls, index: int) -> RateConfig: entry = get_mcs(index) return cls( mcs_index=entry.index, modulation=entry.modulation, code_rate=entry.code_rate, bits_per_symbol=entry.bits_per_symbol, spectral_efficiency=entry.spectral_efficiency, )
[文档] def kcb(self, code_length: int, *, table: int = 1) -> int: """查询当前编码速率下指定码长的信息比特数。""" return get_kcb(self.code_rate, code_length, table=table)