diff --git a/configs/common/client.nml b/configs/common/client.nml index 5ae5ed4795d..50610c952d6 100644 --- a/configs/common/client.nml +++ b/configs/common/client.nml @@ -22,5 +22,3 @@ B emcError SHMEM 192.168.0.4 8192 0 0 3 P xemc emcCommand REMOTE 192.168.0.4 W 0 10.0 0 10 P xemc emcStatus REMOTE 192.168.0.4 R 0 10.0 0 10 P xemc emcError REMOTE 192.168.0.4 R 0 10.0 0 10 -P xemc toolCmd REMOTE 192.168.0.4 W 0 10.0 0 10 -P xemc toolSts REMOTE 192.168.0.4 R 0 10.0 0 10 diff --git a/configs/common/linuxcnc.nml b/configs/common/linuxcnc.nml index b6b61dd0bad..f8d7b994ca0 100644 --- a/configs/common/linuxcnc.nml +++ b/configs/common/linuxcnc.nml @@ -10,29 +10,18 @@ B emcCommand SHMEM localhost 8192 0 0 1 B emcError SHMEM localhost 8192 0 0 3 16 1003 TCP=5005 xdr queue B emcStatus SHMEM localhost 20480 0 0 2 16 1002 TCP=5005 xdr -# These are for the IO controller, EMCIO -B toolCmd SHMEM localhost 1024 0 0 4 16 1004 TCP=5005 xdr -B toolSts SHMEM localhost 1024 0 0 5 16 1005 TCP=5005 xdr - # Processes # Name Buffer Type Host Ops server? timeout master? cnum P emc emcCommand LOCAL localhost RW 0 1.0 0 0 P emc emcStatus LOCAL localhost W 0 1.0 0 0 P emc emcError LOCAL localhost W 0 1.0 0 0 -P emc toolCmd LOCAL localhost W 0 1.0 0 0 -P emc toolSts LOCAL localhost R 0 1.0 0 0 P emcsvr emcCommand LOCAL localhost W 1 1.0 1 2 P emcsvr emcStatus LOCAL localhost R 1 1.0 1 2 P emcsvr emcError LOCAL localhost R 1 1.0 1 2 -P emcsvr toolCmd LOCAL localhost W 1 1.0 1 2 -P emcsvr toolSts LOCAL localhost R 1 1.0 1 2 P emcsvr default LOCAL localhost RW 1 1.0 1 2 -P tool emcError LOCAL localhost W 0 1.0 0 3 -P tool toolCmd LOCAL localhost R 0 1.0 0 3 -P tool toolSts LOCAL localhost W 0 1.0 0 3 P xemc emcCommand LOCAL localhost W 0 10.0 0 10 P xemc emcStatus LOCAL localhost R 0 10.0 0 10 diff --git a/configs/common/linuxcnc_big.nml b/configs/common/linuxcnc_big.nml index f5c72518054..febd64e7553 100644 --- a/configs/common/linuxcnc_big.nml +++ b/configs/common/linuxcnc_big.nml @@ -10,29 +10,18 @@ B emcCommand SHMEM localhost 8192 0 0 1 B emcError SHMEM localhost 8192 0 0 3 16 1003 TCP=5005 xdr queue B emcStatus SHMEM localhost 170000 0 0 2 16 1002 TCP=5005 xdr -# These are for the IO controller, EMCIO -B toolCmd SHMEM localhost 2048 0 0 4 16 1004 TCP=5005 xdr -B toolSts SHMEM localhost 155648 0 0 5 16 1005 TCP=5005 xdr - # Processes # Name Buffer Type Host Ops server? timeout master? cnum P emc emcCommand LOCAL localhost RW 0 1.0 0 0 P emc emcStatus LOCAL localhost W 0 1.0 0 0 P emc emcError LOCAL localhost W 0 1.0 0 0 -P emc toolCmd LOCAL localhost W 0 1.0 0 0 -P emc toolSts LOCAL localhost R 0 1.0 0 0 P emcsvr emcCommand LOCAL localhost W 1 1.0 1 2 P emcsvr emcStatus LOCAL localhost R 1 1.0 1 2 P emcsvr emcError LOCAL localhost R 1 1.0 1 2 -P emcsvr toolCmd LOCAL localhost W 1 1.0 1 2 -P emcsvr toolSts LOCAL localhost R 1 1.0 1 2 P emcsvr default LOCAL localhost RW 1 1.0 1 2 -P tool emcError LOCAL localhost W 0 1.0 0 3 -P tool toolCmd LOCAL localhost R 0 1.0 0 3 -P tool toolSts LOCAL localhost W 0 1.0 0 3 P xemc emcCommand LOCAL localhost W 0 10.0 0 10 P xemc emcStatus LOCAL localhost R 0 10.0 0 10 diff --git a/configs/common/server.nml b/configs/common/server.nml index 7fdbbae6c90..7a4c0e00cf4 100644 --- a/configs/common/server.nml +++ b/configs/common/server.nml @@ -13,34 +13,19 @@ B emcCommand SHMEM localhost 8192 0 0 1 B emcStatus SHMEM localhost 10240 0 0 2 16 1002 TCP=5005 xdr B emcError SHMEM localhost 8192 0 0 3 16 1003 TCP=5005 xdr queue -# These are for the IO controller, EMCIO -B toolCmd SHMEM localhost 1024 0 0 4 16 1004 TCP=5005 xdr -B toolSts SHMEM localhost 4096 0 0 5 16 1005 TCP=5005 xdr -B spindleCmd SHMEM localhost 1024 0 0 6 16 1006 TCP=5005 xdr -B spindleSts SHMEM localhost 1024 0 0 7 16 1007 TCP=5005 xdr - # Processes # Name Buffer Type Host Ops server? timeout master? cnum P emc emcCommand LOCAL localhost RW 0 1.0 0 0 P emc emcStatus LOCAL localhost W 0 1.0 0 0 P emc emcError LOCAL localhost W 0 1.0 0 0 -P emc toolCmd LOCAL localhost W 0 1.0 0 0 -P emc toolSts LOCAL localhost R 0 1.0 0 0 P emcsvr emcCommand LOCAL localhost W 1 1.0 1 2 P emcsvr emcStatus LOCAL localhost R 1 1.0 1 2 P emcsvr emcError LOCAL localhost R 1 1.0 1 2 -P emcsvr toolCmd LOCAL localhost W 1 1.0 1 2 -P emcsvr toolSts LOCAL localhost R 1 1.0 1 2 P emcsvr default LOCAL localhost RW 1 1.0 1 2 -P tool emcError LOCAL localhost W 0 1.0 0 3 -P tool toolCmd LOCAL localhost RW 0 1.0 0 3 -P tool toolSts LOCAL localhost W 0 1.0 0 3 P xemc emcCommand REMOTE 192.168.0.14 W 0 10.0 0 10 P xemc emcStatus REMOTE 192.168.0.14 R 0 10.0 0 10 P xemc emcError REMOTE 192.168.0.14 R 0 10.0 0 10 -P xemc toolCmd REMOTE 192.168.0.14 W 0 10.0 0 10 -P xemc toolSts REMOTE 192.168.0.14 R 0 10.0 0 10 diff --git a/debian/linuxcnc.install.in b/debian/linuxcnc.install.in index efb7543e4de..9c97d10f46c 100644 --- a/debian/linuxcnc.install.in +++ b/debian/linuxcnc.install.in @@ -34,8 +34,6 @@ usr/bin/hy_gt_vfd usr/bin/hy_vfd usr/bin/image-to-gcode usr/bin/inivar -usr/bin/io -usr/bin/iov2 usr/bin/latency-histogram usr/bin/latency-plot usr/bin/latency-test diff --git a/scripts/linuxcnc.in b/scripts/linuxcnc.in index 75abe58b789..b0f3f4d24f7 100644 --- a/scripts/linuxcnc.in +++ b/scripts/linuxcnc.in @@ -541,11 +541,6 @@ if [ -z "$HOMEMOD" ] ; then HOMEMOD=${retval:-homemod} #use default if not found fi - -# 2.4. get io information -GetFromIniEx IO IO EMCIO EMCIO io -EMCIO=$retval - # 2.5. get task information GetFromIni TASK TASK EMCTASK=$retval @@ -830,19 +825,16 @@ fi # "halcmd loadrt" can find them export HAL_RTMOD_DIR=$LINUXCNC_RTLIB_DIR -# 4.3.4. Run io in background if so defined in INI -if [ "$EMCIO" != "" ] ; then - echo "Starting LinuxCNC IO program: $EMCIO" >>$PRINT_FILE - if ! program_available $EMCIO ; then - echo "Can't execute IO program $EMCIO" - Cleanup - exit 1 - fi - $HALCMD loadusr -Wn iocontrol $EMCIO -ini "$INIFILE" -else - echo "Skipping LinuxCNC IO program >>$PRINT_FILE" +# 4.3.7. Run task in background +echo "Starting TASK program: $EMCTASK" >>$PRINT_FILE +if ! program_available $EMCTASK ; then + echo "Can't execute TASK program $EMCTASK" + Cleanup + exit 1 fi +halcmd loadusr -Wn iocontrol $EMCTASK -ini "$INIFILE" + # 4.3.5. Run halui in background, if necessary if [ -n "$HALUI" ] ; then echo "Starting HAL User Interface program: $HALUI" >>$PRINT_FILE @@ -936,17 +928,6 @@ else done fi - -# 4.3.7. Run task in background -echo "Starting TASK program: $EMCTASK" >>$PRINT_FILE -if ! program_available $EMCTASK ; then - echo "Can't execute TASK program $EMCTASK" - Cleanup - exit 1 -fi - -halcmd loadusr -Wn inihal $EMCTASK -ini "$INIFILE" & - # 4.3.8. execute discrete HAL commands from INI file (if any) # get first command from INI file NUM=1 diff --git a/src/Makefile b/src/Makefile index b0cee9bb447..f8c941dc735 100644 --- a/src/Makefile +++ b/src/Makefile @@ -181,7 +181,7 @@ SUBDIRS := \ emc/usr_intf/axis emc/usr_intf/touchy emc/usr_intf/stepconf emc/usr_intf/pncconf \ emc/usr_intf/gremlin emc/usr_intf/gscreen emc/usr_intf/pyui emc/usr_intf/qtvcp \ emc/usr_intf/gmoccapy emc/usr_intf/qtplasmac emc/usr_intf/mdro\ - emc/usr_intf emc/nml_intf emc/task emc/iotask emc/kinematics emc/tp emc/canterp \ + emc/usr_intf emc/nml_intf emc/task emc/kinematics emc/tp emc/canterp \ emc/motion emc/ini emc/rs274ngc emc/sai emc/pythonplugin \ emc/motion-logger \ emc/tooldata \ diff --git a/src/emc/iotask/Submakefile b/src/emc/iotask/Submakefile deleted file mode 100644 index 632dc4e51c5..00000000000 --- a/src/emc/iotask/Submakefile +++ /dev/null @@ -1,15 +0,0 @@ -IOSRCS := emc/iotask/ioControl.cc -IOV2SRCS := emc/iotask/ioControl_v2.cc -USERSRCS += $(IOSRCS) $(IOV2SRCS) - -../bin/io: $(call TOOBJS, $(IOSRCS)) ../lib/liblinuxcnc.a ../lib/libnml.so.0 \ - ../lib/liblinuxcnchal.so.0 ../lib/liblinuxcncini.so.0 ../lib/libtooldata.so.0 - $(ECHO) Linking $(notdir $@) - @$(CXX) -o $@ $^ $(LDFLAGS) - -../bin/iov2: $(call TOOBJS, $(IOV2SRCS)) ../lib/liblinuxcnc.a ../lib/libnml.so.0 \ - ../lib/liblinuxcnchal.so.0 ../lib/liblinuxcncini.so.0 ../lib/libtooldata.so.0 - $(ECHO) Linking $(notdir $@) - @$(CXX) -o $@ $^ $(LDFLAGS) - -TARGETS += ../bin/io ../bin/iov2 diff --git a/src/emc/iotask/ioControl.cc b/src/emc/iotask/ioControl.cc deleted file mode 100644 index 42962d3f2c1..00000000000 --- a/src/emc/iotask/ioControl.cc +++ /dev/null @@ -1,1091 +0,0 @@ -/******************************************************************** -* Description: IoControl.cc -* Simply accepts NML messages sent to the IO controller -* outputs those to a HAL pin, -* and sends back a "Done" message. -* -* -* ENABLE logic: this module exports three HAL pins related to ENABLE. -* The first is emc-enable-in. It is an input from the HAL, when FALSE, -* EMC will go into the STOPPED state (regardless of the state of -* the other two pins). When it goes TRUE, EMC will go into the -* ESTOP_RESET state (also known as READY). -* -* The second HAL pin is an output to the HAL. It is controlled by -* the NML messages ESTOP_ON and ESTOP_OFF, which normally result from -* user actions at the GUI. For the simplest system, loop user-enable-out -* back to emc-enable-in in the HAL. The GUI controls user-enable-out, and EMC -* responds to that once it is looped back. -* -* If external ESTOP inputs are desired, they can be -* used in a classicladder rung, in series with user-enable-out. -* It will look like this: -* -* -----|UEO|-----|EEST|--+--|EEI|--+--(EEI)---- -* | | -* +--|URE|--+ -* UEO=user-enable-out -* EEST=external ESTOP circuitry -* EEI=machine is enabled -* URE=user request enable -* -* This will work like this: EMC will be enabled (by EEI, emc-enabled-in), -* only if UEO, EEST are closed when URE gets strobed. -* If any of UEO (user requested stop) or EEST (external estop) have been -* opened, then EEI will open as well. -* After restoring normal condition (UEO and EEST closed), an additional -* URE (user-request-enable) is needed, this is either sent by the GUI -* (using the EMC_AUX_ESTOP_RESET NML message), or by a hardware button -* connected to the ladder driving URE. -* -* NML messages are sent usually from the user hitting F1 on the GUI. -* -* Derived from a work by Fred Proctor & Will Shackleford -* -* Author: -* License: GPL Version 2 -* System: Linux -* -* Copyright (c) 2004 All rights reserved. -* -* Last change: -********************************************************************/ - -#include -#include -#include -#include -#include -#include -#include -#include "hal.h" /* access to HAL functions/definitions */ -#include "rtapi.h" /* rtapi_print_msg */ -#include "rcs.hh" /* RCS_CMD_CHANNEL */ -#include "emc.hh" /* EMC NML */ -#include "emc_nml.hh" -#include "emcglb.h" /* EMC_NMLFILE, EMC_INIFILE, TOOL_TABLE_FILE */ -#include "inifile.hh" /* INIFILE */ -#include "nml_oi.hh" -#include "timer.hh" -#include "rcs_print.hh" -#include -#include "tooldata.hh" - -static bool io_debug = 0; -#define UNEXPECTED_MSG fprintf(stderr,"UNEXPECTED %s %d\n",__FILE__,__LINE__); - -static RCS_CMD_CHANNEL *emcioCommandBuffer = 0; -static RCS_CMD_MSG *emcioCommand = 0; -static RCS_STAT_CHANNEL *emcioStatusBuffer = 0; -static EMC_IO_STAT emcioStatus; -static NML *emcErrorBuffer = 0; - -static char io_tool_table_file[LINELEN] = "tool.tbl"; // default - -static int random_toolchanger = 0; -static tooldb_t io_db_mode = DB_NOTUSED; -static char db_program[LINELEN] = {0}; - -struct iocontrol_str { - hal_bit_t *user_enable_out; /* output, TRUE when EMC wants stop */ - hal_bit_t *emc_enable_in; /* input, TRUE on any external stop */ - hal_bit_t *user_request_enable; /* output, used to reset ENABLE latch */ - hal_bit_t *coolant_mist; /* coolant mist output pin */ - hal_bit_t *coolant_flood; /* coolant flood output pin */ - - - // the following pins are needed for toolchanging - //tool-prepare - hal_bit_t *tool_prepare; /* output, pin that notifies HAL it needs to prepare a tool */ - hal_s32_t *tool_prep_pocket;/* output, pin that holds the pocketno for the tool table entry matching the tool to be prepared, - only valid when tool-prepare=TRUE */ - hal_s32_t *tool_from_pocket;/* output, pin indicating pocket current load tool retrieved from*/ - hal_s32_t *tool_prep_index; /* output, pin for internal index (idx) of prepped tool above */ - hal_s32_t *tool_prep_number;/* output, pin that holds the tool number to be prepared, only valid when tool-prepare=TRUE */ - hal_s32_t *tool_number; /* output, pin that holds the tool number currently in the spindle */ - hal_bit_t *tool_prepared; /* input, pin that notifies that the tool has been prepared */ - //tool-change - hal_bit_t *tool_change; /* output, notifies a tool-change should happen (emc should be in the tool-change position) */ - hal_bit_t *tool_changed; /* input, notifies tool has been changed */ - - // note: spindle control has been moved to motion -} * iocontrol_data; //pointer to the HAL-struct - -//static iocontrol_struct *iocontrol_data; -static int comp_id; /* component ID */ - -/******************************************************************** -* -* Description: emcIoNmlGet() -* Attempts to connect to NML buffers and set the relevant -* pointers. -* -* Return Value: Zero on success or -1 if can not connect to a buffer. -* -* Side Effects: None. -* -* Called By: main() -* -********************************************************************/ -static int emcIoNmlGet() -{ - int retval = 0; - - /* Try to connect to EMC IO command buffer */ - if (emcioCommandBuffer == 0) { - emcioCommandBuffer = - new RCS_CMD_CHANNEL(emcFormat, "toolCmd", "tool", emc_nmlfile); - if (!emcioCommandBuffer->valid()) { - rtapi_print_msg(RTAPI_MSG_ERR, - "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 buffer */ - if (emcioStatusBuffer == 0) { - emcioStatusBuffer = - new RCS_STAT_CHANNEL(emcFormat, "toolSts", "tool", - emc_nmlfile); - if (!emcioStatusBuffer->valid()) { - rtapi_print_msg(RTAPI_MSG_ERR, - "toolSts buffer not available\n"); - delete emcioStatusBuffer; - emcioStatusBuffer = 0; - retval = -1; - } else { - /* initialize and write status */ - emcioStatus.command_type = 0; - emcioStatus.echo_serial_number = 0; - emcioStatus.status = RCS_STATUS::DONE; - emcioStatusBuffer->write(&emcioStatus); - } - } - - /* try to connect to EMC error buffer */ - if (emcErrorBuffer == 0) { - emcErrorBuffer = - new NML(nmlErrorFormat, "emcError", "tool", emc_nmlfile); - if (!emcErrorBuffer->valid()) { - rtapi_print_msg(RTAPI_MSG_ERR, - "emcError buffer not available\n"); - delete emcErrorBuffer; - emcErrorBuffer = 0; - retval = -1; - } - } - - return retval; -} - -static int iniLoad(const char *filename) -{ - IniFile inifile; - const char *inistring; - bool tooltable_specified = 0; - - /* Open the INI file */ - if (inifile.Open(filename) == false) { - return -1; - } - - if (NULL != (inistring = inifile.Find("TOOL_TABLE", "EMCIO"))) { - strncpy(io_tool_table_file, inistring, sizeof(io_tool_table_file)-1); - tooltable_specified = 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 (NULL != (inistring = inifile.Find("NML_FILE", "EMC"))) { - rtapi_strxcpy(emc_nmlfile, inistring); - } else { - // not found, use default - } - - double temp; - temp = emc_io_cycle_time; - if (NULL != (inistring = inifile.Find("CYCLE_TIME", "EMCIO"))) { - if (1 == sscanf(inistring, "%lf", &emc_io_cycle_time)) { - // found it - } else { - // found, but invalid - emc_io_cycle_time = temp; - rtapi_print - ("invalid [EMCIO] CYCLE_TIME in %s (%s); using default %f\n", - filename, inistring, emc_io_cycle_time); - } - } else { - // not found, using default - rtapi_print - ("[EMCIO] CYCLE_TIME not found in %s; using default %f\n", - filename, emc_io_cycle_time); - } - - inifile.Find(&random_toolchanger, "RANDOM_TOOLCHANGER", "EMCIO"); - - io_db_mode = DB_NOTUSED; - if(NULL != (inistring = inifile.Find("DB_PROGRAM", "EMCIO"))) { - rtapi_strxcpy(db_program,inistring); - io_db_mode = DB_ACTIVE; - if (tooltable_specified) { - fprintf(stderr,"DB_PROGRAM active: IGNORING tool table file %s\n", - io_tool_table_file); - } - } - // close it - inifile.Close(); - - return 0; -} - -static int done = 0; - -/******************************************************************** -* -* Description: quit(int sig) -* Signal handler for SIGINT - Usually generated by a -* Ctrl C sequence from the keyboard. -* -* Return Value: None. -* -* Side Effects: Sets the termination condition of the main while loop. -* -* Called By: Operating system. -* -********************************************************************/ -static void quit(int sig) -{ - done = 1; -} - -/******************************************************************** -* -* Description: iocontrol_hal_init(void) -* -* Side Effects: Exports HAL pins. -* -* Called By: main -********************************************************************/ -static int iocontrol_hal_init(void) -{ - int n = 0, retval; //n - number of the hal component (only one for iocotrol) - - /* STEP 1: initialise the hal component */ - comp_id = hal_init("iocontrol"); - if (comp_id < 0) { - rtapi_print_msg(RTAPI_MSG_ERR, - "IOCONTROL: ERROR: hal_init() failed\n"); - return -1; - } - - /* STEP 2: allocate shared memory for iocontrol data */ - iocontrol_data = (iocontrol_str *) hal_malloc(sizeof(iocontrol_str)); - if (iocontrol_data == 0) { - rtapi_print_msg(RTAPI_MSG_ERR, - "IOCONTROL: ERROR: hal_malloc() failed\n"); - hal_exit(comp_id); - return -1; - } - - /* STEP 3a: export the out-pin(s) */ - - // user-enable-out - retval = hal_pin_bit_newf(HAL_OUT, &(iocontrol_data->user_enable_out), comp_id, - "iocontrol.%d.user-enable-out", n); - if (retval < 0) { - rtapi_print_msg(RTAPI_MSG_ERR, - "IOCONTROL: ERROR: iocontrol %d pin user-enable-out export failed with err=%i\n", - n, retval); - hal_exit(comp_id); - return -1; - } - // user-request-enable - retval = hal_pin_bit_newf(HAL_OUT, &(iocontrol_data->user_request_enable), comp_id, - "iocontrol.%d.user-request-enable", n); - if (retval < 0) { - rtapi_print_msg(RTAPI_MSG_ERR, - "IOCONTROL: ERROR: iocontrol %d pin user-request-enable export failed with err=%i\n", - n, retval); - hal_exit(comp_id); - return -1; - } - // coolant-flood - retval = hal_pin_bit_newf(HAL_OUT, &(iocontrol_data->coolant_flood), comp_id, - "iocontrol.%d.coolant-flood", n); - if (retval < 0) { - rtapi_print_msg(RTAPI_MSG_ERR, - "IOCONTROL: ERROR: iocontrol %d pin coolant-flood export failed with err=%i\n", - n, retval); - hal_exit(comp_id); - return -1; - } - // coolant-mist - retval = hal_pin_bit_newf(HAL_OUT, &(iocontrol_data->coolant_mist), comp_id, - "iocontrol.%d.coolant-mist", n); - if (retval < 0) { - rtapi_print_msg(RTAPI_MSG_ERR, - "IOCONTROL: ERROR: iocontrol %d pin coolant-mist export failed with err=%i\n", - n, retval); - hal_exit(comp_id); - return -1; - } - // tool-prepare - retval = hal_pin_bit_newf(HAL_OUT, &(iocontrol_data->tool_prepare), comp_id, - "iocontrol.%d.tool-prepare", n); - if (retval < 0) { - rtapi_print_msg(RTAPI_MSG_ERR, - "IOCONTROL: ERROR: iocontrol %d pin tool-prepare export failed with err=%i\n", - n, retval); - hal_exit(comp_id); - return -1; - } - // tool-number - retval = hal_pin_s32_newf(HAL_OUT, &(iocontrol_data->tool_number), comp_id, - "iocontrol.%d.tool-number", n); - if (retval < 0) { - rtapi_print_msg(RTAPI_MSG_ERR, - "IOCONTROL: ERROR: iocontrol %d pin tool-number export failed with err=%i\n", - n, retval); - hal_exit(comp_id); - return -1; - } - // tool-prep-number - retval = hal_pin_s32_newf(HAL_OUT, &(iocontrol_data->tool_prep_number), comp_id, - "iocontrol.%d.tool-prep-number", n); - if (retval < 0) { - rtapi_print_msg(RTAPI_MSG_ERR, - "IOCONTROL: ERROR: iocontrol %d pin tool-prep-number export failed with err=%i\n", - n, retval); - hal_exit(comp_id); - return -1; - } - - // tool-prep-index (idx) - retval = hal_pin_s32_newf(HAL_OUT, &(iocontrol_data->tool_prep_index), comp_id, - "iocontrol.%d.tool-prep-index", n); - if (retval < 0) { - rtapi_print_msg(RTAPI_MSG_ERR, - "IOCONTROL: ERROR: iocontrol %d pin tool-prep-index export failed with err=%i\n", - n, retval); - hal_exit(comp_id); - return -1; - } - - // tool-prep-pocket - retval = hal_pin_s32_newf(HAL_OUT, &(iocontrol_data->tool_prep_pocket), comp_id, - "iocontrol.%d.tool-prep-pocket", n); - if (retval < 0) { - rtapi_print_msg(RTAPI_MSG_ERR, - "IOCONTROL: ERROR: iocontrol %d pin tool-prep-pocket export failed with err=%i\n", - n, retval); - hal_exit(comp_id); - return -1; - } - // tool-from-pocket - retval = hal_pin_s32_newf(HAL_OUT, &(iocontrol_data->tool_from_pocket), comp_id, - "iocontrol.%d.tool-from-pocket", n); - if (retval < 0) { - rtapi_print_msg(RTAPI_MSG_ERR, - "IOCONTROL: ERROR: iocontrol %d pin tool-from-pocket export failed with err=%i\n", - n, retval); - hal_exit(comp_id); - return -1; - } - // tool-prepared - retval = hal_pin_bit_newf(HAL_IN, &(iocontrol_data->tool_prepared), comp_id, - "iocontrol.%d.tool-prepared", n); - if (retval < 0) { - rtapi_print_msg(RTAPI_MSG_ERR, - "IOCONTROL: ERROR: iocontrol %d pin tool-prepared export failed with err=%i\n", - n, retval); - hal_exit(comp_id); - return -1; - } - // tool-change - retval = hal_pin_bit_newf(HAL_OUT, &(iocontrol_data->tool_change), comp_id, - "iocontrol.%d.tool-change", n); - if (retval < 0) { - rtapi_print_msg(RTAPI_MSG_ERR, - "IOCONTROL: ERROR: iocontrol %d pin tool-change export failed with err=%i\n", - n, retval); - hal_exit(comp_id); - return -1; - } - // tool-changed - retval = hal_pin_bit_newf(HAL_IN, &(iocontrol_data->tool_changed), comp_id, - "iocontrol.%d.tool-changed", n); - if (retval < 0) { - rtapi_print_msg(RTAPI_MSG_ERR, - "IOCONTROL: ERROR: iocontrol %d pin tool-changed export failed with err=%i\n", - n, retval); - hal_exit(comp_id); - return -1; - } - /* STEP 3b: export the in-pin(s) */ - - // emc-enable-in - retval = hal_pin_bit_newf(HAL_IN, &(iocontrol_data->emc_enable_in), comp_id, - "iocontrol.%d.emc-enable-in", n); - if (retval < 0) { - rtapi_print_msg(RTAPI_MSG_ERR, - "IOCONTROL: ERROR: iocontrol %d pin emc-enable-in export failed with err=%i\n", - n, retval); - hal_exit(comp_id); - return -1; - } - - hal_ready(comp_id); - - return 0; -} - -/******************************************************************** -* -* Description: hal_init_pins(void) -* -* Side Effects: Sets HAL pins default values. -* -* Called By: main -********************************************************************/ -static void hal_init_pins(void) -{ - *(iocontrol_data->user_enable_out)=0; /* output, FALSE when EMC wants stop */ - *(iocontrol_data->user_request_enable)=0;/* output, used to reset HAL latch */ - *(iocontrol_data->coolant_mist)=0; /* coolant mist output pin */ - *(iocontrol_data->coolant_flood)=0; /* coolant flood output pin */ - *(iocontrol_data->tool_prepare)=0; /* output, pin that notifies HAL it needs to prepare a tool */ - *(iocontrol_data->tool_prep_number)=0; /* output, pin that holds the tool number to be prepared, only valid when tool-prepare=TRUE */ - *(iocontrol_data->tool_prep_pocket)=0; /* output, pin that holds the pocketno for the tool to be prepared, only valid when tool-prepare=TRUE */ - *(iocontrol_data->tool_from_pocket)=0; /* output, always 0 at startup */ - *iocontrol_data->tool_prep_index=0; /* output, pin that holds the internal index (idx) of the tool to be prepared, for debug */ - *(iocontrol_data->tool_change)=0; /* output, notifies a tool-change should happen (emc should be in the tool-change position) */ -} - - -/******************************************************************** -* -* Description: read_hal_inputs(void) -* Reads the pin values from HAL -* this function gets called once per cycle -* It sets the values for the emcioStatus.aux.* -* -* Returns: returns > 0 if any of the status has changed -* we then need to update through NML -* -* Side Effects: updates values -* -* Called By: main every CYCLE -********************************************************************/ -static int read_hal_inputs(void) -{ - int oldval, retval = 0; - - oldval = emcioStatus.aux.estop; - - if ( *(iocontrol_data->emc_enable_in)==0) //check for estop from HW - emcioStatus.aux.estop = 1; - else - emcioStatus.aux.estop = 0; - - if (oldval != emcioStatus.aux.estop) { - retval = 1; - } - return retval; -} - -void load_tool(int idx) { - CANON_TOOL_TABLE tdata; - if(random_toolchanger) { - // swap the tools between the desired pocket and the spindle pocket - - CANON_TOOL_TABLE tzero,tpocket; - if ( tooldata_get(&tzero,0 ) != IDX_OK - || tooldata_get(&tpocket,idx) != IDX_OK) { - UNEXPECTED_MSG; return; - } - // spindle-->pocket (specified by idx) - tooldata_db_notify(SPINDLE_UNLOAD,tzero.toolno,idx,tzero); - tzero.pocketno = tpocket.pocketno; - if (tooldata_put(tzero,idx) != IDX_OK) { - UNEXPECTED_MSG; - } - - // pocket-->spindle (idx==0) - tooldata_db_notify(SPINDLE_LOAD,tpocket.toolno,0,tpocket); - tpocket.pocketno = 0; - if (tooldata_put(tpocket,0) != IDX_OK) { - UNEXPECTED_MSG; - } - - if (0 != tooldata_save(io_tool_table_file)) { - emcioStatus.status = RCS_STATUS::ERROR; - } - } else if(idx == 0) { - // on non-random tool-changers, asking for pocket 0 is the secret - // handshake for "unload the tool from the spindle" - tdata = tooldata_entry_init(); - tdata.toolno = 0; // nonrandom unload tool from spindle - tdata.pocketno = 0; // nonrandom unload tool from spindle - if (tooldata_put(tdata,0) != IDX_OK) { - UNEXPECTED_MSG; return; - } - if (tooldata_db_notify(SPINDLE_UNLOAD,0,0,tdata)) { UNEXPECTED_MSG; } - } else { - // just copy the desired tool to the spindle - if (tooldata_get(&tdata,idx) != IDX_OK) { - UNEXPECTED_MSG; return; - } - if (tooldata_put(tdata,0) != IDX_OK) { - UNEXPECTED_MSG; return; - } - // notify idx==0 tool in spindle: - CANON_TOOL_TABLE temp; - if (tooldata_get(&temp,0) != IDX_OK) { UNEXPECTED_MSG; } - if (tooldata_db_notify(SPINDLE_LOAD,temp.toolno,0,temp)) { UNEXPECTED_MSG; } - } -} // load_tool() - -void reload_tool_number(int toolno) { - CANON_TOOL_TABLE tdata; - if(random_toolchanger) return; // doesn't need special handling here - for(int idx = 1; idx <= tooldata_last_index_get(); idx++) { //note <= - if (tooldata_get(&tdata,idx) != IDX_OK) { - UNEXPECTED_MSG; return; - } - if(tdata.toolno == toolno) { - load_tool(idx); - break; - } - } -} - -/******************************************************************** -* -* Description: read_tool_inputs(void) -* Reads the tool-pin values from HAL -* this function gets called once per cycle -* It sets the values for the emcioStatus.aux.* -* -* Returns: returns which of the status has changed -* we then need to update through NML (a bit different as read_hal_inputs) -* -* Side Effects: updates values -* -* Called By: main every CYCLE -********************************************************************/ -static int read_tool_inputs(void) -{ - if (*iocontrol_data->tool_prepare && *iocontrol_data->tool_prepared) { - emcioStatus.tool.pocketPrepped = *iocontrol_data->tool_prep_index; //check if tool has been (idx) prepared - *(iocontrol_data->tool_prepare) = 0; - emcioStatus.status = RCS_STATUS::DONE; // we finally finished to do tool-changing, signal task with RCS_DONE - return 10; //prepped finished - } - - if (*iocontrol_data->tool_change && *iocontrol_data->tool_changed) { - if(!random_toolchanger && emcioStatus.tool.pocketPrepped == 0) { - emcioStatus.tool.toolInSpindle = 0; - emcioStatus.tool.toolFromPocket = *(iocontrol_data->tool_from_pocket) = 0; - } else { - // the tool now in the spindle is the one that was prepared - CANON_TOOL_TABLE tdata; - if (tooldata_get(&tdata,emcioStatus.tool.pocketPrepped) != IDX_OK) { - UNEXPECTED_MSG; return -1; - } - emcioStatus.tool.toolInSpindle = tdata.toolno; - emcioStatus.tool.toolFromPocket = *(iocontrol_data->tool_from_pocket) = tdata.pocketno; - } - if (emcioStatus.tool.toolInSpindle == 0) { - emcioStatus.tool.toolFromPocket = *(iocontrol_data->tool_from_pocket) = 0; - } - *(iocontrol_data->tool_number) = emcioStatus.tool.toolInSpindle; //likewise in HAL - load_tool(emcioStatus.tool.pocketPrepped); - emcioStatus.tool.pocketPrepped = -1; //reset the tool preped number, -1 to permit tool 0 to be loaded - *(iocontrol_data->tool_prep_number) = 0; //likewise in HAL - *(iocontrol_data->tool_prep_pocket) = 0; //likewise in HAL - *(iocontrol_data->tool_prep_index) = 0; //likewise in HAL - *(iocontrol_data->tool_change) = 0; //also reset the tool change signal - emcioStatus.status = RCS_STATUS::DONE; // we finally finished to do tool-changing, signal task with RCS_DONE - return 11; //change finished - } - return 0; -} - -static void do_hal_exit(void) { - hal_exit(comp_id); -} - -/******************************************************************** -* -* Description: main(int argc, char * argv[]) -* Connects to NML buffers and enters an endless loop -* processing NML IO commands. Print statements are -* sent to the console indicating which IO command was -* executed if debug level is set to RTAPI_MSG_DBG. -* -* Return Value: Zero or -1 if INI file not found or failure to connect -* to NML buffers. -* -* Side Effects: None. -* -* Called By: -* -********************************************************************/ -int main(int argc, char *argv[]) -{ -#ifdef TOOL_NML //{ - #define TOOL_DATA "nml" -#else //}{ - #define TOOL_DATA "mmap" -#endif //} - if (getenv( (char*)"IO_DEBUG" )) { getpid(),io_debug = 1; } - if (io_debug) { - fprintf(stderr,"%8d IO: %s\n",getpid(),TOOL_DATA); - fprintf(stderr," EMC_STAT size=%8ld\n",sizeof(EMC_STAT)); - fprintf(stderr," EMC_IO_STAT size=%8ld\n",sizeof(EMC_IO_STAT)); - fprintf(stderr," EMC_TOOL_STAT size=%8ld\n",sizeof(EMC_TOOL_STAT)); - fprintf(stderr," CANON_POCKETS_MAX =%8d\n",CANON_POCKETS_MAX); - } - - int tool_status; - NMLTYPE type; - for (int t = 1; t < argc; t++) { - if (!strcmp(argv[t], "-ini")) { - if (t == argc - 1) { - return -1; - } else { - if (strlen(argv[t+1]) >= LINELEN) { - rtapi_print_msg(RTAPI_MSG_ERR, "INI file name too long (max %d)\n", LINELEN); - rtapi_print_msg(RTAPI_MSG_ERR, " %s\n", argv[t+1]); - return -1; - } - rtapi_strxcpy(emc_inifile, argv[t + 1]); - t++; - } - continue; - } - /* do other args similarly here */ - } - - /* Register the routine that catches the SIGINT signal */ - signal(SIGINT, quit); - /* catch SIGTERM too - the run script uses it to shut things down */ - signal(SIGTERM, quit); - - if (iocontrol_hal_init() != 0) { - rtapi_print_msg(RTAPI_MSG_ERR, "can't initialize the HAL\n"); - return -1; - } - - atexit(do_hal_exit); -#ifdef TOOL_NML //{ -#else //}{ - atexit(tool_mmap_close); -#endif //} - - if (0 != iniLoad(emc_inifile)) { - rtapi_print_msg(RTAPI_MSG_ERR, "can't open INI file %s\n", - emc_inifile); - return -1; - } - - if (0 != emcIoNmlGet()) { - rtapi_print_msg(RTAPI_MSG_ERR, - "can't connect to NML buffers in %s\n", - emc_nmlfile); - return -1; - } - - tooldata_init(random_toolchanger); - tooldata_set_db(io_db_mode); - // io process must be started before task -#ifdef TOOL_NML //{ - tool_nml_register( (CANON_TOOL_TABLE*)&(emcioStatus.tool.toolTable)); - if (io_debug) { - fprintf(stderr,"IO: REGISTER %p\n", - (CANON_TOOL_TABLE*)&(emcioStatus.tool.toolTable)); - } -#else //}{ - tool_mmap_creator((EMC_TOOL_STAT*)&(emcioStatus.tool), random_toolchanger); - if (io_debug) { - fprintf(stderr,"IO: CREATOR random_toolchanger=%d\n",random_toolchanger); - } -#endif //} - - if (io_db_mode == DB_ACTIVE) { - if (tooldata_db_init(db_program,random_toolchanger)) { - fprintf(stderr,"\n%5d IO::tooldata_db_init() FAIL\n\n",getpid()); - io_db_mode = DB_NOTUSED; - } - } - - // on nonrandom machines, always start by assuming the spindle is empty - if(!random_toolchanger) { - CANON_TOOL_TABLE tdata = tooldata_entry_init(); - tdata.pocketno = 0; //nonrandom init - tdata.toolno = -1; //nonrandom init - if (tooldata_put(tdata,0) != IDX_OK) { - UNEXPECTED_MSG; - } - } - if (0 != tooldata_load(io_tool_table_file)) { - rcs_print_error("can't load tool table.\n"); - } - done = 0; - - /* set status values to 'normal' */ - emcioStatus.aux.estop = 1; //estop=1 means to emc that ESTOP condition is met - emcioStatus.tool.pocketPrepped = -1; - if (random_toolchanger) { - CANON_TOOL_TABLE tdata; - if (tooldata_get(&tdata,0) != IDX_OK) { - UNEXPECTED_MSG; return -1; - } - emcioStatus.tool.toolInSpindle = tdata.toolno; - } else { - emcioStatus.tool.toolInSpindle = 0; - } - emcioStatus.coolant.mist = 0; - emcioStatus.coolant.flood = 0; - *(iocontrol_data->tool_number) = emcioStatus.tool.toolInSpindle; - - while (!done) { - // check for inputs from HAL (updates emcioStatus) - // returns 1 if any of the HAL pins changed from the last time we checked - /* if an external ESTOP is activated (or another hal-pin has changed) - a NML message has to be pushed to EMC. - the way it was done status was only checked at the end of a command */ - if (read_hal_inputs() > 0) { - emcioStatus.command_type = EMC_IO_STAT_TYPE; - emcioStatus.echo_serial_number = - emcioCommand->serial_number+1; //need for different serial number, because we are pushing a new message - emcioStatusBuffer->write(&emcioStatus); - } - ; - if ( (tool_status = read_tool_inputs() ) > 0) { // in case of tool prep (or change) update, we only need to change the state (from RCS_EXEC - emcioStatus.command_type = EMC_IO_STAT_TYPE; // to RCS_DONE, no need for different serial_number - emcioStatus.echo_serial_number = - emcioCommand->serial_number; - emcioStatusBuffer->write(&emcioStatus); - } - - /* read NML, run commands */ - if (-1 == emcioCommandBuffer->read()) { - /* bad command, wait until next cycle */ - esleep(emc_io_cycle_time); - /* and repeat */ - continue; - } - - if (0 == emcioCommand || // bad command pointer - 0 == emcioCommand->type || // bad command type - emcioCommand->serial_number == emcioStatus.echo_serial_number) { // command already finished - /* wait until next cycle */ - esleep(emc_io_cycle_time); - /* and repeat */ - continue; - } - - type = emcioCommand->type; - emcioStatus.status = RCS_STATUS::DONE; - - switch (type) { - case 0: - break; - - case EMC_TOOL_INIT_TYPE: - tooldata_load(io_tool_table_file); - reload_tool_number(emcioStatus.tool.toolInSpindle); - break; - - case EMC_TOOL_HALT_TYPE: - rtapi_print_msg(RTAPI_MSG_DBG, "EMC_TOOL_HALT\n"); - break; - - case EMC_TOOL_ABORT_TYPE: - // this gets sent on any Task Abort, so it might be safer to stop - // the spindle and coolant - rtapi_print_msg(RTAPI_MSG_DBG, "EMC_TOOL_ABORT\n"); - emcioStatus.coolant.mist = 0; - emcioStatus.coolant.flood = 0; - *(iocontrol_data->coolant_mist)=0; /* coolant mist output pin */ - *(iocontrol_data->coolant_flood)=0; /* coolant flood output pin */ - *(iocontrol_data->tool_change)=0; /* abort tool change if in progress */ - *(iocontrol_data->tool_prepare)=0; /* abort tool prepare if in progress */ - break; - - case EMC_TOOL_PREPARE_TYPE: - { - int idx = 0; - int toolno = ((EMC_TOOL_PREPARE*)emcioCommand)->tool; - CANON_TOOL_TABLE tdata; - idx = tooldata_find_index_for_tool(toolno); -#ifdef TOOL_NML - if (!random_toolchanger && toolno == 0) { idx = 0; } -#endif - if (idx == -1) { // not found - emcioStatus.tool.pocketPrepped = -1; - } else { - if (tooldata_get(&tdata,idx) != IDX_OK) { - UNEXPECTED_MSG; - } - rtapi_print_msg(RTAPI_MSG_DBG, "EMC_TOOL_PREPARE tool=%d idx=%d\n", toolno, idx); - - *(iocontrol_data->tool_prep_index) = idx; // any type of changer - - // Note: some of the following logic could be simplified - // but is maintained to preserve runtests expectations - // Set HAL pins for tool number, pocket, and index. - if (random_toolchanger) { - // RANDOM_TOOLCHANGER - *(iocontrol_data->tool_prep_number) = tdata.toolno; - if (idx == 0) { - emcioStatus.tool.pocketPrepped = 0; // pocketPrepped is an idx - *(iocontrol_data->tool_prep_pocket) = 0; - break; - } - *(iocontrol_data->tool_prep_pocket) = tdata.pocketno; - } else { - // NON_RANDOM_TOOLCHANGER - if (idx == 0) { - emcioStatus.tool.pocketPrepped = 0; // pocketPrepped is an idx - *(iocontrol_data->tool_prep_number) = 0; - *(iocontrol_data->tool_prep_pocket) = 0; - } else { - *(iocontrol_data->tool_prep_number) = tdata.toolno; - *(iocontrol_data->tool_prep_pocket) = tdata.pocketno; - } - } - // it doesn't make sense to prep the spindle pocket - if (random_toolchanger && idx == 0) { - emcioStatus.tool.pocketPrepped = 0; // idx - break; - } - } - - /* then set the prepare pin to tell external logic to get started */ - *(iocontrol_data->tool_prepare) = 1; - // the feedback logic is done inside read_hal_inputs() - // we only need to set RCS_EXEC if RCS_DONE is not already set by the above logic - if (tool_status != 10) //set above to 10 in case PREP already finished (HAL loopback machine) - emcioStatus.status = RCS_STATUS::EXEC; - } - break; - case EMC_TOOL_LOAD_TYPE: - rtapi_print_msg(RTAPI_MSG_DBG, "EMC_TOOL_LOAD loaded=%d prepped=%d\n", emcioStatus.tool.toolInSpindle, emcioStatus.tool.pocketPrepped); - - { - // it doesn't make sense to load a tool from the spindle pocket - if (random_toolchanger && emcioStatus.tool.pocketPrepped == 0) { - break; - } - - // it's not necessary to load the tool already in the spindle - CANON_TOOL_TABLE tdata; - if (tooldata_get(&tdata, emcioStatus.tool.pocketPrepped) != IDX_OK) { - UNEXPECTED_MSG; - } - if (!random_toolchanger && (emcioStatus.tool.pocketPrepped > 0) && - (emcioStatus.tool.toolInSpindle == tdata.toolno) ) { - break; - } - - if (emcioStatus.tool.pocketPrepped != -1) { - //notify HW for toolchange - *(iocontrol_data->tool_change) = 1; - // the feedback logic is done inside read_hal_inputs() we only - // need to set RCS_EXEC if RCS_DONE is not already set by the - // above logic - if (tool_status != 11) - // set above to 11 in case LOAD already finished (HAL - // loopback machine) - emcioStatus.status = RCS_STATUS::EXEC; - } - break; - } - case EMC_TOOL_UNLOAD_TYPE: - rtapi_print_msg(RTAPI_MSG_DBG, "EMC_TOOL_UNLOAD\n"); - emcioStatus.tool.toolInSpindle = 0; - break; - - case EMC_TOOL_LOAD_TOOL_TABLE_TYPE: - { - const char *filename = - ((EMC_TOOL_LOAD_TOOL_TABLE *) emcioCommand)->file; - if(!strlen(filename)) filename = io_tool_table_file; - rtapi_print_msg(RTAPI_MSG_DBG, "EMC_TOOL_LOAD_TOOL_TABLE\n"); - if (0 != tooldata_load(filename)) { - emcioStatus.status = RCS_STATUS::ERROR; - } else { - reload_tool_number(emcioStatus.tool.toolInSpindle); - } - } - break; - case EMC_TOOL_SET_OFFSET_TYPE: - { - int idx, toolno, o; - double d, f, b; - EmcPose offs; - - idx = ((EMC_TOOL_SET_OFFSET *) emcioCommand)->pocket; - toolno = ((EMC_TOOL_SET_OFFSET *) emcioCommand)->toolno; - offs = ((EMC_TOOL_SET_OFFSET *) emcioCommand)->offset; - d = ((EMC_TOOL_SET_OFFSET *) emcioCommand)->diameter; - f = ((EMC_TOOL_SET_OFFSET *) emcioCommand)->frontangle; - b = ((EMC_TOOL_SET_OFFSET *) emcioCommand)->backangle; - o = ((EMC_TOOL_SET_OFFSET *) emcioCommand)->orientation; - - rtapi_print_msg(RTAPI_MSG_DBG, - "EMC_TOOL_SET_OFFSET idx=%d toolno=%d zoffset=%lf, " - "xoffset=%lf, diameter=%lf, " - "frontangle=%lf, backangle=%lf, orientation=%d\n", - idx, toolno, offs.tran.z, offs.tran.x, d, f, b, o); - CANON_TOOL_TABLE tdata; - if (tooldata_get(&tdata,idx) != IDX_OK) { - UNEXPECTED_MSG; - } - tdata.toolno = toolno; - tdata.offset = offs; - tdata.diameter = d; - tdata.frontangle = f; - tdata.backangle = b; - tdata.orientation = o; - if (tooldata_put(tdata,idx) != IDX_OK) { - UNEXPECTED_MSG; - } - if (0 != tooldata_save(io_tool_table_file)) { - emcioStatus.status = RCS_STATUS::ERROR; - } - if (io_db_mode == DB_ACTIVE) { - int pno = idx; // for random_toolchanger - if (!random_toolchanger) { pno = tdata.pocketno; } - if (tooldata_db_notify(TOOL_OFFSET,toolno,pno,tdata)) { - UNEXPECTED_MSG; - } - } - } - break; - - case EMC_TOOL_SET_NUMBER_TYPE: //m61q- - { - int idx; - - idx = ((EMC_TOOL_SET_NUMBER *) emcioCommand)->tool; - CANON_TOOL_TABLE tdata; - if (tooldata_get(&tdata,idx) != IDX_OK) { - UNEXPECTED_MSG; - } - load_tool(idx); - - idx=0; // update spindle (fix legacy behavior) - if (tooldata_get(&tdata,idx) != IDX_OK) { - UNEXPECTED_MSG; - } - emcioStatus.tool.toolInSpindle = tdata.toolno; - rtapi_print_msg(RTAPI_MSG_DBG, - "EMC_TOOL_SET_NUMBER old_loaded_tool=%d new_idx_number=%d new_tool=%d\n" - , emcioStatus.tool.toolInSpindle, idx, tdata.toolno); - //likewise in HAL - *(iocontrol_data->tool_number) = emcioStatus.tool.toolInSpindle; - if (emcioStatus.tool.toolInSpindle == 0) { - emcioStatus.tool.toolFromPocket = *(iocontrol_data->tool_from_pocket) = 0; // no tool in spindle - } - } - break; - - case EMC_COOLANT_MIST_ON_TYPE: - rtapi_print_msg(RTAPI_MSG_DBG, "EMC_COOLANT_MIST_ON\n"); - emcioStatus.coolant.mist = 1; - *(iocontrol_data->coolant_mist) = 1; - break; - - case EMC_COOLANT_MIST_OFF_TYPE: - rtapi_print_msg(RTAPI_MSG_DBG, "EMC_COOLANT_MIST_OFF\n"); - emcioStatus.coolant.mist = 0; - *(iocontrol_data->coolant_mist) = 0; - break; - - case EMC_COOLANT_FLOOD_ON_TYPE: - rtapi_print_msg(RTAPI_MSG_DBG, "EMC_COOLANT_FLOOD_ON\n"); - emcioStatus.coolant.flood = 1; - *(iocontrol_data->coolant_flood) = 1; - break; - - case EMC_COOLANT_FLOOD_OFF_TYPE: - rtapi_print_msg(RTAPI_MSG_DBG, "EMC_COOLANT_FLOOD_OFF\n"); - emcioStatus.coolant.flood = 0; - *(iocontrol_data->coolant_flood) = 0; - break; - - case EMC_AUX_ESTOP_ON_TYPE: - rtapi_print_msg(RTAPI_MSG_DBG, "EMC_AUX_ESTOP_ON\n"); - /* assert an ESTOP to the outside world (thru HAL) */ - *(iocontrol_data->user_enable_out) = 0; //disable on ESTOP_ON - hal_init_pins(); //resets all HAL pins to safe value - break; - - case EMC_AUX_ESTOP_OFF_TYPE: - rtapi_print_msg(RTAPI_MSG_DBG, "EMC_AUX_ESTOP_OFF\n"); - /* remove ESTOP */ - *(iocontrol_data->user_enable_out) = 1; //we're good to enable on ESTOP_OFF - /* generate a rising edge to reset optional HAL latch */ - *(iocontrol_data->user_request_enable) = 1; - break; - - case EMC_SET_DEBUG_TYPE: - rtapi_print_msg(RTAPI_MSG_DBG, "EMC_SET_DEBUG\n"); - emc_debug = ((EMC_SET_DEBUG *) emcioCommand)->debug; - break; - - case EMC_TOOL_START_CHANGE_TYPE: - rtapi_print_msg(RTAPI_MSG_DBG, "EMC_TOOL_START_CHANGE\n"); - break; - - default: - rtapi_print("IO: unknown command %s\n", emcSymbolLookup(type)); - break; - } /* switch (type) */ - - // ack for the received command - emcioStatus.command_type = type; - emcioStatus.echo_serial_number = emcioCommand->serial_number; - //set above, to allow some commands to fail this - //emcioStatus.status = RCS_DONE; - emcioStatusBuffer->write(&emcioStatus); - - esleep(emc_io_cycle_time); - /* clear reset line to allow for a later rising edge */ - *(iocontrol_data->user_request_enable) = 0; - - } // end of "while (! done)" loop - - if (emcErrorBuffer != 0) { - delete emcErrorBuffer; - emcErrorBuffer = 0; - } - - if (emcioStatusBuffer != 0) { - delete emcioStatusBuffer; - emcioStatusBuffer = 0; - } - - if (emcioCommandBuffer != 0) { - delete emcioCommandBuffer; - emcioCommandBuffer = 0; - } - - return 0; -} diff --git a/src/emc/iotask/ioControl_v2.cc b/src/emc/iotask/ioControl_v2.cc deleted file mode 100644 index 41e2502265c..00000000000 --- a/src/emc/iotask/ioControl_v2.cc +++ /dev/null @@ -1,1245 +0,0 @@ -/******************************************************************** - * Description: IoControl.cc - * Simply accepts NML messages sent to the IO controller - * outputs those to a HAL pin, - * and sends back a "Done" message. - * - * - * ENABLE logic: this module exports three HAL pins related to ENABLE. - * The first is emc-enable-in. It is an input from the HAL, when FALSE, - * EMC will go into the STOPPED state (regardless of the state of - * the other two pins). When it goes TRUE, EMC will go into the - * ESTOP_RESET state (also known as READY). - * - * The second HAL pin is an output to the HAL. It is controlled by - * the NML messages ESTOP_ON and ESTOP_OFF, which normally result from - * user actions at the GUI. For the simplest system, loop user-enable-out - * back to emc-enable-in in the HAL. The GUI controls user-enable-out, and EMC - * responds to that once it is looped back. - * - * If external ESTOP inputs are desired, they can be - * used in a classicladder rung, in series with user-enable-out. - * It will look like this: - * - * -----|UEO|-----|EEST|--+--|EEI|--+--(EEI)---- - * | | - * +--|URE|--+ - * UEO=user-enable-out - * EEST=external ESTOP circuitry - * EEI=machine is enabled - * URE=user request enable - * - * This will work like this: EMC will be enabled (by EEI, emc-enabled-in), - * only if UEO, EEST are closed when URE gets strobed. - * If any of UEO (user requested stop) or EEST (external estop) have been - * opened, then EEI will open as well. - * After restoring normal condition (UEO and EEST closed), an additional - * URE (user-request-enable) is needed, this is either sent by the GUI - * (using the EMC_AUX_ESTOP_RESET NML message), or by a hardware button - * connected to the ladder driving URE. - * - * NML messages are sent usually from the user hitting F1 on the GUI. - * - * Derived from a work by Fred Proctor & Will Shackleford - * - * Author: - * License: GPL Version 2 - * System: Linux - * - * Copyright (c) 2004 All rights reserved. - * - * Last change: Michael Haberler 1/2011 - rework & add v2 protocol support - ********************************************************************/ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "hal.h" /* access to HAL functions/definitions */ -#include "rtapi.h" /* rtapi_print_msg */ -#include "rcs.hh" /* RCS_CMD_CHANNEL */ -#include "emc.hh" /* EMC NML */ -#include "emc_nml.hh" -#include "emcglb.h" /* EMC_NMLFILE, EMC_INIFILE, TOOL_TABLE_FILE */ -#include "inifile.hh" /* INIFILE */ -#include "nml_oi.hh" -#include "timer.hh" -#include "rcs_print.hh" -#include -#include "tooldata.hh" - -static bool io_debug = 0; -#define UNEXPECTED_MSG fprintf(stderr,"UNEXPECTED %s %d\n",__FILE__,__LINE__); - -static RCS_CMD_CHANNEL *emcioCommandBuffer = 0; -static RCS_CMD_MSG *emcioCommand = 0; -static RCS_STAT_CHANNEL *emcioStatusBuffer = 0; -static EMC_IO_STAT emcioStatus; -static NML *emcErrorBuffer = 0; - -static char io_tool_table_file[LINELEN] = "tool.tbl"; // default -static int random_toolchanger = 0; -static tooldb_t io_db_mode = DB_NOTUSED; -static char db_program[LINELEN] = {0}; - -static int support_start_change = 0; -static const char *progname; - -typedef enum { - V1 = 1, - V2 = 2 -} version_t; -static int proto = V2; - -// extend EMC_IO_ABORT_REASON_ENUM from emc.hh -enum { - EMC_ABORT_BY_TOOLCHANGER_FAULT = EMC_ABORT_USER + 1 -}; - -static const char *strcs[] = { "invalid","RCS_DONE","RCS_EXEC","RCS_ERROR"}; - -// read_inputs() returns a mask of changes observed -enum { - TI_PREPARING = 1, - TI_PREPARE_COMPLETE = 2, - TI_CHANGING = 4, - TI_CHANGE_COMPLETE = 8, - TI_TC_FAULT = 16, - TI_TC_ABORT = 32, - TI_EMC_ABORT_SIGNALED = 64, - TI_EMC_ABORT_ACKED = 128, - TI_ESTOP_CHANGED = 256, - TI_START_CHANGE = 1024, - TI_START_CHANGE_ACKED = 2048 -}; - -// iocontrol states. Reflected in state pin -typedef enum { - ST_IDLE = 0, - ST_PREPARING = 1, - ST_START_CHANGE = 2, // V2 only - ST_CHANGING = 3, - ST_WAIT_FOR_ABORT_ACK = 4, // V2 only -} iostate_t; -static const char *strstate[] = { "IDLE","PREPARING","START_CHANGE", "CHANGING","WAIT_FOR_ABORT_ACK"}; - -static int toolchanger_reason; // last fault reason read from toolchanger - -// predicates for testing toolchanger fault conditions -#define TC_FAULT (*(iocontrol_data->toolchanger_faulted)) -#define TC_HARDFAULT (TC_FAULT && (toolchanger_reason <= 0)) -#define TC_SOFTFAULT (TC_FAULT && (toolchanger_reason > 0)) - -struct iocontrol_str { - hal_bit_t *user_enable_out; /* output, TRUE when EMC wants stop */ - hal_bit_t *emc_enable_in; /* input, TRUE on any external stop */ - hal_bit_t *user_request_enable; /* output, used to reset ENABLE latch */ - hal_bit_t *coolant_mist; /* coolant mist output pin */ - hal_bit_t *coolant_flood; /* coolant flood output pin */ - - // the following pins are needed for toolchanging - //tool-prepare - hal_bit_t *tool_prepare; /* output, pin that notifies HAL it needs to prepare a tool */ - hal_s32_t *tool_prep_pocket;/* output, pin that holds the P word from the tool table entry matching the tool to be prepared, - only valid when tool-prepare=TRUE */ - hal_s32_t *tool_prep_index; /* output, internal index (idx) of prepped tool above */ - hal_s32_t *tool_prep_number;/* output, pin that holds the tool number to be prepared, only valid when tool-prepare=TRUE */ - hal_s32_t *tool_number; /* output, pin that holds the tool number currently in the spindle */ - hal_bit_t *tool_prepared; /* input, pin that notifies that the tool has been prepared */ - //tool-change - hal_bit_t *tool_change; /* output, notifies a tool-change should happen (emc should be in the tool-change position) */ - hal_bit_t *tool_changed; /* input, notifies tool has been changed */ - - // v2 protocol - // iocontrolv2 -> toolchanger - hal_bit_t *emc_abort; /* output, signals emc-originated abort to toolchanger */ - hal_bit_t *emc_abort_ack; /* input, handshake line to acknowledge abort_tool_change */ - hal_s32_t *emc_reason; /* output, convey cause for EMC-originated abort to toolchanger. - * UI informational. Valid during emc-abort True. - */ - // toolchanger -> iocontrolv2 - hal_bit_t *toolchanger_fault; /* input, toolchanger signals fault . Always monitored. - * A fault is recorded in the toolchange_faulted pin - */ - hal_bit_t *toolchanger_fault_ack; /* handshake line for above signal. will be set by iocontrol - * after above fault line is recognized and deasserted when - * toolchanger-fault drops. Toolchanger is free to interpret - * the ack; reading the -ack lines assures fault has been - * received and acted upon. - */ - hal_s32_t *toolchanger_reason; /* input, convey reason code for toolchanger-originated - * fault to iocontrol. read during toolchanger-fault True. - * on a toolchange abort, the reason is passed to EMC in the - * emcioStat message. - * a positive value causes an OperatorDisplay text - * a negative value causes an OperatorError text - * a zero value does not cause any display - */ - - hal_bit_t *start_change; /* signal begin of M6 cycle even before move to toolchange - * position starts - */ - hal_bit_t *start_change_ack; /* acknowledge line for start_change */ - - // other: - hal_bit_t *toolchanger_faulted; /* output. signals toolchanger-faul line has toggled - * The next M6 will abort if True. - */ - hal_bit_t *toolchanger_clear_fault; /* input. resets TC fault condition. - * Deasserts toolchanger-faulted if toolchanger-fault is line False. - * Usage: UI - e.g. 'clear TC fault' button - */ - hal_s32_t *state; /* output. Internal state for debugging */ - - // note: spindle control has been moved to motion -} *iocontrol_data; //pointer to the HAL-struct - -static int comp_id; /* component ID */ - -/******************************************************************** - * - * Description: emcIoNmlGet() - * Attempts to connect to NML buffers and set the relevant - * pointers. - * - * Return Value: Zero on success or -1 if can not connect to a buffer. - * - * Side Effects: None. - * - * Called By: main() - * - ********************************************************************/ -static int emcIoNmlGet() -{ - int retval = 0; - - /* Try to connect to EMC IO command buffer */ - if (emcioCommandBuffer == 0) { - emcioCommandBuffer = - new RCS_CMD_CHANNEL(emcFormat, "toolCmd", "tool", emc_nmlfile); - if (!emcioCommandBuffer->valid()) { - rtapi_print_msg(RTAPI_MSG_ERR, - "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 buffer */ - if (emcioStatusBuffer == 0) { - emcioStatusBuffer = - new RCS_STAT_CHANNEL(emcFormat, "toolSts", "tool", - emc_nmlfile); - if (!emcioStatusBuffer->valid()) { - rtapi_print_msg(RTAPI_MSG_ERR, - "toolSts buffer not available\n"); - delete emcioStatusBuffer; - emcioStatusBuffer = 0; - retval = -1; - } else { - /* initialize and write status */ - emcioStatus.command_type = 0; - emcioStatus.echo_serial_number = 0; - emcioStatus.status = RCS_STATUS::DONE; - emcioStatusBuffer->write(&emcioStatus); - } - } - - /* try to connect to EMC error buffer */ - if (emcErrorBuffer == 0) { - emcErrorBuffer = - new NML(nmlErrorFormat, "emcError", "tool", emc_nmlfile); - if (!emcErrorBuffer->valid()) { - rtapi_print_msg(RTAPI_MSG_ERR, - "emcError buffer not available\n"); - delete emcErrorBuffer; - emcErrorBuffer = 0; - retval = -1; - } - } - - return retval; -} - -static int iniLoad(const char *filename) -{ - IniFile inifile; - const char *inistring; - - /* Open the INI file */ - if (inifile.Open(filename) == false) { - return -1; - } - - if (NULL != (inistring = inifile.Find("TOOL_TABLE", "EMCIO"))) { - strncpy(io_tool_table_file, inistring, sizeof(io_tool_table_file)-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; - } - - // make it verbose if debugging RCS - if (emc_debug & EMC_DEBUG_IOCONTROL) { - rtapi_set_msg_level(RTAPI_MSG_DBG); - } - - if (NULL != (inistring = inifile.Find("NML_FILE", "EMC"))) { - rtapi_strxcpy(emc_nmlfile, inistring); - } else { - // not found, use default - } - - double temp; - temp = emc_io_cycle_time; - if (NULL != (inistring = inifile.Find("CYCLE_TIME", "EMCIO"))) { - if (1 == sscanf(inistring, "%lf", &emc_io_cycle_time)) { - // found it - } else { - // found, but invalid - emc_io_cycle_time = temp; - rtapi_print - ("invalid [EMCIO] CYCLE_TIME in %s (%s); using default %f\n", - filename, inistring, emc_io_cycle_time); - } - } else { - // not found, using default - rtapi_print - ("[EMCIO] CYCLE_TIME not found in %s; using default %f\n", - filename, emc_io_cycle_time); - } - - inifile.Find(&proto, "PROTOCOL_VERSION", "EMCIO"); - rtapi_print_msg(RTAPI_MSG_DBG,"%s: [EMCIO] using v%d protocol\n",progname,proto); - - inifile.Find(&random_toolchanger, "RANDOM_TOOLCHANGER", "EMCIO"); - - io_db_mode = DB_NOTUSED; - if(NULL != (inistring = inifile.Find("DB_PROGRAM", "EMCIO"))) { - rtapi_strxcpy(db_program,inistring); - io_db_mode = DB_ACTIVE; - } - // close it - inifile.Close(); - - return 0; -} - -static int done = 0; - -/******************************************************************** - * - * Description: quit(int sig) - * Signal handler for SIGINT - Usually generated by a - * Ctrl C sequence from the keyboard. - * - * Return Value: None. - * - * Side Effects: Sets the termination condition of the main while loop. - * - * Called By: Operating system. - * - ********************************************************************/ -static void quit(int sig) -{ - done = 1; -} - -#define BITPIN(dir,fmt,ptr) \ - if ((retval = hal_pin_bit_newf(dir,ptr,comp_id, fmt,n)) < 0) { \ - snprintf(buf, sizeof(buf),fmt,n); \ - rtapi_print_msg(RTAPI_MSG_ERR, "%s: ERROR: %s - export failed error=%d\n",progname,buf,retval); \ - goto HAL_EXIT; \ - } -#define S32PIN(dir,fmt,ptr) \ - if ((retval = hal_pin_s32_newf(dir,ptr,comp_id, fmt,n)) < 0) { \ - snprintf(buf, sizeof(buf),fmt,n); \ - rtapi_print_msg(RTAPI_MSG_ERR, "%s: ERROR: %s - export failed error=%d\n",progname,buf,retval); \ - goto HAL_EXIT; \ - } - - -/******************************************************************** - * - * Description: iocontrol_hal_init(void) - * - * Side Effects: Exports HAL pins. - * - * Called By: main - ********************************************************************/ -static int iocontrol_hal_init(void) -{ - int n = 0; //n - number of the hal component (only one for iocotrol) - int retval = -1; - char buf[100]; - - // initialise the hal component - if ((comp_id = hal_init("iocontrol")) < 0) { - rtapi_print_msg(RTAPI_MSG_ERR,"%s: ERROR: hal_init() failed - error=%d\n",progname,comp_id); - goto FAIL; - } - - // allocate shared memory for iocontrol data - if ((iocontrol_data = (iocontrol_str *) hal_malloc(sizeof(iocontrol_str))) == NULL) { - rtapi_print_msg(RTAPI_MSG_ERR,"%s: ERROR: hal_malloc() failed\n",progname); - goto HAL_EXIT; - } - - BITPIN( HAL_OUT, "iocontrol.%d.user-enable-out", &(iocontrol_data->user_enable_out)); - BITPIN( HAL_OUT, "iocontrol.%d.user-request-enable", &(iocontrol_data->user_request_enable)); - BITPIN( HAL_OUT, "iocontrol.%d.coolant-flood", &(iocontrol_data->coolant_flood)); - BITPIN( HAL_OUT, "iocontrol.%d.coolant-mist", &(iocontrol_data->coolant_mist)); - S32PIN( HAL_OUT, "iocontrol.%d.tool-number", &(iocontrol_data->tool_number)); - S32PIN( HAL_OUT, "iocontrol.%d.tool-prep-number", &(iocontrol_data->tool_prep_number)); - S32PIN( HAL_OUT, "iocontrol.%d.tool-prep-pocket", &(iocontrol_data->tool_prep_pocket)); - - // tool-prep-index (idx) - retval = hal_pin_s32_newf(HAL_OUT, &(iocontrol_data->tool_prep_index), comp_id, - "iocontrol.%d.tool-prep-index", n); - if (retval < 0) { - rtapi_print_msg(RTAPI_MSG_ERR, - "IOCONTROL: ERROR: iocontrol %d pin tool-prep-index export failed with err=%i\n", - n, retval); - hal_exit(comp_id); - return -1; - } - - BITPIN( HAL_OUT, "iocontrol.%d.tool-prepare", &(iocontrol_data->tool_prepare)); - BITPIN( HAL_IN , "iocontrol.%d.tool-prepared", &(iocontrol_data->tool_prepared)); - BITPIN( HAL_OUT, "iocontrol.%d.tool-change", &(iocontrol_data->tool_change)); - BITPIN( HAL_IN , "iocontrol.%d.tool-changed", &(iocontrol_data->tool_changed)); - BITPIN( HAL_IN , "iocontrol.%d.emc-enable-in", &(iocontrol_data->emc_enable_in)); - - S32PIN( HAL_OUT, "iocontrol.%d.state", &(iocontrol_data->state)); - - // v2 pins - if (proto > V1) { - BITPIN( HAL_OUT, "iocontrol.%d.emc-abort", &(iocontrol_data->emc_abort)); - BITPIN( HAL_IN , "iocontrol.%d.emc-abort-ack", &(iocontrol_data->emc_abort_ack)); - S32PIN( HAL_OUT, "iocontrol.%d.emc-reason", &(iocontrol_data->emc_reason)); - BITPIN( HAL_IN , "iocontrol.%d.toolchanger-fault", &(iocontrol_data->toolchanger_fault)); - BITPIN( HAL_OUT, "iocontrol.%d.toolchanger-fault-ack", &(iocontrol_data->toolchanger_fault_ack)); - S32PIN( HAL_IN , "iocontrol.%d.toolchanger-reason", &(iocontrol_data->toolchanger_reason)); - BITPIN( HAL_OUT, "iocontrol.%d.toolchanger-faulted", &(iocontrol_data->toolchanger_faulted)); - BITPIN( HAL_IN , "iocontrol.%d.toolchanger-clear-fault", &(iocontrol_data->toolchanger_clear_fault)); - BITPIN( HAL_OUT, "iocontrol.%d.start-change", &(iocontrol_data->start_change)); - BITPIN( HAL_IN , "iocontrol.%d.start-change-ack", &(iocontrol_data->start_change_ack)); - } - rtapi_print_msg(RTAPI_MSG_DBG, "%s: iocontrol_hal_init() complete\n",progname); - hal_ready(comp_id); - return(0); - -HAL_EXIT: - hal_exit(comp_id); -FAIL: - return retval; -} - - -/******************************************************************** - * - * Description: hal_init_pins(void) - * - * Side Effects: Sets HAL pins default values. - * - * Called By: main - ********************************************************************/ -static void hal_init_pins(void) -{ - *(iocontrol_data->user_enable_out) = 0; /* output, FALSE when EMC wants stop */ - *(iocontrol_data->user_request_enable) = 0; /* output, used to reset HAL latch */ - *(iocontrol_data->coolant_mist) = 0; /* coolant mist output pin */ - *(iocontrol_data->coolant_flood) = 0; /* coolant flood output pin */ - *(iocontrol_data->tool_prepare) = 0; /* output, pin that notifies HAL it needs to prepare a tool */ - *(iocontrol_data->tool_prep_number) = 0; /* output, pin that holds the tool number to be prepared, only valid when tool-prepare=TRUE */ - *(iocontrol_data->tool_prep_pocket) = 0; /* output, pin that holds the pocketno for the tool to be prepared, only valid when tool-prepare=TRUE */ - *(iocontrol_data->tool_prep_index) = 0; /* output, pin that holds the internal index (idx) of the tool to be prepared, for debug */ - *(iocontrol_data->tool_change) = 0; /* output, notifies a tool-change should happen (emc should be in the tool-change position) */ - - *(iocontrol_data->state) = ST_IDLE; // new pin in v1 mode, too - - if (proto > V1) { - // v2 protocol output pins - *(iocontrol_data->emc_abort) = 0; - *(iocontrol_data->emc_reason) = 0; - *(iocontrol_data->toolchanger_fault_ack) = 0; - *(iocontrol_data->toolchanger_faulted) = 0; - *(iocontrol_data->start_change) = 0; - } -} - -void load_tool(int idx) { - CANON_TOOL_TABLE tdata; - if(random_toolchanger) { - // swap the tools between the desired pocket and the spindle pocket - - CANON_TOOL_TABLE tzero,tpocket; - if ( tooldata_get(&tzero,0 ) != IDX_OK - || tooldata_get(&tpocket,idx) != IDX_OK) { - UNEXPECTED_MSG; return; - } - // spindle-->pocket (specified by idx) - tooldata_db_notify(SPINDLE_UNLOAD,tzero.toolno,idx,tzero); - tzero.pocketno = tpocket.pocketno; - if (tooldata_put(tzero, idx) == IDX_FAIL) { - UNEXPECTED_MSG; - } - - // pocket-->spindle (idx==0) - tooldata_db_notify(SPINDLE_LOAD,tpocket.toolno,0,tpocket); - tpocket.pocketno = 0; - if (tooldata_put(tpocket,0 ) == IDX_FAIL) { - UNEXPECTED_MSG; - } - - if (0 != tooldata_save(io_tool_table_file)) { - emcioStatus.status = RCS_STATUS::ERROR; - } - } else if(idx == 0) { - // magic T0 = pocket 0 = no tool - tdata = tooldata_entry_init(); - tdata.toolno = 0; // nonrandom unload tool from spindle - tdata.pocketno = 0; // nonrandom unload tool from spindle - if (tooldata_put(tdata,0) == IDX_FAIL) { - UNEXPECTED_MSG; return; - } - if (tooldata_db_notify(SPINDLE_UNLOAD,0,0,tdata)) { UNEXPECTED_MSG; } - } else { - // just copy the desired tool to the spindle - if (tooldata_get(&tdata,idx) != IDX_OK) { - UNEXPECTED_MSG; return; - } - if (tooldata_put(tdata,0) == IDX_FAIL) { - UNEXPECTED_MSG; return; - } - // notify idx==0 tool in spindle: - CANON_TOOL_TABLE temp; - if (tooldata_get(&temp,0) != IDX_OK) { UNEXPECTED_MSG; } - if (tooldata_db_notify(SPINDLE_LOAD,temp.toolno,0,temp)) { UNEXPECTED_MSG; } - } -} // load_tool() - -void reload_tool_number(int toolno) { - CANON_TOOL_TABLE tdata; - if(random_toolchanger) return; // doesn't need special handling here - for(int idx = 1; idx <= tooldata_last_index_get(); idx++) { //note <= - if (tooldata_get(&tdata,idx) != IDX_OK) { - UNEXPECTED_MSG; return; - } - if(tdata.toolno == toolno) { - load_tool(idx); - break; - } - } -} - -static char *str_input(int status) -{ - static char seen[200]; - - seen[0] = 0; - if (status & TI_PREPARING) rtapi_strxcat(seen," TI_PREPARING"); - if (status & TI_PREPARE_COMPLETE) rtapi_strxcat(seen," TI_PREPARE_COMPLETE"); - if (status & TI_CHANGING) rtapi_strxcat(seen," TI_CHANGING"); - if (status & TI_CHANGE_COMPLETE) rtapi_strxcat(seen," TI_CHANGE_COMPLETE"); - if (status & TI_TC_FAULT) rtapi_strxcat(seen," TI_TC_FAULT"); - if (status & TI_TC_ABORT) rtapi_strxcat(seen," TI_TC_ABORT"); - if (status & TI_EMC_ABORT_SIGNALED) rtapi_strxcat(seen," TI_EMC_ABORT_SIGNALED"); - if (status & TI_EMC_ABORT_ACKED) rtapi_strxcat(seen," TI_EMC_ABORT_ACKED"); - if (status & TI_ESTOP_CHANGED) rtapi_strxcat(seen," TI_ESTOP_CHANGED"); - if (status & TI_START_CHANGE) rtapi_strxcat(seen," TI_START_CHANGE"); - if (status & TI_START_CHANGE_ACKED) rtapi_strxcat(seen," TI_START_CHANGE_ACKED"); - return seen; -} -/******************************************************************** - * - * Description: read_inputs(void) - * Reads pin values from HAL - * Handle pin protocol - * this function gets called once per cycle - * It sets the values for the emcioStatus.aux.* - * also handle estop - * - * Returns: returns a bitmask of relevant status - * - * Side Effects: updates toolchanger_reason, - * emcioStatus.tool.* - * emcioStatus.aux.estop - * - * Called By: main every CYCLE - ********************************************************************/ - -static int read_inputs(void) -{ - int oldval, retval = 0; - - oldval = emcioStatus.aux.estop; - - if ( *(iocontrol_data->emc_enable_in)==0) //check for estop from HW - emcioStatus.aux.estop = 1; - else - emcioStatus.aux.estop = 0; - - if (oldval != emcioStatus.aux.estop) { - retval |= TI_ESTOP_CHANGED; - } - - if (proto > V1) { - // FIXME test with predicate in main - // record toolchanger fault - if (*iocontrol_data->toolchanger_fault) { - // reason code now valid - toolchanger_reason = *iocontrol_data->toolchanger_reason; - rtapi_print_msg(RTAPI_MSG_DBG, "%s:read_input: toolchanger fault signaled, reason: %d \n",progname, toolchanger_reason); - - // raise ack line - *(iocontrol_data->toolchanger_fault_ack) = 1; - // record the fact that a fault or abort was received - *(iocontrol_data->toolchanger_faulted) = 1; - retval |= TI_TC_FAULT; - } else { - // clear the ack line - *(iocontrol_data->toolchanger_fault_ack) = 0; - } - - // clear toolchanger fault condition if so signaled, - if (*iocontrol_data->toolchanger_clear_fault) { - *(iocontrol_data->toolchanger_faulted) = 0; - // clear last tc fault reason - toolchanger_reason = 0; - retval &= ~TI_TC_FAULT; - } - - // an EMC-side abort is in progress. - if (*iocontrol_data->emc_abort) { - if (*iocontrol_data->emc_abort_ack) { - // the toolchanger acknowledged the fact so deassert - *(iocontrol_data->emc_abort) = 0; - // a completed EMC-side abort always forces IDLE state - *(iocontrol_data->state) = ST_IDLE; - retval |= TI_EMC_ABORT_ACKED; - } else { - // waiting for abort being acked by toolchanger. - retval |= TI_EMC_ABORT_SIGNALED; - } - } - // the very start of an M6 operation was signaled - if (*iocontrol_data->start_change) { - if (*iocontrol_data->start_change_ack) { - // the toolchanger acknowledged the start-change - *(iocontrol_data->start_change) = 0; - retval |= TI_START_CHANGE_ACKED; - } else { - // wait for ack by toolchanger - retval |= TI_START_CHANGE; - } - } - } - - if (*iocontrol_data->tool_prepare) { - if (*iocontrol_data->tool_prepared) { - emcioStatus.tool.pocketPrepped = *(iocontrol_data->tool_prep_index); //check if tool has been prepared - *(iocontrol_data->tool_prepare) = 0; - *(iocontrol_data->state) = ST_IDLE; // normal prepare completion - retval |= TI_PREPARE_COMPLETE; - } else { - *(iocontrol_data->state) = ST_PREPARING; - retval |= TI_PREPARING; - } - } - - if (*iocontrol_data->tool_change) { - - // check whether a toolchanger fault will force an abort of this change - if ((proto > V1) && (*iocontrol_data->toolchanger_faulted)) { - - /* unlikely but possible: toolchanger_faulted was asserted since - * we received the EMC_TOOL_LOAD - * read new reason code - * retract change request - */ - toolchanger_reason = *iocontrol_data->toolchanger_reason; - /* signal an abort in response, abort-ack line is handled - * at beginning of function in next iteration(s) - * this assures toolchanger is aware of an aborted change - * even if it was caused by the toolchanger faulting it in - * the first place - */ - *(iocontrol_data->emc_reason) = EMC_ABORT_BY_TOOLCHANGER_FAULT; - *(iocontrol_data->emc_abort) = 1; - retval |= TI_TC_ABORT; - // give up on request - *(iocontrol_data->tool_change) = 0; - *(iocontrol_data->state) = ST_WAIT_FOR_ABORT_ACK; - } - - if (*iocontrol_data->tool_changed) { - // good to commit this change - if(!random_toolchanger && emcioStatus.tool.pocketPrepped == 0) { - emcioStatus.tool.toolInSpindle = 0; - } else { - // the tool now in the spindle is the one that was prepared - CANON_TOOL_TABLE tdata; - if (tooldata_get(&tdata,emcioStatus.tool.pocketPrepped) != IDX_OK) { - UNEXPECTED_MSG; return -1; - } - emcioStatus.tool.toolInSpindle = tdata.toolno; - } - *(iocontrol_data->tool_number) = emcioStatus.tool.toolInSpindle; // likewise in HAL - load_tool(emcioStatus.tool.pocketPrepped); - emcioStatus.tool.pocketPrepped = -1; // reset the tool prepped number, -1 to permit tool 0 to be loaded - *(iocontrol_data->tool_prep_number) = 0; // likewise in HAL - *(iocontrol_data->tool_prep_pocket) = 0; // likewise in HAL - *(iocontrol_data->tool_prep_index) = 0; // likewise in HAL - *(iocontrol_data->tool_change) = 0; // also reset the tool change signal - *(iocontrol_data->state) = ST_IDLE; - retval |= TI_CHANGE_COMPLETE; - } else { - retval |= TI_CHANGING; - } - } - return retval; -} - -static void do_hal_exit(void) { - hal_exit(comp_id); -} - - -static void update_status(RCS_STATUS status, int serial) -{ - static RCS_STATUS status_reported = RCS_STATUS::UNINITIALIZED; - - emcioStatus.status = status; - if (status_reported != status) { - rtapi_print_msg(RTAPI_MSG_DBG, "%s: updating status=%s state=%s fault=%d reason=%d\n", - progname,strcs[(int)emcioStatus.status],strstate[*(iocontrol_data->state)],//BUG: array accessed at -1 when status is RCS_STATUS::UNINITIALIZED - emcioStatus.fault, emcioStatus.reason - ); - status_reported = emcioStatus.status; // just print this once - } - emcioStatus.command_type = EMC_IO_STAT_TYPE; - emcioStatus.echo_serial_number = serial; - emcioStatusBuffer->write(&emcioStatus); -} - -/******************************************************************** - * - * Description: main(int argc, char * argv[]) - * Connects to NML buffers and enters an endless loop - * processing NML IO commands. Print statements are - * sent to the console indicating which IO command was - * executed if debug level is set to RTAPI_MSG_DBG. - * - * Exit Value: Zero or -1 if INI file not found or failure to connect - * to NML buffers. - * - * Side Effects: None. - * - * Called By: - * - ********************************************************************/ - -int main(int argc, char *argv[]) -{ -#ifdef TOOL_NML //{ - #define TOOL_DATA "nml" -#else //}{ - #define TOOL_DATA "mmap" -#endif //} - - if (getenv( (char*)"IO_DEBUG" )) { getpid(),io_debug = 1; } - if (io_debug) { - fprintf(stderr,"%8d IOV2: %s\n",getpid(),TOOL_DATA); - fprintf(stderr," EMC_STAT size=%8ld\n",sizeof(EMC_STAT)); - fprintf(stderr," EMC_IO_STAT size=%8ld\n",sizeof(EMC_IO_STAT)); - fprintf(stderr," EMC_TOOL_STAT size=%8ld\n",sizeof(EMC_TOOL_STAT)); - fprintf(stderr," CANON_POCKETS_MAX =%8d\n",CANON_POCKETS_MAX); - } - - int input_status; - NMLTYPE type; - - progname = argv[0]; - for (int t = 1; t < argc; t++) { - if (!strcmp(argv[t], "-support-start-change")) { - support_start_change = 1; - continue; - } - if (!strcmp(argv[t], "-ini")) { - if (t == argc - 1) { - return -1; - } else { - if (strlen(argv[t+1]) >= LINELEN) { - rtapi_print_msg(RTAPI_MSG_ERR, "INI file name too long (max %d)\n", LINELEN); - rtapi_print_msg(RTAPI_MSG_ERR, " %s\n", argv[t+1]); - return -1; - } - rtapi_strxcpy(emc_inifile, argv[t + 1]); - t++; - } - continue; - } - /* do other args similarly here */ - } - - /* Register the routine that catches the SIGINT signal */ - signal(SIGINT, quit); - /* catch SIGTERM too - the run script uses it to shut things down */ - signal(SIGTERM, quit); - - if (0 != iniLoad(emc_inifile)) { - rtapi_print_msg(RTAPI_MSG_ERR, "%s: can't open INI file %s\n",progname,emc_inifile); - exit(-1); - } - - if (iocontrol_hal_init() != 0) { - rtapi_print_msg(RTAPI_MSG_ERR, "%s: can't initialize the HAL\n",progname); - exit(-1); - } - - atexit(do_hal_exit); -#ifdef TOOL_NML //{ -#else //}{ - atexit(tool_mmap_close); -#endif //} - - if (0 != emcIoNmlGet()) { - rtapi_print_msg(RTAPI_MSG_ERR, - "%s:can't connect to NML buffers in %s\n",progname,emc_inifile); - exit(-1); - } - - tooldata_init(random_toolchanger); - tooldata_set_db(io_db_mode); - // io process must be started before task -#ifdef TOOL_NML //{ - tool_nml_register( (CANON_TOOL_TABLE*)&(emcioStatus.tool.toolTable)); - if (io_debug) { - fprintf(stderr,"IOV2: REGISTER %p\n", - (CANON_TOOL_TABLE*)&(emcioStatus.tool.toolTable)); - } -#else //}{ - tool_mmap_creator((EMC_TOOL_STAT*)&(emcioStatus.tool), random_toolchanger); - if (io_debug) { - fprintf(stderr,"IOV2: CREATOR random_toolchanger=%d\n",random_toolchanger); - } -#endif //} - - if (io_db_mode == DB_ACTIVE) { - if (tooldata_db_init(db_program,random_toolchanger)) { - fprintf(stderr,"\n%5d IOV2::tooldata_db_init() FAIL\n\n",getpid()); - io_db_mode = DB_NOTUSED; - } - } - - // on nonrandom machines, always start by assuming the spindle is empty - if(!random_toolchanger) { - CANON_TOOL_TABLE tdata = tooldata_entry_init(); - tdata.pocketno = 0; //nonrandom init - tdata.toolno = -1; //nonrandom init - if (tooldata_put(tdata,0) == IDX_FAIL) { - UNEXPECTED_MSG; - } - } - - if (0 != tooldata_load(io_tool_table_file)) { - rcs_print_error("%s: can't load tool table.\n",progname); - } - - done = 0; - - /* set status values to 'normal' */ - emcioStatus.aux.estop = 1; // estop=1 means to emc that ESTOP condition is met - emcioStatus.tool.pocketPrepped = -1; - if (random_toolchanger) { - CANON_TOOL_TABLE tdata; - if (tooldata_get(&tdata,0) != IDX_OK) { - UNEXPECTED_MSG; return -1; - } - emcioStatus.tool.toolInSpindle = tdata.toolno; - } else { - emcioStatus.tool.toolInSpindle = 0; - } - emcioStatus.coolant.mist = 0; - emcioStatus.coolant.flood = 0; - - while (!done) { - - /* check for inputs from HAL (updates emcioStatus) - * read_inputs() returns a bit mask of observed state changes - * if an external ESTOP is activated, - * an NML message has to be pushed to EMC. - * the way it was done status was only checked at the end of a command - */ - input_status = read_inputs(); - - // always piggyback fault and reason - emcioStatus.fault = *(iocontrol_data->toolchanger_faulted); - emcioStatus.reason = toolchanger_reason; - - if (input_status & (TI_PREPARING)) { - update_status(RCS_STATUS::EXEC, emcioCommand->serial_number); - } - - if (input_status & (TI_START_CHANGE|TI_CHANGING)) { - if (TC_FAULT) { - rtapi_print_msg(RTAPI_MSG_DBG, "%s: signaling fault during change, reason=%d state=%s input_status=%s\n", - progname, - toolchanger_reason, - strstate[*(iocontrol_data->state)], - str_input(input_status) - ); - update_status(RCS_STATUS::ERROR, emcioCommand->serial_number); - } else { - update_status(RCS_STATUS::EXEC, emcioCommand->serial_number); - } - } - - // if (input_status & (TI_PREPARE_COMPLETE|TI_CHANGE_COMPLETE|TI_START_CHANGE_ACKED|TI_EMC_ABORT_ACKED)) - if (input_status & (TI_PREPARE_COMPLETE|TI_CHANGE_COMPLETE|TI_START_CHANGE_ACKED)) { - update_status(RCS_STATUS::DONE, emcioCommand->serial_number); - } - - /* read NML, run commands */ - if (-1 == emcioCommandBuffer->read()) { - /* bad command, wait until next cycle */ - esleep(emc_io_cycle_time); - /* and repeat */ - continue; - } - - if (0 == emcioCommand || // bad command pointer - 0 == emcioCommand->type || // bad command type - emcioCommand->serial_number == emcioStatus.echo_serial_number) { // command already finished - /* wait until next cycle */ - esleep(emc_io_cycle_time); - /* and repeat */ - continue; - } - - /* emcioStatus.status is set to RCS_DONE here which would cause - * the next message to be read and processed on the next iteration. - * those command types which need to block processing the next message - * until the step is completed need to set emcioStatus.status to RCS_EXEC - * (EMC_TOOL_PREPARE_TYPE, EMC_TOOL_LOAD_TYPE) - * to cause an abort, set emcioStatus.reason and - * emcioStatus.status to RCS_ERROR. - */ - emcioStatus.status = RCS_STATUS::DONE; - type = emcioCommand->type; - - switch (type) { - case 0: - break; - - case EMC_TOOL_INIT_TYPE: - tooldata_load(io_tool_table_file); - reload_tool_number(emcioStatus.tool.toolInSpindle); - break; - - case EMC_TOOL_HALT_TYPE: - rtapi_print_msg(RTAPI_MSG_DBG, "EMC_TOOL_HALT\n"); - break; - - case EMC_TOOL_ABORT_TYPE: - // this gets sent on any Task Abort, so it might be safer to stop - // mist and coolant - // spindle should be turned off through motion - rtapi_print_msg(RTAPI_MSG_DBG, "EMC_TOOL_ABORT reason=%d\n",((EMC_TOOL_ABORT *) emcioCommand)->reason); - - emcioStatus.coolant.mist = 0; - emcioStatus.coolant.flood = 0; - *(iocontrol_data->coolant_mist) = 0; // coolant mist output pin - *(iocontrol_data->coolant_flood) = 0; // coolant flood output pin - - if (proto > V1) { - // fix race condition by asserting abort-tool-change before - // deasserting tool-change and tool-prepare - *(iocontrol_data->emc_reason) = ((EMC_TOOL_ABORT *) emcioCommand)->reason; - *(iocontrol_data->emc_abort) = 1; // notify TC of abort condition - } - *(iocontrol_data->tool_change) = 0; // abort tool change if in progress - *(iocontrol_data->tool_prepare) = 0; // abort tool prepare if in progress - *(iocontrol_data->start_change) = 0; - - // indicate state change - waiting for ack line in V2 - // wait-for-ack intermediate state meaningful in V2 mode only - *(iocontrol_data->state) = (proto > V1) ? ST_WAIT_FOR_ABORT_ACK : ST_IDLE; - break; - - case EMC_TOOL_PREPARE_TYPE: - { - int idx = 0; - int toolno = ((EMC_TOOL_PREPARE*)emcioCommand)->tool; - CANON_TOOL_TABLE tdata; - idx = tooldata_find_index_for_tool(toolno); -#ifdef TOOL_NML - if (!random_toolchanger && toolno == 0) { idx = 0; } -#endif - rtapi_print_msg(RTAPI_MSG_DBG, "EMC_TOOL_PREPARE tool=%d pocket=%d\n", toolno, idx); - - // it doesn't make sense to prep the spindle pocket - if (random_toolchanger && idx == 0) { - break; - } - *(iocontrol_data->tool_prep_index) = idx; - if (idx == -1) { // not found - emcioStatus.tool.pocketPrepped = 0; - } else { - if (tooldata_get(&tdata,idx) != IDX_OK) { - UNEXPECTED_MSG; - } - /* set tool number first */ - *(iocontrol_data->tool_prep_pocket) = random_toolchanger? idx: tdata.pocketno; - if (!random_toolchanger && idx == 0) { - *(iocontrol_data->tool_prep_number) = 0; - *(iocontrol_data->tool_prep_pocket) = 0; - } else { - *(iocontrol_data->tool_prep_number) = tdata.toolno; - if (tdata.toolno != toolno) // sanity check - rtapi_print_msg(RTAPI_MSG_DBG, "EMC_TOOL_PREPARE: mismatch: tooltable[%d]=%d, got %d\n", - idx, tdata.toolno, toolno); - } - if ((proto > V1) && *(iocontrol_data->toolchanger_faulted)) { // informational - rtapi_print_msg(RTAPI_MSG_DBG, "%s: prepare: toolchanger faulted (reason=%d), next M6 will %s\n", - progname,toolchanger_reason, - toolchanger_reason > 0 ? "set fault code and reason" : "abort program"); - } - // then set the prepare pin to tell external logic to get started - *(iocontrol_data->tool_prepare) = 1; - *(iocontrol_data->state) = ST_PREPARING; - - // delay fetching the next message until prepare done - if (!(input_status & TI_PREPARE_COMPLETE)) { - emcioStatus.status = RCS_STATUS::EXEC; - } - } - } - break; - - case EMC_TOOL_LOAD_TYPE: - { - rtapi_print_msg(RTAPI_MSG_DBG, "EMC_TOOL_LOAD loaded=%d prepped=%d\n", emcioStatus.tool.toolInSpindle, emcioStatus.tool.pocketPrepped); - - // it doesn't make sense to load a tool from the spindle pocket - if (random_toolchanger && emcioStatus.tool.pocketPrepped == 0) { - break; - } - - // it's not necessary to load the tool already in the spindle - CANON_TOOL_TABLE tdata; - if (tooldata_get(&tdata, emcioStatus.tool.pocketPrepped) != IDX_OK) { - UNEXPECTED_MSG; - } - if (!random_toolchanger && (emcioStatus.tool.pocketPrepped > 0) && - (emcioStatus.tool.toolInSpindle == tdata.toolno) ) { - break; - } - - if (emcioStatus.tool.pocketPrepped != -1) { - //notify HW for toolchange - *(iocontrol_data->tool_change) = 1; - *(iocontrol_data->state) = ST_CHANGING; - - // delay fetching the next message until change done - if (! (input_status & TI_CHANGE_COMPLETE)) { - emcioStatus.status = RCS_STATUS::EXEC; - } - } - break; - } - case EMC_TOOL_START_CHANGE_TYPE: - rtapi_print_msg(RTAPI_MSG_DBG, "EMC_START_CHANGE\n"); - // only handle this if explicitly enabled - less backwards config breakage - if ((proto > V1) && support_start_change) { - *(iocontrol_data->start_change) = 1; - *(iocontrol_data->state) = ST_START_CHANGE; - // delay fetching the next message until ack line seen - if (! (input_status & TI_START_CHANGE_ACKED)) { - emcioStatus.status = RCS_STATUS::EXEC; - } - } - break; - - case EMC_TOOL_UNLOAD_TYPE: - rtapi_print_msg(RTAPI_MSG_DBG, "EMC_TOOL_UNLOAD\n"); - emcioStatus.tool.toolInSpindle = 0; - break; - - case EMC_TOOL_LOAD_TOOL_TABLE_TYPE: - { - const char *filename = - ((EMC_TOOL_LOAD_TOOL_TABLE *) emcioCommand)->file; - if(!strlen(filename)) filename = io_tool_table_file; - rtapi_print_msg(RTAPI_MSG_DBG, "EMC_TOOL_LOAD_TOOL_TABLE\n"); - if (0 != tooldata_load(filename)) { - emcioStatus.status = RCS_STATUS::ERROR; - } else { - reload_tool_number(emcioStatus.tool.toolInSpindle); - } - } - break; - - case EMC_TOOL_SET_OFFSET_TYPE: - { - int idx, toolno, o; - double d, f, b; - EmcPose offs; - - idx = ((EMC_TOOL_SET_OFFSET *) emcioCommand)->pocket; - toolno = ((EMC_TOOL_SET_OFFSET *) emcioCommand)->toolno; - offs = ((EMC_TOOL_SET_OFFSET *) emcioCommand)->offset; - d = ((EMC_TOOL_SET_OFFSET *) emcioCommand)->diameter; - f = ((EMC_TOOL_SET_OFFSET *) emcioCommand)->frontangle; - b = ((EMC_TOOL_SET_OFFSET *) emcioCommand)->backangle; - o = ((EMC_TOOL_SET_OFFSET *) emcioCommand)->orientation; - - rtapi_print_msg(RTAPI_MSG_DBG, - "EMC_TOOL_SET_OFFSET idx=%d toolno=%d zoffset=%lf, " - "xoffset=%lf, diameter=%lf, " - "frontangle=%lf, backangle=%lf, orientation=%d\n", - idx, toolno, offs.tran.z, offs.tran.x, d, f, b, o); - CANON_TOOL_TABLE tdata; - if (tooldata_get(&tdata,idx) != IDX_OK) { - UNEXPECTED_MSG; - } - tdata.toolno = toolno; - tdata.offset = offs; - tdata.diameter = d; - tdata.frontangle = f; - tdata.backangle = b; - tdata.orientation = o; - if (tooldata_put(tdata,idx) == IDX_FAIL) { - UNEXPECTED_MSG; - } - if (0 != tooldata_save(io_tool_table_file)) { - emcioStatus.status = RCS_STATUS::ERROR; - } - if (io_db_mode == DB_ACTIVE) { - int pno = idx; // for random_toolchanger - if (!random_toolchanger) { pno = tdata.pocketno; } - if (tooldata_db_notify(TOOL_OFFSET,toolno,pno,tdata)) { UNEXPECTED_MSG; } - } - } - break; - case EMC_TOOL_SET_NUMBER_TYPE: - { - // changed also in interp_convert.cc to convey the pocket number, not the tool number - // needed so toolTable[0] can be properly set including offsets - int idx; - - idx = ((EMC_TOOL_SET_NUMBER *) emcioCommand)->tool; - CANON_TOOL_TABLE tdata; - if (tooldata_get(&tdata,idx) != IDX_OK) { - UNEXPECTED_MSG; - } - load_tool(idx); - - idx=0; // update spindle (fix legacy behavior) - if (tooldata_get(&tdata,idx) != IDX_OK) { - UNEXPECTED_MSG; - } - emcioStatus.tool.toolInSpindle = tdata.toolno; - rtapi_print_msg(RTAPI_MSG_DBG, - "EMC_TOOL_SET_NUMBER idx=%d old_loaded=%d new_number=%d\n", - idx, emcioStatus.tool.toolInSpindle, tdata.toolno); - //likewise in HAL - *(iocontrol_data->tool_number) = emcioStatus.tool.toolInSpindle; - } - break; - - case EMC_COOLANT_MIST_ON_TYPE: - rtapi_print_msg(RTAPI_MSG_DBG, "EMC_COOLANT_MIST_ON\n"); - emcioStatus.coolant.mist = 1; - *(iocontrol_data->coolant_mist) = 1; - break; - - case EMC_COOLANT_MIST_OFF_TYPE: - rtapi_print_msg(RTAPI_MSG_DBG, "EMC_COOLANT_MIST_OFF\n"); - emcioStatus.coolant.mist = 0; - *(iocontrol_data->coolant_mist) = 0; - break; - - case EMC_COOLANT_FLOOD_ON_TYPE: - rtapi_print_msg(RTAPI_MSG_DBG, "EMC_COOLANT_FLOOD_ON\n"); - emcioStatus.coolant.flood = 1; - *(iocontrol_data->coolant_flood) = 1; - break; - - case EMC_COOLANT_FLOOD_OFF_TYPE: - rtapi_print_msg(RTAPI_MSG_DBG, "EMC_COOLANT_FLOOD_OFF\n"); - emcioStatus.coolant.flood = 0; - *(iocontrol_data->coolant_flood) = 0; - break; - - case EMC_AUX_ESTOP_ON_TYPE: - rtapi_print_msg(RTAPI_MSG_DBG, "EMC_AUX_ESTOP_ON\n"); - /* assert an ESTOP to the outside world (thru HAL) */ - *(iocontrol_data->user_enable_out) = 0; //disable on ESTOP_ON - hal_init_pins(); //resets all HAL pins to safe value - break; - - case EMC_AUX_ESTOP_OFF_TYPE: - rtapi_print_msg(RTAPI_MSG_DBG, "EMC_AUX_ESTOP_OFF\n"); - /* remove ESTOP */ - *(iocontrol_data->user_enable_out) = 1; // we're good to enable on ESTOP_OFF - /* generate a rising edge to reset optional HAL latch */ - *(iocontrol_data->user_request_enable) = 1; - break; - - case EMC_SET_DEBUG_TYPE: - rtapi_print_msg(RTAPI_MSG_DBG, "EMC_SET_DEBUG\n"); - emc_debug = ((EMC_SET_DEBUG *) emcioCommand)->debug; - break; - - default: - rtapi_print("IO: unknown command %s\n", emcSymbolLookup(type)); - break; - } /* switch (type) */ - - // ack for the received command - emcioStatus.command_type = type; - emcioStatus.echo_serial_number = emcioCommand->serial_number; - emcioStatus.reason = toolchanger_reason; // always piggyback current fault code - emcioStatusBuffer->write(&emcioStatus); - - esleep(emc_io_cycle_time); - /* clear reset line to allow for a later rising edge */ - *(iocontrol_data->user_request_enable) = 0; - - } // end of "while (! done)" loop - - if (emcErrorBuffer != 0) { - delete emcErrorBuffer; - emcErrorBuffer = 0; - } - - if (emcioStatusBuffer != 0) { - delete emcioStatusBuffer; - emcioStatusBuffer = 0; - } - - if (emcioCommandBuffer != 0) { - delete emcioCommandBuffer; - emcioCommandBuffer = 0; - } - - rtapi_print("%s: exiting\n",progname); - exit(0); -} diff --git a/src/emc/nml_intf/emc.cc b/src/emc/nml_intf/emc.cc index 2b67bd7b0ea..10dbe999a27 100644 --- a/src/emc/nml_intf/emc.cc +++ b/src/emc/nml_intf/emc.cc @@ -42,12 +42,6 @@ void PmCartesian_update(CMS * cms, PmCartesian * x); int emcFormat(NMLTYPE type, void *buffer, CMS * cms) { switch (type) { - case EMC_AUX_ESTOP_OFF_TYPE: - ((EMC_AUX_ESTOP_OFF *) buffer)->update(cms); - break; - case EMC_AUX_ESTOP_ON_TYPE: - ((EMC_AUX_ESTOP_ON *) buffer)->update(cms); - break; case EMC_AUX_STAT_TYPE: ((EMC_AUX_STAT *) buffer)->update(cms); break; @@ -234,9 +228,6 @@ int emcFormat(NMLTYPE type, void *buffer, CMS * cms) case EMC_TOOL_HALT_TYPE: ((EMC_TOOL_HALT *) buffer)->update(cms); break; - case EMC_TOOL_INIT_TYPE: - ((EMC_TOOL_INIT *) buffer)->update(cms); - break; case EMC_TOOL_LOAD_TYPE: ((EMC_TOOL_LOAD *) buffer)->update(cms); break; @@ -357,10 +348,6 @@ int emcFormat(NMLTYPE type, void *buffer, CMS * cms) const char *emc_symbol_lookup(uint32_t type) { switch (type) { - case EMC_AUX_ESTOP_OFF_TYPE: - return "EMC_AUX_ESTOP_OFF"; - case EMC_AUX_ESTOP_ON_TYPE: - return "EMC_AUX_ESTOP_ON"; case EMC_AUX_STAT_TYPE: return "EMC_AUX_STAT"; case EMC_JOINT_HALT_TYPE: @@ -489,8 +476,6 @@ const char *emc_symbol_lookup(uint32_t type) return "EMC_TOOL_ABORT"; case EMC_TOOL_HALT_TYPE: return "EMC_TOOL_HALT"; - case EMC_TOOL_INIT_TYPE: - return "EMC_TOOL_INIT"; case EMC_TOOL_LOAD_TYPE: return "EMC_TOOL_LOAD"; case EMC_TOOL_LOAD_TOOL_TABLE_TYPE: @@ -616,18 +601,6 @@ void EMC_CMD_MSG::update(CMS * cms) } -/* -* NML/CMS Update function for EMC_AUX_ESTOP_OFF -* Automatically generated by NML CodeGen Java Applet. -* on Sat Oct 11 13:45:16 UTC 2003 -*/ -void EMC_AUX_ESTOP_OFF::update(CMS * cms) -{ - - EMC_AUX_CMD_MSG::update(cms); - -} - /* * NML/CMS Update function for EMC_OPERATOR_DISPLAY * Automatically generated by NML CodeGen Java Applet. @@ -982,18 +955,6 @@ void EMC_JOG_CONT::update(CMS * cms) } -/* -* NML/CMS Update function for EMC_TOOL_INIT -* Automatically generated by NML CodeGen Java Applet. -* on Sat Oct 11 13:45:16 UTC 2003 -*/ -void EMC_TOOL_INIT::update(CMS * cms) -{ - - EMC_TOOL_CMD_MSG::update(cms); - -} - /* * NML/CMS Update function for EMC_MOTION_SET_AOUT * Automatically generated by NML CodeGen Java Applet. @@ -1868,18 +1829,6 @@ void EMC_JOINT_SET_MIN_FERROR::update(CMS * cms) } -/* -* NML/CMS Update function for EMC_AUX_ESTOP_ON -* Automatically generated by NML CodeGen Java Applet. -* on Sat Oct 11 13:45:17 UTC 2003 -*/ -void EMC_AUX_ESTOP_ON::update(CMS * cms) -{ - - EMC_AUX_CMD_MSG::update(cms); - -} - /* * NML/CMS Update function for EMC_NULL * Automatically generated by NML CodeGen Java Applet. diff --git a/src/emc/nml_intf/emc.hh b/src/emc/nml_intf/emc.hh index d1987fcce0c..75f91ebd820 100644 --- a/src/emc/nml_intf/emc.hh +++ b/src/emc/nml_intf/emc.hh @@ -147,7 +147,6 @@ struct PM_CARTESIAN; // EMC_TOOL type declarations -#define EMC_TOOL_INIT_TYPE ((NMLTYPE) 1101) #define EMC_TOOL_HALT_TYPE ((NMLTYPE) 1102) #define EMC_TOOL_ABORT_TYPE ((NMLTYPE) 1103) #define EMC_TOOL_PREPARE_TYPE ((NMLTYPE) 1104) @@ -163,8 +162,6 @@ struct PM_CARTESIAN; #define EMC_TOOL_STAT_TYPE ((NMLTYPE) 1199) // EMC_AUX type declarations -#define EMC_AUX_ESTOP_ON_TYPE ((NMLTYPE) 1206) -#define EMC_AUX_ESTOP_OFF_TYPE ((NMLTYPE) 1207) #define EMC_AUX_INPUT_WAIT_TYPE ((NMLTYPE) 1209) #define EMC_AUX_STAT_TYPE ((NMLTYPE) 1299) @@ -446,9 +443,6 @@ extern int emcCoolantFloodOff(); extern int emcIoInit(); extern int emcIoHalt(); extern int emcIoAbort(int reason); -extern int emcIoSetDebug(int debug); - -extern int emcIoUpdate(EMC_IO_STAT * stat); // implementation functions for EMC aggregate types diff --git a/src/emc/nml_intf/emc_nml.hh b/src/emc/nml_intf/emc_nml.hh index 18e4aa4902d..21e1e6c76a9 100644 --- a/src/emc/nml_intf/emc_nml.hh +++ b/src/emc/nml_intf/emc_nml.hh @@ -1228,16 +1228,6 @@ class EMC_TOOL_CMD_MSG:public RCS_CMD_MSG { void update(CMS * cms); }; -class EMC_TOOL_INIT:public EMC_TOOL_CMD_MSG { - public: - EMC_TOOL_INIT():EMC_TOOL_CMD_MSG(EMC_TOOL_INIT_TYPE, - sizeof(EMC_TOOL_INIT)) { - }; - - // For internal NML/CMS use only. - void update(CMS * cms); -}; - class EMC_TOOL_HALT:public EMC_TOOL_CMD_MSG { public: EMC_TOOL_HALT():EMC_TOOL_CMD_MSG(EMC_TOOL_HALT_TYPE, @@ -1383,26 +1373,6 @@ class EMC_AUX_CMD_MSG:public RCS_CMD_MSG { void update(CMS * cms); }; -class EMC_AUX_ESTOP_ON:public EMC_AUX_CMD_MSG { - public: - EMC_AUX_ESTOP_ON():EMC_AUX_CMD_MSG(EMC_AUX_ESTOP_ON_TYPE, - sizeof(EMC_AUX_ESTOP_ON)) { - }; - - // For internal NML/CMS use only. - void update(CMS * cms); -}; - -class EMC_AUX_ESTOP_OFF:public EMC_AUX_CMD_MSG { - public: - EMC_AUX_ESTOP_OFF():EMC_AUX_CMD_MSG(EMC_AUX_ESTOP_OFF_TYPE, - sizeof(EMC_AUX_ESTOP_OFF)) { - }; - - // For internal NML/CMS use only. - void update(CMS * cms); -}; - class EMC_AUX_INPUT_WAIT:public EMC_AUX_CMD_MSG { public: EMC_AUX_INPUT_WAIT():EMC_AUX_CMD_MSG(EMC_AUX_INPUT_WAIT_TYPE, diff --git a/src/emc/task/emcsvr.cc b/src/emc/task/emcsvr.cc index 6642b126a2b..a9021993da6 100644 --- a/src/emc/task/emcsvr.cc +++ b/src/emc/task/emcsvr.cc @@ -31,8 +31,6 @@ #include "nml_srv.hh" // run_nml_servers() #include -static int tool_channels = 1; - static int iniLoad(const char *filename) { IniFile inifile; @@ -63,7 +61,6 @@ static int iniLoad(const char *filename) } else { // not found, use default } - inifile.Find(&tool_channels,"TOOL_CHANNELS","EMC"); // close it inifile.Close(); @@ -99,8 +96,6 @@ static void daemonize() static RCS_CMD_CHANNEL *emcCommandChannel = NULL; static RCS_STAT_CHANNEL *emcStatusChannel = NULL; static NML *emcErrorChannel = NULL; -static RCS_CMD_CHANNEL *toolCommandChannel = NULL; -static RCS_STAT_CHANNEL *toolStatusChannel = NULL; int main(int argc, char *argv[]) { @@ -123,7 +118,6 @@ int main(int argc, char *argv[]) while (fabs(etime() - start_time) < 10.0 && (emcCommandChannel == NULL || emcStatusChannel == NULL - || (tool_channels && (toolCommandChannel == NULL || toolStatusChannel == NULL)) || emcErrorChannel == NULL) ) { if (NULL == emcCommandChannel) { @@ -142,18 +136,6 @@ int main(int argc, char *argv[]) emcErrorChannel = new NML(nmlErrorFormat, "emcError", "emcsvr", emc_nmlfile); } - if (tool_channels) { - if (NULL == toolCommandChannel) { - toolCommandChannel = - new RCS_CMD_CHANNEL(emcFormat, "toolCmd", "emcsvr", - emc_nmlfile); - } - if (NULL == toolStatusChannel) { - toolStatusChannel = - new RCS_STAT_CHANNEL(emcFormat, "toolSts", "emcsvr", - emc_nmlfile); - } - } if (!emcCommandChannel->valid()) { delete emcCommandChannel; @@ -167,16 +149,6 @@ int main(int argc, char *argv[]) delete emcErrorChannel; emcErrorChannel = NULL; } - if (tool_channels) { - if (!toolCommandChannel->valid()) { - delete toolCommandChannel; - toolCommandChannel = NULL; - } - if (!toolStatusChannel->valid()) { - delete toolStatusChannel; - toolStatusChannel = NULL; - } - } esleep(0.200); } @@ -196,18 +168,6 @@ int main(int argc, char *argv[]) emcErrorChannel = new NML(nmlErrorFormat, "emcError", "emcsvr", emc_nmlfile); } - if (tool_channels) { - if (NULL == toolCommandChannel) { - toolCommandChannel = - new RCS_CMD_CHANNEL(emcFormat, "toolCmd", "emcsvr", - emc_nmlfile); - } - if (NULL == toolStatusChannel) { - toolStatusChannel = - new RCS_STAT_CHANNEL(emcFormat, "toolSts", "emcsvr", - emc_nmlfile); - } - } daemonize(); run_nml_servers(); diff --git a/src/emc/task/emctaskmain.cc b/src/emc/task/emctaskmain.cc index 79a7cdf9d8d..832d4f35cf4 100644 --- a/src/emc/task/emctaskmain.cc +++ b/src/emc/task/emctaskmain.cc @@ -830,7 +830,7 @@ static int emcTaskPlan(void) case EMC_MOTION_SET_AOUT_TYPE: case EMC_TRAJ_RIGID_TAP_TYPE: case EMC_TRAJ_SET_TELEOP_ENABLE_TYPE: - case EMC_SET_DEBUG_TYPE: + case EMC_SET_DEBUG_TYPE: retval = emcTaskIssueCommand(emcCommand); break; @@ -945,7 +945,7 @@ static int emcTaskPlan(void) case EMC_MOTION_ADAPTIVE_TYPE: case EMC_TRAJ_RIGID_TAP_TYPE: case EMC_TRAJ_SET_TELEOP_ENABLE_TYPE: - case EMC_SET_DEBUG_TYPE: + case EMC_SET_DEBUG_TYPE: retval = emcTaskIssueCommand(emcCommand); break; @@ -1288,7 +1288,7 @@ static int emcTaskPlan(void) case EMC_TRAJ_PROBE_TYPE: case EMC_AUX_INPUT_WAIT_TYPE: case EMC_TRAJ_RIGID_TAP_TYPE: - case EMC_SET_DEBUG_TYPE: + case EMC_SET_DEBUG_TYPE: case EMC_COOLANT_MIST_ON_TYPE: case EMC_COOLANT_MIST_OFF_TYPE: case EMC_COOLANT_FLOOD_ON_TYPE: @@ -1380,7 +1380,7 @@ static int emcTaskPlan(void) case EMC_MOTION_SET_AOUT_TYPE: case EMC_MOTION_ADAPTIVE_TYPE: case EMC_TRAJ_RIGID_TAP_TYPE: - case EMC_SET_DEBUG_TYPE: + case EMC_SET_DEBUG_TYPE: retval = emcTaskIssueCommand(emcCommand); break; @@ -1920,8 +1920,7 @@ static int emcTaskIssueCommand(NMLmsg * cmd) case EMC_SET_DEBUG_TYPE: /* set the debug level here */ emc_debug = ((EMC_SET_DEBUG *) cmd)->debug; - /* and in IO and motion */ - emcIoSetDebug(emc_debug); + /* and motion */ emcMotionSetDebug(emc_debug); /* and reflect it in the status-- this isn't updated continually */ emcStatus->debug = emc_debug; @@ -2390,7 +2389,7 @@ static EMC_TASK_EXEC emcTaskCheckPostconditions(NMLmsg * cmd) case EMC_SPINDLE_ON_TYPE: case EMC_SPINDLE_OFF_TYPE: case EMC_SPINDLE_ORIENT_TYPE: - case EMC_COOLANT_MIST_ON_TYPE: + case EMC_COOLANT_MIST_ON_TYPE: case EMC_COOLANT_MIST_OFF_TYPE: case EMC_COOLANT_FLOOD_ON_TYPE: case EMC_COOLANT_FLOOD_OFF_TYPE: @@ -2924,26 +2923,6 @@ static int emctask_startup() return -1; } - end = RETRY_TIME; - good = 0; - do { - if (0 == emcIoUpdate(&emcStatus->io)) { - good = 1; - break; - } - esleep(RETRY_INTERVAL); - end -= RETRY_INTERVAL; - if (done) { - emctask_shutdown(); - exit(1); - } - } while (end > 0.0); - if (!good) { - rcs_print_error("can't read IO status\n"); - return -1; - } - - // now motion end = RETRY_TIME; @@ -3246,16 +3225,14 @@ int main(int argc, char *argv[]) // moved up from emc_startup so we can expose it in Python right away emcStatus = new EMC_STAT; -#ifdef TOOL_NML //{ - tool_nml_register( (CANON_TOOL_TABLE*)&emcStatus->io.tool.toolTable); -#else //}{ - tool_mmap_user(); - // initialize database tool finder: -#endif //} // get the Python plugin going // inistantiate task methods object, too - emcTaskOnce(emc_inifile); + if (emcTaskOnce(emc_inifile, emcStatus->io)) { + rcs_print_error("can't initialize task object / HAL\n"); + emctask_shutdown(); + exit(1); + } rtapi_strxcpy(emcStatus->task.ini_filename, emc_inifile); if (task_methods == NULL) { set_rcs_print_destination(RCS_PRINT_TO_STDOUT); // restore diag @@ -3310,7 +3287,6 @@ int main(int argc, char *argv[]) } // update subordinate status - emcIoUpdate(&emcStatus->io); emcMotionUpdate(&emcStatus->motion); // synchronize subordinate states if (emcStatus->io.aux.estop) { @@ -3495,6 +3471,7 @@ int main(int argc, char *argv[]) } else { timer->wait(); } + task_methods->run(); } // end of while (! done) diff --git a/src/emc/task/task.hh b/src/emc/task/task.hh index 79f868e71a2..287f394fcb1 100644 --- a/src/emc/task/task.hh +++ b/src/emc/task/task.hh @@ -16,11 +16,12 @@ #ifndef EMC_TASK_HH #define EMC_TASK_HH #include "taskclass.hh" +#include "emc_nml.hh" extern NMLmsg *emcTaskCommand; extern int stepping; extern int steppingWait; extern int emcTaskQueueCommand(NMLmsg *cmd); -extern int emcTaskOnce(const char *inifile); +extern int emcTaskOnce(const char *inifile, EMC_IO_STAT &emcioStatus); // Returns 0 if all joints are homed, 1 if any joints are un-homed. int all_homed(void); diff --git a/src/emc/task/taskclass.cc b/src/emc/task/taskclass.cc index 276fbf8f2c6..3c956045892 100644 --- a/src/emc/task/taskclass.cc +++ b/src/emc/task/taskclass.cc @@ -22,224 +22,242 @@ #include "rcs.hh" // RCS_CMD_CHANNEL, etc. #include "rcs_print.hh" #include "timer.hh" // esleep, etc. -#include "emc.hh" // EMC NML -#include "emc_nml.hh" #include "emcglb.h" // EMC_INIFILE #include "python_plugin.hh" #include "taskclass.hh" #include -Task *task_methods; - -// IO INTERFACE - -// the NML channels to the EMCIO controller -static RCS_CMD_CHANNEL *emcIoCommandBuffer = 0; -static RCS_STAT_CHANNEL *emcIoStatusBuffer = 0; - -// global status structure -EMC_IO_STAT *emcIoStatus = 0; - -// serial number for communication -static int emcIoCommandSerialNumber = 0; -static double EMCIO_BUFFER_GET_TIMEOUT = 5.0; - -static int forceCommand(RCS_CMD_MSG *msg); +#include "tooldata.hh" +#include "hal.h" -static int emcioNmlGet() +/******************************************************************** +* +* Description: iocontrol_hal_init(void) +* +* Side Effects: Exports HAL pins. +* +* Called By: main +********************************************************************/ +int Task::iocontrol_hal_init(void) { - int retval = 0; - double start_time; - RCS_PRINT_DESTINATION_TYPE orig_dest; - if (emcIoCommandBuffer == 0) { - orig_dest = get_rcs_print_destination(); - set_rcs_print_destination(RCS_PRINT_TO_NULL); - start_time = etime(); - while (start_time - etime() < EMCIO_BUFFER_GET_TIMEOUT) { - emcIoCommandBuffer = - new RCS_CMD_CHANNEL(emcFormat, "toolCmd", "emc", - emc_nmlfile); - if (!emcIoCommandBuffer->valid()) { - delete emcIoCommandBuffer; - emcIoCommandBuffer = 0; - } else { - break; - } - esleep(0.1); - } - set_rcs_print_destination(orig_dest); + int n = 0, retval; //n - number of the hal component (only one for iocotrol) + + /* STEP 1: initialise the hal component */ + comp_id = hal_init("iocontrol"); + if (comp_id < 0) { + rtapi_print_msg(RTAPI_MSG_ERR, + "IOCONTROL: ERROR: hal_init() failed\n"); + return -1; } - if (emcIoCommandBuffer == 0) { - emcIoCommandBuffer = - new RCS_CMD_CHANNEL(emcFormat, "toolCmd", "emc", emc_nmlfile); - if (!emcIoCommandBuffer->valid()) { - delete emcIoCommandBuffer; - emcIoCommandBuffer = 0; - retval = -1; - } + /* STEP 2: allocate shared memory for iocontrol data */ + iocontrol_data = (iocontrol_str *) hal_malloc(sizeof(iocontrol_str)); + if (iocontrol_data == 0) { + rtapi_print_msg(RTAPI_MSG_ERR, "IOCONTROL: ERROR: hal_malloc() failed\n"); + hal_exit(comp_id); + return -1; } - if (emcIoStatusBuffer == 0) { - orig_dest = get_rcs_print_destination(); - set_rcs_print_destination(RCS_PRINT_TO_NULL); - start_time = etime(); - while (start_time - etime() < EMCIO_BUFFER_GET_TIMEOUT) { - emcIoStatusBuffer = - new RCS_STAT_CHANNEL(emcFormat, "toolSts", "emc", - emc_nmlfile); - if (!emcIoStatusBuffer->valid()) { - delete emcIoStatusBuffer; - emcIoStatusBuffer = 0; - } else { - emcIoStatus = - (EMC_IO_STAT *) emcIoStatusBuffer->get_address(); - // capture serial number for next send - emcIoCommandSerialNumber = emcIoStatus->echo_serial_number; - break; - } - esleep(0.1); - } - set_rcs_print_destination(orig_dest); + /* STEP 3a: export the out-pin(s) */ + + // user-enable-out + retval = hal_pin_bit_newf(HAL_OUT, &(iocontrol_data->user_enable_out), comp_id, + "iocontrol.%d.user-enable-out", n); + if (retval < 0) { + rtapi_print_msg(RTAPI_MSG_ERR, + "IOCONTROL: ERROR: iocontrol %d pin user-enable-out export failed with err=%i\n", + n, retval); + hal_exit(comp_id); + return -1; } - - if (emcIoStatusBuffer == 0) { - emcIoStatusBuffer = - new RCS_STAT_CHANNEL(emcFormat, "toolSts", "emc", emc_nmlfile); - if (!emcIoStatusBuffer->valid() - || EMC_IO_STAT_TYPE != emcIoStatusBuffer->peek()) { - delete emcIoStatusBuffer; - emcIoStatusBuffer = 0; - emcIoStatus = 0; - retval = -1; - } else { - emcIoStatus = (EMC_IO_STAT *) emcIoStatusBuffer->get_address(); - // capture serial number for next send - emcIoCommandSerialNumber = emcIoStatus->echo_serial_number; - } + // user-request-enable + retval = hal_pin_bit_newf(HAL_OUT, &(iocontrol_data->user_request_enable), comp_id, + "iocontrol.%d.user-request-enable", n); + if (retval < 0) { + rtapi_print_msg(RTAPI_MSG_ERR, + "IOCONTROL: ERROR: iocontrol %d pin user-request-enable export failed with err=%i\n", + n, retval); + hal_exit(comp_id); + return -1; } - - return retval; -} - -static RCS_CMD_MSG *last_io_command = 0; -static long largest_io_command_size = 0; - -/* - sendCommand() waits until any currently executing command has finished, - then writes the given command.*/ -/*! \todo - FIXME: Not very RCS-like to wait for status done here. (wps) -*/ -static int sendCommand(RCS_CMD_MSG * msg) -{ - // need command buffer to be there - if (0 == emcIoCommandBuffer) { - return -1; + // coolant-flood + retval = hal_pin_bit_newf(HAL_OUT, &(iocontrol_data->coolant_flood), comp_id, + "iocontrol.%d.coolant-flood", n); + if (retval < 0) { + rtapi_print_msg(RTAPI_MSG_ERR, + "IOCONTROL: ERROR: iocontrol %d pin coolant-flood export failed with err=%i\n", + n, retval); + hal_exit(comp_id); + return -1; } - // need status buffer also, to check for command received - if (0 == emcIoStatusBuffer || !emcIoStatusBuffer->valid()) { - return -1; + // coolant-mist + retval = hal_pin_bit_newf(HAL_OUT, &(iocontrol_data->coolant_mist), comp_id, + "iocontrol.%d.coolant-mist", n); + if (retval < 0) { + rtapi_print_msg(RTAPI_MSG_ERR, + "IOCONTROL: ERROR: iocontrol %d pin coolant-mist export failed with err=%i\n", + n, retval); + hal_exit(comp_id); + return -1; } - - // always force-queue an abort - if (msg->type == EMC_TOOL_ABORT_TYPE) { - // just queue the abort and call it a day - int rc = forceCommand(msg); - if (rc) { - rcs_print_error("forceCommand(EMC_TOOL_ABORT) returned %d\n", rc); - } - return 0; + // lube + retval = hal_pin_bit_newf(HAL_OUT, &(iocontrol_data->lube), comp_id, + "iocontrol.%d.lube", n); + if (retval < 0) { + rtapi_print_msg(RTAPI_MSG_ERR, + "IOCONTROL: ERROR: iocontrol %d pin lube export failed with err=%i\n", + n, retval); + hal_exit(comp_id); + return -1; } - - double send_command_timeout = etime() + 5.0; - - // check if we're executing, and wait until we're done - while (etime() < send_command_timeout) { - emcIoStatusBuffer->peek(); - if (emcIoStatus->echo_serial_number != emcIoCommandSerialNumber || - emcIoStatus->status == RCS_STATUS::EXEC) { - esleep(0.001); - continue; - } else { - break; - } + // tool-prepare + retval = hal_pin_bit_newf(HAL_OUT, &(iocontrol_data->tool_prepare), comp_id, + "iocontrol.%d.tool-prepare", n); + if (retval < 0) { + rtapi_print_msg(RTAPI_MSG_ERR, + "IOCONTROL: ERROR: iocontrol %d pin tool-prepare export failed with err=%i\n", + n, retval); + hal_exit(comp_id); + return -1; } - - if (emcIoStatus->echo_serial_number != emcIoCommandSerialNumber || - emcIoStatus->status == RCS_STATUS::EXEC) { - // Still not done, must have timed out. - rcs_print_error - ("Command to IO level (%s:%s) timed out waiting for last command done. \n", - emcSymbolLookup(msg->type), emcIoCommandBuffer->msg2str(msg)); - rcs_print_error - ("emcIoStatus->echo_serial_number=%d, emcIoCommandSerialNumber=%d, emcIoStatus->status=%d\n", - emcIoStatus->echo_serial_number, emcIoCommandSerialNumber, - emcIoStatus->status); - if (0 != last_io_command) { - rcs_print_error("Last command sent to IO level was (%s:%s)\n", - emcSymbolLookup(last_io_command->type), - emcIoCommandBuffer->msg2str(last_io_command)); - } - return -1; + // tool-number + retval = hal_pin_s32_newf(HAL_OUT, &(iocontrol_data->tool_number), comp_id, + "iocontrol.%d.tool-number", n); + if (retval < 0) { + rtapi_print_msg(RTAPI_MSG_ERR, + "IOCONTROL: ERROR: iocontrol %d pin tool-number export failed with err=%i\n", + n, retval); + hal_exit(comp_id); + return -1; } - // now we can send - msg->serial_number = ++emcIoCommandSerialNumber; - if (0 != emcIoCommandBuffer->write(msg)) { - rcs_print_error("Failed to send command to IO level (%s:%s)\n", - emcSymbolLookup(msg->type), - emcIoCommandBuffer->msg2str(msg)); - return -1; + // tool-prep-number + retval = hal_pin_s32_newf(HAL_OUT, &(iocontrol_data->tool_prep_number), comp_id, + "iocontrol.%d.tool-prep-number", n); + if (retval < 0) { + rtapi_print_msg(RTAPI_MSG_ERR, + "IOCONTROL: ERROR: iocontrol %d pin tool-prep-number export failed with err=%i\n", + n, retval); + hal_exit(comp_id); + return -1; } - if (largest_io_command_size < msg->size) { - largest_io_command_size = std::max(msg->size, 4096); - last_io_command = (RCS_CMD_MSG *) realloc(last_io_command, largest_io_command_size); + // tool-prep-index (idx) + retval = hal_pin_s32_newf(HAL_OUT, &(iocontrol_data->tool_prep_index), comp_id, + "iocontrol.%d.tool-prep-index", n); + if (retval < 0) { + rtapi_print_msg(RTAPI_MSG_ERR, + "IOCONTROL: ERROR: iocontrol %d pin tool-prep-index export failed with err=%i\n", + n, retval); + hal_exit(comp_id); + return -1; } - if (0 != last_io_command) { - memcpy(last_io_command, msg, msg->size); + // tool-prep-pocket + retval = hal_pin_s32_newf(HAL_OUT, &(iocontrol_data->tool_prep_pocket), comp_id, + "iocontrol.%d.tool-prep-pocket", n); + if (retval < 0) { + rtapi_print_msg(RTAPI_MSG_ERR, + "IOCONTROL: ERROR: iocontrol %d pin tool-prep-pocket export failed with err=%i\n", + n, retval); + hal_exit(comp_id); + return -1; } - - return 0; -} - -/* - forceCommand() writes the given command regardless of the executing - status of any previous command. -*/ -static int forceCommand(RCS_CMD_MSG * msg) -{ - // need command buffer to be there - if (0 == emcIoCommandBuffer) { - return -1; + // tool-from-pocket + retval = hal_pin_s32_newf(HAL_OUT, &(iocontrol_data->tool_from_pocket), comp_id, + "iocontrol.%d.tool-from-pocket", n); + if (retval < 0) { + rtapi_print_msg(RTAPI_MSG_ERR, + "IOCONTROL: ERROR: iocontrol %d pin tool-from-pocket export failed with err=%i\n", + n, retval); + hal_exit(comp_id); + return -1; } - // need status buffer also, to check for command received - if (0 == emcIoStatusBuffer || !emcIoStatusBuffer->valid()) { - return -1; + // tool-prepared + retval = hal_pin_bit_newf(HAL_IN, &(iocontrol_data->tool_prepared), comp_id, + "iocontrol.%d.tool-prepared", n); + if (retval < 0) { + rtapi_print_msg(RTAPI_MSG_ERR, + "IOCONTROL: ERROR: iocontrol %d pin tool-prepared export failed with err=%i\n", + n, retval); + hal_exit(comp_id); + return -1; } - // send it immediately - msg->serial_number = ++emcIoCommandSerialNumber; - if (0 != emcIoCommandBuffer->write(msg)) { - rcs_print_error("Failed to send command to IO level (%s:%s)\n", - emcSymbolLookup(msg->type), - emcIoCommandBuffer->msg2str(msg)); - return -1; + // tool-change + retval = hal_pin_bit_newf(HAL_OUT, &(iocontrol_data->tool_change), comp_id, + "iocontrol.%d.tool-change", n); + if (retval < 0) { + rtapi_print_msg(RTAPI_MSG_ERR, + "IOCONTROL: ERROR: iocontrol %d pin tool-change export failed with err=%i\n", + n, retval); + hal_exit(comp_id); + return -1; } - - if (largest_io_command_size < msg->size) { - largest_io_command_size = std::max(msg->size, 4096); - last_io_command = (RCS_CMD_MSG *) realloc(last_io_command, largest_io_command_size); + // tool-changed + retval = hal_pin_bit_newf(HAL_IN, &(iocontrol_data->tool_changed), comp_id, + "iocontrol.%d.tool-changed", n); + if (retval < 0) { + rtapi_print_msg(RTAPI_MSG_ERR, + "IOCONTROL: ERROR: iocontrol %d pin tool-changed export failed with err=%i\n", + n, retval); + hal_exit(comp_id); + return -1; } - - if (0 != last_io_command) { - memcpy(last_io_command, msg, msg->size); + /* STEP 3b: export the in-pin(s) */ + + // emc-enable-in + retval = hal_pin_bit_newf(HAL_IN, &(iocontrol_data->emc_enable_in), comp_id, + "iocontrol.%d.emc-enable-in", n); + if (retval < 0) { + rtapi_print_msg(RTAPI_MSG_ERR, + "IOCONTROL: ERROR: iocontrol %d pin emc-enable-in export failed with err=%i\n", + n, retval); + hal_exit(comp_id); + return -1; } - + // lube_level + retval = hal_pin_bit_newf(HAL_IN, &(iocontrol_data->lube_level), comp_id, + "iocontrol.%d.lube_level", n); + if (retval < 0) { + rtapi_print_msg(RTAPI_MSG_ERR, + "IOCONTROL: ERROR: iocontrol %d pin lube_level export failed with err=%i\n", + n, retval); + hal_exit(comp_id); + return -1; + } + *(iocontrol_data->tool_number) = emcioStatus.tool.toolInSpindle; + hal_ready(comp_id); return 0; } +/******************************************************************** +* +* Description: hal_init_pins(void) +* +* Side Effects: Sets HAL pins default values. +* +* Called By: main +********************************************************************/ +void Task::hal_init_pins(void) +{ + *(iocontrol_data->user_enable_out)=0; /* output, FALSE when EMC wants stop */ + *(iocontrol_data->user_request_enable)=0;/* output, used to reset HAL latch */ + *(iocontrol_data->coolant_mist)=0; /* coolant mist output pin */ + *(iocontrol_data->coolant_flood)=0; /* coolant flood output pin */ + *(iocontrol_data->lube)=0; /* lube output pin */ + *(iocontrol_data->tool_prepare)=0; /* output, pin that notifies HAL it needs to prepare a tool */ + *(iocontrol_data->tool_prep_number)=0; /* output, pin that holds the tool number to be prepared, only valid when tool-prepare=TRUE */ + *(iocontrol_data->tool_prep_pocket)=0; /* output, pin that holds the pocketno for the tool to be prepared, only valid when tool-prepare=TRUE */ + *(iocontrol_data->tool_from_pocket)=0; /* output, always 0 at startup */ + *iocontrol_data->tool_prep_index=0; /* output, pin that holds the internal index (idx) of the tool to be prepared, for debug */ + *(iocontrol_data->tool_change)=0; /* output, notifies a tool-change should happen (emc should be in the tool-change position) */ +} + +Task *task_methods; + +// global status structure +EMC_IO_STAT *emcIoStatus = 0; + // glue int emcIoInit() { return task_methods->emcIoInit(); } @@ -250,7 +268,6 @@ int emcIoHalt() { int emcIoAbort(int reason) { return task_methods->emcIoAbort(reason); } -int emcIoSetDebug(int debug) { return task_methods->emcIoSetDebug(debug); } int emcAuxEstopOn() { return task_methods->emcAuxEstopOn(); } int emcAuxEstopOff() { return task_methods->emcAuxEstopOff(); } int emcCoolantMistOn() { return task_methods->emcCoolantMistOn(); } @@ -267,11 +284,13 @@ int emcToolSetOffset(int pocket, int toolno, EmcPose offset, double diameter, return task_methods->emcToolSetOffset( pocket, toolno, offset, diameter, frontangle, backangle, orientation); } int emcToolSetNumber(int number) { return task_methods->emcToolSetNumber(number); } -int emcIoUpdate(EMC_IO_STAT * stat) { return task_methods->emcIoUpdate(stat); } -int emcTaskOnce(const char *filename) +int emcTaskOnce(const char *filename, EMC_IO_STAT &emcioStatus) { - task_methods = new Task(); + task_methods = new Task(emcioStatus); + if (int res = task_methods->iocontrol_hal_init()) { + return res; + } return 0; } @@ -285,7 +304,11 @@ struct _inittab builtin_modules[] = { { NULL, NULL } }; -Task::Task() : random_toolchanger(0) { +Task::Task(EMC_IO_STAT & emcioStatus_in) : + emcioStatus(emcioStatus_in), + random_toolchanger(0), + ini_filename(emc_inifile) + { IniFile inifile; @@ -297,6 +320,37 @@ Task::Task() : random_toolchanger(0) { if ((t = inifile.Find("TOOL_TABLE", "EMCIO")) != NULL) tooltable_filename = strdup(t); } + tool_mmap_creator((EMC_TOOL_STAT*)&(emcioStatus.tool), random_toolchanger); +#ifdef TOOL_NML //{ + tool_nml_register( (CANON_TOOL_TABLE*)&emcStatus->io.tool.toolTable); +#else //}{ + tool_mmap_user(); + // initialize database tool finder: +#endif //} + emcioStatus.status = RCS_STATUS::DONE;//TODO?? + tooldata_init(random_toolchanger); + emcioStatus.tool.pocketPrepped = -1; + if(!random_toolchanger) { + CANON_TOOL_TABLE tdata = tooldata_entry_init(); + tdata.pocketno = 0; //nonrandom init + tdata.toolno = -1; //nonrandom init + if (tooldata_put(tdata,0) != IDX_OK) { + UNEXPECTED_MSG; + } + } + if (0 != tooldata_load(tooltable_filename)) { + rcs_print_error("can't load tool table.\n"); + } + + if (random_toolchanger) { + CANON_TOOL_TABLE tdata; + if (tooldata_get(&tdata,0) != IDX_OK) { + UNEXPECTED_MSG;//todo: handle error + } + emcioStatus.tool.toolInSpindle = tdata.toolno; + } else { + emcioStatus.tool.toolInSpindle = 0; + } }; @@ -379,249 +433,390 @@ static int iniTool(const char *filename) return retval; } +void Task::load_tool(int idx) { + CANON_TOOL_TABLE tdata; + if(random_toolchanger) { + // swap the tools between the desired pocket and the spindle pocket + + CANON_TOOL_TABLE tzero,tpocket; + if ( tooldata_get(&tzero,0 ) != IDX_OK + || tooldata_get(&tpocket,idx) != IDX_OK) { + UNEXPECTED_MSG; return; + } + // spindle-->pocket (specified by idx) + tooldata_db_notify(SPINDLE_UNLOAD,tzero.toolno,idx,tzero); + tzero.pocketno = tpocket.pocketno; + if (tooldata_put(tzero,idx) != IDX_OK) { + UNEXPECTED_MSG; + } + + // pocket-->spindle (idx==0) + tooldata_db_notify(SPINDLE_LOAD,tpocket.toolno,0,tpocket); + tpocket.pocketno = 0; + if (tooldata_put(tpocket,0) != IDX_OK) { + UNEXPECTED_MSG; + } + + if (0 != tooldata_save(tooltable_filename)) { + emcioStatus.status = RCS_STATUS::ERROR; + } + } else if(idx == 0) { + // on non-random tool-changers, asking for pocket 0 is the secret + // handshake for "unload the tool from the spindle" + tdata = tooldata_entry_init(); + tdata.toolno = 0; // nonrandom unload tool from spindle + tdata.pocketno = 0; // nonrandom unload tool from spindle + if (tooldata_put(tdata,0) != IDX_OK) { + UNEXPECTED_MSG; return; + } + if (tooldata_db_notify(SPINDLE_UNLOAD,0,0,tdata)) { UNEXPECTED_MSG; } + } else { + // just copy the desired tool to the spindle + if (tooldata_get(&tdata,idx) != IDX_OK) { + UNEXPECTED_MSG; return; + } + if (tooldata_put(tdata,0) != IDX_OK) { + UNEXPECTED_MSG; return; + } + // notify idx==0 tool in spindle: + CANON_TOOL_TABLE temp; + if (tooldata_get(&temp,0) != IDX_OK) { UNEXPECTED_MSG; } + if (tooldata_db_notify(SPINDLE_LOAD,temp.toolno,0,temp)) { UNEXPECTED_MSG; } + } +} // load_tool() + +void Task::reload_tool_number(int toolno) { + CANON_TOOL_TABLE tdata; + if(random_toolchanger) return; // doesn't need special handling here + for(int idx = 1; idx <= tooldata_last_index_get(); idx++) { //note <= + if (tooldata_get(&tdata,idx) != IDX_OK) { + UNEXPECTED_MSG; return; + } + if(tdata.toolno == toolno) { + load_tool(idx); + break; + } + } +} + // NML commands -int Task::emcIoInit() +int Task::emcIoInit()//EMC_TOOL_INIT { - EMC_TOOL_INIT ioInitMsg; - - // get NML buffer to emcio - if (0 != emcioNmlGet()) { - rcs_print_error("emcioNmlGet() failed.\n"); - return -1; - } + tooldata_load(tooltable_filename); + reload_tool_number(emcioStatus.tool.toolInSpindle); if (0 != iniTool(emc_inifile)) { return -1; } - - // send init command to emcio - if (forceCommand(&ioInitMsg)) { - rcs_print_error("Can't forceCommand(ioInitMsg)\n"); - return -1; - } - return 0; } int Task::emcIoHalt() { - EMC_TOOL_HALT ioHaltMsg; - - // send halt command to emcio - if (emcIoCommandBuffer != 0) { - forceCommand(&ioHaltMsg); - } - // clear out the buffers - - if (emcIoStatusBuffer != 0) { - delete emcIoStatusBuffer; - emcIoStatusBuffer = 0; - emcIoStatus = 0; - } - - if (emcIoCommandBuffer != 0) { - delete emcIoCommandBuffer; - emcIoCommandBuffer = 0; - } - - if (last_io_command) { - free(last_io_command); - last_io_command = 0; - } return 0; } -int Task::emcIoAbort(int reason) +int Task::emcIoAbort(int reason)//EMC_TOOL_ABORT_TYPE { - EMC_TOOL_ABORT ioAbortMsg; - - ioAbortMsg.reason = reason; - // send abort command to emcio - sendCommand(&ioAbortMsg); - + // only used in v2 + // this gets sent on any Task Abort, so it might be safer to stop + // the spindle and coolant + rtapi_print_msg(RTAPI_MSG_DBG, "EMC_TOOL_ABORT\n"); + emcioStatus.coolant.mist = 0; + emcioStatus.coolant.flood = 0; + *(iocontrol_data->coolant_mist)=0; /* coolant mist output pin */ + *(iocontrol_data->coolant_flood)=0; /* coolant flood output pin */ + *(iocontrol_data->tool_change)=0; /* abort tool change if in progress */ + *(iocontrol_data->tool_prepare)=0; /* abort tool prepare if in progress */ return 0; } -int Task::emcIoSetDebug(int debug) +int Task::emcAuxEstopOn()//EMC_AUX_ESTOP_ON_TYPE { - EMC_SET_DEBUG ioDebugMsg; - - ioDebugMsg.debug = debug; - - return sendCommand(&ioDebugMsg); -} - -int Task::emcAuxEstopOn() -{ - EMC_AUX_ESTOP_ON estopOnMsg; - - return forceCommand(&estopOnMsg); + /* assert an ESTOP to the outside world (thru HAL) */ + *(iocontrol_data->user_enable_out) = 0; //disable on ESTOP_ON + hal_init_pins(); //resets all HAL pins to safe valuea + return 0; } int Task::emcAuxEstopOff() { - EMC_AUX_ESTOP_OFF estopOffMsg; - - return forceCommand(&estopOffMsg); //force the EstopOff message + /* remove ESTOP */ + *(iocontrol_data->user_enable_out) = 1; //we're good to enable on ESTOP_OFF + /* generate a rising edge to reset optional HAL latch */ + *(iocontrol_data->user_request_enable) = 1; + emcioStatus.aux.estop = 0; + return 0; } int Task::emcCoolantMistOn() { - EMC_COOLANT_MIST_ON mistOnMsg; - - sendCommand(&mistOnMsg); - + emcioStatus.coolant.mist = 1; + *(iocontrol_data->coolant_mist) = 1; return 0; } int Task::emcCoolantMistOff() { - EMC_COOLANT_MIST_OFF mistOffMsg; - - sendCommand(&mistOffMsg); - + emcioStatus.coolant.mist = 0; + *(iocontrol_data->coolant_mist) = 0; return 0; } int Task::emcCoolantFloodOn() { - EMC_COOLANT_FLOOD_ON floodOnMsg; - - sendCommand(&floodOnMsg); - + emcioStatus.coolant.flood = 1; + *(iocontrol_data->coolant_flood) = 1; return 0; } int Task::emcCoolantFloodOff() { - EMC_COOLANT_FLOOD_OFF floodOffMsg; - - sendCommand(&floodOffMsg); - + emcioStatus.coolant.flood = 0; + *(iocontrol_data->coolant_flood) = 0; return 0; } -int Task::emcToolPrepare(int tool) +int Task::emcToolPrepare(int toolno) { - EMC_TOOL_PREPARE toolPrepareMsg; - - toolPrepareMsg.tool = tool; - sendCommand(&toolPrepareMsg); + int idx = 0; + CANON_TOOL_TABLE tdata; + idx = tooldata_find_index_for_tool(toolno); +#ifdef TOOL_NML + if (!random_toolchanger && toolno == 0) { idx = 0; } +#endif + if (idx == -1) { // not found + emcioStatus.tool.pocketPrepped = -1; + } else { + if (tooldata_get(&tdata,idx) != IDX_OK) { + UNEXPECTED_MSG; + } + rtapi_print_msg(RTAPI_MSG_DBG, "EMC_TOOL_PREPARE tool=%d idx=%d\n", toolno, idx); + + *(iocontrol_data->tool_prep_index) = idx; // any type of changer + + // Note: some of the following logic could be simplified + // but is maintained to preserve runtests expectations + // Set HAL pins for tool number, pocket, and index. + if (random_toolchanger) { + // RANDOM_TOOLCHANGER + *(iocontrol_data->tool_prep_number) = tdata.toolno; + if (idx == 0) { + emcioStatus.tool.pocketPrepped = 0; // pocketPrepped is an idx + *(iocontrol_data->tool_prep_pocket) = 0; + return 0; + } + *(iocontrol_data->tool_prep_pocket) = tdata.pocketno; + } else { + // NON_RANDOM_TOOLCHANGER + if (idx == 0) { + emcioStatus.tool.pocketPrepped = 0; // pocketPrepped is an idx + *(iocontrol_data->tool_prep_number) = 0; + *(iocontrol_data->tool_prep_pocket) = 0; + } else { + *(iocontrol_data->tool_prep_number) = tdata.toolno; + *(iocontrol_data->tool_prep_pocket) = tdata.pocketno; + } + } + // it doesn't make sense to prep the spindle pocket + if (random_toolchanger && idx == 0) { + emcioStatus.tool.pocketPrepped = 0; // idx + return 0; + } + } + /* then set the prepare pin to tell external logic to get started */ + *(iocontrol_data->tool_prepare) = 1; + // the feedback logic is done inside read_hal_inputs() + // we only need to set RCS_EXEC if RCS_DONE is not already set by the above logic + if (tool_status != 10) //set above to 10 in case PREP already finished (HAL loopback machine) + emcioStatus.status = RCS_STATUS::EXEC; return 0; } -int Task::emcToolStartChange() +int Task::emcToolStartChange()//EMC_TOOL_START_CHANGE_TYPE { - EMC_TOOL_START_CHANGE toolStartChangeMsg; - - sendCommand(&toolStartChangeMsg); - return 0; } -int Task::emcToolLoad() +int Task::emcToolLoad()//EMC_TOOL_LOAD_TYPE { - EMC_TOOL_LOAD toolLoadMsg; + // it doesn't make sense to load a tool from the spindle pocket + if (random_toolchanger && emcioStatus.tool.pocketPrepped == 0) { + return 0; + } - sendCommand(&toolLoadMsg); + // it's not necessary to load the tool already in the spindle + CANON_TOOL_TABLE tdata; + if (tooldata_get(&tdata, emcioStatus.tool.pocketPrepped) != IDX_OK) { + UNEXPECTED_MSG; + } + if (!random_toolchanger && (emcioStatus.tool.pocketPrepped > 0) && + (emcioStatus.tool.toolInSpindle == tdata.toolno) ) { + return 0; + } + if (emcioStatus.tool.pocketPrepped != -1) { + //notify HW for toolchange + *(iocontrol_data->tool_change) = 1; + // the feedback logic is done inside read_hal_inputs() we only + // need to set RCS_EXEC if RCS_DONE is not already set by the + // above logic + if (tool_status != 11) + // set above to 11 in case LOAD already finished (HAL + // loopback machine) + emcioStatus.status = RCS_STATUS::EXEC; + } return 0; } -int Task::emcToolUnload() +int Task::emcToolUnload()//EMC_TOOL_UNLOAD_TYPE { - EMC_TOOL_UNLOAD toolUnloadMsg; - - sendCommand(&toolUnloadMsg); - + emcioStatus.tool.toolInSpindle = 0; return 0; } -int Task::emcToolLoadToolTable(const char *file) +int Task::emcToolLoadToolTable(const char *file)//EMC_TOOL_LOAD_TOOL_TABLE_TYPE { - EMC_TOOL_LOAD_TOOL_TABLE toolLoadToolTableMsg; - - rtapi_strxcpy(toolLoadToolTableMsg.file, file); - - sendCommand(&toolLoadToolTableMsg); - + //error handler? + tooldata_load(file); + reload_tool_number(emcioStatus.tool.toolInSpindle); return 0; } -int Task::emcToolSetOffset(int pocket, int toolno, EmcPose offset, double diameter, - double frontangle, double backangle, int orientation) +int Task::emcToolSetOffset(int idx, int toolno, EmcPose offset, double diameter, + double frontangle, double backangle, int orientation)//EMC_TOOL_SET_OFFSET { - EMC_TOOL_SET_OFFSET toolSetOffsetMsg; - - toolSetOffsetMsg.pocket = pocket; - toolSetOffsetMsg.toolno = toolno; - toolSetOffsetMsg.offset = offset; - toolSetOffsetMsg.diameter = diameter; - toolSetOffsetMsg.frontangle = frontangle; - toolSetOffsetMsg.backangle = backangle; - toolSetOffsetMsg.orientation = orientation; - sendCommand(&toolSetOffsetMsg); + int o; + double d, f, b; + + d = diameter; + f = frontangle; + b = backangle; + o = orientation; + + rtapi_print_msg(RTAPI_MSG_DBG, + "EMC_TOOL_SET_OFFSET idx=%d toolno=%d zoffset=%lf, " + "xoffset=%lf, diameter=%lf, " + "frontangle=%lf, backangle=%lf, orientation=%d\n", + idx, toolno, offset.tran.z, offset.tran.x, d, f, b, o); + CANON_TOOL_TABLE tdata; + if (tooldata_get(&tdata,idx) != IDX_OK) { + UNEXPECTED_MSG; + } + tdata.toolno = toolno; + tdata.offset = offset; + tdata.diameter = d; + tdata.frontangle = f; + tdata.backangle = b; + tdata.orientation = o; + if (tooldata_put(tdata,idx) != IDX_OK) { + UNEXPECTED_MSG; + } + if (0 != tooldata_save(tooltable_filename)) { + emcioStatus.status = RCS_STATUS::ERROR; + } + //TODO + // if (io_db_mode == DB_ACTIVE) { + // int pno = idx; // for random_toolchanger + // if (!random_toolchanger) { pno = tdata.pocketno; } + // if (tooldata_db_notify(TOOL_OFFSET,toolno,pno,tdata)) { + // UNEXPECTED_MSG; + // } + // } return 0; } -int Task::emcToolSetNumber(int number) +int Task::emcToolSetNumber(int number)//EMC_TOOL_SET_NUMBER { - EMC_TOOL_SET_NUMBER toolSetNumberMsg; + int idx; - toolSetNumberMsg.tool = number; + idx = number;//TODO: should be toolno + CANON_TOOL_TABLE tdata; + if (tooldata_get(&tdata,idx) != IDX_OK) { + UNEXPECTED_MSG; + } + load_tool(idx); - sendCommand(&toolSetNumberMsg); + idx=0; // update spindle (fix legacy behavior) + if (tooldata_get(&tdata,idx) != IDX_OK) { + UNEXPECTED_MSG; + } + emcioStatus.tool.toolInSpindle = tdata.toolno; + rtapi_print_msg(RTAPI_MSG_DBG, + "EMC_TOOL_SET_NUMBER old_loaded_tool=%d new_idx_number=%d new_tool=%d\n" + , emcioStatus.tool.toolInSpindle, idx, tdata.toolno); + //likewise in HAL + *(iocontrol_data->tool_number) = emcioStatus.tool.toolInSpindle; + if (emcioStatus.tool.toolInSpindle == 0) { + emcioStatus.tool.toolFromPocket = *(iocontrol_data->tool_from_pocket) = 0; // no tool in spindle + } return 0; } -// Status functions - -int Task::emcIoUpdate(EMC_IO_STAT * stat) +/******************************************************************** +* +* Description: read_tool_inputs(void) +* Reads the tool-pin values from HAL +* this function gets called once per cycle +* It sets the values for the emcioStatus.aux.* +* +* Returns: returns which of the status has changed +* we then need to update through NML (a bit different as read_hal_inputs) +* +* Side Effects: updates values +* +* Called By: main every CYCLE +********************************************************************/ +int Task::read_tool_inputs(void) { - if (0 == emcIoStatusBuffer || !emcIoStatusBuffer->valid()) { - return -1; - } - - switch (emcIoStatusBuffer->peek()) { - case -1: - // error on CMS channel - return -1; - break; - - case 0: // nothing new - case EMC_IO_STAT_TYPE: // something new - // drop out to copy - break; - - default: - // something else is in there - return -1; - break; + if (*iocontrol_data->tool_prepare && *iocontrol_data->tool_prepared) { + emcioStatus.tool.pocketPrepped = *iocontrol_data->tool_prep_index; //check if tool has been (idx) prepared + *(iocontrol_data->tool_prepare) = 0; + emcioStatus.status = RCS_STATUS::DONE; // we finally finished to do tool-changing, signal task with RCS_DONE + return 10; //prepped finished } - // copy status - *stat = *emcIoStatus; - - /* - We need to check that the RCS_DONE isn't left over from the previous - command, by comparing the command number we sent with the command - number that emcio echoes. If they're different, then the command - hasn't been acknowledged yet and the state should be forced to be - RCS_STATUS::EXEC. */ - if (stat->echo_serial_number != emcIoCommandSerialNumber) { - stat->status = RCS_STATUS::EXEC; + if (*iocontrol_data->tool_change && *iocontrol_data->tool_changed) { + if(!random_toolchanger && emcioStatus.tool.pocketPrepped == 0) { + emcioStatus.tool.toolInSpindle = 0; + emcioStatus.tool.toolFromPocket = *(iocontrol_data->tool_from_pocket) = 0; + } else { + // the tool now in the spindle is the one that was prepared + CANON_TOOL_TABLE tdata; + if (tooldata_get(&tdata,emcioStatus.tool.pocketPrepped) != IDX_OK) { + UNEXPECTED_MSG; return -1; + } + emcioStatus.tool.toolInSpindle = tdata.toolno; + emcioStatus.tool.toolFromPocket = *(iocontrol_data->tool_from_pocket) = tdata.pocketno; + } + if (emcioStatus.tool.toolInSpindle == 0) { + emcioStatus.tool.toolFromPocket = *(iocontrol_data->tool_from_pocket) = 0; + } + *(iocontrol_data->tool_number) = emcioStatus.tool.toolInSpindle; //likewise in HAL + load_tool(emcioStatus.tool.pocketPrepped); + emcioStatus.tool.pocketPrepped = -1; //reset the tool preped number, -1 to permit tool 0 to be loaded + *(iocontrol_data->tool_prep_number) = 0; //likewise in HAL + *(iocontrol_data->tool_prep_pocket) = 0; //likewise in HAL + *(iocontrol_data->tool_prep_index) = 0; //likewise in HAL + *(iocontrol_data->tool_change) = 0; //also reset the tool change signal + emcioStatus.status = RCS_STATUS::DONE; // we finally finished to do tool-changing, signal task with RCS_DONE + return 11; //change finished } - //commented out because it keeps resetting the spindle speed to some odd value - //the speed gets set by the IO controller, no need to override it here (io takes care of increase/decrease speed too) - // stat->spindle.speed = spindleSpeed; - return 0; } + +void Task::run(){ // called periodically from emctaskmain.cc + tool_status = read_tool_inputs(); + if ( *(iocontrol_data->emc_enable_in)==0) //check for estop from HW + emcioStatus.aux.estop = 1; + else + emcioStatus.aux.estop = 0; +} diff --git a/src/emc/task/taskclass.hh b/src/emc/task/taskclass.hh index 4c7e39e8223..de521f54f1c 100644 --- a/src/emc/task/taskclass.hh +++ b/src/emc/task/taskclass.hh @@ -20,10 +20,39 @@ #include "emc.hh" #include "inifile.hh" +#include "hal.h" + +#define UNEXPECTED_MSG fprintf(stderr,"UNEXPECTED %s %d\n",__FILE__,__LINE__); + +struct iocontrol_str { + hal_bit_t *user_enable_out; /* output, TRUE when EMC wants stop */ + hal_bit_t *emc_enable_in; /* input, TRUE on any external stop */ + hal_bit_t *user_request_enable; /* output, used to reset ENABLE latch */ + hal_bit_t *coolant_mist; /* coolant mist output pin */ + hal_bit_t *coolant_flood; /* coolant flood output pin */ + hal_bit_t *lube; /* lube output pin */ + hal_bit_t *lube_level; /* lube level input pin */ + + // the following pins are needed for toolchanging + //tool-prepare + hal_bit_t *tool_prepare; /* output, pin that notifies HAL it needs to prepare a tool */ + hal_s32_t *tool_prep_pocket;/* output, pin that holds the pocketno for the tool table entry matching the tool to be prepared, + only valid when tool-prepare=TRUE */ + hal_s32_t *tool_from_pocket;/* output, pin indicating pocket current load tool retrieved from*/ + hal_s32_t *tool_prep_index; /* output, pin for internal index (idx) of prepped tool above */ + hal_s32_t *tool_prep_number;/* output, pin that holds the tool number to be prepared, only valid when tool-prepare=TRUE */ + hal_s32_t *tool_number; /* output, pin that holds the tool number currently in the spindle */ + hal_bit_t *tool_prepared; /* input, pin that notifies that the tool has been prepared */ + //tool-change + hal_bit_t *tool_change; /* output, notifies a tool-change should happen (emc should be in the tool-change position) */ + hal_bit_t *tool_changed; /* input, notifies tool has been changed */ + + // note: spindle control has been moved to motion +}; //pointer to the HAL-struct class Task { public: - Task(); + Task(EMC_IO_STAT &emcioStatus_in); virtual ~Task(); virtual int emcIoInit(); @@ -36,7 +65,6 @@ public: virtual int emcCoolantMistOff(); virtual int emcCoolantFloodOn(); virtual int emcCoolantFloodOff(); - virtual int emcIoSetDebug(int debug); virtual int emcToolSetOffset(int pocket, int toolno, EmcPose offset, double diameter, double frontangle, double backangle, int orientation); virtual int emcToolPrepare(int tool); @@ -44,11 +72,21 @@ public: virtual int emcToolLoadToolTable(const char *file); virtual int emcToolUnload(); virtual int emcToolSetNumber(int number); - virtual int emcIoUpdate(EMC_IO_STAT * stat); + int iocontrol_hal_init(void); + void reload_tool_number(int toolno); + void load_tool(int idx); + void run(); + int read_tool_inputs(void); + void hal_init_pins(void); + + EMC_IO_STAT &emcioStatus; int random_toolchanger; + int comp_id; /* hal component ID */ + iocontrol_str *iocontrol_data; const char *ini_filename; const char *tooltable_filename; + int tool_status; }; extern Task *task_methods; diff --git a/tests/motion/g0/motion-test.ini b/tests/motion/g0/motion-test.ini index 629460e2aaa..414c193c1e0 100644 --- a/tests/motion/g0/motion-test.ini +++ b/tests/motion/g0/motion-test.ini @@ -44,6 +44,7 @@ LINEAR_UNITS = inch ANGULAR_UNITS = degree DEFAULT_LINEAR_VELOCITY = 1.2 MAX_LINEAR_VELOCITY = 4 +NO_FORCE_HOMING = 1 # Axes sections --------------------------------------------------------------- diff --git a/tests/motion/g0/test.sh b/tests/motion/g0/test.sh index 0d629e65f96..0a7f9c2630b 100755 --- a/tests/motion/g0/test.sh +++ b/tests/motion/g0/test.sh @@ -33,17 +33,9 @@ samplerpid=$! echo hello EMC mt 1.0 echo set enable EMCTOO - echo set mode manual echo set estop off echo set machine on - echo set home 0 - echo set home 1 - echo set home 2 - - # Wait for homing to complete - wait_for_pin motion.is-all-homed TRUE - echo set mode mdi dist=1 echo set mdi g0x$dist