/*
$Log: MotorMicro.cc,v $
Revision 1.6  1998/12/18 21:17:07  oreilly
Add SemiMotor

Revision 1.5  1997/10/03 09:31:16  oreilly
*** empty log message ***

Revision 1.4  97/09/10  08:36:38  08:36:38  oreilly (Thomas C. O'Reilly)
Removed debugging

Revision 1.3  97/08/12  14:49:26  14:49:26  oreilly (Thomas C. O'Reilly)
*** empty log message ***

Revision 1.2  97/05/30  16:30:05  16:30:05  oreilly (Thomas C. O'Reilly)
*** empty log message ***

Revision 1.1  97/05/06  16:29:30  16:29:30  oreilly (Thomas C. O'Reilly)
Initial revision

*/
#include <stdlib.h>
#include <Xm/Form.h>
#include <Xm/RowColumn.h>
#include <Xm/Label.h>
#include <Xm/PushB.h>
#include <Xm/Separator.h>
#include <Xm/Frame.h>
#include <Vk/VkQuestionDialog.h>
#include <Vk/VkErrorDialog.h>
#include "MotorMicro.h"
#include "TiburonApp.h"
#include "Micro.h"
#include "moogThrusterDM.h"
#include "DmErrno.h"
#include "parseUtils.h"
#include "DataRates.h"


MotorMicro::MotorMicro(const char *name, const char *dmPrefix)
  : Micro(name, dmPrefix)
{
  motorDm = new MotorDm(name, dmPrefix);
  if (motorDm->error())
  {
    char errorBuf[errorMsgSize];
    motorDm->errorMsg(errorBuf);
    setError(errorBuf);
    return;
  }
}


MotorMicro::~MotorMicro()
{
}


MicroGui *MotorMicro::gui(Widget parent, int period)
{
  MotorMicroGui *gui = new MotorMicroGui(_name, parent, this, period);
  gui->show();
  return gui;
}


MicroH2OTemp *MotorMicro::h2OTemp(Widget parent, int period)
{
  MotorH2OTemp *gui = new MotorH2OTemp(_name, parent, this, period);
  gui->show();
  return gui;
}


MotorH2OTemp::MotorH2OTemp(const char *name, Widget parent, 
			   MotorMicro *motorMicro, 
			   int period)
  : MicroH2OTemp(name, parent)
{
  MotorDm *motorDm = motorMicro->motorDm;
  
  /* Find alarm items */
  SystemAlarms *alarms = ((TiburonApp *)theApplication)->systemAlarms;
  
  char alarmName[MaxDmNameLen];
  char errorBuf[errorMsgSize];
  
  strcpy(alarmName, (const char *)motorDm->dmPrefix());
  
  char *alarmNamePtr = alarmName + strlen(alarmName);

  strcpy(alarmNamePtr, TEMPERATURE_ALARM_DM);  
  Alarm *tempAlarm;
  if ((tempAlarm = alarms->find(alarmName)) == NULL)
  {
    sprintf(errorBuf,
	    "MotorH2OTemp::MotorH2OTemp() - couldn't find alarm \"%s\"",
	    alarmName);
    
    theErrorDialog->postAndWait(errorBuf);
  }

  strcpy(alarmNamePtr, WATER_ALARM_DM);  
  Alarm *waterAlarm;
  if ((waterAlarm = alarms->find(alarmName)) == NULL)
  {
    sprintf(errorBuf,
	    "MotorH2OTemp::MotorH2OTemp() - couldn't find alarm \"%s\"",
	    alarmName);

    theErrorDialog->postAndWait(errorBuf);
  }

  Widget nameWidget =
    XtVaCreateManagedWidget(name, xmLabelWidgetClass, _row->baseWidget(),
			    NULL);			    

  _row->append(nameWidget);
  
  _temp = 
    new AlarmedInt16Text("temperature", _row->baseWidget(), "%-3.0f C", 
			 motorDm->microTemp, period, tempAlarm, Dynamic); 

  _row->append(_temp);
  
  Widget nA = 
    XtVaCreateManagedWidget("notApplicable", xmLabelWidgetClass, 
			    _row->baseWidget(), 
			    NULL);
  _row->append(nA);
  
  _housingWater = 
    new AlarmText("housingWater", _row->baseWidget(), waterAlarm, "%s");

  _row->append(_housingWater);
  

  nA = 
    XtVaCreateManagedWidget("notApplicable", xmLabelWidgetClass, 
			    _row->baseWidget(), 
			    NULL);

  _row->append(nA);

  _row->show();
}


