<?xml version='1.0' encoding='utf-8'?><!DOCTYPE nta PUBLIC '-//Uppaal Team//DTD Flat System 1.1//EN' 'http://www.it.uu.se/research/group/darts/uppaal/flat-1_1.dtd'><nta><declaration>//Insert declarations of global clocks, variables, constants and channels.

const int MASTER = 1;
const int SLAVE  = 0;
const int CLOCK_LENGTH = 17;	// Length of clock in bits
const int N_LENGTH = 5; 	// Length of N in bits
const int NR_OF_DEV = 2;
const int NR_FREQ = 79;
const int BD_ADDR_SIZE = 28;
const int CLOCK_PERIOD = 625;//all clock periods times two to keep them integers
const int UNCERTAINTY_DELAY = 10;

const int[0,1] GIAC_LAP [24] = {1,1,0,0,1,1,0,0,1,1,0,1,0,0,0,1,0,1,1,1,1,0,0,1};	// 0x9E8B33
const int[0,1] DCI[4] = {0,0,0,0};

const int FHS = 1;
const int ID = 0;

urgent broadcast chan ether[NR_FREQ][2];
urgent broadcast chan urg;

clock hwclocks[NR_OF_DEV];

int[0,1] CLKNs[NR_OF_DEV] [CLOCK_LENGTH] = {{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}};

void increment(int[0,1] &amp; inputClock[CLOCK_LENGTH])
{
	for(i : int[0,CLOCK_LENGTH-1])
	{
		if (inputClock[i])
			inputClock[i]:=0;
		else
		{	inputClock[i]:=1;
			return;
		}
	}
}
</declaration><template><name x="5" y="5">Device</name><parameter>const int BD_ADDR, int[0,1] &amp;CLKN[CLOCK_LENGTH], clock &amp; hwc ,const bool DoInquiry</parameter><declaration>clock hwclock;

// A will be called A_VAR, since just A does not seem to compile in the latest version of UPPAAL

int[0,1] N[N_LENGTH] = {0,0,0,0,0};		// Number of FHS packets transmitted in response to the inquiry (p94)
const int[0,1] B_TrainOffset[5] = {0,0,0,1,0};	// 8:  B-train
const int[0,1] A_TrainOffset[5] = {0,0,0,1,1};	// 24: A-train


/* -------------- Handling N -------------- */
void incrementN()
{
	for(i : int[0,N_LENGTH-1])
	{
		if (N[i])
			N[i]=0;
		else
		{	N[i]=1;
			return;
		}
	}
}

// Overwrite of first param, since array cannot be returned
// Every operation has a specific function, since generic functions cannot be constructed, due to the fact that variable array size cannot be used as function parameters

/* -------------- Xir -------------- */
// Calculate the Xir value of CLKN12-16 and N (addition modulo 32) and set the bitstream to this value
void calculateXir(int[0,1] &amp;bitStream[5], int[0,1] CLKN[CLOCK_LENGTH], int[0,1] N[N_LENGTH])
{
	int[0, 1] rem = 0;
	for(i : int[0, N_LENGTH-1])
	{	
		int[0, 3] sum = CLKN[i+12] + N[i] + rem;
		rem = sum / 2;
		bitStream[i] = sum % 2;
	}
}

/* -------------- Xi -------------- */
// Calculate the Xi value of various bits of CLKN and set the bitstream to this value
void calculateXi(int[0,1] &amp; bitStream[5], int[0,1] CLKN[CLOCK_LENGTH])
{
	// Variable declarations
	int[0,1] Koffset[5];

	// bitstream = CLKN4-2,0 - CLKN 16-12 mod 16 (EQ6 page 93)
	int[0, 1] rem = 0;
	for(i : int[0, 3])
	{
		int[-2, 1] sub;
		if(i == 0)
			sub = CLKN[0] - CLKN[12];
		else
			sub = CLKN[i+1] - CLKN[i+12] - rem;
		if(sub &lt; 0)
			rem = 1;
		else
			rem = 0;
		bitStream[i] = (sub + 2) % 2;	// Plus 2 to make sure the result will be positive
	}
	
	// bitstream = bitstream + CLKN16-12 mod 32 (EQ6 page 93)
	rem = 0;
	for(i : int[0, 4])
	{
		int[0, 3] sum = bitStream[i] + CLKN[i+12] + rem;
		rem = sum / 2;
		bitStream[i] = sum % 2;
	}

	// bitstream = bitstream + Koffset mod 32 (EQ6 page 93)
	// Koffset is A-train if CLKN4 = 1, B-train otherwise
	rem = 0;
	for(i : int[0, 4])
	{
		int[0, 3] sum;
		if(CLKN[4])
			sum = bitStream[i] + A_TrainOffset[i] + rem;
		else
			sum = bitStream[i] + B_TrainOffset[i] + rem;
		
		rem = sum / 2;
		bitStream[i] = sum % 2;
	}
}


