Страница 6 из 19

Re: Сбор багов LinuxCNC ( багтрекер bug bugtracker баг )

Добавлено: 05 июл 2013, 10:32
Nick
Serg-tmn писал(а):Это выражается в том, что при загрузке файла, если в подпрограмме обнаруживается ошибка, LCNC указывает не номер строки в подпрограмме, где обнаружена ошибка, а номер строки, вызвавшей эту подпрограмму (точнее, следующей за ней, но простим ему эту мелочь).
Да, это есть такое, уже намучился с этим пока для features программы писал...

Re: Сбор багов LinuxCNC ( багтрекер bug bugtracker баг )

Добавлено: 29 авг 2013, 11:26
Bmax77
Обнаружил одну проблемку, не уверен что она именно в Linuxcnc, возможно это баг Stepconf.
Суть в следующем, у меня концевик HomeZ установлен в максимуме оси и как я не пытался настраивать, при поиске ось всевремя уезжала от концевика. Решилось это инверсией пина.
Но сейчас я решил освободить пин для пробника и соединил все Home на одном пине. Проблема решилась правкой ini-файла после Stepconf. Там где указаны скорости поиска датчика Home, поменял им знак на противоположный и ось поехала в нужном направлении.

Re: Сбор багов LinuxCNC ( багтрекер bug bugtracker баг )

Добавлено: 29 авг 2013, 11:45
Nick
По идее, достаточно поставить отрицательную скорость поиска нуля и направление поиска изменится.

Re: Сбор багов LinuxCNC ( багтрекер bug bugtracker баг )

Добавлено: 29 авг 2013, 11:46
Serg
Надо было просто внимательно документацию почитать - так лечится довольно много багов. :hehehe:

Re: Сбор багов LinuxCNC ( багтрекер bug bugtracker баг )

Добавлено: 29 авг 2013, 13:01
Bmax77
Nick писал(а):По идее, достаточно поставить отрицательную скорость поиска нуля и направление поиска изменится.
Ну собственно так и поступил.

Re: Сбор багов LinuxCNC ( багтрекер bug bugtracker баг )

Добавлено: 29 авг 2013, 14:07
Nick
Это не баг, это фича! Все так и должно работать!

Re: Сбор багов LinuxCNC ( багтрекер bug bugtracker баг )

Добавлено: 03 сен 2013, 16:14
torvn77
А когда всё таки сделают правильную настройку планировщику движений?
А то я поставил в арткаме скорость в 1440 мм.мин(24 мм/сек),а LinuxCNC разгоняется только гдето до 576 (точно не помню 560<F<580).
Натройка планировшика G64P0.05Q0.05
Максимальная скорость станка около 2,63 м/мин

Re: Сбор багов LinuxCNC ( багтрекер bug bugtracker баг )

Добавлено: 03 сен 2013, 18:32
michael-yurov
Может ты по рельефу ездишь?
Сделай бесконечно большие ускорения и будет тебе 1440 мм/мин.

Re: Сбор багов LinuxCNC ( багтрекер bug bugtracker баг )

Добавлено: 03 сен 2013, 18:40
torvn77
Может напутал между G64 и M52,буду перепроверять,но эта скорость получена на прямой линии.
Так что было где разогнаться.
--------------------
Сейчас всё нормально,но факт был,может дело в том что не перегружался после обновления или прозевал что-то ?

Re: Сбор багов LinuxCNC ( багтрекер bug bugtracker баг )

Добавлено: 15 сен 2013, 01:01
torvn77
У LinuxCNC есть неприятная фича,"speed overid" замедляет в том числе и скорость быстрого премещения (G00).
Было бы хорошо,если на эту скорость этот ползунок бы не влиял.
Но наверно тут очень много чего придётся переписывать,..
Так что я не надеюсь.
Но всё же поворчу.

Re: Сбор багов LinuxCNC ( багтрекер bug bugtracker баг )

Добавлено: 15 сен 2013, 01:32
PKM
torvn77, есть ползунок Feed override для подачи и Max velocity для общего ограничения.

Re: Сбор багов LinuxCNC ( багтрекер bug bugtracker баг )

Добавлено: 15 сен 2013, 21:09
PKM
torvn77 писал(а):У LinuxCNC есть неприятная фича,"speed overid" замедляет в том числе и скорость быстрого премещения (G00).
Ага, в списке рассылки тоже удивляются по этому поводу. Один из ведущих разработчиков говорит, что так и задумано :)

Re: Сбор багов LinuxCNC ( багтрекер bug bugtracker баг )

Добавлено: 19 сен 2013, 00:46
torvn77
Ползунком Max velocity я не пользуюсь и думаю.что вобще он не нужен.
А вот то,что к Feed override меняет не только фрезеровку,но и быстрое перемещение очень не удобно.
(В предыдущем своём посте я напутал название ползунка и имел ввиду Feed override)

Re: Сбор багов LinuxCNC ( багтрекер bug bugtracker баг )

Добавлено: 07 апр 2014, 23:20
nkp
не баг - но отмечу в этой теме...
встретил такой себе "архаизм" (а может ошибаюсь) ...
в сценарии запуска емс встречается программка "iosh"

Код: Выделить всё

