Нормализация созвездия PeakPower
и AveragePower
(кроме модульной средней степени), как поддержано comm.RectangularQAMModulator
и comm.RectangularQAMDemodulator
по сути не обеспечивается функциями. Этот код показывает вам, как выполнить пиковую мощность и среднюю нормализацию степени с помощью qammod
и qamdemod
функции.
Средняя нормализация степени для трудного решения
Нормализация пиковой мощности для трудного решения
Средняя нормализация степени для аппроксимированного LLR
>> averagePowerReplacementApproxLLR(16, 10, 1) % M=16, avgPow=10, snrdB=1
maxConstellationErr =
0
maxOutputErr =
0
>> averagePowerReplacementApproxLLR(32, 7, 20) % M=32, avgPow=7, snrdB=20
maxConstellationErr =
0
maxOutputErr =
8.5265e-14
>> averagePowerReplacementApproxLLR(64, 111, -2) % M=64, avgPow=111, snrdB=-2
maxConstellationErr =
0
maxOutputErr =
2.2204e-15
>> averagePowerReplacementApproxLLR(1024, 87, 33) % M=1024, avgPow=87, snrdB=33
maxConstellationErr =
0
maxOutputErr =
1.3642e-12
function averagePowerReplacementApproxLLR(M, avgPow, snrdB)
% QAM Workaround for "Average power" normalization method for
% Approximate LLR output when using functions
%
% M - Modulation order. Must be supported by QAM modulator-demodulator
% avgPow - Average constellation power
% snrdB - SNR, in dB. AWGN channel adds noise to provide this SNR.
minD = avgPow2MinD(avgPow, M);
modObj = comm.RectangularQAMModulator('ModulationOrder', M, ...
'NormalizationMethod', 'Average power', ...
'AveragePower', avgPow);
% 1) The two constellations are same
constellationSO = modObj((0:M-1)');
constellationFcn = qammod((0:M-1)', M);
scaledConstellationFcn = (minD/2) .* constellationFcn;
err = constellationSO - scaledConstellationFcn;
maxConstellationErr = max(abs(err))
x = randi([0, M-1], 100, 1);
y1 = modObj(x);
% Add noise
% Reset global rng stream for repeatable noise samples
reset(RandStream.getGlobalStream);
y1Rec = awgn(y1, snrdB, 'measured', 'db');
% noise variance
nv = mean(abs(y1).^2) / 10^(snrdB/10);
demodObj = comm.RectangularQAMDemodulator('ModulationOrder', M, ...
'NormalizationMethod', 'Average power', ...
'AveragePower', avgPow, ...
'BitOutput', true, ...
'DecisionMethod', 'Approximate log-likelihood ratio', ...
'Variance', nv);
z1 = demodObj(y1Rec);
% 2) Functions' output is same as System objects' output, with right
% scaling
y2 = qammod(x, M);
% Scale function's output so that it matches System object output.
y2Scaled = (minD/2) .* y2;
% Add noise
% Reset global rng stream for repeatable noise samples
reset(RandStream.getGlobalStream);
y2Rec = awgn(y2Scaled, snrdB, 'measured', 'db');
% noise variance
nv1 = mean(abs(y2Scaled).^2) / 10^(snrdB/10);
% Scale the received signal for the constellation used by function
y2RecScaled = (2/minD) .* y2Rec;
% Scale the noise variance appropriately
z2 = qamdemod(y2RecScaled, M, 'OutputType', 'approxllr', ...
'NoiseVariance', nv1 * (2/minD)^2);
maxOutputErr = max(abs(z1-z2))
end
function minD = avgPow2MinD(avgPow, M)
% Average power to minimum distance
nBits = log2(M);
if (mod(nBits,2)==0)
% Square QAM
sf = (M - 1)/6;
else
% Cross QAM
if (nBits > 4)
sf = ((31 * M / 32) - 1) / 6;
else
sf = ((5 * M / 4) - 1) / 6;
end
end
minD = sqrt(avgPow/sf);
end
Нормализация пиковой мощности для аппроксимированного LLR
>> peakPowerReplacementApproxLLR(4, 2.5, 7) % M=4, pkPow=2.5, snrdB=7
maxConstellationErr =
0
maxOutputErr =
7.1054e-15
>> peakPowerReplacementApproxLLR(16, 19, 0) % M=16, pkPow=19, snrdB=0
maxConstellationErr =
0
maxOutputErr =
4.4409e-15
>> peakPowerReplacementApproxLLR(128, 12, 4.4) % M=128, pkPow=12, snrdB=4.4
maxConstellationErr =
0
maxOutputErr =
2.6645e-15
>> peakPowerReplacementApproxLLR(256, 221, 16) % M=256, pkPow=221, snrdB=16
maxConstellationErr =
0
maxOutputErr =
2.8422e-14
function peakPowerReplacementApproxLLR(M, pkPow, snrdB)
% QAM Workaround for "Peak power" normalization method for
% Approximate LLR output when using functions
%
% M - Modulation order. Must be supported by QAM modulator-demodulator
% avgPow - Average constellation power
% snrdB - SNR, in dB. AWGN channel adds noise to provide this SNR.
minD = pkPow2MinD(pkPow, M);
modObj = comm.RectangularQAMModulator('ModulationOrder', M, ...
'NormalizationMethod', 'Peak power', ...
'PeakPower', pkPow);
% 1) The two constellations are same
constellationSO = modObj((0:M-1)');
constellationFcn = qammod((0:M-1)', M);
scaledConstellationFcn = (minD/2) .* constellationFcn;
err = constellationSO - scaledConstellationFcn;
maxConstellationErr = max(abs(err))
x = randi([0, M-1], 100, 1);
y1 = modObj(x);
% Add noise
% Reset global rng stream for repeatable noise samples
reset(RandStream.getGlobalStream);
y1Rec = awgn(y1, snrdB, 'measured', 'db');
% noise variance
nv = mean(abs(y1).^2) / 10^(snrdB/10);
demodObj = comm.RectangularQAMDemodulator('ModulationOrder', M, ...
'NormalizationMethod', 'Peak power', ...
'PeakPower', pkPow, ...
'BitOutput', true, ...
'DecisionMethod', 'Approximate log-likelihood ratio', ...
'Variance', nv);
z1 = demodObj(y1Rec);
% 2) Functions' output is same as System objects' output, with right
% scaling
y2 = qammod(x, M);
% Scale function's output so that it matches System object output.
y2Scaled = (minD/2) .* y2;
% Add noise
% Reset global rng stream for repeatable noise samples
reset(RandStream.getGlobalStream);
y2Rec = awgn(y2Scaled, snrdB, 'measured', 'db');
% noise variance
nv1 = mean(abs(y2Scaled).^2) / 10^(snrdB/10);
% Scale the received signal for the constellation used by function
y2RecScaled = (2/minD) .* y2Rec;
% Scale the noise variance appropriately
z2 = qamdemod(y2RecScaled, M, 'OutputType', 'approxllr', ...
'NoiseVariance', nv1 * (2/minD)^2);
maxOutputErr = max(abs(z1-z2))
end
function minD = pkPow2MinD(pkPow, M)
% Peak power to minimum distance
nBits = log2(M);
if (mod(nBits,2)==0)
% Square QAM
sf = 0.5*M - sqrt(M) + 0.5;
else
% Cross QAM
mBy32 = M/32;
if (nBits > 4)
sf = (13 * mBy32) - (5 * sqrt(mBy32)) + 0.5;
else
sf = (20 * mBy32) - (6 * sqrt(mBy32)) + 0.5;
end
end
minD = sqrt(pkPow/sf);
end
Средняя нормализация степени для LLR
>> averagePowerReplacementLLR(16, 20, 1) % M=16, avgPow=20, snrdB=1
maxConstellationErr =
0
maxOutputErr =
8.8818e-16
>> averagePowerReplacementLLR(32, 5.5, 15) % M=32, avgPow=5.5, snrdB=15
maxConstellationErr =
0
maxOutputErr =
7.1054e-15
>> averagePowerReplacementLLR(64, 100, -2) % M=64, avgPow=100, snrdB=-2
maxConstellationErr =
0
maxOutputErr =
8.8818e-16
>> averagePowerReplacementLLR(256, 117, 8) % M=256, avgPow=117, snrdB=8
maxConstellationErr =
0
maxOutputErr =
3.5527e-15
function averagePowerReplacementLLR(M, avgPow, snrdB)
% QAM
% Workaround for "Average power" normalization method for
% LLR output when using functions
%
% M - Modulation order. Must be supported by QAM modulator-demodulator
% avgPow - Average constellation power
% snrdB - SNR, in dB. AWGN channel adds noise to provide this SNR.
minD = avgPow2MinD(avgPow, M);
modObj = comm.RectangularQAMModulator('ModulationOrder', M, ...
'NormalizationMethod', 'Average power', ...
'AveragePower', avgPow);
% 1) The two constellations are same
constellationSO = modObj((0:M-1)');
constellationFcn = qammod((0:M-1)', M);
scaledConstellationFcn = (minD/2) .* constellationFcn;
err = constellationSO - scaledConstellationFcn;
maxConstellationErr = max(abs(err))
x = randi([0, M-1], 100, 1);
y1 = modObj(x);
% Add noise
% Reset global rng stream for repeatable noise samples
reset(RandStream.getGlobalStream);
y1Rec = awgn(y1, snrdB, 'measured', 'db');
% noise variance
nv = mean(abs(y1).^2) / 10^(snrdB/10);
demodObj = comm.RectangularQAMDemodulator('ModulationOrder', M, ...
'NormalizationMethod', 'Average power', ...
'AveragePower', avgPow, ...
'BitOutput', true, ...
'DecisionMethod', 'Log-likelihood ratio', ...
'Variance', nv);
z1 = demodObj(y1Rec);
% 2) Get the same output as System object using functions
y2 = qammod(x, M);
% Scale function's output so that it matches System object output.
y2Scaled = (minD/2) .* y2;
% Add noise
% Reset global rng stream for repeatable noise samples
reset(RandStream.getGlobalStream);
y2Rec = awgn(y2Scaled, snrdB, 'measured', 'db');
% noise variance
nv1 = mean(abs(y2Scaled).^2) / 10^(snrdB/10);
% Create inputs required by utility function to compute LLR
nBits = log2(M);
bitwiseMapping = de2bi((0:M-1)', nBits, 'left-msb');
% c0 contains indices of mapping which has 0 at various bit positions
[c0, ~] = find(bitwiseMapping==0);
c0 = reshape(int32(c0), M/2, nBits);
% c1 contains indices of mapping which has 1 at various bit positions
[c1, ~] = find(bitwiseMapping==1);
c1 = reshape(int32(c1), M/2, nBits);
z2 = comm.internal.utilities.computeLLRsim(y2Rec, M, nBits, ...
scaledConstellationFcn, c0, c1, nv1);
maxOutputErr = max(abs(z1-z2))
end
function minD = avgPow2MinD(avgPow, M)
% Average power to minimum distance
nBits = log2(M);
if (mod(nBits,2)==0)
% Square QAM
sf = (M - 1)/6;
else
% Cross QAM
if (nBits > 4)
sf = ((31 * M / 32) - 1) / 6;
else
sf = ((5 * M / 4) - 1) / 6;
end
end
minD = sqrt(avgPow/sf);
end
Нормализация пиковой мощности для LLR
>> peakPowerReplacementLLR(8, 21, 0) % M=8, pkPow=21, snrdB=0
maxConstellationErr =
0
maxOutputErr =
8.8818e-16
>> peakPowerReplacementLLR(64, 7, 22) % M=64, pkPow=7, snrdB=22
maxConstellationErr =
0
maxOutputErr =
7.1054e-15
>> peakPowerReplacementLLR(512, 1000, -5) % M=512, pkPow=1000, snrdB=-5
maxConstellationErr =
0
maxOutputErr =
2.6645e-15
>> peakPowerReplacementLLR(1024, 1, 6) % M=1024, pkPow=1, snrdB=6
maxConstellationErr =
0
maxOutputErr =
3.5527e-15
function peakPowerReplacementLLR(M, pkPow, snrdB)
% QAM Workaround for "Peak power" normalization method for
% LLR output when using functions
%
% M - Modulation order. Must be supported by QAM modulator-demodulator
% avgPow - Average constellation power
% snrdB - SNR, in dB. AWGN channel adds noise to provide this SNR.
minD = pkPow2MinD(pkPow, M);
modObj = comm.RectangularQAMModulator('ModulationOrder', M, ...
'NormalizationMethod', 'Peak power', ...
'PeakPower', pkPow);
% 1) The two constellations are same
constellationSO = modObj((0:M-1)');
constellationFcn = qammod((0:M-1)', M);
scaledConstellationFcn = (minD/2) .* constellationFcn;
err = constellationSO - scaledConstellationFcn;
maxConstellationErr = max(abs(err))
x = randi([0, M-1], 100, 1);
y1 = modObj(x);
% Add noise
% Reset global rng stream for repeatable noise samples
reset(RandStream.getGlobalStream);
y1Rec = awgn(y1, snrdB, 'measured', 'db');
% noise variance
nv = mean(abs(y1).^2) / 10^(snrdB/10);
demodObj = comm.RectangularQAMDemodulator('ModulationOrder', M, ...
'NormalizationMethod', 'Peak power', ...
'PeakPower', pkPow, ...
'BitOutput', true, ...
'DecisionMethod', 'Log-likelihood ratio', ...
'Variance', nv);
z1 = demodObj(y1Rec);
% 2) Get the same output as System object using functions
y2 = qammod(x, M);
% Scale function's output so that it matches System object output.
y2Scaled = (minD/2) .* y2;
% Add noise
% Reset global rng stream for repeatable noise samples
reset(RandStream.getGlobalStream);
y2Rec = awgn(y2Scaled, snrdB, 'measured', 'db');
% noise variance
nv1 = mean(abs(y2Scaled).^2) / 10^(snrdB/10);
% Create inputs required by utility function to compute LLR
nBits = log2(M);
bitwiseMapping = de2bi((0:M-1)', nBits, 'left-msb');
% c0 contains indices of mapping which has 0 at various bit positions
[c0, ~] = find(bitwiseMapping==0);
c0 = reshape(int32(c0), M/2, nBits);
% c1 contains indices of mapping which has 1 at various bit positions
[c1, ~] = find(bitwiseMapping==1);
c1 = reshape(int32(c1), M/2, nBits);
z2 = comm.internal.utilities.computeLLRsim(y2Rec, M, nBits, ...
scaledConstellationFcn, c0, c1, nv1);
maxOutputErr = max(abs(z1-z2))
end
function minD = pkPow2MinD(pkPow, M)
% Peak power to minimum distance
nBits = log2(M);
if (mod(nBits,2)==0)
% Square QAM
sf = 0.5*M - sqrt(M) + 0.5;
else
% Cross QAM
mBy32 = M/32;
if (nBits > 4)
sf = (13 * mBy32) - (5 * sqrt(mBy32)) + 0.5;
else
sf = (20 * mBy32) - (6 * sqrt(mBy32)) + 0.5;
end
end
minD = sqrt(pkPow/sf);
end