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