changeset 151:e9c9404e3d1f ClockSync

Pff partially working. No PID. When setting the audio clock on the bbb to 44098 the master and slave clock keep diverging instead of converging ...
author Giulio Moro <giuliomoro@yahoo.it>
date Tue, 22 Sep 2015 04:10:07 +0100
parents ebbfb154351a
children 8f98b32d0e23
files core/ClockSync.cpp core/I2c_Codec.cpp include/I2c_Codec.h projects/scope/render.cpp
diffstat 4 files changed, 93 insertions(+), 40 deletions(-) [+]
line wrap: on
line diff
--- a/core/ClockSync.cpp	Tue Sep 22 04:09:13 2015 +0100
+++ b/core/ClockSync.cpp	Tue Sep 22 04:10:07 2015 +0100
@@ -265,48 +265,80 @@
 	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
+	if(calls<30){
+		 // wait for the VirtualClock to stabilize and produce meaningful outputs
+	} else if(calls<50) { //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);
+	} else if (calls==50){ //then compensate for initial offset
+//		printf("compensating for offset: %f\n", movingAverage.getAverage());
 		virtualClock->addOffset(movingAverage.getAverage());
 		movingAverage.reset();
-	} else if (calls>=10){ //use IIR filter from now on
+	} else if (calls>50){ //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 IirFilter iir(1);
+		static bool init = false;
+		if(init == false){
+//			double coeffs[5]={0.00554271721028068, 0.0110854344205614, 0.00554271721028068,
+//							     -1.77863177782459, 0.800802646665708};
+			double coeffs[5]={0.0200833655642113, 0.0401667311284225, 0.0200833655642113,
+						-1.56101807580072, 0.641351538057563};
+			iir.setCoefficients(coeffs);
+			init = true;
+		}
+		float expectedOffsetDifferenceMean = 0.2432;
+		float expectedOffsetDifferenceStd = 6.487;
+		float nlOffset;
+		static float pastOffset = 0;
+		float offsetIncrement = offset-pastOffset;
+		if ( fabsf(offsetIncrement) > 1*expectedOffsetDifferenceStd && calls>51){
+			// non-linear filtering: remove outliers
+			nlOffset = pastOffset;
+//			printf("%f %f                                             0,0,0,0,0,0\n", offset,pastOffset);
+		} else {
+			nlOffset=offset;
+		}
+		pastOffset=nlOffset;
+		float iirOffset = iir.process(nlOffset);
 		static float maxOffset=0;
-		if(calls > 0 ) {
-			maxOffset=fabsf(offset) > fabsf(maxOffset) ? offset : maxOffset;
-			pid.setError(offset);
-			float correction=pid.getOutput();
+		static float pastIirOffset=0;
+		if( calls > 0 ) {
+			maxOffset=fabsf(iirOffset) > fabsf(maxOffset) ? iirOffset : maxOffset;
+			pid.setError(iirOffset);
+			float correction=pid.getOutput()*0.0001;
 			static float oldSamplingRate=44100;
-			printf("%10.3f, %10.3f, %10.3f, %10.3f, %10.3f, %10.3f\n", in, offset, offset-pastOut[2], maxOffset, correction, oldSamplingRate); //unfiltered, filtered
-	//		if(fabsf(offset)>3 && calls>30){
-				//TODO: correct for offset
-	//			float targetSamplingRate=offset>0 ? 44095 : 44105;
-			float targetSamplingRate = oldSamplingRate - correction;
-	#ifndef USE_JUCE
-//			if(oldSamplingRate != targetSamplingRate)
-//				gAudioCodec->setAudioSamplingRate(targetSamplingRate);
-	#endif
+			printf("%10.3f, %10.3f, %10.3f, %10.3f, %10.3f, %10.3f\n",
+					offset, nlOffset, iirOffset, iirOffset - pastIirOffset, correction, oldSamplingRate); //unfiltered, filtered
+			pastIirOffset = iirOffset;
+			float targetSamplingRate;
+			static int direction=1;
+			float thresholdL = -1;
+//			targetSamplingRate = oldSamplingRate - correction;
+			float thresholdH = 3;
+
+			targetSamplingRate = 44100;
+			if(
+				(iirOffset > thresholdH && direction == 1) ||
+				(iirOffset > thresholdL && direction == -1)
+			){
+				targetSamplingRate = 44097;
+				direction = -1;
+			}
+			else if (
+				(iirOffset < -thresholdH && direction == -1) ||
+				(iirOffset < -thresholdL && direction == 1)
+			)
+			{
+				iirOffset = 44102;
+				direction = 1;
+			}
+#ifndef USE_JUCE
+			if(oldSamplingRate != targetSamplingRate){
+				gAudioCodec->setAudioSamplingRate(targetSamplingRate);
+			}
+#endif
 			oldSamplingRate=targetSamplingRate;
-	//			pastOut[1]=pastOut[2]=pastIn[1]=pastIn[2]=offset;
-	//			printf("------setAudioSmplingRate to %f\n", targetSamplingRate);
-	//		}
 		}
 	}
 	calls++;
@@ -330,7 +362,7 @@
 	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.
+		usleep(30000); //this times (roughly) how often sync clockSyncs are being sent.
 		int ret=masterSendSync();
 		if(ret<=0)
 			return -1;
--- a/core/I2c_Codec.cpp	Tue Sep 22 04:09:13 2015 +0100
+++ b/core/I2c_Codec.cpp	Tue Sep 22 04:10:07 2015 +0100
@@ -49,7 +49,7 @@
 	// using P=8 and R=1 gives a resolution of 0.0732421875Hz ( 0.000166% at 44.1kHz)
 	// to obtain Fs=44100 we need to have K=60.2112
 
-	if(setPllP(7))
+	if(setPllP(1))
 		return 1;
 	if(setPllR(1))
 		return 1;
@@ -218,9 +218,9 @@
 	//	f_{S(ref)} = (PLLCLK_IN × K × R)/(2048 × P)
 	float k = ((double)(newSamplingRate * pllP * 2048.0f/(float)pllR)) / PLLCLK_IN ;
 	int ret = setPllK(k);
-	float actualSamplingRate = PLLCLK_IN * (pllJ + pllD/10000.0) * pllR / (2048.0 * pllP);
-	printf("P: %d, R: %d, J: %d, D: %d, samplingRate= %f\n", pllP, pllR, pllJ, pllD, actualSamplingRate );
-//	printf("fs_ref=%f;\n",actualSamplingRate);
+//	printf("P: %d, R: %d, J: %d, D: %d, samplingRate= %f\n", pllP, pllR, pllJ, pllD, getAudioSamplingRate());
+//	printf("fs_ref=%f;\n",getAudioSamplingRate());
+//	printf("0 0 0 0 0 0\n");
 	return ret;
 }
 
