⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 get_packet_timing.m

📁 source Matlab traites the UWB
💻 M
字号:
%
% NN:      number of users
% NPKTS:   number of packets to simulate
% lambda:  queue arrival rate (packets per second)l
% ack_gap:
% WARMUP:  number of warmup packets to pass transient phase
% NSYNC:
% NSFD:
% TC:
% L:
% G:
% PACKET_LENGTH:
% SYMBOL_LENGTH:
% code_len:
% PLOT_DEBUG:
%
% This function returns the struct stat
%
% stat.startTimes:       same but only for the time when we are not
%                        in warmup
% stat.stopTimes:        dito
% stat.UOIPktsSimulated: the number of UOI packets simulated so far
% stat.packets:          packet starting times plus node numbers
%
function [stat] = ...
    get_packet_timing(NN,NPKTS,lambda,ack_gap,WARMUP,NSYNC,NSFD,TC,L,G,...
    PACKET_LENGTH,SYMBOL_LENGTH,code_len,PLOT_DEBUG)

%lambda = 500; %queue arrival rate (packets per second)
preamble_len = (NSYNC + NSFD)*code_len*L*TC;
packet_len   = preamble_len + (PACKET_LENGTH*SYMBOL_LENGTH*TC); %packet length in seconds
payload_len  = packet_len - preamble_len;
templ_len    = G * code_len * L * TC; %length of sync template

% They might be required later
stat.preamble_len = preamble_len;
stat.packet_len   = packet_len;
stat.payload_len  = payload_len;

%repeat lambda if size 1
if(length(lambda)==1)
    lambda = lambda * ones(1,2);
end

%max lambda that can be sustained
lambda_max = floor(1/(packet_len+ack_gap));
fprintf('Maximum Lambda = %.2f\n',lambda_max);
if(sum(lambda > lambda_max)) %one of the lambdas is bigger
  warning('lambda > lambda_max = %d',lambda_max);
  lambda(lambda > lambda_max) = lambda_max;
end
%ack_gap = 0; %seconds
sec_per_symbol = SYMBOL_LENGTH * TC;

%from 802.15.4-2006 standard
macMinBE = 8;%3; %min backoff exponent
aUnitBackoffPeriod = 20; %symbols per backoff period

%we adapt the number of warmup packets here so that it is the number of
%packets of the UOI we will see when the user with highest lambda has sent
%WARMUP packets on the channel
WARMUP = WARMUP/max(lambda) * lambda(1);


%WARMUP = 300; %number of warmup packets to pass transient phase
%NPKTS = 20; %number of packets to simulate

UOI = 1; %node number of UOI (typically 1)

%define events
QARR = 1; %packet arrives at queue
CHARR = 2; %packet leaves queue, arrives at channel
CHDEP = 3; %packet leaves channel

%define states
IDLE = 0; %channel is idle, no packets whatsoever
SEEK = 1; %an interferer packet was seen on channel, if this overlaps with 
%a later packet of the UOI we have to take it into account. Note this is
%also possible over several stages (ie, interferer packet overlapping with
%other interferer packets that finally overlap with the UOI packet)
RX = 3; %a UOI packet is being received



%initialize event Scheduler
evSched.currentTime = -1; %current time
evSched.firingTime = 0; %time of the event in process
evSched.evList = []; % This is the event list, note that it is a [n x 3] vector.
		      % The first column corresponds to the firing time
		      % The second column is the event type
              % 1 arrival of packet in the queue
              % 2 departure of packet of queue / arrival on the channel
              % 3 departure from the channel
              % The third column indicates the node number, 1 = UOI
evSched.evListLength = 0; % And a variable corresponding to the event list size (i.e number of rows)

%simulation state variables
sim.UOIPktsSent = 0; %number of UOI packets seen on the channel
sim.start = false; %flag to indicate whether we are still in warmup or started sim already
sim.forced_start = false; %force start if there are no gaps due to constantly utilized channel
sim.state = IDLE; %state of the sim;
sim.tentStart = 0; %tentative start time, start time induced by interfering packet
%will become a real start time if a UOI packet arrives before all
%interfering packets left the channel
sim.activeIFs = 0; %the number of interfering packets currently on the channel
sim.packets_since_tent = []; %store packets since last tentative start

sim.packetQueue = zeros(1,NN); %current length of the queue for each node
sim.firstLeave = zeros(1,NN); %first possible leave time for new packet
sim.allStartTimes = []; %starting times of simulations WARMUP + SIM
sim.allStopTimes = []; %corresponding ending times WARMUP + SIM
stat.startTimes = []; %same but only for the time when we are not in warmup
stat.stopTimes = []; %dito
debug.UOIstartTimes = []; %the times when an UOI packet arrives on the channel once WARMUP is over
stat.UOIPktsSimulated = 0; %the number of UOI packets simulated so far
stat.packets = []; %packet starting times plus node numbers