MotorH2OTemp::~MotorH2OTemp()
{
}


VkMenuDesc MotorMicroGui::_regenLimitModeMenuDesc[] = 
{ 
  {ACTION, "disabled", &MotorMicroGui::regenLimitDisabledCallback},
  {ACTION, "enabled", &MotorMicroGui::regenLimitEnabledCallback},
  {END}
};    


VkMenuDesc MotorMicroGui::_cntrlModeMenuDesc[] = 
{ 
  {ACTION, "current", &MotorMicroGui::currentCntrlModeCallback},
  {ACTION, "torque", &MotorMicroGui::torqueCntrlModeCallback},
  {ACTION, "velocity", &MotorMicroGui::velocityCntrlModeCallback},
  {ACTION, "linearized", &MotorMicroGui::linearCntrlModeCallback},
  {END}
};    
  

MotorMicroGui::Values::Values()
{
  nvRamDate = motorSerialNo = NULL;
}


MotorMicroGui::Values::~Values()
{
  if (nvRamDate) free(nvRamDate);
  if (motorSerialNo) free(motorSerialNo);
}


MotorMicroGui::MotorMicroGui(const char *name, Widget parent, 
			     MotorMicro *motor,
			     int period)
  : MbariMicroGui(name, parent, motor)
{
  _microTemp = 0;
  _nvRamCycles = 0;
  _nvRamInitialized = 0;
  _nvRamDate = 0;
  _velocity = 0;
  _status = 0;
  _cmdThrust = 0;
  _cmdPower = 0;

  _cntrlMode = 0;
  _regenLimitMode = 0;
  _torqueOffset = 0;
  _currentGain = 0;
  _torqueGain = 0;

  int i;
  for (i = 0; i < VELOCITY_GAIN_SIZE; i++)
    _velocityGains[i] = 0;
  
  for (i = 0; i < LINEARIZED_GAIN_SIZE; i++)
    _linearGains[i] = 0;
  
  _modelParamK4 = 0;
  _regenLimit = 0;

  if (error())
    return;
  
  _motorMicro = motor;

  Widget label;

  TableRowForm *mgr;
  mgr = new TableRowForm("mgr", _baseWidget, 2);
  
  Widget button = 
    XtVaCreateManagedWidget("nvRamWrite", xmPushButtonWidgetClass, 
			    mgr->baseWidget(), NULL);

  XtAddCallback(button, XmNactivateCallback, 
		&MotorMicroGui::nvRamWriteCallback, (XtPointer )this);
		
  mgr->append(button);
  mgr->show();

  mgr = new TableRowForm("mgr", _baseWidget, 2);

  label = 
    XtVaCreateManagedWidget("motorVelocityLabel", xmLabelWidgetClass, 
			    mgr->baseWidget(),
			    NULL);

  _velocity = new DynamicLabel("velocity", mgr->baseWidget(),
			       XmALIGNMENT_BEGINNING); 

  mgr->append(label);
  mgr->append(_velocity);
  _velocity->show();
  mgr->show();

  mgr = new TableRowForm("mgr", _baseWidget, 2);
  
  label = 
    XtVaCreateManagedWidget("cmdThrustLabel", xmLabelWidgetClass, 
			    mgr->baseWidget(), NULL);

  _cmdThrust = new DynamicLabel("cmdThrust", mgr->baseWidget(), 
				XmALIGNMENT_BEGINNING);
  
  mgr->append(label);
  mgr->append(_cmdThrust);
  _cmdThrust->show();
  mgr->show();

  mgr = new TableRowForm("mgr", _baseWidget, 2);
  
  label = 
    XtVaCreateManagedWidget("cmdPowerLabel", xmLabelWidgetClass, 
			    mgr->baseWidget(), NULL);
  
  _cmdPower = new DynamicLabel("cmdPower", mgr->baseWidget(), 
			       XmALIGNMENT_BEGINNING);

  mgr->append(label);
  mgr->append(_cmdPower);
  _cmdPower->show();
  mgr->show();

  mgr = new TableRowForm("mgr", _baseWidget, 2);
    
  label = 
    XtVaCreateManagedWidget("microTempLabel", xmLabelWidgetClass, 
			    mgr->baseWidget(), NULL);

  _microTemp = new DynamicLabel("microTemp", mgr->baseWidget(), 
				XmALIGNMENT_BEGINNING);

  mgr->append(label);
  mgr->append(_microTemp);
  _microTemp->show();
  mgr->show();

  mgr = new TableRowForm("mgr", _baseWidget, 2);
  
  label = 
    XtVaCreateManagedWidget("nvRamDateLabel", xmLabelWidgetClass, 
			    mgr->baseWidget(), NULL);

  _nvRamDate = new DynamicLabel("nvRamDate", mgr->baseWidget(), 
				XmALIGNMENT_BEGINNING);

  mgr->append(label);
  mgr->append(_nvRamDate);
  _nvRamDate->show();
  mgr->show();

  mgr = new TableRowForm("mgr", _baseWidget, 2);

  label = 
    XtVaCreateManagedWidget("nvRamCyclesLabel", xmLabelWidgetClass, 
			    mgr->baseWidget(), NULL);
  
  _nvRamCycles = new DynamicLabel("nvRamCycles", mgr->baseWidget(), 
				  XmALIGNMENT_BEGINNING);
  
  mgr->append(label);
  mgr->append(_nvRamCycles);
  _nvRamCycles->show();
  mgr->show();

  mgr = new TableRowForm("mgr", _baseWidget, 2);

  label = 
    XtVaCreateManagedWidget("nvRamInitializedLabel", xmLabelWidgetClass, 
			    mgr->baseWidget(),
			    NULL);

  _nvRamInitialized = new DynamicLabel("nvRamInitialized", mgr->baseWidget(), 
				       XmALIGNMENT_BEGINNING);

  mgr->append(label);
  mgr->append(_nvRamInitialized);
  mgr->show();

  mgr = new TableRowForm("mgr", _baseWidget, 2);

  label = 
    XtVaCreateManagedWidget("regenLimitModeLabel", xmLabelWidgetClass, 
			    mgr->baseWidget(),
			    NULL);
  
  _regenLimitMode = new VkOptionMenu(mgr->baseWidget(),
				     "regenLimitMode", 
				     _regenLimitModeMenuDesc,
				     (XtPointer )this);

  mgr->append(label);
  mgr->append(_regenLimitMode);
  _regenLimitMode->show();
  mgr->show();

  mgr = new TableRowForm("mgr", _baseWidget, 2);

  label = 
    XtVaCreateManagedWidget("regenLimitLabel", xmLabelWidgetClass, 
			    mgr->baseWidget(), NULL);
  
  _regenLimit = new TextField("regenLimit", mgr->baseWidget());
  _regenLimit->setColumns(TextFieldWidth);
  _regenLimit->addCallback(TextField::acceptCallback, this,
			   (VkCallbackMethod )&MotorMicroGui::writeValue);

  mgr->append(label);
  mgr->append(_regenLimit);
  _regenLimit->show();
  mgr->show();

  mgr = new TableRowForm("mgr", _baseWidget, 2);

  label = 
    XtVaCreateManagedWidget("motorStatusLabel", xmLabelWidgetClass, 
			    mgr->baseWidget(), NULL);
  
  _status = new DynamicLabel("motorStatus", mgr->baseWidget(), 
			     XmALIGNMENT_BEGINNING);

  mgr->append(label);
  mgr->append(_status);
  mgr->show();

  mgr = new TableRowForm("mgr", _baseWidget, 2);

  label = 
    XtVaCreateManagedWidget("motorSerialNoLabel", xmLabelWidgetClass, 
			    mgr->baseWidget(),
			    NULL);
  
  _motorSerialNo = 
    XtVaCreateManagedWidget("motorSerialNo", xmLabelWidgetClass, 
			    mgr->baseWidget(),
			    NULL);

  mgr->append(label);
  mgr->append(_motorSerialNo);
  mgr->show();

  mgr = new TableRowForm("mgr", _baseWidget, 2);

  label = 
    XtVaCreateManagedWidget("motorCntrlModeLabel", xmLabelWidgetClass, 
			    mgr->baseWidget(),
			    NULL);
  
  _cntrlMode = new VkOptionMenu(mgr->baseWidget(),
				"cntrlMode", 
				_cntrlModeMenuDesc,
				(XtPointer )this);
  mgr->append(label);
  mgr->append(_cntrlMode);
  mgr->show();

  mgr = new TableRowForm("mgr", _baseWidget, 2);

  label = 
    XtVaCreateManagedWidget("motorCurrentGainLabel", xmLabelWidgetClass, 
			    mgr->baseWidget(),
			    NULL);
  
  _currentGain = new TextField("currentGain", mgr->baseWidget());
  _currentGain->setColumns(TextFieldWidth);
  _currentGain->addCallback(TextField::acceptCallback, this,
			    (VkCallbackMethod )&MotorMicroGui::writeValue);

  mgr->append(label);
  mgr->append(_currentGain);
  mgr->show();

  mgr = new TableRowForm("mgr", _baseWidget, 2);

  label = 
    XtVaCreateManagedWidget("motorTorqueGainLabel", xmLabelWidgetClass, 
			    mgr->baseWidget(),
			    NULL);
  
  _torqueGain = new TextField("torqueGain", mgr->baseWidget());
  _torqueGain->setColumns(TextFieldWidth);

  _torqueGain->addCallback(TextField::acceptCallback, this,
			   (VkCallbackMethod )&MotorMicroGui::writeValue);

  mgr->append(label);
  mgr->append(_torqueGain);
  mgr->show();

  mgr = new TableRowForm("mgr", _baseWidget, 2);

  label = 
    XtVaCreateManagedWidget("motorTorqueOffsetLabel", xmLabelWidgetClass, 
			    mgr->baseWidget(),
			    NULL);
  
  _torqueOffset = new TextField("torqueOffset", mgr->baseWidget());
  _torqueOffset->setColumns(TextFieldWidth);

  _torqueOffset->addCallback(TextField::acceptCallback, this,
			     (VkCallbackMethod )&MotorMicroGui::writeValue);
  mgr->append(label);
  mgr->append(_torqueOffset);
  mgr->show();

  
  XtVaCreateManagedWidget("velocityModeGainsLabel", xmLabelWidgetClass,
			  _baseWidget, NULL);

  char buf[512];

  for (i = 0; i < VELOCITY_GAIN_SIZE; i++)
  {
    mgr = new TableRowForm("mgr", _baseWidget, 2);
    sprintf(buf, "velocityGainsLabel%d", i);
    label = XtVaCreateManagedWidget(buf, xmLabelWidgetClass, 
				    mgr->baseWidget(), NULL);

    sprintf(buf, "velocityGains%d", i);

    _velocityGains[i] = new TextField(buf, mgr->baseWidget());
    _velocityGains[i]->setColumns(TextFieldWidth);
    _velocityGains[i]->addCallback(TextField::acceptCallback, this,
				   (VkCallbackMethod )
				   &MotorMicroGui::writeValue);

    mgr->append(label);
    mgr->append(_velocityGains[i]);
    mgr->show();
  }

  XtVaCreateManagedWidget("linearizedModeGainsLabel", xmLabelWidgetClass, 
			  _baseWidget,
			  NULL);				    

  for (i = 0; i < LINEARIZED_GAIN_SIZE; i++)
  {
    mgr = new TableRowForm("mgr", _baseWidget, 2);
    sprintf(buf, "linearizedGainsLabel%d", i);
    label = XtVaCreateManagedWidget(buf, xmLabelWidgetClass, 
				    mgr->baseWidget(), NULL);

    sprintf(buf, "linearizedGains%d", i);

    _linearGains[i] = new TextField(buf, mgr->baseWidget());
    _linearGains[i]->setColumns(TextFieldWidth);
    _linearGains[i]->addCallback(TextField::acceptCallback, this,
				 (VkCallbackMethod )&MotorMicroGui::writeValue);

    mgr->append(label);
    mgr->append(_linearGains[i]);
    mgr->show();
  }
  
  mgr = new TableRowForm("mgr", _baseWidget, 2);
  label = 
    XtVaCreateManagedWidget("modelParamK4Label", xmLabelWidgetClass, 
			    mgr->baseWidget(),
			    NULL);
  
  _modelParamK4 = new TextField("modelParamK4", mgr->baseWidget());
  _modelParamK4->setColumns(TextFieldWidth);
  _modelParamK4->addCallback(TextField::acceptCallback, this,
			     (VkCallbackMethod )&MotorMicroGui::writeValue);

  mgr->append(label);
  mgr->append(_modelParamK4);
  mgr->show();

  
  addDmObject(_motorMicro->motorDm->microTemp, DmConsumeFlag);
  addDmObject(_motorMicro->motorDm->velocity, DmConsumeFlag);
  addDmObject(_motorMicro->motorDm->status, DmConsumeFlag);

  addDmObject(_motorMicro->motorDm->nvRamCycles, DmConsumeFlag);
  addDmObject(_motorMicro->motorDm->nvRamInitialized, DmConsumeFlag);
  addDmObject(_motorMicro->motorDm->nvRamDate, DmConsumeFlag);

  addDmObject(_motorMicro->motorDm->nvRamWrite, DmProvideFlag);

  addDmObject(_motorMicro->motorDm->motorSerialNo, DmConsumeFlag);

  addDmObject(_motorMicro->motorDm->cntrlMode, DmConsumeFlag | DmProvideFlag);
  addDmObject(_motorMicro->motorDm->cmdThrust, DmConsumeFlag);
  addDmObject(_motorMicro->motorDm->cmdPower, DmConsumeFlag);
  addDmObject(_motorMicro->motorDm->currentGain, 
	      DmConsumeFlag | DmProvideFlag);

  addDmObject(_motorMicro->motorDm->torqueGain, DmConsumeFlag | DmProvideFlag);
  addDmObject(_motorMicro->motorDm->torqueOffset, 
	      DmConsumeFlag | DmProvideFlag);

  addDmObject(_motorMicro->motorDm->velocityGains, 
	      DmConsumeFlag | DmProvideFlag);

  addDmObject(_motorMicro->motorDm->linearGains, 
	      DmConsumeFlag | DmProvideFlag);

  addDmObject(_motorMicro->motorDm->modelParamK4, 
	      DmConsumeFlag | DmProvideFlag);

  addDmObject(_motorMicro->motorDm->regenLimitMode, 
	      DmConsumeFlag | DmProvideFlag);

  addDmObject(_motorMicro->motorDm->regenLimit, DmConsumeFlag | DmProvideFlag);
  addDmObject(_motorMicro->motorDm->rpmCalibrate, DmConsumeFlag);
  addDmObject(_motorMicro->motorDm->velBufEnable, DmConsumeFlag);
  addDmObject(_motorMicro->motorDm->velBufRead, DmConsumeFlag);

  setConsumePeriod(period);

  if (error()) {
    char errBuf[512];
    errorMsg(errBuf);
    theErrorDialog->postAndWait(errBuf);
  }

  _initial = True;
  updateGui();
  _initial = False;
}


