diff core/ClockSynchronizer.cpp @ 132:e24c531220ee scope-refactoring

Added some sort of synchronization, not working great though
author Giulio Moro <giuliomoro@yahoo.it>
date Thu, 27 Aug 2015 01:42:04 +0100
parents
children 04b1678614c9
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/core/ClockSynchronizer.cpp	Thu Aug 27 01:42:04 2015 +0100
@@ -0,0 +1,114 @@
+/*
+ * ClockSynchronizer.cpp
+ *
+ *  Created on: 26 Aug 2015
+ *      Author: giulio
+ */
+
+#include "ClockSynchronizer.h"
+
+// declare static members
+float ClockSynchronizer::targetSamplingRate;
+float ClockSynchronizer::currentSamplingRate;
+bool ClockSynchronizer::threadRunning;
+int ClockSynchronizer::threadWasRunning;
+bool ClockSynchronizer::staticConstructed=false;
+AuxiliaryTask ClockSynchronizer::setClockTask;
+
+void ClockSynchronizer::staticConstructor(){
+	int priority=90;
+	setClockTask=BeagleRT_createAuxiliaryTask(&ClockSynchronizer::setClock, priority, "setClockTask");
+	threadRunning=false;
+}
+
+void ClockSynchronizer::setClock(){
+	rt_printf("Setting clock to %f\n",targetSamplingRate);
+	threadRunning=true;
+//I2C magic
+	gAudioCodec->setAudioSamplingRate(targetSamplingRate);
+	threadRunning=false;
+	threadWasRunning=3;
+	rt_printf("Exiting thread\n");
+};
+
+ClockSynchronizer::ClockSynchronizer() {
+	reset();
+}
+
+ClockSynchronizer::~ClockSynchronizer(){};
+
+void ClockSynchronizer::setup(){
+	if(staticConstructed==false) //This should be called in the constructor, but because of the current limitations of
+		// BeagleRT, it is here and setup() needs to be called in BeagleRT setup();
+		staticConstructor();
+}
+void ClockSynchronizer::reset(){
+	localCounter=0;
+	remoteCounter=0;
+	lastTime=0;
+	localOffset=-1;
+	remoteOffset=-1;
+	timeOffset=-1;
+	currentSamplingRate=44100;
+}
+
+void ClockSynchronizer::update(int aLocalCounter, int aRemoteCounter, RTIME aLastTime){
+	if(threadRunning==true){ //do nothing if clock is being adjusted
+		rt_printf("do nothing if clock is being adjusted\n");
+		return;
+	}
+	if(threadWasRunning > 0){ //reset variables after clock has been adjusted
+		threadWasRunning--;  // wait a few calls to make sure the clock stabilizes
+		rt_printf("wait a few calls to make sure the clock stabilizes\n");
+		return;
+	}/*
+	if(threadWasRunning==1){
+		threadWasRunning=0;
+		// reset offsets after a correction
+		localOffset=aLocalCounter;
+		remoteOffset=aRemoteCounter;
+		timeOffset=aLastTime;
+		rt_printf("reset variables after clock has been adjusted\n");
+		return;
+	}*/
+	if (localOffset<=0 || remoteOffset<=0){ // probably this is the first run
+		localOffset=aLocalCounter;
+		remoteOffset=aRemoteCounter;
+		timeOffset=aLastTime;
+		rt_printf("First run of update(), localOffset: %d, remoteOffset: %d, timeOffset: %llu\n",
+				localOffset, remoteOffset, timeOffset);
+		return;
+	}
+	localCounter=aLocalCounter-localOffset;
+	remoteCounter=aRemoteCounter-remoteOffset;
+	lastTime=aLastTime-timeOffset;
+	if (localCounter<=0 || remoteCounter<=0 || timeOffset<=0) {// did anything wrong happened?
+		rt_printf("fourth\n");
+		return;
+	}
+	// TODO: make sure we do not get actually adjust the clock too often (e.g.: limits on the timestamp)
+	// Should keep track of last time a change has been made, so that when a large compensation is needed
+	// (e.g.: as the program has just started), adjustClock() is called more frequently
+	// but gets called less often later.
+	// Should also try to avoid drastic correction after a while that the program
+	// has started, so to avoid glitches. But this can maybe be handled by the thread itself.
+	// TODO: should keep a log and maybe compensate for (and prevent) overshoot according to previous changes
+	rt_printf("lastTime: %llu, remoteCounter: %d\n", lastTime, remoteCounter);
+
+	currentSamplingRate=gAudioCodec->getAudioSamplingRate();
+	float T=1/currentSamplingRate;
+	int elapsedSamples=remoteCounter*(NetworkBuffer::bufferLength-NetworkBuffer::headerLength);
+	double expectedTimeUs=T*elapsedSamples*1000000;
+	double actualTimeUs=lastTime/1000.0;
+	targetSamplingRate=expectedTimeUs/actualTimeUs*currentSamplingRate;
+//	rt_printf("Fs: %f, expectedTimeUs: %f, lastTime: %ul\n", expectedTimeUs, lastTime);
+	rt_printf("Fs: %.1f, expectedTimeUs: %4.3f, actualTimeUs: %4.3f, targetFs_ %.3f\n",
+			gAudioCodec->getAudioSamplingRate(), expectedTimeUs/elapsedSamples, actualTimeUs/elapsedSamples, targetSamplingRate);
+	adjustClock();
+}
+
+void ClockSynchronizer::adjustClock(){
+	if(currentSamplingRate!= targetSamplingRate){ //TODO: actually check that the difference is less than the quantization error in the PLL
+		BeagleRT_scheduleAuxiliaryTask(setClockTask);
+	}
+}