annotate 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
rev   line source
giuliomoro@135 1 #include "ClockSync.h"
giuliomoro@135 2
giuliomoro@135 3 void ClockSync::setVirtualClock(VirtualClock &aVirtualClock){
giuliomoro@135 4 virtualClock=&aVirtualClock;
giuliomoro@135 5 }
giuliomoro@135 6 void ClockSync::init(bool thisIsSlave, int aPort, VirtualClock &aVirtualClock){
giuliomoro@135 7 setVirtualClock(aVirtualClock);
giuliomoro@135 8 slave=thisIsSlave;
giuliomoro@135 9 setPort(aPort);
giuliomoro@135 10 // isSlave() ? client.setServer("127.0.0.1") : client.setServer("127.0.0.1");
giuliomoro@135 11 isSlave() ? client.setServer("192.168.7.1") : client.setServer("192.168.7.2");
giuliomoro@135 12 bufferLength=kSyncMessageLength;
giuliomoro@135 13 T1=-1;
giuliomoro@135 14 T1p=-1;
giuliomoro@135 15 T2=-1;
giuliomoro@135 16 T2p=-1;
giuliomoro@135 17 receiveLoopSleepUs=10;
giuliomoro@135 18 receiveLoopTimeout=1e5;
giuliomoro@135 19 movingAverage.setLength(201);
giuliomoro@135 20 expectedClockSyncType=isSlave() ? kSync : kNone;
giuliomoro@135 21 }
giuliomoro@135 22 ClockSync::ClockSync(bool thisIsSlave, int aPort, VirtualClock &aVirtualClock){
giuliomoro@135 23 init(thisIsSlave, aPort, aVirtualClock);
giuliomoro@135 24 }
giuliomoro@135 25 void* ClockSync::getBuffer(){
giuliomoro@135 26 return buffer;
giuliomoro@135 27 }
giuliomoro@135 28 bool ClockSync::isSlave(){
giuliomoro@135 29 return slave;
giuliomoro@135 30 }
giuliomoro@135 31 bool ClockSync::isMaster(){
giuliomoro@135 32 return !slave;
giuliomoro@135 33 }
giuliomoro@135 34 int ClockSync::getType(){
giuliomoro@135 35 return ((int*)buffer)[0];
giuliomoro@135 36 }
giuliomoro@135 37 myClock_t ClockSync::getTimestamp(){
giuliomoro@135 38 return *((myClock_t*)((char*)buffer+sizeof(int)));
giuliomoro@135 39 }
giuliomoro@135 40 void ClockSync::setType(int clockSyncType){
giuliomoro@135 41 ((int*)buffer)[0]=clockSyncType;
giuliomoro@135 42 }
giuliomoro@135 43 void ClockSync::setTimestamp(myClock_t timestamp){
giuliomoro@135 44 ((myClock_t*)((char*)buffer+sizeof(int)))[0]=timestamp;
giuliomoro@135 45 }
giuliomoro@135 46 void ClockSync::print(){
giuliomoro@135 47 //printf("type: %d, timestamp: %lld\n",*((int*)buffer),*((myClock_t*)(((int*)buffer)+1)));
giuliomoro@135 48 }
giuliomoro@135 49 void ClockSync::setPort(int aPort){
giuliomoro@135 50 if(aPort>0){
giuliomoro@135 51 int inPort=isSlave() ? aPort : aPort+1;
giuliomoro@135 52 int outPort=isSlave() ? aPort+1: aPort;
giuliomoro@135 53 server.bindToPort(inPort);
giuliomoro@135 54 client.setPort(outPort);
giuliomoro@135 55 //printf("Receiving on port %d\n", inPort);
giuliomoro@135 56 //printf("Sending to port %d\n", outPort);
giuliomoro@135 57 }
giuliomoro@135 58 }
giuliomoro@135 59 /**
giuliomoro@135 60 * sends a clockSync without blocking, checks results and returns the timestamp
giuliomoro@135 61 * immediately after the clockSync has been sent or -1 if there was an error or timeout expired.
giuliomoro@135 62 */
giuliomoro@135 63 myClock_t ClockSync::send(){
giuliomoro@135 64 // print();
giuliomoro@135 65 int ret;
giuliomoro@135 66 ret=client.waitUntilReady(false, 0);
giuliomoro@135 67 if(ret<=0){ //don't retry
giuliomoro@135 68 return -1;
giuliomoro@135 69 }
giuliomoro@135 70 ret=client.send(buffer, bufferLength);
giuliomoro@135 71 myClock_t timestamp=(myClock_t)virtualClock->getNow();
giuliomoro@135 72 if(ret<0){
giuliomoro@135 73 //if there was an error while sending, don't retry
giuliomoro@135 74 return -1;
giuliomoro@135 75 }
giuliomoro@135 76 return timestamp; //get the accurate time *after* you sent the sync clockSync
giuliomoro@135 77 }
giuliomoro@135 78 /**
giuliomoro@135 79 * receives a clockSync without blocking, checks results and returns the timestamp
giuliomoro@135 80 * immediately after the clockSync has been received, or -1 if there was an error
giuliomoro@135 81 * or 0 if timeout expired.
giuliomoro@135 82 */
giuliomoro@135 83 myClock_t ClockSync::receive(){
giuliomoro@135 84 int ret;
giuliomoro@135 85 ret=server.waitUntilReady(true, 0);
giuliomoro@135 86 if(ret<=0){ //don't retry
giuliomoro@135 87 return 0;
giuliomoro@135 88 }
giuliomoro@135 89 ret=server.read(buffer, bufferLength, false);
giuliomoro@135 90 myClock_t timestamp=(myClock_t)virtualClock->getNow();
giuliomoro@135 91 if(timestamp==0){
giuliomoro@135 92 //printf("The virtualClock period is <=0\n");
giuliomoro@135 93 return -3;
giuliomoro@135 94 }
giuliomoro@135 95 if(ret==-1){
giuliomoro@135 96 //if there was an error while receiving, don't retry
giuliomoro@135 97 return -1;
giuliomoro@135 98 }
giuliomoro@135 99 if(ret!=bufferLength){
giuliomoro@135 100 //printf("Received a clockSync of the wrong size: %d\n", ret);
giuliomoro@135 101 return -2;
giuliomoro@135 102 }
giuliomoro@135 103 // print();
giuliomoro@135 104 return timestamp; //get the accurate time *after* you sent the sync clockSync
giuliomoro@135 105 }
giuliomoro@135 106
giuliomoro@135 107 int ClockSync::masterSendSync(){
giuliomoro@135 108 //let's send a sync clockSync!
giuliomoro@135 109 //printf("Sending a sync clockSync\n");
giuliomoro@135 110 setType(kSync);
giuliomoro@135 111 setTimestamp(-1);//do not care about sending the timestamp, a more accurate one will be sent in the follow up
giuliomoro@135 112 localTimestamp=send();
giuliomoro@135 113 if(localTimestamp<0){
giuliomoro@135 114 //printf("Could not send sync clockSync\n");
giuliomoro@135 115 return -1; //error, don't retry, start over
giuliomoro@135 116 }
giuliomoro@135 117 //let's send a followUp
giuliomoro@135 118 //printf("sent a sync clockSync\n");
giuliomoro@135 119 setType(kFollowUp);
giuliomoro@135 120 setTimestamp(localTimestamp);
giuliomoro@135 121 if(localTimestamp<0){
giuliomoro@135 122 //printf("Could not send followup clockSync\n");
giuliomoro@135 123 return -2; //error, don't retry, start over
giuliomoro@135 124 }
giuliomoro@135 125 int ret=send();
giuliomoro@135 126 if(ret<0){
giuliomoro@135 127 //printf("Error while sending followup\n");
giuliomoro@135 128 return -3;
giuliomoro@135 129 }
giuliomoro@135 130 //printf("sent a followUp clockSync\n");
giuliomoro@135 131 expectedClockSyncType=kDelayReq;
giuliomoro@135 132 return 1;
giuliomoro@135 133 }
giuliomoro@135 134 #ifdef USE_JUCE
giuliomoro@135 135 #define NOTGSHOULDSTOP 1
giuliomoro@135 136 #else
giuliomoro@135 137 extern bool gShouldStop;
giuliomoro@135 138 #define NOTGSHOULDSTOP (!gShouldStop)
giuliomoro@135 139 #endif /* USE_JUCE */
giuliomoro@135 140 int ClockSync::receiveLoop(){
giuliomoro@135 141 int receiveLoopElapsed=0;
giuliomoro@135 142 while( NOTGSHOULDSTOP && (isSlave() || (receiveLoopElapsed<receiveLoopTimeout))){ //when slave, does not timeout!
giuliomoro@135 143 receiveLoopElapsed+=receiveLoopSleepUs;
giuliomoro@135 144 usleep(receiveLoopSleepUs); //how often to check for new clockSyncs;
giuliomoro@135 145 // //printf("waiting for clockSyncs\n");
giuliomoro@135 146 localTimestamp=receive();
giuliomoro@135 147 if(localTimestamp<=0){
giuliomoro@135 148 if(localTimestamp==0){
giuliomoro@135 149 // //printf("Socket not ready to be read: %lld\n", localTimestamp);
giuliomoro@135 150 }
giuliomoro@135 151 else if(localTimestamp==-1){
giuliomoro@135 152 //printf("Error while receiving: %lld\n", localTimestamp);
giuliomoro@135 153 }
giuliomoro@135 154 else if(localTimestamp==-2){
giuliomoro@135 155 // //printf("Wrong size of the received clockSync: %lld\n", localTimestamp);
giuliomoro@135 156 }
giuliomoro@135 157 continue ; //keep waiting
giuliomoro@135 158 }
giuliomoro@135 159 clockSyncType=getType();
giuliomoro@135 160 clockSyncTimestamp=getTimestamp();
giuliomoro@135 161 if(clockSyncType!=expectedClockSyncType){
giuliomoro@135 162 //printf("Wrong clockSync type: %d, expected: %d\n",clockSyncType, expectedClockSyncType);
giuliomoro@135 163 return -2; //start over
giuliomoro@135 164 }
giuliomoro@135 165 //printf("Received clockSync type: %d, clockSyncTimestamp: %lld\n", clockSyncType, clockSyncTimestamp);
giuliomoro@135 166 if(isSlave()==true){
giuliomoro@135 167 int ret=slaveHandleMessage();
giuliomoro@135 168 if(ret==1 && clockSyncType==kDelayResp){ //we are done, end of a cycle!
giuliomoro@135 169 return 1;
giuliomoro@135 170 } else if (ret!=1) {
giuliomoro@135 171 return -1; //
giuliomoro@135 172 } else {
giuliomoro@135 173 continue;
giuliomoro@135 174 }
giuliomoro@135 175 }
giuliomoro@135 176 if(isMaster()==true){ //this is master
giuliomoro@135 177 int ret=masterHandleMessage();
giuliomoro@135 178 if(ret==1 && clockSyncType==kDelayReq){ //we are done, end of a cycle!
giuliomoro@135 179 return 1;
giuliomoro@135 180 } else {
giuliomoro@135 181 return -2; //we are done but something was wrong
giuliomoro@135 182 }
giuliomoro@135 183 }
giuliomoro@135 184 }
giuliomoro@135 185 //printf("Receive loop timeout\n");
giuliomoro@135 186 return -1;
giuliomoro@135 187 }
giuliomoro@135 188
giuliomoro@135 189 int ClockSync::slaveHandleMessage(){
giuliomoro@135 190 switch(clockSyncType){
giuliomoro@135 191 case kSync: //the clockSync timestamp is meaningless, the localTimestamp is when kSync was received
giuliomoro@135 192 T1p=localTimestamp;
giuliomoro@135 193 expectedClockSyncType=kFollowUp;
giuliomoro@135 194 break;
giuliomoro@135 195 case kFollowUp: //the clockSyncTimestamp is the time when kSync was sent, the localTimestamp is meaningless
giuliomoro@135 196 T1=clockSyncTimestamp;
giuliomoro@135 197 //send delayReq
giuliomoro@135 198 setType(kDelayReq);
giuliomoro@135 199 setTimestamp(-1);
giuliomoro@135 200 T2=send();
giuliomoro@135 201 if(T2<0){
giuliomoro@135 202 //printf("Error while sending delayReq\n");
giuliomoro@135 203 return -1;
giuliomoro@135 204 }
giuliomoro@135 205 expectedClockSyncType=kDelayResp;
giuliomoro@135 206 break;
giuliomoro@135 207 case kDelayResp: {//the clockSyncTimestamp is the instant when the master received the kDelayResp clockSync, the localTimestamp is meaningless
giuliomoro@135 208 T2p=clockSyncTimestamp;
giuliomoro@135 209 //TODO: evaluate things
giuliomoro@135 210 double offset=(T1p-T1-T2p+T2)/2.0d;
giuliomoro@135 211 printf("-----------OFFSET IS : %04.1f, average: %04.2f\n", offset, movingAverage.add(offset));
giuliomoro@135 212 expectedClockSyncType=kSync; //end of the cycle, wait for next sync.
giuliomoro@135 213 break;
giuliomoro@135 214 }
giuliomoro@135 215 default:
giuliomoro@135 216 //printf("Unexpected message type\n"); // we should never get here
giuliomoro@135 217 return -1;
giuliomoro@135 218 }
giuliomoro@135 219 return 1;
giuliomoro@135 220 }
giuliomoro@135 221
giuliomoro@135 222 int ClockSync::masterHandleMessage(){
giuliomoro@135 223 switch(clockSyncType){
giuliomoro@135 224 case kDelayReq:
giuliomoro@135 225 //TODO: do something with it
giuliomoro@135 226 //send kDelayResp
giuliomoro@135 227 setType(kDelayResp);
giuliomoro@135 228 setTimestamp(localTimestamp);
giuliomoro@135 229 send();
giuliomoro@135 230 expectedClockSyncType=kNone;
giuliomoro@135 231 break;
giuliomoro@135 232 }
giuliomoro@135 233 }
giuliomoro@135 234
giuliomoro@135 235 int ClockSync::sendReceiveLoop(){
giuliomoro@135 236 if(isSlave()==true){
giuliomoro@135 237 //printf("Waiting for a sync clockSync\n");
giuliomoro@135 238 } else { //if this is master
giuliomoro@135 239 usleep(100000); //this times (roughly) how often sync clockSyncs are being sent.
giuliomoro@135 240 int ret=masterSendSync();
giuliomoro@135 241 if(ret<=0)
giuliomoro@135 242 return -1;
giuliomoro@135 243 }
giuliomoro@135 244 int ret=receiveLoop();
giuliomoro@135 245 if(ret<=0)
giuliomoro@135 246 return -2;
giuliomoro@135 247 return 1;
giuliomoro@135 248 }
giuliomoro@135 249
giuliomoro@135 250