Mercurial > hg > beaglert
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; +} + +