/* -------------- BOX 1 -------------- */
// Addition modulo 32 of bitstream0-4 and A23-27
void add1(int[0,1] &amp;bitstream[5], const int[0,1] A_VAR[28])
{
	int rem = 0;		
	for(i : int[0, 4])
	{
		int[0, 3] sum = bitstream[i] + A_VAR[i+23] + rem;
		rem = sum / 2;
		bitstream[i] = sum % 2;
	}
}

/* -------------- BOX 2 -------------- */
// Xor of  bitstream0-3 and A19-22
void xor(int[0,1] &amp;bitstream[5], const int[0,1] A_VAR[28])
{
	for(i : int[0, 3])
		bitstream[i] = bitstream[i] ^ A_VAR[19 + i];
}

/* -------------- BOX 3 -------------- */
// Butterfly operation using control signal P and inputs Zi1 and Zi2
void butterfly(const bool P, int[0,1] &amp;Zi1, int[0,1] &amp;Zi2)
{
	bool tmp = Zi1;
	if(P)	// Then switch bits
	{
		Zi1 = Zi2;
		Zi2 = tmp;
	}
}

// Permutation operation using the butterfly operation (XOR included).
// Inputs are: bitstream0-4, A8,6,4,2,0, A18-10 and Y1
void perm(int[0,1] &amp;bitstream[5], const int[0,1] A_VAR[28], const bool Y1)
{
	int[0,1] P[14];

	// -- Calculate control signals (P) --
	// P0-8 corresponds to D0-8 which are: A10-18
	for(i : int[0, 8])
		P[i] = A_VAR[i + 10];
	// Pi+9 corresponds to Ci XOR Y1 which are: (A0,2,4,6,8)i XOR Y1
	for(i : int[0,4])
		P[i+9] = A_VAR[i*2] ^ Y1;
		
	// -- Do butterfly operations --
	// See Page 87, Table 2.1
	butterfly(P[13], bitstream[1], bitstream[2]);
	butterfly(P[12], bitstream[0], bitstream[3]);
	butterfly(P[11], bitstream[1], bitstream[3]);
	butterfly(P[10], bitstream[2], bitstream[4]);
	butterfly(P[9], bitstream[0], bitstream[3]);
	butterfly(P[8], bitstream[1], bitstream[4]);
	butterfly(P[7], bitstream[3], bitstream[4]);
	butterfly(P[6], bitstream[0], bitstream[2]);
	butterfly(P[5], bitstream[1], bitstream[3]);
	butterfly(P[4], bitstream[0], bitstream[4]);
	butterfly(P[3], bitstream[3], bitstream[4]);
	butterfly(P[2], bitstream[1], bitstream[2]);
	butterfly(P[1], bitstream[2], bitstream[3]);
	butterfly(P[0], bitstream[0], bitstream[1]);
}

/* -------------- BOX 4 -------------- */
int[0, 31] boolBitstreamToInt(const int[0,1] bitstream[5])	// Cannot be of variable length, UPPAAL cannot handle arrays of variable length as parameter
{
	int[0, 31] result = 0;
	int[1, 32] bitAsInt = 1;	// Maximum of 32, because multiplication by 2 will be executed one time too many
	for(i : int[0,4])
	{
		result = result + (bitstream[i] * bitAsInt);
		bitAsInt = bitAsInt * 2;
	}
	return result;
}

// The input of this function should be A, E will be extracted from it (A1,3,5,...,13)
int[0, 127] boolEInInquiryPhaseToInt(const int[0,1] A_VAR[28])	// Cannot be of variable length, UPPAAL cannot handle arrays of variable length as parameter
{
	int[0, 127] result = 0;
	int[1, 128] bitAsInt = 1;	// Maximum of 128, because multiplication by 2 will be executed one time too many
	for(i : int[0,6])
	{
		result = result + (A_VAR[(2 * i) + 1] * bitAsInt);
		bitAsInt = bitAsInt * 2;
	}
	return result;
}

