annotate core/ClockSynchronizer.cpp @ 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 04b1678614c9
children
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@133 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@133 30 threadWasRunning=1;
giuliomoro@133 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@133 96 static RTIME lastlastTime=0;
giuliomoro@133 97 // rt_printf("interval: %f, \n",(double)(remoteCounter*300.0)/lastTime*1000000000.0);
giuliomoro@133 98 lastlastTime=lastTime;
giuliomoro@132 99 currentSamplingRate=gAudioCodec->getAudioSamplingRate();
giuliomoro@132 100 float T=1/currentSamplingRate;
giuliomoro@132 101 int elapsedSamples=remoteCounter*(NetworkBuffer::bufferLength-NetworkBuffer::headerLength);
giuliomoro@132 102 double expectedTimeUs=T*elapsedSamples*1000000;
giuliomoro@133 103 double actualTimeS=lastTime/1000000000.0;
giuliomoro@132 104 double actualTimeUs=lastTime/1000.0;
giuliomoro@133 105 static float averageBuffer[101]={0};
giuliomoro@133 106 static int averageBufferPointer=0;
giuliomoro@133 107 static float average=0;
giuliomoro@133 108 static int bufferFull=0;
giuliomoro@133 109 average-=averageBuffer[averageBufferPointer];
giuliomoro@133 110 averageBuffer[averageBufferPointer]=elapsedSamples/actualTimeS;
giuliomoro@133 111 average+=averageBuffer[averageBufferPointer];
giuliomoro@133 112 averageBufferPointer++;
giuliomoro@133 113 if(averageBufferPointer==101){
giuliomoro@133 114 averageBufferPointer=0;
giuliomoro@133 115 bufferFull++;
giuliomoro@133 116 }
giuliomoro@133 117
giuliomoro@132 118 // rt_printf("Fs: %f, expectedTimeUs: %f, lastTime: %ul\n", expectedTimeUs, lastTime);
giuliomoro@133 119 // rt_printf("Fs: %.1f, actualTimeS: %4.6f, targetFs_ %.3f\n",
giuliomoro@133 120 if((averageBufferPointer&3)==0){
giuliomoro@133 121 static float oldTargetSamplingRate=0;
giuliomoro@133 122 targetSamplingRate=average/101;
giuliomoro@133 123 if(bufferFull>=3 && fabsf(targetSamplingRate-oldTargetSamplingRate) < 1){
giuliomoro@133 124 rt_printf("%.1f, %4.6f, %.3f;\n",
giuliomoro@133 125 gAudioCodec->getAudioSamplingRate(), actualTimeS, targetSamplingRate, targetSamplingRate-oldTargetSamplingRate);
giuliomoro@133 126 adjustClock();
giuliomoro@133 127 }
giuliomoro@133 128 oldTargetSamplingRate=targetSamplingRate;
giuliomoro@133 129 }
giuliomoro@132 130 }
giuliomoro@132 131
giuliomoro@132 132 void ClockSynchronizer::adjustClock(){
giuliomoro@133 133 if(fabsf(currentSamplingRate-targetSamplingRate)>0.7){ //TODO: actually check that the difference is less than the quantization error in the PLL
giuliomoro@132 134 BeagleRT_scheduleAuxiliaryTask(setClockTask);
giuliomoro@132 135 }
giuliomoro@132 136 }