Main Page   Class Hierarchy   Alphabetical List   Data Structures   File List   Data Fields   Globals  

emctaskmain.cc

Go to the documentation of this file.
00001 /*
00002   Emctaskmain.cc
00003 
00004   Main program for EMC task level
00005 
00006   Modification history:
00007 
00008   17-Aug-2001  FMP added EMC_MOTION_SET_DOUT stuff
00009   31-May-2001  FMP added EMC_SET_DEBUG
00010   11-Dec-2000 WPS modified the DEBUG "Issuing" message.
00011   14-Nov-2000 WPS modified emcTaskExecute so that hopefully after an abort,
00012   estop or fault the current line would still be displayed. 
00013   6-Nov-2000 WPS modified the "can't do that in ? mode" messages to include
00014   the command that it was trying to do.
00015   18-Oct-2000 WPS put in more places to stop the startup after the process
00016   has already received SIGINT. (I have no patience.) Changed the name of
00017   the functions shutdown, startup, and quit to the less generic
00018   emctask_shutdown, emctask_startup, and emctask_quit. shutdown is also
00019   a socket function and this causes some problems.
00020   16-Aug-2000  FMP added EMC_AXIS_ALTER, handled in all modes, states
00021   10-Aug-2000  FMP added EMC_AXIS_LOAD_COMP, in estop/estop reset modes only
00022   4-Aug-2000  FMP hand-integrated WPS's probing stuff from 31-Jul-2000, and
00023   put pre- and postcondition handling of the probe and clear messages to
00024   support them on the interp list.
00025   2-Aug-2000  FMP added another condition to check for EMC done: we also
00026   need emcStatus->task.interpState == EMC_TASK_INTERP_IDLE. Without this,
00027   the EMC reported done when it was really paused on a final M1 in a program.
00028   Also added a check for emcTaskCommand == 0 when checking for
00029   interp_list.len() == 0, to insure that everything was done including the
00030   pending command.
00031   1-Aug-2000  FMP added 2 (RS274NGC_ENDFILE) to list of return values
00032   from emcTaskPlanRead() that signify that the program file is over.
00033   This was done so that "M1" would not keep the program in a paused state.
00034   31-Jul-2000 WPS added some probing stuff.
00035   10-May-2000 WPS added some extra error checking to make sure the
00036   operator would be warned
00037   when amp faults and soft and hard limits are hit.
00038   14-Mar-2000  FMP handled opening of files in estop/estop-reset/mdi modes,
00039   since I was always trying to load a program. Added handling of tool table
00040   and length offset messages in auto-idle, mdi modes
00041   6-Mar-2000  FMP added EMC_DEBUG_NML to enable printing of NML connect
00042   failures
00043   24-Feb-2000  FMP added deadband
00044   23-Feb-2000  FMP added emcInitGlobals()
00045   24-Jan-2000  FMP allowed EMC_AXIS_ENABLE,DISABLE in estop/reset state
00046   22-Jan-2000  FMP added looping timeout around NML channel creations. This
00047   was to handle race condition on emcio controller, which is the master
00048   for the error channel; it can't hurt to do it for the command and status
00049   channels even though we're the master for these and shouldn't get errors.
00050   10-Nov-1999  FMP added EMC_TASK_CYCLE_TIME_ORIG, and fix for situation
00051   where the cycle time is < 0 meaning full-out, no-delay execution. In this
00052   case the EMC_TASK_CYCLE_TIME is set to the original value. This is to
00053   work around the Linux 2.2 bug with gettimeofday().
00054   8-Nov-1999 WPS If'd out RCS_TIMER::wait() calls.
00055   15-Oct-1999  FMP handled EMC_AXIS_ABORT in estop, machine off, since
00056   this would come in if you were jogging into a limit and the machine
00057   estopped, then you let up on the jog button
00058   10-Oct-1999  FMP bracketed error printfs with EMC_DEBUG check
00059   5-Oct-1999  FMP added handling of EMC_AXIS_SET_MIN_FERROR
00060   1-Oct-1999  FMP added handling of EMC_AXIS_OVERRIDE_LIMITS
00061   3-Sep-1999  FMP took out lookup of PARPORT_IO_ADDRESS, which isn't needed
00062   18-Aug-1999  FMP fixed problem with pausing where you could get into a
00063   paused state and not be able to come out; allowed pausing/stepping/resuming
00064   of non-motion statements as well as motion statements; changed some
00065   operator error messages to "can't do that..."
00066   17-Aug-1999  FMP fixed single-step mode; made timeout for EMC_TRAJ_DELAY
00067   more accurate via etime()
00068   14-Jul-1999  FMP blanked out printing of horrible NML errors in prep
00069   for silent retries
00070   15-Jun-1999  FMP added EMC_OPERATOR_ERROR to checkInterpList, since
00071   this is what would pop out errors during verifies. Added setting of
00072   EMC_DEBUG.
00073   10-Jun-1999  FMP used negative values of programStartLine, as set by
00074   EMC_TASK_PLAN_RUN, to mean read through the whole program without executing.
00075   Added checkInterpList to include range checking during verification.
00076   14-May-1999  FMP replaced some calls to emcOperatorError with
00077   rcs_print_error, so that these wouldn't preempt the more specific
00078   errors (interpreter errors, for example) that the operator really
00079   wants to see.
00080   12-May-1999  FMP added check for interp_list.len() to be less than
00081   EMC_TASK_INTERP_MAX_LEN, so that queue won't grow for huge programs.
00082   10-May-1999  FMP added emcTaskNoDelay code so that task loops runs full
00083   out, with no timer wait, if [TASK] CYCLE_TIME value in ini file is <= 0.0.
00084   If so, the EMC_TASK_CYCLE_TIME global is continually set to the actual
00085   time interval.
00086   Added EMC_TASK_INTERP_MAX_LEN to keep huge NC files from soaking up memory.
00087   15-Apr-1999  FMP took out much of the atrophied code for single stepping,
00088   including the lineForStep global that was not used. Single stepping is
00089   still broken, and will be fixed soon.
00090   22-Mar-1999  FMP added line field to EMC_TASK_PLAN_RUN
00091   26-Feb-1999  FMP added handling of EMC_NULL_TYPE
00092   25-Feb-1999  FMP set emcStatus->command_type,echo_serial_number,status
00093   and emcStatus->task.command_type,echo_serial_number,status to be the
00094   same; fixed return codes so that status remains RCS_ERROR until you
00095   send another command
00096   22-Feb-1999  FMP called emcTaskPlanSynch() before emcTaskPlanExecute(),
00097   in manual modes, since the machine may have moved outside purview of interp.
00098   Added EMC_TOOL_SET_OFFSET, handled identically to EMC_TOOL_LOAD_TOOL_TABLE
00099   wrt sequencing.
00100   21-Feb-1999  FMP pulled EMC_TASK_PLAN_EXECUTE into issueCommand(), and
00101   allowed it to go through in most modes, states
00102   16-Feb-1999  FMP changed code for issuing EMC_TASK_SET_MODE to call for
00103   aborts if the desired mode is manual and we're not in manual
00104   12-Feb-1999  FMP added call to emcTaskPlanSynch() after a motion error,
00105   so that the interpreter will pick up the aborted position automatically.
00106   11-Feb-1999  FMP fixed missing break after case for setting output scale
00107   in emcTaskIssueCommand; added handling of EMC_AXIS_SET_FERROR
00108   10-Feb-1999  FMP fixed bug in code for setting output scale, and added
00109   passing of output scale message in all modes, states
00110   7-Feb-1999  FMP took out testing code for logging new messages, since
00111   it screwed up logging.
00112   5-Feb-1999  FMP took out calls to emcOperator error for motion and IO
00113   system error flags that are level-status, since these were flooding the GUI.
00114   4-Feb-1999  FMP allowed spindle and coolant commands to come through
00115   when you're auto and idle or paused, or MDI mode
00116   31-Jan-1999  FMP added EMC_AXIS_SET_GAINS in all modes, states
00117   7-Jan-1999  FMP added additional constraint that interp_list.len() be
00118   0 for emcStatus->status to be RCS_DONE; added logFp for logging
00119   29-Dec-1998  FMP added queueing of EMC_TASK_PLAN_SYNCH after task aborts,
00120   so that the interpreter can be re-synched to the actual aborted position.
00121   Added pass through of EMC_TASK_PLAN_INIT in off/estop/estop reset mode,
00122   auto-idle mode, and MDI mode.
00123   23-Dec-1998  FMP added EMC_TRAJ_SET_OFFSET,ORIGIN sequencing to prevent
00124   read-ahead display of tool length offset and program origin
00125   16-Oct-1998  FMP flushed queued commands when leaving auto mode
00126   15-Oct-1998  FMP changed emcLogError to emcOperatorError per change
00127   in emc.hh; added pre/issue/post handling of them
00128   5-Oct-1998  FMP added lube control
00129   2-Sep-1998  FMP added abort when subordinates report error; added
00130   retries when initing subordinates
00131   18-Aug-1998  FMP took out reverse PID gains, added bias
00132   6-Jul-1998  FMP changed local 'debug' to global EMC_DEBUG
00133   2-Jul-1998  FMP added EMC_TASK_PLAN_SYNCH
00134   1-Jul-1998  FMP added -base
00135   29-Jun-1998  FMP changed %d to %i so -shm command line arg can be in
00136   various bases
00137   26-Jun-1998  FMP added synchronizing of spindle, coolant off when
00138   estop detected
00139   25-Jun-1998  FMP added call to emcTaskPlanClose() when task aborts
00140   15-Jun-1998  FMP added EMC_TRAJ_SET_TERM_COND support
00141   12-Jun-1998  FMP added EMC_TRAJ_DELAY support
00142   11-Jun-1998  FMP added debug flag
00143   5-Jun-1998  FMP added reverse PIDs
00144   2-Jun-1998  FMP added EMC_TRAJ_SET_SCALE to allowable immediate
00145   commands in MDI mode
00146   22-May-1998  FMP added EMC_TASK_PLAN_RESUME to allowable immediate
00147   commands in MDI mode; called emcSymbolLookup for better printing
00148   21-May-1998  FMP fixed arg reversals in calls to emcAxisIncrJog,AbsJog;
00149   added passing of EMC_SPINDLE_INCREASE,DECREASE,CONSTANT in all modes
00150   10-Apr-1998  FMP explicitly set RCS_STAT_MSG members for command_type,
00151   serial_number, and status
00152   25-Mar-1998  FMP took usleep out and reverted to fixed timer->wait()
00153   17-Mar-1998  FMP added check on cycle time, for no-sleep option; took
00154   out quotes in Revision string
00155   4-Mar-1998  FMP added command line arg processing for -nml, -ini
00156   26-Feb-1998  FMP added brake on, off in manual mode
00157   24-Feb-1998  FMP added program origin update to task level, in user units
00158   20-Feb-1998  FMP made preconditions for most IO stuff both motion and IO,
00159   since coolant stuff was interrupting spindle sequence
00160   19-Feb-1998  FMP took out emcTaskSingle,QueueCommand() functions. Now
00161   the interp_list is only appended in the canonical interface.
00162   5-Feb-1998  FMP added ini file loading of cycle time
00163   9-Jan-1998  FMP put timer wait back in
00164   7-Jan-1998  FMP commented out timer wait pending a bug fix
00165   1-Dec-1997  FMP changed NML_SERVO_XXX to EMC_AXIS_XXX
00166   15-Oct_1997 FMP added meat to nml_servo_halt
00167   12-Aug-1997 WPS added update of the active g and m codes to the WM.
00168   11-Aug-1997 WPS added nml_log_error messages whenever a command is
00169   received in a state/mode in which it can't be used.
00170   2-Jul-1997  FMP created
00171   */
00172 
00173 /*
00174   Principles of operation:
00175 
00176   1.  The main program calls emcTaskPlan() and emcTaskExecute() cyclically.
00177 
00178   2.  emcTaskPlan() reads the new command, and decides what to do with
00179   it based on the mode (manual, auto, mdi) or state (estop, on) of the
00180   machine. Many of the commands just go out immediately to the
00181   subsystems (motion and IO). In auto mode, the interpreter is called
00182   and as a result the interp_list is appended with NML commands.
00183 
00184   3.  emcTaskExecute() executes a big switch on execState. If it's done,
00185   it gets the next item off the interp_list, and sets execState to the
00186   preconditions for that. These preconditions include waiting for motion,
00187   waiting for IO, etc. Once they are satisfied, it issues the command, and
00188   sets execState to the postconditions. Once those are satisfied, it gets
00189   the next item off the interp_list, and so on.
00190 
00191   4.  preconditions and postconditions are only looked at in conjunction
00192   with commands on the interp_list. Immediate commands won't have any
00193   pre- or postconditions associated with them looked at.
00194 
00195   5.  At this point, nothing in this file adds anything to the interp_list.
00196   This could change, for example, when defining pre- and postconditions for
00197   jog or home commands. If this is done, make sure that the corresponding
00198   abort command clears out the interp_list.
00199 
00200   6. Single-stepping is handled in checkPreconditions() as the first
00201   condition. If we're in single-stepping mode, as indicated by the
00202   variable 'stepping', we set the state to waiting-for-step. This
00203   polls on the variable 'steppingWait' which is reset to zero when a
00204   step command is received, and set to one when the command is
00205   issued.
00206   */
00207 
00208 extern "C" {
00209 #include <stdio.h>              // vsprintf()
00210 #include <string.h>             // strcpy()
00211 #include <stdarg.h>             // va_start()
00212 #include <stdlib.h>             // exit()
00213 #include <signal.h>             // signal(), SIGINT
00214 #include <float.h>              // DBL_MAX
00215 }
00216 #include "rcs.hh"               // NML classes, nmlErrorFormat()
00217 #include "emc.hh"               // EMC NML
00218 #include "canon.hh"             // CANON_TOOL_TABLE stuff
00219 #include "nml_mod.hh"           // RCS_DONE
00220 #include "inifile.h"            // INIFILE
00221 #include "interpl.hh"           // NML_INTERP_LIST, interp_list
00222 #include "emcglb.h"             // EMC_INIFILE,NMLFILE, EMC_TASK_CYCLE_TIME
00223 
00224 #ifdef NEW_INTERPRETER
00225 #include "rs274ngc_return.hh"   // NCE_FILE_NOT_OPEN
00226 #endif
00227 
00228 
00229 /* ident tag */
00230 #ifndef __GNUC__
00231 #ifndef __attribute__
00232 #define __attribute__(x)
00233 #endif
00234 #endif
00235 
00236 static char __attribute__((unused)) ident[] = "$Id: emctaskmain.cc,v 1.28 2001/11/14 19:07:12 wshackle Exp $";
00237 
00238 // command line args-- global so that other modules can access
00239 int Argc;
00240 char **Argv;
00241 
00242 // NML channels
00243 static RCS_CMD_CHANNEL * emcCommandBuffer = 0;
00244 static RCS_STAT_CHANNEL * emcStatusBuffer = 0;
00245 static NML * emcErrorBuffer = 0;
00246 
00247 // NML command channel data pointer
00248 static RCS_CMD_MSG * emcCommand = 0;
00249 
00250 // global EMC status
00251 EMC_STAT * emcStatus = 0;
00252 
00253 // timer stuff
00254 static RCS_TIMER * timer = 0;
00255 
00256 // flag signifying that ini file [TASK] CYCLE_TIME is <= 0.0, so
00257 // we should not delay at all between cycles. This means also that
00258 // the EMC_TASK_CYCLE_TIME global will be set to the measured cycle
00259 // time each cycle, in case other code references this.
00260 static int emcTaskNoDelay = 0;
00261 static double EMC_TASK_CYCLE_TIME_ORIG = 0.0;
00262 
00263 // delay counter
00264 static double taskExecDelayTimeout = 0.0;
00265 
00266 // emcTaskQueueCommand puts cmd on interp_list
00267 static int emcTaskQueueCommand(NMLmsg * cmd);
00268 
00269 // emcTaskIssueCommand issues command immediately
00270 static int emcTaskIssueCommand(NMLmsg * cmd);
00271 
00272 // pending command to be sent out by emcTaskExecute()
00273 static NMLmsg * emcTaskCommand = 0;
00274 
00275 // general purpose log file
00276 static FILE *logFp = NULL;
00277 #define LOG_FILE "emc.log"      // FIXME-- ini file param
00278 
00279 
00280 // signal handling code to stop main loop
00281 static int done;
00282 static int emctask_shutdown(void);
00283 static int pseudoMdiLineNumber = -1;
00284 
00285 static void emctask_quit(int sig)
00286 {
00287   // set main's done flag
00288   done = 1;
00289 
00290   // restore signal handler
00291   signal(SIGINT, emctask_quit);
00292 }
00293 
00294 
00295 // implementation of EMC error logger
00296 int emcOperatorError(int id, const char *fmt, ...)
00297 {
00298   EMC_OPERATOR_ERROR error_msg;
00299   va_list ap;
00300 
00301   // check channel for validity
00302   if (emcErrorBuffer == NULL)
00303     return -1;
00304   if (! emcErrorBuffer->valid())
00305     return -1;
00306 
00307 
00308   if(NULL == fmt)
00309     {
00310       return -1;
00311     }
00312   if(0 == *fmt)
00313     {
00314       return -1;
00315     }
00316 
00317   // prepend error code, leave off 0 ad-hoc code
00318   error_msg.error[0] = 0;
00319   if (0 != id)
00320     {
00321       sprintf(error_msg.error, "[%d] ", id);
00322     }
00323 
00324   // append error string
00325   va_start(ap, fmt);
00326   vsprintf(&error_msg.error[strlen(error_msg.error)], fmt, ap);
00327   va_end(ap);
00328 
00329   // force a NULL at the end for safety
00330   error_msg.error[EMC_OPERATOR_ERROR_LEN-1] = 0;
00331 
00332   // write it
00333   rcs_print("%s\n",error_msg.error);
00334   return emcErrorBuffer->write(error_msg);
00335 }
00336 
00337 int emcOperatorText(int id, const char *fmt, ...)
00338 {
00339   EMC_OPERATOR_TEXT text_msg;
00340   va_list ap;
00341 
00342   // check channel for validity
00343   if (emcErrorBuffer == NULL)
00344     return -1;
00345   if (! emcErrorBuffer->valid())
00346     return -1;
00347 
00348   // write args to NML message (ignore int text code)
00349   va_start(ap, fmt);
00350   vsprintf(text_msg.text, fmt, ap);
00351   va_end(ap);
00352 
00353   // force a NULL at the end for safety
00354   text_msg.text[EMC_OPERATOR_TEXT_LEN-1] = 0;
00355 
00356   // write it
00357   return emcErrorBuffer->write(text_msg);
00358 }
00359 
00360 int emcOperatorDisplay(int id, const char *fmt, ...)
00361 {
00362   EMC_OPERATOR_DISPLAY display_msg;
00363   va_list ap;
00364 
00365   // check channel for validity
00366   if (emcErrorBuffer == NULL)
00367     return -1;
00368   if (! emcErrorBuffer->valid())
00369     return -1;
00370 
00371   // write args to NML message (ignore int display code)
00372   va_start(ap, fmt);
00373   vsprintf(display_msg.display, fmt, ap);
00374   va_end(ap);
00375 
00376   // force a NULL at the end for safety
00377   display_msg.display[EMC_OPERATOR_DISPLAY_LEN-1] = 0;
00378 
00379   // write it
00380   return emcErrorBuffer->write(display_msg);
00381 }
00382 
00383 // shorthand typecasting ptrs
00384 static EMC_AXIS_HALT *axis_halt_msg;
00385 static EMC_AXIS_DISABLE *disable_msg;
00386 static EMC_AXIS_ENABLE *enable_msg;
00387 static EMC_AXIS_HOME *home_msg;
00388 static EMC_AXIS_JOG *jog_msg;
00389 static EMC_AXIS_ABORT *axis_abort_msg;
00390 static EMC_AXIS_INCR_JOG *incr_jog_msg;
00391 static EMC_AXIS_ABS_JOG *abs_jog_msg;
00392 static EMC_AXIS_SET_CYCLE_TIME *set_cycle_time_msg;
00393 static EMC_AXIS_SET_GAINS *set_gains_msg;
00394 static EMC_AXIS_SET_INPUT_SCALE *set_input_scale_msg;
00395 static EMC_AXIS_SET_OUTPUT_SCALE *set_output_scale_msg;
00396 static EMC_AXIS_SET_FERROR *set_ferror_msg;
00397 static EMC_AXIS_SET_MIN_FERROR *set_min_ferror_msg;
00398 static EMC_AXIS_SET_MAX_POSITION_LIMIT *set_max_limit_msg;
00399 static EMC_AXIS_SET_MIN_POSITION_LIMIT *set_min_limit_msg;
00400 static EMC_AXIS_OVERRIDE_LIMITS *axis_lim_msg;
00401 static EMC_AXIS_SET_OUTPUT *axis_output_msg;
00402 static EMC_AXIS_LOAD_COMP *axis_load_comp_msg;
00403 static EMC_AXIS_ALTER *axis_alter_msg;
00404 
00405 static EMC_TRAJ_SET_SCALE *emcTrajSetScaleMsg;
00406 static EMC_TRAJ_SET_VELOCITY *emcTrajSetVelocityMsg;
00407 static EMC_TRAJ_LINEAR_MOVE *emcTrajLinearMoveMsg;
00408 static EMC_TRAJ_CIRCULAR_MOVE *emcTrajCircularMoveMsg;
00409 static EMC_TRAJ_DELAY *emcTrajDelayMsg;
00410 static EMC_TRAJ_SET_TERM_COND *emcTrajSetTermCondMsg;
00411 
00412 static EMC_MOTION_SET_AOUT *emcMotionSetAoutMsg;
00413 static EMC_MOTION_SET_DOUT *emcMotionSetDoutMsg;
00414 
00415 static EMC_SPINDLE_ON *spindle_on_msg;
00416 static EMC_TOOL_PREPARE *tool_prepare_msg;
00417 static EMC_TOOL_LOAD_TOOL_TABLE *load_tool_table_msg;
00418 static EMC_TOOL_SET_OFFSET *emc_tool_set_offset_msg;
00419 static EMC_TASK_SET_MODE *mode_msg;
00420 static EMC_TASK_SET_STATE *state_msg;
00421 static EMC_TASK_PLAN_RUN *run_msg;
00422 static EMC_TASK_PLAN_EXECUTE *execute_msg;
00423 static EMC_TASK_PLAN_OPEN *open_msg;
00424 
00425 static EMC_LOG_OPEN *log_open_msg;
00426 
00427 // commands we compose here
00428 static EMC_TASK_PLAN_RUN taskPlanRunCmd;// 16-Aug-1999 FMP
00429 static EMC_TASK_PLAN_INIT taskPlanInitCmd;
00430 static EMC_TASK_PLAN_SYNCH taskPlanSynchCmd;
00431 
00432 static int interpResumeState = EMC_TASK_INTERP_IDLE;
00433 static int programStartLine = 0; // which line to run program from
00434 // how long the interp list can be
00435 // FIXME-- make an ini file global
00436 #define EMC_TASK_INTERP_MAX_LEN 1000
00437 
00438 static int stepping = 0;
00439 static int steppingWait = 0;
00440 static int steppedLine = 0;
00441 
00442 /*
00443   checkInterpList(NML_INTERP_LIST *il, EMC_STAT *stat) takes a pointer
00444   to an interpreter list and a pointer to the EMC status, pops each NML
00445   message off the list, and checks it against limits, resource availability,
00446   etc. in the status.
00447 
00448   It returns 0 if all messages check out, -1 if any of them fail. If one
00449   fails, the rest of the list is not checked.
00450  */
00451 static int checkInterpList(NML_INTERP_LIST *il, EMC_STAT *stat)
00452 {
00453   NMLmsg * cmd = 0;
00454   // let's create some shortcuts to casts at compile time
00455 #define operator_error_msg ((EMC_OPERATOR_ERROR *) cmd)
00456 #define linear_move ((EMC_TRAJ_LINEAR_MOVE *) cmd)
00457 #define circular_move ((EMC_TRAJ_CIRCULAR_MOVE *) cmd)
00458 
00459   while (il->len() > 0) {
00460     cmd = il->get();
00461 
00462     switch (cmd->type) {
00463 
00464     case EMC_OPERATOR_ERROR_TYPE:
00465       emcOperatorError(operator_error_msg->id, operator_error_msg->error);
00466       break;
00467 
00468     case EMC_TRAJ_LINEAR_MOVE_TYPE:
00469       if (linear_move->end.tran.x > stat->motion.axis[0].maxPositionLimit) {
00470         emcOperatorError(0, "%s\n%s", stat->task.command, "exceeds +X limit");
00471         return -1;
00472       }
00473       if (linear_move->end.tran.y > stat->motion.axis[1].maxPositionLimit) {
00474         emcOperatorError(0, "%s\n%s", stat->task.command, "exceeds +Y limit");
00475         return -1;
00476       }
00477       if (linear_move->end.tran.z > stat->motion.axis[2].maxPositionLimit) {
00478         emcOperatorError(0, "%s\n%s", stat->task.command, "exceeds +Z limit");
00479         return -1;
00480       }
00481       if (linear_move->end.tran.x < stat->motion.axis[0].minPositionLimit) {
00482         emcOperatorError(0, "%s\n%s", stat->task.command, "exceeds -X limit");
00483         return -1;
00484       }
00485       if (linear_move->end.tran.y < stat->motion.axis[1].minPositionLimit) {
00486         emcOperatorError(0, "%s\n%s", stat->task.command, "exceeds -Y limit");
00487         return -1;
00488       }
00489       if (linear_move->end.tran.z < stat->motion.axis[2].minPositionLimit) {
00490         emcOperatorError(0, "%s\n%s", stat->task.command, "exceeds -Z limit");
00491         return -1;
00492       }
00493       break;
00494 
00495     case EMC_TRAJ_CIRCULAR_MOVE_TYPE:
00496       if (circular_move->end.tran.x > stat->motion.axis[0].maxPositionLimit) {
00497         emcOperatorError(0, "%s\n%s", stat->task.command, "exceeds +X limit");
00498         return -1;
00499       }
00500       if (circular_move->end.tran.y > stat->motion.axis[1].maxPositionLimit) {
00501         emcOperatorError(0, "%s\n%s", stat->task.command, "exceeds +Y limit");
00502         return -1;
00503       }
00504       if (circular_move->end.tran.z > stat->motion.axis[2].maxPositionLimit) {
00505         emcOperatorError(0, "%s\n%s", stat->task.command, "exceeds +Z limit");
00506         return -1;
00507       }
00508       if (circular_move->end.tran.x < stat->motion.axis[0].minPositionLimit) {
00509         emcOperatorError(0, "%s\n%s", stat->task.command, "exceeds -X limit");
00510         return -1;
00511       }
00512       if (circular_move->end.tran.y < stat->motion.axis[1].minPositionLimit) {
00513         emcOperatorError(0, "%s\n%s", stat->task.command, "exceeds -Y limit");
00514         return -1;
00515       }
00516       if (circular_move->end.tran.z < stat->motion.axis[2].minPositionLimit) {
00517         emcOperatorError(0, "%s\n%s", stat->task.command, "exceeds -Z limit");
00518         return -1;
00519       }
00520       break;
00521 
00522     default:
00523       break;
00524     }
00525   }
00526 
00527   return 0;
00528 
00529   // get rid of the compile-time cast shortcuts
00530 #undef circular_move_msg
00531 #undef linear_move_msg
00532 #undef operator_error_msg
00533 }
00534 
00535 /*
00536   emcTaskPlan()
00537 
00538   Planner for NC code or manual mode operations
00539   */
00540 static int emcTaskPlan(void)
00541 {
00542   NMLTYPE type;
00543   static char errstring[200];
00544   int retval = 0;
00545   int readRetval;
00546   int execRetval;
00547 
00548   // check for new command
00549   if (emcCommand->serial_number !=
00550       emcStatus->echo_serial_number) {
00551     // flag it here locally as a new command
00552     type = emcCommand->type;
00553   }
00554   else {
00555     // no new command-- reset local flag
00556     type = 0;
00557   }
00558 
00559   // handle any new command
00560   switch (emcStatus->task.state) {
00561   case EMC_TASK_STATE_OFF:
00562   case EMC_TASK_STATE_ESTOP:
00563   case EMC_TASK_STATE_ESTOP_RESET:
00564 
00565     // now switch on the mode
00566     switch (emcStatus->task.mode) {
00567     case EMC_TASK_MODE_MANUAL:
00568     case EMC_TASK_MODE_AUTO:
00569     case EMC_TASK_MODE_MDI:
00570 
00571       // now switch on the command
00572       switch (type) {
00573       case 0:
00574       case EMC_NULL_TYPE:
00575         // no command
00576         break;
00577 
00578         // immediate commands
00579       case EMC_AXIS_SET_CYCLE_TIME_TYPE:
00580       case EMC_AXIS_SET_GAINS_TYPE:
00581       case EMC_AXIS_DISABLE_TYPE:
00582       case EMC_AXIS_ENABLE_TYPE:
00583       case EMC_AXIS_SET_OUTPUT_SCALE_TYPE:
00584       case EMC_AXIS_SET_FERROR_TYPE:
00585       case EMC_AXIS_SET_MIN_FERROR_TYPE:
00586       case EMC_AXIS_ABORT_TYPE:
00587       case EMC_AXIS_SET_OUTPUT_TYPE:
00588       case EMC_AXIS_LOAD_COMP_TYPE:
00589       case EMC_AXIS_ALTER_TYPE:
00590       case EMC_TRAJ_SET_SCALE_TYPE:
00591       case EMC_TRAJ_SET_VELOCITY_TYPE:
00592       case EMC_TASK_INIT_TYPE:
00593       case EMC_TASK_SET_MODE_TYPE:
00594       case EMC_TASK_SET_STATE_TYPE:
00595       case EMC_TASK_PLAN_INIT_TYPE:
00596       case EMC_TASK_PLAN_OPEN_TYPE:
00597       case EMC_TASK_ABORT_TYPE:
00598       case EMC_LOG_OPEN_TYPE:
00599       case EMC_LOG_START_TYPE:
00600       case EMC_LOG_STOP_TYPE:
00601       case EMC_LOG_CLOSE_TYPE:
00602       case EMC_TRAJ_SET_PROBE_INDEX_TYPE:
00603       case EMC_TRAJ_SET_PROBE_POLARITY_TYPE:
00604       case EMC_TRAJ_CLEAR_PROBE_TRIPPED_FLAG_TYPE:
00605       case EMC_TRAJ_PROBE_TYPE:
00606       case EMC_TRAJ_SET_TELEOP_ENABLE_TYPE:
00607       case EMC_SET_DEBUG_TYPE:
00608         retval = emcTaskIssueCommand(emcCommand);
00609         break;
00610 
00611         // one case where we need to be in manual mode
00612       case EMC_AXIS_OVERRIDE_LIMITS_TYPE:
00613         retval = 0;
00614         if (emcStatus->task.mode == EMC_TASK_MODE_MANUAL) {
00615           retval = emcTaskIssueCommand(emcCommand);
00616         }
00617         break;
00618 
00619         // queued commands
00620 
00621       case EMC_TASK_PLAN_EXECUTE_TYPE:
00622         // resynch the interpreter, since we may have moved externally
00623         emcTaskIssueCommand(&taskPlanSynchCmd);
00624         // and now call for interpreter execute
00625         retval = emcTaskIssueCommand(emcCommand);
00626         break;
00627 
00628       case EMC_TOOL_LOAD_TOOL_TABLE_TYPE:
00629       case EMC_TOOL_SET_OFFSET_TYPE:
00630         // send to IO
00631         emcTaskQueueCommand(emcCommand);
00632         // signify no more reading
00633         emcTaskPlanSetWait();
00634         if (EMC_DEBUG & EMC_DEBUG_INTERP) {
00635           rcs_print("emcTaskPlanSetWait() called\n");
00636         }
00637 
00638         // then resynch interpreter
00639         emcTaskQueueCommand(&taskPlanSynchCmd);
00640         break;
00641 
00642       default:
00643         emcOperatorError(0, "command (%s) cannot be executed until the machine is out of E-stop and turned on", emc_symbol_lookup(type));
00644         retval = -1;
00645         break;
00646 
00647       } // switch (type)
00648 
00649     default:
00650       // invalid mode
00651       break;
00652 
00653     } // switch (mode)
00654 
00655     break;                      // case EMC_TASK_STATE_OFF,ESTOP,ESTOP_RESET
00656 
00657   case EMC_TASK_STATE_ON:
00658     /* we can do everything (almost) when the machine is on, so
00659        let's switch on the execution mode */
00660     switch (emcStatus->task.mode) {
00661     case EMC_TASK_MODE_MANUAL:  // ON, MANUAL
00662       switch (type) {
00663       case 0:
00664       case EMC_NULL_TYPE:
00665         // no command
00666         break;
00667 
00668         // immediate commands
00669 
00670       case EMC_AXIS_DISABLE_TYPE:
00671       case EMC_AXIS_ENABLE_TYPE:
00672       case EMC_AXIS_SET_CYCLE_TIME_TYPE:
00673       case EMC_AXIS_SET_GAINS_TYPE:
00674       case EMC_AXIS_SET_INPUT_SCALE_TYPE:
00675       case EMC_AXIS_SET_OUTPUT_SCALE_TYPE:
00676       case EMC_AXIS_SET_FERROR_TYPE:
00677       case EMC_AXIS_SET_MIN_FERROR_TYPE:
00678       case EMC_AXIS_SET_MAX_POSITION_LIMIT_TYPE:
00679       case EMC_AXIS_SET_MIN_POSITION_LIMIT_TYPE:
00680       case EMC_AXIS_ABORT_TYPE:
00681       case EMC_AXIS_HALT_TYPE:
00682       case EMC_AXIS_HOME_TYPE:
00683       case EMC_AXIS_JOG_TYPE:
00684       case EMC_AXIS_INCR_JOG_TYPE:
00685       case EMC_AXIS_ABS_JOG_TYPE:
00686       case EMC_AXIS_OVERRIDE_LIMITS_TYPE:
00687       case EMC_AXIS_SET_OUTPUT_TYPE:
00688       case EMC_AXIS_ALTER_TYPE:
00689       case EMC_TRAJ_PAUSE_TYPE:
00690       case EMC_TRAJ_RESUME_TYPE:
00691       case EMC_TRAJ_ABORT_TYPE:
00692       case EMC_TRAJ_SET_SCALE_TYPE:
00693       case EMC_SPINDLE_ON_TYPE:
00694       case EMC_SPINDLE_OFF_TYPE:
00695       case EMC_SPINDLE_BRAKE_RELEASE_TYPE:
00696       case EMC_SPINDLE_BRAKE_ENGAGE_TYPE:
00697       case EMC_SPINDLE_INCREASE_TYPE:
00698       case EMC_SPINDLE_DECREASE_TYPE:
00699       case EMC_SPINDLE_CONSTANT_TYPE:
00700       case EMC_COOLANT_MIST_ON_TYPE:
00701       case EMC_COOLANT_MIST_OFF_TYPE:
00702       case EMC_COOLANT_FLOOD_ON_TYPE:
00703       case EMC_COOLANT_FLOOD_OFF_TYPE:
00704       case EMC_LUBE_ON_TYPE:
00705       case EMC_LUBE_OFF_TYPE:
00706       case EMC_TASK_SET_MODE_TYPE:
00707       case EMC_TASK_SET_STATE_TYPE:
00708       case EMC_TASK_ABORT_TYPE:
00709       case EMC_TASK_PLAN_PAUSE_TYPE:
00710       case EMC_TASK_PLAN_RESUME_TYPE:
00711       case EMC_TASK_PLAN_INIT_TYPE:
00712       case EMC_TASK_PLAN_SYNCH_TYPE:
00713       case EMC_LOG_OPEN_TYPE:
00714       case EMC_LOG_START_TYPE:
00715       case EMC_LOG_STOP_TYPE:
00716       case EMC_LOG_CLOSE_TYPE:
00717       case EMC_TRAJ_SET_PROBE_INDEX_TYPE:
00718       case EMC_TRAJ_SET_PROBE_POLARITY_TYPE:
00719       case EMC_TRAJ_CLEAR_PROBE_TRIPPED_FLAG_TYPE:
00720       case EMC_TRAJ_PROBE_TYPE:
00721       case EMC_TRAJ_SET_TELEOP_ENABLE_TYPE:
00722       case EMC_TRAJ_SET_TELEOP_VECTOR_TYPE:
00723       case EMC_SET_DEBUG_TYPE:
00724         retval = emcTaskIssueCommand(emcCommand);
00725         break;
00726 
00727         // queued commands
00728 
00729       case EMC_TASK_PLAN_EXECUTE_TYPE:
00730         // resynch the interpreter, since we may have moved externally
00731         emcTaskIssueCommand(&taskPlanSynchCmd);
00732         // and now call for interpreter execute
00733         retval = emcTaskIssueCommand(emcCommand);
00734         break;
00735 
00736       case EMC_TOOL_LOAD_TOOL_TABLE_TYPE:
00737       case EMC_TOOL_SET_OFFSET_TYPE:
00738         // send to IO
00739         emcTaskQueueCommand(emcCommand);
00740         // signify no more reading
00741         emcTaskPlanSetWait();
00742         if (EMC_DEBUG & EMC_DEBUG_INTERP) {
00743           rcs_print("emcTaskPlanSetWait() called\n");
00744         }
00745         // then resynch interpreter
00746         emcTaskQueueCommand(&taskPlanSynchCmd);
00747         break;
00748 
00749         // otherwise we can't handle it
00750       default:
00751         sprintf(errstring,"can't do that (%s) in manual mode",
00752                 emc_symbol_lookup(type));
00753         emcOperatorError(0, errstring);
00754         retval = -1;
00755         break;
00756 
00757       } // switch (type) in ON, MANUAL
00758 
00759       break;                    // case EMC_TASK_MODE_MANUAL
00760 
00761     case EMC_TASK_MODE_AUTO:            // ON, AUTO
00762       switch (emcStatus->task.interpState) {
00763       case EMC_TASK_INTERP_IDLE:        // ON, AUTO, IDLE
00764         switch (type) {
00765         case 0:
00766         case EMC_NULL_TYPE:
00767           // no command
00768           break;
00769 
00770           // immediate commands
00771 
00772         case EMC_AXIS_SET_CYCLE_TIME_TYPE:
00773         case EMC_AXIS_SET_GAINS_TYPE:
00774         case EMC_AXIS_SET_OUTPUT_SCALE_TYPE:
00775         case EMC_AXIS_SET_FERROR_TYPE:
00776         case EMC_AXIS_SET_MIN_FERROR_TYPE:
00777         case EMC_AXIS_SET_OUTPUT_TYPE:
00778         case EMC_AXIS_ALTER_TYPE:
00779         case EMC_TRAJ_PAUSE_TYPE:
00780         case EMC_TRAJ_RESUME_TYPE:
00781         case EMC_TRAJ_ABORT_TYPE:
00782         case EMC_TRAJ_SET_SCALE_TYPE:
00783         case EMC_SPINDLE_ON_TYPE:
00784         case EMC_SPINDLE_OFF_TYPE:
00785         case EMC_SPINDLE_BRAKE_RELEASE_TYPE:
00786         case EMC_SPINDLE_BRAKE_ENGAGE_TYPE:
00787         case EMC_SPINDLE_INCREASE_TYPE:
00788         case EMC_SPINDLE_DECREASE_TYPE:
00789         case EMC_SPINDLE_CONSTANT_TYPE:
00790         case EMC_COOLANT_MIST_ON_TYPE:
00791         case EMC_COOLANT_MIST_OFF_TYPE:
00792         case EMC_COOLANT_FLOOD_ON_TYPE:
00793         case EMC_COOLANT_FLOOD_OFF_TYPE:
00794         case EMC_LUBE_ON_TYPE:
00795         case EMC_LUBE_OFF_TYPE:
00796         case EMC_TASK_SET_MODE_TYPE:
00797         case EMC_TASK_SET_STATE_TYPE:
00798         case EMC_TASK_ABORT_TYPE:
00799         case EMC_TASK_PLAN_INIT_TYPE:
00800         case EMC_TASK_PLAN_OPEN_TYPE:
00801         case EMC_TASK_PLAN_RUN_TYPE:
00802         case EMC_TASK_PLAN_EXECUTE_TYPE:
00803         case EMC_TASK_PLAN_PAUSE_TYPE:
00804         case EMC_TASK_PLAN_RESUME_TYPE:
00805         case EMC_LOG_OPEN_TYPE:
00806         case EMC_LOG_START_TYPE:
00807         case EMC_LOG_STOP_TYPE:
00808         case EMC_LOG_CLOSE_TYPE:
00809         case EMC_TRAJ_SET_PROBE_INDEX_TYPE:
00810         case EMC_TRAJ_SET_PROBE_POLARITY_TYPE:
00811         case EMC_TRAJ_CLEAR_PROBE_TRIPPED_FLAG_TYPE:
00812         case EMC_TRAJ_PROBE_TYPE:
00813         case EMC_SET_DEBUG_TYPE:
00814           retval = emcTaskIssueCommand(emcCommand);
00815           break;
00816 
00817         case EMC_TASK_PLAN_STEP_TYPE:
00818           // handles case where first action is to step the program
00819           taskPlanRunCmd.line = 1; // run from start
00820           // FIXME-- can have GUI set this; send a run instead of a step
00821           retval = emcTaskIssueCommand(&taskPlanRunCmd);
00822           // issuing an EMC_TASK_PLAN_RUN message clears the stepping
00823           // flag-- reset it here
00824           stepping = 1;         // set step flag
00825           steppingWait = 0;     // don't wait for first one
00826           break;
00827 
00828         case EMC_TOOL_LOAD_TOOL_TABLE_TYPE:
00829         case EMC_TOOL_SET_OFFSET_TYPE:
00830           // send to IO
00831           emcTaskQueueCommand(emcCommand);
00832           // signify no more reading
00833           emcTaskPlanSetWait();
00834           if (EMC_DEBUG & EMC_DEBUG_INTERP) {
00835             rcs_print("emcTaskPlanSetWait() called\n");
00836           }
00837           // then resynch interpreter
00838           emcTaskQueueCommand(&taskPlanSynchCmd);
00839           break;
00840 
00841           // otherwise we can't handle it
00842         default:
00843           sprintf(errstring,"can't do that (%s) in auto mode with the interpreter idle",
00844                   emc_symbol_lookup(type));
00845           emcOperatorError(0, errstring);
00846           retval = -1;
00847           break;
00848 
00849         } // switch (type) in ON, AUTO, IDLE
00850 
00851         break;          // EMC_TASK_INTERP_IDLE
00852 
00853       case EMC_TASK_INTERP_READING: // ON, AUTO, READING
00854         switch (type) {
00855         case 0:
00856         case EMC_NULL_TYPE:
00857           // no command
00858           break;
00859 
00860           // immediate commands
00861 
00862         case EMC_AXIS_SET_CYCLE_TIME_TYPE:
00863         case EMC_AXIS_SET_GAINS_TYPE:
00864         case EMC_AXIS_SET_OUTPUT_SCALE_TYPE:
00865         case EMC_AXIS_SET_FERROR_TYPE:
00866         case EMC_AXIS_SET_MIN_FERROR_TYPE:
00867         case EMC_AXIS_SET_OUTPUT_TYPE:
00868         case EMC_AXIS_ALTER_TYPE:
00869         case EMC_TRAJ_PAUSE_TYPE:
00870         case EMC_TRAJ_RESUME_TYPE:
00871         case EMC_TRAJ_ABORT_TYPE:
00872         case EMC_TRAJ_SET_SCALE_TYPE:
00873         case EMC_SPINDLE_INCREASE_TYPE:
00874         case EMC_SPINDLE_DECREASE_TYPE:
00875         case EMC_SPINDLE_CONSTANT_TYPE:
00876         case EMC_TASK_PLAN_PAUSE_TYPE:
00877         case EMC_TASK_PLAN_RESUME_TYPE:
00878         case EMC_TASK_SET_MODE_TYPE:
00879         case EMC_TASK_SET_STATE_TYPE:
00880         case EMC_TASK_ABORT_TYPE:
00881         case EMC_LOG_OPEN_TYPE:
00882         case EMC_LOG_START_TYPE:
00883         case EMC_LOG_STOP_TYPE:
00884         case EMC_LOG_CLOSE_TYPE:
00885         case EMC_TRAJ_SET_PROBE_INDEX_TYPE:
00886         case EMC_TRAJ_SET_PROBE_POLARITY_TYPE:
00887         case EMC_TRAJ_CLEAR_PROBE_TRIPPED_FLAG_TYPE:
00888         case EMC_TRAJ_PROBE_TYPE:
00889         case EMC_SET_DEBUG_TYPE:
00890           retval = emcTaskIssueCommand(emcCommand);
00891           break;
00892 
00893         case EMC_TASK_PLAN_STEP_TYPE:
00894           stepping = 1; // set stepping mode in case it's not
00895           steppingWait = 0; // clear the wait
00896           break;
00897 
00898           // otherwise we can't handle it
00899         default:
00900           sprintf(errstring,"can't do that (%s) in auto mode with the interpreter reading",
00901                   emc_symbol_lookup(type));
00902           emcOperatorError(0, errstring);
00903           retval = -1;
00904           break;
00905 
00906         } // switch (type) in ON, AUTO, READING
00907 
00908         // now handle interpreter call logic
00909         if (interp_list.len() <= EMC_TASK_INTERP_MAX_LEN) {
00910           if (emcTaskPlanIsWait()) {
00911             // delay reading of next line until all is done
00912             if (interp_list.len() == 0 &&
00913                 emcTaskCommand == 0 &&
00914                 emcStatus->task.execState == EMC_TASK_EXEC_DONE) {
00915               emcTaskPlanClearWait();
00916               if (EMC_DEBUG & EMC_DEBUG_INTERP) {
00917                 rcs_print("emcTaskPlanClearWait() called\n");
00918               }
00919             }
00920           }
00921           else {
00922             readRetval = emcTaskPlanRead();
00923             if (EMC_DEBUG & EMC_DEBUG_INTERP) {
00924               rcs_print("emcTaskPlanRead() returned %d\n",readRetval);
00925             }
00926 #ifdef NEW_INTERPRETER
00927             if(readRetval > RS274NGC_MIN_ERROR ||
00928                readRetval == 3 /* RS274NGC_ENDFILE */ ||
00929 #else
00930             if (readRetval != -1 /* RS274NGC_ERROR */ ||
00931 #endif
00932                 readRetval == 1 /* RS274NGC_EXIT */ ||
00933                 readRetval == 2 /* RS274NGC_ENDFILE, RS274NGC_EXECUTE_FINISH */ )
00934 
00935               {
00936                 // end of file
00937                 emcStatus->task.interpState = EMC_TASK_INTERP_WAITING;
00938               }
00939             else {
00940               // got a good line
00941               // record the line number and command
00942               emcStatus->task.readLine = emcTaskPlanLine();
00943               if (EMC_DEBUG & EMC_DEBUG_INTERP) {
00944                 rcs_print("emcTaskPlanLine() returned %d\n", emcStatus->task.readLine);
00945               }
00946 
00947               interp_list.set_line_number(emcStatus->task.readLine);
00948               emcTaskPlanCommand((char *) &emcStatus->task.command);
00949               if (EMC_DEBUG & EMC_DEBUG_INTERP) {
00950                 rcs_print("emcTaskPlanCommand(%s) called. (line_number=%d)\n", ((char *) &emcStatus->task.command),emcStatus->task.readLine);
00951               }
00952               // and execute it
00953                  execRetval = emcTaskPlanExecute(0);
00954               if (EMC_DEBUG & EMC_DEBUG_INTERP) {
00955                 rcs_print("emcTaskPlanExecute(0) return %d\n", execRetval);
00956               }
00957               if (execRetval == -1 /* RS274NGC_ERROR */ ||
00958 #ifdef NEW_INTERPRETER
00959                   execRetval > RS274NGC_MIN_ERROR ||
00960 #endif
00961                   execRetval == 1 /* RS274NGC_EXIT */ ) {
00962                 // end of file
00963                 emcStatus->task.interpState = EMC_TASK_INTERP_WAITING;
00964               }
00965 #ifdef NEW_INTERPRETER
00966               else if (execRetval == 2 /* RS274NGC_EXECUTE_FINISH */ )
00967 #else
00968               else if (execRetval == 3 /* RS274NGC_EXECUTE_FINISH */ )
00969 #endif
00970                 {
00971                   // RS274NGC_EXECUTE_FINISH signifies
00972                   // that no more reading should be done until everything
00973                   // outstanding is completed
00974                   emcTaskPlanSetWait();
00975                   if (EMC_DEBUG & EMC_DEBUG_INTERP) {
00976                     rcs_print("emcTaskPlanSetWait() called\n");
00977                   }              
00978                   // and resynch interp WM
00979                   emcTaskQueueCommand(&taskPlanSynchCmd);
00980                 }
00981 #ifdef NEW_INTERPRETER
00982               else if (execRetval != 0 ) {
00983                 // end of file
00984                 emcStatus->task.interpState = EMC_TASK_INTERP_WAITING;
00985               }
00986 #endif
00987               else {
00988 
00989                 // executed a good line
00990               }
00991 
00992               // throw the results away if we're supposed to read
00993               // through it
00994               if (programStartLine < 0 ||
00995                   emcStatus->task.readLine < programStartLine) {
00996                 // we're stepping over lines, so check them for
00997                 // limits, etc. and clear then out
00998                 if (0 != checkInterpList(&interp_list, emcStatus)) {
00999                   // problem with actions, so do same as we did
01000                   // for a bad read from emcTaskPlanRead() above
01001                   emcStatus->task.interpState = EMC_TASK_INTERP_WAITING;
01002                 }
01003                 // and clear it regardless
01004                 interp_list.clear();
01005               }
01006             } // else read was OK, so execute
01007           } // else not emcTaskPlanIsWait
01008         } // if interp len is less than max
01009 
01010         break;          // EMC_TASK_INTERP_READING
01011 
01012       case EMC_TASK_INTERP_PAUSED:      // ON, AUTO, PAUSED
01013         switch (type) {
01014         case 0:
01015         case EMC_NULL_TYPE:
01016           // no command
01017           break;
01018 
01019           // immediate commands
01020 
01021         case EMC_AXIS_SET_CYCLE_TIME_TYPE:
01022         case EMC_AXIS_SET_GAINS_TYPE:
01023         case EMC_AXIS_SET_OUTPUT_SCALE_TYPE:
01024         case EMC_AXIS_SET_FERROR_TYPE:
01025         case EMC_AXIS_SET_MIN_FERROR_TYPE:
01026         case EMC_AXIS_SET_OUTPUT_TYPE:
01027         case EMC_AXIS_ALTER_TYPE:
01028         case EMC_TRAJ_PAUSE_TYPE:
01029         case EMC_TRAJ_RESUME_TYPE:
01030         case EMC_TRAJ_ABORT_TYPE:
01031         case EMC_TRAJ_SET_SCALE_TYPE:
01032         case EMC_SPINDLE_ON_TYPE:
01033         case EMC_SPINDLE_OFF_TYPE:
01034         case EMC_SPINDLE_BRAKE_RELEASE_TYPE:
01035         case EMC_SPINDLE_BRAKE_ENGAGE_TYPE:
01036         case EMC_SPINDLE_INCREASE_TYPE:
01037         case EMC_SPINDLE_DECREASE_TYPE:
01038         case EMC_SPINDLE_CONSTANT_TYPE:
01039         case EMC_COOLANT_MIST_ON_TYPE:
01040         case EMC_COOLANT_MIST_OFF_TYPE:
01041         case EMC_COOLANT_FLOOD_ON_TYPE:
01042         case EMC_COOLANT_FLOOD_OFF_TYPE:
01043         case EMC_LUBE_ON_TYPE:
01044         case EMC_LUBE_OFF_TYPE:
01045         case EMC_TASK_SET_MODE_TYPE:
01046         case EMC_TASK_SET_STATE_TYPE:
01047         case EMC_TASK_ABORT_TYPE:
01048         case EMC_TASK_PLAN_EXECUTE_TYPE:
01049         case EMC_TASK_PLAN_PAUSE_TYPE:
01050         case EMC_TASK_PLAN_RESUME_TYPE:
01051         case EMC_LOG_OPEN_TYPE:
01052         case EMC_LOG_START_TYPE:
01053         case EMC_LOG_STOP_TYPE:
01054         case EMC_LOG_CLOSE_TYPE:
01055         case EMC_TRAJ_SET_PROBE_INDEX_TYPE:
01056         case EMC_TRAJ_SET_PROBE_POLARITY_TYPE:
01057         case EMC_TRAJ_CLEAR_PROBE_TRIPPED_FLAG_TYPE:
01058         case EMC_TRAJ_PROBE_TYPE:
01059         case EMC_SET_DEBUG_TYPE:
01060           retval = emcTaskIssueCommand(emcCommand);
01061           break;
01062 
01063         case EMC_TASK_PLAN_STEP_TYPE:
01064           if (emcStatus->motion.traj.paused &&
01065               emcStatus->motion.traj.queue > 0) {
01066             // there are pending motions paused; step them
01067             emcTrajStep();
01068           }
01069           else {
01070             // motion is not paused, or it is but there is no queue,
01071             // so we can resume normal interpretation in step mode
01072             emcTrajResume();
01073             stepping = 1;       // set stepping mode in case it's not
01074             steppingWait = 0; // clear the wait
01075             emcStatus->task.interpState = interpResumeState;
01076           }
01077           break;
01078 
01079           // otherwise we can't handle it
01080         default:
01081           sprintf(errstring,"can't do that (%s) in auto mode with the interpreter paused",
01082                   emc_symbol_lookup(type));
01083           emcOperatorError(0, errstring);
01084           retval = -1;
01085           break;
01086 
01087         } // switch (type) in ON, AUTO, PAUSED
01088 
01089         break;          // EMC_TASK_INTERP_PAUSED
01090 
01091       case EMC_TASK_INTERP_WAITING:
01092         // interpreter ran to end
01093         // handle input commands
01094         switch (type) {
01095         case 0:
01096         case EMC_NULL_TYPE:
01097           // no command
01098           break;
01099 
01100           // immediate commands
01101 
01102         case EMC_AXIS_SET_CYCLE_TIME_TYPE:
01103         case EMC_AXIS_SET_GAINS_TYPE:
01104         case EMC_AXIS_SET_OUTPUT_SCALE_TYPE:
01105         case EMC_AXIS_SET_FERROR_TYPE:
01106         case EMC_AXIS_SET_MIN_FERROR_TYPE:
01107         case EMC_AXIS_SET_OUTPUT_TYPE:
01108         case EMC_AXIS_ALTER_TYPE:
01109         case EMC_TRAJ_PAUSE_TYPE:
01110         case EMC_TRAJ_RESUME_TYPE:
01111         case EMC_TRAJ_ABORT_TYPE:
01112         case EMC_TRAJ_SET_SCALE_TYPE:
01113         case EMC_SPINDLE_INCREASE_TYPE:
01114         case EMC_SPINDLE_DECREASE_TYPE:
01115         case EMC_SPINDLE_CONSTANT_TYPE:
01116         case EMC_TASK_PLAN_EXECUTE_TYPE:
01117         case EMC_TASK_PLAN_PAUSE_TYPE:
01118         case EMC_TASK_PLAN_RESUME_TYPE:
01119         case EMC_TASK_SET_MODE_TYPE:
01120         case EMC_TASK_SET_STATE_TYPE:
01121         case EMC_TASK_ABORT_TYPE:
01122         case EMC_LOG_OPEN_TYPE:
01123         case EMC_LOG_START_TYPE:
01124         case EMC_LOG_STOP_TYPE:
01125         case EMC_LOG_CLOSE_TYPE:
01126         case EMC_TRAJ_SET_PROBE_INDEX_TYPE:
01127         case EMC_TRAJ_SET_PROBE_POLARITY_TYPE:
01128         case EMC_TRAJ_CLEAR_PROBE_TRIPPED_FLAG_TYPE:
01129         case EMC_TRAJ_PROBE_TYPE:
01130         case EMC_SET_DEBUG_TYPE:
01131           retval = emcTaskIssueCommand(emcCommand);
01132           break;
01133 
01134         case EMC_TASK_PLAN_STEP_TYPE:
01135           stepping = 1; // set stepping mode in case it's not
01136           steppingWait = 0; // clear the wait
01137           break;
01138 
01139           // otherwise we can't handle it
01140         default:
01141           sprintf(errstring,"can't do that (%s) in auto mode with the interpreter waiting",
01142                   emc_symbol_lookup(type));
01143           emcOperatorError(0, errstring);
01144           retval = -1;
01145           break;
01146 
01147         } // switch (type) in ON, AUTO, WAITING
01148 
01149         // now handle call logic
01150         // check for subsystems done
01151         if (interp_list.len() == 0 &&
01152             emcTaskCommand == 0 &&
01153             emcStatus->motion.traj.queue == 0 &&
01154             emcStatus->io.status == RCS_DONE) 
01155           // finished
01156           {  
01157             int was_open = taskplanopen;
01158             if(was_open)
01159               {
01160                 emcTaskPlanClose();
01161                 if (EMC_DEBUG & EMC_DEBUG_INTERP && was_open) {
01162                   rcs_print("emcTaskPlanClose() called at %s:%d\n",__FILE__,__LINE__);
01163                 }
01164                 // then resynch interpreter
01165                 emcTaskQueueCommand(&taskPlanSynchCmd);
01166               }
01167             else
01168               {
01169                 emcStatus->task.interpState = EMC_TASK_INTERP_IDLE;
01170               }     
01171             emcStatus->task.readLine = 0;
01172             interp_list.set_line_number(0);             
01173           }
01174         else {
01175           // still executing
01176         }
01177 
01178         break;                  // end of case EMC_TASK_INTERP_WAITING
01179 
01180       default:
01181         // coding error
01182         rcs_print_error("invalid mode(%d)",emcStatus->task.mode);
01183         retval = -1;
01184         break;
01185 
01186       } // switch (mode) in ON, AUTO
01187 
01188       break;            // case EMC_TASK_MODE_AUTO
01189 
01190     case EMC_TASK_MODE_MDI:             // ON, MDI
01191       switch (type) {
01192       case 0:
01193       case EMC_NULL_TYPE:
01194         // no command
01195         break;
01196 
01197         // immediate commands
01198 
01199       case EMC_AXIS_SET_CYCLE_TIME_TYPE:
01200       case EMC_AXIS_SET_GAINS_TYPE:
01201       case EMC_AXIS_SET_OUTPUT_SCALE_TYPE:
01202       case EMC_AXIS_SET_FERROR_TYPE:
01203       case EMC_AXIS_SET_MIN_FERROR_TYPE:
01204       case EMC_AXIS_SET_OUTPUT_TYPE:
01205       case EMC_AXIS_ALTER_TYPE:
01206       case EMC_TRAJ_SET_SCALE_TYPE:
01207       case EMC_SPINDLE_ON_TYPE:
01208       case EMC_SPINDLE_OFF_TYPE:
01209       case EMC_SPINDLE_BRAKE_RELEASE_TYPE:
01210       case EMC_SPINDLE_BRAKE_ENGAGE_TYPE:
01211       case EMC_SPINDLE_INCREASE_TYPE:
01212       case EMC_SPINDLE_DECREASE_TYPE:
01213       case EMC_SPINDLE_CONSTANT_TYPE:
01214       case EMC_COOLANT_MIST_ON_TYPE:
01215       case EMC_COOLANT_MIST_OFF_TYPE:
01216       case EMC_COOLANT_FLOOD_ON_TYPE:
01217       case EMC_COOLANT_FLOOD_OFF_TYPE:
01218       case EMC_LUBE_ON_TYPE:
01219       case EMC_LUBE_OFF_TYPE:
01220       case EMC_TASK_SET_MODE_TYPE:
01221       case EMC_TASK_SET_STATE_TYPE:
01222       case EMC_TASK_PLAN_INIT_TYPE:
01223       case EMC_TASK_PLAN_OPEN_TYPE:
01224       case EMC_TASK_PLAN_EXECUTE_TYPE:
01225       case EMC_TASK_PLAN_PAUSE_TYPE:
01226       case EMC_TASK_PLAN_RESUME_TYPE:
01227       case EMC_TASK_ABORT_TYPE:
01228       case EMC_LOG_OPEN_TYPE:
01229       case EMC_LOG_START_TYPE:
01230       case EMC_LOG_STOP_TYPE:
01231       case EMC_LOG_CLOSE_TYPE:
01232       case EMC_TRAJ_SET_PROBE_INDEX_TYPE:
01233       case EMC_TRAJ_SET_PROBE_POLARITY_TYPE:
01234       case EMC_TRAJ_CLEAR_PROBE_TRIPPED_FLAG_TYPE:
01235       case EMC_TRAJ_PROBE_TYPE:
01236       case EMC_SET_DEBUG_TYPE:
01237         retval = emcTaskIssueCommand(emcCommand);
01238         break;
01239 
01240       case EMC_TOOL_LOAD_TOOL_TABLE_TYPE:
01241       case EMC_TOOL_SET_OFFSET_TYPE:
01242         // send to IO
01243         emcTaskQueueCommand(emcCommand);
01244         // signify no more reading
01245         emcTaskPlanSetWait();
01246         if (EMC_DEBUG & EMC_DEBUG_INTERP) {
01247           rcs_print("emcTaskPlanSetWait() called\n");
01248         }
01249         // then resynch interpreter
01250         emcTaskQueueCommand(&taskPlanSynchCmd);
01251         break;
01252 
01253         // otherwise we can't handle it
01254       default:
01255         
01256         sprintf(errstring,"can't do that (%s) in MDI mode",
01257                 emc_symbol_lookup(type));
01258         emcOperatorError(0, errstring);
01259         retval = -1;
01260         break;
01261 
01262       } // switch (type) in ON, MDI
01263 
01264       break;            // case EMC_TASK_MODE_MDI
01265 
01266     default:
01267       break;
01268 
01269     } // switch (mode)
01270 
01271     break;                      // case EMC_TASK_STATE_ON
01272 
01273   default:
01274     break;
01275 
01276   } // switch (task.state)
01277 
01278   return retval;
01279 }
01280 
01281 /*
01282    emcTaskCheckPreconditions() is called for commands on the interp_list.
01283    Immediate commands, i.e., commands sent from calls to emcTaskIssueCommand()
01284    in emcTaskPlan() directly, are not handled here.
01285 
01286    The return value is a state for emcTaskExecute() to wait on, e.g.,
01287    EMC_TASK_EXEC_WAITING_FOR_MOTION, before the command can be sent out.
01288    */
01289 static int emcTaskCheckPreconditions(NMLmsg * cmd)
01290 {
01291   if (0 == cmd) {
01292     return EMC_TASK_EXEC_DONE;
01293   }
01294 
01295   switch (cmd->type) {
01296     // operator messages, if queued, will go out when everything before
01297     // them is done
01298   case EMC_OPERATOR_ERROR_TYPE:
01299   case EMC_OPERATOR_TEXT_TYPE:
01300   case EMC_OPERATOR_DISPLAY_TYPE:
01301   case EMC_TRAJ_PROBE_TYPE:     // prevent blending of this
01302   case EMC_TRAJ_CLEAR_PROBE_TRIPPED_FLAG_TYPE: // and this
01303     return EMC_TASK_EXEC_WAITING_FOR_MOTION_AND_IO;
01304     break;
01305 
01306   case EMC_TRAJ_LINEAR_MOVE_TYPE:
01307   case EMC_TRAJ_CIRCULAR_MOVE_TYPE:
01308   case EMC_TRAJ_SET_VELOCITY_TYPE:
01309   case EMC_TRAJ_SET_TERM_COND_TYPE:
01310     return EMC_TASK_EXEC_WAITING_FOR_IO;
01311     break;
01312 
01313   case EMC_TRAJ_SET_OFFSET_TYPE:
01314     // this applies the tool length offset variable after previous motions
01315   case EMC_TRAJ_SET_ORIGIN_TYPE:
01316     // this applies the program origin after previous motions
01317     return EMC_TASK_EXEC_WAITING_FOR_MOTION;
01318     break;
01319 
01320   case EMC_TOOL_LOAD_TYPE:
01321   case EMC_TOOL_UNLOAD_TYPE:
01322   case EMC_COOLANT_MIST_ON_TYPE:
01323   case EMC_COOLANT_MIST_OFF_TYPE:
01324   case EMC_COOLANT_FLOOD_ON_TYPE:
01325   case EMC_COOLANT_FLOOD_OFF_TYPE:
01326   case EMC_SPINDLE_ON_TYPE:
01327   case EMC_SPINDLE_OFF_TYPE:
01328     return EMC_TASK_EXEC_WAITING_FOR_MOTION_AND_IO;
01329     break;
01330 
01331   case EMC_TOOL_PREPARE_TYPE:
01332   case EMC_LUBE_ON_TYPE:
01333   case EMC_LUBE_OFF_TYPE:
01334     return EMC_TASK_EXEC_WAITING_FOR_IO;
01335     break;
01336 
01337   case EMC_TOOL_LOAD_TOOL_TABLE_TYPE:
01338   case EMC_TOOL_SET_OFFSET_TYPE:
01339     return EMC_TASK_EXEC_WAITING_FOR_MOTION_AND_IO;
01340     break;
01341 
01342   case EMC_TASK_PLAN_PAUSE_TYPE:
01343     /* pause on the interp list is queued, so wait
01344        until all are done */
01345     return EMC_TASK_EXEC_WAITING_FOR_MOTION_AND_IO;
01346     break;
01347 
01348   case EMC_TASK_PLAN_END_TYPE:
01349     return EMC_TASK_EXEC_WAITING_FOR_MOTION_AND_IO;
01350     break;
01351 
01352   case EMC_TASK_PLAN_INIT_TYPE:
01353   case EMC_TASK_PLAN_RUN_TYPE:
01354   case EMC_TASK_PLAN_SYNCH_TYPE:
01355   case EMC_TASK_PLAN_EXECUTE_TYPE:
01356     return EMC_TASK_EXEC_WAITING_FOR_MOTION_AND_IO;
01357     break;
01358 
01359   case EMC_TRAJ_DELAY_TYPE:
01360     return EMC_TASK_EXEC_WAITING_FOR_MOTION_AND_IO;
01361     break;
01362 
01363   case EMC_MOTION_SET_AOUT_TYPE:
01364   case EMC_MOTION_SET_DOUT_TYPE:
01365     return EMC_TASK_EXEC_DONE;
01366     break;
01367 
01368   default:
01369     // unrecognized command
01370     if (EMC_DEBUG & EMC_DEBUG_TASK_ISSUE) {
01371       rcs_print_error("preconditions: unrecognized command %d:%s\n",cmd->type, 
01372                       emc_symbol_lookup(cmd->type));
01373     }
01374     return EMC_TASK_EXEC_ERROR;
01375     break;
01376   }
01377 
01378   return EMC_TASK_EXEC_DONE;
01379 }
01380 
01381 // puts command on interp list
01382 static int emcTaskQueueCommand(NMLmsg * cmd)
01383 {
01384   if (0 == cmd) {
01385     return 0;
01386   }
01387 
01388   interp_list.append(cmd);
01389 
01390   return 0;
01391 }
01392 
01393 // issues command immediately
01394 static int emcTaskIssueCommand(NMLmsg * cmd)
01395 {
01396   int retval = 0;
01397   int execRetval = 0;
01398 
01399   if (0 == cmd) {
01400     return 0;
01401   }
01402 
01403   if (EMC_DEBUG & EMC_DEBUG_TASK_ISSUE) {
01404     rcs_print("Issuing %s -- \t (%s)\n", emcSymbolLookup(cmd->type),
01405               emcCommandBuffer->msg2str(cmd));
01406   }
01407 
01408   switch (cmd->type) {
01409     // general commands
01410 
01411   case EMC_OPERATOR_ERROR_TYPE:
01412     retval = emcOperatorError(((EMC_OPERATOR_ERROR *) cmd)->id,
01413                               ((EMC_OPERATOR_ERROR *) cmd)->error);
01414     break;
01415 
01416   case EMC_OPERATOR_TEXT_TYPE:
01417     retval = emcOperatorText(((EMC_OPERATOR_TEXT *) cmd)->id,
01418                              ((EMC_OPERATOR_TEXT *) cmd)->text);
01419     break;
01420 
01421   case EMC_OPERATOR_DISPLAY_TYPE:
01422     retval = emcOperatorDisplay(((EMC_OPERATOR_DISPLAY *) cmd)->id,
01423                                 ((EMC_OPERATOR_DISPLAY *) cmd)->display);
01424     break;
01425 
01426     // axis commands
01427 
01428   case EMC_AXIS_DISABLE_TYPE:
01429     disable_msg = (EMC_AXIS_DISABLE *) cmd;
01430     retval = emcAxisDisable(disable_msg->axis);
01431     break;
01432 
01433   case EMC_AXIS_ENABLE_TYPE:
01434     enable_msg = (EMC_AXIS_ENABLE *) cmd;
01435     retval = emcAxisEnable(enable_msg->axis);
01436     break;
01437 
01438   case EMC_AXIS_HOME_TYPE:
01439     home_msg = (EMC_AXIS_HOME *) cmd;
01440     retval = emcAxisHome(home_msg->axis);
01441     break;
01442 
01443   case EMC_AXIS_JOG_TYPE:
01444     jog_msg = (EMC_AXIS_JOG *) cmd;
01445     retval = emcAxisJog(jog_msg->axis, jog_msg->vel);
01446     break;
01447 
01448   case EMC_AXIS_ABORT_TYPE:
01449     axis_abort_msg = (EMC_AXIS_ABORT *) cmd;
01450     retval = emcAxisAbort(axis_abort_msg->axis);
01451     break;
01452 
01453   case EMC_AXIS_INCR_JOG_TYPE:
01454     incr_jog_msg = (EMC_AXIS_INCR_JOG *) cmd;
01455     retval = emcAxisIncrJog(incr_jog_msg->axis,
01456                             incr_jog_msg->incr,
01457                             incr_jog_msg->vel);
01458     break;
01459 
01460   case EMC_AXIS_ABS_JOG_TYPE:
01461     abs_jog_msg = (EMC_AXIS_ABS_JOG *) cmd;
01462     retval = emcAxisAbsJog(abs_jog_msg->axis,
01463                            abs_jog_msg->pos,
01464                            abs_jog_msg->vel);
01465     break;
01466 
01467   case EMC_AXIS_SET_GAINS_TYPE:
01468     set_gains_msg = (EMC_AXIS_SET_GAINS *) cmd;
01469     retval = emcAxisSetGains(set_gains_msg->axis,
01470                              set_gains_msg->p,
01471                              set_gains_msg->i,
01472                              set_gains_msg->d,
01473                              set_gains_msg->ff0,
01474                              set_gains_msg->ff1,
01475                              set_gains_msg->ff2,
01476                              set_gains_msg->backlash,
01477                              set_gains_msg->bias,
01478                              set_gains_msg->maxError,
01479                              set_gains_msg->deadband);
01480     break;
01481 
01482   case EMC_AXIS_SET_CYCLE_TIME_TYPE:
01483     set_cycle_time_msg = (EMC_AXIS_SET_CYCLE_TIME *) cmd;
01484     retval = emcAxisSetCycleTime(set_cycle_time_msg->axis,
01485                                  set_cycle_time_msg->cycleTime);
01486     break;
01487 
01488   case EMC_AXIS_SET_INPUT_SCALE_TYPE:
01489     set_input_scale_msg = (EMC_AXIS_SET_INPUT_SCALE *) cmd;
01490     retval = emcAxisSetInputScale(set_input_scale_msg->axis,
01491                                   set_input_scale_msg->scale,
01492                                   set_input_scale_msg->offset);
01493     break;
01494 
01495   case EMC_AXIS_SET_OUTPUT_SCALE_TYPE:
01496     set_output_scale_msg = (EMC_AXIS_SET_OUTPUT_SCALE *) cmd;
01497     retval = emcAxisSetOutputScale(set_output_scale_msg->axis,
01498                                    set_output_scale_msg->scale,
01499                                    set_output_scale_msg->offset);
01500     break;
01501 
01502   case EMC_AXIS_SET_FERROR_TYPE:
01503     set_ferror_msg = (EMC_AXIS_SET_FERROR *) cmd;
01504     retval = emcAxisSetFerror(set_ferror_msg->axis,
01505                               set_ferror_msg->ferror);
01506     break;
01507 
01508   case EMC_AXIS_SET_MIN_FERROR_TYPE:
01509     set_min_ferror_msg = (EMC_AXIS_SET_MIN_FERROR *) cmd;
01510     retval = emcAxisSetMinFerror(set_min_ferror_msg->axis,
01511                                  set_min_ferror_msg->ferror);
01512     break;
01513 
01514   case EMC_AXIS_SET_MAX_POSITION_LIMIT_TYPE:
01515     set_max_limit_msg = (EMC_AXIS_SET_MAX_POSITION_LIMIT *) cmd;
01516     retval = emcAxisSetMaxPositionLimit(set_max_limit_msg->axis,
01517                                         set_max_limit_msg->limit);
01518     break;
01519 
01520   case EMC_AXIS_SET_MIN_POSITION_LIMIT_TYPE:
01521     set_min_limit_msg = (EMC_AXIS_SET_MIN_POSITION_LIMIT *) cmd;
01522     retval = emcAxisSetMinPositionLimit(set_min_limit_msg->axis,
01523                                         set_min_limit_msg->limit);
01524     break;
01525 
01526   case EMC_AXIS_HALT_TYPE:
01527     axis_halt_msg = (EMC_AXIS_HALT *) cmd;
01528     retval = emcAxisHalt(axis_halt_msg->axis);
01529     break;
01530 
01531   case EMC_AXIS_OVERRIDE_LIMITS_TYPE:
01532     axis_lim_msg = (EMC_AXIS_OVERRIDE_LIMITS *) cmd;
01533     retval = emcAxisOverrideLimits(axis_lim_msg->axis);
01534     break;
01535 
01536   case EMC_AXIS_SET_OUTPUT_TYPE:
01537     axis_output_msg = (EMC_AXIS_SET_OUTPUT *) cmd;
01538     retval = emcAxisSetOutput(axis_output_msg->axis,
01539                               axis_output_msg->output);
01540     break;
01541 
01542   case EMC_AXIS_LOAD_COMP_TYPE:
01543     axis_load_comp_msg = (EMC_AXIS_LOAD_COMP *) cmd;
01544     retval = emcAxisLoadComp(axis_load_comp_msg->axis,
01545                              axis_load_comp_msg->file);
01546     break;
01547 
01548   case EMC_AXIS_ALTER_TYPE:
01549     axis_alter_msg = (EMC_AXIS_ALTER *) cmd;
01550     retval = emcAxisAlter(axis_alter_msg->axis,
01551                           axis_alter_msg->alter);
01552     break;
01553 
01554     // traj commands
01555 
01556   case EMC_TRAJ_SET_SCALE_TYPE:
01557     emcTrajSetScaleMsg =
01558       (EMC_TRAJ_SET_SCALE *) cmd;
01559     retval = emcTrajSetScale(emcTrajSetScaleMsg->scale);
01560     break;
01561 
01562   case EMC_TRAJ_SET_VELOCITY_TYPE:
01563     emcTrajSetVelocityMsg =
01564       (EMC_TRAJ_SET_VELOCITY *) cmd;
01565     retval = emcTrajSetVelocity(emcTrajSetVelocityMsg->velocity);
01566     break;
01567 
01568   case EMC_TRAJ_LINEAR_MOVE_TYPE:
01569     emcTrajLinearMoveMsg = (EMC_TRAJ_LINEAR_MOVE *) cmd;
01570     retval = emcTrajLinearMove(emcTrajLinearMoveMsg->end);
01571     break;
01572 
01573   case EMC_TRAJ_CIRCULAR_MOVE_TYPE:
01574     emcTrajCircularMoveMsg = (EMC_TRAJ_CIRCULAR_MOVE *) cmd;
01575     retval = emcTrajCircularMove(emcTrajCircularMoveMsg->end,
01576                                  emcTrajCircularMoveMsg->center,
01577                                  emcTrajCircularMoveMsg->normal,
01578                                  emcTrajCircularMoveMsg->turn);
01579     break;
01580 
01581   case EMC_TRAJ_PAUSE_TYPE:
01582     retval = emcTrajPause();
01583     break;
01584 
01585   case EMC_TRAJ_RESUME_TYPE:
01586     retval = emcTrajResume();
01587     break;
01588 
01589   case EMC_TRAJ_ABORT_TYPE:
01590     retval = emcTrajAbort();
01591     break;
01592 
01593   case EMC_TRAJ_DELAY_TYPE:
01594     emcTrajDelayMsg = (EMC_TRAJ_DELAY *) cmd;
01595 #if defined(LINUX_KERNEL_2_2)
01596     // load the timeout delta clock
01597     taskExecDelayTimeout = emcTrajDelayMsg->delay;
01598 #else
01599     // set the timeout clock to expire at 'now' + delay time
01600     taskExecDelayTimeout = etime() + emcTrajDelayMsg->delay;
01601 #endif
01602     retval = 0;
01603     break;
01604 
01605   case EMC_TRAJ_SET_TERM_COND_TYPE:
01606     emcTrajSetTermCondMsg = (EMC_TRAJ_SET_TERM_COND *) cmd;
01607     retval = emcTrajSetTermCond(emcTrajSetTermCondMsg->cond);
01608     break;
01609 
01610   case EMC_TRAJ_SET_OFFSET_TYPE:
01611     // update tool offset
01612     emcStatus->task.toolOffset.tran.z =
01613       ((EMC_TRAJ_SET_OFFSET *) cmd)->offset.tran.z;
01614     retval = 0;
01615     break;
01616 
01617   case EMC_TRAJ_SET_ORIGIN_TYPE:
01618     // struct-copy program origin
01619     emcStatus->task.origin =
01620       ((EMC_TRAJ_SET_ORIGIN *) cmd)->origin;
01621     retval = 0;
01622     break;
01623 
01624   case EMC_TRAJ_SET_PROBE_INDEX_TYPE:
01625     retval = emcTrajSetProbeIndex(((EMC_TRAJ_SET_PROBE_INDEX *)cmd)->index);
01626     break;
01627 
01628   case EMC_TRAJ_SET_PROBE_POLARITY_TYPE:
01629     retval = emcTrajSetProbePolarity(((EMC_TRAJ_SET_PROBE_POLARITY *)cmd)->polarity);
01630     break;
01631 
01632   case EMC_TRAJ_CLEAR_PROBE_TRIPPED_FLAG_TYPE:
01633     retval = emcTrajClearProbeTrippedFlag();
01634     break;
01635 
01636   case EMC_TRAJ_PROBE_TYPE:
01637     retval = emcTrajProbe(((EMC_TRAJ_PROBE *)cmd)->pos);
01638     break;
01639 
01640   case EMC_TRAJ_SET_TELEOP_ENABLE_TYPE:
01641     if (((EMC_TRAJ_SET_TELEOP_ENABLE *) cmd)->enable) {
01642       retval = emcTrajSetMode(EMC_TRAJ_MODE_TELEOP);
01643     }
01644     else {
01645       retval = emcTrajSetMode(EMC_TRAJ_MODE_FREE);
01646     }
01647     break;
01648 
01649   case EMC_TRAJ_SET_TELEOP_VECTOR_TYPE:
01650     retval = emcTrajSetTeleopVector(((EMC_TRAJ_SET_TELEOP_VECTOR *)cmd)->vector);
01651     break;
01652 
01653   case EMC_MOTION_SET_AOUT_TYPE:
01654     retval = emcMotionSetAout(((EMC_MOTION_SET_AOUT *)cmd)->index,
01655                               ((EMC_MOTION_SET_AOUT *)cmd)->start,
01656                               ((EMC_MOTION_SET_AOUT *)cmd)->end);
01657     break;
01658 
01659   case EMC_MOTION_SET_DOUT_TYPE:
01660     retval = emcMotionSetDout(((EMC_MOTION_SET_DOUT *)cmd)->index,
01661                               ((EMC_MOTION_SET_DOUT *)cmd)->start,
01662                               ((EMC_MOTION_SET_DOUT *)cmd)->end);
01663     break;
01664 
01665   case EMC_SET_DEBUG_TYPE:
01666     /* set the debug level here */
01667     EMC_DEBUG = ((EMC_SET_DEBUG *) cmd)->debug;
01668     /* and in IO and motion */
01669     emcIoSetDebug(EMC_DEBUG);
01670     emcMotionSetDebug(EMC_DEBUG);
01671     /* and reflect it in the status-- this isn't updated continually */
01672     emcStatus->debug = EMC_DEBUG;
01673     break;
01674     
01675     // unimplemented ones
01676 
01677     // IO commands
01678 
01679   case EMC_SPINDLE_ON_TYPE:
01680     spindle_on_msg = (EMC_SPINDLE_ON *) cmd;
01681     retval = emcSpindleOn(spindle_on_msg->speed);
01682     break;
01683 
01684   case EMC_SPINDLE_OFF_TYPE:
01685     retval = emcSpindleOff();
01686     break;
01687 
01688   case EMC_SPINDLE_BRAKE_RELEASE_TYPE:
01689     retval = emcSpindleBrakeRelease();
01690     break;
01691 
01692   case EMC_SPINDLE_INCREASE_TYPE:
01693     retval = emcSpindleIncrease();
01694     break;
01695 
01696   case EMC_SPINDLE_DECREASE_TYPE:
01697     retval = emcSpindleDecrease();
01698     break;
01699 
01700   case EMC_SPINDLE_CONSTANT_TYPE:
01701     retval = emcSpindleConstant();
01702     break;
01703 
01704   case EMC_SPINDLE_BRAKE_ENGAGE_TYPE:
01705     retval = emcSpindleBrakeEngage();
01706     break;
01707 
01708   case EMC_COOLANT_MIST_ON_TYPE:
01709     retval = emcCoolantMistOn();
01710     break;
01711 
01712   case EMC_COOLANT_MIST_OFF_TYPE:
01713     retval = emcCoolantMistOff();
01714     break;
01715 
01716   case EMC_COOLANT_FLOOD_ON_TYPE:
01717     retval = emcCoolantFloodOn();
01718     break;
01719 
01720   case EMC_COOLANT_FLOOD_OFF_TYPE:
01721     retval = emcCoolantFloodOff();
01722     break;
01723 
01724   case EMC_LUBE_ON_TYPE:
01725     retval = emcLubeOn();
01726     break;
01727 
01728   case EMC_LUBE_OFF_TYPE:
01729     retval = emcLubeOff();
01730     break;
01731 
01732   case EMC_TOOL_PREPARE_TYPE:
01733     tool_prepare_msg = (EMC_TOOL_PREPARE *) cmd;
01734     retval = emcToolPrepare(tool_prepare_msg->tool);
01735     break;
01736 
01737   case EMC_TOOL_LOAD_TYPE:
01738     retval = emcToolLoad();
01739     break;
01740 
01741   case EMC_TOOL_UNLOAD_TYPE:
01742     retval = emcToolUnload();
01743     break;
01744 
01745   case EMC_TOOL_LOAD_TOOL_TABLE_TYPE:
01746     load_tool_table_msg = (EMC_TOOL_LOAD_TOOL_TABLE *) cmd;
01747     retval = emcToolLoadToolTable(load_tool_table_msg->file);
01748     break;
01749 
01750   case EMC_TOOL_SET_OFFSET_TYPE:
01751     emc_tool_set_offset_msg = (EMC_TOOL_SET_OFFSET *) cmd;
01752     retval = emcToolSetOffset(emc_tool_set_offset_msg->tool,
01753                               emc_tool_set_offset_msg->length,
01754                               emc_tool_set_offset_msg->diameter);
01755     break;
01756 
01757     // task commands
01758 
01759   case EMC_TASK_INIT_TYPE:
01760     retval = emcTaskInit();
01761     break;
01762 
01763   case EMC_TASK_ABORT_TYPE:
01764 
01765     // FIXME-- duplicate code for abort,
01766     // also near end of main, when aborting on subordinate errors,
01767     // and in emcTaskExecute()
01768 
01769     // abort everything
01770     emcTaskAbort();
01771 
01772     // without emcTaskPlanClose(), a new run command resumes at
01773     // aborted line-- feature that may be considered later
01774     { 
01775       int was_open = taskplanopen;
01776       emcTaskPlanClose();
01777       if (EMC_DEBUG & EMC_DEBUG_INTERP && was_open) {
01778         rcs_print("emcTaskPlanClose() called at %s:%d\n",__FILE__,__LINE__);
01779       }
01780     }   
01781 
01782     // clear out the pending command
01783     emcTaskCommand = 0;
01784     interp_list.clear();
01785 
01786     // clear out the interpreter state
01787     emcStatus->task.interpState = EMC_TASK_INTERP_IDLE;
01788     emcStatus->task.execState = EMC_TASK_EXEC_DONE;
01789     stepping = 0;
01790     steppingWait = 0;
01791 
01792     // now queue up command to resynch interpreter
01793     emcTaskQueueCommand(&taskPlanSynchCmd);
01794 
01795     retval = 0;
01796     break;
01797 
01798     // mode and state commands
01799 
01800   case EMC_TASK_SET_MODE_TYPE:
01801     mode_msg = (EMC_TASK_SET_MODE *) cmd;
01802     if (mode_msg->mode == EMC_TASK_MODE_MANUAL &&
01803         emcStatus->task.mode != EMC_TASK_MODE_MANUAL) {
01804       // leaving auto or mdi mode for manual
01805 
01806       // FIXME-- duplicate code for abort,
01807       // also near end of main, when aborting on subordinate errors,
01808       // and in emcTaskExecute()
01809 
01810       // abort everything
01811       emcTaskAbort();
01812 
01813       // without emcTaskPlanClose(), a new run command resumes at
01814       // aborted line-- feature that may be considered later
01815       { 
01816         int was_open = taskplanopen;
01817         emcTaskPlanClose();
01818         if (EMC_DEBUG & EMC_DEBUG_INTERP && was_open) {
01819           rcs_print("emcTaskPlanClose() called at %s:%d\n",__FILE__,__LINE__);
01820         }
01821       }   
01822 
01823       // clear out the pending command
01824       emcTaskCommand = 0;
01825       interp_list.clear();
01826 
01827       // clear out the interpreter state
01828       emcStatus->task.interpState = EMC_TASK_INTERP_IDLE;
01829       emcStatus->task.execState = EMC_TASK_EXEC_DONE;
01830       stepping = 0;
01831       steppingWait = 0;
01832 
01833       // now queue up command to resynch interpreter
01834       emcTaskQueueCommand(&taskPlanSynchCmd);
01835       retval = 0;
01836     }
01837     retval = emcTaskSetMode(mode_msg->mode);
01838     break;
01839 
01840   case EMC_TASK_SET_STATE_TYPE:
01841     state_msg = (EMC_TASK_SET_STATE *) cmd;
01842     retval = emcTaskSetState(state_msg->state);
01843     break;
01844 
01845     // interpreter commands
01846 
01847   case EMC_TASK_PLAN_OPEN_TYPE:
01848     open_msg = (EMC_TASK_PLAN_OPEN *) cmd;
01849     retval = emcTaskPlanOpen(open_msg->file);
01850     if (EMC_DEBUG & EMC_DEBUG_INTERP) {
01851       rcs_print("emcTaskPlanOpen(%s) returned %d\n",open_msg->file, 
01852                 retval);
01853     }
01854 #ifdef NEW_INTERPRETER
01855     if(retval > RS274NGC_MIN_ERROR)
01856       {
01857         retval = -1;
01858       }
01859 #endif
01860     if (-1 == retval) {
01861       emcOperatorError(0, "can't open %s", open_msg->file);
01862     }
01863     else {
01864       strcpy(emcStatus->task.file, open_msg->file);
01865       retval = 0;
01866     }
01867     break;
01868 
01869   case EMC_TASK_PLAN_EXECUTE_TYPE:
01870     stepping = 0;
01871     steppingWait = 0;
01872     execute_msg = (EMC_TASK_PLAN_EXECUTE *) cmd;
01873     if (execute_msg->command[0] != 0) {
01874       if(emcStatus->task.mode == EMC_TASK_MODE_MDI)
01875         {
01876           interp_list.set_line_number(--pseudoMdiLineNumber);
01877         }
01878       execRetval = emcTaskPlanExecute(execute_msg->command);
01879       if (EMC_DEBUG & EMC_DEBUG_INTERP) {
01880         rcs_print("emcTaskPlanExecute(%s) returned %d\n",execute_msg->command,execRetval);
01881       }
01882       if (execRetval == 2 /* RS274NGC_ENDFILE */ ) {
01883         // this is an end-of-file
01884         // need to flush execution, so signify no more reading
01885         // until all is done
01886         emcTaskPlanSetWait();
01887         if (EMC_DEBUG & EMC_DEBUG_INTERP) {
01888           rcs_print("emcTaskPlanSetWait() called\n");
01889         }
01890         // and resynch the interpreter WM
01891         emcTaskQueueCommand(&taskPlanSynchCmd);
01892         // it's success, so retval really is 0
01893         retval = 0;
01894       }
01895 #ifdef NEW_INTERPRETER
01896       else if (execRetval != 0 ) {
01897 #else
01898       else if (execRetval == -1 /* RS274NGC_ERROR */ ) {
01899 #endif
01900         retval = -1;
01901       }
01902       else {
01903         // other codes are OK
01904         retval = 0;
01905       }
01906     }
01907     break;
01908 
01909   case EMC_TASK_PLAN_RUN_TYPE:
01910     stepping = 0;
01911     steppingWait = 0;
01912     if(!taskplanopen && emcStatus->task.file[0] != 0)
01913       {
01914         emcTaskPlanOpen(emcStatus->task.file);
01915       }
01916     run_msg = (EMC_TASK_PLAN_RUN *) cmd;
01917     programStartLine = run_msg->line;
01918     emcStatus->task.interpState = EMC_TASK_INTERP_READING;
01919     retval = 0;
01920     break;
01921 
01922   case EMC_TASK_PLAN_PAUSE_TYPE:
01923     emcTrajPause();
01924     if (emcStatus->task.interpState != EMC_TASK_INTERP_PAUSED) {
01925       interpResumeState = emcStatus->task.interpState;
01926     }
01927     emcStatus->task.interpState = EMC_TASK_INTERP_PAUSED;
01928     retval = 0;
01929     break;
01930 
01931   case EMC_TASK_PLAN_RESUME_TYPE:
01932     emcTrajResume();
01933     emcStatus->task.interpState = interpResumeState;
01934     stepping = 0;
01935     steppingWait = 0;
01936     retval = 0;
01937     break;
01938 
01939   case EMC_TASK_PLAN_END_TYPE:
01940     retval = 0;
01941     break;
01942 
01943   case EMC_TASK_PLAN_INIT_TYPE:
01944     retval = emcTaskPlanInit();
01945     if (EMC_DEBUG & EMC_DEBUG_INTERP) {
01946       rcs_print("emcTaskPlanInit() returned %d\n",retval);
01947     }
01948 #ifdef NEW_INTERPRETER
01949     if(retval > RS274NGC_MIN_ERROR)
01950       {
01951         retval = -1;
01952       }
01953 #endif
01954     break;
01955 
01956   case EMC_TASK_PLAN_SYNCH_TYPE:
01957     retval = emcTaskPlanSynch();
01958     if (EMC_DEBUG & EMC_DEBUG_INTERP) {
01959       rcs_print("emcTaskPlanSynch() returned %d\n",retval);
01960     }
01961 #ifdef NEW_INTERPRETER
01962     if(retval > RS274NGC_MIN_ERROR)
01963       {
01964         retval = -1;
01965       }
01966 #endif
01967     break;
01968 
01969   case EMC_LOG_OPEN_TYPE:
01970     log_open_msg = (EMC_LOG_OPEN *) cmd;
01971     retval = emcLogOpen(log_open_msg->file,
01972                         log_open_msg->type,
01973                         log_open_msg->size,
01974                         log_open_msg->skip,
01975                         log_open_msg->which,
01976                         log_open_msg->triggerType,
01977                         log_open_msg->triggerVar,
01978                         log_open_msg->triggerThreshold);
01979     break;
01980 
01981   case EMC_LOG_START_TYPE:
01982     retval = emcLogStart();
01983     break;
01984 
01985   case EMC_LOG_STOP_TYPE:
01986     retval = emcLogStop();
01987     break;
01988 
01989   case EMC_LOG_CLOSE_TYPE:
01990     retval = emcLogClose();
01991     break;
01992 
01993   default:
01994     // unrecognized command
01995     if (EMC_DEBUG & EMC_DEBUG_TASK_ISSUE) {
01996       rcs_print_error("ignoring issue of unknown command %d:%s\n", cmd->type,
01997                       emc_symbol_lookup(cmd->type));
01998     }
01999     retval = 0;         // don't consider this an error
02000     break;
02001   }
02002 
02003   if (retval == -1) {
02004     if (EMC_DEBUG & EMC_DEBUG_TASK_ISSUE) {
02005       rcs_print_error("error executing command %d:%s\n", cmd->type,
02006                       emc_symbol_lookup(cmd->type));
02007     }
02008   }
02009 
02010   return retval;
02011 }
02012 
02013 /*
02014    emcTaskCheckPostconditions() is called for commands on the interp_list.
02015    Immediate commands, i.e., commands sent from calls to emcTaskIssueCommand()
02016    in emcTaskPlan() directly, are not handled here.
02017 
02018    The return value is a state for emcTaskExecute() to wait on, e.g.,
02019    EMC_TASK_EXEC_WAITING_FOR_MOTION, after the command has finished and
02020    before any other commands can be sent out.
02021    */
02022 static int emcTaskCheckPostconditions(NMLmsg * cmd)
02023 {
02024   if (0 == cmd) {
02025     return EMC_TASK_EXEC_DONE;
02026   }
02027 
02028   switch (cmd->type) {
02029   case EMC_OPERATOR_ERROR_TYPE:
02030   case EMC_OPERATOR_TEXT_TYPE:
02031   case EMC_OPERATOR_DISPLAY_TYPE:
02032     return EMC_TASK_EXEC_DONE;
02033     break;
02034 
02035   case EMC_TRAJ_LINEAR_MOVE_TYPE:
02036   case EMC_TRAJ_CIRCULAR_MOVE_TYPE:
02037   case EMC_TRAJ_SET_VELOCITY_TYPE:
02038   case EMC_TRAJ_SET_TERM_COND_TYPE:
02039   case EMC_TRAJ_SET_OFFSET_TYPE:
02040   case EMC_TRAJ_SET_ORIGIN_TYPE: 
02041   case EMC_TRAJ_PROBE_TYPE:
02042   case EMC_TRAJ_CLEAR_PROBE_TRIPPED_FLAG_TYPE:
02043   case EMC_TRAJ_SET_TELEOP_ENABLE_TYPE:
02044   case EMC_TRAJ_SET_TELEOP_VECTOR_TYPE:
02045     return EMC_TASK_EXEC_DONE;
02046     break;
02047 
02048   case EMC_TOOL_PREPARE_TYPE:
02049   case EMC_TOOL_LOAD_TYPE:
02050   case EMC_TOOL_UNLOAD_TYPE:
02051   case EMC_TOOL_LOAD_TOOL_TABLE_TYPE:
02052   case EMC_TOOL_SET_OFFSET_TYPE:
02053   case EMC_SPINDLE_ON_TYPE:
02054   case EMC_SPINDLE_OFF_TYPE:
02055   case EMC_COOLANT_MIST_ON_TYPE:
02056   case EMC_COOLANT_MIST_OFF_TYPE:
02057   case EMC_COOLANT_FLOOD_ON_TYPE:
02058   case EMC_COOLANT_FLOOD_OFF_TYPE:
02059   case EMC_LUBE_ON_TYPE:
02060   case EMC_LUBE_OFF_TYPE:
02061     return EMC_TASK_EXEC_DONE;
02062     break;
02063 
02064   case EMC_TASK_PLAN_RUN_TYPE:
02065   case EMC_TASK_PLAN_PAUSE_TYPE:
02066   case EMC_TASK_PLAN_END_TYPE:
02067   case EMC_TASK_PLAN_INIT_TYPE:
02068   case EMC_TASK_PLAN_SYNCH_TYPE:
02069   case EMC_TASK_PLAN_EXECUTE_TYPE:
02070     return EMC_TASK_EXEC_DONE;
02071     break;
02072 
02073   case EMC_TRAJ_DELAY_TYPE:
02074     return EMC_TASK_EXEC_WAITING_FOR_DELAY;
02075     break;
02076 
02077   case EMC_MOTION_SET_AOUT_TYPE:
02078   case EMC_MOTION_SET_DOUT_TYPE:
02079     return EMC_TASK_EXEC_DONE;
02080     break;
02081 
02082   default:
02083     // unrecognized command
02084     if (EMC_DEBUG & EMC_DEBUG_TASK_ISSUE) {
02085       rcs_print_error("postconditions: unrecognized command %d:%s\n",cmd->type, 
02086                       emc_symbol_lookup(cmd->type));
02087     }
02088     return EMC_TASK_EXEC_DONE;
02089     break;
02090   }
02091 }
02092 
02093 /*
02094   STEPPING_CHECK() is a macro that prefaces a switch-case with a check
02095   for stepping. If stepping is active, it waits until the step has been
02096   given, then falls through to the rest of the case statement.
02097 */
02098 
02099 #define STEPPING_CHECK()                                                   \
02100 if (stepping) {                                                            \
02101   if (! steppingWait) {                                                    \
02102     steppingWait = 1;                                                      \
02103     steppedLine = emcStatus->task.currentLine;                             \
02104   }                                                                        \
02105   else {                                                                   \
02106     if (emcStatus->task.currentLine != steppedLine) {                      \
02107       break;                                                               \
02108     }                                                                      \
02109   }                                                                        \
02110 }
02111 
02112 // executor function
02113 static int emcTaskExecute(void)
02114 {
02115   int retval = 0;
02116 
02117   switch (emcStatus->task.execState) {
02118   case EMC_TASK_EXEC_ERROR:
02119 
02120     // FIXME-- duplicate code for abort,
02121     // also near end of main, when aborting on subordinate errors,
02122     // and in emcTaskIssueCommand()
02123 
02124     // abort everything
02125     emcTaskAbort();
02126 
02127     // without emcTaskPlanClose(), a new run command resumes at
02128     // aborted line-- feature that may be considered later
02129     { 
02130       int was_open = taskplanopen;
02131       emcTaskPlanClose();
02132       if (EMC_DEBUG & EMC_DEBUG_INTERP && was_open) {
02133         rcs_print("emcTaskPlanClose() called at %s:%d\n",__FILE__,__LINE__);
02134       }
02135     }   
02136 
02137 
02138     // clear out pending command
02139     emcTaskCommand = 0;
02140     interp_list.clear();
02141 
02142     // clear out the interpreter state
02143     emcStatus->task.interpState = EMC_TASK_INTERP_IDLE;
02144     emcStatus->task.execState = EMC_TASK_EXEC_DONE;
02145     stepping = 0;
02146     steppingWait = 0;
02147 
02148     // now queue up command to resynch interpreter
02149     emcTaskQueueCommand(&taskPlanSynchCmd);
02150 
02151     retval = -1;
02152     break;
02153 
02154   case EMC_TASK_EXEC_DONE:
02155     STEPPING_CHECK();
02156     if (! emcStatus->motion.traj.queueFull &&
02157         emcStatus->task.interpState != EMC_TASK_INTERP_PAUSED) {
02158       if (0 == emcTaskCommand) {
02159         // need a new command
02160         emcTaskCommand = interp_list.get();
02161         // interp_list now has line number associated with this-- get it
02162         if( 0 != emcTaskCommand)
02163           {
02164             emcStatus->task.currentLine = interp_list.get_line_number();
02165             // and set it for all subsystems which use queued ids
02166             emcTrajSetMotionId(emcStatus->task.currentLine);
02167             if (emcStatus->motion.traj.queueFull) {
02168               emcStatus->task.execState = EMC_TASK_EXEC_WAITING_FOR_MOTION_QUEUE;
02169             }
02170             else {
02171               emcStatus->task.execState =
02172                 emcTaskCheckPreconditions(emcTaskCommand);
02173             }
02174           }
02175       }
02176       else {
02177         // have an outstanding command
02178         if (0 != emcTaskIssueCommand(emcTaskCommand)) {
02179           emcStatus->task.execState = EMC_TASK_EXEC_ERROR;
02180           retval = -1;
02181         }
02182         else {
02183           emcStatus->task.execState =
02184             emcTaskCheckPostconditions(emcTaskCommand);
02185         }
02186         emcTaskCommand = 0;     // reset it
02187       }
02188     }
02189     break;
02190 
02191   case EMC_TASK_EXEC_WAITING_FOR_MOTION_QUEUE:
02192     STEPPING_CHECK();
02193     if (! emcStatus->motion.traj.queueFull) {
02194       if (0 != emcTaskCommand) {
02195         emcStatus->task.execState = emcTaskCheckPreconditions(emcTaskCommand);
02196       }
02197       else {
02198         emcStatus->task.execState = EMC_TASK_EXEC_DONE;
02199       }
02200     }
02201     break;
02202 
02203   case EMC_TASK_EXEC_WAITING_FOR_PAUSE:
02204     STEPPING_CHECK();
02205     if (emcStatus->task.interpState != EMC_TASK_INTERP_PAUSED) {
02206       if (0 != emcTaskCommand) {
02207         if (emcStatus->motion.traj.queue > 0) {
02208           emcStatus->task.execState = EMC_TASK_EXEC_WAITING_FOR_MOTION_QUEUE;
02209         }
02210         else {
02211           emcStatus->task.execState = emcTaskCheckPreconditions(emcTaskCommand);
02212         }
02213       }
02214       else {
02215         emcStatus->task.execState = EMC_TASK_EXEC_DONE;
02216       }
02217     }
02218     break;
02219 
02220 
02221   case EMC_TASK_EXEC_WAITING_FOR_MOTION:
02222     STEPPING_CHECK();
02223     if (emcStatus->motion.status == RCS_ERROR) {
02224       // emcOperatorError(0, "error in motion controller");
02225       emcStatus->task.execState = EMC_TASK_EXEC_ERROR;
02226     }
02227     else if (emcStatus->motion.status == RCS_DONE) {
02228       emcStatus->task.execState = EMC_TASK_EXEC_DONE;
02229     }
02230     break;
02231 
02232   case EMC_TASK_EXEC_WAITING_FOR_IO:
02233     STEPPING_CHECK();
02234     if (emcStatus->io.status == RCS_ERROR) {
02235       // emcOperatorError(0, "error in IO controller");
02236       emcStatus->task.execState = EMC_TASK_EXEC_ERROR;
02237     }
02238     else if (emcStatus->io.status == RCS_DONE) {
02239       emcStatus->task.execState = EMC_TASK_EXEC_DONE;
02240     }
02241     break;
02242 
02243   case EMC_TASK_EXEC_WAITING_FOR_MOTION_AND_IO:
02244     STEPPING_CHECK();
02245     if (emcStatus->motion.status == RCS_ERROR) {
02246       // emcOperatorError(0, "error in motion controller");
02247       emcStatus->task.execState = EMC_TASK_EXEC_ERROR;
02248     }
02249     else if (emcStatus->io.status == RCS_ERROR) {
02250       // emcOperatorError(0, "error in IO controller");
02251       emcStatus->task.execState = EMC_TASK_EXEC_ERROR;
02252     }
02253     else if (emcStatus->motion.status == RCS_DONE &&
02254              emcStatus->io.status == RCS_DONE) {
02255       emcStatus->task.execState = EMC_TASK_EXEC_DONE;
02256     }
02257     break;
02258 
02259   case EMC_TASK_EXEC_WAITING_FOR_DELAY:
02260     STEPPING_CHECK();
02261 #if defined(LINUX_KERNEL_2_2)
02262     if (taskExecDelayTimeout <= 0.0) {
02263       emcStatus->task.execState = EMC_TASK_EXEC_DONE;
02264     }
02265     else {
02266       taskExecDelayTimeout -= EMC_TASK_CYCLE_TIME;
02267     }
02268 #else
02269     if (etime() >= taskExecDelayTimeout) {
02270       emcStatus->task.execState = EMC_TASK_EXEC_DONE;
02271     }
02272 #endif
02273     break;
02274 
02275   default:
02276     // coding error
02277     if (EMC_DEBUG & EMC_DEBUG_TASK_ISSUE) {
02278       rcs_print_error("invalid execState");
02279     }
02280     retval = -1;
02281     break;
02282   }
02283 
02284   return retval;
02285 }
02286 
02287 // called to allocate and init resources
02288 static int emctask_startup()
02289 {
02290   double end;
02291   int good;
02292 
02293 #define RETRY_TIME 10.0         // seconds to wait for subsystems to come up
02294 #define RETRY_INTERVAL 1.0      // seconds between wait tries for a subsystem
02295 
02296   // get our status data structure
02297   emcStatus = new EMC_STAT;
02298 
02299   // get the NML command buffer
02300   if (! (EMC_DEBUG & EMC_DEBUG_NML)) {
02301     set_rcs_print_destination(RCS_PRINT_TO_NULL); // inhibit diag messages
02302   }
02303   end = RETRY_TIME;
02304   good = 0;
02305   do {
02306     if (NULL != emcCommandBuffer) {
02307       delete emcCommandBuffer;
02308     }
02309     emcCommandBuffer = new RCS_CMD_CHANNEL(emcFormat, "emcCommand", "emc", EMC_NMLFILE);
02310     if (emcCommandBuffer->valid()) {
02311       good = 1;
02312       break;
02313     }
02314     esleep(RETRY_INTERVAL);
02315     end -= RETRY_INTERVAL;
02316     if(done)
02317       {
02318         emctask_shutdown();
02319         exit(1);
02320       }
02321   } while (end > 0.0);
02322   set_rcs_print_destination(RCS_PRINT_TO_STDOUT); // restore diag messages
02323   if (! good) {
02324     rcs_print_error("can't get emcCommand buffer\n");
02325     return -1;
02326   }
02327   // get our command data structure
02328   emcCommand = emcCommandBuffer->get_address();
02329 
02330   // get the NML status buffer
02331   if (! (EMC_DEBUG & EMC_DEBUG_NML)) {
02332     set_rcs_print_destination(RCS_PRINT_TO_NULL); // inhibit diag messages
02333   }
02334   end = RETRY_TIME;
02335   good = 0;
02336   do {
02337     if (NULL != emcStatusBuffer) {
02338       delete emcStatusBuffer;
02339     }
02340     emcStatusBuffer = new RCS_STAT_CHANNEL(emcFormat, "emcStatus", "emc", EMC_NMLFILE);
02341     if (emcStatusBuffer->valid()) {
02342       good = 1;
02343       break;
02344     }
02345     esleep(RETRY_INTERVAL);
02346     end -= RETRY_INTERVAL;
02347     if(done)
02348       {
02349         emctask_shutdown();
02350         exit(1);
02351       }
02352   } while (end > 0.0);
02353   set_rcs_print_destination(RCS_PRINT_TO_STDOUT); // restore diag messages
02354   if (! good) {
02355     rcs_print_error("can't get emcStatus buffer\n");
02356     return -1;
02357   }
02358 
02359   if (! (EMC_DEBUG & EMC_DEBUG_NML)) {
02360     set_rcs_print_destination(RCS_PRINT_TO_NULL); // inhibit diag messages
02361   }
02362   end = RETRY_TIME;
02363   good = 0;
02364   do {
02365     if (NULL != emcErrorBuffer) {
02366       delete emcErrorBuffer;
02367     }
02368     emcErrorBuffer = new NML(nmlErrorFormat, "emcError", "emc", EMC_NMLFILE);
02369     if (emcErrorBuffer->valid()) {
02370       good = 1;
02371       break;
02372     }
02373     esleep(RETRY_INTERVAL);
02374     end -= RETRY_INTERVAL;
02375     if(done)
02376       {
02377         emctask_shutdown();
02378         exit(1);
02379       }
02380   } while (end > 0.0);
02381   set_rcs_print_destination(RCS_PRINT_TO_STDOUT); // restore diag messages
02382   if (! good) {
02383     rcs_print_error("can't get emcError buffer\n");
02384     return -1;
02385   }
02386 
02387   // get the timer
02388   if (! emcTaskNoDelay) {
02389       timer = new RCS_TIMER(EMC_TASK_CYCLE_TIME);
02390     }
02391 
02392   // initialize the subsystems
02393 
02394   // IO first
02395 
02396   if (! (EMC_DEBUG & EMC_DEBUG_NML)) {
02397     set_rcs_print_destination(RCS_PRINT_TO_NULL); // inhibit diag messages
02398   }
02399   end = RETRY_TIME;
02400   good = 0;
02401   do {
02402     if (0 == emcIoInit()) {
02403       good = 1;
02404       break;
02405     }
02406     esleep(RETRY_INTERVAL);
02407     end -= RETRY_INTERVAL;
02408     if(done)
02409       {
02410         emctask_shutdown();
02411         exit(1);
02412       }
02413   } while (end > 0.0);
02414   set_rcs_print_destination(RCS_PRINT_TO_STDOUT); // restore diag messages
02415   if (! good) {
02416     rcs_print_error("can't initialize IO\n");
02417     return -1;
02418   }
02419 
02420   end = RETRY_TIME;
02421   good = 0;
02422   do {
02423     if (0 == emcIoUpdate(&emcStatus->io)) {
02424       good = 1;
02425       break;
02426     }
02427     esleep(RETRY_INTERVAL);
02428     end -= RETRY_INTERVAL;
02429     if(done)
02430       {
02431         emctask_shutdown();
02432         exit(1);
02433       }
02434   } while (end > 0.0);
02435   if (! good) {
02436     rcs_print_error("can't read IO status\n");
02437     return -1;
02438   }
02439 
02440   // now motion
02441 
02442   end = RETRY_TIME;
02443   good = 0;
02444   do {
02445     if (0 == emcMotionInit()) {
02446       good = 1;
02447       break;
02448     }
02449     esleep(RETRY_INTERVAL);
02450     end -= RETRY_INTERVAL;
02451     if(done)
02452       {
02453         emctask_shutdown();
02454         exit(1);
02455       }
02456   } while (end > 0.0);
02457   if (! good) {
02458     rcs_print_error("can't initialize motion\n");
02459     return -1;
02460   }
02461 
02462   end = RETRY_TIME;
02463   good = 0;
02464   do {
02465     if (0 == emcMotionUpdate(&emcStatus->motion)) {
02466       good = 1;
02467       break;
02468     }
02469     esleep(RETRY_INTERVAL);
02470     end -= RETRY_INTERVAL;
02471     if(done)
02472       {
02473         emctask_shutdown();
02474         exit(1);
02475       }
02476   } while (end > 0.0);
02477   if (! good) {
02478     rcs_print_error("can't read motion status\n");
02479     return -1;
02480   }
02481 
02482   // now the interpreter
02483   if (0 != emcTaskPlanInit()) {
02484     rcs_print_error("can't initialize interpreter\n");
02485     return -1;
02486   }
02487 
02488   if(done)
02489     {
02490       emctask_shutdown();
02491       exit(1);
02492     }
02493 
02494   // now task
02495   if (0 != emcTaskInit()) {
02496     rcs_print_error("can't initialize task\n");
02497     return -1;
02498   }
02499   emcTaskUpdate(&emcStatus->task);
02500 
02501   return 0;
02502 }
02503 
02504 // called to deallocate resources
02505 static int emctask_shutdown(void)
02506 {
02507   // shut down the subsystems
02508 
02509   if( 0 != emcStatus)
02510     {
02511       emcTaskHalt();
02512       emcTaskPlanExit();
02513       emcMotionHalt();
02514       emcIoHalt();
02515     }
02516 
02517   // delete the timer
02518   if (0 != timer)
02519     {
02520       delete timer;
02521       timer = 0;
02522     }
02523 
02524   // delete the NML channels
02525 
02526   if (0 != emcErrorBuffer)
02527     {
02528       delete emcErrorBuffer;
02529       emcErrorBuffer = 0;
02530     }
02531 
02532   if (0 != emcStatusBuffer)
02533     {
02534       delete emcStatusBuffer;
02535       emcStatusBuffer = 0;
02536       emcStatus = 0;
02537     }
02538 
02539   if (0 != emcCommandBuffer)
02540     {
02541       delete emcCommandBuffer;
02542       emcCommandBuffer = 0;
02543       emcCommand = 0;
02544     }
02545 
02546   if( 0 != emcStatus)
02547     {
02548       delete emcStatus;
02549       emcStatus = 0;
02550     }
02551   return 0;
02552 }
02553 
02554 static int iniLoad(const char *filename)
02555 {
02556   INIFILE inifile;
02557   const char *inistring;
02558   char version[INIFILE_MAX_LINELEN];
02559   double saveDouble;
02560 
02561   // open it
02562   if (-1 == inifile.open(filename)) {
02563     return -1;
02564   }
02565 
02566   if (NULL != (inistring = inifile.find("DEBUG", "EMC"))) {
02567     // copy to global
02568     if (1 != sscanf(inistring, "%i", &EMC_DEBUG)) {
02569       EMC_DEBUG = 0;
02570     }
02571   }
02572   else {
02573     // not found, use default
02574     EMC_DEBUG = 0;
02575   }
02576   if (EMC_DEBUG & EMC_DEBUG_RCS) {
02577     // set_rcs_print_flag(PRINT_EVERYTHING);
02578     max_rcs_errors_to_print=-1;
02579   }
02580 
02581   if (EMC_DEBUG & EMC_DEBUG_VERSIONS) {
02582     if (NULL != (inistring = inifile.find("VERSION", "EMC"))) {
02583       // print version
02584       sscanf(inistring, "$Revision: %s", version);
02585       rcs_print("Version:  %s\n", version);
02586     }
02587     else {
02588       // not found, not fatal
02589       rcs_print("Version:  (not found)\n");
02590     }
02591 
02592     if (NULL != (inistring = inifile.find("MACHINE", "EMC"))) {
02593       // print machine
02594       rcs_print("Machine:  %s\n", inistring);
02595     }
02596     else {
02597       // not found, not fatal
02598       rcs_print("Machine:  (not found)\n");
02599     }
02600   }
02601 
02602   if (NULL != (inistring = inifile.find("NML_FILE", "EMC"))) {
02603     // copy to global
02604     strcpy(EMC_NMLFILE, inistring);
02605   }
02606   else {
02607     // not found, use default
02608   }
02609 
02610   if (NULL != (inistring = inifile.find("RS274NGC_STARTUP_CODE","EMC"))) {
02611     // copy to global
02612     strcpy(RS274NGC_STARTUP_CODE, inistring);
02613   }
02614   else {
02615     // not found, use default
02616   }
02617 
02618   saveDouble = EMC_TASK_CYCLE_TIME;
02619   EMC_TASK_CYCLE_TIME_ORIG = EMC_TASK_CYCLE_TIME;
02620   emcTaskNoDelay = 0;
02621   if (NULL != (inistring = inifile.find("CYCLE_TIME", "TASK"))) {
02622     if (1 == sscanf(inistring, "%lf", &EMC_TASK_CYCLE_TIME)) {
02623       // found it
02624       // if it's <= 0.0, then flag that we don't want to
02625       // wait at all, which will set the EMC_TASK_CYCLE_TIME
02626       // global to the actual time deltas
02627       if (EMC_TASK_CYCLE_TIME <= 0.0) {
02628         emcTaskNoDelay = 1;
02629       }
02630     }
02631     else {
02632       // found, but invalid
02633       EMC_TASK_CYCLE_TIME = saveDouble;
02634       rcs_print("invalid [TASK] CYCLE_TIME in %s (%s); using default %f\n",
02635                 filename, inistring, EMC_TASK_CYCLE_TIME);
02636     }
02637   }
02638   else {
02639     // not found, using default
02640     rcs_print("[TASK] CYCLE_TIME not found in %s; using default %f\n",
02641               filename, EMC_TASK_CYCLE_TIME);
02642   }
02643 
02644   // close it
02645   inifile.close();
02646 
02647   return 0;
02648 }
02649 
02650 static EMC_STAT last_emc_status;
02651 
02652 /*
02653   syntax: a.out {-d -ini <inifile>} {-nml <nmlfile>} {-shm <key>}
02654   */
02655 int main(int argc, char *argv[])
02656 {
02657   int taskAborted = 0;          // flag to prevent flurry of task aborts
02658   int taskPlanError = 0;
02659   int taskExecuteError = 0;
02660 #ifndef LINUX_KERNEL_2_2
02661   double startTime, endTime;
02662 #endif
02663 
02664   double minTime, maxTime;
02665 
02666   // copy command line args
02667   Argc = argc;
02668   Argv = argv;
02669 
02670   // trap ^C
02671   // loop until done
02672   done = 0;
02673   signal(SIGINT, emctask_quit);
02674 
02675   // set print destination to stdout, for console apps
02676   set_rcs_print_destination(RCS_PRINT_TO_STDOUT);
02677 
02678   // blank out the annoying RCS version message
02679   rcs_version_printed = 1;
02680 
02681   // open the general purpose file log
02682   if (NULL == (logFp = fopen(LOG_FILE, "w"))) {
02683     // can't log; ignore
02684   }
02685 
02686   // process command line args
02687   if (0 != emcGetArgs(argc, argv)) {
02688     rcs_print_error("error in argument list\n");
02689     exit(1);
02690   }
02691 
02692   if (done) {
02693     emctask_shutdown();
02694     exit(1);
02695   }
02696 
02697   // initialize globals
02698   emcInitGlobals();
02699 
02700   if (done) {
02701     emctask_shutdown();
02702     exit(1);
02703   }
02704 
02705   // get configuration information
02706   iniLoad(EMC_INIFILE);
02707 
02708   if (done) {
02709     emctask_shutdown();
02710     exit(1);
02711   }
02712 
02713   // initialize everything
02714   if (0 != emctask_startup()) {
02715     emctask_shutdown();
02716     exit(1);
02717   }
02718 
02719   // set the default startup modes
02720   emcTaskSetState(EMC_TASK_STATE_ESTOP);
02721   emcTaskSetMode(EMC_TASK_MODE_MANUAL);
02722 
02723   // reflect the initial value of EMC_DEBUG in emcStatus->debug
02724   emcStatus->debug = EMC_DEBUG;
02725 
02726 #if ! defined(LINUX_KERNEL_2_2)
02727   startTime = etime();          // set start time before entering loop;
02728                                 // it will be set at end of loop from now on
02729   minTime = DBL_MAX;            // set to value that can never be exceeded
02730   maxTime = 0.0;                // set to value that can never be underset
02731 #endif
02732   while (! done) {
02733     // read command
02734     if (0 != emcCommandBuffer->peek()) {
02735       // got a new command, so clear out errors
02736       taskPlanError = 0;
02737       taskExecuteError = 0;
02738     }
02739 
02740     // run control cycle
02741     if (0 != emcTaskPlan()) {
02742       taskPlanError = 1;
02743     }
02744     if (0 != emcTaskExecute()) {
02745       taskExecuteError = 1;
02746     }
02747 
02748     // update subordinate status
02749 
02750     emcIoUpdate(&emcStatus->io);
02751     emcMotionUpdate(&emcStatus->motion);
02752 
02753     // synchronize subordinate states
02754     if (emcStatus->io.aux.estop) {
02755       if (emcStatus->motion.traj.enabled) {
02756         if(EMC_DEBUG & EMC_DEBUG_IO_POINTS)
02757           {
02758             rcs_print("emcStatus->io.aux.estop=%d\n", emcStatus->io.aux.estop);
02759             rcs_print("emcStatus->io.aux.estopIn=%d\n", emcStatus->io.aux.estopIn);
02760           }
02761         emcTrajDisable();
02762       }
02763       if (emcStatus->io.coolant.mist) {
02764         emcCoolantMistOff();
02765       }
02766       if (emcStatus->io.coolant.flood) {
02767         emcCoolantFloodOff();
02768       }
02769       if (emcStatus->io.lube.on) {
02770         emcLubeOff();
02771       }
02772       if (emcStatus->io.spindle.enabled) {
02773         emcSpindleOff();
02774       }
02775     }
02776 
02777     // check for subordinate errors, and halt task if so
02778     if (emcStatus->motion.status == RCS_ERROR ||
02779         emcStatus->io.status == RCS_ERROR) {
02780 
02781       // FIXME-- duplicate code for abort,
02782       // also in emcTaskExecute()
02783       // and in emcTaskIssueCommand()
02784 
02785       if (! taskAborted) {
02786         // abort everything
02787         emcTaskAbort();
02788 
02789         // without emcTaskPlanClose(), a new run command resumes at
02790         // aborted line-- feature that may be considered later
02791         { 
02792           int was_open = taskplanopen;
02793           emcTaskPlanClose();
02794           if (EMC_DEBUG & EMC_DEBUG_INTERP && was_open) {
02795             rcs_print("emcTaskPlanClose() called at %s:%d\n",__FILE__,__LINE__);
02796           }
02797         }   
02798 
02799         // clear out the pending command
02800         emcTaskCommand = 0;
02801         interp_list.clear();
02802 
02803         // clear out the interpreter state
02804         emcStatus->task.interpState = EMC_TASK_INTERP_IDLE;
02805         emcStatus->task.execState = EMC_TASK_EXEC_DONE;
02806         stepping = 0;
02807         steppingWait = 0;
02808 
02809         // now queue up command to resynch interpreter
02810         emcTaskQueueCommand(&taskPlanSynchCmd);
02811         taskAborted = 1;
02812       }
02813     }
02814     else {
02815       taskAborted = 0;
02816     }
02817 
02818     // update task-specific status
02819     emcTaskUpdate(&emcStatus->task);
02820 
02821     // handle RCS_STAT_MSG base class members explicitly, since this
02822     // is not an NML_MODULE and they won't be set automatically
02823 
02824     // do task
02825     emcStatus->task.command_type = emcCommand->type;
02826     emcStatus->task.echo_serial_number = emcCommand->serial_number;
02827 
02828     // do top level
02829     emcStatus->command_type = emcCommand->type;
02830     emcStatus->echo_serial_number = emcCommand->serial_number;
02831 
02832     if (taskPlanError || taskExecuteError ||
02833         emcStatus->task.execState == EMC_TASK_EXEC_ERROR ||
02834         emcStatus->motion.status == RCS_ERROR ||
02835         emcStatus->io.status == RCS_ERROR) {
02836       emcStatus->status = RCS_ERROR;
02837       emcStatus->task.status = RCS_ERROR;
02838     }
02839     else if (! taskPlanError && ! taskExecuteError &&
02840              emcStatus->task.execState == EMC_TASK_EXEC_DONE &&
02841              emcStatus->motion.status == RCS_DONE &&
02842              emcStatus->io.status == RCS_DONE &&
02843              interp_list.len() == 0 &&
02844              emcTaskCommand == 0 &&
02845              emcStatus->task.interpState == EMC_TASK_INTERP_IDLE) {
02846       emcStatus->status = RCS_DONE;
02847       emcStatus->task.status = RCS_DONE;
02848     }
02849     else {
02850       emcStatus->status = RCS_EXEC;
02851       emcStatus->task.status = RCS_EXEC;
02852     }
02853     // ignore state, line, source_line, and source_file[] since they're N/A
02854 
02855     // Check for some error/warning conditions and warn the operator.
02856     // The GUI would be a better place to check these but we will have lot's
02857     // of gui's and some will neglect to check these flags.
02858     for (int i = 0; i < EMC_AXIS_MAX; i++) {
02859       if (last_emc_status.motion.axis[i].fault == 0 &&
02860           emcStatus->motion.axis[i].fault == 1) {
02861         emcOperatorError(0,"Amplifier fault on axis %d.", i);
02862       }
02863       last_emc_status.motion.axis[i].fault = emcStatus->motion.axis[i].fault;
02864       if (last_emc_status.motion.axis[i].minSoftLimit == 0 &&
02865           emcStatus->motion.axis[i].minSoftLimit == 1) {
02866         emcOperatorError(0,"Minimum Software Limit on axis %d exceeded.", i);
02867       }
02868       last_emc_status.motion.axis[i].minSoftLimit = emcStatus->motion.axis[i].minSoftLimit;
02869       if (last_emc_status.motion.axis[i].maxSoftLimit == 0 &&
02870           emcStatus->motion.axis[i].maxSoftLimit == 1) {
02871         emcOperatorError(0,"Maximum Software Limit on axis %d exceeded.", i);
02872       }
02873       last_emc_status.motion.axis[i].maxSoftLimit = emcStatus->motion.axis[i].maxSoftLimit;
02874       if (last_emc_status.motion.axis[i].minHardLimit == 0 &&
02875           emcStatus->motion.axis[i].minHardLimit == 1) {
02876         emcOperatorError(0,"Minimum Hardware Limit on axis %d exceeded.", i);
02877       }
02878       last_emc_status.motion.axis[i].minHardLimit = emcStatus->motion.axis[i].minHardLimit;
02879       if (last_emc_status.motion.axis[i].maxHardLimit == 0 &&
02880           emcStatus->motion.axis[i].maxHardLimit == 1) {
02881         emcOperatorError(0,"Maximum Hardware Limit on axis %d exceeded.", i);
02882       }
02883       last_emc_status.motion.axis[i].maxHardLimit = emcStatus->motion.axis[i].maxHardLimit;
02884     }
02885 
02886     // write it
02887     // since emcStatus was passed to the WM init functions, it
02888     // will be updated in the _update() functions above. There's
02889     // no need to call the individual functions on all WM items.
02890     emcStatusBuffer->write(emcStatus);
02891 
02892     // wait on timer cycle, if specified, or calculate actual
02893     // interval if ini file says to run full out via
02894     // [TASK] CYCLE_TIME <= 0.0
02895     if (emcTaskNoDelay) {
02896 #if defined(LINUX_KERNEL_2_2)
02897       // work around bug in gettimeofday() by running off nominal time
02898       EMC_TASK_CYCLE_TIME = EMC_TASK_CYCLE_TIME_ORIG;
02899       minTime = maxTime = EMC_TASK_CYCLE_TIME_ORIG;
02900 #else
02901       endTime = etime();
02902       EMC_TASK_CYCLE_TIME = endTime - startTime;
02903       if (EMC_TASK_CYCLE_TIME < minTime && ! done) {
02904         minTime = EMC_TASK_CYCLE_TIME;
02905       }
02906       else if (EMC_TASK_CYCLE_TIME > maxTime && ! done) {
02907         maxTime = EMC_TASK_CYCLE_TIME;
02908       }
02909       startTime = endTime;
02910 #endif
02911     }
02912     else {
02913 #if defined(LINUX_KERNEL_2_2)
02914       // work around bug in gettimeofday() by running off nominal time
02915       esleep(EMC_TASK_CYCLE_TIME);
02916 #else
02917       timer->wait();
02918 #endif
02919     }
02920   } // end of while (! done)
02921 
02922   // clean up everything
02923   emctask_shutdown();
02924 
02925   if (NULL != logFp) {
02926     fclose(logFp);
02927     logFp = NULL;
02928   }
02929 
02930   // FIXME-- debugging
02931   if (emcTaskNoDelay) {
02932     printf("cycle times (seconds): %f min, %f max\n", minTime, maxTime);
02933   }
02934 
02935   // and leave
02936   exit(0);
02937 }
02938 

Generated on Sun Dec 2 15:27:40 2001 for EMC by doxygen1.2.11.1 written by Dimitri van Heesch, © 1997-2001