⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 iosh.cc

📁 Source code for an Numeric Cmputer
💻 CC
📖 第 1 页 / 共 3 页
字号:
/********************************************************************* Description: iosh.cc*   Extended-Tcl-based general IO programming shell with NML connectivity**   Derived from a work by Fred Proctor & Will Shackleford** Author:* License: GPL Version 2* System: Linux*    * Copyright (c) 2004 All rights reserved.** Last change:* $Revision: 1.16 $* $Author: jepler $* $Date: 2006/01/31 04:28:31 $********************************************************************//*! \todo   FIXME  add tool_in_spindle status*/#include <stdio.h>#include <string.h>#include <stdlib.h>#include <signal.h>#include <sys/io.h>#include "tcl.h"#include "tk.h"#include "rcs.hh"		// etime()#include "posemath.h"		// PM_POSE#include "emc.hh"		// EMC NML#include "emcglb.h"		// EMC_NMLFILE, TRAJ_MAX_VELOCITY, etc.#include "emccfg.h"		// DEFAULT_TRAJ_MAX_VELOCITY#include "inifile.hh"		// INIFILE#include "motion.h"		// emc struct and commands#include "usrmotintf.h"		// usrmot interface#include <unistd.h>		/* iopl() *//*  Using iosh:  iosh {<script>} {-- -ini <ini file>}  With filename, it opens NML buffers to the EMC IO, runs the script, closes  the buffers, and quits.  Without filename, it runs interactively.  With -- -ini <inifile>, uses inifile instead of emc.ini. Note that  the two dashes prevents Tcl from looking at the remaining args, which  would otherwise trigger a Tcl error that it doesn't understand what  -ini means.  EMC IO commands:  emc_io_connect  emc_io_disconnect  Open or close the NML buffers to the command in, status out, and error out.  Returns 0 if OK, or -1 if not.  emc_io_read_command  Peek the NML command buffer. Returns 0 if OK, -1 if not.  emc_io_get_command  Puts the command string, e.g., "emc_aux_estop_off", or "none". Returns 0.  emc_io_get_command_type  Puts the command NML number. Returns 0.  emc_io_get_serial_number  Puts the command serial number. Returns 0.  emc_io_write_status  Write the EMC_IO_STAT structure out to NML. Returns 0 if OK, -1 if error.  emc_io_write_error  Write the error string to the error NML buffer. Returns 0 if OK, -1 if error.  emc_io_load_tool_table  Loads the tool table specified in the ini file  IO status, sets associated field in the NML status structure  emc_io_status_heartbeat <number>  emc_io_status_echo_serial_number <number>  emc_io_status_status done | exec | error  emc_io_status_estop on | off  emc_io_status_mist on | off  emc_io_status_flood on | off  emc_io_status_lube on | off  emc_io_status_lube_level ok | low  emc_io_status_spindle_speed <speed>  emc_io_status_spindle_enabled on | off  emc_io_status_spindle_direction <pos> <neg> 0  emc_io_status_spindle_increasing <pos> <neg> 0  emc_io_status_spindle_brake on | off  emc_io_status_tool_prepped <number>  emc_io_status_tool_in_spindle <number>  IO commands:  inb <address>  Reads and returns the byte at <address>. If address begins with 0x,  it's interpreted as a hex number, otherwise it's decimal.  outb <address> <value>  Writes the byte <value> to <address>. If address or value begins with 0x,  it's interpreted as a hex number, otherwise it's decimal. Returns nothing.  inw <address>  Reads and returns the short at <address>. If address begins with 0x,  it's interpreted as a hex number, otherwise it's decimal.  outw <address> <value>  Writes the short <value> to <address>. If address or value begins with 0x,  it's interpreted as a hex number, otherwise it's decimal. Returns nothing.  inl <address>  Reads and returns the long at <address>. If address begins with 0x,  it's interpreted as a hex number, otherwise it's decimal.  outl <address> <value>  Writes the long <value> to <address>. If address or value begins with 0x,  it's interpreted as a hex number, otherwise it's decimal. Returns nothing.  emc_mot_move <axis> <position> <velocity>      emc_mot_rawinput <axis>      emc_mot_shmem: need no args*/// the NML channels to the EMC taskstatic RCS_CMD_CHANNEL *emcioCommandBuffer = 0;// NML command channel data pointerstatic RCS_CMD_MSG *emcioCommand = 0;static RCS_STAT_CHANNEL *emcioStatusBuffer = 0;static EMC_IO_STAT emcioStatus;// the NML channel for errorsstatic NML *emcErrorBuffer = 0;// Shared memory to communicate with emcmotstatic emcmot_command_t emcmotCommand;extern emcmot_struct_t *emcmotshmem;static long shmem = 0;		// Shared memory flag// "defined but not used"...//static int motionId = 0;static int emcIoNmlGet(){    int retval = 0;    // try to connect to EMC IO cmd    if (emcioCommandBuffer == 0) {	emcioCommandBuffer =	    new RCS_CMD_CHANNEL(emcFormat, "toolCmd", "tool", EMC_NMLFILE);	if (!emcioCommandBuffer->valid()) {	    rcs_print_error("emcToolCmd buffer not available\n");	    delete emcioCommandBuffer;	    emcioCommandBuffer = 0;	    retval = -1;	} else {	    // get our command data structure	    emcioCommand = emcioCommandBuffer->get_address();	}    }    // try to connect to EMC IO status    if (emcioStatusBuffer == 0) {	emcioStatusBuffer =	    new RCS_STAT_CHANNEL(emcFormat, "toolSts", "tool",				 EMC_NMLFILE);	if (!emcioStatusBuffer->valid()) {	    rcs_print_error("toolSts buffer not available\n");	    delete emcioStatusBuffer;	    emcioStatusBuffer = 0;	    retval = -1;	} else {	    // initialize and write status	    emcioStatus.heartbeat = 0;	    emcioStatus.command_type = 0;	    emcioStatus.echo_serial_number = 0;	    emcioStatus.status = RCS_DONE;	    emcioStatusBuffer->write(&emcioStatus);	}    }    return retval;}static int emcErrorNmlGet(){    int retval = 0;    if (emcErrorBuffer == 0) {	emcErrorBuffer =	    new NML(nmlErrorFormat, "emcError", "tool", EMC_NMLFILE);	if (!emcErrorBuffer->valid()) {	    rcs_print_error("emcError buffer not available\n");	    delete emcErrorBuffer;	    emcErrorBuffer = 0;	    retval = -1;	}    }    return retval;}// EMC IO commandsstatic int emc_ini(ClientData clientdata,		   Tcl_Interp * interp, int objc, Tcl_Obj * CONST objv[]){    Inifile inifile;    const char *inistring;    const char *varstr, *secstr;    if (objc != 3) {	Tcl_SetResult(interp, "emc_ini: need 'var' and 'section'",		      TCL_VOLATILE);	return TCL_ERROR;    }    // open it    if (inifile.open(EMC_INIFILE) == false) {	return -1;    }    varstr = Tcl_GetStringFromObj(objv[1], 0);    secstr = Tcl_GetStringFromObj(objv[2], 0);    if (NULL == (inistring = inifile.find(varstr, secstr))) {	return TCL_OK;    }    Tcl_SetResult(interp, (char *) inistring, TCL_VOLATILE);    // close it    inifile.close();    return TCL_OK;}static int emc_io_connect(ClientData clientdata,			  Tcl_Interp * interp, int objc,			  Tcl_Obj * CONST objv[]){    double end;    int good;#define RETRY_TIME 10.0		// seconds to wait for subsystems to come up#define RETRY_INTERVAL 1.0	// seconds between wait tries for a subsystem    if (objc != 1) {	Tcl_SetResult(interp, "emc_io_connect: need no args\n",		      TCL_VOLATILE);	return TCL_ERROR;    }    if (!(EMC_DEBUG & EMC_DEBUG_NML)) {	set_rcs_print_destination(RCS_PRINT_TO_NULL);	// inhibit diag	// messages    }    end = RETRY_TIME;    good = 0;    do {	if (0 == emcIoNmlGet()) {	    good = 1;	    break;	}	esleep(RETRY_INTERVAL);	end -= RETRY_INTERVAL;    } while (end > 0.0);    if (!(EMC_DEBUG & EMC_DEBUG_NML)) {	set_rcs_print_destination(RCS_PRINT_TO_STDOUT);	// restore diag	// messages    }    if (!good) {	Tcl_SetObjResult(interp, Tcl_NewIntObj(-1));	return TCL_OK;    }    if (!(EMC_DEBUG & EMC_DEBUG_NML)) {	set_rcs_print_destination(RCS_PRINT_TO_NULL);	// inhibit diag	// messages    }    end = RETRY_TIME;    good = 0;    do {	if (0 == emcErrorNmlGet()) {	    good = 1;	    break;	}	esleep(RETRY_INTERVAL);	end -= RETRY_INTERVAL;    } while (end > 0.0);    if (!(EMC_DEBUG & EMC_DEBUG_NML)) {	set_rcs_print_destination(RCS_PRINT_TO_STDOUT);	// restore diag	// messages    }    if (!good) {	Tcl_SetObjResult(interp, Tcl_NewIntObj(-1));	return TCL_OK;    }    Tcl_SetObjResult(interp, Tcl_NewIntObj(0));    return TCL_OK;}static int emc_io_disconnect(ClientData clientdata,			     Tcl_Interp * interp, int objc,			     Tcl_Obj * CONST objv[]){    if (objc != 1) {	Tcl_SetResult(interp, "emc_io_disconnect: need no args\n",		      TCL_VOLATILE);	return TCL_ERROR;    }    if (emcErrorBuffer != 0) {	delete emcErrorBuffer;	emcErrorBuffer = 0;    }    if (emcioStatusBuffer != 0) {	delete emcioStatusBuffer;	emcioStatusBuffer = 0;    }    if (emcioCommandBuffer != 0) {	delete emcioCommandBuffer;	emcioCommandBuffer = 0;    }    Tcl_SetObjResult(interp, Tcl_NewIntObj(0));    return TCL_OK;}/*  emc_io_read_command peeks the NML command buffer. The side effect is  that emcioCommand now latches the NML contents. Other functions, like  emc_io_get_command,serial_number, get the contents from emcioCommand.  Returns 0 if OK, -1 if error reading NML.*/static int emc_io_read_command(ClientData clientdata,			       Tcl_Interp * interp, int objc,			       Tcl_Obj * CONST objv[]){    if (objc != 1) {	Tcl_SetResult(interp, "emc_io_read_command: need no args\n",		      TCL_VOLATILE);	return TCL_ERROR;    }    // read NML buffer    if (0 == emcioCommandBuffer || 0 == emcioCommand) {	Tcl_SetObjResult(interp, Tcl_NewIntObj(-1));	return TCL_OK;    }    // latch new command into emcioCommand    if (-1 == emcioCommandBuffer->peek()) {	Tcl_SetObjResult(interp, Tcl_NewIntObj(-1));	return TCL_OK;    }    Tcl_SetObjResult(interp, Tcl_NewIntObj(0));    return TCL_OK;}/*  load the tool table from file filename into toolTable[] array.  Array is CANON_TOOL_MAX + 1 entries, since 0 is included.  If filename is "", use global established from ini file  */static int loadToolTable(const char *filename,			 CANON_TOOL_TABLE toolTable[]){    int t;    FILE *fp;    char buffer[CANON_TOOL_ENTRY_LEN];    const char *name;    // check filename    if (filename[0] == 0) {	name = TOOL_TABLE_FILE;    } else {	// point to name provided	name = filename;    }    // open tool table file    if (NULL == (fp = fopen(name, "r"))) {	// can't open file	return -1;    }    // clear out tool table    for (t = 0; t <= CANON_TOOL_MAX; t++) {	// unused tools are 0, 0.0, 0.0	toolTable[t].id = 0;	toolTable[t].length = 0.0;	toolTable[t].diameter = 0.0;    }    /*       Override 0's with codes from tool file       File format is:       <header>       <pocket # 0..CANON_TOOL_MAX> <FMS id> <length> <diameter>       ...     */    // read and discard header    if (NULL == fgets(buffer, 256, fp)) {	// nothing in file at all	fclose(fp);	return -1;    }    while (!feof(fp)) {	int pocket;	int id;	double length;	double diameter;	// just read pocket, ID, and length offset	if (NULL == fgets(buffer, CANON_TOOL_ENTRY_LEN, fp)) {	    break;	}	if (4 != sscanf(buffer, "%d %d %lf %lf",			&pocket, &id, &length, &diameter)) {	    // bad entry-- skip	    continue;	} else {	    if (pocket < 0 || pocket > CANON_TOOL_MAX) {		continue;	    } else {		toolTable[pocket].id = id;		toolTable[pocket].length = length;		toolTable[pocket].diameter = diameter;	    }	}    }    // close the file    fclose(fp);    return 0;}/*  save the tool table to file filename from toolTable[] array.  Array is CANON_TOOL_MAX + 1 entries, since 0 is included.  If filename is "", use global established from ini file  *//* FIXME - commented out, seems it's not usedstatic int saveToolTable(const char *filename,			 CANON_TOOL_TABLE toolTable[]){    int pocket;    FILE *fp;    const char *name;    // check filename    if (filename[0] == 0) {	name = TOOL_TABLE_FILE;    } else {	// point to name provided	name = filename;    }    // open tool table file    if (NULL == (fp = fopen(name, "w"))) {	// can't open file	return -1;    }    // write header    fprintf(fp, "POC\tFMS\tLEN\t\tDIAM\n");    for (pocket = 1; pocket <= CANON_TOOL_MAX; pocket++) {	fprintf(fp, "%d\t%d\t%f\t%f\n",		pocket,		toolTable[pocket].id,		toolTable[pocket].length, toolTable[pocket].diameter);    }    // close the file    fclose(fp);    return 0;}FIXME - commented out, seems it's not used*//*  emc_io_get_command returns the string and any args associated with  the command, or "none" if nothing is there.  The convention for returning strings is that they're the lower-case  version of their NMLTYPE declarations in emc.hh, without the trailing  _TYPE, e.g.,  EMC_IO_INIT_TYPE -> emc_io_init  Note that these aren't always what you type in emcsh, for example,  EMC_AUX_ESTOP_OFF_TYPE -> emc_aux_estop off, not "emc_estop off". To  support the interchangeability of these, emcsh will be set up so that  the short versions ("emc_estop off") will supplement the conventional  names, which will always be present.*/static int emc_io_get_command(ClientData clientdata,			      Tcl_Interp * interp, int objc,			      Tcl_Obj * CONST objv[]){    NMLTYPE type;    char string[256];    if (objc != 1) {	Tcl_SetResult(interp, "emc_io_read_command: need no args\n",		      TCL_VOLATILE);	return TCL_ERROR;    }    // check for valid ptr    if (0 == emcioCommand) {	Tcl_SetResult(interp, "none", TCL_VOLATILE);	return TCL_OK;    }    type = emcioCommand->type;    switch (type) {    case 0:	Tcl_SetResult(interp, "none", TCL_VOLATILE);	break;    case EMC_IO_INIT_TYPE:	Tcl_SetResult(interp, "emc_io_init", TCL_VOLATILE);	break;    case EMC_TOOL_INIT_TYPE:	Tcl_SetResult(interp, "emc_tool_init", TCL_VOLATILE);	//Load the tool table on beginning	loadToolTable(TOOL_TABLE_FILE, emcioStatus.tool.toolTable);	break;    case EMC_TOOL_HALT_TYPE:	Tcl_SetResult(interp, "emc_tool_halt", TCL_VOLATILE);	break;    case EMC_TOOL_ABORT_TYPE:	Tcl_SetResult(interp, "emc_tool_abort", TCL_VOLATILE);	break;    case EMC_TOOL_PREPARE_TYPE:	sprintf(string, "emc_tool_prepare %d",		((EMC_TOOL_PREPARE *) emcioCommand)->tool);	Tcl_SetResult(interp, string, TCL_VOLATILE);	break;    case EMC_TOOL_LOAD_TYPE:	Tcl_SetResult(interp, "emc_tool_load", TCL_VOLATILE);	break;    case EMC_TOOL_UNLOAD_TYPE:	Tcl_SetResult(interp, "emc_tool_unload", TCL_VOLATILE);	break;    case EMC_SPINDLE_INIT_TYPE:	Tcl_SetResult(interp, "emc_spindle_init", TCL_VOLATILE);	break;    case EMC_SPINDLE_HALT_TYPE:	Tcl_SetResult(interp, "emc_spindle_halt", TCL_VOLATILE);	break;    case EMC_SPINDLE_ABORT_TYPE:

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -