





%------------------------------------------------------------
%function [S_achieved] = backoff_expo( M, T, N, L, CWmin, CWmax, p]
%
% 
%
% M:  number of stations
% N = number of packets for each station
% L:  packet length
% 
% 
function S_achieved = backoff_expo ( M, T, N, L, CWmin, CWmax, p)

% Labeling the channel actual usage 
%lab[i] =  0, idle;
%           1,sender 1 using 
%           2, sender 2 using
%           3, collision
%           
% channel sensing and collision avoidance, backoff

%Sender's plan
% plan[i]  =0 , idle
%          =1,  send
%          =2 backoff;
Wait = L/2;
Interval = round(T/N) ;


S_begin_wait = zeros ( M, 1);
for i = 1:M
    S_begin_wait(i) = round(Wait*rand)+1;
end
%S2_begin_wait = round(Wait*rand);
%initialize
Lab = zeros (1,T);
S_plan = zeros (M,T);
%S2_plan = zeros (1,T);
S_arrive = zeros (M,T);
%S2_arrive = zeros (1,T);

%packet_arrive should be initialzied and fix:
for i= 1:M
for j= S_begin_wait(i): Interval : T
            S_arrive(i,j) = 1;
end
end
        

S_last_CW = 1:M;
S_last_CW(1:M) = -1;

S_backoff = 1:M;
S_backoff(1:M) = -1;

% back_off counter
% -1 means not set
% 0 the time to send is due
% 1-9 back off 

%arriving queue should be defined
S_queue = zeros( 1, M);
S_sent = zeros( 1, M);
S_arranged = zeros( 1, M);
S_achieved(1:M)= 0;
S_success = 1:M ;
S_success(1:M) = false;
S_flag = 1:M ;
S_flag(1:M) = false; % flag signalling the collision
%
% while loop this is a run in time-scale

for j=1:T    
   %-------------channel use judgemnt--------------------- 
    
   if ( Lab(j) == 0 )     
       if ( sum(S_plan(1:M,j)) == 1 )
            for i=1:M
                if S_plan(i,j) == 1
                    Lab(j:j+L-1) = i;
                    if ( rand > p(i) )
                            S_success(i) = true   ;
                    else %packet loss
                            S_success(i) = false ;
                    end
                end
            end
       elseif ( sum(S_plan(1:M,j)) > 1 )
            Lab(j:j+L-1) = -1;
            for i=1:M
                if S_plan(i,j) == 1
                    S_flag(i) = true;
                    S_success(i) = false;
                end
            end
       end
            
   end 
   
   %-----------Sender Handling------------------
   % new packet arrival
   for i = 1:M
         
   if ( S_arrive(i,j) == 1)
       S_queue(i) = S_queue(i) + 1 ;
       if ( S_arranged(i) == S_achieved(i)  && S_backoff(i) == -1)
           % need arrange new backoff for transmission
           %     S1_backoff = round(rand * CWfix) + 1;
           if  (S_last_CW(i) == -1 )
               S_backoff(i) = round( rand*CWmin) + 1;
               S_last_CW(i) = CWmin;
           end
       end
   end
   
   %channel sensing
   
       % backoff is due
       if ( S_backoff(i) == 0 )
           S_plan(i,j+1:j+L)= 1;
           S_arranged(i) = S_achieved(i) + 1;
           S_backoff(i) = -1;
       end
       % decrement backoff couneter when channel is idle
       if ( Lab(j) == 0  && S_backoff(i) > 0)
           % Sending 1 is in backoff procedure
           S_backoff(i) = S_backoff(i) - 1;
       end
              
       if ( Lab(j) == i || ( Lab(j) == -1 && S_flag(i) == true)  )
           S_sent(i)  = S_sent(i) + 1;
       end
       % if packet transmisison is finished, we judge the packet succeed or
       % fail, and get new backoff
       if (S_sent(i) == L)
           if ( S_success(i) == true )
               S_achieved(i) = S_achieved(i) + 1 ;
               S_last_CW(i) = -1; % as show that contention window should be reset to minimum
           end
           if ( S_queue(i) > S_achieved(i) ) % need arrange new backoff for transmission
              % S1_backoff = round(rand *CWfix) + 1; 
              if ( S_last_CW(i) == -1)
                  S_backoff(i) = round( rand*CWmin) + 1;
                  S_last_CW(i) = CWmin;
              elseif ( S_last_CW(i) == CWmax)
                  S_backoff(i) = round( rand*CWmax) + 1;
              else
                  S_backoff(i) = round( rand*2*S_last_CW(i)) + 1;
                  S_last_CW(i) = 2*S_last_CW(i);
              end
           end
           S_sent(i) = 0;
           S_flag(i) = false;
       end
       
       
   end
    
   
end
       
  




    