function Cleanup() {

    echo "Shutting down and cleaning up LinuxCNC..."
    # Kill displays first - that should cause an orderly
    #   shutdown of the rest of linuxcnc
    for KILL_TASK in xlinuxcnc ylinuxcnc linuxcncpanel keystick iosh linuxcncsh linuxcncrsh linuxcnctop mdi debuglevel; do
	if $PIDOF $KILL_TASK >>$DEBUG_FILE ; then
	    KillTaskWithTimeout
	fi
    done
(для просмотра содержимого нажмите на ссылку)

Код: Выделить всё

/*
  iosh.cc

  Extended-Tcl-based general IO programming shell with NML connectivity

  Modification history:
  
  9-Nov-2002 P.C. Made a start on communications via shared memory with a
  view to accessing IO with calls to emcmot. Linked to usrmotintf for this
  reason.
  13-Oct-2000 tlr added a conditional based on linux so that the include
  file, <sys/io.h> was not included twice.
  21-Sep-2000  FMP added Tcl_SetVar(EMC_INIFILE) so that subscripts can
  access the .ini file name via $EMC_INIFILE.
  12-Apr-2000 WPS forced this file to compile on a SUN
  12-Apr-2000 WPS traded ifndef WIN32 for ifdef HAVE_TCL_EXTEND since
  I don't have tclExtend on the Suns either.
  20-Mar-2000 WPS made the EMC_DEBUG_NML flag enable NML error messages.
  13-Mar-2000 WPS added include <sys/io.h> for iopl() prototype.
  22-Jan-2000  FMP added call to Tcl_Exit(), exit() in thisQuit()
  21-Jan-2000  FMP added SIGINT signal handler
  20-Jan-2000  FMP added emc_io_status_tool_in_spindle,tool_prepped;
  added EMC_SPINDLE_ON,OFF; reworked NML handling so that serial number
  echoing, heartbeat are not done here and should be done in script
  14-Nov-1999  FMP added IO status setting functions
  13-Nov-1999  FMP added NML connectivity
  9-Nov-1999  FMP created
  */

/*
  FIXME

  add tool_in_spindle status
*/

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <signal.h>

#include "tcl.h"
#ifdef HAVE_TCL_EXTEND
#include "tclExtend.h"
#endif

#include "tk.h"

#include "rcs.hh"               // etime()
#include "posemath.h"           // PM_POSE
#include "emc.hh"               // EMC NML
#include "emcglb.h"             // EMC_NMLFILE, TRAJ_MAX_VELOCITY, etc.
#include "emccfg.h"             // DEFAULT_TRAJ_MAX_VELOCITY
#include "inifile.h"            // INIFILE
#include "emcmot.h"		// emc struct and commands
#include "usrmotintf.h"		// usrmot interface

#ifdef SUN
/*
  The following variable is a special hack that is needed in order for
  Sun shared libraries to be used for Tcl.
 */
extern "C" int matherr();
int *tclDummyMathPtr = (int *) matherr;
#endif

#ifdef LINUX

#include <unistd.h>             /* iopl() */
#include "cppio.hh"		// inb(),cpp_outb() for C++ apps.

#else

// nullify in/out instructions for non-Linux plats, which don't have them
#define cpp_iopl(level) 0
#define cpp_inb(addr) 0
#define cpp_outb(val,addr)
#define cpp_inw(addr) 0
#define cpp_outw(val,addr)
#define cpp_inl(addr) 0
#define cpp_outl(val,addr)

#endif

/*
  Using iosh:

  iosh {<script>} {-- -ini <ini file>}

  With filename, it opens NML buffers to the EMC IO, runs the script, closes
  the buffers, and quits.

  Without filename, it runs interactively.

  With -- -ini <inifile>, uses inifile instead of emc.ini. Note that
  the two dashes prevents Tcl from looking at the remaining args, which
  would otherwise trigger a Tcl error that it doesn't understand what
  -ini means.

  EMC IO commands:

  emc_io_connect
  emc_io_disconnect
  Open or close the NML buffers to the command in, status out, and error out.
  Returns 0 if OK, or -1 if not.

  emc_io_read_command
  Peek the NML command buffer. Returns 0 if OK, -1 if not.

  emc_io_get_command
  Puts the command string, e.g., "emc_aux_estop_off", or "none". Returns 0.

  emc_io_get_command_type
  Puts the command NML number. Returns 0.

  emc_io_get_serial_number
  Puts the command serial number. Returns 0.

  emc_io_write_status
  Write the EMC_IO_STAT structure out to NML. Returns 0 if OK, -1 if error.

  emc_io_write_error
  Write the error string to the error NML buffer. Returns 0 if OK, -1 if error.

  IO status, sets associated field in the NML status structure

  emc_io_status_heartbeat <number>
  emc_io_status_echo_serial_number <number>
  emc_io_status_status done | exec | error
  emc_io_status_estop on | off
  emc_io_status_mist on | off
  emc_io_status_flood on | off
  emc_io_status_lube on | off
  emc_io_status_lube_level ok | low
  emc_io_status_spindle_speed <speed>
  emc_io_status_spindle_enabled on | off
  emc_io_status_spindle_direction <pos> <neg> 0
  emc_io_status_spindle_increasing <pos> <neg> 0
  emc_io_status_spindle_brake on | off
  emc_io_status_tool_prepped <number>
  emc_io_status_tool_in_spindle <number>

  IO commands:

  inb <address>
  Reads and returns the byte at <address>. If address begins with 0x,
  it's interpreted as a hex number, otherwise it's decimal.

  outb <address> <value>
  Writes the byte <value> to <address>. If address or value begins with 0x,
  it's interpreted as a hex number, otherwise it's decimal. Returns nothing.

  inw <address>
  Reads and returns the short at <address>. If address begins with 0x,
  it's interpreted as a hex number, otherwise it's decimal.

  outw <address> <value>
  Writes the short <value> to <address>. If address or value begins with 0x,
  it's interpreted as a hex number, otherwise it's decimal. Returns nothing.

  inl <address>
  Reads and returns the long at <address>. If address begins with 0x,
  it's interpreted as a hex number, otherwise it's decimal.

  outl <address> <value>
  Writes the long <value> to <address>. If address or value begins with 0x,
  it's interpreted as a hex number, otherwise it's decimal. Returns nothing.
*/


// the NML channels to the EMC task
static RCS_CMD_CHANNEL *emcioCommandBuffer = 0;
// NML command channel data pointer
static RCS_CMD_MSG * emcioCommand = 0;
static RCS_STAT_CHANNEL *emcioStatusBuffer = 0;
static EMC_IO_STAT emcioStatus;

// the NML channel for errors
static NML *emcErrorBuffer = 0;

// Shared memory to communicate with emcmot
static EMCMOT_COMMAND emcmotCommand;
extern EMCMOT_STRUCT *emcmotshmem;
static long shmem = 0;			// Shared memory flag
static int motionId = 0;

static int emcIoNmlGet()
{
  int retval = 0;

  // try to connect to EMC IO cmd
  if (emcioCommandBuffer == 0) {
    emcioCommandBuffer = new RCS_CMD_CHANNEL(emcFormat, "toolCmd", "tool", EMC_NMLFILE);
    if (! emcioCommandBuffer->valid()) {
      rcs_print_error("emcToolCmd buffer not available\n");
      delete emcioCommandBuffer;
      emcioCommandBuffer = 0;
      retval = -1;
    }
    else {
      // get our command data structure
      emcioCommand = emcioCommandBuffer->get_address();
    }
  }

  // try to connect to EMC IO status
  if (emcioStatusBuffer == 0) {
    emcioStatusBuffer = new RCS_STAT_CHANNEL(emcFormat, "toolSts", "tool", EMC_NMLFILE);
    if (! emcioStatusBuffer->valid()) {
      rcs_print_error("toolSts buffer not available\n");
      delete emcioStatusBuffer;
      emcioStatusBuffer = 0;
      retval = -1;
    }
    else {
      // initialize and write status
      emcioStatus.heartbeat = 0;
      emcioStatus.command_type = 0;
      emcioStatus.echo_serial_number = 0;
      emcioStatus.status = RCS_DONE;
      emcioStatusBuffer->write(&emcioStatus);
    }
  }

  return retval;
}

static int emcErrorNmlGet()
{
  int retval = 0;

  if (emcErrorBuffer == 0) {
    emcErrorBuffer = new NML(nmlErrorFormat, "emcError", "tool", EMC_NMLFILE);
    if (! emcErrorBuffer->valid()) {
      rcs_print_error("emcError buffer not available\n");
      delete emcErrorBuffer;
      emcErrorBuffer = 0;
      retval = -1;
    }
  }

  return retval;
}

// EMC IO commands

static int emc_ini(ClientData clientdata,
                   Tcl_Interp *interp,
                   int objc,
                   Tcl_Obj *CONST objv[])
{
  INIFILE inifile;
  const char *inistring;
  const char *varstr, *secstr;

  if (objc != 3) {
    Tcl_SetResult(interp, "emc_ini: need 'var' and 'section'", TCL_VOLATILE);
    return TCL_ERROR;
  }

  // open it
  if (-1 == inifile.open(EMC_INIFILE)) {
    return -1;
  }

  varstr = Tcl_GetStringFromObj(objv[1], 0);
  secstr = Tcl_GetStringFromObj(objv[2], 0);

  if (NULL == (inistring = inifile.find(varstr, secstr))) {
    return TCL_OK;
  }

  Tcl_SetResult(interp, (char *) inistring, TCL_VOLATILE);

  // close it
  inifile.close();

  return TCL_OK;
}

static int emc_io_connect(ClientData clientdata,
                          Tcl_Interp *interp,
                          int objc,
                          Tcl_Obj *CONST objv[])
{
  double end;
  int good;

#define RETRY_TIME 10.0         // seconds to wait for subsystems to come up
#define RETRY_INTERVAL 1.0      // seconds between wait tries for a subsystem

  if (objc != 1) {
    Tcl_SetResult(interp, "emc_io_connect: need no args\n", TCL_VOLATILE);
    return TCL_ERROR;
  }
  if (! (EMC_DEBUG & EMC_DEBUG_NML)) {
    set_rcs_print_destination(RCS_PRINT_TO_NULL);       // inhibit diag messages
  }
  end = RETRY_TIME;
  good = 0;
  do {
    if (0 == emcIoNmlGet()) {
      good = 1;
      break;
    }
    esleep(RETRY_INTERVAL);
    end -= RETRY_INTERVAL;
  } while (end > 0.0);

  if (! (EMC_DEBUG & EMC_DEBUG_NML)) {
    set_rcs_print_destination(RCS_PRINT_TO_STDOUT); // restore diag messages
  }

  if (! good) {
    Tcl_SetObjResult(interp, Tcl_NewIntObj(-1));
    return TCL_OK;
  }

  if (! (EMC_DEBUG & EMC_DEBUG_NML)) {
    set_rcs_print_destination(RCS_PRINT_TO_NULL);       // inhibit diag messages
  }
  end = RETRY_TIME;
  good = 0;
  do {
    if (0 == emcErrorNmlGet()) {
      good = 1;
      break;
    }
    esleep(RETRY_INTERVAL);
    end -= RETRY_INTERVAL;
  } while (end > 0.0);

  if (! (EMC_DEBUG & EMC_DEBUG_NML)) {
    set_rcs_print_destination(RCS_PRINT_TO_STDOUT); // restore diag messages
  }
  if (! good) {
    Tcl_SetObjResult(interp,Tcl_NewIntObj(-1));
    return TCL_OK;
  }

  Tcl_SetObjResult(interp, Tcl_NewIntObj(0));
  return TCL_OK;
}

static int emc_io_disconnect(ClientData clientdata,
                             Tcl_Interp *interp,
                             int objc,
                             Tcl_Obj *CONST objv[])
{
  if (objc != 1) {
    Tcl_SetResult(interp, "emc_io_disconnect: need no args\n", TCL_VOLATILE);
    return TCL_ERROR;
  }

  if (emcErrorBuffer != 0) {
    delete emcErrorBuffer;
    emcErrorBuffer = 0;
  }

  if (emcioStatusBuffer != 0) {
    delete emcioStatusBuffer;
    emcioStatusBuffer = 0;
  }

  if (emcioCommandBuffer != 0) {
    delete emcioCommandBuffer;
    emcioCommandBuffer = 0;
  }

  Tcl_SetObjResult(interp, Tcl_NewIntObj(0));
  return TCL_OK;
}

/*
  emc_io_read_command peeks the NML command buffer. The side effect is
  that emcioCommand now latches the NML contents. Other functions, like
  emc_io_get_command,serial_number, get the contents from emcioCommand.

  Returns 0 if OK, -1 if error reading NML.
*/
static int emc_io_read_command(ClientData clientdata,
                               Tcl_Interp *interp,
                               int objc,
                               Tcl_Obj *CONST objv[])
{
  if (objc != 1) {
    Tcl_SetResult(interp, "emc_io_read_command: need no args\n", TCL_VOLATILE);
    return TCL_ERROR;
  }

  // read NML buffer
  if (0 == emcioCommandBuffer ||
      0 == emcioCommand) {
    Tcl_SetObjResult(interp, Tcl_NewIntObj(-1));
    return TCL_OK;
  }

  // latch new command into emcioCommand
  if (-1 == emcioCommandBuffer->peek()) {
    Tcl_SetObjResult(interp, Tcl_NewIntObj(-1));
    return TCL_OK;
  }

  Tcl_SetObjResult(interp, Tcl_NewIntObj(0));
  return TCL_OK;
}

/*
  emc_io_get_command returns the string and any args associated with
  the command, or "none" if nothing is there.

  The convention for returning strings is that they're the lower-case
  version of their NMLTYPE declarations in emc.hh, without the trailing
  _TYPE, e.g.,

  EMC_IO_INIT_TYPE -> emc_io_init

  Note that these aren't always what you type in emcsh, for example,
  EMC_AUX_ESTOP_OFF_TYPE -> emc_aux_estop off, not "emc_estop off". To
  support the interchangeability of these, emcsh will be set up so that
  the short versions ("emc_estop off") will supplement the conventional
  names, which will always be present.
*/
static int emc_io_get_command(ClientData clientdata,
                              Tcl_Interp *interp,
                              int objc,
                              Tcl_Obj *CONST objv[])
{
  NMLTYPE type;
  char string[256];

  if (objc != 1) {
    Tcl_SetResult(interp, "emc_io_read_command: need no args\n", TCL_VOLATILE);
    return TCL_ERROR;
  }

  // check for valid ptr
  if (0 == emcioCommand) {
    Tcl_SetResult(interp, "none", TCL_VOLATILE);
    return TCL_OK;
  }

  type = emcioCommand->type;
  switch (type) {
  case 0:
    Tcl_SetResult(interp, "none", TCL_VOLATILE);
    break;

  case EMC_IO_INIT_TYPE:
    Tcl_SetResult(interp, "emc_io_init", TCL_VOLATILE);
    break;

  case EMC_TOOL_INIT_TYPE:
    Tcl_SetResult(interp, "emc_tool_init", TCL_VOLATILE);
    break;

  case EMC_TOOL_HALT_TYPE:
    Tcl_SetResult(interp, "emc_tool_halt", TCL_VOLATILE);
    break;

  case EMC_TOOL_ABORT_TYPE:
    Tcl_SetResult(interp, "emc_tool_abort", TCL_VOLATILE);
    break;

  case EMC_TOOL_PREPARE_TYPE:
    sprintf(string, "emc_tool_prepare %d",
            ((EMC_TOOL_PREPARE *) emcioCommand)->tool);
    Tcl_SetResult(interp, string, TCL_VOLATILE);
    break;

  case EMC_TOOL_LOAD_TYPE:
    Tcl_SetResult(interp, "emc_tool_load", TCL_VOLATILE);
    break;

  case EMC_TOOL_UNLOAD_TYPE:
    Tcl_SetResult(interp, "emc_tool_unload", TCL_VOLATILE);
    break;

  case EMC_SPINDLE_INIT_TYPE:
    Tcl_SetResult(interp, "emc_spindle_init", TCL_VOLATILE);
    break;

  case EMC_SPINDLE_HALT_TYPE:
    Tcl_SetResult(interp, "emc_spindle_halt", TCL_VOLATILE);
    break;

  case EMC_SPINDLE_ABORT_TYPE:
    Tcl_SetResult(interp, "emc_spindle_abort", TCL_VOLATILE);
    break;

  case EMC_SPINDLE_ON_TYPE:
    sprintf(string, "emc_spindle_on %f",
            ((EMC_SPINDLE_ON *) emcioCommand)->speed);
    Tcl_SetResult(interp, string, TCL_VOLATILE);
    break;

  case EMC_SPINDLE_OFF_TYPE:
    Tcl_SetResult(interp, "emc_spindle_off", TCL_VOLATILE);
    break;

  case EMC_SPINDLE_FORWARD_TYPE:
    Tcl_SetResult(interp, "emc_spindle_forward", TCL_VOLATILE);
    break;

  case EMC_SPINDLE_REVERSE_TYPE:
    Tcl_SetResult(interp, "emc_spindle_reverse", TCL_VOLATILE);
    break;

  case EMC_SPINDLE_STOP_TYPE:
    Tcl_SetResult(interp, "emc_spindle_stop", TCL_VOLATILE);
    break;

  case EMC_SPINDLE_INCREASE_TYPE:
    Tcl_SetResult(interp, "emc_spindle_increase", TCL_VOLATILE);
    break;

  case EMC_SPINDLE_DECREASE_TYPE:
    Tcl_SetResult(interp, "emc_spindle_decrease", TCL_VOLATILE);
    break;

  case EMC_SPINDLE_CONSTANT_TYPE:
    Tcl_SetResult(interp, "emc_spindle_constant", TCL_VOLATILE);
    break;

  case EMC_SPINDLE_BRAKE_RELEASE_TYPE:
    Tcl_SetResult(interp, "emc_spindle_brake_release", TCL_VOLATILE);
    break;

  case EMC_SPINDLE_BRAKE_ENGAGE_TYPE:
    Tcl_SetResult(interp, "emc_spindle_brake_engage", TCL_VOLATILE);
    break;

  case EMC_COOLANT_INIT_TYPE:
    Tcl_SetResult(interp, "emc_coolant_init", TCL_VOLATILE);
    break;

  case EMC_COOLANT_HALT_TYPE:
    Tcl_SetResult(interp, "emc_coolant_halt", TCL_VOLATILE);
    break;

  case EMC_COOLANT_ABORT_TYPE:
    Tcl_SetResult(interp, "emc_coolant_abort", TCL_VOLATILE);
    break;

  case EMC_COOLANT_MIST_ON_TYPE:
    Tcl_SetResult(interp, "emc_coolant_mist_on", TCL_VOLATILE);
    break;

  case EMC_COOLANT_MIST_OFF_TYPE:
    Tcl_SetResult(interp, "emc_coolant_mist_off", TCL_VOLATILE);
    break;

  case EMC_COOLANT_FLOOD_ON_TYPE:
    Tcl_SetResult(interp, "emc_coolant_flood_on", TCL_VOLATILE);
    break;

  case EMC_COOLANT_FLOOD_OFF_TYPE:
    Tcl_SetResult(interp, "emc_coolant_flood_off", TCL_VOLATILE);
    break;

  case EMC_AUX_INIT_TYPE:
    Tcl_SetResult(interp, "emc_aux_init", TCL_VOLATILE);
    break;

  case EMC_AUX_HALT_TYPE:
    Tcl_SetResult(interp, "emc_aux_halt", TCL_VOLATILE);
    break;

  case EMC_AUX_ABORT_TYPE:
    Tcl_SetResult(interp, "emc_aux_abort", TCL_VOLATILE);
    break;

  case EMC_AUX_ESTOP_ON_TYPE:
    Tcl_SetResult(interp, "emc_aux_estop_on", TCL_VOLATILE);
    break;

  case EMC_AUX_ESTOP_OFF_TYPE:
    Tcl_SetResult(interp, "emc_aux_estop_off", TCL_VOLATILE);
    break;

  case EMC_LUBE_INIT_TYPE:
    Tcl_SetResult(interp, "emc_lube_init", TCL_VOLATILE);
    break;

  case EMC_LUBE_HALT_TYPE:
    Tcl_SetResult(interp, "emc_lube_halt", TCL_VOLATILE);
    break;

  case EMC_LUBE_ABORT_TYPE:
    Tcl_SetResult(interp, "emc_lube_abort", TCL_VOLATILE);
    break;

  case EMC_LUBE_ON_TYPE:
    Tcl_SetResult(interp, "emc_lube_on", TCL_VOLATILE);
    break;

  case EMC_LUBE_OFF_TYPE:
    Tcl_SetResult(interp, "emc_lube_off", TCL_VOLATILE);
    break;

  default:
    Tcl_SetResult(interp, (char *) emcSymbolLookup(type), TCL_VOLATILE);
    break;
  }

  return TCL_OK;
}

/*
  Returns the NML command type number
*/
static int emc_io_get_command_type(ClientData clientdata,
                                    Tcl_Interp *interp,
                                    int objc,
                                    Tcl_Obj *CONST objv[])
{
  if (objc != 1) {
    Tcl_SetResult(interp, "emc_io_get_command_type: need no args\n", TCL_VOLATILE);
    return TCL_ERROR;
  }

  Tcl_SetObjResult(interp, Tcl_NewIntObj(emcioCommand->type));

  return TCL_OK;
}

/*
  Returns the NML command serial number
*/
static int emc_io_get_serial_number(ClientData clientdata,
                                    Tcl_Interp *interp,
                                    int objc,
                                    Tcl_Obj *CONST objv[])
{
  if (objc != 1) {
    Tcl_SetResult(interp, "emc_io_get_serial_number: need no args\n", TCL_VOLATILE);
    return TCL_ERROR;
  }

  Tcl_SetObjResult(interp, Tcl_NewIntObj(emcioCommand->serial_number));

  return TCL_OK;
}

static int emc_io_write_status(ClientData clientdata,
                               Tcl_Interp *interp,
                               int objc,
                               Tcl_Obj *CONST objv[])
{
  if (objc != 1) {
    Tcl_SetResult(interp, "emc_io_write_status: need no args", TCL_VOLATILE);
    return TCL_ERROR;
  }

  if (0 == emcioStatusBuffer) {
    Tcl_SetObjResult(interp, Tcl_NewIntObj(-1));
    return TCL_OK;
  }

  if (0 == emcioStatusBuffer->write(&emcioStatus)) {
    Tcl_SetObjResult(interp, Tcl_NewIntObj(0));
  }
  else {
    Tcl_SetObjResult(interp, Tcl_NewIntObj(-1));
  }
  return TCL_OK;
}

static int emc_io_write_error(ClientData clientdata,
                              Tcl_Interp *interp,
                              int objc,
                              Tcl_Obj *CONST objv[])
{
  EMC_OPERATOR_ERROR error_msg;

  if (objc != 2) {
    Tcl_SetResult(interp, "emc_io_write_error: need error string", TCL_VOLATILE);
    return TCL_ERROR;
  }

  if (0 == emcErrorBuffer) {
    Tcl_SetObjResult(interp, Tcl_NewIntObj(-1));
    return TCL_OK;
  }

  strncpy(error_msg.error, Tcl_GetStringFromObj(objv[1], 0), EMC_OPERATOR_ERROR_LEN);
  error_msg.error[EMC_OPERATOR_ERROR_LEN - 1] = 0;
  if (0 == emcErrorBuffer->write(&error_msg)) {
    Tcl_SetObjResult(interp, Tcl_NewIntObj(0));
  }
  else {
    Tcl_SetObjResult(interp, Tcl_NewIntObj(-1));
  }
  return TCL_OK;
}

// IO status

/* set the status heartbeat */
static int emc_io_status_heartbeat(ClientData clientdata,
                                   Tcl_Interp *interp,
                                   int objc,
                                   Tcl_Obj *CONST objv[])
{
  int heartbeat;

  if (objc != 2) {
    Tcl_SetResult(interp, "emc_io_status_heartbeat: need heartbeat", TCL_VOLATILE);
    return TCL_ERROR;
  }

  if (TCL_OK == Tcl_GetIntFromObj(0, objv[1], &heartbeat)) {
    emcioStatus.heartbeat = heartbeat;
    return TCL_OK;
  }

  Tcl_SetResult(interp, "emc_io_status_heartbeat: bad heartbeat", TCL_VOLATILE);
  return TCL_ERROR;
}

static int emc_io_status_command_type(ClientData clientdata,
                                      Tcl_Interp *interp,
                                      int objc,
                                      Tcl_Obj *CONST objv[])
{
  int command_type;

  if (objc != 2) {
    Tcl_SetResult(interp, "emc_io_status_command_type: need command type", TCL_VOLATILE);
    return TCL_ERROR;
  }

  if (TCL_OK == Tcl_GetIntFromObj(0, objv[1], &command_type)) {
    emcioStatus.command_type = command_type;
    return TCL_OK;
  }

  Tcl_SetResult(interp, "emc_io_status_command_type: need command type", TCL_VOLATILE);
  return TCL_ERROR;
}

static int emc_io_status_echo_serial_number(ClientData clientdata,
                                            Tcl_Interp *interp,
                                            int objc,
                                            Tcl_Obj *CONST objv[])
{
  int echo_serial_number;

  if (objc != 2) {
    Tcl_SetResult(interp, "emc_io_status_echo_serial_number: need echo serial number", TCL_VOLATILE);
    return TCL_ERROR;
  }

  if (TCL_OK == Tcl_GetIntFromObj(0, objv[1], &echo_serial_number)) {
    emcioStatus.echo_serial_number = echo_serial_number;
    return TCL_OK;
  }

  Tcl_SetResult(interp, "emc_io_status_echo_serial_number: need echo serial number", TCL_VOLATILE);
  return TCL_ERROR;
}

/*
  set the NML status to done, exec, error, or read it with no args.
*/
static int emc_io_status_status(ClientData clientdata,
                                Tcl_Interp *interp,
                                int objc,
                                Tcl_Obj *CONST objv[])
{
  const char *objstr;

  if (objc != 2) {
    Tcl_SetResult(interp, "emc_io_status: need done | exec | error", TCL_VOLATILE);
    return TCL_ERROR;
  }

  objstr = Tcl_GetStringFromObj(objv[1], 0);
  if (! strcmp(objstr, "done")) {
    emcioStatus.status = RCS_DONE;
    return TCL_OK;
  }
  else if (! strcmp(objstr, "exec")) {
    emcioStatus.status = RCS_EXEC;
    return TCL_OK;
  }
  else if (! strcmp(objstr, "error")) {
    emcioStatus.status = RCS_ERROR;
    return TCL_OK;
  }

  Tcl_SetResult(interp, "emc_io_status: need done | exec | error", TCL_VOLATILE);
  return TCL_ERROR;
}

static int emc_io_status_estop(ClientData clientdata,
                               Tcl_Interp *interp,
                               int objc,
                               Tcl_Obj *CONST objv[])
{
  const char *objstr;

  if (objc != 2) {
    Tcl_SetResult(interp, "emc_io_status_estop: need on | off", TCL_VOLATILE);
    return TCL_ERROR;
  }

  objstr = Tcl_GetStringFromObj(objv[1], 0);
  if (! strcmp(objstr, "on")) {
    emcioStatus.aux.estop = 1;
    return TCL_OK;
  }
  else if (! strcmp(objstr, "off")) {
    emcioStatus.aux.estop = 0;
    return TCL_OK;
  }

  Tcl_SetResult(interp, "emc_io_status_estop: need on | off", TCL_VOLATILE);
  return TCL_ERROR;
}

static int emc_io_status_mist(ClientData clientdata,
                              Tcl_Interp *interp,
                              int objc,
                              Tcl_Obj *CONST objv[])
{
  const char *objstr;

  if (objc != 2) {
    Tcl_SetResult(interp, "emc_io_status_mist: need on | off", TCL_VOLATILE);
    return TCL_ERROR;
  }

  objstr = Tcl_GetStringFromObj(objv[1], 0);
  if (! strcmp(objstr, "on")) {
    emcioStatus.coolant.mist = 1;
    return TCL_OK;
  }
  else if (! strcmp(objstr, "off")) {
    emcioStatus.coolant.mist = 0;
    return TCL_OK;
  }

  Tcl_SetResult(interp, "emc_io_status_mist: need on | off", TCL_VOLATILE);
  return TCL_ERROR;
}

static int emc_io_status_flood(ClientData clientdata,
                               Tcl_Interp *interp,
                               int objc,
                               Tcl_Obj *CONST objv[])
{
  const char *objstr;

  if (objc != 2) {
    Tcl_SetResult(interp, "emc_io_status_flood: need on | off", TCL_VOLATILE);
    return TCL_ERROR;
  }

  objstr = Tcl_GetStringFromObj(objv[1], 0);
  if (! strcmp(objstr, "on")) {
    emcioStatus.coolant.flood = 1;
    return TCL_OK;
  }
  else if (! strcmp(objstr, "off")) {
    emcioStatus.coolant.flood = 0;
    return TCL_OK;
  }

  Tcl_SetResult(interp, "emc_io_status_flood: need on | off", TCL_VOLATILE);
  return TCL_ERROR;
}

static int emc_io_status_lube(ClientData clientdata,
                              Tcl_Interp *interp,
                              int objc,
                              Tcl_Obj *CONST objv[])
{
  const char *objstr;

  if (objc != 2) {
    Tcl_SetResult(interp, "emc_io_status_lube: need on | off", TCL_VOLATILE);
    return TCL_ERROR;
  }

  objstr = Tcl_GetStringFromObj(objv[1], 0);
  if (! strcmp(objstr, "on")) {
    emcioStatus.lube.on = 1;
    return TCL_OK;
  }
  else if (! strcmp(objstr, "off")) {
    emcioStatus.lube.on = 0;
    return TCL_OK;
  }

  Tcl_SetResult(interp, "emc_io_status_lube: need on | off", TCL_VOLATILE);
  return TCL_ERROR;
}

static int emc_io_status_lube_level(ClientData clientdata,
                                    Tcl_Interp *interp,
                                    int objc,
                                    Tcl_Obj *CONST objv[])
{
  const char *objstr;

  if (objc != 2) {
    Tcl_SetResult(interp, "emc_io_status_lube_level: need ok | low", TCL_VOLATILE);
    return TCL_ERROR;
  }

  objstr = Tcl_GetStringFromObj(objv[1], 0);
  if (! strcmp(objstr, "ok")) {
    emcioStatus.lube.level = 1;
    return TCL_OK;
  }
  else if (! strcmp(objstr, "low")) {
    emcioStatus.lube.level = 0;
    return TCL_OK;
  }

  Tcl_SetResult(interp, "emc_io_status_lube_level: need ok | low", TCL_VOLATILE);
  return TCL_ERROR;
}

static int emc_io_status_spindle_speed(ClientData clientdata,
                                       Tcl_Interp *interp,
                                       int objc,
                                       Tcl_Obj *CONST objv[])
{
  double speed;

  if (objc != 2) {
    Tcl_SetResult(interp, "emc_io_status_spindle_speed: need speed", TCL_VOLATILE);
    return TCL_ERROR;
  }

  if (TCL_OK == Tcl_GetDoubleFromObj(0, objv[1], &speed)) {
    emcioStatus.spindle.speed = speed;
    return TCL_OK;
  }

  Tcl_SetResult(interp, "emc_io_status_spindle_speed: need speed", TCL_VOLATILE);
  return TCL_ERROR;
}

static int emc_io_status_spindle_enabled(ClientData clientdata,
                                         Tcl_Interp *interp,
                                         int objc,
                                         Tcl_Obj *CONST objv[])
{
  const char *objstr;

  if (objc != 2) {
    Tcl_SetResult(interp, "emc_io_status_spindle_enabled: need on | off", TCL_VOLATILE);
    return TCL_ERROR;
  }

  objstr = Tcl_GetStringFromObj(objv[1], 0);
  if (! strcmp(objstr, "on")) {
    emcioStatus.spindle.enabled = 1;
    return TCL_OK;
  }
  else if (! strcmp(objstr, "off")) {
    emcioStatus.spindle.enabled = 0;
    return TCL_OK;
  }

  Tcl_SetResult(interp, "emc_io_status_spindle_enabled: need on | off", TCL_VOLATILE);
  return TCL_ERROR;
}

static int emc_io_status_spindle_direction(ClientData clientdata,
                                           Tcl_Interp *interp,
                                           int objc,
                                           Tcl_Obj *CONST objv[])
{
  int direction;

  if (objc != 2) {
    Tcl_SetResult(interp, "emc_io_status_spindle_direction: need direction", TCL_VOLATILE);
    return TCL_ERROR;
  }

  if (TCL_OK == Tcl_GetIntFromObj(0, objv[1], &direction)) {
    emcioStatus.spindle.direction = direction;
    return TCL_OK;
  }

  Tcl_SetResult(interp, "emc_io_status_spindle_direction: need direction", TCL_VOLATILE);
  return TCL_ERROR;
}

static int emc_io_status_spindle_increasing(ClientData clientdata,
                                           Tcl_Interp *interp,
                                           int objc,
                                           Tcl_Obj *CONST objv[])
{
  int increasing;

  if (objc != 2) {
    Tcl_SetResult(interp, "emc_io_status_spindle_increasing: need increasing", TCL_VOLATILE);
    return TCL_ERROR;
  }

  if (TCL_OK == Tcl_GetIntFromObj(0, objv[1], &increasing)) {
    emcioStatus.spindle.increasing = increasing;
    return TCL_OK;
  }

  Tcl_SetResult(interp, "emc_io_status_spindle_increasing: need increasing", TCL_VOLATILE);
  return TCL_ERROR;
}

static int emc_io_status_spindle_brake(ClientData clientdata,
                                       Tcl_Interp *interp,
                                       int objc,
                                       Tcl_Obj *CONST objv[])
{
  const char *objstr;

  if (objc != 2) {
    Tcl_SetResult(interp, "emc_io_status_spindle_brake: need on | off", TCL_VOLATILE);
    return TCL_ERROR;
  }

  objstr = Tcl_GetStringFromObj(objv[1], 0);
  if (! strcmp(objstr, "on")) {
    emcioStatus.spindle.brake = 1;
    return TCL_OK;
  }
  else if (! strcmp(objstr, "off")) {
    emcioStatus.spindle.brake = 0;
    return TCL_OK;
  }

  Tcl_SetResult(interp, "emc_io_status_spindle_brake: need on | off", TCL_VOLATILE);
  return TCL_ERROR;
}

static int emc_io_status_tool_prepped(ClientData clientdata,
                                      Tcl_Interp *interp,
                                      int objc,
                                      Tcl_Obj *CONST objv[])
{
  int toolPrepped;

  if (objc != 2) {
    Tcl_SetResult(interp, "emc_io_status_tool_prepped: need tool", TCL_VOLATILE);
    return TCL_ERROR;
  }

  if (TCL_OK == Tcl_GetIntFromObj(0, objv[1], &toolPrepped)) {
    emcioStatus.tool.toolPrepped = toolPrepped;
    return TCL_OK;
  }

  Tcl_SetResult(interp, "emc_io_status_tool_prepped: need tool", TCL_VOLATILE);
  return TCL_ERROR;
}

static int emc_io_status_tool_in_spindle(ClientData clientdata,
                                         Tcl_Interp *interp,
                                         int objc,
                                         Tcl_Obj *CONST objv[])
{
  int toolInSpindle;

  if (objc != 2) {
    Tcl_SetResult(interp, "emc_io_status_tool_in_spindle: need tool", TCL_VOLATILE);
    return TCL_ERROR;
  }

  if (TCL_OK == Tcl_GetIntFromObj(0, objv[1], &toolInSpindle)) {
    emcioStatus.tool.toolInSpindle = toolInSpindle;
    return TCL_OK;
  }

  Tcl_SetResult(interp, "emc_io_status_tool_in_spindle: need tool", TCL_VOLATILE);
  return TCL_ERROR;
}

// IO commands

static int unpriv = 0;          // non-zero means can't read IO

// note the leading f_ so we don't conflict with real inb
static int f_inb(ClientData clientdata,
                 Tcl_Interp *interp,
                 int objc,
                 Tcl_Obj *CONST objv[])
{
  long address;

  if (objc == 2) {
    if (TCL_OK == Tcl_GetLongFromObj(0, objv[1], &address)) {
      if (unpriv) {
        Tcl_SetObjResult(interp, Tcl_NewIntObj(0xFF));
        return TCL_OK;
      }
      Tcl_SetObjResult(interp, Tcl_NewIntObj((int) cpp_inb(address)));
      return TCL_OK;
    }
  }

  Tcl_SetResult(interp, "syntax: inb <address>", TCL_VOLATILE);
  return TCL_ERROR;
}

// note the leading f_ so we don't conflict with real outb
static int f_outb(ClientData clientdata,
                  Tcl_Interp *interp,
                  int objc,
                  Tcl_Obj *CONST objv[])
{
  long address;
  int value;

  if (objc == 3) {
    if (TCL_OK == Tcl_GetLongFromObj(0, objv[1], &address) &&
        TCL_OK == Tcl_GetIntFromObj(0, objv[2], &value)) {
      if (unpriv) {
        return TCL_OK;
      }
      cpp_outb((char) value, address);
      return TCL_OK;
    }
  }

  Tcl_SetResult(interp, "syntax: outb <address> <value>", TCL_VOLATILE);
  return TCL_ERROR;
}

// note the leading f_ so we don't conflict with real inw
static int f_inw(ClientData clientdata,
                 Tcl_Interp *interp,
                 int objc,
                 Tcl_Obj *CONST objv[])
{
  long address;

  if (objc == 2) {
    if (TCL_OK == Tcl_GetLongFromObj(0, objv[1], &address)) {
      if (unpriv) {
        Tcl_SetObjResult(interp, Tcl_NewIntObj(0xFFFF));
        return TCL_OK;
      }
      Tcl_SetObjResult(interp, Tcl_NewIntObj((int) cpp_inw(address)));
      return TCL_OK;
    }
  }

  Tcl_SetResult(interp, "syntax: inw <address>", TCL_VOLATILE);
  return TCL_ERROR;
}

// note the leading f_ so we don't conflict with real outw
static int f_outw(ClientData clientdata,
                  Tcl_Interp *interp,
                  int objc,
                  Tcl_Obj *CONST objv[])
{
  long address;
  int value;

  if (objc == 3) {
    if (TCL_OK == Tcl_GetLongFromObj(0, objv[1], &address) &&
        TCL_OK == Tcl_GetIntFromObj(0, objv[2], &value)) {
      if (unpriv) {
        return TCL_OK;
      }
      cpp_outw((short) value, address);
      return TCL_OK;
    }
  }

  Tcl_SetResult(interp, "syntax: outw <address> <value>", TCL_VOLATILE);
  return TCL_ERROR;
}

// note the leading f_ so we don't conflict with real inl
static int f_inl(ClientData clientdata,
                 Tcl_Interp *interp,
                 int objc,
                 Tcl_Obj *CONST objv[])
{
  long address;

  if (objc == 2) {
    if (TCL_OK == Tcl_GetLongFromObj(0, objv[1], &address)) {
      if (unpriv) {
        Tcl_SetObjResult(interp, Tcl_NewLongObj(0xFFFFFFFF));
        return TCL_OK;
      }
      Tcl_SetObjResult(interp, Tcl_NewLongObj(cpp_inl(address)));
      return TCL_OK;
    }
  }

  Tcl_SetResult(interp, "syntax: inl <address>", TCL_VOLATILE);
  return TCL_ERROR;
}

// note the leading f_ so we don't conflict with real outl
static int f_outl(ClientData clientdata,
                  Tcl_Interp *interp,
                  int objc,
                  Tcl_Obj *CONST objv[])
{
  long address;
  long value;

  if (objc == 3) {
    if (TCL_OK == Tcl_GetLongFromObj(0, objv[1], &address) &&
        TCL_OK == Tcl_GetLongFromObj(0, objv[2], &value)) {
      if (unpriv) {
        return TCL_OK;
      }
      cpp_outl(value, address);
      return TCL_OK;
    }
  }

  Tcl_SetResult(interp, "syntax: outl <address> <value>", TCL_VOLATILE);
  return TCL_ERROR;
}

static int emc_mot_shmem(ClientData clientdata,
                  Tcl_Interp *interp,
                  int objc,
                  Tcl_Obj *CONST objv[])
{

  if (objc == 1) {
      if (unpriv) {
        Tcl_SetObjResult(interp, Tcl_NewLongObj(0xFFFFFFFF));
        return TCL_OK;
      }
      Tcl_SetObjResult(interp, Tcl_NewLongObj(shmem));
      return TCL_OK;
  }

  Tcl_SetResult(interp, "emc_mot_shmem: need no args", TCL_VOLATILE);
  return TCL_ERROR;
}

static int emc_mot_rawinput(ClientData clientdata,
                 Tcl_Interp *interp,
                 int objc,
                 Tcl_Obj *CONST objv[])
{
  int axis;

  if (objc == 2) {
    if (TCL_OK == Tcl_GetIntFromObj(0, objv[1], &axis)) {
      if (shmem > 0) {
        Tcl_SetObjResult(interp, Tcl_NewDoubleObj(emcmotshmem->debug.rawInput[axis]));
        return TCL_OK;
      } else {
      Tcl_SetObjResult(interp, Tcl_NewDoubleObj(0));
      return TCL_OK;
    }
  }
 }
  Tcl_SetResult(interp, "syntax: emc_mot_rawinput <axis>", TCL_VOLATILE);
  return TCL_ERROR;
}

static int emc_mot_move(ClientData clientdata,
                 Tcl_Interp *interp,
                 int objc,
                 Tcl_Obj *CONST objv[])
{
  int axis;
  double move;
  double vel;

  if (objc == 4) {
    if (TCL_OK != Tcl_GetIntFromObj(0, objv[1], &axis)) {
      return TCL_ERROR;
      }
    if (TCL_OK != Tcl_GetDoubleFromObj(0, objv[2], &move)) {
      return TCL_ERROR;
      }
    if (TCL_OK != Tcl_GetDoubleFromObj(0, objv[3], &vel)) {
      return TCL_ERROR;
      }
// Set the velocity
    emcmotCommand.vel = vel;
    emcmotCommand.command =EMCMOT_SET_VEL;
    usrmotWriteEmcmotCommand(&emcmotCommand);
// Get the current position
    emcmotCommand.pos.tran.x = emcmotshmem->status.actualPos.tran.x;
    emcmotCommand.pos.tran.y = emcmotshmem->status.actualPos.tran.y;
    emcmotCommand.pos.tran.z = emcmotshmem->status.actualPos.tran.z;
// Program the move
    switch (axis) {
    case 0:
      emcmotCommand.pos.tran.x = move;
    break;
    case 1:
      emcmotCommand.pos.tran.y = move;
    break;
    case 2:
      emcmotCommand.pos.tran.z = move;
    break;
    }

    emcmotCommand.id = emcmotshmem->status.id ++;
    emcmotCommand.command =EMCMOT_SET_LINE;
    usrmotWriteEmcmotCommand(&emcmotCommand);
    return TCL_OK;
  }

  Tcl_SetResult(interp, "syntax: emc_mot_move <axis> <position> <velocity>", TCL_VOLATILE);
  return TCL_ERROR;
}

int Tcl_AppInit(Tcl_Interp *interp)
{
  /*
   * Call the init procedures for included packages.  Each call should
   * look like this:
   *
   * if (Mod_Init(interp) == TCL_ERROR) {
   *     return TCL_ERROR;
   * }
   *
   * where "Mod" is the name of the module.
   */

  if (Tcl_Init(interp) == TCL_ERROR) {
    return TCL_ERROR;
  }

#ifdef HAVE_TCL_EXTEND
  if (Tclx_Init(interp) == TCL_ERROR) {
    return TCL_ERROR;
  }
#endif

  if (Tk_Init(interp) == TCL_ERROR) {
      return TCL_ERROR;
  }

  /*
   * Call Tcl_CreateCommand for application-specific commands, if
   * they weren't already created by the init procedures called above.
   */

  Tcl_CreateObjCommand(interp, "emc_ini", emc_ini, (ClientData) NULL, (Tcl_CmdDeleteProc *) NULL);

  Tcl_CreateObjCommand(interp, "emc_io_connect", emc_io_connect, (ClientData) NULL, (Tcl_CmdDeleteProc *) NULL);

  Tcl_CreateObjCommand(interp, "emc_io_disconnect", emc_io_disconnect, (ClientData) NULL, (Tcl_CmdDeleteProc *) NULL);

  Tcl_CreateObjCommand(interp, "emc_io_read_command", emc_io_read_command, (ClientData) NULL, (Tcl_CmdDeleteProc *) NULL);

  Tcl_CreateObjCommand(interp, "emc_io_get_command", emc_io_get_command, (ClientData) NULL, (Tcl_CmdDeleteProc *) NULL);

  Tcl_CreateObjCommand(interp, "emc_io_get_command_type", emc_io_get_command_type, (ClientData) NULL, (Tcl_CmdDeleteProc *) NULL);

  Tcl_CreateObjCommand(interp, "emc_io_get_serial_number", emc_io_get_serial_number, (ClientData) NULL, (Tcl_CmdDeleteProc *) NULL);

  Tcl_CreateObjCommand(interp, "emc_io_write_status", emc_io_write_status, (ClientData) NULL, (Tcl_CmdDeleteProc *) NULL);

  Tcl_CreateObjCommand(interp, "emc_io_write_error", emc_io_write_error, (ClientData) NULL, (Tcl_CmdDeleteProc *) NULL);

  Tcl_CreateObjCommand(interp, "emc_io_status_heartbeat", emc_io_status_heartbeat, (ClientData) NULL, (Tcl_CmdDeleteProc *) NULL);

  Tcl_CreateObjCommand(interp, "emc_io_status_command_type", emc_io_status_command_type, (ClientData) NULL, (Tcl_CmdDeleteProc *) NULL);

  Tcl_CreateObjCommand(interp, "emc_io_status_echo_serial_number", emc_io_status_echo_serial_number, (ClientData) NULL, (Tcl_CmdDeleteProc *) NULL);

  Tcl_CreateObjCommand(interp, "emc_io_status_status", emc_io_status_status, (ClientData) NULL, (Tcl_CmdDeleteProc *) NULL);

  Tcl_CreateObjCommand(interp, "emc_io_status_estop", emc_io_status_estop, (ClientData) NULL, (Tcl_CmdDeleteProc *) NULL);

  Tcl_CreateObjCommand(interp, "emc_io_status_mist", emc_io_status_mist, (ClientData) NULL, (Tcl_CmdDeleteProc *) NULL);

  Tcl_CreateObjCommand(interp, "emc_io_status_flood", emc_io_status_flood, (ClientData) NULL, (Tcl_CmdDeleteProc *) NULL);

  Tcl_CreateObjCommand(interp, "emc_io_status_lube", emc_io_status_lube, (ClientData) NULL, (Tcl_CmdDeleteProc *) NULL);

  Tcl_CreateObjCommand(interp, "emc_io_status_lube_level", emc_io_status_lube_level, (ClientData) NULL, (Tcl_CmdDeleteProc *) NULL);

  Tcl_CreateObjCommand(interp, "emc_io_status_spindle_speed", emc_io_status_spindle_speed, (ClientData) NULL, (Tcl_CmdDeleteProc *) NULL);

  Tcl_CreateObjCommand(interp, "emc_io_status_spindle_enabled", emc_io_status_spindle_enabled, (ClientData) NULL, (Tcl_CmdDeleteProc *) NULL);

  Tcl_CreateObjCommand(interp, "emc_io_status_spindle_direction", emc_io_status_spindle_direction, (ClientData) NULL, (Tcl_CmdDeleteProc *) NULL);

  Tcl_CreateObjCommand(interp, "emc_io_status_spindle_increasing", emc_io_status_spindle_increasing, (ClientData) NULL, (Tcl_CmdDeleteProc *) NULL);

  Tcl_CreateObjCommand(interp, "emc_io_status_spindle_brake", emc_io_status_spindle_brake, (ClientData) NULL, (Tcl_CmdDeleteProc *) NULL);

  Tcl_CreateObjCommand(interp, "emc_io_status_tool_prepped", emc_io_status_tool_prepped, (ClientData) NULL, (Tcl_CmdDeleteProc *) NULL);

  Tcl_CreateObjCommand(interp, "emc_io_status_tool_in_spindle", emc_io_status_tool_in_spindle, (ClientData) NULL, (Tcl_CmdDeleteProc *) NULL);

  Tcl_CreateObjCommand(interp, "inb", f_inb, (ClientData) NULL, (Tcl_CmdDeleteProc *) NULL);

  Tcl_CreateObjCommand(interp, "outb", f_outb, (ClientData) NULL, (Tcl_CmdDeleteProc *) NULL);

  Tcl_CreateObjCommand(interp, "inw", f_inw, (ClientData) NULL, (Tcl_CmdDeleteProc *) NULL);

  Tcl_CreateObjCommand(interp, "outw", f_outw, (ClientData) NULL, (Tcl_CmdDeleteProc *) NULL);

  Tcl_CreateObjCommand(interp, "inl", f_inl, (ClientData) NULL, (Tcl_CmdDeleteProc *) NULL);

  Tcl_CreateObjCommand(interp, "outl", f_outl, (ClientData) NULL, (Tcl_CmdDeleteProc *) NULL);

  Tcl_CreateObjCommand(interp, "emc_mot_shmem", emc_mot_shmem, (ClientData) NULL, (Tcl_CmdDeleteProc *) NULL);

  Tcl_CreateObjCommand(interp, "emc_mot_rawinput", emc_mot_rawinput, (ClientData) NULL, (Tcl_CmdDeleteProc *) NULL);

  Tcl_CreateObjCommand(interp, "emc_mot_move", emc_mot_move, (ClientData) NULL, (Tcl_CmdDeleteProc *) NULL);

  /*
   * Specify a user-specific startup file to invoke if the application
   * is run interactively.  Typically the startup file is "~/.apprc"
   * where "app" is the name of the application.  If this line is deleted
   * then no user-specific startup file will be run under any conditions.
   */

  Tcl_SetVar(interp, "tcl_rcFileName", "~/.tclmainrc", TCL_GLOBAL_ONLY);

  // set app-specific global variables
  Tcl_SetVar(interp, "EMC_INIFILE", EMC_INIFILE, TCL_GLOBAL_ONLY);

  return TCL_OK;
}

static void thisQuit(ClientData clientData)
{
  // clean up NML channels

  if (emcErrorBuffer != 0) {
    delete emcErrorBuffer;
    emcErrorBuffer = 0;
  }

  if (emcioStatusBuffer != 0) {
    delete emcioStatusBuffer;
    emcioStatusBuffer = 0;
  }

  if (emcioCommandBuffer != 0) {
    delete emcioCommandBuffer;
    emcioCommandBuffer = 0;
    emcioCommand = 0;
  }

  // turn off port access
  cpp_iopl(0);
  // Clean up shared memory
  usrmotExit();
  Tcl_Exit(0);
  exit(0);
}

/*
  iniLoad() loads basic parameters from the ini file that are needed
  to define functions here:

  [EMC] DEBUG
  [EMC] VERSION
  [EMC] MACHINE
  [EMC] NML_FILE

  The rest of the ini file parameters for the IO subsystems, e.g.,

  [EMCIO] CYCLE_TIME
  [EMCIO] or [EMC] IO_BASE_ADDRESS
  [EMCIO] TOOL_TABLE
  [EMCIO] SPINDLE_OFF_WAIT
  [EMCIO] ESTOP_SENSE_INDEX

  etc. are read in by the Tcl/Tk script via emc_ini and used in the script.
*/

static  int iniLoad(const char *filename)
{
  INIFILE inifile;
  const char *inistring;
  char version[INIFILE_MAX_LINELEN];

  // open it
  if (-1 == inifile.open(filename)) {
    return -1;
  }

  if (NULL != (inistring = inifile.find("DEBUG", "EMC"))) {
    // copy to global
    if (1 != sscanf(inistring, "%i", &EMC_DEBUG)) {
      EMC_DEBUG = 0;
    }
  }
  else {
    // not found, use default
    EMC_DEBUG = 0;
  }

  if (EMC_DEBUG & EMC_DEBUG_VERSIONS) {
    if (NULL != (inistring = inifile.find("VERSION", "EMC"))) {
      // print version
      sscanf(inistring, "$Revision: %s", version);
      rcs_print("Version:  %s\n", version);
    }
    else {
      // not found, not fatal
      rcs_print("Version:  (not found)\n");
    }

    if (NULL != (inistring = inifile.find("MACHINE", "EMC"))) {
      // print machine
      rcs_print("Machine:  %s\n", inistring);
    }
    else {
      // not found, not fatal
      rcs_print("Machine:  (not found)\n");
    }
  }

  if (NULL != (inistring = inifile.find("NML_FILE", "EMC"))) {
    // copy to global
    strcpy(EMC_NMLFILE, inistring);
  }
  else {
    // not found, use default
  }

  // close it
  inifile.close();

  return 0;
}

static void sigQuit(int sig)
{
  thisQuit((ClientData) 0);
}


int main(int argc, char *argv[])
{
char tmp;
  // blank out the annoying RCS version message
  rcs_version_printed = 1;

  // process command line args
  if (0 != emcGetArgs(argc, argv)) {
    rcs_print_error("error in argument list\n");
    exit(1);
  }

  // get configuration information
  iniLoad(EMC_INIFILE);

  // Enable shared memory comms.
  usrmotIniLoad(EMC_INIFILE);
  if (-1 != (shmem = usrmotInit())) {
    shmem = (long) emcmotshmem;
  }
  
  // turn on port access
  unpriv = 0;
  if (0 != cpp_iopl(3)) {
    fprintf(stderr, "not privileged to access IO-- disabling IO\n");
    unpriv = 1;
  }

  // attach our quit function to exit
  Tcl_CreateExitHandler(thisQuit, (ClientData) 0);

  // attach our quit function to SIGINT
  signal(SIGINT, sigQuit);

  // run Tk main loop
  Tk_Main(argc, argv, Tcl_AppInit);
/* Tk_Main bombs straight out, so anything after this does NOT get executed.
   So any cleanup operations need to be done in thisQuit(). */

  exit(0);
}
это довольно старый исходник ,который даже в 2.4 уже не включали
потом на смену "пришла " emcsh.cc , которая есть в сборках , но пользователю рекомендуется уже linuxcncrsh
-------------
в Makefile тоже указан несуществующий файл emc/usr_intf/iosh.cc:
(для просмотра содержимого нажмите на ссылку)

Код: Выделить всё

EMCSHSRCS := emc/usr_intf/emcsh.cc \
             emc/usr_intf/shcom.cc
EMCRSHSRCS := emc/usr_intf/emcrsh.cc \
              emc/usr_intf/shcom.cc
EMCSCHEDSRCS := emc/usr_intf/schedrmt.cc \
              emc/usr_intf/emcsched.cc \
              emc/usr_intf/shcom.cc
EMCLCDSRCS := emc/usr_intf/emclcd.cc \
              emc/usr_intf/shcom.cc \
              emc/usr_intf/sockets.c

HALUISRCS := emc/usr_intf/halui.cc
ifeq "$(HAVE_NCURSES)" "yes"
KEYSTICKSRCS := emc/usr_intf/keystick.cc
endif
ifeq "$(HAVE_XAW)" "yes"
XEMCSRCS := emc/usr_intf/xemc.cc
endif

TCLSRCS := emc/usr_intf/emcsh.cc emc/usr_intf/iosh.cc
USERSRCS += $(EMCSHSRCS) $(EMCRSHSRCS) $(EMCSCHEDSRCS) $(EMCLCDSRCS) $(USRMOTSRCS) $(HALUISRCS) $(KEYSTICKSRCS)

ifeq "$(HAVE_NCURSES)" "yes"
USERSRCS += $(KEYSTICKSRCS)
endif

ifeq "$(HAVE_XAW)" "yes"
USERSRCS += $(XEMCSRCS)
endif

$(call TOOBJSDEPS, $(TCLSRCS)) : EXTRAFLAGS = $(ULFLAGS) $(TCL_CFLAGS)
$(call TOOBJSDEPS, $(EMCSHSRCS)) : EXTRAFLAGS = $(ULFLAGS) $(TCL_CFLAGS) -fPIC

../bin/tooledit: emc/usr_intf/tooledit.tcl
	cp $< $@
	chmod +x $@
TARGETS += ../bin/tooledit

../tcl/linuxcnc.so: $(call TOOBJS, $(EMCSHSRCS)) ../lib/liblinuxcnc.a ../lib/liblinuxcncini.so.0 ../lib/libnml.so.0
	$(ECHO) Linking $(notdir $@)
	$(Q)$(CXX) -shared $(LDFLAGS) -o $@ $(ULFLAGS) $(TCL_CFLAGS) $^ $(TCL_LIBS) -lXinerama
TARGETS += ../tcl/linuxcnc.so

../bin/linuxcncrsh: $(call TOOBJS, $(EMCRSHSRCS)) ../lib/liblinuxcnc.a ../lib/libnml.so.0 ../lib/liblinuxcncini.so.0
	$(ECHO) Linking $(notdir $@)
	$(Q)$(CXX) $(LDFLAGS) -o $@ $(ULFLAGS) $^ -lpthread
TARGETS += ../bin/linuxcncrsh

../bin/schedrmt: $(call TOOBJS, $(EMCSCHEDSRCS)) ../lib/liblinuxcnc.a ../lib/libnml.so.0 ../lib/liblinuxcncini.so.0
	$(ECHO) Linking $(notdir $@)
	$(Q)$(CXX) $(LDFLAGS) -o $@ $(ULFLAGS) $^ -lpthread
TARGETS += ../bin/schedrmt

../bin/linuxcnclcd: $(call TOOBJS, $(EMCLCDSRCS)) ../lib/liblinuxcnc.a ../lib/libnml.so.0 ../lib/liblinuxcncini.so.0
	$(ECHO) Linking $(notdir $@)
	$(Q)$(CXX) $(LDFLAGS) -o $@ $(ULFLAGS) $^
TARGETS += ../bin/linuxcnclcd

../bin/halui: $(call TOOBJS, $(HALUISRCS)) ../lib/liblinuxcnc.a ../lib/liblinuxcncini.so.0 ../lib/libnml.so.0 ../lib/liblinuxcnchal.so.0
	$(ECHO) Linking $(notdir $@)
	$(Q)$(CXX) $(LDFLAGS) -o $@ $(ULFLAGS) $^ 
TARGETS += ../bin/halui

ifeq "$(HAVE_NCURSES)" "yes"
../bin/keystick: $(call TOOBJS, $(KEYSTICKSRCS)) ../lib/liblinuxcnc.a ../lib/libnml.so.0 ../lib/liblinuxcncini.so.0
	$(ECHO) Linking $(notdir $@)
	$(Q)$(CXX) $(LDFLAGS) -o $@ $(ULFLAGS) $^ $(KEYSTICKLIBS)
TARGETS += ../bin/keystick
endif

ifeq "$(HAVE_XAW)" "yes"
$(call TOOBJSDEPS,$(XEMCSRCS)): EXTRAFLAGS = $(CFLAGS_X)
../bin/xlinuxcnc: $(call TOOBJS, $(XEMCSRCS)) ../lib/liblinuxcnc.a ../lib/libnml.so.0 ../lib/liblinuxcncini.so.0
	$(ECHO) Linking $(notdir $@)
	$(Q)$(CXX) $(LDFLAGS) -o $@ $(ULFLAGS) $^ $(XLIBS)
TARGETS += ../bin/xlinuxcnc
endif
=========
ps
может я что то и не доглядел...

Re: Сбор багов LinuxCNC ( багтрекер bug bugtracker баг )

Добавлено: 07 апр 2014, 23:43
Serg
nkp писал(а):в Makefile тоже указан несуществующий файл emc/usr_intf/iosh.cc:
Ни одна цель в Makefile от него не зависит.

Re: Сбор багов LinuxCNC ( багтрекер bug bugtracker баг )

Добавлено: 07 апр 2014, 23:51
nkp
UAVpilot писал(а):Ни одна цель в Makefile от него не зависит.
я еще не знаю синтаксис make - но предполагал , что все это на работу не сказывается...
вышесказаное больше относится к вопросу "чистоты кода" - такие вещи в исходниках встречал и раньше,
не отмечал просто ...

Re: Сбор багов LinuxCNC ( багтрекер bug bugtracker баг )

Добавлено: 08 апр 2014, 15:17
Serg
nkp писал(а):к вопросу "чистоты кода"
Ну это довольно филосовский вопрос. Например С-ный код со вставками типа

Код: Выделить всё

#if 0
   blah-blah-blah
#endif
можно считать чистым?.. :)

