/*
$Log: SemiMotorMicro.cc,v $
Revision 1.1  1998/12/18 21:19:07  oreilly
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 <sys/param.h>
#include "SemiMotorMicro.h"
#include "TiburonApp.h"
#include "Micro.h"
#include "thrusterDM.h"
#include "DmErrno.h"
#include "parseUtils.h"
#include "DataRates.h"


SemiMotorMicro::SemiMotorMicro(const char *name, const char *dmPrefix)
  : Micro(name, dmPrefix)
{
  motorDm = new SemiMotorDm(name, dmPrefix);
  if (motorDm->error())
  {
    char errorBuf[errorMsgSize];
    motorDm->errorMsg(errorBuf);
    setError(errorBuf);
    return;
  }
}


SemiMotorMicro::~SemiMotorMicro()
{
}


MicroGui *SemiMotorMicro::gui(Widget parent, int period)
{
  SemiMotorMicroGui *gui = new SemiMotorMicroGui(_name, parent, this, period);
  gui->show();
  return gui;
}


MicroH2OTemp *SemiMotorMicro::h2OTemp(Widget parent, int period)
{
  SemiMotorH2OTemp *gui = new SemiMotorH2OTemp(_name, parent, this, period);
  gui->show();
  return gui;
}


SemiMotorH2OTemp::SemiMotorH2OTemp(const char *name, Widget parent, 
				   SemiMotorMicro *motorMicro, 
				   int period)
  : MicroH2OTemp(name, parent)
{
  SemiMotorDm *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,
	    "SemiMotorH2OTemp::SemiMotorH2OTemp() - "
	    "couldn't find alarm \"%s\"",
	    alarmName);
    
    theErrorDialog->postAndWait(errorBuf);
  }

  strcpy(alarmNamePtr, HUMIDITY_ALARM_DM);  
  Alarm *humidityAlarm;
  if ((humidityAlarm = alarms->find(alarmName)) == NULL)
  {
    sprintf(errorBuf,
	    "SemiMotorH2OTemp::SemiMotorH2OTemp() - "
	    "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->heatSinkTemp, period, tempAlarm, Dynamic); 

  _row->append(_temp);
  
  _humidity = 
    new AlarmedNat16Text("humidity", _row->baseWidget(), "%-3.0f %", 
			 motorDm->humidity, period, humidityAlarm, Dynamic); 

  _row->append(_humidity);
  

  Widget nA = 
    XtVaCreateManagedWidget("notApplicable", xmLabelWidgetClass, 
			    _row->baseWidget(), 
			    NULL);
  _row->append(nA);
  

  nA = 
    XtVaCreateManagedWidget("notApplicable", xmLabelWidgetClass, 
			    _row->baseWidget(), 
			    NULL);

  _row->append(nA);

  _row->show();
}


SemiMotorH2OTemp::~SemiMotorH2OTemp()
{
}


VkMenuDesc SemiMotorMicroGui::_cntrlModeMenuDesc[] = 
{ 
  {ACTION, "current", &SemiMotorMicroGui::currentCntrlModeCallback},
  {ACTION, "torque", NULL},
  {ACTION, "velocity", &SemiMotorMicroGui::velocityCntrlModeCallback},
  {ACTION, "semi", &SemiMotorMicroGui::semiCntrlModeCallback},
  {END}
};    
  

SemiMotorMicroGui::Values::Values()
{
}


SemiMotorMicroGui::Values::~Values()
{
}


SemiMotorMicroGui::SemiMotorMicroGui(const char *name, Widget parent, 
				     SemiMotorMicro *motor,
				     int period)
  : MicroGui(name, parent, motor)
{
  char buf[512];

  _heatSinkTemp = 0;
  _humidity = 0;
  _velocity = 0;
  _status = 0;
  _cmdThrust = 0;
  _cntrlMode = 0;
  _currentGain = 0;

  int i;
  for (i = 0; i < VELOCITY_GAIN_SIZE; i++)
    _velocityGains[i] = 0;
  
  _modelParamK4 = 0;

  if (error())
    return;
  
  _motorMicro = motor;

  Widget label;
  Widget frame;
  Widget mgr2;

  TableRowForm *mgr;
  
  /* Find alarm items */
  SystemAlarms *alarms = ((TiburonApp *)theApplication)->systemAlarms;

  char alarmName[MaxDmNameLen];
  char errorBuf[errorMsgSize];
  
  strcpy(alarmName, (const char *)_motorMicro->motorDm->dmPrefix());
  
  char *alarmNamePtr = alarmName + strlen(alarmName);

  strcpy(alarmNamePtr, TEMPERATURE_ALARM_DM);  
  Alarm *tempAlarm;
  if ((tempAlarm = alarms->find(alarmName)) == NULL)
  {
    sprintf(errorBuf,
	    "SemiMotorH2OTemp::SemiMotorH2OTemp() - "
	    "couldn't find alarm \"%s\"",
	    alarmName);
    
    theErrorDialog->postAndWait(errorBuf);
  }

  strcpy(alarmNamePtr, HUMIDITY_ALARM_DM);  
  Alarm *humidityAlarm;
  if ((humidityAlarm = alarms->find(alarmName)) == NULL)
  {
    sprintf(errorBuf,
	    "SemiMotorH2OTemp::SemiMotorH2OTemp() - "
	    "couldn't find alarm \"%s\"",
	    alarmName);

    theErrorDialog->postAndWait(errorBuf);
  }

  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("torqueLabel", xmLabelWidgetClass, 
			    mgr->baseWidget(),
			    NULL);

  _torque = 
    new DynamicLabel("torque", mgr->baseWidget(), XmALIGNMENT_BEGINNING);

  mgr->append(label);
  mgr->append(_torque);
  mgr->show();


  mgr = new TableRowForm("mgr", _baseWidget, 2);

  label = 
    XtVaCreateManagedWidget("motorCurrentLabel", xmLabelWidgetClass,
			    mgr->baseWidget(), NULL);

  _current = new DynamicLabel("current", mgr->baseWidget(), 
			      XmALIGNMENT_BEGINNING);

  _current->show();

  mgr->append(label);
  mgr->append(_current);
  mgr->show();


  mgr = new TableRowForm("mgr", _baseWidget, 2);

  label = 
    XtVaCreateManagedWidget("inputVoltageLabel", xmLabelWidgetClass,
			    mgr->baseWidget(), NULL);

  _inputVoltage = new DynamicLabel("inputVoltage", mgr->baseWidget(), 
			      XmALIGNMENT_BEGINNING);

  _inputVoltage->show();

  mgr->append(label);
  mgr->append(_inputVoltage);
  mgr->show();

  mgr = new TableRowForm("mgr", _baseWidget, 2);
    
  label = 
    XtVaCreateManagedWidget("heatSinkTempLabel", xmLabelWidgetClass, 
			    mgr->baseWidget(), NULL);

  _heatSinkTemp = 
    new AlarmedInt16Text("heatSinkTemp", mgr->baseWidget(), "%-3.0f", 
			 _motorMicro->motorDm->heatSinkTemp, period, 
			 tempAlarm, Dynamic); 

  mgr->append(label);
  mgr->append(_heatSinkTemp);
  _heatSinkTemp->show();
  mgr->show();

  mgr = new TableRowForm("mgr", _baseWidget, 2);

  label = 
    XtVaCreateManagedWidget("humidityLabel", xmLabelWidgetClass, 
			    mgr->baseWidget(), NULL);

  _humidity = 
    new AlarmedNat16Text("humidity", mgr->baseWidget(), "%-3.0f", 
			 _motorMicro->motorDm->humidity, period, 
			 humidityAlarm, Dynamic); 

  mgr->append(label);
  mgr->append(_humidity);
  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("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("outputPowerLabel", xmLabelWidgetClass,
			    mgr->baseWidget(), NULL);

  _outputPower = new DynamicLabel("outputPower", mgr->baseWidget(), 
				 XmALIGNMENT_BEGINNING);

  mgr->append(label);
  mgr->append(_outputPower);
  _outputPower->show();
  mgr->show();

  mgr = new TableRowForm("mgr", _baseWidget, 2);

  label = 
    XtVaCreateManagedWidget("elapsedHoursLabel", xmLabelWidgetClass,
			    mgr->baseWidget(), NULL);

  _elapsedHours = 
    XtVaCreateManagedWidget("elapsedHours", xmLabelWidgetClass,
			    mgr->baseWidget(), NULL);

  mgr->append(label);
  mgr->append(_elapsedHours);
  mgr->show();
  
  Widget mgr5;

  frame = XtVaCreateManagedWidget("frame", xmFrameWidgetClass, _baseWidget, 0);

  mgr5 = XtVaCreateWidget("mgr5", xmRowColumnWidgetClass, frame, 
			  XmNorientation, XmVERTICAL, 0);

  mgr = new TableRowForm("mgr", mgr5, 2);

  label = 
    XtVaCreateManagedWidget("faultCodeLabel", xmLabelWidgetClass, 
			    mgr->baseWidget(),
			    NULL);
  

  _faultCode = 
    XtVaCreateManagedWidget("faultCode", xmLabelWidgetClass,
			    mgr->baseWidget(), NULL);
			    
  mgr->append(label);
  mgr->append(_faultCode);
  mgr->show();

  mgr2 = XtVaCreateWidget("faultQueueMgr", xmRowColumnWidgetClass, mgr5,
			  XmNorientation, XmVERTICAL, 0);

  XtVaCreateManagedWidget("faultQueueLabel", xmLabelWidgetClass,
			  mgr2, NULL);

  sprintf(buf, "%8s %8s %8s %8s %8s",
	  "drvStat", "elpsd_t", "i_mag", "vdc", "rpm");

  XmString xmstr = XmStringCreateSimple(buf);

  XtVaCreateManagedWidget("header", xmLabelWidgetClass, mgr2,
			  XmNlabelString, xmstr, 0);

  XmStringFree(xmstr);

  for (i = 0; i < FAULT_QUEUE_LENGTH; i++) {
    _faultQueueEntry[i] = 
      XtVaCreateManagedWidget("fault", xmLabelWidgetClass, mgr2, 0);
  }

  Widget mgr3;
  mgr3 = XtVaCreateWidget("mgr3", xmRowColumnWidgetClass, mgr2,
			  XmNorientation, XmHORIZONTAL, 0);

  _readFaultQueue = XtVaCreateManagedWidget("readFaultQueue", 
					    xmPushButtonWidgetClass, mgr3, 0);

  XtAddCallback(_readFaultQueue, XmNactivateCallback,
		&SemiMotorMicroGui::faultQueueCallback, (XtPointer )this);

  _clearFaultQueue = XtVaCreateManagedWidget("clearFaultQueue", 
					     xmPushButtonWidgetClass, mgr3, 0);
  
  XtAddCallback(_clearFaultQueue, XmNactivateCallback,
		&SemiMotorMicroGui::faultQueueCallback, (XtPointer )this);

  XtManageChild(mgr3);
  XtManageChild(mgr2);
  XtManageChild(mgr5);

  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 )&SemiMotorMicroGui::writeValue);

  mgr->append(label);
  mgr->append(_currentGain);
  mgr->show();

  frame = XtVaCreateManagedWidget("frame", xmFrameWidgetClass, _baseWidget, 0);

  mgr2 = XtVaCreateWidget("mgr2", xmRowColumnWidgetClass, frame, 
			  XmNorientation, XmVERTICAL, 0);

  XtVaCreateManagedWidget("velocityModeGainsLabel", xmLabelWidgetClass,
			  mgr2, NULL);

  for (i = 0; i < VELOCITY_GAIN_SIZE; i++)
  {
    mgr = new TableRowForm("mgr", mgr2, 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 )
				   &SemiMotorMicroGui::writeValue);

    mgr->append(label);
    mgr->append(_velocityGains[i]);
    mgr->show();
  }

  XtManageChild(mgr2);

  XtVaCreateManagedWidget("linearizedModeGainsLabel", xmLabelWidgetClass, 
			  _baseWidget,
			  NULL);				    

  
  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 )&SemiMotorMicroGui::writeValue);

  mgr->append(label);
  mgr->append(_modelParamK4);
  mgr->show();

  addDmObject(_motorMicro->motorDm->heatSinkTemp, DmConsumeFlag);
  addDmObject(_motorMicro->motorDm->velocity, DmConsumeFlag);
  addDmObject(_motorMicro->motorDm->enableStatus, DmConsumeFlag);

  addDmObject(_motorMicro->motorDm->cntrlMode, DmConsumeFlag | DmProvideFlag);
  addDmObject(_motorMicro->motorDm->cmdThrust, DmConsumeFlag);
  addDmObject(_motorMicro->motorDm->currentGain, 
	      DmConsumeFlag | DmProvideFlag);

  addDmObject(_motorMicro->motorDm->velocityGains, 
	      DmConsumeFlag | DmProvideFlag);

  addDmObject(_motorMicro->motorDm->modelParamK4, 
	      DmConsumeFlag | DmProvideFlag);

  addDmObject(_motorMicro->motorDm->faultQueue, DmConsumeFlag);
  addDmObject(_motorMicro->motorDm->readFaultQueue, DmProvideFlag);
  addDmObject(_motorMicro->motorDm->clearFaultQueue, DmProvideFlag);
  addDmObject(_motorMicro->motorDm->current, DmConsumeFlag);
  addDmObject(_motorMicro->motorDm->faultCode, DmConsumeFlag);
  addDmObject(_motorMicro->motorDm->inputVoltage, DmConsumeFlag);
  addDmObject(_motorMicro->motorDm->outputPower, DmConsumeFlag);
  addDmObject(_motorMicro->motorDm->elapsedHours, DmConsumeFlag);
  addDmObject(_motorMicro->motorDm->torque, DmConsumeFlag);

  setConsumePeriod(period);

  if (error()) {
    char errBuf[512];
    errorMsg(errBuf);
    theErrorDialog->postAndWait(errBuf);
  }

  _initial = True;
  updateGui();
  _initial = False;
}


