Code covered by the BSD License

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

### Stuart McGarrity (view profile)

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
% C++ Code
%{
Bits
Bits spreadOut(input.size()*Ns,false); //initialize to all zero

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
}
}
}
%}
Ns=constants.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)]);

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;
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));

% 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);
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);

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]; }
%}

% C++ Code
%{
for (j=0; j<nSamples; j += NsCCK) {
}
%}

% 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
```