Public Member Functions | Protected Member Functions
PPSBuffer Class Reference

Brief description of class still missing. More...

#include <PPSBuffer.h>

Inheritance diagram for PPSBuffer:
GpCoreTools::DynamicBuffer

List of all members.

Public Member Functions

 PPSBuffer (UbxDevice *gpsDevice)
 ~PPSBuffer ()

Protected Member Functions

virtual int bytesAvailable (char *buffer, int byteCount)

Detailed Description

Brief description of class still missing.

Full description of class still missing


Constructor & Destructor Documentation

PPSBuffer::PPSBuffer ( UbxDevice gpsDevice)

Description of constructor still missing

References TRACE.

  : DynamicBuffer(0)
{
  TRACE;
  _gpsDevice=gpsDevice;
  _lastPPS=0;
}

Description of destructor still missing

References TRACE.

{
  TRACE;
}

Member Function Documentation

int PPSBuffer::bytesAvailable ( char *  buffer,
int  byteCount 
) [protected, virtual]

Implements GpCoreTools::DynamicBuffer.

References GpCoreTools::LinearRegression::a(), QGpCoreTools::abs(), GpCoreTools::LinearRegression::add(), GpCoreTools::LinearRegression::at(), GpCoreTools::LinearRegression::b(), GpCoreTools::LinearRegression::badValue(), GpCoreTools::LinearRegression::calculate(), GpCoreTools::LinearRegression::count(), UbxDevice::isResetPpsDrift(), UbxDevice::LostPpsLock, UbxDevice::monitorDriftMode(), UbxDevice::NoLock, UbxDevice::PpsLock, GpCoreTools::LinearRegression::remove(), GpCoreTools::LinearRegression::reset(), UbxDevice::resetGpsDrift(), UbxDevice::setPpsDriftCount(), UbxDevice::setTimeStatus(), GpCoreTools::LinearRegression::stddev(), UbxDevice::timeStatus(), and TRACE.