%schedule arrival of first packet for every node
for i=1:NN
  evSched = addEvent(getNextArrival(lambda(min(i,2))),QARR,i,evSched);
end

%run the simulation
while(true)
  %get next event
  evSched.firingTime = evSched.evList(1,1);
  evType             = evSched.evList(1,2);
  node               = evSched.evList(1,3);

  % Remove it from the event list
  evSched = delEvent(evSched);
    
  switch evType
   case QARR,
    %schedule the departure, arrival on channel of the packet
    if(sim.packetQueue(node) == 0)
      sim.firstLeave(node) = ...
          max(evSched.firingTime,sim.firstLeave(node));
    end
    %calculate random backoff
    bo_s = getBackoff(macMinBE,aUnitBackoffPeriod,sec_per_symbol);
    %schedule the arrival of the packet on the channel
    evSched = addEvent(sim.firstLeave(node)+bo_s,CHARR,node,evSched);
    %when is the earliest possible, next packet can be sent
    sim.firstLeave(node) = ...
        sim.firstLeave(node)+bo_s+packet_len+ack_gap;

    %increment size of queue
    sim.packetQueue(node) = sim.packetQueue(node) + 1;

    %schedule next arrival
    evSched = ...
        addEvent(evSched.firingTime+getNextArrival(lambda(min(node,2))), ...
                 QARR,node,evSched);
            
   case CHARR,
    %delete it from the packet queue
    sim.packetQueue(node) = sim.packetQueue(node) - 1;
    %schedule it's departure from the channel
    evSched = addEvent(evSched.firingTime+packet_len,CHDEP,node,evSched);
    if(node == UOI)%check whether WARMUP over
      if(sim.UOIPktsSent > WARMUP)
        sim.start = true;
      end
      sim.UOIPktsSent = sim.UOIPktsSent + 1;
      %fprintf('tarr=%.5f, tdep=%.5f, q=%d\n',evSched.firingTime,evSched.firingTime+packet_len,sim.packetQueue(node));
    end
    %register the packet
    stat.packets = [stat.packets; evSched.firingTime,node];