MotorMicroGui::~MotorMicroGui()
{
  delete _microTemp;
  delete _nvRamCycles;
  delete _nvRamInitialized;
  delete _nvRamDate;
  delete _velocity;
  delete _status;
  delete _cmdThrust;
  delete _cmdPower;

  delete _cntrlMode;
  delete _regenLimitMode;
  delete _torqueOffset;
  delete _currentGain;
  delete _torqueGain;

  int i;
  
  for (i = 0; i < VELOCITY_GAIN_SIZE; i++)
    delete _velocityGains[i];
  
  for (i = 0; i < LINEARIZED_GAIN_SIZE; i++)
    delete _linearGains[i];
  
  delete _modelParamK4;
  delete _regenLimit;
}


void MotorMicroGui::updateGui(DM_Item handle)
{
  char buf[512];
  DM_Time t;
  Errno errno;
  char errorBuf[errorMsgSize];
  Nat16 n16value;
  Int16 i16value;
  Int32 i32value;
  Int16 gains[10];
  
  if ((errno = _motorMicro->motorDm->microTemp->read(&i16value, &t)) 
      != SUCCESS)
  {
    sprintDmError(errno, "MotorMicroGui::updateGui(), reading microTemp", 
		  errorBuf);

    setError(errorBuf);
  }
  else if (_initial || i16value != _values.microTemp)
  {
    sprintf(buf, "%d", i16value);
    _microTemp->setText(buf);
    _values.microTemp = i16value;
  }
  
  if ((errno = _motorMicro->motorDm->velocity->read(&i16value, &t)) != SUCCESS)
  {
    sprintDmError(errno, "MotorMicroGui::updateGui(), reading velocity", 
		  errorBuf);

    setError(errorBuf);
  }
  else if (_initial || i16value != _values.velocity)
  {
    sprintf(buf, "%d", i16value);
    _velocity->setText(buf);
    _values.velocity = i16value;
  }
  
  if ((errno = _motorMicro->motorDm->status->read(&i16value, &t)) != SUCCESS)
  {
    sprintDmError(errno, "MotorMicroGui::updateGui(), reading status", 
		  errorBuf);

    setError(errorBuf);
  }
  else if (_initial || i16value != _values.status)
  {
    switch (i16value)
    {
      case STATUS_UNKNOWN:
      strcpy(buf, MotorStatusAlarm::UnkStatusMnem);
      break;
    
      case MOTOR_NO_FAULT:
      strcpy(buf, MotorStatusAlarm::NoFaultMnem);
      break;
    
      case MOTOR_CONTROLLER_VOLTS:
      strcpy(buf, MotorStatusAlarm::ControlVoltMnem);
      break;
    
      case MOTOR_CONTROLLER_TEMP:
      strcpy(buf, MotorStatusAlarm::ControlTempMnem);
      break;
    
      case MOTOR_STALL:
      strcpy(buf, MotorStatusAlarm::StallMnem);
      break;
    
      case MOTOR_RESOLVER:
      strcpy(buf, MotorStatusAlarm::ResolverMnem);
      break;
    
      case MOTOR_OVERCURRENT:
      strcpy(buf, MotorStatusAlarm::OverCurrMnem);
      break;
    
      case MOTOR_FAULT:
      strcpy(buf, MotorStatusAlarm::FaultMnem);
      break;
    }
    _status->setText(buf);
    _values.status = i16value;
  }
  
  if ((errno = _motorMicro->motorDm->nvRamCycles->read(&n16value, &t)) 
      != SUCCESS)
  {
    sprintDmError(errno, "MotorMicroGui::updateGui(), reading nvRamCycles", 
		  errorBuf);

    setError(errorBuf);
  }
  else if (_initial || n16value != _values.nvRamCycles)
  {
    sprintf(buf, "%d", n16value);
    _nvRamCycles->setText(buf);
    _values.nvRamCycles = n16value;
  }
  
  if ((errno = _motorMicro->motorDm->nvRamDate->read(buf, &t)) != SUCCESS)
  {
    sprintDmError(errno, "MotorMicroGui::updateGui(), reading nvRamDate", 
		  errorBuf);

    setError(errorBuf);
  }
  else if (_initial || (_values.nvRamDate && strcmp(buf, _values.nvRamDate)))
  {
    _nvRamDate->setText(buf);
    if (_values.nvRamDate)
      free(_values.nvRamDate);
    
    _values.nvRamDate = strdup(buf);
  }
  
  if ((errno = _motorMicro->motorDm->motorSerialNo->read(buf, &t)) != SUCCESS)
  {
    sprintDmError(errno, "MotorMicroGui::updateGui(), reading motorSerialNo", 
		  errorBuf);

    setError(errorBuf);
  }
  else if (_initial || 
	   (_values.motorSerialNo && strcmp(buf, _values.motorSerialNo)))
  {
    XmString xmstr = XmStringCreateSimple(buf);
    XtVaSetValues(_motorSerialNo, XmNlabelString, xmstr, NULL);
    XmStringFree(xmstr);
    if (_values.motorSerialNo)
      free(_values.motorSerialNo);
    
    _values.motorSerialNo = strdup(buf);
  }
  
  if ((errno = _motorMicro->motorDm->cntrlMode->read(&i32value, &t)) 
      != SUCCESS)
  {
    sprintDmError(errno, "MotorMicroGui::updateGui(), reading cntrlMode", 
		  errorBuf);

    setError(errorBuf);
  }
  else if (_initial || i32value != _values.cntrlMode)
  {
    _cntrlMode->set((int )i32value);
    _values.cntrlMode = i32value;
  }
  
  if ((errno = _motorMicro->motorDm->cmdThrust->read(&i16value, &t)) 
      != SUCCESS)
  {
    sprintDmError(errno, "MotorMicroGui::updateGui(), reading cmdThrust", 
		  errorBuf);

    setError(errorBuf);
  }
  else if (_initial || i16value != _values.cmdThrust)
  {
    sprintf(buf, "%d", i16value);
    _cmdThrust->setText(buf);
    _values.cmdThrust = i16value;
  }
  
  if ((errno = _motorMicro->motorDm->cmdPower->read(&i16value, &t)) != SUCCESS)
  {
    sprintDmError(errno, "MotorMicroGui::updateGui(), reading cmdPower",
		  errorBuf);

    setError(errorBuf);
  }
  else if (_initial || i16value != _values.cmdPower)
  {
    sprintf(buf, "%d", i16value);
    _cmdPower->setText(buf);
    _values.cmdPower = i16value;
  }
  
  if ((errno = _motorMicro->motorDm->currentGain->read(&i16value, &t)) 
      != SUCCESS)
  {
    sprintDmError(errno, "MotorMicroGui::updateGui(), reading currentGain",
		  errorBuf);

    setError(errorBuf);
  }
  else if (_initial || i16value != _values.currentGain)
  {
    sprintf(buf, "%d", i16value);
    _currentGain->set(buf);
    _values.currentGain = i16value;
  }
  
  if ((errno = _motorMicro->motorDm->torqueGain->read(&i16value, &t)) 
      != SUCCESS)
  {
    sprintDmError(errno, "MotorMicroGui::updateGui(), reading torqueGain", 
		  errorBuf);

    setError(errorBuf);
  }
  else if (_initial || i16value != _values.torqueGain)
  {
    sprintf(buf, "%d", i16value);
    _torqueGain->set(buf);
    _values.torqueGain = i16value;
  }
  
  if ((errno = _motorMicro->motorDm->torqueOffset->read(&i16value, &t)) 
      != SUCCESS)
  {
    sprintDmError(errno, "MotorMicroGui::updateGui(), reading torqueOffset", 
		  errorBuf);

    setError(errorBuf);
  }
  else if (_initial || i16value != _values.torqueOffset)
  {
    sprintf(buf, "%d", i16value);
    _torqueOffset->set(buf);
    _values.torqueOffset = i16value;
  }

  int index;
  
  if ((errno = 
       _motorMicro->motorDm->velocityGains->read(gains, &t)) 
      != SUCCESS)
  {
    sprintDmError(errno, "MotorMicroGui::updateGui(), reading velocityGains",
		  errorBuf);

    setError(errorBuf);
  } 
  else
  {
    for (index = 0; index < VELOCITY_GAIN_SIZE; index++)
    {
      if (_initial || gains[index] != _values.velocityGains[index])
      {
	sprintf(buf, "%d", gains[index]);
	_velocityGains[index]->set(buf);
	_values.velocityGains[index] = gains[index];
      }
    }
  }
  
  if ((errno = _motorMicro->motorDm->linearGains->read(gains, &t))
      != SUCCESS)
  {
    sprintDmError(errno, "MotorMicroGui::updateGui(), reading linearGains",
		  errorBuf);

    setError(errorBuf);
  } 
  else
  {
    for (index = 0; index < LINEARIZED_GAIN_SIZE; index++)
    {
      if (_initial || gains[index] != _values.linearGains[index])
      {
	sprintf(buf, "%d", gains[index]);
	_linearGains[index]->set(buf);
	_values.linearGains[index] = gains[index];
      }
    }
  }
  
  if ((errno = _motorMicro->motorDm->modelParamK4->read(&i16value, &t)) 
      != SUCCESS)
  {
    sprintDmError(errno, "MotorMicroGui::updateGui(), reading modelParamK4",
		  errorBuf);

    setError(errorBuf);
  } 
  else if (_initial || i16value != _values.modelParamK4)
  {
    sprintf(buf, "%d", i16value);
    _modelParamK4->set(buf);
    _values.modelParamK4 = i16value;
  }
  
  MBool boolValue;
  
  if ((errno = _motorMicro->motorDm->regenLimitMode->read(&boolValue, &t)) 
      != SUCCESS)
  {
    sprintDmError(errno, 
		  "MotorMicroGui::updateGui(), reading regenLimitMode",
		  errorBuf);

    setError(errorBuf);
  } 
  else if (_initial || (boolValue != _values.regenLimitMode))
  {
    if (boolValue)
      _regenLimitMode->set(1);
    else
      _regenLimitMode->set(0);

    _values.regenLimitMode = boolValue;
  }
  
  if ((errno = _motorMicro->motorDm->regenLimit->read(&n16value, &t)) 
      != SUCCESS)
  {
    sprintDmError(errno, "MotorMicroGui::updateGui(), reading regenLimit",
		  errorBuf);

    setError(errorBuf);
  }
  else if (_initial || n16value != _values.regenLimit)
  {
    sprintf(buf, "%d", n16value);
    _regenLimit->set(buf);
    _values.regenLimit = n16value;
  }
}


