////////////////////////////////////////////////////////////////////////////////
//
// PURPOSE:  Dvl Driver.
// AUTHOR:   Tom O'Reilly & Rob McEwen
// DATE:     01/3/9
// COMMENTS: 
//
////////////////////////////////////////////////////////////////////////////////
//
#include <process.h>
#include "DvlServer.h"

DvlServer::DvlServer(const char *driverName, SerialParameters *serialParams) 
  : DvlIF_SK() 
{
  _serialParams = serialParams;
  _output = new DvlOutput(SharedData::ReadWrite);
  _driverName = strdup(driverName);
  m_lastPingTime = 0.;
}



DvlServer::~DvlServer() 
{
  delete _output;
  free((void *)_driverName);
}


void DvlServer::name(DeviceIF::Name name)
{
  // Dummy implementation for now
  strcpy(name, "Dvl");
}


void DvlServer::serialNumber(DeviceIF::Name number)
{
  // Dummy implementation for now
  strcpy(number, "XXX");
}


DeviceIF::Status DvlServer::initialize()
{
  // Dummy implementation for now
  return DeviceIF::Ok;
}


DeviceIF::Status DvlServer::powerOn()
{
  // Dummy implementation for now
  return DeviceIF::Ok;
}


DeviceIF::Status DvlServer::powerOff()
{
  // Dummy implementation for now
  return DeviceIF::Ok;
}


DeviceIF::Status DvlServer::status()
{
  // Dummy implementation for now
  return DeviceIF::Ok;
}


DeviceIF::Status DvlServer::dataLoggingOn()
{
  // Dummy implementation for now
  return DeviceIF::Ok;
}


DeviceIF::Status DvlServer::dataLoggingOff()
{
  // Dummy implementation for now
  return DeviceIF::Ok;
}


DeviceIF::Status DvlServer::get(DvlIF::Data *data, Boolean *newData) 
{
  _output->read();
  //
  // Flag new data:
  //
  *newData = False;
  if( m_lastPingTime < _output->data.pingTime )
  {
    *newData = True;
    m_lastPingTime = _output->data.pingTime;
  }
  //
  // Write the data from shared memory back across the idl interface:
  //
  memcpy((void *)data, (void *)&_output->data, sizeof(DvlIF::Data));
  //
  // Return an error if the serial line has a problem:
  //
  if( _output->data.badComms != 0 ) return DeviceIF::Error;
  //
  // If the DVL has a valid bottom lock, return OK
  //
  if((_output->data.bottomStatus == 0) && 
     ((_output->data.dataStatus & BAD_BOTTOM_TRACK_VELOCITY) !=
                                  BAD_BOTTOM_TRACK_VELOCITY)  )
    return DeviceIF::Ok;
  //
  // Or, if the DVL is tracking water mass velocity, return OK
  //
  if((_output->data.waterStatus == 0) && 
     ((_output->data.dataStatus & BAD_WATER_MASS_VELOCITY) !=
                                  BAD_WATER_MASS_VELOCITY)  )
    return DeviceIF::Ok;
  //
  // Otherwise, tell Navigation that the DVL reading is in error.
  //
  return DeviceIF::Error;
}


int DvlServer::spawnAuxTasks()
{
  char *program = (char *)_driverName;

  char errorBuf[256];
  char buf[256];
 
  pid_t pid;
 
  switch ((pid = fork())) {
     
  case 0:
    // In child
    // Execute server program
    execlp(program, program, "-serial", _serialParams->string(), 0);

    sprintf(errorBuf, 
	    "Task::spawnServer() - execlp() of \"%s\" failed", program);

    perror(errorBuf);
 
    break;

  case -1:
    perror("Task::spawnServer() - fork() failed");
    return -1;
  }

  return 0;
}