// Addition modulo 79 of bitstream0-4, A13,11,9,...1 and Y2 (Input F is 0 in inquiry scan, inquiry response and inquiry phase)
int [0,78] add2(const int[0,1] bitstream[5], const int[0,1] A_VAR[28], const bool Y2D32)	// Last input Y2D32 is Y2 divided by 32
{
	int[0, 31] bitStreamInt = boolBitstreamToInt(bitstream);
	int[0, 127] EInt = boolEInInquiryPhaseToInt(A_VAR);
	return (bitStreamInt + EInt + (32 * Y2D32)) % 79;
}

/* -------------- REGISTER BANK -------------- */
// Returns the actual frequency number that can be found in the frequency register bank, using the given index
int [0,78] hopFreqRegisterBank(const int [0,78] index)
{
	int[0,78] freq;
	if(index &lt; 40)
		freq = index * 2;		// Even frequencies-&gt; at most 78
	else
		freq = (index - 40) * 2 + 1;	// Odd frequencies-&gt; at most 
	return freq;
}

/* -------------- FREQUENCY CALCULATIONS -------------- */
int calcInquiryPhaseFreq(int[0,1] &amp;bitStream[5], bool Y1, bool Y2D32)	// Last parameter is Y2 divided by 32
{
	// Vars
	int[0,1] A_VAR [28];
	int freqIndex;

	// Init address value (A0-23 = GIAC_LAP and A24-27 = DCI)	
	for(i : int[0,23])
		A_VAR[i] = GIAC_LAP[i];
	for(i : int[0,3])
		A_VAR[i+24] = DCI[i];

	// Selection box calculation
	add1(bitStream, A_VAR);			// Add box 1
	xor(bitStream, A_VAR);			// Xor box
	perm(bitStream, A_VAR, Y1);			// Perm box
	freqIndex = add2(bitStream, A_VAR, Y2D32);	// Add box 2
	return hopFreqRegisterBank(freqIndex);
}

int calcInquiryScanFreq()
{
	// Vars	
	int[0,1] bitStream[5] = {0,0,0,0,0};

	// Xir calculation
	calculateXir(bitStream, CLKN, N);
	return calcInquiryPhaseFreq(bitStream, 0, 0);
	
}

int calcInquiryFreq()
{
	// Vars	
	int[0,1] bitStream[5] = {0,0,0,0,0};

	// Xi calculation
	calculateXi(bitStream, CLKN);
	return calcInquiryPhaseFreq(bitStream, CLKN[1], CLKN[1]);
	
}

/* The doIncrement is true if the frequency of the next slot should be calculated instead of the current one (only used in the uncertainty delay calculation)*/
int calcInquiryResponseFreq(const bool doIncrement)
{	

	int[0,1] clockCopy[CLOCK_LENGTH];
	
	// Vars	
	int[0,1] bitStream[5] = {0,0,0,0,0};

	for(i : int[0,CLOCK_LENGTH-1])
	{
		clockCopy[i] = CLKN[i];
	}

	if (doIncrement)
		increment(clockCopy);

	// Xir calculation
	calculateXir(bitStream, clockCopy, N);
	return calcInquiryPhaseFreq(bitStream, 1, 1);
	
}