@@ -243,7 +243,7 @@
 	return k;
 }
 
-float I2c_Codec::getAudioSamplingRate(){
+double I2c_Codec::getAudioSamplingRate(){
 	int pllP=1; //TODO: create get/set for pllP and pllR
 	int pllR=1;
 	long int PLLCLK_IN=12000000;
--- a/include/I2c_Codec.h	Tue Sep 22 04:09:13 2015 +0100
+++ b/include/I2c_Codec.h	Tue Sep 22 04:10:07 2015 +0100
@@ -38,12 +38,12 @@
 	int setPllR(unsigned int r);
 	int setPllK(float k);
 	int setAudioSamplingRate(float newSamplingRate);
+	double getAudioSamplingRate();
 	short unsigned int getPllJ();
 	unsigned int getPllD();
 	unsigned int getPllP();
 	unsigned int getPllR();
 	float getPllK();
-	float getAudioSamplingRate();
 	int setDACVolume(int halfDbSteps);
 	int writeDACVolumeRegisters(bool mute);
 	int setADCVolume(int halfDbSteps);
--- a/projects/scope/render.cpp	Tue Sep 22 04:09:13 2015 +0100
+++ b/projects/scope/render.cpp	Tue Sep 22 04:10:07 2015 +0100
@@ -76,6 +76,27 @@
 //		BeagleRT_scheduleAuxiliaryTask(testTime);
 		clockSyncThread.startThread(); //make sure you uncomment .init in setup()
 	}
+	/*
+	switch (count){
+	case 5000:
+			gAudioCodec->setAudioSamplingRate(44101);
+			printf("0 0 0\n");
+			break;
+	case 10000:
+			gAudioCodec->setAudioSamplingRate(44100);
+			printf("0 0 0\n");
+			break;
+	case 15000:
+			gAudioCodec->setAudioSamplingRate(44099);
+			printf("0 0 0\n");
+			break;
+	case 20000:
+			gAudioCodec->setAudioSamplingRate(44100);
+			printf("0 0 0\n");
+			count = 0;
+			break;
+	}
+	*/
 	static float phase=0;
 	float phaseInc=gFrequency1/44100.0*2*M_PI;
 //	rt_printf("phaseInc: %f, phase: %f\n",phaseInc,phase);