/ src / emc / task / taskintf.cc
taskintf.cc
   1  /********************************************************************
   2  * Description: taskintf.cc
   3  *   Interface functions for motion.
   4  *
   5  *   Derived from a work by Fred Proctor & Will Shackleford
   6  *
   7  * Author:
   8  * License: GPL Version 2
   9  * System: Linux
  10  *    
  11  * Copyright (c) 2004 All rights reserved.
  12  *
  13  ********************************************************************/
  14  
  15  #include <cmath>
  16  #include <float.h>		// DBL_MAX
  17  #include <string.h>		// memcpy() strncpy()
  18  #include <unistd.h>             // unlink()
  19  
  20  #include "usrmotintf.h"		// usrmotInit(), usrmotReadEmcmotStatus(),
  21  				// etc.
  22  #include "motion.h"		// emcmot_command_t,STATUS, etc.
  23  #include "motion_debug.h"
  24  #include "emc.hh"
  25  #include "emccfg.h"		// EMC_INIFILE
  26  #include "emcglb.h"		// EMC_INIFILE
  27  #include "emc_nml.hh"
  28  #include "rcs_print.hh"
  29  #include "timer.hh"
  30  #include "inifile.hh"
  31  #include "iniaxis.hh"
  32  #include "inijoint.hh"
  33  #include "initraj.hh"
  34  #include "inihal.hh"
  35  
  36  value_inihal_data old_inihal_data;
  37  
  38  /* define this to catch isnan errors, for rtlinux FPU register 
  39     problem testing */
  40  #define ISNAN_TRAP
  41  
  42  #ifdef ISNAN_TRAP
  43  #define CATCH_NAN(cond) do {                           \
  44      if (cond) {                                        \
  45          printf("isnan error in %s()\n", __FUNCTION__); \
  46          return -1;                                     \
  47      }                                                  \
  48  } while(0)
  49  #else
  50  #define CATCH_NAN(cond) do {} while(0)
  51  #endif
  52  
  53  
  54  // MOTION INTERFACE
  55  
  56  /*! \todo FIXME - this decl was originally much later in the file, moved
  57  here temporarily for debugging */
  58  static emcmot_status_t emcmotStatus;
  59  
  60  /*
  61    Implementation notes:
  62  
  63    Initing:  the emcmot interface needs to be inited once, but nml_traj_init()
  64    and nml_servo_init() can be called in any order. Similarly, the emcmot
  65    interface needs to be exited once, but nml_traj_exit() and nml_servo_exit()
  66    can be called in any order. They can also be called multiple times. Flags
  67    are used to signify if initing has been done, or if the final exit has
  68    been called.
  69    */
  70  
  71  static struct TrajConfig_t TrajConfig;
  72  static struct JointConfig_t JointConfig[EMCMOT_MAX_JOINTS];
  73  static struct AxisConfig_t AxisConfig[EMCMOT_MAX_AXIS];
  74  
  75  static emcmot_command_t emcmotCommand;
  76  
  77  __attribute__ ((unused))
  78  static int emcmotIoInited = 0;	// non-zero means io called init
  79  static int emcmotion_initialized = 0;	// non-zero means both
  80  						// emcMotionInit called.
  81  
  82  // local status data, not provided by emcmot
  83  static unsigned long localMotionHeartbeat = 0;
  84  static int localMotionCommandType = 0;
  85  static int localMotionEchoSerialNumber = 0;
  86  
  87  //FIXME-AJ: see if needed
  88  //static double localEmcAxisUnits[EMCMOT_MAX_AXIS];
  89  
  90  // axes and joints are numbered 0..NUM-1
  91  
  92  /*
  93    In emcmot, we need to set the cycle time for traj, and the interpolation
  94    rate, in any order, but both need to be done. 
  95   */
  96  
  97  /*! functions involving joints */
  98  
  99  int emcJointSetType(int joint, unsigned char jointType)
 100  {
 101      if (joint < 0 || joint >= EMCMOT_MAX_JOINTS) {
 102  	return 0;
 103      }
 104  
 105      JointConfig[joint].Type = jointType;
 106  
 107      if (emc_debug & EMC_DEBUG_CONFIG) {
 108          rcs_print("%s(%d, %d)\n", __FUNCTION__, joint, jointType);
 109      }
 110      return 0;
 111  }
 112  
 113  int emcJointSetUnits(int joint, double units)
 114  {
 115      if (joint < 0 || joint >= EMCMOT_MAX_JOINTS) {
 116  	return 0;
 117      }
 118  
 119      JointConfig[joint].Units = units;
 120  
 121      if (emc_debug & EMC_DEBUG_CONFIG) {
 122          rcs_print("%s(%d, %.4f)\n", __FUNCTION__, joint, units);
 123      }
 124      return 0;
 125  }
 126  
 127  int emcJointSetBacklash(int joint, double backlash)
 128  {
 129  #ifdef ISNAN_TRAP
 130      if (std::isnan(backlash)) {
 131  	printf("std::isnan error in emcJointSetBacklash()\n");
 132  	return -1;
 133      }
 134  #endif
 135  
 136      if (joint < 0 || joint >= EMCMOT_MAX_JOINTS) {
 137  	return 0;
 138      }
 139  
 140      emcmotCommand.command = EMCMOT_SET_JOINT_BACKLASH;
 141      emcmotCommand.joint = joint;
 142      emcmotCommand.backlash = backlash;
 143  
 144      int retval = usrmotWriteEmcmotCommand(&emcmotCommand);
 145  
 146      if (emc_debug & EMC_DEBUG_CONFIG) {
 147          rcs_print("%s(%d, %.4f) returned %d\n", __FUNCTION__, joint, backlash, retval);
 148      }
 149      return retval;
 150  }
 151  
 152  int emcJointSetMinPositionLimit(int joint, double limit)
 153  {
 154  #ifdef ISNAN_TRAP
 155      if (std::isnan(limit)) {
 156  	printf("isnan error in emcJointSetMinPosition()\n");
 157  	return -1;
 158      }
 159  #endif
 160  
 161      if (joint < 0 || joint >= EMCMOT_MAX_JOINTS) {
 162  	return 0;
 163      }
 164  
 165      JointConfig[joint].MinLimit = limit;
 166  
 167      emcmotCommand.command = EMCMOT_SET_JOINT_POSITION_LIMITS;
 168      emcmotCommand.joint = joint;
 169      emcmotCommand.minLimit = JointConfig[joint].MinLimit;
 170      emcmotCommand.maxLimit = JointConfig[joint].MaxLimit;
 171  
 172      int retval = usrmotWriteEmcmotCommand(&emcmotCommand);
 173  
 174      if (emc_debug & EMC_DEBUG_CONFIG) {
 175          rcs_print("%s(%d, %.4f) returned %d\n", __FUNCTION__, joint, limit, retval);
 176      }
 177      return retval;
 178  }
 179  
 180  int emcJointSetMaxPositionLimit(int joint, double limit)
 181  {
 182  #ifdef ISNAN_TRAP
 183      if (std::isnan(limit)) {
 184  	printf("std::isnan error in emcJointSetMaxPosition()\n");
 185  	return -1;
 186      }
 187  #endif
 188  
 189      if (joint < 0 || joint >= EMCMOT_MAX_JOINTS) {
 190  	return 0;
 191      }
 192  
 193      JointConfig[joint].MaxLimit = limit;
 194  
 195      emcmotCommand.command = EMCMOT_SET_JOINT_POSITION_LIMITS;
 196      emcmotCommand.joint = joint;
 197      emcmotCommand.minLimit = JointConfig[joint].MinLimit;
 198      emcmotCommand.maxLimit = JointConfig[joint].MaxLimit;
 199  
 200      int retval = usrmotWriteEmcmotCommand(&emcmotCommand);
 201  
 202      if (emc_debug & EMC_DEBUG_CONFIG) {
 203          rcs_print("%s(%d, %.4f) returned %d\n", __FUNCTION__, joint, limit, retval);
 204      }
 205      return retval;
 206  }
 207  
 208  int emcJointSetMotorOffset(int joint, double offset) 
 209  {
 210  #ifdef ISNAN_TRAP
 211      if (std::isnan(offset)) {
 212  	printf("isnan error in emcJointSetMotorOffset()\n");
 213  	return -1;
 214      }
 215  #endif
 216  
 217      if (joint < 0 || joint >= EMCMOT_MAX_JOINTS) {
 218  	return 0;
 219      }
 220      emcmotCommand.command = EMCMOT_SET_JOINT_MOTOR_OFFSET;
 221      emcmotCommand.joint = joint;
 222      emcmotCommand.motor_offset = offset;
 223      
 224      int retval = usrmotWriteEmcmotCommand(&emcmotCommand);
 225  
 226      if (emc_debug & EMC_DEBUG_CONFIG) {
 227          rcs_print("%s(%d, %.4f) returned %d\n", __FUNCTION__, joint, offset, retval);
 228      }
 229      return retval;
 230  }
 231  
 232  int emcJointSetFerror(int joint, double ferror)
 233  {
 234  #ifdef ISNAN_TRAP
 235      if (std::isnan(ferror)) {
 236  	printf("isnan error in emcJointSetFerror()\n");
 237  	return -1;
 238      }
 239  #endif
 240  
 241      if (joint < 0 || joint >= EMCMOT_MAX_JOINTS) {
 242  	return 0;
 243      }
 244  
 245      emcmotCommand.command = EMCMOT_SET_JOINT_MAX_FERROR;
 246      emcmotCommand.joint = joint;
 247      emcmotCommand.maxFerror = ferror;
 248  
 249      int retval = usrmotWriteEmcmotCommand(&emcmotCommand);
 250  
 251      if (emc_debug & EMC_DEBUG_CONFIG) {
 252          rcs_print("%s(%d, %.4f) returned %d\n", __FUNCTION__, joint, ferror, retval);
 253      }
 254      return retval;
 255  }
 256  
 257  int emcJointSetMinFerror(int joint, double ferror)
 258  {
 259  #ifdef ISNAN_TRAP
 260      if (std::isnan(ferror)) {
 261  	printf("isnan error in emcJointSetMinFerror()\n");
 262  	return -1;
 263      }
 264  #endif
 265  
 266      if (joint < 0 || joint >= EMCMOT_MAX_JOINTS) {
 267  	return 0;
 268      }
 269      emcmotCommand.command = EMCMOT_SET_JOINT_MIN_FERROR;
 270      emcmotCommand.joint = joint;
 271      emcmotCommand.minFerror = ferror;
 272  
 273      int retval = usrmotWriteEmcmotCommand(&emcmotCommand);
 274  
 275      if (emc_debug & EMC_DEBUG_CONFIG) {
 276          rcs_print("%s(%d, %.4f) returned %d\n", __FUNCTION__, joint, ferror, retval);
 277      }
 278      return retval;
 279  }
 280  
 281  int emcJointSetHomingParams(int joint, double home, double offset, double home_final_vel,
 282  			   double search_vel, double latch_vel,
 283  			   int use_index, int encoder_does_not_reset,
 284  			   int ignore_limits, int is_shared,
 285  			   int sequence,int volatile_home, int locking_indexer,int absolute_encoder)
 286  {
 287  #ifdef ISNAN_TRAP
 288      if (std::isnan(home) || std::isnan(offset) || std::isnan(home_final_vel) ||
 289  	std::isnan(search_vel) || std::isnan(latch_vel)) {
 290  	printf("isnan error in emcJointSetHomingParams()\n");
 291  	return -1;
 292      }
 293  #endif
 294  
 295      if (joint < 0 || joint >= EMCMOT_MAX_JOINTS) {
 296  	return 0;
 297      }
 298  
 299      emcmotCommand.command = EMCMOT_SET_JOINT_HOMING_PARAMS;
 300      emcmotCommand.joint = joint;
 301      emcmotCommand.home = home;
 302      emcmotCommand.offset = offset;
 303      emcmotCommand.home_final_vel = home_final_vel;
 304      emcmotCommand.search_vel = search_vel;
 305      emcmotCommand.latch_vel = latch_vel;
 306      emcmotCommand.flags = 0;
 307      emcmotCommand.home_sequence = sequence;
 308      emcmotCommand.volatile_home = volatile_home;
 309      if (use_index) {
 310  	emcmotCommand.flags |= HOME_USE_INDEX;
 311      }
 312      if (encoder_does_not_reset) {
 313  	emcmotCommand.flags |= HOME_INDEX_NO_ENCODER_RESET;
 314      }
 315      if (ignore_limits) {
 316  	emcmotCommand.flags |= HOME_IGNORE_LIMITS;
 317      }
 318      if (is_shared) {
 319  	emcmotCommand.flags |= HOME_IS_SHARED;
 320      }
 321      if (locking_indexer) {
 322          emcmotCommand.flags |= HOME_UNLOCK_FIRST;
 323      }
 324      if (absolute_encoder) {
 325          switch (absolute_encoder) {
 326            case 0: break;
 327            case 1: emcmotCommand.flags |= HOME_ABSOLUTE_ENCODER;
 328                    emcmotCommand.flags |= HOME_NO_REHOME;
 329                    break;
 330            case 2: emcmotCommand.flags |= HOME_ABSOLUTE_ENCODER;
 331                    emcmotCommand.flags |= HOME_NO_REHOME;
 332                    emcmotCommand.flags |= HOME_NO_FINAL_MOVE;
 333                    break;
 334            default: fprintf(stderr,
 335                     "Unknown option for absolute_encoder <%d>",absolute_encoder);
 336                    break;
 337          }
 338      }
 339  
 340      int retval = usrmotWriteEmcmotCommand(&emcmotCommand);
 341  
 342      if (emc_debug & EMC_DEBUG_CONFIG) {
 343          rcs_print("%s(%d, %.4f, %.4f, %.4f, %.4f, %.4f, %d, %d, %d, %d, %d) returned %d\n",
 344            __FUNCTION__, joint, home, offset, home_final_vel, search_vel, latch_vel,
 345            use_index, ignore_limits, is_shared, sequence, volatile_home, retval);
 346      }
 347      return retval;
 348  }
 349  
 350  int emcJointUpdateHomingParams(int joint, double home, double offset, int sequence)
 351  {
 352      CATCH_NAN(std::isnan(home) || std::isnan(offset) );
 353  
 354      if (joint < 0 || joint >= EMCMOT_MAX_JOINTS) {
 355  	return 0;
 356      }
 357  
 358      emcmotCommand.command = EMCMOT_UPDATE_JOINT_HOMING_PARAMS;
 359      emcmotCommand.joint = joint;
 360      emcmotCommand.home = home;
 361      emcmotCommand.offset = offset;
 362      emcmotCommand.home_sequence = sequence;
 363  
 364      int retval = usrmotWriteEmcmotCommand(&emcmotCommand);
 365  
 366      if (emc_debug & EMC_DEBUG_CONFIG) {
 367          rcs_print("%s(%d, %.4f, %.4f) returned %d\n",
 368            __FUNCTION__, joint, home, offset,retval);
 369      }
 370      return retval;
 371  }
 372  
 373  int emcJointSetMaxVelocity(int joint, double vel)
 374  {
 375      CATCH_NAN(std::isnan(vel));
 376  
 377      if (joint < 0 || joint >= EMCMOT_MAX_JOINTS) {
 378  	return 0;
 379      }
 380  
 381      if (vel < 0.0) {
 382  	vel = 0.0;
 383      }
 384  
 385      JointConfig[joint].MaxVel = vel;
 386  
 387      emcmotCommand.command = EMCMOT_SET_JOINT_VEL_LIMIT;
 388      emcmotCommand.joint = joint;
 389      emcmotCommand.vel = vel;
 390      
 391      int retval = usrmotWriteEmcmotCommand(&emcmotCommand);
 392  
 393      if (emc_debug & EMC_DEBUG_CONFIG) {
 394          rcs_print("%s(%d, %.4f) returned %d\n", __FUNCTION__, joint, vel, retval);
 395      }
 396      return retval;
 397  }
 398  
 399  int emcJointSetMaxAcceleration(int joint, double acc)
 400  {
 401      CATCH_NAN(std::isnan(acc));
 402  
 403      if (joint < 0 || joint >= EMCMOT_MAX_JOINTS) {
 404  	return 0;
 405      }
 406      if (acc < 0.0) {
 407  	acc = 0.0;
 408      }
 409      JointConfig[joint].MaxAccel = acc;
 410      //FIXME-AJ: need functions for setting the AXIS_MAX_ACCEL (either from the ini, or from kins..)
 411      emcmotCommand.command = EMCMOT_SET_JOINT_ACC_LIMIT;
 412      emcmotCommand.joint = joint;
 413      emcmotCommand.acc = acc;
 414      
 415      int retval = usrmotWriteEmcmotCommand(&emcmotCommand);
 416  
 417      if (emc_debug & EMC_DEBUG_CONFIG) {
 418          rcs_print("%s(%d, %.4f) returned %d\n", __FUNCTION__, joint, acc, retval);
 419      }
 420      return retval;
 421  }
 422  
 423  /*! functions involving carthesian Axes (X,Y,Z,A,B,C,U,V,W) */
 424      
 425  int emcAxisSetMinPositionLimit(int axis, double limit)
 426  {
 427      CATCH_NAN(std::isnan(limit));
 428  
 429      if (axis < 0 || axis >= EMCMOT_MAX_AXIS || !(TrajConfig.AxisMask & (1 << axis))) {
 430  	return 0;
 431      }
 432  
 433      AxisConfig[axis].MinLimit = limit;
 434  
 435      emcmotCommand.command = EMCMOT_SET_AXIS_POSITION_LIMITS;
 436      emcmotCommand.axis = axis;
 437      emcmotCommand.minLimit = AxisConfig[axis].MinLimit;
 438      emcmotCommand.maxLimit = AxisConfig[axis].MaxLimit;
 439  
 440      int retval = usrmotWriteEmcmotCommand(&emcmotCommand);
 441  
 442      if (emc_debug & EMC_DEBUG_CONFIG) {
 443          rcs_print("%s(%d, %.4f) returned %d\n", __FUNCTION__, axis, limit, retval);
 444      }
 445      return retval;
 446  }
 447  
 448  int emcAxisSetMaxPositionLimit(int axis, double limit)
 449  {
 450      CATCH_NAN(std::isnan(limit));
 451  
 452      if (axis < 0 || axis >= EMCMOT_MAX_AXIS || !(TrajConfig.AxisMask & (1 << axis))) {
 453  	return 0;
 454      }
 455  
 456      AxisConfig[axis].MaxLimit = limit;
 457  
 458      emcmotCommand.command = EMCMOT_SET_AXIS_POSITION_LIMITS;
 459      emcmotCommand.axis = axis;
 460      emcmotCommand.minLimit = AxisConfig[axis].MinLimit;
 461      emcmotCommand.maxLimit = AxisConfig[axis].MaxLimit;
 462  
 463      int retval = usrmotWriteEmcmotCommand(&emcmotCommand);
 464  
 465      if (emc_debug & EMC_DEBUG_CONFIG) {
 466          rcs_print("%s(%d, %.4f) returned %d\n", __FUNCTION__, axis, limit, retval);
 467      }
 468      return retval;
 469  }
 470  
 471  int emcAxisSetMaxVelocity(int axis, double vel,double ext_offset_vel)
 472  {
 473      CATCH_NAN(std::isnan(vel));
 474  
 475      if (axis < 0 || axis >= EMCMOT_MAX_AXIS || !(TrajConfig.AxisMask & (1 << axis))) {
 476  	return 0;
 477      }
 478  
 479      if (vel < 0.0) {
 480  	vel = 0.0;
 481      }
 482  
 483      AxisConfig[axis].MaxVel = vel;
 484  
 485      emcmotCommand.command = EMCMOT_SET_AXIS_VEL_LIMIT;
 486      emcmotCommand.axis = axis;
 487      emcmotCommand.vel = vel;
 488      emcmotCommand.ext_offset_vel = ext_offset_vel;
 489      int retval = usrmotWriteEmcmotCommand(&emcmotCommand);
 490  
 491      if (emc_debug & EMC_DEBUG_CONFIG) {
 492          rcs_print("%s(%d, %.4f) returned %d\n", __FUNCTION__, axis, vel, retval);
 493      }
 494      return retval;
 495  }
 496  
 497  int emcAxisSetMaxAcceleration(int axis, double acc,double ext_offset_acc)
 498  {
 499      CATCH_NAN(std::isnan(acc));
 500  
 501      if (axis < 0 || axis >= EMCMOT_MAX_AXIS || !(TrajConfig.AxisMask & (1 << axis))) {
 502  	return 0;
 503      }
 504  
 505      if (acc < 0.0) {
 506  	acc = 0.0;
 507      }
 508      
 509      AxisConfig[axis].MaxAccel = acc;    
 510  
 511      emcmotCommand.command = EMCMOT_SET_AXIS_ACC_LIMIT;
 512      emcmotCommand.axis = axis;
 513      emcmotCommand.acc = acc;
 514      emcmotCommand.ext_offset_acc = ext_offset_acc;
 515      int retval = usrmotWriteEmcmotCommand(&emcmotCommand);
 516  
 517      if (emc_debug & EMC_DEBUG_CONFIG) {
 518          rcs_print("%s(%d, %.4f) returned %d\n", __FUNCTION__, axis, acc, retval);
 519      }
 520      return retval;
 521  }
 522  
 523  int emcAxisSetLockingJoint(int axis, int joint)
 524  {
 525  
 526      if (axis < 0 || axis >= EMCMOT_MAX_AXIS || !(TrajConfig.AxisMask & (1 << axis))) {
 527  	return 0;
 528      }
 529  
 530      if (joint < 0) {
 531  	joint = -1;
 532      }
 533  
 534      emcmotCommand.command = EMCMOT_SET_AXIS_LOCKING_JOINT;
 535      emcmotCommand.axis    = axis;
 536      emcmotCommand.joint   = joint;
 537      int retval = usrmotWriteEmcmotCommand(&emcmotCommand);
 538  
 539      if (emc_debug & EMC_DEBUG_CONFIG) {
 540          rcs_print("%s(%d, %d) returned %d\n", __FUNCTION__, axis, joint, retval);
 541      }
 542      return retval;
 543  }
 544  
 545  double emcAxisGetMaxVelocity(int axis)
 546  {
 547      if (axis < 0 || axis >= EMCMOT_MAX_AXIS) {
 548          return 0;
 549      }
 550  
 551      return AxisConfig[axis].MaxVel;
 552  }
 553  
 554  double emcAxisGetMaxAcceleration(int axis)
 555  {
 556      if (axis < 0 || axis >= EMCMOT_MAX_AXIS) {
 557          return 0;
 558      }
 559  
 560      return AxisConfig[axis].MaxAccel;
 561  }
 562  
 563  int emcAxisUpdate(EMC_AXIS_STAT stat[], int axis_mask)
 564  {
 565      int axis_num;
 566      emcmot_axis_status_t *axis;
 567      
 568      for (axis_num = 0; axis_num < EMCMOT_MAX_AXIS; axis_num++) {
 569          if(!(axis_mask & (1 << axis_num))) continue;
 570          axis = &(emcmotStatus.axis_status[axis_num]);
 571  
 572          stat[axis_num].velocity = axis->teleop_vel_cmd;
 573          stat[axis_num].minPositionLimit = axis->min_pos_limit;
 574          stat[axis_num].maxPositionLimit = axis->max_pos_limit;
 575      }
 576      return 0;
 577  }
 578  
 579  /* This function checks to see if any joint or the traj has
 580     been inited already.  At startup, if none have been inited,
 581     usrmotIniLoad and usrmotInit must be called first.  At
 582     shutdown, after all have been halted, the usrmotExit must
 583     be called.
 584  */
 585  
 586  static int JointOrTrajInited(void)
 587  {
 588      int joint;
 589  
 590      for (joint = 0; joint < EMCMOT_MAX_JOINTS; joint++) {
 591  	if (JointConfig[joint].Inited) {
 592  	    return 1;
 593  	}
 594      }
 595      if (TrajConfig.Inited) {
 596  	return 1;
 597      }
 598      return 0;
 599  }
 600  
 601  int emcJointInit(int joint)
 602  {
 603      int retval = 0;
 604      if (joint < 0 || joint >= EMCMOT_MAX_JOINTS) {
 605  	return 0;
 606      }
 607      // init emcmot interface
 608      if (!JointOrTrajInited()) {
 609  	usrmotIniLoad(emc_inifile);
 610  	if (0 != usrmotInit("emc2_task")) {
 611  	    return -1;
 612  	}
 613      }
 614      JointConfig[joint].Inited = 1;
 615      if (0 != iniJoint(joint, emc_inifile)) {
 616  	retval = -1;
 617      }
 618      return retval;
 619  }
 620  
 621  int emcAxisInit(int axis)
 622  {
 623      int retval = 0;
 624  
 625      if (axis < 0 || axis >= EMCMOT_MAX_AXIS) {
 626  	return 0;
 627      }
 628      // init emcmot interface
 629      if (!JointOrTrajInited()) {
 630  	usrmotIniLoad(emc_inifile);
 631  	if (0 != usrmotInit("emc2_task")) {
 632  	    return -1;
 633  	}
 634      }
 635      AxisConfig[axis].Inited = 1;
 636      if (0 != iniAxis(axis, emc_inifile)) {
 637  	retval = -1;
 638      }
 639      return retval;
 640  }
 641  
 642  int emcJointHalt(int joint)
 643  {
 644      if (joint < 0 || joint >= EMCMOT_MAX_JOINTS) {
 645  	return 0;
 646      }
 647      /*! \todo FIXME-- refs global emcStatus; should make EMC_JOINT_STAT an arg here */
 648      if (NULL != emcStatus && emcmotion_initialized
 649  	&& JointConfig[joint].Inited) {
 650  	//dumpJoint(joint, emc_inifile, &emcStatus->motion.joint[joint]);
 651      }
 652      JointConfig[joint].Inited = 0;
 653  
 654      if (!JointOrTrajInited()) {
 655  	usrmotExit();		// ours is final exit
 656      }
 657  
 658      return 0;
 659  }
 660  
 661  int emcJointAbort(int joint)
 662  {
 663      if (joint < 0 || joint >= EMCMOT_MAX_JOINTS) {
 664  	return 0;
 665      }
 666      emcmotCommand.command = EMCMOT_JOINT_ABORT;
 667      emcmotCommand.joint = joint;
 668  
 669      return usrmotWriteEmcmotCommand(&emcmotCommand);
 670  }
 671  
 672  int emcJointActivate(int joint)
 673  {
 674      if (joint < 0 || joint >= EMCMOT_MAX_JOINTS) {
 675  	return 0;
 676      }
 677  
 678      emcmotCommand.command = EMCMOT_JOINT_ACTIVATE;
 679      emcmotCommand.joint = joint;
 680  
 681      int retval = usrmotWriteEmcmotCommand(&emcmotCommand);
 682  
 683      if (emc_debug & EMC_DEBUG_CONFIG) {
 684          rcs_print("%s(%d) returned %d\n", __FUNCTION__, joint, retval);
 685      }
 686      return retval;
 687  }
 688  
 689  int emcJointDeactivate(int joint)
 690  {
 691      if (joint < 0 || joint >= EMCMOT_MAX_JOINTS) {
 692  	return 0;
 693      }
 694  
 695      emcmotCommand.command = EMCMOT_JOINT_DEACTIVATE;
 696      emcmotCommand.joint = joint;
 697  
 698      return usrmotWriteEmcmotCommand(&emcmotCommand);
 699  }
 700  
 701  int emcJointOverrideLimits(int joint)
 702  {
 703      // can have joint < 0, for resuming normal limit checking
 704      if (joint >= EMCMOT_MAX_JOINTS) {
 705  	return 0;
 706      }
 707  
 708      emcmotCommand.command = EMCMOT_OVERRIDE_LIMITS;
 709      emcmotCommand.joint = joint;
 710  
 711      return usrmotWriteEmcmotCommand(&emcmotCommand);
 712  }
 713  
 714  int emcJointEnable(int joint)
 715  {
 716      if (joint < 0 || joint >= EMCMOT_MAX_JOINTS) {
 717  	return 0;
 718      }
 719  
 720      emcmotCommand.command = EMCMOT_JOINT_ENABLE_AMPLIFIER;
 721      emcmotCommand.joint = joint;
 722  
 723      return usrmotWriteEmcmotCommand(&emcmotCommand);
 724  }
 725  
 726  int emcJointDisable(int joint)
 727  {
 728      if (joint < 0 || joint >= EMCMOT_MAX_JOINTS) {
 729  	return 0;
 730      }
 731  
 732      emcmotCommand.command = EMCMOT_JOINT_DISABLE_AMPLIFIER;
 733      emcmotCommand.joint = joint;
 734  
 735      return usrmotWriteEmcmotCommand(&emcmotCommand);
 736  }
 737  
 738  int emcJointHome(int joint)
 739  {
 740      if (joint < -1 || joint >= EMCMOT_MAX_JOINTS) {
 741  	return 0;
 742      }
 743  
 744      emcmotCommand.command = EMCMOT_JOINT_HOME;
 745      emcmotCommand.joint = joint;
 746  
 747      return usrmotWriteEmcmotCommand(&emcmotCommand);
 748  }
 749  
 750  int emcJointUnhome(int joint)
 751  {
 752  	if (joint < -2 || joint >= EMCMOT_MAX_JOINTS) {
 753  		return 0;
 754  	}
 755  
 756  	emcmotCommand.command = EMCMOT_JOINT_UNHOME;
 757  	emcmotCommand.joint = joint;
 758  
 759  	return usrmotWriteEmcmotCommand(&emcmotCommand);
 760  }
 761  
 762  int emcJogCont(int nr, double vel, int jjogmode)
 763  {
 764      if (jjogmode) {
 765          if (nr < 0 || nr >= EMCMOT_MAX_JOINTS) { return 0; }
 766          if (vel > JointConfig[nr].MaxVel) {
 767              vel = JointConfig[nr].MaxVel;
 768          } else if (vel < -JointConfig[nr].MaxVel) {
 769              vel = -JointConfig[nr].MaxVel;
 770          }
 771          emcmotCommand.joint = nr;
 772          emcmotCommand.axis = -1;  //NA
 773      } else {
 774          if (nr < 0 || nr >= EMCMOT_MAX_AXIS) { return 0; }
 775          if (vel > AxisConfig[nr].MaxVel) {
 776              vel = AxisConfig[nr].MaxVel;
 777          } else if (vel < -AxisConfig[nr].MaxVel) {
 778              vel = -AxisConfig[nr].MaxVel;
 779          }
 780          emcmotCommand.joint = -1; //NA
 781          emcmotCommand.axis = nr;
 782      }
 783      emcmotCommand.command = EMCMOT_JOG_CONT;
 784      emcmotCommand.vel = vel;
 785  
 786      return usrmotWriteEmcmotCommand(&emcmotCommand);
 787  }
 788  
 789  int emcJogIncr(int nr, double incr, double vel, int jjogmode)
 790  {
 791      if (jjogmode) {
 792          if (nr < 0 || nr >= EMCMOT_MAX_JOINTS) { return 0; }
 793          if (vel > JointConfig[nr].MaxVel) {
 794              vel = JointConfig[nr].MaxVel;
 795          } else if (vel < -JointConfig[nr].MaxVel) {
 796              vel = -JointConfig[nr].MaxVel;
 797          }
 798          emcmotCommand.joint = nr;
 799          emcmotCommand.axis = -1; //NA
 800      } else {
 801          if (nr < 0 || nr >= EMCMOT_MAX_AXIS) { return 0; }
 802          if (vel > AxisConfig[nr].MaxVel) {
 803              vel = AxisConfig[nr].MaxVel;
 804          } else if (vel < -AxisConfig[nr].MaxVel) {
 805              vel = -AxisConfig[nr].MaxVel;
 806          }
 807          emcmotCommand.joint = -1; //NA
 808          emcmotCommand.axis = nr;
 809      }
 810      emcmotCommand.command = EMCMOT_JOG_INCR;
 811      emcmotCommand.vel = vel;
 812      emcmotCommand.offset = incr;
 813  
 814      return usrmotWriteEmcmotCommand(&emcmotCommand);
 815  }
 816  
 817  int emcJogAbs(int nr, double pos, double vel, int jjogmode)
 818  {
 819      if (jjogmode) {        
 820          if (nr < 0 || nr >= EMCMOT_MAX_JOINTS) { return 0; }
 821          if (vel > JointConfig[nr].MaxVel) {
 822              vel = JointConfig[nr].MaxVel;
 823          } else if (vel < -JointConfig[nr].MaxVel) {
 824              vel = -JointConfig[nr].MaxVel;
 825          }
 826          emcmotCommand.joint = nr;
 827          emcmotCommand.axis = -1; //NA
 828      } else {
 829          if (nr < 0 || nr >= EMCMOT_MAX_AXIS) { return 0; }
 830          if (vel > AxisConfig[nr].MaxVel) {
 831              vel = AxisConfig[nr].MaxVel;
 832          } else if (vel < -AxisConfig[nr].MaxVel) {
 833              vel = -AxisConfig[nr].MaxVel;
 834          }
 835          emcmotCommand.joint = -1; //NA
 836          emcmotCommand.axis = nr;
 837      }
 838      emcmotCommand.command = EMCMOT_JOG_ABS;
 839      emcmotCommand.vel = vel;
 840      emcmotCommand.offset = pos;
 841  
 842      return usrmotWriteEmcmotCommand(&emcmotCommand);
 843  }
 844  
 845  int emcJogStop(int nr, int jjogmode)
 846  {
 847      if (jjogmode) {
 848          if (nr < 0 || nr >= EMCMOT_MAX_JOINTS) { return 0; }
 849          emcmotCommand.joint = nr;
 850          emcmotCommand.axis = -1; //NA
 851      } else {
 852          if (nr < 0 || nr >= EMCMOT_MAX_AXIS) { return 0; }
 853          emcmotCommand.joint = -1; //NA
 854          emcmotCommand.axis = nr;
 855      }
 856      emcmotCommand.command = EMCMOT_JOINT_ABORT;
 857      return usrmotWriteEmcmotCommand(&emcmotCommand);
 858  }
 859  
 860  
 861  int emcJointLoadComp(int joint, const char *file, int type)
 862  {
 863      return usrmotLoadComp(joint, file, type);
 864  }
 865  
 866  static emcmot_config_t emcmotConfig;
 867  int get_emcmot_debug_info = 0;
 868  
 869  /*
 870    these globals are set in emcMotionUpdate(), then referenced in
 871    emcJointUpdate(), emcTrajUpdate() to save calls to usrmotReadEmcmotStatus
 872   */
 873  static emcmot_debug_t emcmotDebug;
 874  static char errorString[EMCMOT_ERROR_LEN];
 875  static int new_config = 0;
 876  
 877  /*! \todo FIXME - debugging - uncomment the following line to log changes in
 878     JOINT_FLAG */
 879  // #define WATCH_FLAGS 1
 880  
 881  int emcJointUpdate(EMC_JOINT_STAT stat[], int numJoints)
 882  {
 883  /*! \todo FIXME - this function accesses data that has been
 884     moved.  Once I know what it is used for I'll fix it */
 885  
 886      int joint_num;
 887      emcmot_joint_status_t *joint;
 888  #ifdef WATCH_FLAGS
 889      static int old_joint_flag[8];
 890  #endif
 891  
 892      // check for valid range
 893      if (numJoints <= 0 || numJoints > EMCMOT_MAX_JOINTS) {
 894  	return -1;
 895      }
 896  
 897      for (joint_num = 0; joint_num < numJoints; joint_num++) {
 898  	/* point to joint data */
 899  
 900  	joint = &(emcmotStatus.joint_status[joint_num]);
 901  
 902  	stat[joint_num].jointType = JointConfig[joint_num].Type;
 903  	stat[joint_num].units = JointConfig[joint_num].Units;
 904  	if (new_config) {
 905  	    stat[joint_num].backlash = joint->backlash;
 906  	    stat[joint_num].minPositionLimit = joint->min_pos_limit;
 907  	    stat[joint_num].maxPositionLimit = joint->max_pos_limit;
 908  	    stat[joint_num].minFerror = joint->min_ferror;
 909  	    stat[joint_num].maxFerror = joint->max_ferror;
 910  /*! \todo FIXME - should all homing config params be included here? */
 911  //	    stat[joint_num].homeOffset = joint->home_offset;
 912  	}
 913  	stat[joint_num].output = joint->pos_cmd;
 914  	stat[joint_num].input = joint->pos_fb;
 915  	stat[joint_num].velocity = joint->vel_cmd;
 916  	stat[joint_num].ferrorCurrent = joint->ferror;
 917  	stat[joint_num].ferrorHighMark = joint->ferror_high_mark;
 918  
 919  	stat[joint_num].homing = joint->homing;
 920  	stat[joint_num].homed  = joint->homed;
 921  
 922  	stat[joint_num].fault = (joint->flag & EMCMOT_JOINT_FAULT_BIT ? 1 : 0);
 923  	stat[joint_num].enabled = (joint->flag & EMCMOT_JOINT_ENABLE_BIT ? 1 : 0);
 924  	stat[joint_num].inpos = (joint->flag & EMCMOT_JOINT_INPOS_BIT ? 1 : 0);
 925  
 926  /* FIXME - soft limits are now applied to the command, and should never
 927     happen */
 928  	stat[joint_num].minSoftLimit = 0;
 929  	stat[joint_num].maxSoftLimit = 0;
 930  	stat[joint_num].minHardLimit =
 931  	    (joint->flag & EMCMOT_JOINT_MIN_HARD_LIMIT_BIT ? 1 : 0);
 932  	stat[joint_num].maxHardLimit =
 933  	    (joint->flag & EMCMOT_JOINT_MAX_HARD_LIMIT_BIT ? 1 : 0);
 934  	stat[joint_num].overrideLimits = !!(emcmotStatus.overrideLimitMask);	// one
 935  	// for
 936  	// all
 937  
 938  #ifdef WATCH_FLAGS
 939  	if (old_joint_flag[joint_num] != joint->flag) {
 940  	    printf("joint %d flag: %04X -> %04X\n", joint_num,
 941  		   old_joint_flag[joint_num], joint->flag);
 942  	    old_joint_flag[joint_num] = joint->flag;
 943  	}
 944  #endif
 945  	if (joint->flag & EMCMOT_JOINT_ERROR_BIT) {
 946  	    if (stat[joint_num].status != RCS_ERROR) {
 947  		rcs_print_error("Error on joint %d, command number %d\n",
 948  				joint_num, emcmotStatus.commandNumEcho);
 949  		stat[joint_num].status = RCS_ERROR;
 950  	    }
 951  	} else if (joint->flag & EMCMOT_JOINT_INPOS_BIT) {
 952  	    stat[joint_num].status = RCS_DONE;
 953  	} else {
 954  	    stat[joint_num].status = RCS_EXEC;
 955  	}
 956      }
 957      return 0;
 958  }
 959  
 960  // EMC_TRAJ functions
 961  
 962  int emcTrajSetJoints(int joints)
 963  {
 964      if (joints <= 0 || joints > EMCMOT_MAX_JOINTS) {
 965  	rcs_print("emcTrajSetJoints failing: joints=%d\n",
 966  		joints);
 967  	return -1;
 968      }
 969  
 970      TrajConfig.Joints = joints;
 971      emcmotCommand.command = EMCMOT_SET_NUM_JOINTS;
 972      emcmotCommand.joint = joints;
 973      int retval = usrmotWriteEmcmotCommand(&emcmotCommand);
 974  
 975      if (emc_debug & EMC_DEBUG_CONFIG) {
 976          rcs_print("%s(%d) returned %d\n", __FUNCTION__, joints, retval);
 977      }
 978      return retval;
 979  }
 980  
 981  int emcTrajSetAxes(int axismask)
 982  {
 983      int axes = 0;
 984      for(int i=0; i<EMCMOT_MAX_AXIS; i++)
 985          if(axismask & (1<<i)) axes = i+1;
 986  
 987      TrajConfig.DeprecatedAxes = axes;
 988      TrajConfig.AxisMask = axismask;
 989      
 990      if (emc_debug & EMC_DEBUG_CONFIG) {
 991          rcs_print("%s(%d, %d)\n", __FUNCTION__, axes, axismask);
 992      }
 993      return 0;
 994  }
 995  
 996  int emcTrajSetSpindles(int spindles)
 997  {
 998      if (spindles <= 0 || spindles > EMCMOT_MAX_SPINDLES) {
 999  	rcs_print("emcTrajSetSpindles failing: spindles=%d\n",
1000  		spindles);
1001  	return -1;
1002      }
1003  
1004      TrajConfig.Spindles = spindles;
1005      emcmotCommand.command = EMCMOT_SET_NUM_SPINDLES;
1006      emcmotCommand.spindle = spindles;
1007      int retval = usrmotWriteEmcmotCommand(&emcmotCommand);
1008  
1009      if (emc_debug & EMC_DEBUG_CONFIG) {
1010          rcs_print("%s(%d) returned %d\n", __FUNCTION__, spindles, retval);
1011      }
1012      return retval;
1013  }
1014  
1015  int emcTrajSetUnits(double linearUnits, double angularUnits)
1016  {
1017      if (linearUnits <= 0.0 || angularUnits <= 0.0) {
1018  	return -1;
1019      }
1020  
1021      TrajConfig.LinearUnits = linearUnits;
1022      TrajConfig.AngularUnits = angularUnits;
1023  
1024      if (emc_debug & EMC_DEBUG_CONFIG) {
1025          rcs_print("%s(%.4f, %.4f)\n", __FUNCTION__, linearUnits, angularUnits);
1026      }
1027      return 0;
1028  }
1029  
1030  int emcTrajSetMode(int mode)
1031  {
1032      switch (mode) {
1033      case EMC_TRAJ_MODE_FREE:
1034  	emcmotCommand.command = EMCMOT_FREE;
1035  	return usrmotWriteEmcmotCommand(&emcmotCommand);
1036  
1037      case EMC_TRAJ_MODE_COORD:
1038  	emcmotCommand.command = EMCMOT_COORD;
1039  	return usrmotWriteEmcmotCommand(&emcmotCommand);
1040  
1041      case EMC_TRAJ_MODE_TELEOP:
1042  	emcmotCommand.command = EMCMOT_TELEOP;
1043  	return usrmotWriteEmcmotCommand(&emcmotCommand);
1044  
1045      default:
1046  	return -1;
1047      }
1048  }
1049  
1050  int emcTrajSetVelocity(double vel, double ini_maxvel)
1051  {
1052      if (vel < 0.0) {
1053  	vel = 0.0;
1054      } else if (vel > TrajConfig.MaxVel) {
1055  	vel = TrajConfig.MaxVel;
1056      }
1057  
1058      if (ini_maxvel < 0.0) {
1059  	    ini_maxvel = 0.0;
1060      } else if (vel > TrajConfig.MaxVel) {
1061  	    ini_maxvel = TrajConfig.MaxVel;
1062      }
1063  
1064      emcmotCommand.command = EMCMOT_SET_VEL;
1065      emcmotCommand.vel = vel;
1066      emcmotCommand.ini_maxvel = ini_maxvel;
1067  
1068      int retval = usrmotWriteEmcmotCommand(&emcmotCommand);
1069  
1070      if (emc_debug & EMC_DEBUG_CONFIG) {
1071          rcs_print("%s(%.4f, %.4f) returned %d\n", __FUNCTION__, vel, ini_maxvel, retval);
1072      }
1073      return retval;
1074  }
1075  
1076  int emcTrajSetAcceleration(double acc)
1077  {
1078      if (acc < 0.0) {
1079  	acc = 0.0;
1080      } else if (acc > TrajConfig.MaxAccel) {
1081  	acc = TrajConfig.MaxAccel;
1082      }
1083  
1084      emcmotCommand.command = EMCMOT_SET_ACC;
1085      emcmotCommand.acc = acc;
1086  
1087      int retval = usrmotWriteEmcmotCommand(&emcmotCommand);
1088  
1089      if (emc_debug & EMC_DEBUG_CONFIG) {
1090          rcs_print("%s(%.4f) returned %d\n", __FUNCTION__, acc, retval);
1091      }
1092      return retval;
1093  }
1094  
1095  /*
1096    emcmot has no limits on max velocity, acceleration so we'll save them
1097    here and apply them in the functions above
1098    */
1099  int emcTrajSetMaxVelocity(double vel)
1100  {
1101      if (vel < 0.0) {
1102  	vel = 0.0;
1103      }
1104  
1105      TrajConfig.MaxVel = vel;
1106  
1107      emcmotCommand.command = EMCMOT_SET_VEL_LIMIT;
1108      emcmotCommand.vel = vel;
1109  
1110      int retval = usrmotWriteEmcmotCommand(&emcmotCommand);
1111  
1112      if (emc_debug & EMC_DEBUG_CONFIG) {
1113          rcs_print("%s(%.4f) returned %d\n", __FUNCTION__, vel, retval);
1114      }
1115      return retval;
1116  }
1117  
1118  int emcTrajSetMaxAcceleration(double acc)
1119  {
1120      if (acc < 0.0) {
1121  	acc = 0.0;
1122      }
1123  
1124      TrajConfig.MaxAccel = acc;
1125  
1126      if (emc_debug & EMC_DEBUG_CONFIG) {
1127          rcs_print("%s(%.4f)\n", __FUNCTION__, acc);
1128      }
1129      return 0;
1130  }
1131  
1132  int emcTrajSetHome(EmcPose home)
1133  {
1134  #ifdef ISNAN_TRAP
1135      if (std::isnan(home.tran.x) || std::isnan(home.tran.y) || std::isnan(home.tran.z) ||
1136  	std::isnan(home.a) || std::isnan(home.b) || std::isnan(home.c) ||
1137  	std::isnan(home.u) || std::isnan(home.v) || std::isnan(home.w)) {
1138  	printf("std::isnan error in emcTrajSetHome()\n");
1139  	return 0;		// ignore it for now, just don't send it
1140      }
1141  #endif
1142  
1143      emcmotCommand.command = EMCMOT_SET_WORLD_HOME;
1144      emcmotCommand.pos = home;
1145  
1146      int retval = usrmotWriteEmcmotCommand(&emcmotCommand);
1147  
1148      if (emc_debug & EMC_DEBUG_CONFIG) {
1149          rcs_print("%s(%.4f, %.4f, %.4f, %.4f, %.4f, %.4f, %.4f, %.4f, %.4f) returned %d\n", 
1150            __FUNCTION__, home.tran.x, home.tran.y, home.tran.z, home.a, home.b, home.c, 
1151            home.u, home.v, home.w, retval);
1152      }
1153      return retval;
1154  }
1155  
1156  int emcTrajSetScale(double scale)
1157  {
1158      if (scale < 0.0) {
1159  	scale = 0.0;
1160      }
1161  
1162      emcmotCommand.command = EMCMOT_FEED_SCALE;
1163      emcmotCommand.scale = scale;
1164  
1165      return usrmotWriteEmcmotCommand(&emcmotCommand);
1166  }
1167  
1168  int emcTrajSetRapidScale(double scale)
1169  {
1170      if (scale < 0.0) {
1171  	scale = 0.0;
1172      }
1173  
1174      emcmotCommand.command = EMCMOT_RAPID_SCALE;
1175      emcmotCommand.scale = scale;
1176  
1177      return usrmotWriteEmcmotCommand(&emcmotCommand);
1178  }
1179  
1180  int emcTrajSetSpindleScale(int spindle, double scale)
1181  {
1182      if (scale < 0.0) {
1183  	scale = 0.0;
1184      }
1185  
1186      emcmotCommand.command = EMCMOT_SPINDLE_SCALE;
1187      emcmotCommand.scale = scale;
1188      emcmotCommand.spindle = spindle;
1189  
1190      return usrmotWriteEmcmotCommand(&emcmotCommand);
1191  }
1192  
1193  int emcTrajSetFOEnable(unsigned char mode)
1194  {
1195      emcmotCommand.command = EMCMOT_FS_ENABLE;
1196      emcmotCommand.mode = mode;
1197  
1198      return usrmotWriteEmcmotCommand(&emcmotCommand);
1199  }
1200  
1201  int emcTrajSetFHEnable(unsigned char mode)
1202  {
1203      emcmotCommand.command = EMCMOT_FH_ENABLE;
1204      emcmotCommand.mode = mode;
1205  
1206      return usrmotWriteEmcmotCommand(&emcmotCommand);
1207  }
1208  
1209  int emcTrajSetSOEnable(unsigned char mode)
1210  {
1211      emcmotCommand.command = EMCMOT_SS_ENABLE;
1212      emcmotCommand.mode = mode;
1213  
1214      return usrmotWriteEmcmotCommand(&emcmotCommand);
1215  }
1216  
1217  int emcTrajSetAFEnable(unsigned char enable)
1218  {
1219      emcmotCommand.command = EMCMOT_AF_ENABLE;
1220  
1221      if ( enable ) {
1222  	emcmotCommand.flags = 1;
1223      } else {
1224  	emcmotCommand.flags = 0;
1225      }
1226      return usrmotWriteEmcmotCommand(&emcmotCommand);
1227  }
1228  
1229  int emcTrajSetMotionId(int id)
1230  {
1231  
1232      if (EMC_DEBUG_MOTION_TIME & emc_debug) {
1233  	if (id != TrajConfig.MotionId) {
1234  	    rcs_print("Outgoing motion id is %d.\n", id);
1235  	}
1236      }
1237  
1238      TrajConfig.MotionId = id;
1239  
1240      return 0;
1241  }
1242  
1243  int emcTrajInit()
1244  {
1245      int retval = 0;
1246  
1247      TrajConfig.Inited = 0;
1248      TrajConfig.Joints = 0;
1249      TrajConfig.MaxAccel = DBL_MAX;
1250      TrajConfig.DeprecatedAxes = 0;
1251      TrajConfig.AxisMask = 0;
1252      TrajConfig.LinearUnits = 1.0;
1253      TrajConfig.AngularUnits = 1.0;
1254      TrajConfig.MotionId = 0;
1255      TrajConfig.MaxVel = DEFAULT_TRAJ_MAX_VELOCITY;
1256  
1257      // init emcmot interface
1258      if (!JointOrTrajInited()) {
1259  	usrmotIniLoad(emc_inifile);
1260  	if (0 != usrmotInit("emc2_task")) {
1261  	    return -1;
1262  	}
1263      }
1264      TrajConfig.Inited = 1;
1265      // initialize parameters from ini file
1266      if (0 != iniTraj(emc_inifile)) {
1267  	retval = -1;
1268      }
1269      return retval;
1270  }
1271  
1272  int emcTrajHalt()
1273  {
1274      TrajConfig.Inited = 0;
1275  
1276      if (!JointOrTrajInited()) {
1277  	usrmotExit();		// ours is final exit
1278      }
1279  
1280      return 0;
1281  }
1282  
1283  int emcTrajEnable()
1284  {
1285      emcmotCommand.command = EMCMOT_ENABLE;
1286  
1287      return usrmotWriteEmcmotCommand(&emcmotCommand);
1288  }
1289  
1290  int emcTrajDisable()
1291  {
1292      emcmotCommand.command = EMCMOT_DISABLE;
1293  
1294      return usrmotWriteEmcmotCommand(&emcmotCommand);
1295  }
1296  
1297  int emcTrajAbort()
1298  {
1299      emcmotCommand.command = EMCMOT_ABORT;
1300  
1301      return usrmotWriteEmcmotCommand(&emcmotCommand);
1302  }
1303  
1304  int emcTrajPause()
1305  {
1306      emcmotCommand.command = EMCMOT_PAUSE;
1307  
1308      return usrmotWriteEmcmotCommand(&emcmotCommand);
1309  }
1310  
1311  int emcTrajReverse()
1312  {
1313      emcmotCommand.command = EMCMOT_REVERSE;
1314  
1315      return usrmotWriteEmcmotCommand(&emcmotCommand);
1316  }
1317  
1318  int emcTrajForward()
1319  {
1320      emcmotCommand.command = EMCMOT_FORWARD;
1321  
1322      return usrmotWriteEmcmotCommand(&emcmotCommand);
1323  }
1324  
1325  int emcTrajStep()
1326  {
1327      emcmotCommand.command = EMCMOT_STEP;
1328  
1329      return usrmotWriteEmcmotCommand(&emcmotCommand);
1330  }
1331  
1332  int emcTrajResume()
1333  {
1334      emcmotCommand.command = EMCMOT_RESUME;
1335  
1336      return usrmotWriteEmcmotCommand(&emcmotCommand);
1337  }
1338  
1339  int emcTrajDelay(double delay)
1340  {
1341      /* nothing need be done here - it's done in task controller */
1342  
1343      return 0;
1344  }
1345  
1346  double emcTrajGetLinearUnits()
1347  {
1348      return TrajConfig.LinearUnits;
1349  }
1350  
1351  double emcTrajGetAngularUnits()
1352  {
1353      return TrajConfig.AngularUnits;
1354  }
1355  
1356  int emcTrajSetOffset(EmcPose tool_offset)
1357  {
1358      emcmotCommand.command = EMCMOT_SET_OFFSET;
1359      emcmotCommand.tool_offset = tool_offset;
1360      return usrmotWriteEmcmotCommand(&emcmotCommand);
1361  }
1362  
1363  int emcTrajSetSpindleSync(int spindle, double fpr, bool wait_for_index)
1364  {
1365      emcmotCommand.command = EMCMOT_SET_SPINDLESYNC;
1366      emcmotCommand.spindle = spindle;
1367      emcmotCommand.spindlesync = fpr;
1368      emcmotCommand.flags = wait_for_index;
1369      return usrmotWriteEmcmotCommand(&emcmotCommand);
1370  }
1371  
1372  int emcTrajSetTermCond(int cond, double tolerance)
1373  {
1374      emcmotCommand.command = EMCMOT_SET_TERM_COND;
1375      // Direct passthrough since TP can handle the distinction now
1376      emcmotCommand.termCond = cond;
1377      emcmotCommand.tolerance = tolerance;
1378  
1379      return usrmotWriteEmcmotCommand(&emcmotCommand);
1380  }
1381  
1382  int emcTrajLinearMove(EmcPose end, int type, double vel, double ini_maxvel, double acc,
1383                        int indexer_jnum)
1384  {
1385  #ifdef ISNAN_TRAP
1386      if (std::isnan(end.tran.x) || std::isnan(end.tran.y) || std::isnan(end.tran.z) ||
1387          std::isnan(end.a) || std::isnan(end.b) || std::isnan(end.c) ||
1388          std::isnan(end.u) || std::isnan(end.v) || std::isnan(end.w)) {
1389  	printf("std::isnan error in emcTrajLinearMove()\n");
1390  	return 0;		// ignore it for now, just don't send it
1391      }
1392  #endif
1393  
1394      emcmotCommand.command = EMCMOT_SET_LINE;
1395  
1396      emcmotCommand.pos = end;
1397  
1398      emcmotCommand.id = TrajConfig.MotionId;
1399      emcmotCommand.motion_type = type;
1400      emcmotCommand.vel = vel;
1401      emcmotCommand.ini_maxvel = ini_maxvel;
1402      emcmotCommand.acc = acc;
1403      emcmotCommand.turn = indexer_jnum;
1404  
1405      return usrmotWriteEmcmotCommand(&emcmotCommand);
1406  }
1407  
1408  int emcTrajCircularMove(EmcPose end, PM_CARTESIAN center,
1409  			PM_CARTESIAN normal, int turn, int type, double vel, double ini_maxvel, double acc)
1410  {
1411  #ifdef ISNAN_TRAP
1412      if (std::isnan(end.tran.x) || std::isnan(end.tran.y) || std::isnan(end.tran.z) ||
1413  	std::isnan(end.a) || std::isnan(end.b) || std::isnan(end.c) ||
1414  	std::isnan(end.u) || std::isnan(end.v) || std::isnan(end.w) ||
1415  	std::isnan(center.x) || std::isnan(center.y) || std::isnan(center.z) ||
1416  	std::isnan(normal.x) || std::isnan(normal.y) || std::isnan(normal.z)) {
1417  	printf("std::isnan error in emcTrajCircularMove()\n");
1418  	return 0;		// ignore it for now, just don't send it
1419      }
1420  #endif
1421  
1422      emcmotCommand.command = EMCMOT_SET_CIRCLE;
1423  
1424      emcmotCommand.pos = end;
1425      emcmotCommand.motion_type = type;
1426  
1427      emcmotCommand.center.x = center.x;
1428      emcmotCommand.center.y = center.y;
1429      emcmotCommand.center.z = center.z;
1430  
1431      emcmotCommand.normal.x = normal.x;
1432      emcmotCommand.normal.y = normal.y;
1433      emcmotCommand.normal.z = normal.z;
1434  
1435      emcmotCommand.turn = turn;
1436      emcmotCommand.id = TrajConfig.MotionId;
1437  
1438      emcmotCommand.vel = vel;
1439      emcmotCommand.ini_maxvel = ini_maxvel;
1440      emcmotCommand.acc = acc;
1441  
1442      return usrmotWriteEmcmotCommand(&emcmotCommand);
1443  }
1444  
1445  int emcTrajClearProbeTrippedFlag()
1446  {
1447      emcmotCommand.command = EMCMOT_CLEAR_PROBE_FLAGS;
1448  
1449      return usrmotWriteEmcmotCommand(&emcmotCommand);
1450  }
1451  
1452  int emcTrajProbe(EmcPose pos, int type, double vel, double ini_maxvel, double acc, unsigned char probe_type)
1453  {
1454  #ifdef ISNAN_TRAP
1455      if (std::isnan(pos.tran.x) || std::isnan(pos.tran.y) || std::isnan(pos.tran.z) ||
1456          std::isnan(pos.a) || std::isnan(pos.b) || std::isnan(pos.c) ||
1457          std::isnan(pos.u) || std::isnan(pos.v) || std::isnan(pos.w)) {
1458  	printf("std::isnan error in emcTrajProbe()\n");
1459  	return 0;		// ignore it for now, just don't send it
1460      }
1461  #endif
1462  
1463      emcmotCommand.command = EMCMOT_PROBE;
1464      emcmotCommand.pos = pos;
1465      emcmotCommand.id = TrajConfig.MotionId;
1466      emcmotCommand.motion_type = type;
1467      emcmotCommand.vel = vel;
1468      emcmotCommand.ini_maxvel = ini_maxvel;
1469      emcmotCommand.acc = acc;
1470      emcmotCommand.probe_type = probe_type;
1471  
1472      return usrmotWriteEmcmotCommand(&emcmotCommand);
1473  }
1474  
1475  int emcTrajRigidTap(EmcPose pos, double vel, double ini_maxvel, double acc, double scale)
1476  {
1477  #ifdef ISNAN_TRAP
1478      if (std::isnan(pos.tran.x) || std::isnan(pos.tran.y) || std::isnan(pos.tran.z)) {
1479  	printf("std::isnan error in emcTrajRigidTap()\n");
1480  	return 0;		// ignore it for now, just don't send it
1481      }
1482  #endif
1483  
1484      emcmotCommand.command = EMCMOT_RIGID_TAP;
1485      emcmotCommand.pos.tran = pos.tran;
1486      emcmotCommand.id = TrajConfig.MotionId;
1487      emcmotCommand.vel = vel;
1488      emcmotCommand.ini_maxvel = ini_maxvel;
1489      emcmotCommand.acc = acc;
1490      emcmotCommand.scale = scale;
1491  
1492      return usrmotWriteEmcmotCommand(&emcmotCommand);
1493  }
1494  
1495  
1496  static int last_id = 0;
1497  static int last_id_printed = 0;
1498  static int last_status = 0;
1499  static double last_id_time;
1500  
1501  int emcTrajUpdate(EMC_TRAJ_STAT * stat)
1502  {
1503      int joint, enables;
1504  
1505      stat->joints = TrajConfig.Joints;
1506      stat->spindles = TrajConfig.Spindles;
1507      stat->deprecated_axes = TrajConfig.DeprecatedAxes;
1508      stat->axis_mask = TrajConfig.AxisMask;
1509      stat->linearUnits = TrajConfig.LinearUnits;
1510      stat->angularUnits = TrajConfig.AngularUnits;
1511  
1512      stat->mode =
1513  	emcmotStatus.
1514  	motionFlag & EMCMOT_MOTION_TELEOP_BIT ? EMC_TRAJ_MODE_TELEOP
1515  	: (emcmotStatus.
1516  	   motionFlag & EMCMOT_MOTION_COORD_BIT ? EMC_TRAJ_MODE_COORD :
1517  	   EMC_TRAJ_MODE_FREE);
1518  
1519      /* enabled if motion enabled and all joints enabled */
1520      stat->enabled = 0;		/* start at disabled */
1521      if (emcmotStatus.motionFlag & EMCMOT_MOTION_ENABLE_BIT) {
1522  	for (joint = 0; joint < TrajConfig.Joints; joint++) {
1523  /*! \todo Another #if 0 */
1524  #if 0				/*! \todo FIXME - the axis flag has been moved to the joint struct */
1525  	    if (!emcmotStatus.axisFlag[axis] & EMCMOT_JOINT_ENABLE_BIT) {
1526  		break;
1527  	    }
1528  #endif
1529  	    /* got here, then all are enabled */
1530  	    stat->enabled = 1;
1531  	}
1532      }
1533  
1534      stat->inpos = emcmotStatus.motionFlag & EMCMOT_MOTION_INPOS_BIT;
1535      stat->queue = emcmotStatus.depth;
1536      stat->activeQueue = emcmotStatus.activeDepth;
1537      stat->queueFull = emcmotStatus.queueFull;
1538      stat->id = emcmotStatus.id;
1539      stat->motion_type = emcmotStatus.motionType;
1540      stat->distance_to_go = emcmotStatus.distance_to_go;
1541      stat->dtg = emcmotStatus.dtg;
1542      stat->current_vel = emcmotStatus.current_vel;
1543      if (EMC_DEBUG_MOTION_TIME & emc_debug) {
1544  	if (stat->id != last_id) {
1545  	    if (last_id != last_id_printed) {
1546  		rcs_print("Motion id %d took %f seconds.\n", last_id,
1547  			  etime() - last_id_time);
1548  		last_id_printed = last_id;
1549  	    }
1550  	    last_id = stat->id;
1551  	    last_id_time = etime();
1552  	}
1553      }
1554  
1555      stat->paused = emcmotStatus.paused;
1556      stat->scale = emcmotStatus.feed_scale;
1557      stat->rapid_scale = emcmotStatus.rapid_scale;
1558  
1559      stat->position = emcmotStatus.carte_pos_cmd;
1560  
1561      stat->actualPosition = emcmotStatus.carte_pos_fb;
1562  
1563      stat->velocity = emcmotStatus.vel;
1564      stat->acceleration = emcmotStatus.acc;
1565      stat->maxAcceleration = TrajConfig.MaxAccel;
1566  
1567      if (emcmotStatus.motionFlag & EMCMOT_MOTION_ERROR_BIT) {
1568  	stat->status = RCS_ERROR;
1569      } else if (stat->inpos && (stat->queue == 0)) {
1570  	stat->status = RCS_DONE;
1571      } else {
1572  	stat->status = RCS_EXEC;
1573      }
1574  
1575      if (EMC_DEBUG_MOTION_TIME & emc_debug) {
1576  	if (stat->status == RCS_DONE && last_status != RCS_DONE
1577  	    && stat->id != last_id_printed) {
1578  	    rcs_print("Motion id %d took %f seconds.\n", last_id,
1579  		      etime() - last_id_time);
1580  	    last_id_printed = last_id = stat->id;
1581  	    last_id_time = etime();
1582  	}
1583      }
1584  
1585      stat->probedPosition = emcmotStatus.probedPos;
1586  
1587      stat->probeval = emcmotStatus.probeVal;
1588      stat->probing = emcmotStatus.probing;
1589      stat->probe_tripped = emcmotStatus.probeTripped;
1590      
1591      if (emcmotStatus.motionFlag & EMCMOT_MOTION_COORD_BIT)
1592          enables = emcmotStatus.enables_queued;
1593      else
1594          enables = emcmotStatus.enables_new;
1595      
1596      stat->feed_override_enabled = enables & FS_ENABLED;
1597      stat->adaptive_feed_enabled = enables & AF_ENABLED;
1598      stat->feed_hold_enabled = enables & FH_ENABLED;
1599  
1600      if (new_config) {
1601  	stat->cycleTime = emcmotConfig.trajCycleTime;
1602  	stat->kinematics_type = emcmotConfig.kinType;
1603  	stat->maxVelocity = emcmotConfig.limitVel;
1604      }
1605  
1606      return 0;
1607  }
1608  
1609  
1610  int setup_inihal(void) {
1611      // Must be called after emcTrajInit(), which loads the number of
1612      // joints from the ini file.
1613      if (emcmotion_initialized != 1) {
1614          rcs_print_error("%s: emcMotionInit() has not completed, can't setup inihal\n", __FUNCTION__);
1615          return -1;
1616      }
1617  
1618      if (ini_hal_init(TrajConfig.Joints)) {
1619          rcs_print_error("%s: ini_hal_init(%d) failed\n", __FUNCTION__, TrajConfig.Joints);
1620          return -1;
1621      }
1622  
1623      if (ini_hal_init_pins(TrajConfig.Joints)) {
1624          rcs_print_error("%s: ini_hal_init_pins(%d) failed\n", __FUNCTION__, TrajConfig.Joints);
1625          return -1;
1626      }
1627  
1628      return 0;
1629  }
1630  
1631  
1632  int emcPositionLoad() {
1633      double positions[EMCMOT_MAX_JOINTS];
1634      IniFile ini;
1635      ini.Open(emc_inifile);
1636      const char *posfile = ini.Find("POSITION_FILE", "TRAJ");
1637      ini.Close();
1638      if(!posfile || !posfile[0]) return 0;
1639      FILE *f = fopen(posfile, "r");
1640      if(!f) return 0;
1641      for(int i=0; i<EMCMOT_MAX_JOINTS; i++) {
1642  	int r = fscanf(f, "%lf", &positions[i]);
1643  	if(r != 1) {
1644              fclose(f);
1645              rcs_print("%s: failed to load joint %d position from %s, ignoring\n", __FUNCTION__, i, posfile);
1646              return -1;
1647          }
1648      }
1649      fclose(f);
1650      int result = 0;
1651      for(int i=0; i<EMCMOT_MAX_JOINTS; i++) {
1652  	if(emcJointSetMotorOffset(i, -positions[i]) != 0) {
1653              rcs_print("%s: failed to set joint %d position (%.6f) from %s, ignoring\n", __FUNCTION__, i, positions[i], posfile);
1654              result = -1;
1655          }
1656      }
1657      return result;
1658  }
1659  
1660  
1661  int emcPositionSave() {
1662      IniFile ini;
1663      const char *posfile;
1664  
1665      ini.Open(emc_inifile);
1666      try {
1667          posfile = ini.Find("POSITION_FILE", "TRAJ");
1668      } catch (IniFile::Exception e) {
1669          ini.Close();
1670          return -1;
1671      }
1672      ini.Close();
1673  
1674      if(!posfile || !posfile[0]) return 0;
1675      // like the var file, make sure the posfile is recreated according to umask
1676      unlink(posfile);
1677      FILE *f = fopen(posfile, "w");
1678      if(!f) return -1;
1679      for(int i=0; i<EMCMOT_MAX_JOINTS; i++) {
1680  	int r = fprintf(f, "%.17f\n", emcmotStatus.joint_status[i].pos_fb);
1681  	if(r < 0) { fclose(f); return -1; }
1682      }
1683      fclose(f);
1684      return 0;
1685  }
1686  
1687  // EMC_MOTION functions
1688  
1689  // This function gets called by Task from emctask_startup().
1690  // emctask_startup() calls this function in a loop, retrying it until
1691  // it succeeds or until the retries time out.
1692  int emcMotionInit()
1693  {
1694      int r;
1695      int joint, axis;
1696      
1697      r = emcTrajInit(); // we want to check Traj first, the sane defaults for units are there
1698      // it also determines the number of existing joints, and axes
1699      if (r != 0) {
1700          rcs_print("%s: emcTrajInit failed\n", __FUNCTION__);
1701          return -1;
1702      }
1703  
1704      for (joint = 0; joint < TrajConfig.Joints; joint++) {
1705  	if (0 != emcJointInit(joint)) {
1706              rcs_print("%s: emcJointInit(%d) failed\n", __FUNCTION__, joint);
1707              return -1;
1708  	}
1709      }
1710  
1711      for (axis = 0; axis < EMCMOT_MAX_AXIS; axis++) {
1712          if (TrajConfig.AxisMask & (1<<axis)) {
1713  	    if (0 != emcAxisInit(axis)) {
1714                  rcs_print("%s: emcAxisInit(%d) failed\n", __FUNCTION__, axis);
1715                  return -1;
1716  	    }
1717  	}
1718      }
1719  
1720      // Ignore errors from emcPositionLoad(), because what are you going to do?
1721      (void)emcPositionLoad();
1722  
1723      emcmotion_initialized = 1;
1724  
1725      return 0;
1726  }
1727  
1728  int emcMotionHalt()
1729  {
1730      int r1, r2, r3, r4, r5;
1731      int t;
1732  
1733      r1 = -1;
1734      for (t = 0; t < EMCMOT_MAX_JOINTS; t++) {
1735  	if (0 == emcJointHalt(t)) {
1736  	    r1 = 0;		// at least one is okay
1737  	}
1738      }
1739  
1740      r2 = emcTrajDisable();
1741      r3 = emcTrajHalt();
1742      r4 = emcPositionSave();
1743      r5 = ini_hal_exit();
1744      emcmotion_initialized = 0;
1745  
1746      return (r1 == 0 && r2 == 0 && r3 == 0 && r4 == 0 && r5 == 0) ? 0 : -1;
1747  }
1748  
1749  int emcMotionAbort()
1750  {
1751      int r1;
1752      int r2;
1753      int r3 = 0;
1754      int t;
1755  
1756      r1 = -1;
1757      for (t = 0; t < EMCMOT_MAX_JOINTS; t++) {
1758  	if (0 == emcJointAbort(t)) {
1759  	    r1 = 0;		// at least one is okay
1760  	}
1761      }
1762  
1763      r2 = emcTrajAbort();
1764  
1765      return (r1 == 0 && r2 == 0 && r3 == 0) ? 0 : -1;
1766  }
1767  
1768  int emcMotionSetDebug(int debug)
1769  {
1770      emcmotCommand.command = EMCMOT_SET_DEBUG;
1771      emcmotCommand.debug = debug;
1772  
1773      return usrmotWriteEmcmotCommand(&emcmotCommand);
1774  }
1775  
1776  /*! \function emcMotionSetAout()
1777      
1778      This function sends a EMCMOT_SET_AOUT message to the motion controller.
1779      That one plans a AOUT command when motion starts or right now.
1780  
1781      @parameter	index	which output gets modified
1782      @parameter	now	wheather change is imediate or synched with motion
1783      @parameter	start	value set at start of motion
1784      @parameter	end	value set at end of motion
1785  */
1786  int emcMotionSetAout(unsigned char index, double start, double end, unsigned char now)
1787  {
1788      emcmotCommand.command = EMCMOT_SET_AOUT;
1789      emcmotCommand.now = now;
1790      emcmotCommand.out = index;
1791    /*! \todo FIXME-- if this works, set up some dedicated cmd fields instead of
1792       borrowing these */
1793      emcmotCommand.minLimit = start;
1794      emcmotCommand.maxLimit = end;
1795  
1796      return usrmotWriteEmcmotCommand(&emcmotCommand);
1797  }
1798  
1799  /*! \function emcMotionSetDout()
1800      
1801      This function sends a EMCMOT_SET_DOUT message to the motion controller.
1802      That one plans a DOUT command when motion starts or right now.
1803  
1804      @parameter	index	which output gets modified
1805      @parameter	now	wheather change is imediate or synched with motion
1806      @parameter	start	value set at start of motion
1807      @parameter	end	value set at end of motion
1808  */
1809  int emcMotionSetDout(unsigned char index, unsigned char start,
1810  		     unsigned char end, unsigned char now)
1811  {
1812      emcmotCommand.command = EMCMOT_SET_DOUT;
1813      emcmotCommand.now = now;
1814      emcmotCommand.out = index;
1815      emcmotCommand.start = start;
1816      emcmotCommand.end = end;
1817  
1818      return usrmotWriteEmcmotCommand(&emcmotCommand);
1819  }
1820  
1821  int emcSpindleAbort(int spindle)
1822  {
1823      return emcSpindleOff(spindle);
1824  }
1825  
1826  int emcSpindleSpeed(int spindle, double speed, double css_factor, double offset)
1827  {
1828      if (emcmotStatus.spindle_status[spindle].speed == 0){
1829          return 0;} //spindle stopped, not updating speed */
1830  
1831      return emcSpindleOn(spindle, speed, css_factor, offset);
1832  }
1833  
1834  int emcSpindleOrient(int spindle, double orientation, int mode)
1835  {
1836      emcmotCommand.command = EMCMOT_SPINDLE_ORIENT;
1837      emcmotCommand.spindle = spindle;
1838      emcmotCommand.orientation = orientation;
1839      emcmotCommand.mode = mode;
1840      return usrmotWriteEmcmotCommand(&emcmotCommand);
1841  }
1842  
1843  
1844  int emcSpindleOn(int spindle, double speed, double css_factor, double offset, int wait_for_at_speed)
1845  {
1846  
1847      emcmotCommand.command = EMCMOT_SPINDLE_ON;
1848      emcmotCommand.spindle = spindle;
1849      emcmotCommand.vel = speed;
1850      emcmotCommand.ini_maxvel = css_factor;
1851      emcmotCommand.acc = offset;
1852      emcmotCommand.wait_for_spindle_at_speed = wait_for_at_speed;
1853      return usrmotWriteEmcmotCommand(&emcmotCommand);
1854  }
1855  
1856  int emcSpindleOff(int spindle)
1857  {
1858      emcmotCommand.command = EMCMOT_SPINDLE_OFF;
1859      emcmotCommand.spindle = spindle;
1860      return usrmotWriteEmcmotCommand(&emcmotCommand);
1861  }
1862  
1863  int emcSpindleBrakeRelease(int spindle)
1864  {
1865      emcmotCommand.command = EMCMOT_SPINDLE_BRAKE_RELEASE;
1866      emcmotCommand.spindle = spindle;
1867      return usrmotWriteEmcmotCommand(&emcmotCommand);
1868  }
1869  
1870  int emcSpindleBrakeEngage(int spindle)
1871  {
1872      emcmotCommand.command = EMCMOT_SPINDLE_BRAKE_ENGAGE;
1873      emcmotCommand.spindle = spindle;
1874      return usrmotWriteEmcmotCommand(&emcmotCommand);
1875  }
1876  
1877  int emcSpindleIncrease(int spindle)
1878  {
1879      emcmotCommand.command = EMCMOT_SPINDLE_INCREASE;
1880      emcmotCommand.spindle = spindle;
1881      return usrmotWriteEmcmotCommand(&emcmotCommand);
1882  }
1883  
1884  int emcSpindleDecrease(int spindle)
1885  {
1886      emcmotCommand.command = EMCMOT_SPINDLE_DECREASE;
1887      emcmotCommand.spindle = spindle;
1888      return usrmotWriteEmcmotCommand(&emcmotCommand);
1889  }
1890  
1891  int emcSpindleConstant(int spindle)
1892  {
1893      return 0; // nothing to do
1894  }
1895  
1896  int emcSpindleUpdate(EMC_SPINDLE_STAT stat[], int num_spindles){
1897  	int s;
1898  	int enables;
1899      if (emcmotStatus.motionFlag & EMCMOT_MOTION_COORD_BIT)
1900          enables = emcmotStatus.enables_queued;
1901      else
1902          enables = emcmotStatus.enables_new;
1903  
1904      for (s = 0; s < num_spindles; s++){
1905  		stat[s].spindle_override_enabled = enables & SS_ENABLED;
1906  		stat[s].enabled = emcmotStatus.spindle_status[s].speed != 0;
1907  		stat[s].speed = emcmotStatus.spindle_status[s].speed;
1908  		stat[s].brake = emcmotStatus.spindle_status[s].brake;
1909  		stat[s].direction = emcmotStatus.spindle_status[s].direction;
1910  		stat[s].orient_state = emcmotStatus.spindle_status[s].orient_state;
1911  		stat[s].orient_fault = emcmotStatus.spindle_status[s].orient_fault;
1912  		stat[s].spindle_scale = emcmotStatus.spindle_status[s].scale;
1913      }
1914      return 0;
1915  }
1916  
1917  int emcMotionUpdate(EMC_MOTION_STAT * stat)
1918  {
1919      int r1, r2, r3, r4;
1920      int joint;
1921      int error;
1922      int exec;
1923      int dio, aio;
1924  
1925      // read the emcmot status
1926      if (0 != usrmotReadEmcmotStatus(&emcmotStatus)) {
1927  	return -1;
1928      }
1929      new_config = 0;
1930      if (emcmotStatus.config_num != emcmotConfig.config_num) {
1931  	if (0 != usrmotReadEmcmotConfig(&emcmotConfig)) {
1932  	    return -1;
1933  	}
1934  	new_config = 1;
1935      }
1936  
1937      if (get_emcmot_debug_info) {
1938  	if (0 != usrmotReadEmcmotDebug(&emcmotDebug)) {
1939  	    return -1;
1940  	}
1941      }
1942      // read the emcmot error
1943      if (0 != usrmotReadEmcmotError(errorString)) {
1944  	// no error, so ignore
1945      } else {
1946  	// an error to report
1947  	emcOperatorError(0, "%s", errorString);
1948      }
1949  
1950      // save the heartbeat and command number locally,
1951      // for use with emcMotionUpdate
1952      localMotionHeartbeat = emcmotStatus.heartbeat;
1953      localMotionCommandType = emcmotStatus.commandEcho;	/*! \todo FIXME-- not NML one! */
1954      localMotionEchoSerialNumber = emcmotStatus.commandNumEcho;
1955  
1956      r3 = emcTrajUpdate(&stat->traj);
1957      r1 = emcJointUpdate(&stat->joint[0], stat->traj.joints);
1958      r2 = emcAxisUpdate(&stat->axis[0], stat->traj.axis_mask);
1959      r3 = emcTrajUpdate(&stat->traj);
1960      r4 = emcSpindleUpdate(&stat->spindle[0], stat->traj.spindles);
1961      stat->heartbeat = localMotionHeartbeat;
1962      stat->command_type = localMotionCommandType;
1963      stat->echo_serial_number = localMotionEchoSerialNumber;
1964      stat->debug = emcmotConfig.debug;
1965  
1966      for (dio = 0; dio < EMCMOT_MAX_DIO; dio++) {
1967  	stat->synch_di[dio] = emcmotStatus.synch_di[dio];
1968  	stat->synch_do[dio] = emcmotStatus.synch_do[dio];
1969      }
1970  
1971      for (aio = 0; aio < EMCMOT_MAX_AIO; aio++) {
1972  	stat->analog_input[aio] = emcmotStatus.analog_input[aio];
1973  	stat->analog_output[aio] = emcmotStatus.analog_output[aio];
1974      }
1975  
1976      stat->numExtraJoints=emcmotStatus.numExtraJoints;
1977  
1978      // set the status flag
1979      error = 0;
1980      exec = 0;
1981  
1982      // FIXME-AJ: joints not axes
1983      for (joint = 0; joint < stat->traj.joints; joint++) {
1984  	if (stat->joint[joint].status == RCS_ERROR) {
1985  	    error = 1;
1986  	    break;
1987  	}
1988  	if (stat->joint[joint].status == RCS_EXEC) {
1989  	    exec = 1;
1990  	    break;
1991  	}
1992      }
1993      if (stat->traj.status == RCS_ERROR) {
1994  	error = 1;
1995      } else if (stat->traj.status == RCS_EXEC) {
1996  	exec = 1;
1997      }
1998  
1999      if (error) {
2000  	stat->status = RCS_ERROR;
2001      } else if (exec) {
2002  	stat->status = RCS_EXEC;
2003      } else {
2004  	stat->status = RCS_DONE;
2005      }
2006      return (r1 == 0 && r2 == 0 && r3 == 0 && r4 == 0) ? 0 : -1;
2007  }
2008  
2009  int emcSetupArcBlends(int arcBlendEnable,
2010          int arcBlendFallbackEnable,
2011          int arcBlendOptDepth,
2012          int arcBlendGapCycles,
2013          double arcBlendRampFreq,
2014          double arcBlendTangentKinkRatio) {
2015  
2016      emcmotCommand.command = EMCMOT_SETUP_ARC_BLENDS;
2017      emcmotCommand.arcBlendEnable = arcBlendEnable;
2018      emcmotCommand.arcBlendFallbackEnable = arcBlendFallbackEnable;
2019      emcmotCommand.arcBlendOptDepth = arcBlendOptDepth;
2020      emcmotCommand.arcBlendGapCycles = arcBlendGapCycles;
2021      emcmotCommand.arcBlendRampFreq = arcBlendRampFreq;
2022      emcmotCommand.arcBlendTangentKinkRatio = arcBlendTangentKinkRatio;
2023      return usrmotWriteEmcmotCommand(&emcmotCommand);
2024  }
2025  
2026  int emcSetMaxFeedOverride(double maxFeedScale) {
2027      emcmotCommand.command = EMCMOT_SET_MAX_FEED_OVERRIDE;
2028      emcmotCommand.maxFeedScale = maxFeedScale;
2029      return usrmotWriteEmcmotCommand(&emcmotCommand);
2030  }
2031  
2032  int emcSetProbeErrorInhibit(int j_inhibit, int h_inhibit) {
2033      emcmotCommand.command = EMCMOT_SET_PROBE_ERR_INHIBIT;
2034      emcmotCommand.probe_jog_err_inhibit = j_inhibit;
2035      emcmotCommand.probe_home_err_inhibit = h_inhibit;
2036      return usrmotWriteEmcmotCommand(&emcmotCommand);
2037  }
2038  
2039  int emcGetExternalOffsetApplied(void) {
2040      return emcmotStatus.external_offsets_applied;
2041  }
2042  
2043  EmcPose emcGetExternalOffsets(void) {
2044      return emcmotStatus.eoffset_pose;
2045  }