Constellation normalization by PeakPower
and
AveragePower
(other than unit average power) as supported
by comm.RectangularQAMModulator
and
comm.RectangularQAMDemodulator
is not
inherently provided by functions. This code shows you how to perform peak power and
average power normalization using qammod
and qamdemod
functions.
Average Power Normalization for Hard Decision
Output shown here compares computation of average power normalization for hard
decision using alternative approach. Functions used follow the output.
>> averagePowerReplacement(64)
maxConstellationErr =
0
objModDemodOutputIsEqual =
logical
1
objModFcnDemodIsEqual =
logical
1
fcnModObjDemodIsEqual =
logical
1
>> averagePowerReplacement(32)
maxConstellationErr =
0
objModDemodOutputIsEqual =
logical
1
objModFcnDemodIsEqual =
logical
1
fcnModObjDemodIsEqual =
logical
1
Functions shown here compares computation of average power normalization for
hard decision using alternative approach.
Peak Power Normalization for Hard Decision
Output shown here compares computation of peak power normalization for hard
decision using alternative approach. Functions used follow the output.
>> peakPowerReplacement(16)
maxConstellationErr =
0
objModDemodOutputIsEqual =
logical
1
objModFcnDemodIsEqual =
logical
1
fcnModObjDemodIsEqual =
logical
1
>> peakPowerReplacement(128)
maxConstellationErr =
0
objModDemodOutputIsEqual =
logical
1
objModFcnDemodIsEqual =
logical
1
fcnModObjDemodIsEqual =
logical
1
Functions shown here compares computation of peak power normalization for hard
decision using alternative approach.
Average Power Normalization for Approximate LLR
Output shown here compares computation of average power normalization for
approximate LLR using alternative approach. Functions used follow the
output.
>> 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
Functions shown here compares computation of average power normalization for
approximate LLR using alternative approach.
Peak Power Normalization for Approximate LLR
Output shown here compares computation of peak power normalization for
approximate LLR using alternative approach. Functions used follow the
output.
>> 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
Functions shown here compares computation of peak power normalization for
approximate LLR using alternative approach.
Average Power Normalization for LLR
Output shown here compares computation of average power normalization for LLR
using alternative approach. Functions used follow the output.
>> 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
Functions shown here compares computation of average power normalization for
LLR using alternative approach.
function averagePowerReplacementLLR(M, avgPow, snrdB)
% QAM alternative 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
Peak Power Normalization for LLR
Output shown here compares computation of peak power normalization for LLR
using alternative approach. Functions used follow the output.
>> 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
Functions shown here compares computation of peak power normalization for LLR
using alternative approach.
function peakPowerReplacementLLR(M, pkPow, snrdB)
% QAM alternative 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