void MotorMicroGui::writeRegenLimitMode(MBool enabled)
{
  DM_Time t;
  t.tv_sec = time(NULL);
  t.tv_usec = 0;
  _motorMicro->motorDm->regenLimitMode->write(enabled, &t);
}


void MotorMicroGui::writeCntrlMode(motorCtrlMode mode)
{
  int value = (int )mode;
  
  DM_Time t;
  t.tv_sec = time(NULL);
  t.tv_usec = 0;
  _motorMicro->motorDm->cntrlMode->write(mode, &t);
}


void MotorMicroGui::nvRamWrite()
{
  DM_Time t;
  t.tv_sec = time(NULL);
  t.tv_usec = 0;

  _motorMicro->motorDm->nvRamWrite->write(&t);    
}


void MotorMicroGui::writeValue(VkCallbackObject *obj,
			       void *clientData,
			       void *callData)
{
  DM_Time t;
  t.tv_sec = time(NULL);
  t.tv_usec = 0;
  Errno errno;
  char errorBuf[errorMsgSize];
  
  MBool debug = FALSE;
  dprintf(stderr, "MotorMicroGui::writeValue()\n");
  Int16 i16Value;
  Int16 gains[5];
  Nat16 n16Value;
  
  if (obj == _currentGain)
  {
    i16Value = atoi(_currentGain->get());
    errno = _motorMicro->motorDm->currentGain->write(i16Value, &t);
  }
  else if (obj == _torqueGain)
  {
    i16Value = atoi(_torqueGain->get());
    errno = _motorMicro->motorDm->torqueGain->write(i16Value, &t);    
  }
  else if (obj == _velocityGains[0] ||
	   obj == _velocityGains[1] ||
	   obj == _velocityGains[2])
  {
    gains[0] = atoi(_velocityGains[0]->get());
    gains[1] = atoi(_velocityGains[1]->get());
    gains[2] = atoi(_velocityGains[2]->get());    
    errno = _motorMicro->motorDm->velocityGains->write(gains, &t);    
  }
  else if (obj == _linearGains[0] ||
	   obj == _linearGains[1])
  {
    gains[0] = atoi(_linearGains[0]->get());
    gains[1] = atoi(_linearGains[1]->get());
    errno = _motorMicro->motorDm->linearGains->write(gains, &t);    
  }
  else if (obj == _modelParamK4)
  {
    i16Value = atoi(_modelParamK4->get());
    errno = _motorMicro->motorDm->modelParamK4->write(i16Value, &t); 
  }
  else if (obj == _regenLimit)
  {
    n16Value = atoi(_regenLimit->get());
    errno = _motorMicro->motorDm->regenLimit->write(n16Value, &t); 
  }
  else if (obj == _torqueOffset)
  {
    i16Value = atoi(_torqueOffset->get());
    errno = _motorMicro->motorDm->torqueOffset->write(i16Value, &t);
  }
  else
  {
    fprintf(stderr, "MotorMicroGui::writeValue() - unknown object\n");
    return;
  }

  if (errno != SUCCESS)
  {
    sprintDmError(errno, "MotorMicroGui::writeValue()", errorBuf);
    theErrorDialog->postAndWait(errorBuf);
  }
}



