Code covered by the BSD License  

Highlights from
Comparison of C++ and MATLAB Using Object Oriented Application Example

image thumbnail

Comparison of C++ and MATLAB Using Object Oriented Application Example

by

 

28 Feb 2008 (Updated )

Wireless Communications Application Example Used to Compare C++ and MATLABĀ® Code

IEEE802_11b_Transmitter
% IEEE802_11b_Transmitter Class
%
% Copyright 2008-2009 The MathWorks, Inc

% C++ Code
%{
#include <math.h>
#include "ieee802.11b.h"
#include "util.h"
%}

classdef IEEE802_11b_Transmitter < Transmitter
    properties
        % C++ Code
        %{
            //** All bitrates **//
            FIRFilter m_H;      // RSRC pulse shaping filter
            double m_rollOff;   //raised cosine filter roll-off factor
            //** End all bitrates **/
            //** 1 Mb/s only **//
            bool m_diffEncMem;          // differential encoder memory
            static const Bits m_chip;   // Barker code
            //** End 1 Mb/s only **//
            //** 11 Mb/s (CCK) only **//
            Signal m_codeTable;     // 8*256 code table for all combinations of CCK code
            //** End 11 Mb/s (CCK) only **//
        %}
        m_H;                   % RSRC pulse shaping filter
        m_rollOff;             % Raised cosine filter roll-off factor
        m_diffEncMem;          % Differential encoder memory
        m_chip= [1,0,1,1,0,1,1,1,0,0,0]'; % Barker code
        m_codeTable;           % 8*256 code table for all combinations of
        m_freqTrack;           % Memory for the instantaneous phase generated by the frequency offset
    end
    methods
        function hObj=IEEE802_11b_Transmitter(varargin)
            % C++ Code
            %{
            IEEE802_11b_Transmitter::IEEE802_11b_Transmitter(int bitrate,
                                                             double phase_shift)
            : m_H(RSLENGTH),
              m_diffEncMem(false),  //diff encoder memory = 0
              m_codeTable(8*256)
            %}

            bitrate=varargin{1};
            phase_shift=getArg(2,varargin,0);

            hObj.m_H=FIRFilter(constants.RSLENGTH);
            hObj.m_diffEncMem=0;      % diff encoder memory = 0 (changed from boolean)
            hObj.m_codeTable=zeros(8*256,1);

            % C++ Code
            %{
            {
                m_bitrate = bitrate;
                setPhase(phase_shift);
                setRollOff(1.0);
                m_freqTrack = 0;

                initCodeTable();
            }
            %}
            hObj.m_bitrate = bitrate;
            hObj.m_phase=phase_shift;
            hObj.setRollOff(1);
            hObj.m_freqTrack = 0;
            initCodeTable(hObj);
        end

        % C++ Code
        %{
        //virtual
        IEEE802_11b_Transmitter::~IEEE802_11b_Transmitter() {
        }
        Not required
        %}

        function reset(hObj)
            % C++ Code
            %{
            //virtual
            void
            IEEE802_11b_Transmitter::reset() {
                setPhase(0.0);
                m_H.reset();
                m_freqTrack = 0;
                m_diffEncMem = false;
            }
            %}
            hObj.m_phase=0;
            reset(hObj.m_H);
            hObj.m_freqTrack = 0;
            hObj.m_diffEncMem = 0;
        end
        function diffOut=diffEncode(hObj,input)
            % C++ Code
            %{
            Bits
            IEEE802_11b_Transmitter::diffEncode(const Bits& input) {
                Bits diffOut(input.size());
                for (int j=0;j<input.size();++j) {
                    diffOut[j] = m_diffEncMem^input[j];
                    m_diffEncMem = diffOut[j];
                }

                return diffOut;
            }
            %}

            diffOut=zeros(length(input),1);
            % Can't vectorize
            for ii=1:length(input)
                diffOut(ii) = xor(hObj.m_diffEncMem,input(ii));
                hObj.m_diffEncMem = diffOut(ii);
            end

        end
        function spreadOut=addChips(hObj,input)
            % C++ Code
            %{
            Bits
            IEEE802_11b_Transmitter::addChips(const Bits& input) {
                Bits spreadOut(input.size()*Ns,false); //initialize to all zero
                _ASSERTE((spreadOut.size() % Ns) == 0);

                for (int i=0;i<input.size();++i){ // spread each bit individually by the Barker code
                    for(int j=0; j<11; ++j) { //insert three zero between each chip bit
                        spreadOut[i*Ns+4*j]= m_chip[j]^input[i];
                    }
                }
            	return spreadOut;
            }
            %}
            Ns=constants.Ns;
            spreadOut=zeros(Ns*length(input),1);
            spreadOut((1:4:length(input)*Ns)')=...
                bsxfun(@xor,hObj.m_chip,input');

        end
        function modOut=modulate_1Mb_s(hObj,input,df)
            % C++ Code
            %{
            Signal
            IEEE802_11b_Transmitter:: modulate_1Mb_s(const Bits& input,
                                                     double df) {
                Signal modOut(Ns*input.size());
                double nrzBit;
                double phase = getPhase();
                int offset=0;

                for (int i=0; i<input.size(); ++i) {
                    Bits diffOut=diffEncode(input[slice(i,1)]);
                    Bits spread=addChips(diffOut[slice(i,1)]);

                    for (int j=0; j<Ns; ++j){
                        double tt=df*(j+Ns*m_freqTrack)/((double)Ns);
                        if (tt>1) { tt=fmod(tt,1.); }
                        tt *= twopi;
                        nrzBit=0;
                        if ((j%4)==0) { nrzBit=dsign(spread[i*Ns+j]); }
                        Sample phaseOut=m_H.FilterStep(Sample(nrzBit,0.0));
                        modOut[offset*Ns+j]=exp(Sample(0.0,phase+tt))*phaseOut;
                    } // end j
                    offset++;
                    m_freqTrack++;
                } // end i

                return modOut;
            }
            %}

            % Get constanst for use later
            Ns=constants.Ns;
            twopi=constants.twopi;

            modOut=zeros(Ns*length(input),1);
            phase = hObj.m_phase;
            offset=0;

            for ii=1:length(input)

                diffOut =diffEncode(hObj,input(ii));
                spread=addChips(hObj,diffOut); % Perhpas C mistake

                % Vectorized
                jj=(0:Ns-1)';
                tt=df*(jj+Ns*hObj.m_freqTrack)/Ns;
                found=tt>1;
                tt(found)=rem(tt(found),1);
                tt = tt*twopi;
                nrzBit=zeros(Ns,1);
                found=(mod(jj,4)==0);
                nrzBit(found)=1-2*(spread(jj(found)+1));
                phaseOut=FilterStepN(hObj.m_H,nrzBit);
                modOut(offset*Ns+jj+1,1)=exp(j*(phase+tt)).*phaseOut;

                offset=offset+1;
                hObj.m_freqTrack=hObj.m_freqTrack+1;

            end

        end
        function modOut=modulate_11Mb_s(hObj,input)
            % C++ Code
            %{
            Signal
            IEEE802_11b_Transmitter:: modulate_11Mb_s(const Bits& input) {
                _ASSERTE(input.size() == codeLength);

                int nSamples = NsCCK*codeLength;
                Signal codeZero(nSamples, Sample(0.0,0.0));
                Signal modOut(NsCCK*codeLength);
                Signal codeRead(codeLength);

                unsigned Buf8 = 0;
            %}

            codeLength=constants.codeLength;
            NsCCK=constants.NsCCK;

            assert(length(input) == codeLength);
            nSamples = NsCCK*codeLength;
            codeZero=zeros(nSamples,1);

            Buf8 = 0; % Note: could use unsigned32

            % C++ Code
            %{
                int j;
                for (j=codeLength-1; j>=0; --j) {
                    Buf8 *= 2;
                    Buf8 += input[j];
                }
            %}
            for ii=codeLength:-1:1
                Buf8 = Buf8*2;
                Buf8 = Buf8+input(ii);
            end

            % Generate 8 output phase samples for the 8 bits

            % C++ Code
            %{
            int offset=codeLength*Buf8;
            %}
            offset=codeLength*Buf8;

            % C++ Code
            %{
             for (j=0; j<codeLength; ++j) { codeRead[j] = m_codeTable[offset+j]; }
            %}
            codeRead = hObj.m_codeTable(offset+(1:codeLength));

            % C++ Code
            %{
                for (j=0; j<nSamples; j += NsCCK) {
                    codeZero[j] = codeRead[j/NsCCK];
                }
            %}
            codeZero(1:NsCCK:nSamples) = codeRead;

            % C++ Code
            %{
            %     for (j=0; j<nSamples; ++j) {
            %         Sample out = m_H.FilterStep(codeZero[j]);
            %         modOut[j] = out;
            %     }
            %}
            modOut = FilterStepN(hObj.m_H,codeZero);

            % C++ Code
            %{
                 return modOut;
             }
            %}
        end
        function modOut=transmit(hObj,input,df)
            % C++ Code
            %{
            //virtual
            Signal
            IEEE802_11b_Transmitter:: transmit(const Bits& input,
                                               double df) {
                switch (m_bitrate) {
                case 1:
                    return modulate_1Mb_s(input, df); break;
                case 11: {
                    const int nSamples=codeLength*NsCCK;
                    _ASSERTE((input.size() % codeLength) == 0);
                    Signal modOut(NsCCK*input.size());
                    int begin = 0;
                    int end = nSamples-1;
                    for (int i=0; i<input.size(); i += codeLength) {
                        Bits inputSlice = input[slice(i,codeLength)];
                        modOut.set(modulate_11Mb_s(inputSlice), begin, end);
                        begin += nSamples; end += nSamples;
                    }
                    return modOut; break;
                }
                default:
                    _ASSERTE(false);
                    fprintf(stderr,"Error: %d is not a valid bitrate.\n", m_bitrate);
                    Signal empty;
                    return empty;
                    break;
                }
            }
            %}

            % Get Constants for use later
            codeLength=constants.codeLength;
            NsCCK=constants.NsCCK;

            switch hObj.m_bitrate
                case 1
                    modOut=modulate_1Mb_s(hObj,input, df);
                case 11
                    nSamples=codeLength*NsCCK;
                    assert(mod(length(input), codeLength) == 0);
                    modOut=zeros(NsCCK*length(input),1);
                    begin = 1;
                    ending = nSamples;
                    for ii=1:codeLength:length(input)
                        inputSlice = input(ii:(ii+codeLength-1));
                        modOut(begin:ending)=modulate_11Mb_s(hObj,inputSlice);
                        begin = begin+nSamples;
                        ending = ending+nSamples;
                    end
                otherwise
                    error('Error: %d is not a valid bitrate.\n', hObj.m_bitrate);
            end
        end
        function out=minInputLength(hObj)
            % C++ Code
            %{
            //virtual
            int
            IEEE802_11b_Transmitter::minInputLength() const {
                switch (m_bitrate) {
                case 1:
                    return 1; break;
                case 11:
                    return codeLength; break;
                default:
                    _ASSERTE(false);
                    fprintf(stderr,"Error: %d is not a valid bitrate.\n", m_bitrate);
                    return 0;
                    break;
                }
            }
            %}
            switch hObj.m_bitrate
                case 1
                    out=1;
                case 11
                    out=constants.codeLength;
                otherwise
                    error('Error: %d is not a valid bitrate.\n', hObj.m_bitrate);
                    out=0;
            end

        end
        function setRollOff(hObj,rollOff)
            % C++ Code
            %{
            void
            IEEE802_11b_Transmitter::setRollOff(double rollOff) {
                m_rollOff = rollOff;
                setRSRCpulseShapingFilter(m_H, rollOff);
            }
            %}
            hObj.m_rollOff=rollOff;
            hObj.m_H=setRSRCpulseShapingFilter(hObj.m_H,rollOff);
        end

        % C++ Code
        %{
        double
        IEEE802_11b_Transmitter::getRollOff() const {
            return m_rollOff;
        }
        Not required
        %}

        function initCodeTable(hObj)
            % C++ Code
            %{
            void
            IEEE802_11b_Transmitter::initCodeTable() {
                double phase[4] = { 0.0, PI, PI/2.0, 1.5*PI };
                double ph[4];
            %}

            % Get Constants
            PI=constants.PI;
            codeLength=constants.codeLength;

            phase=[0;PI;PI/2;1.5*PI];
            ph=zeros(4,1);

            % C++ Code
            %{
            for (int i=0; i<256; ++i) {
            %}
            for ii=0:255
                % QPSK phase
                % C++ Code
                %{
                        ph[0] = phase[i & 0x03];
                        ph[1] = phase[(i>>2) & 0x03];
                        ph[2] = phase[(i>>4) & 0x03];
                        ph[3] = phase[(i>>6) & 0x03];
                %}

                % 1 + to account of one based indexing
                ku=uint32(ii);
                ph(1)=phase(1+bitand(ku,uint32(3)));
                ph(2)=phase(1+bitand(bitshift(ku,-2),uint32(3)));
                ph(3)=phase(1+bitand(bitshift(ku,-4),uint32(3)));
                ph(4)=phase(1+bitand(bitshift(ku,-6),uint32(3)));

                % CCK phase output
                % C++ Code
                %{
                m_codeTable[codeLength*i+0] =  exp(Sample(0.0,ph[0]+ph[1]+ph[2]+ph[3]));
                m_codeTable[codeLength*i+1] =  exp(Sample(0.0,ph[0]+ph[2]+ph[3]));
                m_codeTable[codeLength*i+2] =  exp(Sample(0.0,ph[0]+ph[1]+ph[3]));
                m_codeTable[codeLength*i+3] = -exp(Sample(0.0,ph[0]+ph[3]));
                m_codeTable[codeLength*i+4] =  exp(Sample(0.0,ph[0]+ph[1]+ph[2]));
                m_codeTable[codeLength*i+5] =  exp(Sample(0.0,ph[0]+ph[2]));
                m_codeTable[codeLength*i+6] = -exp(Sample(0.0,ph[0]+ph[1]));
                m_codeTable[codeLength*i+7] =  exp(Sample(0.0,ph[0]));
                %}
                hObj.m_codeTable(1+codeLength*ii+0) =  exp(j*(ph(1)+ph(2)+ph(3)+ph(4)));
                hObj.m_codeTable(1+codeLength*ii+1) =  exp(j*(ph(1)      +ph(3)+ph(4)));
                hObj.m_codeTable(1+codeLength*ii+2) =  exp(j*(ph(1)+ph(2)      +ph(4)));
                hObj.m_codeTable(1+codeLength*ii+3) = -exp(j*(ph(1)            +ph(4)));
                hObj.m_codeTable(1+codeLength*ii+4) =  exp(j*(ph(1)+ph(2)+ph(3)));
                hObj.m_codeTable(1+codeLength*ii+5) =  exp(j*(ph(1)      +ph(3)));
                hObj.m_codeTable(1+codeLength*ii+6) = -exp(j*(ph(1)+ph(2)));
                hObj.m_codeTable(1+codeLength*ii+7) =  exp(j*(ph(1)));
            end
        end

        % C++ Code
        %{
        //static
function a=m_chip
                    % const Bits IEEE802_11b_Transmitter::m_chip = Bits(a,11);

                    % static bool a[11] = {1,0,1,1,0,1,1,1,0,0,0};
                    a = {1,0,1,1,0,1,1,1,0,0,0};
        end
        Not used. Implemented as constant property
        %}
    end
end

function out = dsign(bval)
% Not used. In lined instead
% C++ Code
%{
static inline double dsign(bool bval) { return ((bval) ? -1.0 : 1.0); }
%}
if bval
    out=-1;
else
    out =1;
end
end

Contact us