bool clockIsMax()
{
	for(i : int[0,CLOCK_LENGTH-1])
	{
		if (!CLKN[i])
			return false;
	}
	return true;

}
</declaration><location id="id0" x="464" y="-16"></location><location id="id1" x="328" y="232"></location><location id="id2" x="-368" y="48"><name x="-424" y="16">WaitingToStart</name><label kind="invariant" x="-408" y="64">!clockIsMax()</label></location><location id="id3" x="-216" y="-136"></location><location id="id4" x="464" y="128"><name x="454" y="98">Finished</name></location><location id="id5" x="464" y="-136"><name x="454" y="-166">TX01</name><label kind="invariant" x="448" y="-152">hwc &lt;= CLOCK_PERIOD - UNCERTAINTY_DELAY</label></location><location id="id6" x="240" y="-136"><name x="230" y="-166">TX00</name></location><location id="id7" x="8" y="-136"><name x="-16" y="-171">TX00start</name></location><location id="id8" x="240" y="-16"><name x="216" y="-48">RX1_</name></location><location id="id9" x="136" y="232"><name x="104" y="200">DoneScanningWaitingToSend</name><label kind="invariant" x="48" y="240">hwclock &lt;= 2*CLOCK_PERIOD</label></location><location id="id10" x="-216" y="232"><name x="-226" y="202">Scan</name></location><location id="id11" x="-216" y="48"><name x="-256" y="32">Init</name><committed/></location><init ref="id2"/><transition><source ref="id0"/><target ref="id8"/><label kind="guard" x="336" y="-32">CLKN[1]==1</label><label kind="synchronisation" x="376" y="-16">urg!</label></transition><transition><source ref="id0"/><target ref="id4"/><label kind="synchronisation" x="404" y="41">ether[calcInquiryResponseFreq(1)][FHS]?</label></transition><transition><source ref="id1"/><target ref="id4"/><label kind="synchronisation" x="304" y="168">ether[calcInquiryResponseFreq(0)][FHS]!</label><label kind="assignment" x="348" y="188">incrementN()</label></transition><transition><source ref="id9"/><target ref="id1"/><label kind="guard" x="184" y="256">hwclock == 2* CLOCK_PERIOD</label></transition><transition><source ref="id2"/><target ref="id11"/></transition><transition><source ref="id3"/><target ref="id7"/><label kind="guard" x="-200" y="-160">CLKN[0]==0 &amp;&amp; CLKN[1]==0</label><label kind="synchronisation" x="-112" y="-128">urg!</label></transition><transition><source ref="id8"/><target ref="id4"/><label kind="synchronisation" x="112" y="32">ether[calcInquiryResponseFreq(0)][FHS]?</label></transition><transition><source ref="id8"/><target ref="id7"/><label kind="guard" x="72" y="-40">CLKN[1]==0</label><label kind="synchronisation" x="104" y="-16">urg!</label><nail x="8" y="-16"/></transition><transition><source ref="id5"/><target ref="id0"/><label kind="guard" x="448" y="-88">hwc &gt;= CLOCK_PERIOD - UNCERTAINTY_DELAY</label></transition><transition><source ref="id6"/><target ref="id5"/><label kind="guard" x="328" y="-160">CLKN[0]==1</label><label kind="synchronisation" x="256" y="-136">ether[calcInquiryFreq()][ID]!</label></transition><transition><source ref="id7"/><target ref="id6"/><label kind="guard" x="80" y="-160">CLKN[0]==0</label><label kind="synchronisation" x="32" y="-136">ether[calcInquiryFreq()][ID]!</label></transition><transition><source ref="id10"/><target ref="id9"/><label kind="synchronisation" x="-192" y="248">ether[calcInquiryScanFreq()][ID]?</label><label kind="assignment" x="-144" y="232">hwclock := 0</label></transition><transition><source ref="id11"/><target ref="id10"/><label kind="guard" x="-288" y="128">!DoInquiry</label></transition><transition><source ref="id11"/><target ref="id3"/><label kind="guard" x="-240" y="-56">DoInquiry</label></transition></template><template><name x="5" y="5">BluetoothClock</name><parameter>int[0,1] &amp; CLKN[CLOCK_LENGTH], clock &amp; time</parameter><declaration>

const int HALF_JITTER = 3;
const int DRIFT = 1;
const int CLK_MIN = DRIFT + CLOCK_PERIOD - HALF_JITTER;
const int CLK_MAX = DRIFT + CLOCK_PERIOD + HALF_JITTER;


void tickClock()
{
	increment(CLKN);
}

// For verification
bool clocksEqual(const int[0,1] C1[CLOCK_LENGTH], const int[0,1] C2[CLOCK_LENGTH])
{
	for(i : int[0,CLOCK_LENGTH-1])
	{
		if(C1[i] != C2[i])
			return false;
	}
	return true;
}



bool equals(const int[0,1] CLKN_COMP[CLOCK_LENGTH])
{
	return clocksEqual(CLKN, CLKN_COMP);
}



void copy(const int[0,1] source[CLOCK_LENGTH], int[0,1] &amp;target[CLOCK_LENGTH])
{
	for(i : int[0,CLOCK_LENGTH-1])
		target[i] = source[i];
}</declaration><location id="id12" x="176" y="144"><label kind="invariant" x="88" y="160">time&lt;=CLK_MAX</label></location><init ref="id12"/><transition><source ref="id12"/><target ref="id12"/><label kind="guard" x="200" y="48">time&gt;=CLK_MIN</label><label kind="assignment" x="216" y="96">time:=0,
tickClock()</label><nail x="256" y="128"/><nail x="192" y="64"/></transition></template><system>//Insert process assignments.
MasterBTClock := BluetoothClock(CLKNs[MASTER], hwclocks[MASTER]);
SlaveBTClock  := BluetoothClock(CLKNs[SLAVE], hwclocks[SLAVE]);
Master := Device(MASTER, CLKNs[MASTER], hwclocks[MASTER], true);
Slave := Device(SLAVE, CLKNs[SLAVE], hwclocks[SLAVE], false);

//Edit system definition.
system Master, Slave, MasterBTClock, SlaveBTClock;
</system></nta>