{
  TRACE;
  if(byteCount!=1) {  // Ignore if more than one byte is received
    Log::write(0, "more than one byte for PPS, fix GPS config\n");
    return byteCount;
  }
  // Record immediately the current time
  timeval sysTime, deltaTime;
  /*timespec clockTime;
  if(clock_gettime(CLOCK_REALTIME, &clockTime)!=0) {
    Log::write(0, "cannot get clock\n");
    return byteCount;
  }*/
  gettimeofday(&sysTime, 0);
  if(_gpsDevice->timeStatus()==UbxDevice::NoLock ||
     _gpsDevice->timeStatus()==UbxDevice::LostPpsLock) {
    return byteCount; // First wait for GPS lock before doing anything else
  }
  //Log::write(0, "pps clock %i s; %lf us\n", clockTime.tv_sec, (double)clockTime.tv_nsec*0.001);
  //Log::write(0, "pps timeofday %i s; %i us\n", sysTime.tv_sec, sysTime.tv_usec);
  deltaTime.tv_sec=0;
  // Fix average bias observed versus PPS on RNG: 30 ms of pulse length+transmission delay.
  //sysTime.tv_usec-=31640;
  // Fix average bias observed versus PPS on RNG: 180 ms of pulse length+transmission delay.
  sysTime.tv_usec-=181640;
  if(sysTime.tv_usec>500000) {
    deltaTime.tv_usec=1000000-sysTime.tv_usec;
    sysTime.tv_sec++;
  } else {
    deltaTime.tv_usec=-sysTime.tv_usec;
  }
#ifdef MONITOR_DRIFT_MODE
  if(_gpsDevice->monitorDriftMode()) {
    Log::write(0, "pps time delay %i %.3f ms\n", time(NULL), deltaTime.tv_usec);
    return byteCount;
  }
#endif
  if(_gpsDevice->isResetPpsDrift()) {
    Log::write(0, "pps drift reset\n");
    _drift.reset();
  }
  _drift.add(sysTime.tv_sec, deltaTime.tv_usec);
  //Log::writeNoStamp(0, "pps_drift %i %lg ms\n", sysTime.tv_sec, deltaTime.tv_usec*1e-3);

  if(_drift.count()>30) {
    _drift.calculate();
    float stddev=_drift.stddev();
    int badValueIndex=_drift.badValue(2.5*stddev);
    // From experience, if stddev if larger than 5 ms, the estimation of clock drift is not correct, continue stacking
    if(badValueIndex>=0) {
      Log::write(5, "pps drift dt(t)= %.20lg *t+ %.20lg bad value %i standard deviation= %f\n", _drift.a(), _drift.b(), badValueIndex, stddev);
      _drift.remove(badValueIndex);
    } else if(stddev>5000) {
        Log::write(5, "pps drift dt(t)= %.20lg *t+ %.20lg standard deviation=%f ms > 5 ms \n", _drift.a(), _drift.b(), stddev*0.001);
        if(_drift.count()>40) {
          _drift.reset();
        }
    } else {
      Log::write(10, "pps drift: dt(t)= %lg *t+ %lg, dt(now)= %lg ms\n", _drift.a(), _drift.b(), _drift.at(sysTime.tv_sec)*0.001);
      Log::write(5, "pps drift standard deviation= %f us.\n", stddev);
      deltaTime.tv_usec=_drift.at(sysTime.tv_sec);
      // System clock considered locked if delta is less than 10 ms
      int absDeltaUSec=abs(deltaTime.tv_usec);
      if(absDeltaUSec<10000) {
        if(adjtime(&deltaTime, 0)!=0) {
          Log::write(0, "pps adjust time: %s\n", strerror(errno));
        } else {
          if(absDeltaUSec>2000) {
            Log::write(2, "pps adjust time larger than 2 ms: %.3lf ms\n", deltaTime.tv_usec*0.001);
          }
          if(_gpsDevice->timeStatus()!=UbxDevice::PpsLock) {
            _gpsDevice->setTimeStatus(UbxDevice::PpsLock);
            if(_gpsDevice->timeStatus()==UbxDevice::PpsLock) {
              Log::write(0, "time locked to gps and pps\n");
            }
          }
        }
      } else {
        Log::write(0, "system clock and pps differ by %.3f ms: force system time.\n", deltaTime.tv_usec*0.001);
        //sysTime.tv_usec=31640;
        sysTime.tv_usec=181640;
        Log::write(0, "pps set time to %li.%06li\n", sysTime.tv_sec, sysTime.tv_usec);
        if(settimeofday(&sysTime, 0)!=0) {
          Log::write(0, "pps set time: %s\n", strerror(errno));
        } else {
          // Repeate time because the time stamping in log file might have a big jump
          Log::write(0, "pps time set to %li.%06li\n", sysTime.tv_sec, sysTime.tv_usec);
        }
        // Strong change in time, so reset Gps drift and status
        if(_gpsDevice->timeStatus()!=UbxDevice::PpsLock) {
          _gpsDevice->setTimeStatus(UbxDevice::NoLock);
        }
        _gpsDevice->resetGpsDrift();
      }
      _drift.reset();
    }
  }
  time_t t=sysTime.tv_sec;
  tm * d=gmtime(&t);
  if(_gpsDevice->timeStatus()==UbxDevice::PpsLock) {
    ScreenClient::write(12, 0, "%02i:%02i:%02i", d->tm_hour, d->tm_min, d->tm_sec);

    // Monitor and log missing PPSs
    if(_lastPPS!=sysTime.tv_sec-1 && _lastPPS!=0) {
      Log::write(0, "missing %i ppses\n", sysTime.tv_sec-_lastPPS-1);
      if(_lastPPS<sysTime.tv_sec-61) { // More than a minute without PPS
        _gpsDevice->setTimeStatus(UbxDevice::LostPpsLock);
        _lastPPS=0;
      } else {
        _lastPPS=sysTime.tv_sec;
      }
    } else {
      _lastPPS=sysTime.tv_sec;
    }
  } else {
    ScreenClient::write(12, 0, "PPS %3i ", _drift.count());
    _gpsDevice->setPpsDriftCount(_drift.count());
  }
  return byteCount;
}

The documentation for this class was generated from the following files:
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Defines