Code covered by the BSD License  

Highlights from
pskdemodXOR

pskdemodXOR

by

 

08 Dec 2011 (Updated )

Implements a demodulator object for M-PSK physical layer network coding.

pskdemodXOR
classdef pskdemodXOR < handle
% pskdemodXOR 
%   - implements a demodulator object for M-PSK physical layer network coding 
%   - facilitates 'XOR over the air' through ML detection of x = x1 + x2,
%     where x1, x2 are data streams identically modulated with M-PSK
%   - the constructor accepts a 'modem.pskmod' object (of Communications System Toolbox),
%     and creates a matching 'pskdemodXOR' object
%   - member function 'demodulate' handles the demodulation 
%
%   e.g. usage:
%       M = 8; K = 100;
%       hMod = modem.pskmod(M); 
%       hDemod = pskdemodXOR(hMod);
%       D1 = randi(M,1,K)-1; x1 = modulate(hMod,D1);
%       D2 = randi(M,1,K)-1; x2 = modulate(hMod,D2);
%       D = hDemod.demodulate(x1+x2); 
%       all(bitxor(D1,D2)==D)  % ans = 1
%
%   - properties: 
%     -----------
%   - following properties are readonly, and set at construction to match
%   the 'modem.pskmod' object
%       M, PhaseOffset, SymbolOrder = {'Binary','Gray'}
%   - 'OutputType' is set at construction; but can be reset
%           e.g. obj.OutputType = 'Bit'
%   - 'XORConstellation' and 'XORSymbolMapping' stores the constellation
%   and the symbol mapping corresponding to the XORed streams
%   - only DecisionType = 'Hard decision' is supported presently
%
%   - member functions: 
%     ----------------
%     demodulate (symbol-by-symbol ML detection), 
%     show (displays XORed constellation), 
%     mindist (computes min. distance between 2 points in the constellation)
%
%   - for details see help on each function (e.g. help pskdemodXOR.demodulate ) 
%
%   Author        : Damith Senaratne, (http://www.damiths.info)
%   Released date : 14th November 2011 
%   Version       : 1.0

    properties
        OutputType = 'Integer' % 'Bit' or 'Integer'
    end
    
    properties(SetAccess = private)
        M = [] % 2,4,8,16,...
        PhaseOffset = 0;
        SymbolOrder = 'Binary' % 'Binary' or 'Gray'
        DecisionType = 'Hard decision'
        XORConstellation = []
        XORSymbolMapping = []
    end
    
    properties(Access = private)
        Integer2Bits = [] % used only when OutputType = 'Bit'
    end
    
    methods
        function this = pskdemodXOR(arg)   
        % --------------------
        % constructor       
        % ------------
        %
        %   usage: (e.g.)
        %       hMod = modem.pskmod(...); 
        %       hDemod = pskdemodXOR(hMod);
        % --------------------
            if nargin == 0
                % default constructor: required when constructing arrays!
            elseif isa(arg,'pskdemodXOR')
                this = arg; 
            elseif strcmp(class(arg),'modem.pskmod')
                hMod = arg;
                if strcmp(hMod.Type,'PSK Modulator')  
                    this.M = hMod.M;
                    this.PhaseOffset = hMod.PhaseOffset;
                    this.SymbolOrder = hMod.SymbolOrder;
                    this.OutputType = hMod.InputType;
                    if strcmp(this.OutputType,'Bit')
                        this.setInteger2BitMap;
                    end
                    this.setXORConstMapping(hMod);
                else
                    error('pskdemodXOR: unsupported modulation scheme!');
                end
            else
                error('pskdemodXOR: invalid usage!');
            end
        end
        
        function y = demodulate(this, x)
        % --------------------
        % demodulate
        %   - implements `XOR over the air' through symbol-by-symbol ML detection of x = x1 + x2,
        %     where x1,x2 are data streams identically modulated with M-PSK
        %   - x can be of arbitary dimensions
        %   - a cell array is returned if 'Output Type' is 'Bit'
        %     (use: 'cell2mat' to expand the cells)
        %
        %   e.g. usage:
        %       M = 8; K = 100;
        %       hMod = modem.pskmod(M); 
        %       hDemod = pskdemodXOR(hMod);
        %       D1 = randi(M,1,K)-1; x1 = modulate(hMod,D1);
        %       D2 = randi(M,1,K)-1; x2 = modulate(hMod,D2);
        %       D = hDemod.demodulate(x1+x2); 
        %       all(bitxor(D1,D2)==D)  % ans = 1
        % --------------------
            OutputBits = strcmp(this.OutputType,'Bit');
            
            if OutputBits
                y = cell(size(x));
            else
                y = zeros(size(x));
            end
            
            for k = 1:length(x(:)) % loop for each symbol
                % determine closest XORed constellation point
                [~,I] = min(abs(x(k)-this.XORConstellation)); 
                if OutputBits
                    y{k} = this.Integer2Bits(:,this.XORSymbolMapping(I(1))+1);
                else
                    y(k) = this.XORSymbolMapping(I(1));
                end
            end
        end
        
        function show(this)
        % --------------------
        % show
        %   - displays the constellation diagram
        % 
        % usage: object.show;
        % --------------------
        plot(real(this.XORConstellation),imag(this.XORConstellation),'x');
            hold on;
            for k = 1:length(this.XORConstellation)
               text(real(this.XORConstellation(k)),imag(this.XORConstellation(k))+0.05,dec2bin(this.XORSymbolMapping(k),log2(this.M))); 
            end
            v = axis;
            v(1) = v(1)-0.25; v(2) = v(2)+0.25; v(3) = v(3)-0.25; v(4) = v(4)+0.25;
            axis(v); 
        end
        
       
        function d = mindist(this)
        % --------------------
        % mindist
        %   - computes the minimum distance between 2 constellation points
        % 
        % usage: object.mindst;
        % --------------------
            d = min(abs(this.XORConstellation(2:end)-this.XORConstellation(1)));
            for k = 2:length(this.XORConstellation)-1
                tmp = min(abs(this.XORConstellation(k+1:end)-this.XORConstellation(k)));
                if tmp<d
                   d = tmp; 
                end
            end
        end
        
        % ------------
        % set methods      
        % ------------
        function set.OutputType(this, val)
            if strcmp(val,'Integer') || strcmp(val,'Bit') 
                this.OutputType = val;
                this.setInteger2BitMap;
            else
                error('pskdemodXOR: invalid OutputType: ''%s''',val);
            end
        end
        
    end 
    
    methods(Access = private)
        % -------------------
        % private utilities!
        % -------------------
        
        function setInteger2BitMap(this)
            if strcmp(this.OutputType,'Integer')
                this.Integer2Bits = [];
            else
                r = ceil(log2(this.M));
                this.Integer2Bits = zeros(r,this.M);
                s = 0:this.M-1;
                for k = 1:r
                    this.Integer2Bits(k,:) = mod(s,2);
                    s = fix(s/2);
                end
            end
        end
        
        function this = setXORConstMapping(this,hMod)
            [x,y] = meshgrid(hMod.SymbolMapping,hMod.SymbolMapping); map = bitxor(x,y);
            [x,y] = meshgrid(hMod.Constellation,hMod.Constellation); const = x + y;

            trunc = @(x)real(x).*(abs(real(x))>1e-10) + 1i* imag(x).*(abs(imag(x))>1e-10); 
            const = trunc(const(:)); % truncate (to avoid accuracy vs. precision issues)
            [tmp,I,J] = unique([real(const), imag(const)],'rows'); % get unique constellation points
            this.XORConstellation = (tmp(:,1)+1i*tmp(:,2)).';
            this.XORSymbolMapping = map(I.');

            % verify that XOR over the air holds!
            if any(this.XORSymbolMapping(J).' ~= map(:))
                error('pskdemodXOR: setXORConstMapping: constellation invcompatible with XOR over the air!');
            end
        end
    end

end

Contact us