% 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