Re: Сбор багов LinuxCNC ( багтрекер bug bugtracker баг )

Добавлено: 08 апр 2014, 19:09
nkp
UAVpilot писал(а):можно считать чистым?.
я конечно не программист ,и всех шуточек программерских не знаю(а если точнее - то вообще не знаю)...
приведенный код мне кажеться смысловой нагрузки не несет , если только где то нет
примерно такой строки:
#define 0 1
ну или чего то подобного...
=============
а в "моем" случае я имел в виду полностью устаревший код , не применяемый вовсе в нынешних сборках...

Re: Сбор багов LinuxCNC ( багтрекер bug bugtracker баг )

Добавлено: 08 апр 2014, 21:31
Serg
Это просто безопасный способ выключения участка кода. Бывает полезно когда неработающий код нужно оставить в файле, например в качестве коментария, если это помогает понять код.
Часто используется, чтобы акцентировать внимание, что раньше код был вот таким, а теперь стал таким и что "изобретать велосипед" не стоит. Ну или для любящих ковыряться в иходниках как пометка типа "можно сделать и вот таким способом, но не рекомендуется". :)

Re: Сбор багов LinuxCNC ( багтрекер bug bugtracker баг )

Добавлено: 20 май 2014, 03:20
torvn77
Наткнулся на следующее.
Делаю тестовую суброутину:

Код: Выделить всё

O<measurent_tool> sub
	(MSG, Measurent tool start)
	t1m6
	(MSG, Measurent tool start)
O<measurent_tool> endsub
M30
Кладу в папачку и обращаюсь к ней через консоль MDI командой "O<measurent_tool> call",
выскакивает ошибка "File not open"
Делаю УП вызывающею тестовую суброутину,

Код: Выделить всё

O<measurent_tool> call
M30
Запускаю её,вызов суброутины проходит нормально.
Возвращаюсь в консоль MDI,поднимаю из истории команду и повторяю вызов.
Теперь вызов суброутины и в консоли проходит нормально так же.
ИМХО это баг.
Конфиг ini
Purelogic_PLC4x-G2_Test_Subroutines.ini
(2.47 КБ) 952 скачивания
,остальные файлы я не изменял.
stepconf :
Purelogic_PLC4x-G2_Test_Subroutines.stepconf.gz
(1.23 КБ) 943 скачивания