void MotorMicroGui::regenLimitEnabledCallback(Widget w,
					      XtPointer clientData,
					      XtPointer callData)
{
  MotorMicroGui *obj = (MotorMicroGui *)clientData;
  obj->writeRegenLimitMode(TRUE);
}


void MotorMicroGui::regenLimitDisabledCallback(Widget w,
					       XtPointer clientData,
					       XtPointer callData)
{
  MotorMicroGui *obj = (MotorMicroGui *)clientData;
  obj->writeRegenLimitMode(FALSE);
}


void MotorMicroGui::currentCntrlModeCallback(Widget w,
					     XtPointer clientData,
					     XtPointer callData)
{
  MotorMicroGui *obj = (MotorMicroGui *)clientData;
  obj->writeCntrlMode(CURRENT);
}


void MotorMicroGui::torqueCntrlModeCallback(Widget w,
					    XtPointer clientData,
					    XtPointer callData)
{
  MotorMicroGui *obj = (MotorMicroGui *)clientData;
  obj->writeCntrlMode(TORQUE);
}


void MotorMicroGui::velocityCntrlModeCallback(Widget w,
					      XtPointer clientData,
					      XtPointer callData)
{
  MotorMicroGui *obj = (MotorMicroGui *)clientData;
  obj->writeCntrlMode(VELOCITY);
}


void MotorMicroGui::linearCntrlModeCallback(Widget w,
					    XtPointer clientData,
					    XtPointer callData)
{
  MotorMicroGui *obj = (MotorMicroGui *)clientData;
  obj->writeCntrlMode(LINEARIZED);
}


void MotorMicroGui::nvRamWriteCallback(Widget w, 
				       XtPointer clientData, 
				       XtPointer callData)
{
  if (theQuestionDialog->postAndWait("Really write to Micro's NVRAM?") 
      == VkDialogManager::OK)
  {
    MotorMicroGui *obj = (MotorMicroGui *)clientData;
    obj->nvRamWrite();
  }
}
