diff --git a/TODO b/TODO index e7b21e0d6662647fc6e6b97b1626ffecba469b52..8c61b06df019f3ecce29ff0c6a81f0b993f3b8db 100644 --- a/TODO +++ b/TODO @@ -40,8 +40,6 @@ Version 1.5.0: - Implement indent in 'ethercat ma' - Implement 0xXXXX:YY format for specifying SDOs. - Lookup codes for 64bit data types. - - Move data type usage string into DataTypeHandler. - - Implement interpretation of SoE '[SP]-x-yyy' strings. - Implement reading from stream for soe_write. Future issues: diff --git a/tool/CommandDownload.cpp b/tool/CommandDownload.cpp index 47ec9c1564edea7ccccf8262424d14c40d603a62..ee008f139dcaad1134532b21310b408a399e5d02 100644 --- a/tool/CommandDownload.cpp +++ b/tool/CommandDownload.cpp @@ -59,9 +59,7 @@ string CommandDownload::helpString() const << "information service or the SDO is not in the dictionary," << endl << "the --type option is mandatory." << endl << endl - << "These are the valid SDO entry data types:" << endl - << " int8, int16, int32, uint8, uint16, uint32, string," << endl - << " octet_string." << endl + << typeInfo() << endl << "Arguments:" << endl << " INDEX is the SDO index and must be an unsigned" << endl diff --git a/tool/CommandRegRead.cpp b/tool/CommandRegRead.cpp index 5689d52366ad7917b08e66846f7fc53bb1ad72b3..8847ba7bcd9becb2c3e63fbb8273e4bae1f85766 100644 --- a/tool/CommandRegRead.cpp +++ b/tool/CommandRegRead.cpp @@ -62,9 +62,7 @@ string CommandRegRead::helpString() const << " can be omitted), if a selected data type" << endl << " implies a length." << endl << endl - << "These are the valid data types:" << endl - << " int8, int16, int32, int64, uint8, uint16, uint32," << endl - << " uint64, string, raw." << endl + << typeInfo() << endl << "Command-specific options:" << endl << " --alias -a <alias>" << endl diff --git a/tool/CommandRegWrite.cpp b/tool/CommandRegWrite.cpp index 9927f3d427dbc20be3d4c231f050c6403cf7e989..0c6ed51292d8648a469475a75a0ac2cfe64014df 100644 --- a/tool/CommandRegWrite.cpp +++ b/tool/CommandRegWrite.cpp @@ -64,9 +64,7 @@ string CommandRegWrite::helpString() const << " stdin. If a datatype was specified, VALUE is" << endl << " interpreted respective to the given type." << endl << endl - << "These are the valid data types:" << endl - << " int8, int16, int32, int64, uint8, uint16, uint32," << endl - << " uint64, string." << endl + << typeInfo() << endl << "Command-specific options:" << endl << " --alias -a <alias>" << endl diff --git a/tool/CommandSoeRead.cpp b/tool/CommandSoeRead.cpp index 7623d8a8c52967da8ee4c038a7593a7e4bf089c8..6edb894d3ef9054f2d6cd299127c9fc29c87cea4 100644 --- a/tool/CommandSoeRead.cpp +++ b/tool/CommandSoeRead.cpp @@ -37,7 +37,7 @@ using namespace std; /*****************************************************************************/ CommandSoeRead::CommandSoeRead(): - Command("soe_read", "Read an SoE IDN from a slave.") + SoeCommand("soe_read", "Read an SoE IDN from a slave.") { } @@ -47,20 +47,27 @@ string CommandSoeRead::helpString() const { stringstream str; - str << getName() << " [OPTIONS] <INDEX> <SUBINDEX>" << endl + str << getName() << " [OPTIONS] <IDN>" << endl << endl << getBriefDescription() << endl << endl << "This command requires a single slave to be selected." << endl << endl << "Arguments:" << endl - << " IDN is the IDN and must be an unsigned" << endl - << " 16 bit number." << endl + << " IDN is the IDN and must be either an unsigned" << endl + << " 16 bit number acc. to IEC 61800-7-204:" << endl + << " Bit 15: (0) Standard data, (1) Product data" << endl + << " Bit 14 - 12: Parameter set (0 - 7)" << endl + << " Bit 11 - 0: Data block number" << endl + << " or a string like 'P-0-150'." << endl + << endl + << typeInfo() << endl << "Command-specific options:" << endl << " --alias -a <alias>" << endl << " --position -p <pos> Slave selection. See the help of" << endl << " the 'slaves' command." << endl + << " --type -t <type> Data type (see above)." << endl << endl << numericInfo(); @@ -72,7 +79,7 @@ string CommandSoeRead::helpString() const void CommandSoeRead::execute(const StringVector &args) { SlaveList slaves; - stringstream err, strIdn; + stringstream err; const DataType *dataType = NULL; ec_ioctl_slave_soe_read_t ioctl; @@ -81,12 +88,10 @@ void CommandSoeRead::execute(const StringVector &args) throwInvalidUsageException(err); } - strIdn << args[0]; - strIdn - >> resetiosflags(ios::basefield) // guess base from prefix - >> ioctl.idn; - if (strIdn.fail()) { - err << "Invalid IDN '" << args[0] << "'!"; + try { + ioctl.idn = parseIdn(args[0]); + } catch (runtime_error &e) { + err << "Invalid IDN '" << args[0] << "': " << e.what(); throwInvalidUsageException(err); } diff --git a/tool/CommandSoeRead.h b/tool/CommandSoeRead.h index c7cff524ba26692cf529aff6a496a9bf61b9891f..31ac9fe616158ec1f68cdee0f756e0bc5778af9d 100644 --- a/tool/CommandSoeRead.h +++ b/tool/CommandSoeRead.h @@ -30,14 +30,12 @@ #ifndef __COMMANDSOEREAD_H__ #define __COMMANDSOEREAD_H__ -#include "Command.h" -#include "DataTypeHandler.h" +#include "SoeCommand.h" /****************************************************************************/ class CommandSoeRead: - public Command, - public DataTypeHandler + public SoeCommand { public: CommandSoeRead(); diff --git a/tool/CommandSoeWrite.cpp b/tool/CommandSoeWrite.cpp index 1d93f48dc3cc74c91faac1a46417058821953ac5..a67345b42ce73aa95eac343b94a905df46c766f7 100644 --- a/tool/CommandSoeWrite.cpp +++ b/tool/CommandSoeWrite.cpp @@ -37,7 +37,7 @@ using namespace std; /*****************************************************************************/ CommandSoeWrite::CommandSoeWrite(): - Command("soe_write", "Write an SoE IDN to a slave.") + SoeCommand("soe_write", "Write an SoE IDN to a slave.") { } @@ -47,17 +47,23 @@ string CommandSoeWrite::helpString() const { stringstream str; - str << getName() << " [OPTIONS] <INDEX> <SUBINDEX> <VALUE>" << endl + str << getName() << " [OPTIONS] <IDN> <VALUE>" << endl << endl << getBriefDescription() << endl << endl << "This command requires a single slave to be selected." << endl << endl << "Arguments:" << endl - << " IDN is the IDN and must be an unsigned" << endl - << " 16 bit number." << endl + << " IDN is the IDN and must be either an unsigned" << endl + << " 16 bit number acc. to IEC 61800-7-204:" << endl + << " Bit 15: (0) Standard data, (1) Product data" << endl + << " Bit 14 - 12: Parameter set (0 - 7)" << endl + << " Bit 11 - 0: Data block number" << endl + << " or a string like 'P-0-150'." << endl << " VALUE is the value to write and is interpreted" << endl << " as the given datatype (see above)." << endl + << endl + << typeInfo() << endl << "Command-specific options:" << endl << " --alias -a <alias>" << endl @@ -85,12 +91,10 @@ void CommandSoeWrite::execute(const StringVector &args) throwInvalidUsageException(err); } - strIdn << args[0]; - strIdn - >> resetiosflags(ios::basefield) // guess base from prefix - >> ioctl.idn; - if (strIdn.fail()) { - err << "Invalid IDN '" << args[0] << "'!"; + try { + ioctl.idn = parseIdn(args[0]); + } catch (runtime_error &e) { + err << "Invalid IDN '" << args[0] << "': " << e.what(); throwInvalidUsageException(err); } diff --git a/tool/CommandSoeWrite.h b/tool/CommandSoeWrite.h index 3c507b4a8e11f4a874d5506c9279c5d5c32d60a0..c5cc14f50d5e0a75ac45b58ed83acf05d5544c40 100644 --- a/tool/CommandSoeWrite.h +++ b/tool/CommandSoeWrite.h @@ -30,14 +30,12 @@ #ifndef __COMMANDSOEWRITE_H__ #define __COMMANDSOEWRITE_H__ -#include "Command.h" -#include "DataTypeHandler.h" +#include "SoeCommand.h" /****************************************************************************/ class CommandSoeWrite: - public Command, - public DataTypeHandler + public SoeCommand { public: CommandSoeWrite(); diff --git a/tool/CommandUpload.cpp b/tool/CommandUpload.cpp index 0f9605856770eea158bbc32a45235c9a42bdb738..7a186f54c8c85b7aeab7ed93f8b753c501c986cb 100644 --- a/tool/CommandUpload.cpp +++ b/tool/CommandUpload.cpp @@ -59,9 +59,7 @@ string CommandUpload::helpString() const << "information service or the SDO is not in the dictionary," << endl << "the --type option is mandatory." << endl << endl - << "These are the valid SDO entry data types:" << endl - << " int8, int16, int32, uint8, uint16, uint32, string," << endl - << " octet_string." << endl + << typeInfo() << endl << "Arguments:" << endl << " INDEX is the SDO index and must be an unsigned" << endl diff --git a/tool/DataTypeHandler.cpp b/tool/DataTypeHandler.cpp index 028c451c4a3e1c1aeefe429ab95d13b225738419..2dfaf838156cc098506126758127b31fd19c90e6 100644 --- a/tool/DataTypeHandler.cpp +++ b/tool/DataTypeHandler.cpp @@ -64,6 +64,20 @@ const DataTypeHandler::DataType *DataTypeHandler::findDataType( /****************************************************************************/ +string DataTypeHandler::typeInfo() +{ + stringstream s; + + s + << "These are valid data types to use with" << endl + << "the --type option:" << endl + << " int8, int16, int32, uint8, uint16, uint32, string," << endl + << " octet_string." << endl; + return s.str(); +} + +/****************************************************************************/ + const DataTypeHandler::DataType *DataTypeHandler::findDataType(uint16_t code) { const DataType *d; diff --git a/tool/DataTypeHandler.h b/tool/DataTypeHandler.h index 2a0e08a0bfb3d7382ed7ccbaf777f1d2fb8ff07a..9064895726287c4f25ad11df638c04db39df3143 100644 --- a/tool/DataTypeHandler.h +++ b/tool/DataTypeHandler.h @@ -51,6 +51,8 @@ class DataTypeHandler size_t byteSize; }; + static std::string typeInfo(); + static const DataType *findDataType(const std::string &); static const DataType *findDataType(uint16_t); static size_t interpretAsType(const DataType *, const std::string &, diff --git a/tool/Makefile.am b/tool/Makefile.am index ba4d7fcd821a9145cb67ad7f078354ad49880f79..b1de2434b9037da6110798be4f37d00ee732a294 100644 --- a/tool/Makefile.am +++ b/tool/Makefile.am @@ -66,6 +66,7 @@ ethercat_SOURCES = \ MasterDevice.cpp \ NumberListParser.cpp \ SdoCommand.cpp \ + SoeCommand.cpp \ main.cpp \ sii_crc.cpp @@ -106,6 +107,7 @@ noinst_HEADERS = \ MasterDevice.h \ NumberListParser.h \ SdoCommand.h \ + SoeCommand.h \ sii_crc.h if ENABLE_EOE diff --git a/tool/SoeCommand.cpp b/tool/SoeCommand.cpp new file mode 100644 index 0000000000000000000000000000000000000000..70030e2013b9584f204b54c6cee7bc9b42cca9ad --- /dev/null +++ b/tool/SoeCommand.cpp @@ -0,0 +1,108 @@ +/***************************************************************************** + * + * $Id$ + * + * Copyright (C) 2006-2009 Florian Pose, Ingenieurgemeinschaft IgH + * + * This file is part of the IgH EtherCAT Master. + * + * The IgH EtherCAT Master is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License version 2, as + * published by the Free Software Foundation. + * + * The IgH EtherCAT Master is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General + * Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with the IgH EtherCAT Master; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + * --- + * + * The license mentioned above concerns the source code only. Using the + * EtherCAT technology and brand is only permitted in compliance with the + * industrial property and similar rights of Beckhoff Automation GmbH. + * + ****************************************************************************/ + +#include <iomanip> +using namespace std; + +#include "SoeCommand.h" + +/*****************************************************************************/ + +SoeCommand::SoeCommand(const string &name, const string &briefDesc): + Command(name, briefDesc) +{ +} + +/*****************************************************************************/ + +uint16_t SoeCommand::parseIdn(const string &str) +{ + uint16_t idn = 0x0000; + stringstream s, err; + + if (!str.length()) { + err << "Zero-size string not allowed!"; + throw runtime_error(err.str()); + } + + if (str[0] == 'S' || str[0] == 'P') { + unsigned int num; + unsigned char c; + + s << str; + + s >> c; + if (c == 'P') { + idn |= 0x8000; + } + + s >> c; + if (s.fail() || c != '-') { + err << "'-' expected!"; + throw runtime_error(err.str()); + } + + s >> num; + if (s.fail() || num > 7) { + err << "Invalid parameter set number!"; + throw runtime_error(err.str()); + } + idn |= num << 12; + + s >> c; + if (s.fail() || c != '-') { + err << "'-' expected!"; + throw runtime_error(err.str()); + } + + s >> num; + if (s.fail() || num > 4095) { + err << "Invalid data block number!"; + throw runtime_error(err.str()); + } + idn |= num; + + s.peek(); + if (!s.eof()) { + err << "Additional input!"; + throw runtime_error(err.str()); + } + } else { + s << str; + s >> resetiosflags(ios::basefield) >> idn; + if (s.fail()) { + err << "Invalid number!"; + throw runtime_error(err.str()); + } + } + + return idn; +} + +/****************************************************************************/ diff --git a/tool/SoeCommand.h b/tool/SoeCommand.h new file mode 100644 index 0000000000000000000000000000000000000000..478bec90c99270bb11e554dfbec392737ada0647 --- /dev/null +++ b/tool/SoeCommand.h @@ -0,0 +1,51 @@ +/***************************************************************************** + * + * $Id$ + * + * Copyright (C) 2006-2009 Florian Pose, Ingenieurgemeinschaft IgH + * + * This file is part of the IgH EtherCAT Master. + * + * The IgH EtherCAT Master is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License version 2, as + * published by the Free Software Foundation. + * + * The IgH EtherCAT Master is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General + * Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with the IgH EtherCAT Master; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + * --- + * + * The license mentioned above concerns the source code only. Using the + * EtherCAT technology and brand is only permitted in compliance with the + * industrial property and similar rights of Beckhoff Automation GmbH. + * + ****************************************************************************/ + +#ifndef __SOECOMMAND_H__ +#define __SOECOMMAND_H__ + +#include "Command.h" +#include "DataTypeHandler.h" + +/****************************************************************************/ + +class SoeCommand: + public Command, + public DataTypeHandler +{ + public: + SoeCommand(const string &, const string &); + + protected: + static uint16_t parseIdn(const string &); +}; + +/****************************************************************************/ + +#endif