Go to the documentation of this file.00001
00002
00003
00004
00005
00006 #include "softwarePLL.h"
00007 #include <iostream>
00008
00009
00010 #include <math.h>
00011 #include <iterator>
00012 #include <iostream>
00013 #include <fstream>
00014 #include <sstream>
00015 #include <vector>
00016 #include <string>
00017
00018
00019
00020 const double SoftwarePLL::MaxAllowedTimeDeviation = 0.001;
00021 const uint32_t SoftwarePLL::MaxExtrapolationCounter = 5;
00022
00023
00024
00025 class CSVRow
00026 {
00027 public:
00028 std::string const& operator[](std::size_t index) const
00029 {
00030 return m_data[index];
00031 }
00032 std::size_t size() const
00033 {
00034 return m_data.size();
00035 }
00036 void readNextRow(std::istream& str)
00037 {
00038 std::string line;
00039 std::getline(str, line);
00040
00041 std::stringstream lineStream(line);
00042 std::string cell;
00043
00044 m_data.clear();
00045 while(std::getline(lineStream, cell, ';'))
00046 {
00047 m_data.push_back(cell);
00048 }
00049
00050 if (!lineStream && cell.empty())
00051 {
00052
00053 m_data.push_back("");
00054 }
00055 }
00056 private:
00057 std::vector<std::string> m_data;
00058 };
00059
00060 std::istream& operator>>(std::istream& str, CSVRow& data)
00061 {
00062 data.readNextRow(str);
00063 return str;
00064 }
00065
00066
00067
00068 bool SoftwarePLL::pushIntoFifo(double curTimeStamp, uint32_t curtick)
00069
00070 {
00071 for (int i = 0; i < fifoSize - 1; i++)
00072 {
00073 tickFifo[i] = tickFifo[i + 1];
00074 clockFifo[i] = clockFifo[i + 1];
00075 }
00076 tickFifo[fifoSize - 1] = curtick;
00077 clockFifo[fifoSize - 1] = curTimeStamp;
00078
00079 if (numberValInFifo < fifoSize)
00080 {
00081 numberValInFifo++;
00082 }
00083 FirstTick(tickFifo[0]);
00084 FirstTimeStamp(clockFifo[0]);
00085
00086 return(true);
00087 }
00088
00089 double SoftwarePLL::extraPolateRelativeTimeStamp(uint32_t tick)
00090 {
00091 uint32_t tempTick = tick;
00092 tempTick -= (uint32_t)(0xFFFFFFFF & FirstTick());
00093 double timeDiff = tempTick * this->InterpolationSlope();
00094 return(timeDiff);
00095
00096 }
00097
00098 int SoftwarePLL::findDiffInFifo(double diff, double tol)
00099 {
00100 int numFnd = 0;
00101 double minAllowedDiff = (1.0 - tol) * diff;
00102 double maxAllowedDiff = (1.0 + tol) * diff;
00103
00104 for (int i = 0; i < numberValInFifo - 1; i++)
00105 {
00106 double diffTime = this->clockFifo[i+1] - clockFifo[i];
00107 if ((diffTime >= minAllowedDiff) && (diffTime <= maxAllowedDiff))
00108 {
00109 numFnd++;
00110 }
00111 }
00112
00113 return(numFnd);
00114 }
00115
00124 bool SoftwarePLL::updatePLL(uint32_t sec, uint32_t nanoSec, uint32_t curtick)
00125 {
00126 double start = sec + nanoSec * 1E-9;
00127 bool bRet = true;
00128
00129 if (false == IsInitialized())
00130 {
00131 pushIntoFifo(start, curtick);
00132 bool bCheck = this->updateInterpolationSlope();
00133 if (bCheck)
00134 {
00135 IsInitialized(true);
00136 }
00137 }
00138
00139 if (IsInitialized() == false)
00140 {
00141 return(false);
00142 }
00143
00144 double relTimeStamp = extraPolateRelativeTimeStamp(curtick);
00145 double cmpTimeStamp = start - this->FirstTimeStamp();
00146
00147 bool timeStampVerified = false;
00148 if (nearSameTimeStamp(relTimeStamp, cmpTimeStamp) == true)
00149 {
00150 timeStampVerified = true;
00151 pushIntoFifo(start, curtick);
00152 updateInterpolationSlope();
00153 ExtrapolationDivergenceCounter(0);
00154 }
00155
00156 if (timeStampVerified == false)
00157 {
00158
00159 uint32_t tmp = ExtrapolationDivergenceCounter();
00160 tmp++;
00161 ExtrapolationDivergenceCounter(tmp);
00162 if (ExtrapolationDivergenceCounter() >= SoftwarePLL::MaxExtrapolationCounter)
00163 {
00164 IsInitialized(false);
00165 }
00166
00167 }
00168
00169 return(true);
00170 }
00171
00172 bool SoftwarePLL::getCorrectedTimeStamp(uint32_t& sec, uint32_t& nanoSec, uint32_t curtick)
00173 {
00174 if (IsInitialized() == false)
00175 {
00176 return(false);
00177 }
00178
00179 double relTimeStamp = extraPolateRelativeTimeStamp(curtick);
00180 double corrTime = relTimeStamp + this->FirstTimeStamp();
00181 sec = (uint32_t)corrTime;
00182 double frac = corrTime - sec;
00183 nanoSec = (uint32_t)(1E9 * frac);
00184 return(true);
00185 }
00186
00187 bool SoftwarePLL::nearSameTimeStamp(double relTimeStamp1, double relTimeStamp2)
00188 {
00189 double dTAbs = fabs(relTimeStamp1 - relTimeStamp2);
00190 if (dTAbs < AllowedTimeDeviation())
00191 {
00192 return(true);
00193 }
00194 else
00195 {
00196 return(false);
00197 }
00198 }
00199
00200 bool SoftwarePLL::updateInterpolationSlope()
00201 {
00202
00203 if (numberValInFifo < fifoSize)
00204 {
00205 return(false);
00206 }
00207 std::vector<uint64_t> tickFifoUnwrap;
00208 std::vector<double> clockFifoUnwrap;
00209 clockFifoUnwrap.resize(fifoSize);
00210 tickFifoUnwrap.resize(fifoSize);
00211 uint64_t tickOffset = 0;
00212 clockFifoUnwrap[0] = 0.00;
00213 tickFifoUnwrap[0] = 0;
00214 FirstTimeStamp(this->clockFifo[0]);
00215 FirstTick(this->tickFifo[0]);
00216
00217 uint64_t tickDivisor = 0x100000000;
00218
00219
00220
00221 for (int i = 1; i < fifoSize; i++)
00222 {
00223 if (tickFifo[i] < tickFifo[i - 1])
00224 {
00225 tickOffset += tickDivisor;
00226 }
00227 tickFifoUnwrap[i] = tickOffset + tickFifo[i] - FirstTick();
00228 clockFifoUnwrap[i] = (this->clockFifo[i] - FirstTimeStamp());
00229 }
00230
00231 double sum_xy = 0.0;
00232 double sum_x = 0.0;
00233 double sum_y = 0.0;
00234 double sum_xx = 0.0;
00235 for (int i = 0; i < fifoSize; i++)
00236 {
00237 sum_xy += tickFifoUnwrap[i] * clockFifoUnwrap[i];
00238 sum_x += tickFifoUnwrap[i];
00239 sum_y += clockFifoUnwrap[i];
00240 sum_xx += tickFifoUnwrap[i] * tickFifoUnwrap[i];
00241 }
00242
00243
00244 double m = (fifoSize * sum_xy - sum_x * sum_y) / (fifoSize * sum_xx - sum_x*sum_x);
00245
00246 int matchCnt = 0;
00247 for (int i = 0; i < fifoSize; i++)
00248 {
00249 double yesti = m * tickFifoUnwrap[i];
00250 if (this->nearSameTimeStamp(yesti, clockFifoUnwrap[i]))
00251 {
00252 matchCnt++;
00253 }
00254 }
00255
00256 bool retVal = false;
00257 if (matchCnt == fifoSize)
00258 {
00259 InterpolationSlope(m);
00260 retVal = true;
00261 }
00262
00263 return(retVal);
00264 }
00265
00266 #if 0
00267 bool SoftwarePLL::getDemoFileData(std::string fileName, std::vector<uint32_t>& tickVec,std::vector<uint32_t>& secVec, std::vector<uint32_t>& nanoSecVec )
00268 {
00269 std::ifstream file(fileName);
00270
00271 CSVRow row;
00272 tickVec.clear();
00273 secVec.clear();
00274 nanoSecVec.clear();
00275 int lineCnt = 0;
00276 while (file >> row) {
00277 if (lineCnt > 0)
00278 {
00279 uint32_t tickVal = (uint32_t)std::stoi(row[0]);
00280 uint32_t secVal = (uint32_t)std::stoi(row[1]);
00281 uint32_t nanoSecVal = (uint32_t)std::stoi(row[2]);
00282 tickVec.push_back(tickVal);
00283 secVec.push_back(secVal);
00284 nanoSecVec.push_back(nanoSecVal);
00285 }
00286 lineCnt++;
00287 }
00288 if (lineCnt <= 1)
00289 return false;
00290 else
00291 return true;
00292 }
00293 #endif
00294
00295
00296 void SoftwarePLL::testbed()
00297 {
00298 std::cout << "Running testbed for SofwarePLL" << std::endl;
00299 uint32_t curtick = 0;
00300 int cnt = 0;
00301
00302 SoftwarePLL testPll;
00303 uint32_t sec = 9999;
00304 uint32_t nanoSec = 0;
00305 double tickPerSec = 1E6;
00306 uint32_t tickInc = 1000;
00307 int maxLoop = 20;
00308
00309 std::vector<uint32_t> tickVec;
00310 std::vector<uint32_t> secVec;
00311 std::vector<uint32_t> nanoSecVec;
00312 bool bRet = false;
00313
00314 bool testWithDataFile = true;
00315 if (testWithDataFile)
00316 {
00317
00318 maxLoop = tickVec.size();
00319 }
00320
00321 for (int i = 0; i < maxLoop; i++)
00322 {
00323 if (testWithDataFile)
00324 {
00325 curtick = tickVec[i];
00326 sec = secVec[i];
00327 nanoSec = nanoSecVec[i];
00328 }
00329 else
00330 {
00331 cnt++;
00332 curtick += tickInc;
00333 double deltaT = tickInc / tickPerSec;
00334 nanoSec += (int)(deltaT * 1E9);
00335 if (nanoSec >= 1E9)
00336 {
00337 nanoSec = 0;
00338 sec++;
00339 }
00340 if (cnt >= 8)
00341 {
00342 sec++;
00343 }
00344 }
00345 printf("Before correction: %3d.%09d\n", sec, nanoSec);
00346 uint32_t org_sec = sec;
00347 uint32_t org_nanoSec = nanoSec;
00348
00349 bool bRet = testPll.getCorrectedTimeStamp(sec, nanoSec, curtick);
00350
00351 bool corrected = false;
00352 if ((nanoSec != org_nanoSec) || (sec != org_sec))
00353 {
00354 corrected =true;
00355 }
00356 printf("After correction : %3d.%09d %s %s\n", sec, nanoSec, bRet ? "OK " : "DISMISS", corrected ? "MODI." : "OK ");
00357 }
00358
00359 return;
00360 }
00361
00362
00363
00364 #ifdef softwarePLL_MAINTEST
00365 int main(int argc, char **argv)
00366 {
00367 printf("Test for softwarePLL-Class\n");
00368 printf("\n");
00369 SoftwarePLL::testbed();
00370 }
00371 #endif
00372
00373
00374
00375
00376
00377
00378
00379
00380
00381
00382
00383
00384
00385
00386
00387
00388
00389
00390
00391
00392
00393
00394
00395
00396
00397
00398
00399
00400
00401
00402
00403
00404