# ofdmdemod
使用正交频分复用解调时域信号
函数库: TyCommunication
# 语法
outSym = ofdmdemod(ofdmSig, nfft, cplen)
outSym = ofdmdemod(ofdmSig, nfft, cplen, symOffset)
outSym = ofdmdemod(ofdmSig, nfft, cplen, symOffset, nullidx)
outSym, pilots = ofdmdemod(ofdmSig, nfft, cplen, symOffset, nullidx, pilotidx)
# 说明
outSym=ofdmdemod(ofdmSig, nfft, cplen) 使用由 nfft 指定的 FFT 大小和由 cplen 指定的循环前缀长度,对 ofdmSig 中指定的输入时域信号执行 OFDM 解调 。
outSym=ofdmdemod(ofdmSig, nfft, cplen, symOffset) 在输入信号解调之前,对每个 OFDM 符号应用符号采样偏移 symOffset。
outSym=ofdmdemod(ofdmSig, nfft, cplen, symOffset, nullidx) 从 nullidx 中指定的位置删除空子载波。在此语法中,符号采样偏移应用于每个 OFDM 符号,输出的行数为 nfft–length(nullidx),这说明空子载波已被去除。使用空子载波来计算保护带和 DC 子载波。
outSym, pilots=ofdmdemod(ofdmSig, nfft, cplen, symOffset, nullidx, pilotidx) 返回 pilotidx 中指定的导频索引的导频子载波。在此语法中,符号采样偏移应用于每个 OFDM 符号,输出的行数为nfft–length(nullidx)–length(pilotidx),这说明空子载波和导频子载波已被去除。该函数假设导频子载波位置在每个 OFDM 符号和发射天线上都是相同的。 示例
# 示例
使用 OFDM 对 QPSK 信号进行调制和解调
using TyCommunication
using TyMath
rng = MT19937ar(1234)
nfft = 64
cplen = 16
nSym = 10
nullIdx = [1:6; 33; (64 - 4):64]
pilotIdx = [12; 26; 40; 54]
numDataCarrs = nfft - length(nullIdx) - length(pilotIdx)
dataIn = complex.(rand(rng, numDataCarrs, nSym), rand(rng, numDataCarrs, nSym))
pilots = repeat(pskmod((0:3), 4), 1, nSym)
y2 = ofdmmod(dataIn, nfft, cplen, nullIdx, pilotIdx, pilots)
symOffset = cplen
x2, rxPilots = ofdmdemod(y2, nfft, cplen, symOffset, nullIdx, pilotIdx)
maximum(abs.(x2[:, :, 1] .- dataIn))
ans = 3.510833468576701e-16
不同 CP 长度的 OFDM 解调
OFDM - 为不同符号解调不同 CP 长度的信号。
初始化输入参数,定义空子载波和先导子载波的位置。生成随机数据并进行 OFDM 调制。
using TyMath
using TyCommunication
rng = MT19937ar(1234)
M = 16;
nfft = 64;
cplen = [16 32];
nSym = 2;
dataSym = randi(rng, [0 M - 1], nfft, nSym);
qamSig = qammod(dataSym, M; UnitAveragePower=true);
y1 = ofdmmod(qamSig, nfft, cplen);
解调 OFDM 符号。将结果与原始输入数据进行比较。信号之间的差异可以忽略不计。
x1, = ofdmdemod(y1, nfft, cplen);
rxData = qamdemod(x1, M; UnitAveragePower=true);
isequal(rxData, dataSym)
true
SISO 链路的调制解调
对具有瑞利衰落的 16-QAM 信号的 SISO 链路应用 OFDM 多路复用。
using TyCommunication
using TyMath
using TyStatistics
using TyBase
s1 = mt19937ar(12345)
nFFT = 64
cpLen = 16
nullIdx = [1:6; 33; (64 - 4):64]'
numTones = nFFT - length(nullIdx)
# 每符号比特数
k = 4;
M = 2^k
constSym = qammod((0:(M - 1)), M; UnitAveragePower=true)
maxDopp = 1
pathDelays = [0 4e-3 8e-3]
pathGains = [0 -2 -3]
sRate = 1000
sampIdx = round.(Int, pathDelays / (1 / sRate)) .+ 1
chan = comm_RayleighChannel(;
PathGainsOutputPort=true,
MaximumDopplerShift=maxDopp,
PathDelays=pathDelays,
AveragePathGains=pathGains,
SampleRate=sRate,
RandomStream="mt19937ar with seed",
)
data = randi(s1, [0 M - 1], numTones, 1)
modOut = qammod(data, M; UnitAveragePower=true)
应用 OFDM 调制并将信号通过信道传输。
y = ofdmmod(modOut, nFFT, cpLen, nullIdx)
fadSig, pg = step(chan, y)
确定符号采样偏移。
symOffset = min(maximum(sampIdx), cpLen)
symOffset = 9
对接收到的信号进行 OFDM 解调。
x, = ofdmdemod(fadSig, nFFT, cpLen, symOffset, nullIdx)
将路径增益 pg 转换为标量抽头增益。在信号恢复过程中使用抽头增益进行均衡。
hImp = complex.(zeros(1, nFFT))
hImp[:, sampIdx] = mean(pg, 1)
hall = fftshift(fft(vec(hImp)), 1)
dataIdx = Int64.(setdiff((1:nFFT)', nullIdx))
h = hall[dataIdx]
对信号进行均衡。
eqH = conj(h) ./ (conj(h) .* h)
eqSig = eqH .* x
cdScope = comm_ConstellationDiagram(;
ShowReferenceConstellation=true, ReferenceConstellation=constSym
)
step(cdScope, eqSig)
解调 16-QAM 符号以恢复信号。计算比特错误率。
rxSym = qamdemod(eqSig, M, ; UnitAveragePower=true)
numErr, = symerr(data, rxSym)
fprintf(
"Number of symbol errors:" *
string(numErr) *
" out of " *
string(length(data)) *
" symbols.",
)
Number of symbol errors:2 out of 52 symbols.
# 输入参数
ofdmSig - 调制的 OFDM 符号复数符号的二维数组
nfft - FFT 长度大于或等于8的整数
FFT 长度,指定为大于或等于8的整数。nfft 相当于解调过程中使用的子载波数。
数据类型: Int64
cplen - 循环前缀长度标量 | 长度为N_{Sym}的行向量
循环前缀长度,指定为标量或长度为
当将 cplen 指定为标量时,通过所有天线的所有符号的循环前缀长度都相同;
当将 cplen 指定为长度为
的行向量时,循环前缀长度可以因符号而异,但通过所有天线保持相同的长度。
数据类型: Int64
symOffset - 符号采样偏移cplen(默认) | 标量 | 向量
nullidx - 空子载波位置的索引列向量
空子载波位置的索引,指定为元素值从 1 到 nfft 的列向量。如果指定 nullidx,则 outSym 中的行数为 (nfft-length(nullidx))。有关详细信息,请参见子载波分配和保护频带。
数据类型: Int64
pilotidx - 导频子载波位置的索引列向量
导频子载波位置的索引,指定为元素值从 1 到 nfft 的列向量。如果指定 pilotidx,则 outSym 中的行数为 (nfft-length(nullidx)-length(pilotidx))。有关详细信息,请参见子载波分配和保护频带。
数据类型: Int64
# 输出参数
outSym - 输出解调符号3维数组
pilots - 导频子载波3维数组
导频子载波,以
数据类型: Int64
# 详细信息
OFDM 解调
OFDM 解调器使用正交频分调制对多子载波时域信号进行多路复用。
OFDM 解调使用 FFT 运算产生 N 个并行数据流。OFDM 解调器由一组 N 个相关器组成,每个 OFDM 子载波分配一个相关器,然后进行并行到串行转换。

子载波分配和保护频带
单独的 OFDM 子载波被分配为数据、导频或空子载波。
如下图所示,子载波被指定为数据、DC、导频或保护带子载波。
数据子载波传输用户数据;
导频子载波用于信道估计;
空子载波不传输数据。没有数据的子载波用于提供 DC 空值并用作 OFDM 资源块之间的缓冲区;
如果 nfft 是偶数,则空 DC 子载波是频带的中心,索引值为 (nfft/2+1),如果 nfft 是奇数,则为 ((nfft+1)/2)。
保护带在连续的 OFDM 符号之间提供缓冲区,以通过减少符号间干扰来保护传输信号的完整性。
空子载波使用户能够针对特定标准(例如 802.11格式、LTE、WiMAX 或自定义分配)对保护带和 DC 子载波位置进行建模。用户可以通过分配空子载波索引向量来分配空值的位置。
在 OFDM 中,保护间隔与保护频带相似,通过减少码间干扰来保护传输信号的完整性。
保护间隔的分配类似于保护带的分配。用户可以对保护间隔进行建模以提供 OFDM 符号之间的时间间隔。保护间隔有助于在信号通过时间色散信道后保持符号间正交性。保护间隔是通过使用循环前缀创建的。循环前缀插入将 OFDM 符号的最后部分复制为 OFDM 符号的第一部分。
只要时间分散的跨度不超过循环前缀的持续时间,循环前缀插入的优势就保持不变。
因为循环前缀占用了可用于数据传输的带宽,所以插入循环前缀会导致用户数据吞吐量的部分减少。
窗口化和符号偏移
为了减少由在发射机中应用信号加窗而引入的符号间干扰 (ISI),该函数在解调每个 OFDM 符号之前应用分数符号偏移。信号加窗通常应用于传输的 OFDM 符号,以平滑连续 OFDM 符号之间的不连续性。加窗减少了符号间带外发射,但增加了 ISI。
加窗的 OFDM 符号由循环前缀 (CP)、ODFM 符号数据以及符号开头和结尾的加窗区域组成。如图所示,前导窗肩和尾窗肩都有尾巴。
为了减少码间干扰,用户可以通过在 OFDM 符号解调之前指定符号采样偏移来调整信号采样定时。
将符号采样偏移指定为从 0 到
当符号采样偏移是从 0 到
的标量时,FFT 窗口从 CP 长度的 x+1 样本开始; 当符号采样偏移为 0 时,不应用偏移,FFT 窗口从符号的第一个样本开始;
当符号采样偏移量是循环前缀长度
时,FFT 窗口在最后一个 CP 采样之后开始。如果未指定符号采样偏移,则此偏移为默认设置。