reg_write with data types.
authorFlorian Pose <fp@igh-essen.com>
Wed, 08 Apr 2009 14:10:34 +0000
changeset 1389 5b392b22a2da
parent 1388 3c886ec376f5
child 1390 7e600a39a91b
reg_write with data types.
tool/CommandReg.cpp
tool/CommandReg.h
tool/CommandRegRead.cpp
tool/CommandRegRead.h
tool/CommandRegWrite.cpp
tool/CommandRegWrite.h
tool/Makefile.am
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tool/CommandReg.cpp	Wed Apr 08 14:10:34 2009 +0000
@@ -0,0 +1,70 @@
+/*****************************************************************************
+ *
+ *  $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 "CommandReg.h"
+
+/*****************************************************************************/
+
+CommandReg::CommandReg(const string &name, const string &briefDesc):
+    Command(name, briefDesc)
+{
+}
+
+/****************************************************************************/
+
+const CommandReg::DataType *CommandReg::findDataType(
+        const string &str
+        )
+{
+    const DataType *d;
+    
+    for (d = dataTypes; d->name; d++)
+        if (str == d->name)
+            return d;
+
+    return NULL;
+}
+
+/****************************************************************************/
+
+const CommandReg::DataType CommandReg::dataTypes[] = {
+    {"int8",         1},
+    {"int16",        2},
+    {"int32",        4},
+    {"int64",        8},
+    {"uint8",        1},
+    {"uint16",       2},
+    {"uint32",       4},
+    {"uint64",       8},
+    {"string",       0},
+    {"raw",          0},
+    {}
+};
+
+/*****************************************************************************/
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tool/CommandReg.h	Wed Apr 08 14:10:34 2009 +0000
@@ -0,0 +1,54 @@
+/*****************************************************************************
+ *
+ *  $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 __COMMANDREG_H__
+#define __COMMANDREG_H__
+
+#include "Command.h"
+
+/****************************************************************************/
+
+class CommandReg:
+    public Command
+{
+    public:
+        CommandReg(const string &, const string &);
+
+    protected:
+        struct DataType {
+            const char *name;
+            unsigned int byteSize;
+        };
+        static const DataType dataTypes[];
+        static const DataType *findDataType(const string &);
+};
+
+/****************************************************************************/
+
+#endif
--- a/tool/CommandRegRead.cpp	Wed Apr 08 12:48:59 2009 +0000
+++ b/tool/CommandRegRead.cpp	Wed Apr 08 14:10:34 2009 +0000
@@ -36,7 +36,7 @@
 /*****************************************************************************/
 
 CommandRegRead::CommandRegRead():
-    Command("reg_read", "Output a slave's register contents.")
+    CommandReg("reg_read", "Output a slave's register contents.")
 {
 }
 
@@ -63,7 +63,7 @@
         << endl
         << "These are the valid data types:" << endl
         << "  int8, int16, int32, int64, uint8, uint16, uint32," << endl
-        << "  uint64, string, octet_string, raw." << endl
+        << "  uint64, string, raw." << endl
         << endl
     	<< "Command-specific options:" << endl
         << "  --alias    -a <alias>" << endl
@@ -159,13 +159,13 @@
 	}
 
     cout << setfill('0');
