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

iosh.cc

Go to the documentation of this file.
00001 /*
00002   iosh.cc
00003 
00004   Extended-Tcl-based general IO programming shell with NML connectivity
00005 
00006   Modification history:
00007 
00008   13-Oct-2000 tlr added a conditional based on linux so that the include
00009   file, <sys/io.h> was not included twice.
00010   21-Sep-2000  FMP added Tcl_SetVar(EMC_INIFILE) so that subscripts can
00011   access the .ini file name via $EMC_INIFILE.
00012   12-Apr-2000 WPS forced this file to compile on a SUN
00013   12-Apr-2000 WPS traded ifndef WIN32 for ifdef HAVE_TCL_EXTEND since
00014   I don't have tclExtend on the Suns either.
00015   20-Mar-2000 WPS made the EMC_DEBUG_NML flag enable NML error messages.
00016   13-Mar-2000 WPS added include <sys/io.h> for iopl() prototype.
00017   22-Jan-2000  FMP added call to Tcl_Exit(), exit() in thisQuit()
00018   21-Jan-2000  FMP added SIGINT signal handler
00019   20-Jan-2000  FMP added emc_io_status_tool_in_spindle,tool_prepped;
00020   added EMC_SPINDLE_ON,OFF; reworked NML handling so that serial number
00021   echoing, heartbeat are not done here and should be done in script
00022   14-Nov-1999  FMP added IO status setting functions
00023   13-Nov-1999  FMP added NML connectivity
00024   9-Nov-1999  FMP created
00025   */
00026 
00027 /*
00028   FIXME
00029 
00030   add tool_in_spindle status
00031 */
00032 
00033 #include <stdio.h>
00034 #include <string.h>
00035 #include <stdlib.h>
00036 #include <signal.h>
00037 
00038 #include "tcl.h"
00039 #ifdef HAVE_TCL_EXTEND
00040 #include "tclExtend.h"
00041 #endif
00042 
00043 #include "tk.h"
00044 
00045 #include "rcs.hh"               // etime()
00046 #include "posemath.h"           // PM_POSE
00047 #include "emc.hh"               // EMC NML
00048 #include "emcglb.h"             // EMC_NMLFILE, TRAJ_MAX_VELOCITY, etc.
00049 #include "emccfg.h"             // DEFAULT_TRAJ_MAX_VELOCITY
00050 #include "inifile.h"            // INIFILE
00051 
00052 #ifdef SUN
00053 /*
00054   The following variable is a special hack that is needed in order for
00055   Sun shared libraries to be used for Tcl.
00056  */
00057 extern "C" int matherr();
00058 int *tclDummyMathPtr = (int *) matherr;
00059 #endif
00060 
00061 #ifdef LINUX
00062 
00063 #include <unistd.h>             /* iopl() */
00064 #include "cppio.hh"             // inb(),cpp_outb() for C++ apps.
00065 
00066 #else
00067 
00068 // nullify in/out instructions for non-Linux plats, which don't have them
00069 #define cpp_iopl(level) 0
00070 #define cpp_inb(addr) 0
00071 #define cpp_outb(val,addr)
00072 #define cpp_inw(addr) 0
00073 #define cpp_outw(val,addr)
00074 #define cpp_inl(addr) 0
00075 #define cpp_outl(val,addr)
00076 
00077 #endif
00078 
00079 /*
00080   Using iosh:
00081 
00082   iosh {<script>} {-- -ini <ini file>}
00083 
00084   With filename, it opens NML buffers to the EMC IO, runs the script, closes
00085   the buffers, and quits.
00086 
00087   Without filename, it runs interactively.
00088 
00089   With -- -ini <inifile>, uses inifile instead of emc.ini. Note that
00090   the two dashes prevents Tcl from looking at the remaining args, which
00091   would otherwise trigger a Tcl error that it doesn't understand what
00092   -ini means.
00093 
00094   EMC IO commands:
00095 
00096   emc_io_connect
00097   emc_io_disconnect
00098   Open or close the NML buffers to the command in, status out, and error out.
00099   Returns 0 if OK, or -1 if not.
00100 
00101   emc_io_read_command
00102   Peek the NML command buffer. Returns 0 if OK, -1 if not.
00103 
00104   emc_io_get_command
00105   Puts the command string, e.g., "emc_aux_estop_off", or "none". Returns 0.
00106 
00107   emc_io_get_command_type
00108   Puts the command NML number. Returns 0.
00109 
00110   emc_io_get_serial_number
00111   Puts the command serial number. Returns 0.
00112 
00113   emc_io_write_status
00114   Write the EMC_IO_STAT structure out to NML. Returns 0 if OK, -1 if error.
00115 
00116   emc_io_write_error
00117   Write the error string to the error NML buffer. Returns 0 if OK, -1 if error.
00118 
00119   IO status, sets associated field in the NML status structure
00120 
00121   emc_io_status_heartbeat <number>
00122   emc_io_status_echo_serial_number <number>
00123   emc_io_status_status done | exec | error
00124   emc_io_status_estop on | off
00125   emc_io_status_mist on | off
00126   emc_io_status_flood on | off
00127   emc_io_status_lube on | off
00128   emc_io_status_lube_level ok | low
00129   emc_io_status_spindle_speed <speed>
00130   emc_io_status_spindle_enabled on | off
00131   emc_io_status_spindle_direction <pos> <neg> 0
00132   emc_io_status_spindle_increasing <pos> <neg> 0
00133   emc_io_status_spindle_brake on | off
00134   emc_io_status_tool_prepped <number>
00135   emc_io_status_tool_in_spindle <number>
00136 
00137   IO commands:
00138 
00139   inb <address>
00140   Reads and returns the byte at <address>. If address begins with 0x,
00141   it's interpreted as a hex number, otherwise it's decimal.
00142 
00143   outb <address> <value>
00144   Writes the byte <value> to <address>. If address or value begins with 0x,
00145   it's interpreted as a hex number, otherwise it's decimal. Returns nothing.
00146 
00147   inw <address>
00148   Reads and returns the short at <address>. If address begins with 0x,
00149   it's interpreted as a hex number, otherwise it's decimal.
00150 
00151   outw <address> <value>
00152   Writes the short <value> to <address>. If address or value begins with 0x,
00153   it's interpreted as a hex number, otherwise it's decimal. Returns nothing.
00154 
00155   inl <address>
00156   Reads and returns the long at <address>. If address begins with 0x,
00157   it's interpreted as a hex number, otherwise it's decimal.
00158 
00159   outl <address> <value>
00160   Writes the long <value> to <address>. If address or value begins with 0x,
00161   it's interpreted as a hex number, otherwise it's decimal. Returns nothing.
00162 */
00163 
00164 
00165 // the NML channels to the EMC task
00166 static RCS_CMD_CHANNEL *emcioCommandBuffer = 0;
00167 // NML command channel data pointer
00168 static RCS_CMD_MSG * emcioCommand = 0;
00169 static RCS_STAT_CHANNEL *emcioStatusBuffer = 0;
00170 static EMC_IO_STAT emcioStatus;
00171 
00172 // the NML channel for errors
00173 static NML *emcErrorBuffer = 0;
00174 
00175 static int emcIoNmlGet()
00176 {
00177   int retval = 0;
00178 
00179   // try to connect to EMC IO cmd
00180   if (emcioCommandBuffer == 0) {
00181     emcioCommandBuffer = new RCS_CMD_CHANNEL(emcFormat, "toolCmd", "tool", EMC_NMLFILE);
00182     if (! emcioCommandBuffer->valid()) {
00183       rcs_print_error("emcToolCmd buffer not available\n");
00184       delete emcioCommandBuffer;
00185       emcioCommandBuffer = 0;
00186       retval = -1;
00187     }
00188     else {
00189       // get our command data structure
00190       emcioCommand = emcioCommandBuffer->get_address();
00191     }
00192   }
00193 
00194   // try to connect to EMC IO status
00195   if (emcioStatusBuffer == 0) {
00196     emcioStatusBuffer = new RCS_STAT_CHANNEL(emcFormat, "toolSts", "tool", EMC_NMLFILE);
00197     if (! emcioStatusBuffer->valid()) {
00198       rcs_print_error("toolSts buffer not available\n");
00199       delete emcioStatusBuffer;
00200       emcioStatusBuffer = 0;
00201       retval = -1;
00202     }
00203     else {
00204       // initialize and write status
00205       emcioStatus.heartbeat = 0;
00206       emcioStatus.command_type = 0;
00207       emcioStatus.echo_serial_number = 0;
00208       emcioStatus.status = RCS_DONE;
00209       emcioStatusBuffer->write(&emcioStatus);
00210     }
00211   }
00212 
00213   return retval;
00214 }
00215 
00216 static int emcErrorNmlGet()
00217 {
00218   int retval = 0;
00219 
00220   if (emcErrorBuffer == 0) {
00221     emcErrorBuffer = new NML(nmlErrorFormat, "emcError", "tool", EMC_NMLFILE);
00222     if (! emcErrorBuffer->valid()) {
00223       rcs_print_error("emcError buffer not available\n");
00224       delete emcErrorBuffer;
00225       emcErrorBuffer = 0;
00226       retval = -1;
00227     }
00228   }
00229 
00230   return retval;
00231 }
00232 
00233 // EMC IO commands
00234 
00235 static int emc_ini(ClientData clientdata,
00236                    Tcl_Interp *interp,
00237                    int objc,
00238                    Tcl_Obj *CONST objv[])
00239 {
00240   INIFILE inifile;
00241   const char *inistring;
00242   const char *varstr, *secstr;
00243 
00244   if (objc != 3) {
00245     Tcl_SetResult(interp, "emc_ini: need 'var' and 'section'", TCL_VOLATILE);
00246     return TCL_ERROR;
00247   }
00248 
00249   // open it
00250   if (-1 == inifile.open(EMC_INIFILE)) {
00251     return -1;
00252   }
00253 
00254   varstr = Tcl_GetStringFromObj(objv[1], 0);
00255   secstr = Tcl_GetStringFromObj(objv[2], 0);
00256 
00257   if (NULL == (inistring = inifile.find(varstr, secstr))) {
00258     return TCL_OK;
00259   }
00260 
00261   Tcl_SetResult(interp, (char *) inistring, TCL_VOLATILE);
00262 
00263   // close it
00264   inifile.close();
00265 
00266   return TCL_OK;
00267 }
00268 
00269 static int emc_io_connect(ClientData clientdata,
00270                           Tcl_Interp *interp,
00271                           int objc,
00272                           Tcl_Obj *CONST objv[])
00273 {
00274   double end;
00275   int good;
00276 
00277 #define RETRY_TIME 10.0         // seconds to wait for subsystems to come up
00278 #define RETRY_INTERVAL 1.0      // seconds between wait tries for a subsystem
00279 
00280   if (objc != 1) {
00281     Tcl_SetResult(interp, "emc_io_connect: need no args\n", TCL_VOLATILE);
00282     return TCL_ERROR;
00283   }
00284   if (! (EMC_DEBUG & EMC_DEBUG_NML)) {
00285     set_rcs_print_destination(RCS_PRINT_TO_NULL);       // inhibit diag messages
00286   }
00287   end = RETRY_TIME;
00288   good = 0;
00289   do {
00290     if (0 == emcIoNmlGet()) {
00291       good = 1;
00292       break;
00293     }
00294     esleep(RETRY_INTERVAL);
00295     end -= RETRY_INTERVAL;
00296   } while (end > 0.0);
00297 
00298   if (! (EMC_DEBUG & EMC_DEBUG_NML)) {
00299     set_rcs_print_destination(RCS_PRINT_TO_STDOUT); // restore diag messages
00300   }
00301 
00302   if (! good) {
00303     Tcl_SetObjResult(interp, Tcl_NewIntObj(-1));
00304     return TCL_OK;
00305   }
00306 
00307   if (! (EMC_DEBUG & EMC_DEBUG_NML)) {
00308     set_rcs_print_destination(RCS_PRINT_TO_NULL);       // inhibit diag messages
00309   }
00310   end = RETRY_TIME;
00311   good = 0;
00312   do {
00313     if (0 == emcErrorNmlGet()) {
00314       good = 1;
00315       break;
00316     }
00317     esleep(RETRY_INTERVAL);
00318     end -= RETRY_INTERVAL;
00319   } while (end > 0.0);
00320 
00321   if (! (EMC_DEBUG & EMC_DEBUG_NML)) {
00322     set_rcs_print_destination(RCS_PRINT_TO_STDOUT); // restore diag messages
00323   }
00324   if (! good) {
00325     Tcl_SetObjResult(interp,Tcl_NewIntObj(-1));
00326     return TCL_OK;
00327   }
00328 
00329   Tcl_SetObjResult(interp, Tcl_NewIntObj(0));
00330   return TCL_OK;
00331 }
00332 
00333 static int emc_io_disconnect(ClientData clientdata,
00334                              Tcl_Interp *interp,
00335                              int objc,
00336                              Tcl_Obj *CONST objv[])
00337 {
00338   if (objc != 1) {
00339     Tcl_SetResult(interp, "emc_io_disconnect: need no args\n", TCL_VOLATILE);
00340     return TCL_ERROR;
00341   }
00342 
00343   if (emcErrorBuffer != 0) {
00344     delete emcErrorBuffer;
00345     emcErrorBuffer = 0;
00346   }
00347 
00348   if (emcioStatusBuffer != 0) {
00349     delete emcioStatusBuffer;
00350     emcioStatusBuffer = 0;
00351   }
00352 
00353   if (emcioCommandBuffer != 0) {
00354     delete emcioCommandBuffer;
00355     emcioCommandBuffer = 0;
00356   }
00357 
00358   Tcl_SetObjResult(interp, Tcl_NewIntObj(0));
00359   return TCL_OK;
00360 }
00361 
00362 /*
00363   emc_io_read_command peeks the NML command buffer. The side effect is
00364   that emcioCommand now latches the NML contents. Other functions, like
00365   emc_io_get_command,serial_number, get the contents from emcioCommand.
00366 
00367   Returns 0 if OK, -1 if error reading NML.
00368 */
00369 static int emc_io_read_command(ClientData clientdata,
00370                                Tcl_Interp *interp,
00371                                int objc,
00372                                Tcl_Obj *CONST objv[])
00373 {
00374   if (objc != 1) {
00375     Tcl_SetResult(interp, "emc_io_read_command: need no args\n", TCL_VOLATILE);
00376     return TCL_ERROR;
00377   }
00378 
00379   // read NML buffer
00380   if (0 == emcioCommandBuffer ||
00381       0 == emcioCommand) {
00382     Tcl_SetObjResult(interp, Tcl_NewIntObj(-1));
00383     return TCL_OK;
00384   }
00385 
00386   // latch new command into emcioCommand
00387   if (-1 == emcioCommandBuffer->peek()) {
00388     Tcl_SetObjResult(interp, Tcl_NewIntObj(-1));
00389     return TCL_OK;
00390   }
00391 
00392   Tcl_SetObjResult(interp, Tcl_NewIntObj(0));
00393   return TCL_OK;
00394 }
00395 
00396 /*
00397   emc_io_get_command returns the string and any args associated with
00398   the command, or "none" if nothing is there.
00399 
00400   The convention for returning strings is that they're the lower-case
00401   version of their NMLTYPE declarations in emc.hh, without the trailing
00402   _TYPE, e.g.,
00403 
00404   EMC_IO_INIT_TYPE -> emc_io_init
00405 
00406   Note that these aren't always what you type in emcsh, for example,
00407   EMC_AUX_ESTOP_OFF_TYPE -> emc_aux_estop off, not "emc_estop off". To
00408   support the interchangeability of these, emcsh will be set up so that
00409   the short versions ("emc_estop off") will supplement the conventional
00410   names, which will always be present.
00411 */
00412 static int emc_io_get_command(ClientData clientdata,
00413                               Tcl_Interp *interp,
00414                               int objc,
00415                               Tcl_Obj *CONST objv[])
00416 {
00417   NMLTYPE type;
00418   char string[256];
00419 
00420   if (objc != 1) {
00421     Tcl_SetResult(interp, "emc_io_read_command: need no args\n", TCL_VOLATILE);
00422     return TCL_ERROR;
00423   }
00424 
00425   // check for valid ptr
00426   if (0 == emcioCommand) {
00427     Tcl_SetResult(interp, "none", TCL_VOLATILE);
00428     return TCL_OK;
00429   }
00430 
00431   type = emcioCommand->type;
00432   switch (type) {
00433   case 0:
00434     Tcl_SetResult(interp, "none", TCL_VOLATILE);
00435     break;
00436 
00437   case EMC_IO_INIT_TYPE:
00438     Tcl_SetResult(interp, "emc_io_init", TCL_VOLATILE);
00439     break;
00440 
00441   case EMC_TOOL_INIT_TYPE:
00442     Tcl_SetResult(interp, "emc_tool_init", TCL_VOLATILE);
00443     break;
00444 
00445   case EMC_TOOL_HALT_TYPE:
00446     Tcl_SetResult(interp, "emc_tool_halt", TCL_VOLATILE);
00447     break;
00448 
00449   case EMC_TOOL_ABORT_TYPE:
00450     Tcl_SetResult(interp, "emc_tool_abort", TCL_VOLATILE);
00451     break;
00452 
00453   case EMC_TOOL_PREPARE_TYPE:
00454     sprintf(string, "emc_tool_prepare %d",
00455             ((EMC_TOOL_PREPARE *) emcioCommand)->tool);
00456     Tcl_SetResult(interp, string, TCL_VOLATILE);
00457     break;
00458 
00459   case EMC_TOOL_LOAD_TYPE:
00460     Tcl_SetResult(interp, "emc_tool_load", TCL_VOLATILE);
00461     break;
00462 
00463   case EMC_TOOL_UNLOAD_TYPE:
00464     Tcl_SetResult(interp, "emc_tool_unload", TCL_VOLATILE);
00465     break;
00466 
00467   case EMC_SPINDLE_INIT_TYPE:
00468     Tcl_SetResult(interp, "emc_spindle_init", TCL_VOLATILE);
00469     break;
00470 
00471   case EMC_SPINDLE_HALT_TYPE:
00472     Tcl_SetResult(interp, "emc_spindle_halt", TCL_VOLATILE);
00473     break;
00474 
00475   case EMC_SPINDLE_ABORT_TYPE:
00476     Tcl_SetResult(interp, "emc_spindle_abort", TCL_VOLATILE);
00477     break;
00478 
00479   case EMC_SPINDLE_ON_TYPE:
00480     sprintf(string, "emc_spindle_on %f",
00481             ((EMC_SPINDLE_ON *) emcioCommand)->speed);
00482     Tcl_SetResult(interp, string, TCL_VOLATILE);
00483     break;
00484 
00485   case EMC_SPINDLE_OFF_TYPE:
00486     Tcl_SetResult(interp, "emc_spindle_off", TCL_VOLATILE);
00487     break;
00488 
00489   case EMC_SPINDLE_FORWARD_TYPE:
00490     Tcl_SetResult(interp, "emc_spindle_forward", TCL_VOLATILE);
00491     break;
00492 
00493   case EMC_SPINDLE_REVERSE_TYPE:
00494     Tcl_SetResult(interp, "emc_spindle_reverse", TCL_VOLATILE);
00495     break;
00496 
00497   case EMC_SPINDLE_STOP_TYPE:
00498     Tcl_SetResult(interp, "emc_spindle_stop", TCL_VOLATILE);
00499     break;
00500 
00501   case EMC_SPINDLE_INCREASE_TYPE:
00502     Tcl_SetResult(interp, "emc_spindle_increase", TCL_VOLATILE);
00503     break;
00504 
00505   case EMC_SPINDLE_DECREASE_TYPE:
00506     Tcl_SetResult(interp, "emc_spindle_decrease", TCL_VOLATILE);
00507     break;
00508 
00509   case EMC_SPINDLE_CONSTANT_TYPE:
00510     Tcl_SetResult(interp, "emc_spindle_constant", TCL_VOLATILE);
00511     break;
00512 
00513   case EMC_SPINDLE_BRAKE_RELEASE_TYPE:
00514     Tcl_SetResult(interp, "emc_spindle_brake_release", TCL_VOLATILE);
00515     break;
00516 
00517   case EMC_SPINDLE_BRAKE_ENGAGE_TYPE:
00518     Tcl_SetResult(interp, "emc_spindle_brake_engage", TCL_VOLATILE);
00519     break;
00520 
00521   case EMC_COOLANT_INIT_TYPE:
00522     Tcl_SetResult(interp, "emc_coolant_init", TCL_VOLATILE);
00523     break;
00524 
00525   case EMC_COOLANT_HALT_TYPE:
00526     Tcl_SetResult(interp, "emc_coolant_halt", TCL_VOLATILE);
00527     break;
00528 
00529   case EMC_COOLANT_ABORT_TYPE:
00530     Tcl_SetResult(interp, "emc_coolant_abort", TCL_VOLATILE);
00531     break;
00532 
00533   case EMC_COOLANT_MIST_ON_TYPE:
00534     Tcl_SetResult(interp, "emc_coolant_mist_on", TCL_VOLATILE);
00535     break;
00536 
00537   case EMC_COOLANT_MIST_OFF_TYPE:
00538     Tcl_SetResult(interp, "emc_coolant_mist_off", TCL_VOLATILE);
00539     break;
00540 
00541   case EMC_COOLANT_FLOOD_ON_TYPE:
00542     Tcl_SetResult(interp, "emc_coolant_flood_on", TCL_VOLATILE);
00543     break;
00544 
00545   case EMC_COOLANT_FLOOD_OFF_TYPE:
00546     Tcl_SetResult(interp, "emc_coolant_flood_off", TCL_VOLATILE);
00547     break;
00548 
00549   case EMC_AUX_INIT_TYPE:
00550     Tcl_SetResult(interp, "emc_aux_init", TCL_VOLATILE);
00551     break;
00552 
00553   case EMC_AUX_HALT_TYPE:
00554     Tcl_SetResult(interp, "emc_aux_halt", TCL_VOLATILE);
00555     break;
00556 
00557   case EMC_AUX_ABORT_TYPE:
00558     Tcl_SetResult(interp, "emc_aux_abort", TCL_VOLATILE);
00559     break;
00560 
00561   case EMC_AUX_ESTOP_ON_TYPE:
00562     Tcl_SetResult(interp, "emc_aux_estop_on", TCL_VOLATILE);
00563     break;
00564 
00565   case EMC_AUX_ESTOP_OFF_TYPE:
00566     Tcl_SetResult(interp, "emc_aux_estop_off", TCL_VOLATILE);
00567     break;
00568 
00569   case EMC_LUBE_INIT_TYPE:
00570     Tcl_SetResult(interp, "emc_lube_init", TCL_VOLATILE);
00571     break;
00572 
00573   case EMC_LUBE_HALT_TYPE:
00574     Tcl_SetResult(interp, "emc_lube_halt", TCL_VOLATILE);
00575     break;
00576 
00577   case EMC_LUBE_ABORT_TYPE:
00578     Tcl_SetResult(interp, "emc_lube_abort", TCL_VOLATILE);
00579     break;
00580 
00581   case EMC_LUBE_ON_TYPE:
00582     Tcl_SetResult(interp, "emc_lube_on", TCL_VOLATILE);
00583     break;
00584 
00585   case EMC_LUBE_OFF_TYPE:
00586     Tcl_SetResult(interp, "emc_lube_off", TCL_VOLATILE);
00587     break;
00588 
00589   default:
00590     Tcl_SetResult(interp, (char *) emcSymbolLookup(type), TCL_VOLATILE);
00591     break;
00592   }
00593 
00594   return TCL_OK;
00595 }
00596 
00597 /*
00598   Returns the NML command type number
00599 */
00600 static int emc_io_get_command_type(ClientData clientdata,
00601                                     Tcl_Interp *interp,
00602                                     int objc,
00603                                     Tcl_Obj *CONST objv[])
00604 {
00605   if (objc != 1) {
00606     Tcl_SetResult(interp, "emc_io_get_command_type: need no args\n", TCL_VOLATILE);
00607     return TCL_ERROR;
00608   }
00609 
00610   Tcl_SetObjResult(interp, Tcl_NewIntObj(emcioCommand->type));
00611 
00612   return TCL_OK;
00613 }
00614 
00615 /*
00616   Returns the NML command serial number
00617 */
00618 static int emc_io_get_serial_number(ClientData clientdata,
00619                                     Tcl_Interp *interp,
00620                                     int objc,
00621                                     Tcl_Obj *CONST objv[])
00622 {
00623   if (objc != 1) {
00624     Tcl_SetResult(interp, "emc_io_get_serial_number: need no args\n", TCL_VOLATILE);
00625     return TCL_ERROR;
00626   }
00627 
00628   Tcl_SetObjResult(interp, Tcl_NewIntObj(emcioCommand->serial_number));
00629 
00630   return TCL_OK;
00631 }
00632 
00633 static int emc_io_write_status(ClientData clientdata,
00634                                Tcl_Interp *interp,
00635                                int objc,
00636                                Tcl_Obj *CONST objv[])
00637 {
00638   if (objc != 1) {
00639     Tcl_SetResult(interp, "emc_io_write_status: need no args", TCL_VOLATILE);
00640     return TCL_ERROR;
00641   }
00642 
00643   if (0 == emcioStatusBuffer) {
00644     Tcl_SetObjResult(interp, Tcl_NewIntObj(-1));
00645     return TCL_OK;
00646   }
00647 
00648   if (0 == emcioStatusBuffer->write(&emcioStatus)) {
00649     Tcl_SetObjResult(interp, Tcl_NewIntObj(0));
00650   }
00651   else {
00652     Tcl_SetObjResult(interp, Tcl_NewIntObj(-1));
00653   }
00654   return TCL_OK;
00655 }
00656 
00657 static int emc_io_write_error(ClientData clientdata,
00658                               Tcl_Interp *interp,
00659                               int objc,
00660                               Tcl_Obj *CONST objv[])
00661 {
00662   EMC_OPERATOR_ERROR error_msg;
00663 
00664   if (objc != 2) {
00665     Tcl_SetResult(interp, "emc_io_write_error: need error string", TCL_VOLATILE);
00666     return TCL_ERROR;
00667   }
00668 
00669   if (0 == emcErrorBuffer) {
00670     Tcl_SetObjResult(interp, Tcl_NewIntObj(-1));
00671     return TCL_OK;
00672   }
00673 
00674   strncpy(error_msg.error, Tcl_GetStringFromObj(objv[1], 0), EMC_OPERATOR_ERROR_LEN);
00675   error_msg.error[EMC_OPERATOR_ERROR_LEN - 1] = 0;
00676   if (0 == emcErrorBuffer->write(&error_msg)) {
00677     Tcl_SetObjResult(interp, Tcl_NewIntObj(0));
00678   }
00679   else {
00680     Tcl_SetObjResult(interp, Tcl_NewIntObj(-1));
00681   }
00682   return TCL_OK;
00683 }
00684 
00685 // IO status
00686 
00687 /* set the status heartbeat */
00688 static int emc_io_status_heartbeat(ClientData clientdata,
00689                                    Tcl_Interp *interp,
00690                                    int objc,
00691                                    Tcl_Obj *CONST objv[])
00692 {
00693   int heartbeat;
00694 
00695   if (objc != 2) {
00696     Tcl_SetResult(interp, "emc_io_status_heartbeat: need heartbeat", TCL_VOLATILE);
00697     return TCL_ERROR;
00698   }
00699 
00700   if (TCL_OK == Tcl_GetIntFromObj(0, objv[1], &heartbeat)) {
00701     emcioStatus.heartbeat = heartbeat;
00702     return TCL_OK;
00703   }
00704 
00705   Tcl_SetResult(interp, "emc_io_status_heartbeat: bad heartbeat", TCL_VOLATILE);
00706   return TCL_ERROR;
00707 }
00708 
00709 static int emc_io_status_command_type(ClientData clientdata,
00710                                       Tcl_Interp *interp,
00711                                       int objc,
00712                                       Tcl_Obj *CONST objv[])
00713 {
00714   int command_type;
00715 
00716   if (objc != 2) {
00717     Tcl_SetResult(interp, "emc_io_status_command_type: need command type", TCL_VOLATILE);
00718     return TCL_ERROR;
00719   }
00720 
00721   if (TCL_OK == Tcl_GetIntFromObj(0, objv[1], &command_type)) {
00722     emcioStatus.command_type = command_type;
00723     return TCL_OK;
00724   }
00725 
00726   Tcl_SetResult(interp, "emc_io_status_command_type: need command type", TCL_VOLATILE);
00727   return TCL_ERROR;
00728 }
00729 
00730 static int emc_io_status_echo_serial_number(ClientData clientdata,
00731                                             Tcl_Interp *interp,
00732                                             int objc,
00733                                             Tcl_Obj *CONST objv[])
00734 {
00735   int echo_serial_number;
00736 
00737   if (objc != 2) {
00738     Tcl_SetResult(interp, "emc_io_status_echo_serial_number: need echo serial number", TCL_VOLATILE);
00739     return TCL_ERROR;
00740   }
00741 
00742   if (TCL_OK == Tcl_GetIntFromObj(0, objv[1], &echo_serial_number)) {
00743     emcioStatus.echo_serial_number = echo_serial_number;
00744     return TCL_OK;
00745   }
00746 
00747   Tcl_SetResult(interp, "emc_io_status_echo_serial_number: need echo serial number", TCL_VOLATILE);
00748   return TCL_ERROR;
00749 }
00750 
00751 /*
00752   set the NML status to done, exec, error, or read it with no args.
00753 */
00754 static int emc_io_status_status(ClientData clientdata,
00755                                 Tcl_Interp *interp,
00756                                 int objc,
00757                                 Tcl_Obj *CONST objv[])
00758 {
00759   const char *objstr;
00760 
00761   if (objc != 2) {
00762     Tcl_SetResult(interp, "emc_io_status: need done | exec | error", TCL_VOLATILE);
00763     return TCL_ERROR;
00764   }
00765 
00766   objstr = Tcl_GetStringFromObj(objv[1], 0);
00767   if (! strcmp(objstr, "done")) {
00768     emcioStatus.status = RCS_DONE;
00769     return TCL_OK;
00770   }
00771   else if (! strcmp(objstr, "exec")) {
00772     emcioStatus.status = RCS_EXEC;
00773     return TCL_OK;
00774   }
00775   else if (! strcmp(objstr, "error")) {
00776     emcioStatus.status = RCS_ERROR;
00777     return TCL_OK;
00778   }
00779 
00780   Tcl_SetResult(interp, "emc_io_status: need done | exec | error", TCL_VOLATILE);
00781   return TCL_ERROR;
00782 }
00783 
00784 static int emc_io_status_estop(ClientData clientdata,
00785                                Tcl_Interp *interp,
00786                                int objc,
00787                                Tcl_Obj *CONST objv[])
00788 {
00789   const char *objstr;
00790 
00791   if (objc != 2) {
00792     Tcl_SetResult(interp, "emc_io_status_estop: need on | off", TCL_VOLATILE);
00793     return TCL_ERROR;
00794   }
00795 
00796   objstr = Tcl_GetStringFromObj(objv[1], 0);
00797   if (! strcmp(objstr, "on")) {
00798     emcioStatus.aux.estop = 1;
00799     return TCL_OK;
00800   }
00801   else if (! strcmp(objstr, "off")) {
00802     emcioStatus.aux.estop = 0;
00803     return TCL_OK;
00804   }
00805 
00806   Tcl_SetResult(interp, "emc_io_status_estop: need on | off", TCL_VOLATILE);
00807   return TCL_ERROR;
00808 }
00809 
00810 static int emc_io_status_mist(ClientData clientdata,
00811                               Tcl_Interp *interp,
00812                               int objc,
00813                               Tcl_Obj *CONST objv[])
00814 {
00815   const char *objstr;
00816 
00817   if (objc != 2) {
00818     Tcl_SetResult(interp, "emc_io_status_mist: need on | off", TCL_VOLATILE);
00819     return TCL_ERROR;
00820   }
00821 
00822   objstr = Tcl_GetStringFromObj(objv[1], 0);
00823   if (! strcmp(objstr, "on")) {
00824     emcioStatus.coolant.mist = 1;
00825     return TCL_OK;
00826   }
00827   else if (! strcmp(objstr, "off")) {
00828     emcioStatus.coolant.mist = 0;
00829     return TCL_OK;
00830   }
00831 
00832   Tcl_SetResult(interp, "emc_io_status_mist: need on | off", TCL_VOLATILE);
00833   return TCL_ERROR;
00834 }
00835 
00836 static int emc_io_status_flood(ClientData clientdata,
00837                                Tcl_Interp *interp,
00838                                int objc,
00839                                Tcl_Obj *CONST objv[])
00840 {
00841   const char *objstr;
00842 
00843   if (objc != 2) {
00844     Tcl_SetResult(interp, "emc_io_status_flood: need on | off", TCL_VOLATILE);
00845     return TCL_ERROR;
00846   }
00847 
00848   objstr = Tcl_GetStringFromObj(objv[1], 0);
00849   if (! strcmp(objstr, "on")) {
00850     emcioStatus.coolant.flood = 1;
00851     return TCL_OK;
00852   }
00853   else if (! strcmp(objstr, "off")) {
00854     emcioStatus.coolant.flood = 0;
00855     return TCL_OK;
00856   }
00857 
00858   Tcl_SetResult(interp, "emc_io_status_flood: need on | off", TCL_VOLATILE);
00859   return TCL_ERROR;
00860 }
00861 
00862 static int emc_io_status_lube(ClientData clientdata,
00863                               Tcl_Interp *interp,
00864                               int objc,
00865                               Tcl_Obj *CONST objv[])
00866 {
00867   const char *objstr;
00868 
00869   if (objc != 2) {
00870     Tcl_SetResult(interp, "emc_io_status_lube: need on | off", TCL_VOLATILE);
00871     return TCL_ERROR;
00872   }
00873 
00874   objstr = Tcl_GetStringFromObj(objv[1], 0);
00875   if (! strcmp(objstr, "on")) {
00876     emcioStatus.lube.on = 1;
00877     return TCL_OK;
00878   }
00879   else if (! strcmp(objstr, "off")) {
00880     emcioStatus.lube.on = 0;
00881     return TCL_OK;
00882   }
00883 
00884   Tcl_SetResult(interp, "emc_io_status_lube: need on | off", TCL_VOLATILE);
00885   return TCL_ERROR;
00886 }
00887 
00888 static int emc_io_status_lube_level(ClientData clientdata,
00889                                     Tcl_Interp *interp,
00890                                     int objc,
00891                                     Tcl_Obj *CONST objv[])
00892 {
00893   const char *objstr;
00894 
00895   if (objc != 2) {
00896     Tcl_SetResult(interp, "emc_io_status_lube_level: need ok | low", TCL_VOLATILE);
00897     return TCL_ERROR;
00898   }
00899 
00900   objstr = Tcl_GetStringFromObj(objv[1], 0);
00901   if (! strcmp(objstr, "ok")) {
00902     emcioStatus.lube.level = 1;
00903     return TCL_OK;
00904   }
00905   else if (! strcmp(objstr, "low")) {
00906     emcioStatus.lube.level = 0;
00907     return TCL_OK;
00908   }
00909 
00910   Tcl_SetResult(interp, "emc_io_status_lube_level: need ok | low", TCL_VOLATILE);
00911   return TCL_ERROR;
00912 }
00913 
00914 static int emc_io_status_spindle_speed(ClientData clientdata,
00915                                        Tcl_Interp *interp,
00916                                        int objc,
00917                                        Tcl_Obj *CONST objv[])
00918 {
00919   double speed;
00920 
00921   if (objc != 2) {
00922     Tcl_SetResult(interp, "emc_io_status_spindle_speed: need speed", TCL_VOLATILE);
00923     return TCL_ERROR;
00924   }
00925 
00926   if (TCL_OK == Tcl_GetDoubleFromObj(0, objv[1], &speed)) {
00927     emcioStatus.spindle.speed = speed;
00928     return TCL_OK;
00929   }
00930 
00931   Tcl_SetResult(interp, "emc_io_status_spindle_speed: need speed", TCL_VOLATILE);
00932   return TCL_ERROR;
00933 }
00934 
00935 static int emc_io_status_spindle_enabled(ClientData clientdata,
00936                                          Tcl_Interp *interp,
00937                                          int objc,
00938                                          Tcl_Obj *CONST objv[])
00939 {
00940   const char *objstr;
00941 
00942   if (objc != 2) {
00943     Tcl_SetResult(interp, "emc_io_status_spindle_enabled: need on | off", TCL_VOLATILE);
00944     return TCL_ERROR;
00945   }
00946 
00947   objstr = Tcl_GetStringFromObj(objv[1], 0);
00948   if (! strcmp(objstr, "on")) {
00949     emcioStatus.spindle.enabled = 1;
00950     return TCL_OK;
00951   }
00952   else if (! strcmp(objstr, "off")) {
00953     emcioStatus.spindle.enabled = 0;
00954     return TCL_OK;
00955   }
00956 
00957   Tcl_SetResult(interp, "emc_io_status_spindle_enabled: need on | off", TCL_VOLATILE);
00958   return TCL_ERROR;
00959 }
00960 
00961 static int emc_io_status_spindle_direction(ClientData clientdata,
00962                                            Tcl_Interp *interp,
00963                                            int objc,
00964                                            Tcl_Obj *CONST objv[])
00965 {
00966   int direction;
00967 
00968   if (objc != 2) {
00969     Tcl_SetResult(interp, "emc_io_status_spindle_direction: need direction", TCL_VOLATILE);
00970     return TCL_ERROR;
00971   }
00972 
00973   if (TCL_OK == Tcl_GetIntFromObj(0, objv[1], &direction)) {
00974     emcioStatus.spindle.direction = direction;
00975     return TCL_OK;
00976   }
00977 
00978   Tcl_SetResult(interp, "emc_io_status_spindle_direction: need direction", TCL_VOLATILE);
00979   return TCL_ERROR;
00980 }
00981 
00982 static int emc_io_status_spindle_increasing(ClientData clientdata,
00983                                            Tcl_Interp *interp,
00984                                            int objc,
00985                                            Tcl_Obj *CONST objv[])
00986 {
00987   int increasing;
00988 
00989   if (objc != 2) {
00990     Tcl_SetResult(interp, "emc_io_status_spindle_increasing: need increasing", TCL_VOLATILE);
00991     return TCL_ERROR;
00992   }
00993 
00994   if (TCL_OK == Tcl_GetIntFromObj(0, objv[1], &increasing)) {
00995     emcioStatus.spindle.increasing = increasing;
00996     return TCL_OK;
00997   }
00998 
00999   Tcl_SetResult(interp, "emc_io_status_spindle_increasing: need increasing", TCL_VOLATILE);
01000   return TCL_ERROR;
01001 }
01002 
01003 static int emc_io_status_spindle_brake(ClientData clientdata,
01004                                        Tcl_Interp *interp,
01005                                        int objc,
01006                                        Tcl_Obj *CONST objv[])
01007 {
01008   const char *objstr;
01009 
01010   if (objc != 2) {
01011     Tcl_SetResult(interp, "emc_io_status_spindle_brake: need on | off", TCL_VOLATILE);
01012     return TCL_ERROR;
01013   }
01014 
01015   objstr = Tcl_GetStringFromObj(objv[1], 0);
01016   if (! strcmp(objstr, "on")) {
01017     emcioStatus.spindle.brake = 1;
01018     return TCL_OK;
01019   }
01020   else if (! strcmp(objstr, "off")) {
01021     emcioStatus.spindle.brake = 0;
01022     return TCL_OK;
01023   }
01024 
01025   Tcl_SetResult(interp, "emc_io_status_spindle_brake: need on | off", TCL_VOLATILE);
01026   return TCL_ERROR;
01027 }
01028 
01029 static int emc_io_status_tool_prepped(ClientData clientdata,
01030                                       Tcl_Interp *interp,
01031                                       int objc,
01032                                       Tcl_Obj *CONST objv[])
01033 {
01034   int toolPrepped;
01035 
01036   if (objc != 2) {
01037     Tcl_SetResult(interp, "emc_io_status_tool_prepped: need tool", TCL_VOLATILE);
01038     return TCL_ERROR;
01039   }
01040 
01041   if (TCL_OK == Tcl_GetIntFromObj(0, objv[1], &toolPrepped)) {
01042     emcioStatus.tool.toolPrepped = toolPrepped;
01043     return TCL_OK;
01044   }
01045 
01046   Tcl_SetResult(interp, "emc_io_status_tool_prepped: need tool", TCL_VOLATILE);
01047   return TCL_ERROR;
01048 }
01049 
01050 static int emc_io_status_tool_in_spindle(ClientData clientdata,
01051                                          Tcl_Interp *interp,
01052                                          int objc,
01053                                          Tcl_Obj *CONST objv[])
01054 {
01055   int toolInSpindle;
01056 
01057   if (objc != 2) {
01058     Tcl_SetResult(interp, "emc_io_status_tool_in_spindle: need tool", TCL_VOLATILE);
01059     return TCL_ERROR;
01060   }
01061 
01062   if (TCL_OK == Tcl_GetIntFromObj(0, objv[1], &toolInSpindle)) {
01063     emcioStatus.tool.toolInSpindle = toolInSpindle;
01064     return TCL_OK;
01065   }
01066 
01067   Tcl_SetResult(interp, "emc_io_status_tool_in_spindle: need tool", TCL_VOLATILE);
01068   return TCL_ERROR;
01069 }
01070 
01071 // IO commands
01072 
01073 static int unpriv = 0;          // non-zero means can't read IO
01074 
01075 // note the leading f_ so we don't conflict with real inb
01076 static int f_inb(ClientData clientdata,
01077                  Tcl_Interp *interp,
01078                  int objc,
01079                  Tcl_Obj *CONST objv[])
01080 {
01081   long address;
01082 
01083   if (objc == 2) {
01084     if (TCL_OK == Tcl_GetLongFromObj(0, objv[1], &address)) {
01085       if (unpriv) {
01086         Tcl_SetObjResult(interp, Tcl_NewIntObj(0xFF));
01087         return TCL_OK;
01088       }
01089       Tcl_SetObjResult(interp, Tcl_NewIntObj((int) cpp_inb(address)));
01090       return TCL_OK;
01091     }
01092   }
01093 
01094   Tcl_SetResult(interp, "syntax: inb <address>", TCL_VOLATILE);
01095   return TCL_ERROR;
01096 }
01097 
01098 // note the leading f_ so we don't conflict with real outb
01099 static int f_outb(ClientData clientdata,
01100                   Tcl_Interp *interp,
01101                   int objc,
01102                   Tcl_Obj *CONST objv[])
01103 {
01104   long address;
01105   int value;
01106 
01107   if (objc == 3) {
01108     if (TCL_OK == Tcl_GetLongFromObj(0, objv[1], &address) &&
01109         TCL_OK == Tcl_GetIntFromObj(0, objv[2], &value)) {
01110       if (unpriv) {
01111         return TCL_OK;
01112       }
01113       cpp_outb((char) value, address);
01114       return TCL_OK;
01115     }
01116   }
01117 
01118   Tcl_SetResult(interp, "syntax: outb <address> <value>", TCL_VOLATILE);
01119   return TCL_ERROR;
01120 }
01121 
01122 // note the leading f_ so we don't conflict with real inw
01123 static int f_inw(ClientData clientdata,
01124                  Tcl_Interp *interp,
01125                  int objc,
01126                  Tcl_Obj *CONST objv[])
01127 {
01128   long address;
01129 
01130   if (objc == 2) {
01131     if (TCL_OK == Tcl_GetLongFromObj(0, objv[1], &address)) {
01132       if (unpriv) {
01133         Tcl_SetObjResult(interp, Tcl_NewIntObj(0xFFFF));
01134         return TCL_OK;
01135       }
01136       Tcl_SetObjResult(interp, Tcl_NewIntObj((int) cpp_inw(address)));
01137       return TCL_OK;
01138     }
01139   }
01140 
01141   Tcl_SetResult(interp, "syntax: inw <address>", TCL_VOLATILE);
01142   return TCL_ERROR;
01143 }
01144 
01145 // note the leading f_ so we don't conflict with real outw
01146 static int f_outw(ClientData clientdata,
01147                   Tcl_Interp *interp,
01148                   int objc,
01149                   Tcl_Obj *CONST objv[])
01150 {
01151   long address;
01152   int value;
01153 
01154   if (objc == 3) {
01155     if (TCL_OK == Tcl_GetLongFromObj(0, objv[1], &address) &&
01156         TCL_OK == Tcl_GetIntFromObj(0, objv[2], &value)) {
01157       if (unpriv) {
01158         return TCL_OK;
01159       }
01160       cpp_outw((short) value, address);
01161       return TCL_OK;
01162     }
01163   }
01164 
01165   Tcl_SetResult(interp, "syntax: outw <address> <value>", TCL_VOLATILE);
01166   return TCL_ERROR;
01167 }
01168 
01169 // note the leading f_ so we don't conflict with real inl
01170 static int f_inl(ClientData clientdata,
01171                  Tcl_Interp *interp,
01172                  int objc,
01173                  Tcl_Obj *CONST objv[])
01174 {
01175   long address;
01176 
01177   if (objc == 2) {
01178     if (TCL_OK == Tcl_GetLongFromObj(0, objv[1], &address)) {
01179       if (unpriv) {
01180         Tcl_SetObjResult(interp, Tcl_NewLongObj(0xFFFFFFFF));
01181         return TCL_OK;
01182       }
01183       Tcl_SetObjResult(interp, Tcl_NewLongObj(cpp_inl(address)));
01184       return TCL_OK;
01185     }
01186   }
01187 
01188   Tcl_SetResult(interp, "syntax: inl <address>", TCL_VOLATILE);
01189   return TCL_ERROR;
01190 }
01191 
01192 // note the leading f_ so we don't conflict with real outl
01193 static int f_outl(ClientData clientdata,
01194                   Tcl_Interp *interp,
01195                   int objc,
01196                   Tcl_Obj *CONST objv[])
01197 {
01198   long address;
01199   long value;
01200 
01201   if (objc == 3) {
01202     if (TCL_OK == Tcl_GetLongFromObj(0, objv[1], &address) &&
01203         TCL_OK == Tcl_GetLongFromObj(0, objv[2], &value)) {
01204       if (unpriv) {
01205         return TCL_OK;
01206       }
01207       cpp_outl(value, address);
01208       return TCL_OK;
01209     }
01210   }
01211 
01212   Tcl_SetResult(interp, "syntax: outl <address> <value>", TCL_VOLATILE);
01213   return TCL_ERROR;
01214 }
01215 
01216 int Tcl_AppInit(Tcl_Interp *interp)
01217 {
01218   /*
01219    * Call the init procedures for included packages.  Each call should
01220    * look like this:
01221    *
01222    * if (Mod_Init(interp) == TCL_ERROR) {
01223    *     return TCL_ERROR;
01224    * }
01225    *
01226    * where "Mod" is the name of the module.
01227    */
01228 
01229   if (Tcl_Init(interp) == TCL_ERROR) {
01230     return TCL_ERROR;
01231   }
01232 
01233 #ifdef HAVE_TCL_EXTEND
01234   if (Tclx_Init(interp) == TCL_ERROR) {
01235     return TCL_ERROR;
01236   }
01237 #endif
01238 
01239   if (Tk_Init(interp) == TCL_ERROR) {
01240       return TCL_ERROR;
01241   }
01242 
01243   /*
01244    * Call Tcl_CreateCommand for application-specific commands, if
01245    * they weren't already created by the init procedures called above.
01246    */
01247 
01248   Tcl_CreateObjCommand(interp, "emc_ini", emc_ini, (ClientData) NULL, (Tcl_CmdDeleteProc *) NULL);
01249 
01250   Tcl_CreateObjCommand(interp, "emc_io_connect", emc_io_connect, (ClientData) NULL, (Tcl_CmdDeleteProc *) NULL);
01251 
01252   Tcl_CreateObjCommand(interp, "emc_io_disconnect", emc_io_disconnect, (ClientData) NULL, (Tcl_CmdDeleteProc *) NULL);
01253 
01254   Tcl_CreateObjCommand(interp, "emc_io_read_command", emc_io_read_command, (ClientData) NULL, (Tcl_CmdDeleteProc *) NULL);
01255 
01256   Tcl_CreateObjCommand(interp, "emc_io_get_command", emc_io_get_command, (ClientData) NULL, (Tcl_CmdDeleteProc *) NULL);
01257 
01258   Tcl_CreateObjCommand(interp, "emc_io_get_command_type", emc_io_get_command_type, (ClientData) NULL, (Tcl_CmdDeleteProc *) NULL);
01259 
01260   Tcl_CreateObjCommand(interp, "emc_io_get_serial_number", emc_io_get_serial_number, (ClientData) NULL, (Tcl_CmdDeleteProc *) NULL);
01261 
01262   Tcl_CreateObjCommand(interp, "emc_io_write_status", emc_io_write_status, (ClientData) NULL, (Tcl_CmdDeleteProc *) NULL);
01263 
01264   Tcl_CreateObjCommand(interp, "emc_io_write_error", emc_io_write_error, (ClientData) NULL, (Tcl_CmdDeleteProc *) NULL);
01265 
01266   Tcl_CreateObjCommand(interp, "emc_io_status_heartbeat", emc_io_status_heartbeat, (ClientData) NULL, (Tcl_CmdDeleteProc *) NULL);
01267 
01268   Tcl_CreateObjCommand(interp, "emc_io_status_command_type", emc_io_status_command_type, (ClientData) NULL, (Tcl_CmdDeleteProc *) NULL);
01269 
01270   Tcl_CreateObjCommand(interp, "emc_io_status_echo_serial_number", emc_io_status_echo_serial_number, (ClientData) NULL, (Tcl_CmdDeleteProc *) NULL);
01271 
01272   Tcl_CreateObjCommand(interp, "emc_io_status_status", emc_io_status_status, (ClientData) NULL, (Tcl_CmdDeleteProc *) NULL);
01273 
01274   Tcl_CreateObjCommand(interp, "emc_io_status_estop", emc_io_status_estop, (ClientData) NULL, (Tcl_CmdDeleteProc *) NULL);
01275 
01276   Tcl_CreateObjCommand(interp, "emc_io_status_mist", emc_io_status_mist, (ClientData) NULL, (Tcl_CmdDeleteProc *) NULL);
01277 
01278   Tcl_CreateObjCommand(interp, "emc_io_status_flood", emc_io_status_flood, (ClientData) NULL, (Tcl_CmdDeleteProc *) NULL);
01279 
01280   Tcl_CreateObjCommand(interp, "emc_io_status_lube", emc_io_status_lube, (ClientData) NULL, (Tcl_CmdDeleteProc *) NULL);
01281 
01282   Tcl_CreateObjCommand(interp, "emc_io_status_lube_level", emc_io_status_lube_level, (ClientData) NULL, (Tcl_CmdDeleteProc *) NULL);
01283 
01284   Tcl_CreateObjCommand(interp, "emc_io_status_spindle_speed", emc_io_status_spindle_speed, (ClientData) NULL, (Tcl_CmdDeleteProc *) NULL);
01285 
01286   Tcl_CreateObjCommand(interp, "emc_io_status_spindle_enabled", emc_io_status_spindle_enabled, (ClientData) NULL, (Tcl_CmdDeleteProc *) NULL);
01287 
01288   Tcl_CreateObjCommand(interp, "emc_io_status_spindle_direction", emc_io_status_spindle_direction, (ClientData) NULL, (Tcl_CmdDeleteProc *) NULL);
01289 
01290   Tcl_CreateObjCommand(interp, "emc_io_status_spindle_increasing", emc_io_status_spindle_increasing, (ClientData) NULL, (Tcl_CmdDeleteProc *) NULL);
01291 
01292   Tcl_CreateObjCommand(interp, "emc_io_status_spindle_brake", emc_io_status_spindle_brake, (ClientData) NULL, (Tcl_CmdDeleteProc *) NULL);
01293 
01294   Tcl_CreateObjCommand(interp, "emc_io_status_tool_prepped", emc_io_status_tool_prepped, (ClientData) NULL, (Tcl_CmdDeleteProc *) NULL);
01295 
01296   Tcl_CreateObjCommand(interp, "emc_io_status_tool_in_spindle", emc_io_status_tool_in_spindle, (ClientData) NULL, (Tcl_CmdDeleteProc *) NULL);
01297 
01298   Tcl_CreateObjCommand(interp, "inb", f_inb, (ClientData) NULL, (Tcl_CmdDeleteProc *) NULL);
01299 
01300   Tcl_CreateObjCommand(interp, "outb", f_outb, (ClientData) NULL, (Tcl_CmdDeleteProc *) NULL);
01301 
01302   Tcl_CreateObjCommand(interp, "inw", f_inw, (ClientData) NULL, (Tcl_CmdDeleteProc *) NULL);
01303 
01304   Tcl_CreateObjCommand(interp, "outw", f_outw, (ClientData) NULL, (Tcl_CmdDeleteProc *) NULL);
01305 
01306   Tcl_CreateObjCommand(interp, "inl", f_inl, (ClientData) NULL, (Tcl_CmdDeleteProc *) NULL);
01307 
01308   Tcl_CreateObjCommand(interp, "outl", f_outl, (ClientData) NULL, (Tcl_CmdDeleteProc *) NULL);
01309 
01310   /*
01311    * Specify a user-specific startup file to invoke if the application
01312    * is run interactively.  Typically the startup file is "~/.apprc"
01313    * where "app" is the name of the application.  If this line is deleted
01314    * then no user-specific startup file will be run under any conditions.
01315    */
01316 
01317   Tcl_SetVar(interp, "tcl_rcFileName", "~/.tclmainrc", TCL_GLOBAL_ONLY);
01318 
01319   // set app-specific global variables
01320   Tcl_SetVar(interp, "EMC_INIFILE", EMC_INIFILE, TCL_GLOBAL_ONLY);
01321 
01322   return TCL_OK;
01323 }
01324 
01325 static void thisQuit(ClientData clientData)
01326 {
01327   // clean up NML channels
01328 
01329   if (emcErrorBuffer != 0) {
01330     delete emcErrorBuffer;
01331     emcErrorBuffer = 0;
01332   }
01333 
01334   if (emcioStatusBuffer != 0) {
01335     delete emcioStatusBuffer;
01336     emcioStatusBuffer = 0;
01337   }
01338 
01339   if (emcioCommandBuffer != 0) {
01340     delete emcioCommandBuffer;
01341     emcioCommandBuffer = 0;
01342     emcioCommand = 0;
01343   }
01344 
01345   // turn off port access
01346   cpp_iopl(0);
01347 
01348   Tcl_Exit(0);
01349   exit(0);
01350 }
01351 
01352 /*
01353   iniLoad() loads basic parameters from the ini file that are needed
01354   to define functions here:
01355 
01356   [EMC] DEBUG
01357   [EMC] VERSION
01358   [EMC] MACHINE
01359   [EMC] NML_FILE
01360 
01361   The rest of the ini file parameters for the IO subsystems, e.g.,
01362 
01363   [EMCIO] CYCLE_TIME
01364   [EMCIO] or [EMC] PARPORT_IO_ADDRESS
01365   [EMCIO] TOOL_TABLE
01366   [EMCIO] SPINDLE_OFF_WAIT
01367   [EMCIO] ESTOP_SENSE_INDEX
01368 
01369   etc. are read in by the Tcl/Tk script via emc_ini and used in the script.
01370 */
01371 
01372 static  int iniLoad(const char *filename)
01373 {
01374   INIFILE inifile;
01375   const char *inistring;
01376   char version[INIFILE_MAX_LINELEN];
01377 
01378   // open it
01379   if (-1 == inifile.open(filename)) {
01380     return -1;
01381   }
01382 
01383   if (NULL != (inistring = inifile.find("DEBUG", "EMC"))) {
01384     // copy to global
01385     if (1 != sscanf(inistring, "%i", &EMC_DEBUG)) {
01386       EMC_DEBUG = 0;
01387     }
01388   }
01389   else {
01390     // not found, use default
01391     EMC_DEBUG = 0;
01392   }
01393 
01394   if (EMC_DEBUG & EMC_DEBUG_VERSIONS) {
01395     if (NULL != (inistring = inifile.find("VERSION", "EMC"))) {
01396       // print version
01397       sscanf(inistring, "$Revision: %s", version);
01398       rcs_print("Version:  %s\n", version);
01399     }
01400     else {
01401       // not found, not fatal
01402       rcs_print("Version:  (not found)\n");
01403     }
01404 
01405     if (NULL != (inistring = inifile.find("MACHINE", "EMC"))) {
01406       // print machine
01407       rcs_print("Machine:  %s\n", inistring);
01408     }
01409     else {
01410       // not found, not fatal
01411       rcs_print("Machine:  (not found)\n");
01412     }
01413   }
01414 
01415   if (NULL != (inistring = inifile.find("NML_FILE", "EMC"))) {
01416     // copy to global
01417     strcpy(EMC_NMLFILE, inistring);
01418   }
01419   else {
01420     // not found, use default
01421   }
01422 
01423   // close it
01424   inifile.close();
01425 
01426   return 0;
01427 }
01428 
01429 static void sigQuit(int sig)
01430 {
01431   thisQuit((ClientData) 0);
01432 }
01433 
01434 int main(int argc, char *argv[])
01435 {
01436   // blank out the annoying RCS version message
01437   rcs_version_printed = 1;
01438 
01439   // process command line args
01440   if (0 != emcGetArgs(argc, argv)) {
01441     rcs_print_error("error in argument list\n");
01442     exit(1);
01443   }
01444 
01445   // get configuration information
01446   iniLoad(EMC_INIFILE);
01447 
01448   // turn on port access
01449   unpriv = 0;
01450   if (0 != cpp_iopl(3)) {
01451     fprintf(stderr, "not privileged to access IO-- disabling IO\n");
01452     unpriv = 1;
01453   }
01454 
01455   // attach our quit function to exit
01456   Tcl_CreateExitHandler(thisQuit, (ClientData) 0);
01457 
01458   // attach our quit function to SIGINT
01459   signal(SIGINT, sigQuit);
01460 
01461   // run Tk main loop
01462   Tk_Main(argc, argv, Tcl_AppInit);
01463 
01464   exit(0);
01465 }

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