Code covered by the BSD License  

Highlights from
Exact BER for Gray-coded 2^2n-QAM modulation with AWGN

image thumbnail
from Exact BER for Gray-coded 2^2n-QAM modulation with AWGN by Paul A.M. Bune
Generates a MatLab-code expression for the exact theoretical BER for Gray-coded 2^2n-QAM modulation

ExactBER(varargin)
function ExactBER(varargin)
%
% Generates MatLab-code expressions describing the exact theoretical
% uncoded ("raw") bit error ratio vs. Eb/N0 and Es/N0 for the transmission
% of symmetrical binary signals using Gray-coded 2^2n-QAM modulation over
% an AWGN channel with a coherent detection receiver.
%
% LastMod 2008-04-25    Paul A.M. Bun - Alcatel-Lucent Stuttgart, Germany
% Created 2008-02-04    Paul A.M. Bun - Alcatel-Lucent Stuttgart, Germany
%
%
% Use:
% ===
%
% ExactBER(n)
% ExactBER(n, 'details')
%
% n = 1: QPSK
% n = 2: QAM16
% n = 3: QAM64
% n = 4: QAM256
% n = 5: QAM1024
% n = 6: QAM4096
% n = 7: QAM16384
% n = 8: QAM65536
%     etc.
%
%
% Example:
% =======
%
% >> ExactBER(2)
%
% Theoretical AWGN uncoded BER for QAM16:
% 
% EsN0 = 4 * EbN0
%
% F = sqrt(EsN0/10)
%
% BER = (3/8) * erfc(F) + (1/4) * erfc(3*F) - (1/8) * erfc(5*F)
%
%

ShowDetailsFlag = false;

if nargin == 0 || numel(varargin{1}) > 1 || varargin{1} < 1 || ...
    mod(varargin{1}, 1)
  disp('Please type "help ExactBER" for instructions.');
  return;
else
  NrOfClasses = varargin{1};
end

if nargin == 2
  if ischar(varargin{2}) && lower(varargin{2}(1)) == 'd'
    ShowDetailsFlag = true;
  else
    disp('Unknown option.');
    disp('Please type "help ExactBER" for instructions.');
    return;
  end
end

if NrOfClasses > 1
  ModulationString = ['QAM' num2str(bitshift(1, 2 * NrOfClasses))];
else
  ModulationString = 'QPSK';
end

disp(' ');
disp(['Theoretical AWGN uncoded BER for ' ModulationString ':']);
disp(' ');
disp(['EsN0 = ' num2str(2 * NrOfClasses) ' * EbN0']);
disp(' ');

Power = 0;
for iX = 1:bitshift(1, NrOfClasses - 1)
  for iY = 1:bitshift(1, NrOfClasses - 1)
    Power = Power + (2 * iX - 1)^2 + (2 * iX - 1)^2;
  end
end
Power = Power / (bitshift(1, NrOfClasses - 1))^2;
disp(['F = sqrt(EsN0/' num2str(Power) ')']);

BasicPattern = [1; 0; 0; 1];
NrOfPositions = bitshift(1, NrOfClasses);
BitConstellation = zeros(NrOfClasses, NrOfPositions);
Terms = zeros(NrOfClasses, NrOfPositions - 1, 2);
for iClass = 1:NrOfClasses
  if ShowDetailsFlag
    disp(' ');
  end
  SpreadingFactor =  bitshift(1, NrOfClasses - iClass);
  NrOfBitChanges = 0;
  BitChange = zeros(1, NrOfPositions);
  for iPosition = 1:NrOfPositions
    BasicPatternIndex = 1 + ...
      mod(floor((iPosition - 1)/ SpreadingFactor), 4);
    BitConstellation(iClass, iPosition) = BasicPattern(BasicPatternIndex);
    if iPosition > 1
      if BitConstellation(iClass, iPosition) ~= ...
          BitConstellation(iClass, iPosition - 1)
        NrOfBitChanges = NrOfBitChanges + 1;
        BitChange(NrOfBitChanges) = 2 * (iPosition - 1) - NrOfPositions;
      end
    end
    BitChange = BitChange(1:NrOfBitChanges);
  end
  for iBit = 0:1
    BitDimension = iBit + 1;
    for iPosition = 1:NrOfPositions
      if BitConstellation(iClass, iPosition) == iBit
        Position = 2 * iPosition - 1 - NrOfPositions;
        BitChangePosition = find(Position < BitChange, 1);
        if isempty(BitChangePosition)
          BitChangePosition = NrOfBitChanges + 1;
        end
        SignValue = -1;
        for iBitChange = (BitChangePosition - 1):-1:1
          SignValue = -SignValue;
          TermPosition = ...
            bitshift(abs(Position - BitChange(iBitChange)) + 1, -1);
          Terms(iClass, TermPosition, BitDimension) = ...
            Terms(iClass, TermPosition, BitDimension) + SignValue;
        end
        SignValue = -1;
        for iBitChange = BitChangePosition:NrOfBitChanges
          SignValue = -SignValue;
          TermPosition = ...
            bitshift(abs(Position - BitChange(iBitChange)) + 1, -1);
          Terms(iClass, TermPosition, BitDimension) = ...
            Terms(iClass, TermPosition, BitDimension) + SignValue;
        end
      end
    end
  end
  if ShowDetailsFlag
    if sum(abs(Terms(iClass, :, 1) - Terms(iClass, :, 2))) > 0
      for iBit = 0:1
        disp(['Class ' num2str(iClass) ', bit = ' num2str(iBit) ':']);
        WriteLine(NrOfPositions, Terms(iClass, :, iBit + 1), 2);
      end
    end
    if NrOfClasses > 1
      disp(['Class ' num2str(iClass) ':']);
      WriteLine(2 * NrOfPositions, sum(Terms(iClass, :, :), 3), 2);
    end
  end
end
if ShowDetailsFlag
  if NrOfClasses > 1
    disp(' ');
  end
end
if ShowDetailsFlag
  disp(['Overall ' ModulationString ':']);
  WriteLine(2 * NrOfPositions * NrOfClasses, ...
    sum(sum(Terms(:, :, :), 3), 1), 2);
else
  disp(' ');
  WriteLine(2 * NrOfPositions * NrOfClasses, ...
    sum(sum(Terms(:, :, :), 3), 1), 0);
end
disp(' ');
return;

% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

function WriteLine(Denominator, TermVector, Indentation)

Line = [repmat(' ', 1, Indentation) 'BER = '];
FirstTerm = true;
for iTerm = 1:length(TermVector)
  Term = TermVector(iTerm);
  if Term ~= 0
    if ~FirstTerm
      if Term < 0
        Line = [Line ' - '];
      else
        Line = [Line ' + '];
      end
    else
      if Term < 0
        Line = [Line '-'];
      end
    end
    FirstTerm = false;
    if abs(Term) == Denominator
      Line = [Line 'erfc('];
    else
      TermGCD = gcd(abs(Term), Denominator);
      Line = [Line '(' num2str(abs(Term)/TermGCD) '/' ...
        num2str(Denominator/TermGCD) ') * erfc('];
    end
    if iTerm > 1
      Line = [Line num2str(2 * iTerm - 1) '*'];
    end
    Line = [Line 'F)'];
  end
end
disp(Line);
return;

Contact us at files@mathworks.com