diff core/ClockSync.cpp @ 135:e77e2e712fbc ClockSync

To work with the ClockSync plugin
author Giulio Moro <giuliomoro@yahoo.it>
date Sat, 12 Sep 2015 20:05:55 +0100
parents
children 4e2dd3eb1d28
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/core/ClockSync.cpp	Sat Sep 12 20:05:55 2015 +0100
@@ -0,0 +1,250 @@
+#include "ClockSync.h"
+
+void ClockSync::setVirtualClock(VirtualClock &aVirtualClock){
+	virtualClock=&aVirtualClock;
+}
+void ClockSync::init(bool thisIsSlave, int aPort, VirtualClock &aVirtualClock){
+	setVirtualClock(aVirtualClock);
+	slave=thisIsSlave;
+	setPort(aPort);
+	//  isSlave() ? client.setServer("127.0.0.1") : client.setServer("127.0.0.1");
+	isSlave() ? client.setServer("192.168.7.1") : client.setServer("192.168.7.2");
+	bufferLength=kSyncMessageLength;
+	T1=-1;
+	T1p=-1;
+	T2=-1;
+	T2p=-1;
+	receiveLoopSleepUs=10;
+	receiveLoopTimeout=1e5;
+	movingAverage.setLength(201);
+	expectedClockSyncType=isSlave() ? kSync : kNone;
+}
+ClockSync::ClockSync(bool thisIsSlave, int aPort, VirtualClock &aVirtualClock){
+	init(thisIsSlave, aPort, aVirtualClock);
+}
+void* ClockSync::getBuffer(){
+	return buffer;
+}
+bool ClockSync::isSlave(){
+	return slave;
+}
+bool ClockSync::isMaster(){
+	return !slave;
+}
+int ClockSync::getType(){
+	return ((int*)buffer)[0];
+}
+myClock_t ClockSync::getTimestamp(){
+	return *((myClock_t*)((char*)buffer+sizeof(int)));
+}
+void ClockSync::setType(int clockSyncType){
+	((int*)buffer)[0]=clockSyncType;
+}
+void ClockSync::setTimestamp(myClock_t timestamp){
+	((myClock_t*)((char*)buffer+sizeof(int)))[0]=timestamp;
+}
+void ClockSync::print(){
+	 //printf("type: %d, timestamp: %lld\n",*((int*)buffer),*((myClock_t*)(((int*)buffer)+1)));
+}
+void ClockSync::setPort(int aPort){
+	if(aPort>0){
+		int inPort=isSlave() ? aPort : aPort+1;
+		int outPort=isSlave() ? aPort+1: aPort;
+		server.bindToPort(inPort);
+		client.setPort(outPort);
+		//printf("Receiving on port %d\n", inPort);
+		//printf("Sending to port %d\n", outPort);
+	}
+}
+/** 
+ * sends a clockSync without blocking, checks results and returns the timestamp
+ * immediately after the clockSync has been sent or -1 if there was an error or timeout expired.
+*/
+myClock_t ClockSync::send(){
+	//  print();
+	int ret;
+	ret=client.waitUntilReady(false, 0);
+	if(ret<=0){ //don't retry
+		return -1;
+	}
+	ret=client.send(buffer, bufferLength);
+	myClock_t timestamp=(myClock_t)virtualClock->getNow();
+	if(ret<0){
+	//if there was an error while sending, don't retry
+		return -1;
+	}
+	return timestamp; //get the accurate time *after* you sent the sync clockSync
+}
+/** 
+ * receives a clockSync without blocking, checks results and returns the timestamp
+ * immediately after the clockSync has been received, or -1 if there was an error 
+ * or 0 if timeout expired.
+*/
+myClock_t ClockSync::receive(){
+	int ret;
+	ret=server.waitUntilReady(true, 0);
+	if(ret<=0){ //don't retry
+		return 0;
+	}
+	ret=server.read(buffer, bufferLength, false);
+	myClock_t timestamp=(myClock_t)virtualClock->getNow();
+	if(timestamp==0){
+		//printf("The virtualClock period is <=0\n");
+		return -3;
+	}
+	if(ret==-1){
+		//if there was an error while receiving, don't retry
+		return -1;
+	}
+	if(ret!=bufferLength){
+		//printf("Received a clockSync of the wrong size: %d\n", ret);
+		return -2;
+	}
+	//  print();
+	return timestamp; //get the accurate time *after* you sent the sync clockSync
+}
+
+int ClockSync::masterSendSync(){
+	//let's send a sync clockSync!
+	//printf("Sending a sync clockSync\n");
+	setType(kSync);
+	setTimestamp(-1);//do not care about sending the timestamp, a more accurate one will be sent in the follow up
+	localTimestamp=send();
+	if(localTimestamp<0){
+		//printf("Could not send sync clockSync\n");
+		return -1; //error, don't retry, start over
+	}
+	//let's send a followUp
+	//printf("sent a sync clockSync\n");
+	setType(kFollowUp);
+	setTimestamp(localTimestamp);
+	if(localTimestamp<0){
+		//printf("Could not send followup clockSync\n");
+		return -2; //error, don't retry, start over
+	}
+	int ret=send();
+	if(ret<0){
+		//printf("Error while sending followup\n");
+		return -3;
+	}
+	//printf("sent a followUp clockSync\n");
+	expectedClockSyncType=kDelayReq;
+	return 1;
+}
+#ifdef USE_JUCE
+#define NOTGSHOULDSTOP 1
+#else
+extern bool gShouldStop;
+#define NOTGSHOULDSTOP (!gShouldStop)
+#endif /* USE_JUCE */
+int ClockSync::receiveLoop(){
+	int receiveLoopElapsed=0;
+	while( NOTGSHOULDSTOP && (isSlave() || (receiveLoopElapsed<receiveLoopTimeout))){ //when slave, does not timeout!
+		receiveLoopElapsed+=receiveLoopSleepUs;
+		usleep(receiveLoopSleepUs); //how often to check for new clockSyncs;
+		//   //printf("waiting for clockSyncs\n");
+		localTimestamp=receive();
+		if(localTimestamp<=0){
+			if(localTimestamp==0){
+				//  //printf("Socket not ready to be read: %lld\n", localTimestamp);
+			}
+			else if(localTimestamp==-1){
+				//printf("Error while receiving: %lld\n", localTimestamp);
+			}
+			else if(localTimestamp==-2){
+				//  //printf("Wrong size of the received clockSync: %lld\n", localTimestamp);
+			}
+			continue ; //keep waiting
+		}
+		clockSyncType=getType();
+		clockSyncTimestamp=getTimestamp();
+		if(clockSyncType!=expectedClockSyncType){
+			//printf("Wrong clockSync type: %d, expected: %d\n",clockSyncType, expectedClockSyncType);
+			return -2; //start over
+		}
+		//printf("Received clockSync type: %d, clockSyncTimestamp: %lld\n", clockSyncType, clockSyncTimestamp);
+		if(isSlave()==true){
+			int ret=slaveHandleMessage();
+			if(ret==1 && clockSyncType==kDelayResp){ //we are done, end of a cycle!
+				return 1;
+			} else if (ret!=1) {
+				return -1; //
+			} else {
+				continue;
+			}
+		}
+		if(isMaster()==true){ //this is master
+			int ret=masterHandleMessage();
+			if(ret==1 && clockSyncType==kDelayReq){ //we are done, end of a cycle!
+				return 1;
+			} else {
+				return -2; //we are done but something was wrong
+			}
+		}
+	}
+	//printf("Receive loop timeout\n");
+	return -1;
+}
+
+int ClockSync::slaveHandleMessage(){
+	switch(clockSyncType){
+		case kSync: //the clockSync timestamp is meaningless, the localTimestamp is when kSync was received
+			T1p=localTimestamp;
+			expectedClockSyncType=kFollowUp;
+			break;
+		case kFollowUp: //the clockSyncTimestamp is the time when kSync was sent, the localTimestamp is meaningless
+			T1=clockSyncTimestamp;
+			//send delayReq
+			setType(kDelayReq);
+			setTimestamp(-1);
+			T2=send();
+			if(T2<0){
+				//printf("Error while sending delayReq\n");
+				return -1;
+			}
+			expectedClockSyncType=kDelayResp;
+			break;
+		case kDelayResp: {//the clockSyncTimestamp is the instant when the master received the kDelayResp clockSync, the localTimestamp is meaningless
+			T2p=clockSyncTimestamp;
+			//TODO: evaluate things
+			double offset=(T1p-T1-T2p+T2)/2.0d;
+			printf("-----------OFFSET IS : %04.1f, average: %04.2f\n", offset, movingAverage.add(offset));
+			expectedClockSyncType=kSync; //end of the cycle, wait for next sync.
+			break;
+		}
+		default:
+			//printf("Unexpected message type\n"); // we should never get here
+			return -1;
+	}
+	return 1;
+}
+
+int ClockSync::masterHandleMessage(){
+	switch(clockSyncType){
+		case kDelayReq:
+			//TODO: do something with it
+			//send kDelayResp
+			setType(kDelayResp);
+			setTimestamp(localTimestamp);
+			send();
+			expectedClockSyncType=kNone;
+		break;
+	}
+}
+
+int ClockSync::sendReceiveLoop(){
+	if(isSlave()==true){
+		 //printf("Waiting for a sync clockSync\n");
+	} else { //if this is master
+		usleep(100000); //this times (roughly) how often sync clockSyncs are being sent.
+		int ret=masterSendSync();
+		if(ret<=0)
+			return -1;
+	}
+	int ret=receiveLoop();
+	if(ret<=0)
+		return -2;
+	return 1;
+}
+
+