下面给出常见 QAM 调制(16-QAM、64-QAM、256-QAM)的“比特→复符号”映射表(Gray 码顺序,平均功率归一化为 1)。
写法与 QPSK 表完全一致,只是比特长度和星座点更多。
把下面的字典直接替换 self.mapping_table
即可;解调表 demapping_table
只要把键值对反过来即可。
1️⃣ 16-QAM(4 bit / 符号)
# 归一化因子:1/√10
nf16 = np.sqrt(10)
mapping_16qam = {
(0,0,0,0): (-3+3j)/nf16,
(0,0,0,1): (-3+1j)/nf16,
(0,0,1,1): (-3-1j)/nf16,
(0,0,1,0): (-3-3j)/nf16,
(0,1,0,0): (-1+3j)/nf16,
(0,1,0,1): (-1+1j)/nf16,
(0,1,1,1): (-1-1j)/nf16,
(0,1,1,0): (-1-3j)/nf16,
(1,1,0,0): ( 1+3j)/nf16,
(1,1,0,1): ( 1+1j)/nf16,
(1,1,1,1): ( 1-1j)/nf16,
(1,1,1,0): ( 1-3j)/nf16,
(1,0,0,0): ( 3+3j)/nf16,
(1,0,0,1): ( 3+1j)/nf16,
(1,0,1,1): ( 3-1j)/nf16,
(1,0,1,0): ( 3-3j)/nf16
}
2️⃣ 64-QAM(6 bit / 符号)
# 归一化因子:1/√42
nf64 = np.sqrt(42)
# 生成 Gray 码 64-QAM 表最简单的方法:
iq = np.array([-7,-5,-3,-1,1,3,5,7])
sym64 = [(b3,b2,b1, b5,b4,b0) # Gray 码比特顺序
for b0 in range(2) for b1 in range(2) for b2 in range(2)
for b3 in range(2) for b4 in range(2) for b5 in range(2)]
mapping_64qam = {
tuple(bits): (iq[idx_i] + 1j*iq[idx_q]) / nf64
for bits in sym64
for idx_i, idx_q in [(int(''.join(map(str,bits[:3])),2),
int(''.join(map(str,bits[3:])),2))]
}
(嫌手打麻烦可直接用 qammod
生成:
mapping = qammod(np.arange(64), 64, 'gray', 'UnitAveragePower', True)
)
3️⃣ 256-QAM(8 bit / 符号)
# 归一化因子:1/√170
nf256 = np.sqrt(170)
iq = np.array([-15,-13,-11,-9,-7,-5,-3,-1,1,3,5,7,9,11,13,15])
sym256 = [(b7,b6,b5,b4, b3,b2,b1,b0) for ...] # 同上思路
mapping_256qam = {
tuple(bits): (iq[idx_i] + 1j*iq[idx_q]) / nf256
...
}
4️⃣ 通用“一键生成”模板(推荐)
from commpy.modulation import QAMModem # 需要 pip install scikit-commpy
modem = QAMModem(M) # M = 4,16,64,256...
mapping_table = {
tuple(np.binary_repr(k, int(np.log2(M)))): modem.mapping[k]
for k in range(M)
}
✅ 解调表(反查)
demapping_table = {v: list(k) for k, v in mapping_table.items()}
一句话:
只要改 M、归一化因子和比特长度,其余逻辑与 QPSK 完全一致。