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