Mercurial > hg > beaglert
diff 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 |
line wrap: on
line diff
--- a/core/ClockSync.cpp Mon Sep 14 14:57:54 2015 +0100 +++ b/core/ClockSync.cpp Mon Sep 14 15:42:11 2015 +0100 @@ -10,14 +10,20 @@ // 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; + resetTs(); + receiveLoopSleepUs=100; + receiveLoopTimeout=1e5; + movingAverage.setLength(31); + expectedClockSyncType=isSlave() ? kSync : kNone; +} +void ClockSync::resetTs(){ T1=-1; T1p=-1; T2=-1; T2p=-1; - receiveLoopSleepUs=100; - receiveLoopTimeout=1e5; - movingAverage.setLength(31); - expectedClockSyncType=isSlave() ? kSync : kNone; +} +bool ClockSync::areTsValid(){ + return T1>0 && T1p>0 && T2>0 && T2p>0; } ClockSync::ClockSync(bool thisIsSlave, int aPort, VirtualClock &aVirtualClock){ init(thisIsSlave, aPort, aVirtualClock); @@ -190,6 +196,7 @@ int ClockSync::slaveHandleMessage(){ switch(clockSyncType){ case kSync: //the clockSync timestamp is meaningless, the localTimestamp is when kSync was received + resetTs(); T1p=localTimestamp; expectedClockSyncType=kFollowUp; break; @@ -209,8 +216,42 @@ T2p=clockSyncTimestamp; //TODO: evaluate things double offset=(T1p-T1-T2p+T2)/2.0d; - printf("-----------OFFSET IS : %04.4f seconds, average: %04.4f seconds\n", - offset/44100.f, movingAverage.add(offset)/44100.f); + if(areTsValid()){ + processOffset(offset); + + /* + static int calls=0; + static double referenceOffset=0; + + if(calls<100){ // start by averaging everything + movingAverage.add(offset); + } else { //once we get an estimate, start discarding outliers + float maxOffsetDeviation=20; + float deviation=fabsf(movingAverage.getAverage()-offset); + if(deviation<maxOffsetDeviation){ + movingAverage.add(offset); + printf("w(end+1)=%4.1f;\n", movingAverage.getAverage()); + } else { +// printf("Out of range: %f \n", deviation); + } + } + printf("offset(end+1)=%f;\n", offset); + if (calls==100){ +// printf("Update reference\n"); + referenceOffset=movingAverage.getAverage(); + } else if (calls==200){ + calls=99; + } + calls++; +*/ + +// printf("%lld, %lld, %lld, %lld \n", T1, T1p, T2, T2p); +// if(T2-T1p<0){ +// printf("Negative: %lld, %lld, %lld, %lld \n", T1, T1p, T2, T2p); +// } + } else { + printf("InvalidTs:\n %lld, %lld, %lld, %lld \n", T1, T1p, T2, T2p); + } expectedClockSyncType=kSync; //end of the cycle, wait for next sync. break; } @@ -220,17 +261,61 @@ } return 1; } - +#include <I2c_Codec.h> +extern I2c_Codec* gAudioCodec; +void ClockSync::processOffset(double offset){ + static int calls=0; + // TODO: change the flow control below so that it can happen multiple times + //(base it upon the length of movingAverage rather than the number of calls) + if(calls<10) { //get an initial guess + movingAverage.add(offset); +// printf("-----------OFFSET IS : %04.4f samples, average: %04.4f samples\n", +// offset, movingAverage.getAverage()); + } else if (calls==10){ //then compensate for initial offset +// printf("compensating for offset: %f\n", offset); + virtualClock->addOffset(movingAverage.getAverage()); + movingAverage.reset(); + } else if (calls>=10){ //use IIR filter from now on + //filter coefficients obtained from Matlab : [B,A]=butter(2,0.005); +// static float B[3]={6.10061787580662e-05, 0.000122012357516132, 6.10061787580662e-05}; +// static float A[3]={1, -1.97778648377676, 0.978030508491796}; + static float B[3]={6.10061787580662e-05, 0.000122012357516132, 6.10061787580662e-05}; + static float A[3]={1, -1.97778648377676, 0.978030508491796}; + static float pastOut[3]={0,0,0}; + static float pastIn[3]={0,0,0}; + float in=offset; + float out= -pastOut[1]*A[1] -pastOut[2]*A[2] +in*B[0] +pastIn[1]*B[1] +pastIn[2]*B[2]; + pastOut[2]=pastOut[1]; + pastOut[1]=out; + pastIn[2]=pastIn[1]; + pastIn[1]=in; + offset=out; + static float maxOffset=0; + maxOffset=fabsf(offset) > fabsf(maxOffset) ? offset : maxOffset; + printf("%10.3f, %10.3f, %10.3f, %10.3f\n", in, offset, offset-pastOut[2], maxOffset); //unfiltered, filtered + if(fabsf(offset)>10 && calls>30){ + calls=11; + //TODO: correct for offset + float targetSamplingRate=offset>0 ? 44097 : 44103; + gAudioCodec->setAudioSamplingRate(targetSamplingRate); +// pastOut[1]=pastOut[2]=pastIn[1]=pastIn[2]=offset; + printf("------setAudioSmplingRate to %f\n", targetSamplingRate); + } + } + calls++; +} int ClockSync::masterHandleMessage(){ switch(clockSyncType){ case kDelayReq: - //TODO: do something with it //send kDelayResp setType(kDelayResp); setTimestamp(localTimestamp); send(); expectedClockSyncType=kNone; + return 1; break; + default: + return -1; } }