annotate 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
rev   line source
giuliomoro@132 1 /*
giuliomoro@132 2 * ClockSynchronizer.cpp
giuliomoro@132 3 *
giuliomoro@132 4 * Created on: 26 Aug 2015
giuliomoro@132 5 * Author: giulio
giuliomoro@132 6 */
giuliomoro@132 7
giuliomoro@132 8 #include "ClockSynchronizer.h"
giuliomoro@132 9
giuliomoro@132 10 // declare static members
giuliomoro@132 11 float ClockSynchronizer::targetSamplingRate;
giuliomoro@132 12 float ClockSynchronizer::currentSamplingRate;
giuliomoro@132 13 bool ClockSynchronizer::threadRunning;
giuliomoro@132 14 int ClockSynchronizer::threadWasRunning;
giuliomoro@132 15 bool ClockSynchronizer::staticConstructed=false;
giuliomoro@132 16 AuxiliaryTask ClockSynchronizer::setClockTask;
giuliomoro@132 17
giuliomoro@132 18 void ClockSynchronizer::staticConstructor(){
giuliomoro@132 19 int priority=90;
giuliomoro@132 20 setClockTask=BeagleRT_createAuxiliaryTask(&ClockSynchronizer::setClock, priority, "setClockTask");
giuliomoro@132 21 threadRunning=false;
giuliomoro@132 22 }
giuliomoro@132 23
giuliomoro@132 24 void ClockSynchronizer::setClock(){
giuliomoro@132 25 rt_printf("Setting clock to %f\n",targetSamplingRate);
giuliomoro@132 26 threadRunning=true;
giuliomoro@132 27 //I2C magic
giuliomoro@132 28 gAudioCodec->setAudioSamplingRate(targetSamplingRate);
giuliomoro@132 29 threadRunning=false;
giuliomoro@132 30 threadWasRunning=3;
giuliomoro@132 31 rt_printf("Exiting thread\n");
giuliomoro@132 32 };
giuliomoro@132 33
giuliomoro@132 34 ClockSynchronizer::ClockSynchronizer() {
giuliomoro@132 35 reset();
giuliomoro@132 36 }
giuliomoro@132 37
giuliomoro@132 38 ClockSynchronizer::~ClockSynchronizer(){};
giuliomoro@132 39
giuliomoro@132 40 void ClockSynchronizer::setup(){
giuliomoro@132 41 if(staticConstructed==false) //This should be called in the constructor, but because of the current limitations of
giuliomoro@132 42 // BeagleRT, it is here and setup() needs to be called in BeagleRT setup();
giuliomoro@132 43 staticConstructor();
giuliomoro@132 44 }
giuliomoro@132 45 void ClockSynchronizer::reset(){
giuliomoro@132 46 localCounter=0;
giuliomoro@132 47 remoteCounter=0;
giuliomoro@132 48 lastTime=0;
giuliomoro@132 49 localOffset=-1;
giuliomoro@132 50 remoteOffset=-1;
giuliomoro@132 51 timeOffset=-1;
giuliomoro@132 52 currentSamplingRate=44100;
giuliomoro@132 53 }
giuliomoro@132 54
giuliomoro@132 55 void ClockSynchronizer::update(int aLocalCounter, int aRemoteCounter, RTIME aLastTime){
giuliomoro@132 56 if(threadRunning==true){ //do nothing if clock is being adjusted
giuliomoro@132 57 rt_printf("do nothing if clock is being adjusted\n");
giuliomoro@132 58 return;
giuliomoro@132 59 }
giuliomoro@132 60 if(threadWasRunning > 0){ //reset variables after clock has been adjusted
giuliomoro@132 61 threadWasRunning--; // wait a few calls to make sure the clock stabilizes
giuliomoro@132 62 rt_printf("wait a few calls to make sure the clock stabilizes\n");
giuliomoro@132 63 return;
giuliomoro@132 64 }/*
giuliomoro@132 65 if(threadWasRunning==1){
giuliomoro@132 66 threadWasRunning=0;
giuliomoro@132 67 // reset offsets after a correction
giuliomoro@132 68 localOffset=aLocalCounter;
giuliomoro@132 69 remoteOffset=aRemoteCounter;
giuliomoro@132 70 timeOffset=aLastTime;
giuliomoro@132 71 rt_printf("reset variables after clock has been adjusted\n");
giuliomoro@132 72 return;
giuliomoro@132 73 }*/
giuliomoro@132 74 if (localOffset<=0 || remoteOffset<=0){ // probably this is the first run
giuliomoro@132 75 localOffset=aLocalCounter;
giuliomoro@132 76 remoteOffset=aRemoteCounter;
giuliomoro@132 77 timeOffset=aLastTime;
giuliomoro@132 78 rt_printf("First run of update(), localOffset: %d, remoteOffset: %d, timeOffset: %llu\n",
giuliomoro@132 79 localOffset, remoteOffset, timeOffset);
giuliomoro@132 80 return;
giuliomoro@132 81 }
giuliomoro@132 82 localCounter=aLocalCounter-localOffset;
giuliomoro@132 83 remoteCounter=aRemoteCounter-remoteOffset;
giuliomoro@132 84 lastTime=aLastTime-timeOffset;
giuliomoro@132 85 if (localCounter<=0 || remoteCounter<=0 || timeOffset<=0) {// did anything wrong happened?
giuliomoro@132 86 rt_printf("fourth\n");
giuliomoro@132 87 return;
giuliomoro@132 88 }
giuliomoro@132 89 // TODO: make sure we do not get actually adjust the clock too often (e.g.: limits on the timestamp)
giuliomoro@132 90 // Should keep track of last time a change has been made, so that when a large compensation is needed
giuliomoro@132 91 // (e.g.: as the program has just started), adjustClock() is called more frequently
giuliomoro@132 92 // but gets called less often later.
giuliomoro@132 93 // Should also try to avoid drastic correction after a while that the program
giuliomoro@132 94 // has started, so to avoid glitches. But this can maybe be handled by the thread itself.
giuliomoro@132 95 // TODO: should keep a log and maybe compensate for (and prevent) overshoot according to previous changes
giuliomoro@132 96 rt_printf("lastTime: %llu, remoteCounter: %d\n", lastTime, remoteCounter);
giuliomoro@132 97
giuliomoro@132 98 currentSamplingRate=gAudioCodec->getAudioSamplingRate();
giuliomoro@132 99 float T=1/currentSamplingRate;
giuliomoro@132 100 int elapsedSamples=remoteCounter*(NetworkBuffer::bufferLength-NetworkBuffer::headerLength);
giuliomoro@132 101 double expectedTimeUs=T*elapsedSamples*1000000;
giuliomoro@132 102 double actualTimeUs=lastTime/1000.0;
giuliomoro@132 103 targetSamplingRate=expectedTimeUs/actualTimeUs*currentSamplingRate;
giuliomoro@132 104 // rt_printf("Fs: %f, expectedTimeUs: %f, lastTime: %ul\n", expectedTimeUs, lastTime);
giuliomoro@132 105 rt_printf("Fs: %.1f, expectedTimeUs: %4.3f, actualTimeUs: %4.3f, targetFs_ %.3f\n",
giuliomoro@132 106 gAudioCodec->getAudioSamplingRate(), expectedTimeUs/elapsedSamples, actualTimeUs/elapsedSamples, targetSamplingRate);
giuliomoro@132 107 adjustClock();
giuliomoro@132 108 }
giuliomoro@132 109
giuliomoro@132 110 void ClockSynchronizer::adjustClock(){
giuliomoro@132 111 if(currentSamplingRate!= targetSamplingRate){ //TODO: actually check that the difference is less than the quantization error in the PLL
giuliomoro@132 112 BeagleRT_scheduleAuxiliaryTask(setClockTask);
giuliomoro@132 113 }
giuliomoro@132 114 }