-    if (!dataType ||
-            dataType->name == "string" ||
-            dataType->name == "octet_string") {
+    if (!dataType || dataType->name == "string") {
         uint16_t i;
         for (i = 0; i < data.length; i++) {
             cout << data.data[i];
         }
+        if (dataType)
+            cout << endl;
     } else if (dataType->name == "int8") {
         int sval = *(int8_t *) data.data;
         cout << sval << " 0x" << hex << setw(2) << sval << endl;
@@ -190,7 +190,7 @@
     } else if (dataType->name == "uint64") {
         long long unsigned int uval = le32_to_cpup(data.data);
         cout << uval << " 0x" << hex << setw(8) << uval << endl;
-    } else {
+    } else { // raw
         uint8_t *d = data.data;
         unsigned int size = data.length;
 
@@ -206,36 +206,4 @@
     delete [] data.data;
 }
 
-/****************************************************************************/
-
-const CommandRegRead::DataType *CommandRegRead::findDataType(
-        const string &str
-        )
-{
-    const DataType *d;
-    
-    for (d = dataTypes; d->name; d++)
-        if (str == d->name)
-            return d;
-
-    return NULL;
-}
-
-/****************************************************************************/
-
-const CommandRegRead::DataType CommandRegRead::dataTypes[] = {
-    {"int8",         1},
-    {"int16",        2},
-    {"int32",        4},
-    {"int64",        8},
-    {"uint8",        1},
-    {"uint16",       2},
-    {"uint32",       4},
-    {"uint64",       8},
-    {"string",       0},
-    {"octet_string", 0},
-    {"raw",          0},
-    {}
-};
-
 /*****************************************************************************/
--- a/tool/CommandRegRead.h	Wed Apr 08 12:48:59 2009 +0000
+++ b/tool/CommandRegRead.h	Wed Apr 08 14:10:34 2009 +0000
@@ -30,26 +30,18 @@
 #ifndef __COMMANDREGREAD_H__
 #define __COMMANDREGREAD_H__
 
-#include "Command.h"
+#include "CommandReg.h"
 
 /****************************************************************************/
 
 class CommandRegRead:
-    public Command
+    public CommandReg
 {
     public:
         CommandRegRead();
 
         string helpString() const;
         void execute(MasterDevice &, const StringVector &);
-
-    private:
-        struct DataType {
-            const char *name;
-            unsigned int byteSize;
-        };
-        static const DataType dataTypes[];
-        static const DataType *findDataType(const string &);
 };
 
 /****************************************************************************/
--- a/tool/CommandRegWrite.cpp	Wed Apr 08 12:48:59 2009 +0000
+++ b/tool/CommandRegWrite.cpp	Wed Apr 08 14:10:34 2009 +0000
@@ -38,7 +38,7 @@
 /*****************************************************************************/
 
 CommandRegWrite::CommandRegWrite():
-    Command("reg_write", "Write data to a slave's registers.")
+    CommandReg("reg_write", "Write data to a slave's registers.")
 {
 }
 
@@ -48,21 +48,30 @@
 {
     stringstream str;
 
-    str << getName() << " [OPTIONS] <OFFSET> <FILENAME>" << endl
+    str << getName() << " [OPTIONS] <OFFSET> <DATA>" << endl
         << endl 
         << getBriefDescription() << endl
         << endl
         << "This command requires a single slave to be selected." << endl
     	<< endl
         << "Arguments:" << endl
-        << "  OFFSET   must be the register address." << endl
-        << "  FILENAME must be a path to a file with data to write." << endl
-        << "           If it is '-', data are read from stdin." << endl
+        << "  OFFSET  is the register address to write to." << endl
+        << "  DATA    depends on whether a datatype was specified" << endl
+		<< "          with the --type option: If not, DATA must be" << endl
+		<< "          either a path to a file with data to write," << endl
+		<< "          or '-', which means, that data are read from" << endl
+		<< "          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
+		<< 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();
 
@@ -92,17 +101,85 @@
         throwInvalidUsageException(err);
     }
 
-    if (args[1] == "-") {
-        loadRegData(&data, cin);
-    } else {
-        file.open(args[1].c_str(), ifstream::in | ifstream::binary);
-        if (file.fail()) {
-            err << "Failed to open '" << args[0] << "'!";
-            throwCommandException(err);
+	if (getDataType().empty()) {
+		if (args[1] == "-") {
+			loadRegData(&data, cin);
+		} else {
+			file.open(args[1].c_str(), ifstream::in | ifstream::binary);
+			if (file.fail()) {
+				err << "Failed to open '" << args[1] << "'!";
+				throwCommandException(err);
+			}
+			loadRegData(&data, file);
+			file.close();
+		}
+	} else {
+		stringstream strValue;
+		const DataType *dataType = findDataType(getDataType());
+
+        if (!dataType) {
+            err << "Invalid data type '" << getDataType() << "'!";
+            throwInvalidUsageException(err);
         }
-        loadRegData(&data, file);
-        file.close();
-    }
+
+		if (dataType->byteSize) {
+			data.length = dataType->byteSize;
+			data.data = new uint8_t[data.length];
+		}
+
+		strValue << args[1];
+		strValue >> resetiosflags(ios::basefield); // guess base from prefix
+		strValue.exceptions(ios::failbit);
+
+		try {
+			if (dataType->name == "int8") {
+				int16_t val; // uint8_t is interpreted as char
+				strValue >> val;
+				if (val > 127 || val < -128)
+					throw ios::failure("Value out of range");
+				*data.data = (int8_t) val;
+			} else if (dataType->name == "int16") {
+				int16_t val;
+				strValue >> val;
+				*(int16_t *) data.data = cpu_to_le16(val);
+			} else if (dataType->name == "int32") {
+				int32_t val;
+				strValue >> val;
+				*(int32_t *) data.data = cpu_to_le32(val);
+			} else if (dataType->name == "uint8") {
+				uint16_t val; // uint8_t is interpreted as char
+				strValue >> val;
+				if (val > 0xff)
+					throw ios::failure("Value out of range");
+				*data.data = (uint8_t) val;
+			} else if (dataType->name == "uint16") {
+				uint16_t val;
+				strValue >> val;
+				*(uint16_t *) data.data = cpu_to_le16(val);
+			} else if (dataType->name == "uint32") {
+				uint32_t val;
+				strValue >> val;
+				*(uint32_t *) data.data = cpu_to_le32(val);
+			} else if (dataType->name == "string" ||
+					dataType->name == "octet_string") {
+				data.length = strValue.str().size();
+				if (!data.length) {
+					err << "Zero-size string now allowed!";
+					throwCommandException(err);
+				}
+				data.data = new uint8_t[data.length];
+				strValue >> (char *) data.data;
+			} else {
+				err << "Invalid data type " << dataType->name;
+				throwCommandException(err);
+			}
+		} catch (ios::failure &e) {
+			delete [] data.data;
+			err << "Invalid value argument '" << args[1]
+				<< "' for type '" << dataType->name << "'!";
+			throwInvalidUsageException(err);
+		}
+	}
 
     if ((uint32_t) data.offset + data.length > 0xffff) {
         err << "Offset and length exceeding 64k!";
--- a/tool/CommandRegWrite.h	Wed Apr 08 12:48:59 2009 +0000
+++ b/tool/CommandRegWrite.h	Wed Apr 08 14:10:34 2009 +0000
@@ -30,12 +30,12 @@
 #ifndef __COMMANDREGWRITE_H__
 #define __COMMANDREGWRITE_H__
 
-#include "Command.h"
+#include "CommandReg.h"
 
 /****************************************************************************/
 
 class CommandRegWrite:
-    public Command
+    public CommandReg
 {
     public:
         CommandRegWrite();
--- a/tool/Makefile.am	Wed Apr 08 12:48:59 2009 +0000
+++ b/tool/Makefile.am	Wed Apr 08 14:10:34 2009 +0000
@@ -45,6 +45,7 @@
 	CommandFoeWrite.cpp \
 	CommandMaster.cpp \
 	CommandPdos.cpp \
+	CommandReg.cpp \
 	CommandRegRead.cpp \
 	CommandRegWrite.cpp \
 	CommandSdos.cpp \
@@ -73,6 +74,7 @@
 	CommandFoeWrite.h \
 	CommandMaster.h \
 	CommandPdos.h \
+	CommandReg.h \
 	CommandRegRead.h \
 	CommandRegWrite.h \
 	CommandSdos.h \