comparison core/ClockSync.cpp @ 141:44d07fa9bd03 ClockSync

Ultra-basic feedback for clock sync works^CIssues: response time of the IIR filter is too slow, requires PID and better filtering algorithm.
author Giulio Moro <giuliomoro@yahoo.it>
date Mon, 14 Sep 2015 15:42:11 +0100
parents 4e2dd3eb1d28
children 55c1e591cb2e
comparison
equal deleted inserted replaced
140:5edc6d0713ef 141:44d07fa9bd03
8 slave=thisIsSlave; 8 slave=thisIsSlave;
9 setPort(aPort); 9 setPort(aPort);
10 // isSlave() ? client.setServer("127.0.0.1") : client.setServer("127.0.0.1"); 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"); 11 isSlave() ? client.setServer("192.168.7.1") : client.setServer("192.168.7.2");
12 bufferLength=kSyncMessageLength; 12 bufferLength=kSyncMessageLength;
13 resetTs();
14 receiveLoopSleepUs=100;
15 receiveLoopTimeout=1e5;
16 movingAverage.setLength(31);
17 expectedClockSyncType=isSlave() ? kSync : kNone;
18 }
19 void ClockSync::resetTs(){
13 T1=-1; 20 T1=-1;
14 T1p=-1; 21 T1p=-1;
15 T2=-1; 22 T2=-1;
16 T2p=-1; 23 T2p=-1;
17 receiveLoopSleepUs=100; 24 }
18 receiveLoopTimeout=1e5; 25 bool ClockSync::areTsValid(){
19 movingAverage.setLength(31); 26 return T1>0 && T1p>0 && T2>0 && T2p>0;
20 expectedClockSyncType=isSlave() ? kSync : kNone;
21 } 27 }
22 ClockSync::ClockSync(bool thisIsSlave, int aPort, VirtualClock &aVirtualClock){ 28 ClockSync::ClockSync(bool thisIsSlave, int aPort, VirtualClock &aVirtualClock){
23 init(thisIsSlave, aPort, aVirtualClock); 29 init(thisIsSlave, aPort, aVirtualClock);
24 } 30 }
25 void* ClockSync::getBuffer(){ 31 void* ClockSync::getBuffer(){
188 } 194 }
189 195
190 int ClockSync::slaveHandleMessage(){ 196 int ClockSync::slaveHandleMessage(){
191 switch(clockSyncType){ 197 switch(clockSyncType){
192 case kSync: //the clockSync timestamp is meaningless, the localTimestamp is when kSync was received 198 case kSync: //the clockSync timestamp is meaningless, the localTimestamp is when kSync was received
199 resetTs();
193 T1p=localTimestamp; 200 T1p=localTimestamp;
194 expectedClockSyncType=kFollowUp; 201 expectedClockSyncType=kFollowUp;
195 break; 202 break;
196 case kFollowUp: //the clockSyncTimestamp is the time when kSync was sent, the localTimestamp is meaningless 203 case kFollowUp: //the clockSyncTimestamp is the time when kSync was sent, the localTimestamp is meaningless
197 T1=clockSyncTimestamp; 204 T1=clockSyncTimestamp;
207 break; 214 break;
208 case kDelayResp: {//the clockSyncTimestamp is the instant when the master received the kDelayResp clockSync, the localTimestamp is meaningless 215 case kDelayResp: {//the clockSyncTimestamp is the instant when the master received the kDelayResp clockSync, the localTimestamp is meaningless
209 T2p=clockSyncTimestamp; 216 T2p=clockSyncTimestamp;
210 //TODO: evaluate things 217 //TODO: evaluate things
211 double offset=(T1p-T1-T2p+T2)/2.0d; 218 double offset=(T1p-T1-T2p+T2)/2.0d;
212 printf("-----------OFFSET IS : %04.4f seconds, average: %04.4f seconds\n", 219 if(areTsValid()){
213 offset/44100.f, movingAverage.add(offset)/44100.f); 220 processOffset(offset);
221
222 /*
223 static int calls=0;
224 static double referenceOffset=0;
225
226 if(calls<100){ // start by averaging everything
227 movingAverage.add(offset);
228 } else { //once we get an estimate, start discarding outliers
229 float maxOffsetDeviation=20;
230 float deviation=fabsf(movingAverage.getAverage()-offset);
231 if(deviation<maxOffsetDeviation){
232 movingAverage.add(offset);
233 printf("w(end+1)=%4.1f;\n", movingAverage.getAverage());
234 } else {
235 // printf("Out of range: %f \n", deviation);
236 }
237 }
238 printf("offset(end+1)=%f;\n", offset);
239 if (calls==100){
240 // printf("Update reference\n");
241 referenceOffset=movingAverage.getAverage();
242 } else if (calls==200){
243 calls=99;
244 }
245 calls++;
246 */
247
248 // printf("%lld, %lld, %lld, %lld \n", T1, T1p, T2, T2p);
249 // if(T2-T1p<0){
250 // printf("Negative: %lld, %lld, %lld, %lld \n", T1, T1p, T2, T2p);
251 // }
252 } else {
253 printf("InvalidTs:\n %lld, %lld, %lld, %lld \n", T1, T1p, T2, T2p);
254 }
214 expectedClockSyncType=kSync; //end of the cycle, wait for next sync. 255 expectedClockSyncType=kSync; //end of the cycle, wait for next sync.
215 break; 256 break;
216 } 257 }
217 default: 258 default:
218 //printf("Unexpected message type\n"); // we should never get here 259 //printf("Unexpected message type\n"); // we should never get here
219 return -1; 260 return -1;
220 } 261 }
221 return 1; 262 return 1;
222 } 263 }
223 264 #include <I2c_Codec.h>
265 extern I2c_Codec* gAudioCodec;
266 void ClockSync::processOffset(double offset){
267 static int calls=0;
268 // TODO: change the flow control below so that it can happen multiple times
269 //(base it upon the length of movingAverage rather than the number of calls)
270 if(calls<10) { //get an initial guess
271 movingAverage.add(offset);
272 // printf("-----------OFFSET IS : %04.4f samples, average: %04.4f samples\n",
273 // offset, movingAverage.getAverage());
274 } else if (calls==10){ //then compensate for initial offset
275 // printf("compensating for offset: %f\n", offset);
276 virtualClock->addOffset(movingAverage.getAverage());
277 movingAverage.reset();
278 } else if (calls>=10){ //use IIR filter from now on
279 //filter coefficients obtained from Matlab : [B,A]=butter(2,0.005);
280 // static float B[3]={6.10061787580662e-05, 0.000122012357516132, 6.10061787580662e-05};
281 // static float A[3]={1, -1.97778648377676, 0.978030508491796};
282 static float B[3]={6.10061787580662e-05, 0.000122012357516132, 6.10061787580662e-05};
283 static float A[3]={1, -1.97778648377676, 0.978030508491796};
284 static float pastOut[3]={0,0,0};
285 static float pastIn[3]={0,0,0};
286 float in=offset;
287 float out= -pastOut[1]*A[1] -pastOut[2]*A[2] +in*B[0] +pastIn[1]*B[1] +pastIn[2]*B[2];
288 pastOut[2]=pastOut[1];
289 pastOut[1]=out;
290 pastIn[2]=pastIn[1];
291 pastIn[1]=in;
292 offset=out;
293 static float maxOffset=0;
294 maxOffset=fabsf(offset) > fabsf(maxOffset) ? offset : maxOffset;
295 printf("%10.3f, %10.3f, %10.3f, %10.3f\n", in, offset, offset-pastOut[2], maxOffset); //unfiltered, filtered
296 if(fabsf(offset)>10 && calls>30){
297 calls=11;
298 //TODO: correct for offset
299 float targetSamplingRate=offset>0 ? 44097 : 44103;
300 gAudioCodec->setAudioSamplingRate(targetSamplingRate);
301 // pastOut[1]=pastOut[2]=pastIn[1]=pastIn[2]=offset;
302 printf("------setAudioSmplingRate to %f\n", targetSamplingRate);
303 }
304 }
305 calls++;
306 }
224 int ClockSync::masterHandleMessage(){ 307 int ClockSync::masterHandleMessage(){
225 switch(clockSyncType){ 308 switch(clockSyncType){
226 case kDelayReq: 309 case kDelayReq:
227 //TODO: do something with it
228 //send kDelayResp 310 //send kDelayResp
229 setType(kDelayResp); 311 setType(kDelayResp);
230 setTimestamp(localTimestamp); 312 setTimestamp(localTimestamp);
231 send(); 313 send();
232 expectedClockSyncType=kNone; 314 expectedClockSyncType=kNone;
315 return 1;
233 break; 316 break;
317 default:
318 return -1;
234 } 319 }
235 } 320 }
236 321
237 int ClockSync::sendReceiveLoop(){ 322 int ClockSync::sendReceiveLoop(){
238 if(isSlave()==true){ 323 if(isSlave()==true){