SemiMotorMicroGui::~SemiMotorMicroGui()
{
  delete _heatSinkTemp;
  delete _humidity;
  delete _velocity;
  delete _status;
  delete _cmdThrust;
  delete _torque;
  delete _cntrlMode;
  delete _currentGain;
  delete _current;
  delete _torque;
  delete _outputPower;
  delete _inputVoltage;

  int i;
  
  for (i = 0; i < VELOCITY_GAIN_SIZE; i++)
    delete _velocityGains[i];
  
  delete _modelParamK4;
}


void SemiMotorMicroGui::updateGui(DM_Item changedHandle)
{
  char buf[512];
  DM_Time t;
  Errno errno;
  char errorBuf[errorMsgSize];
  Nat16 n16value;
  Int16 i16value;
  Int32 i32value;
  Int16 gains[10];
  Boolean debug = False;
  XmString xmstr;

  if ((errno = _motorMicro->motorDm->velocity->read(&i16value, &t)) != SUCCESS)
  {
    sprintDmError(errno, "SemiMotorMicroGui::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->enableStatus->read(&i32value, &t)) 
      != SUCCESS)
  {
    sprintDmError(errno, 
		  "SemiMotorMicroGui::updateGui(), reading enableStatus", 
		  errorBuf);

    setError(errorBuf);
  }
  else if (_initial || i32value != _values.status)
  {
    if (i32value)
      strcpy(buf, "Enabled");
    else
      strcpy(buf, "Disabled");

    _status->setText(buf);
    _values.status = i32value;
  }
  
  if ((errno = _motorMicro->motorDm->cntrlMode->read(&i32value, &t)) 
      != SUCCESS)
  {
    sprintDmError(errno, "SemiMotorMicroGui::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, "SemiMotorMicroGui::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->torque->read(&i16value, &t)) 
      != SUCCESS)
  {
    sprintDmError(errno, 
		  "SemiMotorMicroGui::updateGui(), reading torque", 
		  errorBuf);

    setError(errorBuf);
  }
  else if (_initial || i16value != _values.torque)
  {
    sprintf(buf, "%d", i16value);
    _torque->setText(buf);
    _values.torque = i16value;
  }

  if ((errno = _motorMicro->motorDm->currentGain->read(&i16value, &t)) 
      != SUCCESS)
  {
    sprintDmError(errno, "SemiMotorMicroGui::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->current->read(&n16value, &t)) 
      != SUCCESS)
  {
    sprintDmError(errno, "SemiMotorMicroGui::updateGui(), reading current",
		  errorBuf);

    setError(errorBuf);
  }
  else if (_initial || n16value != _values.current)
  {
    sprintf(buf, "%.1f", n16value/1000.);
    _current->setText(buf);
    _values.current = n16value;
  }

  if ((errno = _motorMicro->motorDm->velocity->read(&i16value, &t)) 
      != SUCCESS)
  {
    sprintDmError(errno, "SemiMotorMicroGui::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->outputPower->read(&n16value, &t)) 
      != SUCCESS)
  {
    sprintDmError(errno, "SemiMotorMicroGui::updateGui(), reading outputPower",
		  errorBuf);

    setError(errorBuf);
  }
  else if (_initial || n16value != _values.outputPower)
  {
    sprintf(buf, "%d", n16value);
    _outputPower->setText(buf);
    _values.outputPower = n16value;
  }

  if ((errno = _motorMicro->motorDm->inputVoltage->read(&n16value, &t)) 
      != SUCCESS)
  {
    sprintDmError(errno, 
		  "SemiMotorMicroGui::updateGui(), reading inputVoltage",
		  errorBuf);

    setError(errorBuf);
  }
  else if (_initial || n16value != _values.inputVoltage)
  {
    sprintf(buf, "%d", n16value);
    _inputVoltage->setText(buf);
    _values.inputVoltage = n16value;
  }

  if ((errno = _motorMicro->motorDm->elapsedHours->read(&n16value, &t)) 
      != SUCCESS)
  {
    sprintDmError(errno, 
		  "SemiMotorMicroGui::updateGui(), reading elapsedHours",
		  errorBuf);

    setError(errorBuf);
  }
  else if (_initial || n16value != _values.elapsedHours)
  {
    sprintf(buf, "%d", n16value);
    xmstr = XmStringCreateSimple(buf);
    XtVaSetValues(_elapsedHours, XmNlabelString, xmstr, NULL);
    XmStringFree(xmstr);
    _values.elapsedHours = n16value;
  }

  if ((errno = _motorMicro->motorDm->faultCode->read(&i32value, &t)) 
      != SUCCESS)
  {
    sprintDmError(errno, "SemiMotorMicroGui::updateGui(), reading faultCode",
		  errorBuf);

    setError(errorBuf);
  }
  else if (_initial || i32value != _values.faultCode)
  {
    char *mnem;
    switch (i32value) {

    case motorNoFault_FC:
      mnem = "OK";
      break;

    case invertorSatFault_FC:
      mnem = "InvertorSatFault";
      break;

    case dbOverload_FC:
      mnem = "DbOverload";
      break;

    case phaseOverCurrent_FC:
      mnem = "PhaseOverCurrent";
      break;

    case singlePhaseInput_FC:
      mnem = "SinglePhaseInput";
      break;

    case dcUndervoltage_FC:
      mnem = "DCUnderVoltage";
      break;

    case dcOvervoltage_FC:
      mnem = "DCOvervoltage";
      break;

    case baseDriveFault_FC:
      mnem = "BaseDriveFault";
      break;

    case adOffsetTolerance_FC:
      mnem = "AdOffsetTolerance";
      break;

    case motorFault_FC:
      mnem = "MotorFault";
      break;

    case heatSinkOverTemp_FC:
      mnem = "HeatSinkOverTemp";
      break;

    case thermalOverload_FC:
      mnem = "ThermalOverload";
      break;

    case communicationsFault_FC:
      mnem = "CommsFault";
      break;

    case externalFault_FC:
      mnem = "ExternalFault";
      break;

    case motorParamFault_FC:
      mnem = "MotorParamFault";
      break;

    case driveReset_FC:
      mnem = "DriveReset";
      break;

    default:
      mnem = "Unknown Fault!";
      break;
    }
    xmstr = XmStringCreateSimple(mnem);
    XtVaSetValues(_faultCode, XmNlabelString, xmstr, NULL);
    XmStringFree(xmstr);

    _values.faultCode = i32value;
  }

  
  int index;
  
  if ((errno = 
       _motorMicro->motorDm->velocityGains->read(gains, &t)) 
      != SUCCESS)
  {
    sprintDmError(errno, 
		  "SemiMotorMicroGui::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->modelParamK4->read(&i16value, &t)) 
      != SUCCESS)
  {
    sprintDmError(errno, 
		  "SemiMotorMicroGui::updateGui(), reading modelParamK4",
		  errorBuf);

    setError(errorBuf);
  } 
  else if (_initial || i16value != _values.modelParamK4)
  {
    sprintf(buf, "%d", i16value);
    _modelParamK4->set(buf);
    _values.modelParamK4 = i16value;
  }

  dprintf(stderr, "SemiMotorMicroGui::updateGui() - changed handle=%d\n",
	  changedHandle);

  dprintf(stderr, "SemiMotorMicroGui::updateGui() - faultqueue handle=%d\n",
	  _motorMicro->motorDm->faultQueue->getHandle());

  DmMotorFaultObject::Queue queue;
  if ((errno = _motorMicro->motorDm->faultQueue->read(queue.entry, &t)) 
      != SUCCESS) {

    sprintDmError(errno, 
		  "SemiMotorMicroGui::updateGui(), reading modelParamK4",
		  errorBuf);

    setError(errorBuf);
  } 
  else {
    int i;

    
    Boolean update = False;
    if (_initial)
      update = True;

    else {
      if (memcmp((void *)&queue, (void *)&_values.queue, 
		 sizeof(DmMotorFaultObject::Queue)))
	update = True;
    }

    if (update) {
      for (i = 0; i < FAULT_QUEUE_LENGTH; i++) {

	char hexbuf[10];
	sprintf(hexbuf, "0x%x", queue.entry[i].driveStatus);

	sprintf(buf, "%8s %8d %8d %8d %8d",
		hexbuf, queue.entry[i].elapsedTime, 
		queue.entry[i].i_mag, queue.entry[i].vdc, queue.entry[i].rpm);
		
	xmstr = XmStringCreateSimple(buf);
	XtVaSetValues(_faultQueueEntry[i], XmNlabelString, xmstr, 0);
	XmStringFree(xmstr);
	memcpy((void *)&_values.queue, &queue,
	       sizeof(DmMotorFaultObject::Queue));
      }
    }
  }
}


void SemiMotorMicroGui::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 SemiMotorMicroGui::writeValue(VkCallbackObject *obj,
			       void *clientData,
			       void *callData)
{
  DM_Time t;
  t.tv_sec = time(NULL);
  t.tv_usec = 0;
  Errno errno = SUCCESS;
  char errorBuf[errorMsgSize];
  
  MBool debug = FALSE;
  dprintf(stderr, "SemiMotorMicroGui::writeValue()\n");
  Int16 i16Value;
  Int16 gains[5];
  Nat16 n16Value;
  
  if (obj == _currentGain)
  {
    if (!isInteger((char *)_currentGain->get())) {
      sprintf(errorBuf, "Invalid current gain: must be integer");
      theErrorDialog->postAndWait(errorBuf);
      return;
    }
    i16Value = atoi(_currentGain->get());
    errno = _motorMicro->motorDm->currentGain->write(i16Value, &t);
  }
  else if (obj == _velocityGains[0] ||
	   obj == _velocityGains[1] ||
	   obj == _velocityGains[2])
  {
    dprintf(stderr, "SemiMotorMicroGui::writeValue() - velocity gains\n");
    dprintf(stderr, "item \"%s\"\n", 
	    _motorMicro->motorDm->velocityGains->getName());

    if (!isInteger((char *)_velocityGains[0]->get()) ||
	!isInteger((char *)_velocityGains[1]->get()) ||
	!isInteger((char *)_velocityGains[2]->get())) {
      sprintf(errorBuf, "Invalid velocity gain: must be integer");
      theErrorDialog->postAndWait(errorBuf);
      return;
    }
    gains[0] = atoi(_velocityGains[0]->get());
    gains[1] = atoi(_velocityGains[1]->get());
    gains[2] = atoi(_velocityGains[2]->get());    
    dprintf(stderr, "write %d, %d, %d\n",
	    gains[0], gains[1], gains[2]);

    errno = _motorMicro->motorDm->velocityGains->write(gains, &t);    
  }
  else if (obj == _modelParamK4)
  {
    if (!isInteger((char *)_modelParamK4->get())) {
      sprintf(errorBuf, "Invalid model param K4: must be integer");
      theErrorDialog->postAndWait(errorBuf);
      return;
    }

    i16Value = atoi(_modelParamK4->get());
    errno = _motorMicro->motorDm->modelParamK4->write(i16Value, &t); 
  }
  else {
    fprintf(stderr, "SemiMotorMicroGui::writeValue() - unknown object\n");
    return;
  }

  if (errno != SUCCESS)
  {
    sprintDmError(errno, "SemiMotorMicroGui::writeValue()", errorBuf);
    theErrorDialog->postAndWait(errorBuf);
  }
}



void SemiMotorMicroGui::currentCntrlModeCallback(Widget w,
					     XtPointer clientData,
					     XtPointer callData)
{
  SemiMotorMicroGui *obj = (SemiMotorMicroGui *)clientData;
  obj->writeCntrlMode(CURRENT);
}


void SemiMotorMicroGui::velocityCntrlModeCallback(Widget w,
					      XtPointer clientData,
					      XtPointer callData)
{
  SemiMotorMicroGui *obj = (SemiMotorMicroGui *)clientData;
  obj->writeCntrlMode(VELOCITY);
}


void SemiMotorMicroGui::semiCntrlModeCallback(Widget w,
					    XtPointer clientData,
					    XtPointer callData)
{
  SemiMotorMicroGui *obj = (SemiMotorMicroGui *)clientData;
  obj->writeCntrlMode(SEMIVELOCITY);
}


void SemiMotorMicroGui::faultQueueCallback(Widget w,
					   XtPointer clientData,
					   XtPointer callData)
{
  SemiMotorMicroGui *obj = (SemiMotorMicroGui *)clientData;
  DmEmptyObject *dmObject;
  if (w == obj->_readFaultQueue)
    dmObject = obj->_motorMicro->motorDm->readFaultQueue;
  else 
    dmObject = obj->_motorMicro->motorDm->clearFaultQueue;

  Errno errno;
  char errorBuf[100];
  DM_Time t;
  t.tv_sec = time(NULL);
  t.tv_usec = 0;

  if ((errno = dmObject->write(&t)) != SUCCESS) {
    sprintDmError(errno, "SemiMotorMicro::faultQueueCallback()", errorBuf);
    theErrorDialog->postAndWait(errorBuf);
  }
}

