{
}

{
	Program for use with lwdaq library. (C) 2009 Kevan Hashemi, 
	hashemi@opensourceinstruments.com, Open Source Instruments
	
	This program is free software; you can redistribute it and/or modify it
	under the terms of the GNU General Public License as published by the
	Free Software Foundation; either version 2 of the License, or (at your
	option) any later version.
	
	This program is distributed in the hope that it will be useful, but
	WITHOUT ANY WARRANTY; without even the implied warranty of
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	See the GNU
	General Public License for more details.
	
	You should have received a copy of the GNU General Public License along
	with this program; if not, write to the Free Software Foundation, Inc.,
	59 Temple Place - Suite 330, Boston, MA	02111-1307, USA.
}
program p;

{
	This program simulates all n collision cycles for n subcutaneous transmitters 
	sharing the same receiver. The simulations provide the results shown in the
	Collisions section of our Subcutaneous Transmitter report.
}

uses
	utils;
	
const
	num_periods=1050000;
	scatter_extent=16;
	scatter_quantum=1/64;
	nominal_period=64*1000/32.768;{us}
	ppm_spread=10;
	message_time=7;{us}
	interval_length=1000000;{us}
	
type
	message_type=record
		timestamp:cardinal;
		id:cardinal;
	end;
	message_list(n:integer)=array [1..n] of message_type;
	period_list(m:integer)=array [1..m] of real;
	counter_list(m:integer)=array [1..m] of integer;
	
var
	num_xmitters:integer;

	mlp:^message_list;
	plp:^period_list;
	clp:^counter_list;
	
	m,n,p:integer;
	swapped:boolean;
	interval_start,interval_num:integer;
	
	f:text;
	
procedure swap(a,b:integer);
var m_saved:message_type;
begin
	m_saved:=mlp^[a];
	mlp^[a]:=mlp^[b];
	mlp^[b]:=m_saved;
end;

function greater(a,b:integer):boolean;
begin
	greater:=(mlp^[a].timestamp>mlp^[b].timestamp);
end;

begin
	write('num_xmitters? ');
	readln(num_xmitters);
	if num_xmitters<1 then exit;
	
	new(mlp,num_xmitters*num_periods);
	writeln('allocated ',sizeof(mlp^),' bytes for message list.');
	
	new(plp,num_xmitters);
	for m:=1 to num_xmitters do begin
		plp^[m]:=nominal_period*(1+(random_0_to_1-0.5)*2*ppm_spread/1000000);
	end;
	writeln('periods 1 through ',num_xmitters:1,':');
	for m:=1 to num_xmitters do begin
		writeln(plp^[m]:1:3);
	end;
	
	writeln('generating ',num_xmitters*num_periods:1,' messages...');
	n:=1;
	for p:=1 to num_periods do begin
		for m:=1 to num_xmitters do begin
			mlp^[n].timestamp:=round(plp^[m]
				*(p + round(scatter_extent*random_0_to_1-0.5)*scatter_quantum));
			mlp^[n].id:=m;
			inc(n);
		end;
	end;
		
	writeln('sorting messages in order of timestamp...');
	quick_sort(1,num_xmitters*num_periods-1,swap,greater);

	writeln('eliminating messages that collide...');	
	for n:=1 to num_xmitters*num_periods-1 do begin
		if mlp^[n+1].timestamp-mlp^[n].timestamp<=message_time then begin
			mlp^[n].id:=0;
			mlp^[n+1].id:=0;
		end;
	end;
	
	new(clp,num_xmitters);
	
	writeln('reception with time...');
	n:=1;
	interval_num:=1;
	rewrite(f,'data.txt');
	write(f,' time ');
	for m:=1 to num_xmitters do begin
		clp^[m]:=0;
		write(f,'No',m:1,' ');
	end;
	writeln(f);
	while n<=num_xmitters*num_periods do begin
		if mlp^[n].timestamp0 then inc(clp^[mlp^[n].id]);
		end else begin
			write(f,interval_num*interval_length/1000000:10:2,' ');
			for m:=1 to num_xmitters do 
				write(f,100*clp^[m]*nominal_period/interval_length:4:1,' ');
			writeln(f);
			inc(interval_num);
			for m:=1 to num_xmitters do clp^[m]:=0;
		end;
		inc(n);
	end;
	close(f);
	
end.