% $$$     %start registering packets
% $$$     if(sim.start)
% $$$       if(isempty(stat.packets))%fill in the packets since the last 
% $$$                                %tentative start wich now will become the start of our overall sim
% $$$         stat.packets = [stat.packets; sim.packets_since_tent]; 
% $$$       end
% $$$       stat.packets = [stat.packets; evSched.firingTime, node];
% $$$     end
            
    %act depending on current state
    switch sim.state
     case IDLE,
      if(node == UOI)%IDLE + UOI arrival -> start sim, go to RX
        sim.allStartTimes = [sim.allStartTimes evSched.firingTime];
        if(sim.start) %if warmup over we need to keep track of how many UOI
                      %packets we simulated, plus fill the
                      %start/stopTimes arrays
          stat.UOIPktsSimulated = stat.UOIPktsSimulated + 1;
          debug.UOIstartTimes = [debug.UOIstartTimes evSched.firingTime];
          stat.startTimes = [stat.startTimes evSched.firingTime];
        end
        sim.state = RX;
      else%IDLE + IF arrival -> might have to start here, go to SEEK
        sim.tentStart = evSched.firingTime;
        sim.activeIFs = sim.activeIFs + 1;
        sim.state = SEEK;
        sim.packets_since_tent = [evSched.firingTime, node];
      end
     case SEEK,
      if(node == UOI)%SEEK + UOI arrival -> start sim (unless already running), go to RX
        if(~isempty(sim.allStopTimes) && sim.allStopTimes(end) == sim.tentStart)
          sim.allStopTimes = sim.allStopTimes(1:end-1);
          if((sim.start && stat.UOIPktsSimulated > 0) || ...
             (sim.forced_start &&stat.UOIPktsSimulated == 0))
            
            %if warmup over we need to keep track of how many UOI
            %packets we simulated, plus fill the
            %start/stopTimes arrays
            stat.UOIPktsSimulated = stat.UOIPktsSimulated + 1;
            debug.UOIstartTimes = [debug.UOIstartTimes evSched.firingTime];
            if(stat.UOIPktsSimulated ~= 0)
              stat.stopTimes = stat.stopTimes(1:end-1); 
            end
          end
          %make sure we dont look for a gap forever (in the case
          %we have constantly something on the channel)
          if(sim.UOIPktsSent > 2*WARMUP)
            sim.forced_start = true; %force start at the end of this packet
          end
        else
          sim.allStartTimes = [sim.allStartTimes sim.tentStart];
          if(sim.start)
            %if warmup over we need to keep track of how many UOI
            %packets we simulated, plus fill the
            %start/stopTimes arrays
            stat.UOIPktsSimulated = stat.UOIPktsSimulated + 1;
            debug.UOIstartTimes = [debug.UOIstartTimes evSched.firingTime];
            stat.startTimes = [stat.startTimes sim.tentStart];
          end
        end
        sim.state = RX;
      else%SEEK/RX + IF arrival -> active IFs ++
        sim.activeIFs = sim.activeIFs + 1;
        sim.packets_since_tent = [sim.packets_since_tent; evSched.firingTime, node];
      end
     case RX,%
      if(node == UOI)
        fprintf('Bug: arrival while receiving!\n');
      else%SEEK/RX + IF arrival -> active IFs ++
        sim.activeIFs = sim.activeIFs + 1; 
      end
     otherwise
      fprintf('Bug: this type of state does not exist!\n');
    end
            
   case CHDEP,
    %act depeding on current state
    switch sim.state
     case IDLE,
      fprintf('Bug: departure while idle!\n');
     case SEEK,
      if(node == UOI)
        fprintf('Bug: UOI departure while seeking!\n');
      else%SEEK + IF departure -> active IFs --, go to idle if no more IFs active
        sim.activeIFs = sim.activeIFs - 1;
        if(sim.activeIFs == 0)
          sim.state = IDLE;
        end
      end
     case RX,
      if(node == UOI)%RX + UOI departure -> register stop time, 0 active IFs, goto IDLE
        if(sim.activeIFs == 0)
          sim.state = IDLE;
        else%otherwise it could be that we have to go on simulating
          sim.tentStart = evSched.firingTime;
          sim.state = SEEK;
        end
        sim.allStopTimes = [sim.allStopTimes evSched.firingTime];
        if(sim.start && stat.UOIPktsSimulated)
          %if warmup over we need to keep track of how many UOI
          %packets we simulated, plus fill the
          %start/stopTimes arrays
          stat.stopTimes = [stat.stopTimes evSched.firingTime]; 
        end
        if(stat.UOIPktsSimulated == NPKTS)%check whether we are done
          break;
        end
                        
        if(sim.forced_start && stat.UOIPktsSimulated == 0)
          stat.startTimes = [stat.startTimes evSched.firingTime];
        end
      else%RX + IF departure -> decrease active IFs
        sim.activeIFs = sim.activeIFs - 1;
      end
     otherwise
      fprintf('Bug: this type of state does not exist!\n');
    end
            
   otherwise
    fprintf('Bug: this type of event does not exist!\n');
  end
end

%only keep the packets that are useful ie, that fall into a start-stop
%period
%ind_useful_pkts = [];
%first get those who started within one packet length from first start
temp = stat.packets(:,1)';
if(sim.forced_start)
  temp(temp<=stat.startTimes(1)-packet_len)=0;
else
  temp(temp<=stat.startTimes(1)-packet_len-templ_len)=0;
end
temp(temp>=stat.startTimes(1))=0;
ind_useful_pkts = find(temp);
for i=1:length(stat.startTimes)
  temp = stat.packets(:,1)';
  temp(temp<stat.startTimes(i)-templ_len)=0;
  temp(temp>stat.stopTimes(i))=0;
  %     find(temp)
  ind_useful_pkts = [ind_useful_pkts find(temp)];
end
ind_useful_pkts = unique(sort(ind_useful_pkts));
stat.packets = stat.packets(ind_useful_pkts,:);

if(sim.forced_start)
  stat.startTimes(1) = stat.startTimes(1) + templ_len;
end
stat.startTimes = stat.startTimes - templ_len;

if(PLOT_DEBUG)
  figure
  stem(stat.startTimes,ones(1,length(stat.startTimes)),'r')
  hold on
  stem(stat.stopTimes,ones(1,length(stat.stopTimes)),'b')
  stem(debug.UOIstartTimes,ones(1,length(debug.UOIstartTimes)),'gx')
  stem(stat.packets(:,1),min(1,stat.packets(:,2)/2),'k.')
end

%effective packets per seconds
sim_time = stat.stopTimes(end)-stat.startTimes(1);
eff_pkts_per_second = NPKTS/sim_time;
theoretical_rate_Mbps = lambda(1)*PACKET_LENGTH/1e06;
eff_rate_Mbps = NPKTS*PACKET_LENGTH/sim_time/1e06;

fprintf('Duration of the simulation = %.4f [s]\n',sim_time);
fprintf('Packets/sec = %.2f, theo. rate = %.2f [Mbps]\n', ...
        eff_pkts_per_second,theoretical_rate_Mbps);
fprintf('Eff. rate = %.2f [Mbps]\n',eff_rate_Mbps);

return;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -