Moved every command into a separate file.
This commit is contained in:
parent
c57ffba9c8
commit
d103d9295d
|
|
@ -35,8 +35,23 @@ bin_PROGRAMS = ethercat
|
|||
|
||||
ethercat_SOURCES = \
|
||||
MasterDevice.cpp MasterDevice.h \
|
||||
coe_datatypes.cpp \
|
||||
sii_crc.cpp \
|
||||
cmd_alias.cpp \
|
||||
cmd_config.cpp \
|
||||
cmd_data.cpp \
|
||||
cmd_debug.cpp \
|
||||
cmd_domain.cpp \
|
||||
cmd_master.cpp \
|
||||
cmd_pdos.cpp \
|
||||
cmd_sdos.cpp \
|
||||
cmd_sdo_download.cpp \
|
||||
cmd_sdo_upload.cpp \
|
||||
cmd_slaves.cpp \
|
||||
cmd_sii_read.cpp \
|
||||
cmd_sii_write.cpp \
|
||||
cmd_states.cpp \
|
||||
cmd_xml.cpp \
|
||||
main.cpp
|
||||
|
||||
ethercat_CXXFLAGS = -I../master -Wall
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
|
|
@ -8,9 +8,6 @@
|
|||
#define __EC_MASTER_H__
|
||||
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <list>
|
||||
using namespace std;
|
||||
|
||||
#include "../include/ecrt.h"
|
||||
|
|
@ -64,27 +61,12 @@ class MasterDevice
|
|||
void getSdoEntry(ec_ioctl_slave_sdo_entry_t *, uint16_t, int, uint8_t);
|
||||
void readSii(ec_ioctl_slave_sii_t *);
|
||||
void writeSii(ec_ioctl_slave_sii_t *);
|
||||
void setDebug(unsigned int);
|
||||
void sdoDownload(ec_ioctl_slave_sdo_download_t *);
|
||||
void sdoUpload(ec_ioctl_slave_sdo_upload_t *);
|
||||
void requestState(uint16_t, uint8_t);
|
||||
|
||||
protected:
|
||||
#if 0
|
||||
void outputDomainData(unsigned int);
|
||||
enum {BreakAfterBytes = 16};
|
||||
void showDomain(unsigned int);
|
||||
void listSlavePdos(uint16_t, bool = false);
|
||||
void listSlaveSdos(uint16_t, bool = false);
|
||||
void listSlaves(int);
|
||||
void showSlave(uint16_t);
|
||||
void generateSlaveXml(uint16_t);
|
||||
void requestState(uint16_t, uint8_t);
|
||||
|
||||
static string slaveState(uint8_t);
|
||||
static void printRawData(const uint8_t *, unsigned int);
|
||||
static uint8_t calcSiiCrc(const uint8_t *, unsigned int);
|
||||
#endif
|
||||
|
||||
private:
|
||||
//enum {DefaultBufferSize = 1024};
|
||||
|
||||
unsigned int index;
|
||||
int fd;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@
|
|||
using namespace std;
|
||||
|
||||
#include "globals.h"
|
||||
#include "sii_crc.h"
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
|
|
@ -82,47 +83,6 @@ void command_alias(void)
|
|||
|
||||
/*****************************************************************************/
|
||||
|
||||
/** Calculates the SII checksum field.
|
||||
*
|
||||
* The checksum is generated with the polynom x^8+x^2+x+1 (0x07) and an
|
||||
* initial value of 0xff (see IEC 61158-6-12 ch. 5.4).
|
||||
*
|
||||
* The below code was originally generated with PYCRC
|
||||
* http://www.tty1.net/pycrc
|
||||
*
|
||||
* ./pycrc.py --width=8 --poly=0x07 --reflect-in=0 --xor-in=0xff
|
||||
* --reflect-out=0 --xor-out=0 --generate c --algorithm=bit-by-bit
|
||||
*
|
||||
* \return CRC8
|
||||
*/
|
||||
uint8_t calcSiiCrc(
|
||||
const uint8_t *data, /**< pointer to data */
|
||||
size_t length /**< number of bytes in \a data */
|
||||
)
|
||||
{
|
||||
unsigned int i;
|
||||
uint8_t bit, byte, crc = 0x48;
|
||||
|
||||
while (length--) {
|
||||
byte = *data++;
|
||||
for (i = 0; i < 8; i++) {
|
||||
bit = crc & 0x80;
|
||||
crc = (crc << 1) | ((byte >> (7 - i)) & 0x01);
|
||||
if (bit) crc ^= 0x07;
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < 8; i++) {
|
||||
bit = crc & 0x80;
|
||||
crc <<= 1;
|
||||
if (bit) crc ^= 0x07;
|
||||
}
|
||||
|
||||
return crc;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/** Writes the Secondary slave address (alias) to the slave's SII.
|
||||
*/
|
||||
void writeSlaveAlias(
|
||||
|
|
|
|||
|
|
@ -0,0 +1,78 @@
|
|||
/*****************************************************************************
|
||||
*
|
||||
* $Id$
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#include <iostream>
|
||||
using namespace std;
|
||||
|
||||
#include "globals.h"
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
const char *help_data =
|
||||
"[OPTIONS]\n"
|
||||
"\n"
|
||||
"Output binary domain data.\n"
|
||||
"\n"
|
||||
"Command-specific options:\n"
|
||||
" --domain -d <index> Positive numerical domain index. If this option\n"
|
||||
" is not specified, data of all domains are\n"
|
||||
" output.\n";
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
void outputDomainData(unsigned int);
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
void command_data()
|
||||
{
|
||||
masterDev.open(MasterDevice::Read);
|
||||
|
||||
if (domainIndex == -1) {
|
||||
unsigned int i;
|
||||
ec_ioctl_master_t master;
|
||||
|
||||
masterDev.getMaster(&master);
|
||||
|
||||
for (i = 0; i < master.domain_count; i++) {
|
||||
outputDomainData(i);
|
||||
}
|
||||
} else {
|
||||
outputDomainData(domainIndex);
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
void outputDomainData(unsigned int domainIndex)
|
||||
{
|
||||
ec_ioctl_domain_t domain;
|
||||
ec_ioctl_domain_data_t data;
|
||||
unsigned char *processData;
|
||||
unsigned int i;
|
||||
|
||||
masterDev.getDomain(&domain, domainIndex);
|
||||
|
||||
if (!domain.data_size)
|
||||
return;
|
||||
|
||||
processData = new unsigned char[domain.data_size];
|
||||
|
||||
try {
|
||||
masterDev.getData(&data, domainIndex, domain.data_size, processData);
|
||||
} catch (MasterDeviceException &e) {
|
||||
delete [] processData;
|
||||
throw e;
|
||||
}
|
||||
|
||||
for (i = 0; i < data.data_size; i++)
|
||||
cout << processData[i];
|
||||
cout.flush();
|
||||
|
||||
delete [] processData;
|
||||
}
|
||||
|
||||
/****************************************************************************/
|
||||
|
|
@ -0,0 +1,48 @@
|
|||
/*****************************************************************************
|
||||
*
|
||||
* $Id$
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#include <sstream>
|
||||
#include <iomanip>
|
||||
using namespace std;
|
||||
|
||||
#include "globals.h"
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
const char *help_debug =
|
||||
"[OPTIONS]\n"
|
||||
"\n"
|
||||
"\n"
|
||||
"Command-specific options:\n";
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
void command_debug(void)
|
||||
{
|
||||
stringstream str;
|
||||
int debugLevel;
|
||||
|
||||
if (commandArgs.size() != 1) {
|
||||
stringstream err;
|
||||
err << "'debug' takes exactly one argument!";
|
||||
throw MasterDeviceException(err.str());
|
||||
}
|
||||
|
||||
str << commandArgs[0];
|
||||
str >> resetiosflags(ios::basefield) // guess base from prefix
|
||||
>> debugLevel;
|
||||
|
||||
if (str.fail()) {
|
||||
stringstream err;
|
||||
err << "Invalid debug level '" << commandArgs[0] << "'!";
|
||||
throw MasterDeviceException(err.str());
|
||||
}
|
||||
|
||||
masterDev.open(MasterDevice::ReadWrite);
|
||||
masterDev.setDebug(debugLevel);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
|
@ -0,0 +1,115 @@
|
|||
/*****************************************************************************
|
||||
*
|
||||
* $Id$
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#include <iostream>
|
||||
#include <iomanip>
|
||||
using namespace std;
|
||||
|
||||
#include "globals.h"
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
const char *help_domains =
|
||||
"[OPTIONS]\n"
|
||||
"\n"
|
||||
"\n"
|
||||
"Command-specific options:\n";
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
void showDomain(unsigned int);
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
void command_domains(void)
|
||||
{
|
||||
masterDev.open(MasterDevice::Read);
|
||||
|
||||
if (domainIndex == -1) {
|
||||
unsigned int i;
|
||||
ec_ioctl_master_t master;
|
||||
|
||||
masterDev.getMaster(&master);
|
||||
|
||||
for (i = 0; i < master.domain_count; i++) {
|
||||
showDomain(i);
|
||||
}
|
||||
} else {
|
||||
showDomain(domainIndex);
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
void showDomain(unsigned int domainIndex)
|
||||
{
|
||||
ec_ioctl_domain_t domain;
|
||||
unsigned char *processData;
|
||||
ec_ioctl_domain_data_t data;
|
||||
unsigned int i, j;
|
||||
ec_ioctl_domain_fmmu_t fmmu;
|
||||
unsigned int dataOffset;
|
||||
|
||||
masterDev.getDomain(&domain, domainIndex);
|
||||
|
||||
cout << "Domain" << dec << domainIndex << ":"
|
||||
<< " LogBaseAddr 0x"
|
||||
<< hex << setfill('0')
|
||||
<< setw(8) << domain.logical_base_address
|
||||
<< ", Size " << dec << setfill(' ')
|
||||
<< setw(3) << domain.data_size
|
||||
<< ", WorkingCounter "
|
||||
<< domain.working_counter << "/"
|
||||
<< domain.expected_working_counter << endl;
|
||||
|
||||
if (!domain.data_size || verbosity != Verbose)
|
||||
return;
|
||||
|
||||
processData = new unsigned char[domain.data_size];
|
||||
|
||||
try {
|
||||
masterDev.getData(&data, domainIndex, domain.data_size, processData);
|
||||
} catch (MasterDeviceException &e) {
|
||||
delete [] processData;
|
||||
throw e;
|
||||
}
|
||||
|
||||
for (i = 0; i < domain.fmmu_count; i++) {
|
||||
masterDev.getFmmu(&fmmu, domainIndex, i);
|
||||
|
||||
cout << " SlaveConfig "
|
||||
<< dec << fmmu.slave_config_alias
|
||||
<< ":" << fmmu.slave_config_position
|
||||
<< ", SM" << (unsigned int) fmmu.sync_index << " ("
|
||||
<< setfill(' ') << setw(6)
|
||||
<< (fmmu.dir == EC_DIR_INPUT ? "Input" : "Output")
|
||||
<< "), LogAddr 0x"
|
||||
<< hex << setfill('0')
|
||||
<< setw(8) << fmmu.logical_address
|
||||
<< ", Size " << dec << fmmu.data_size << endl;
|
||||
|
||||
dataOffset = fmmu.logical_address - domain.logical_base_address;
|
||||
if (dataOffset + fmmu.data_size > domain.data_size) {
|
||||
stringstream err;
|
||||
err << "Fmmu information corrupted!";
|
||||
delete [] processData;
|
||||
throw MasterDeviceException(err.str());
|
||||
}
|
||||
|
||||
cout << " " << hex << setfill('0');
|
||||
for (j = 0; j < fmmu.data_size; j++) {
|
||||
if (j && !(j % BreakAfterBytes))
|
||||
cout << endl << " ";
|
||||
cout << setw(2)
|
||||
<< (unsigned int) *(processData + dataOffset + j) << " ";
|
||||
}
|
||||
cout << endl;
|
||||
}
|
||||
|
||||
delete [] processData;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
|
@ -0,0 +1,74 @@
|
|||
/*****************************************************************************
|
||||
*
|
||||
* $Id$
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#include <iostream>
|
||||
#include <iomanip>
|
||||
using namespace std;
|
||||
|
||||
#include "globals.h"
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
const char *help_master =
|
||||
"[OPTIONS]\n"
|
||||
"\n"
|
||||
"\n"
|
||||
"Command-specific options:\n";
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
void command_master(void)
|
||||
{
|
||||
ec_ioctl_master_t data;
|
||||
stringstream err;
|
||||
unsigned int i;
|
||||
|
||||
masterDev.open(MasterDevice::Read);
|
||||
masterDev.getMaster(&data);
|
||||
|
||||
cout
|
||||
<< "Master" << masterIndex << endl
|
||||
<< " Phase: ";
|
||||
|
||||
switch (data.phase) {
|
||||
case 0: cout << "Waiting for device..."; break;
|
||||
case 1: cout << "Idle"; break;
|
||||
case 2: cout << "Operation"; break;
|
||||
default:
|
||||
err << "Invalid master phase " << data.phase;
|
||||
throw MasterDeviceException(err.str());
|
||||
}
|
||||
|
||||
cout << endl
|
||||
<< " Slaves: " << data.slave_count << endl;
|
||||
|
||||
for (i = 0; i < 2; i++) {
|
||||
cout << " Device" << i << ": ";
|
||||
if (data.devices[i].address[0] == 0x00
|
||||
&& data.devices[i].address[1] == 0x00
|
||||
&& data.devices[i].address[2] == 0x00
|
||||
&& data.devices[i].address[3] == 0x00
|
||||
&& data.devices[i].address[4] == 0x00
|
||||
&& data.devices[i].address[5] == 0x00) {
|
||||
cout << "None.";
|
||||
} else {
|
||||
cout << hex << setfill('0')
|
||||
<< setw(2) << (unsigned int) data.devices[i].address[0] << ":"
|
||||
<< setw(2) << (unsigned int) data.devices[i].address[1] << ":"
|
||||
<< setw(2) << (unsigned int) data.devices[i].address[2] << ":"
|
||||
<< setw(2) << (unsigned int) data.devices[i].address[3] << ":"
|
||||
<< setw(2) << (unsigned int) data.devices[i].address[4] << ":"
|
||||
<< setw(2) << (unsigned int) data.devices[i].address[5] << " ("
|
||||
<< (data.devices[i].attached ? "attached" : "waiting...")
|
||||
<< ")" << endl << dec
|
||||
<< " Tx count: " << data.devices[i].tx_count << endl
|
||||
<< " Rx count: " << data.devices[i].rx_count;
|
||||
}
|
||||
cout << endl;
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
|
@ -0,0 +1,98 @@
|
|||
/*****************************************************************************
|
||||
*
|
||||
* $Id$
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#include <iostream>
|
||||
#include <iomanip>
|
||||
using namespace std;
|
||||
|
||||
#include "globals.h"
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
const char *help_pdos =
|
||||
"[OPTIONS]\n"
|
||||
"\n"
|
||||
"\n"
|
||||
"Command-specific options:\n";
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
void listSlavePdos(uint16_t, bool);
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
void command_pdos(void)
|
||||
{
|
||||
masterDev.open(MasterDevice::Read);
|
||||
|
||||
if (slavePosition == -1) {
|
||||
unsigned int numSlaves = masterDev.slaveCount(), i;
|
||||
|
||||
for (i = 0; i < numSlaves; i++) {
|
||||
listSlavePdos(i, true);
|
||||
}
|
||||
} else {
|
||||
listSlavePdos(slavePosition, false);
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
void listSlavePdos(uint16_t slavePosition, bool withHeader)
|
||||
{
|
||||
ec_ioctl_slave_t slave;
|
||||
ec_ioctl_slave_sync_t sync;
|
||||
ec_ioctl_slave_sync_pdo_t pdo;
|
||||
ec_ioctl_slave_sync_pdo_entry_t entry;
|
||||
unsigned int i, j, k;
|
||||
|
||||
masterDev.getSlave(&slave, slavePosition);
|
||||
|
||||
if (withHeader)
|
||||
cout << "=== Slave " << slavePosition << " ===" << endl;
|
||||
|
||||
for (i = 0; i < slave.sync_count; i++) {
|
||||
masterDev.getSync(&sync, slavePosition, i);
|
||||
|
||||
cout << "SM" << i << ":"
|
||||
<< " PhysAddr 0x"
|
||||
<< hex << setfill('0')
|
||||
<< setw(4) << sync.physical_start_address
|
||||
<< ", DefaultSize "
|
||||
<< dec << setfill(' ') << setw(4) << sync.default_size
|
||||
<< ", ControlRegister 0x"
|
||||
<< hex << setfill('0') << setw(2)
|
||||
<< (unsigned int) sync.control_register
|
||||
<< ", Enable " << dec << (unsigned int) sync.enable
|
||||
<< endl;
|
||||
|
||||
for (j = 0; j < sync.pdo_count; j++) {
|
||||
masterDev.getPdo(&pdo, slavePosition, i, j);
|
||||
|
||||
cout << " " << (sync.control_register & 0x04 ? "R" : "T")
|
||||
<< "xPdo 0x"
|
||||
<< hex << setfill('0')
|
||||
<< setw(4) << pdo.index
|
||||
<< " \"" << pdo.name << "\"" << endl;
|
||||
|
||||
if (verbosity == Quiet)
|
||||
continue;
|
||||
|
||||
for (k = 0; k < pdo.entry_count; k++) {
|
||||
masterDev.getPdoEntry(&entry, slavePosition, i, j, k);
|
||||
|
||||
cout << " Pdo entry 0x"
|
||||
<< hex << setfill('0')
|
||||
<< setw(4) << entry.index
|
||||
<< ":" << setw(2) << (unsigned int) entry.subindex
|
||||
<< ", " << dec << (unsigned int) entry.bit_length
|
||||
<< " bit, \"" << entry.name << "\"" << endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
|
@ -0,0 +1,180 @@
|
|||
/*****************************************************************************
|
||||
*
|
||||
* $Id$
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#include <iostream>
|
||||
#include <iomanip>
|
||||
using namespace std;
|
||||
|
||||
#include "globals.h"
|
||||
#include "coe_datatypes.h"
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
const char *help_sdo_download =
|
||||
"[OPTIONS]\n"
|
||||
"\n"
|
||||
"\n"
|
||||
"Command-specific options:\n";
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
void command_sdo_download(void)
|
||||
{
|
||||
stringstream strIndex, strSubIndex, strValue, err;
|
||||
ec_ioctl_slave_sdo_download_t data;
|
||||
unsigned int number;
|
||||
const CoEDataType *dataType = NULL;
|
||||
|
||||
if (slavePosition < 0) {
|
||||
err << "'sdo_download' requires a slave! Please specify --slave.";
|
||||
throw MasterDeviceException(err.str());
|
||||
}
|
||||
data.slave_position = slavePosition;
|
||||
|
||||
if (commandArgs.size() != 3) {
|
||||
err << "'sdo_download' takes 3 arguments!";
|
||||
throw MasterDeviceException(err.str());
|
||||
}
|
||||
|
||||
strIndex << commandArgs[0];
|
||||
strIndex
|
||||
>> resetiosflags(ios::basefield) // guess base from prefix
|
||||
>> data.sdo_index;
|
||||
if (strIndex.fail()) {
|
||||
err << "Invalid Sdo index '" << commandArgs[0] << "'!";
|
||||
throw MasterDeviceException(err.str());
|
||||
}
|
||||
|
||||
strSubIndex << commandArgs[1];
|
||||
strSubIndex
|
||||
>> resetiosflags(ios::basefield) // guess base from prefix
|
||||
>> number;
|
||||
if (strSubIndex.fail() || number > 0xff) {
|
||||
err << "Invalid Sdo subindex '" << commandArgs[1] << "'!";
|
||||
throw MasterDeviceException(err.str());
|
||||
}
|
||||
data.sdo_entry_subindex = number;
|
||||
|
||||
if (dataTypeStr != "") { // data type specified
|
||||
if (!(dataType = findDataType(dataTypeStr))) {
|
||||
err << "Invalid data type '" << dataTypeStr << "'!";
|
||||
throw MasterDeviceException(err.str());
|
||||
}
|
||||
} else { // no data type specified: fetch from dictionary
|
||||
ec_ioctl_slave_sdo_entry_t entry;
|
||||
|
||||
masterDev.open(MasterDevice::ReadWrite);
|
||||
|
||||
try {
|
||||
masterDev.getSdoEntry(&entry, slavePosition,
|
||||
data.sdo_index, data.sdo_entry_subindex);
|
||||
} catch (MasterDeviceException &e) {
|
||||
err << "Failed to determine Sdo entry data type. "
|
||||
<< "Please specify --type.";
|
||||
throw ExecutionFailureException(err);
|
||||
}
|
||||
if (!(dataType = findDataType(entry.data_type))) {
|
||||
err << "Pdo entry has unknown data type 0x"
|
||||
<< hex << setfill('0') << setw(4) << entry.data_type << "!"
|
||||
<< " Please specify --type.";
|
||||
throw ExecutionFailureException(err);
|
||||
}
|
||||
}
|
||||
|
||||
if (dataType->byteSize) {
|
||||
data.data_size = dataType->byteSize;
|
||||
} else {
|
||||
data.data_size = DefaultBufferSize;
|
||||
}
|
||||
|
||||
data.data = new uint8_t[data.data_size + 1];
|
||||
|
||||
strValue << commandArgs[2];
|
||||
strValue >> resetiosflags(ios::basefield); // guess base from prefix
|
||||
strValue.exceptions(ios::failbit);
|
||||
|
||||
try {
|
||||
switch (dataType->coeCode) {
|
||||
case 0x0002: // 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 = val;
|
||||
break;
|
||||
}
|
||||
case 0x0003: // int16
|
||||
{
|
||||
int16_t val;
|
||||
strValue >> val;
|
||||
*(int16_t *) data.data = cputole16(val);
|
||||
break;
|
||||
}
|
||||
case 0x0004: // int32
|
||||
{
|
||||
int32_t val;
|
||||
strValue >> val;
|
||||
*(int32_t *) data.data = cputole32(val);
|
||||
break;
|
||||
}
|
||||
case 0x0005: // uint8
|
||||
{
|
||||
uint16_t val; // uint8_t is interpreted as char
|
||||
strValue >> val;
|
||||
if (val > 0xff)
|
||||
throw ios::failure("Value out of range");
|
||||
*data.data = val;
|
||||
break;
|
||||
}
|
||||
case 0x0006: // uint16
|
||||
{
|
||||
uint16_t val;
|
||||
strValue >> val;
|
||||
*(uint16_t *) data.data = cputole16(val);
|
||||
break;
|
||||
}
|
||||
case 0x0007: // uint32
|
||||
{
|
||||
uint32_t val;
|
||||
strValue >> val;
|
||||
*(uint32_t *) data.data = cputole32(val);
|
||||
break;
|
||||
}
|
||||
case 0x0009: // string
|
||||
if (strValue.str().size() >= data.data_size) {
|
||||
err << "String too large";
|
||||
throw MasterDeviceException(err.str());
|
||||
}
|
||||
data.data_size = strValue.str().size();
|
||||
strValue >> (char *) data.data;
|
||||
break;
|
||||
|
||||
default:
|
||||
delete [] data.data;
|
||||
err << "Unknown data type 0x" << hex << dataType->coeCode;
|
||||
throw MasterDeviceException(err.str());
|
||||
}
|
||||
} catch (ios::failure &e) {
|
||||
delete [] data.data;
|
||||
err << "Invalid value argument '" << commandArgs[2]
|
||||
<< "' for type '" << dataType->name << "'!";
|
||||
throw MasterDeviceException(err.str());
|
||||
}
|
||||
|
||||
masterDev.open(MasterDevice::ReadWrite);
|
||||
|
||||
try {
|
||||
masterDev.sdoDownload(&data);
|
||||
} catch(MasterDeviceException &e) {
|
||||
delete [] data.data;
|
||||
throw e;
|
||||
}
|
||||
|
||||
delete [] data.data;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
|
@ -0,0 +1,160 @@
|
|||
/*****************************************************************************
|
||||
*
|
||||
* $Id$
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#include <iostream>
|
||||
#include <iomanip>
|
||||
using namespace std;
|
||||
|
||||
#include "globals.h"
|
||||
#include "coe_datatypes.h"
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
const char *help_sdo_upload =
|
||||
"[OPTIONS]\n"
|
||||
"\n"
|
||||
"\n"
|
||||
"Command-specific options:\n";
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
void command_sdo_upload(void)
|
||||
{
|
||||
stringstream strIndex, strSubIndex;
|
||||
int sval;
|
||||
ec_ioctl_slave_sdo_upload_t data;
|
||||
unsigned int uval;
|
||||
const CoEDataType *dataType = NULL;
|
||||
|
||||
if (slavePosition < 0) {
|
||||
stringstream err;
|
||||
err << "'sdo_upload' requires a slave! Please specify --slave.";
|
||||
throw MasterDeviceException(err.str());
|
||||
}
|
||||
data.slave_position = slavePosition;
|
||||
|
||||
if (commandArgs.size() != 2) {
|
||||
stringstream err;
|
||||
err << "'sdo_upload' takes two arguments!";
|
||||
throw MasterDeviceException(err.str());
|
||||
}
|
||||
|
||||
strIndex << commandArgs[0];
|
||||
strIndex
|
||||
>> resetiosflags(ios::basefield) // guess base from prefix
|
||||
>> data.sdo_index;
|
||||
if (strIndex.fail()) {
|
||||
stringstream err;
|
||||
err << "Invalid Sdo index '" << commandArgs[0] << "'!";
|
||||
throw MasterDeviceException(err.str());
|
||||
}
|
||||
|
||||
strSubIndex << commandArgs[1];
|
||||
strSubIndex
|
||||
>> resetiosflags(ios::basefield) // guess base from prefix
|
||||
>> uval;
|
||||
if (strSubIndex.fail() || uval > 0xff) {
|
||||
stringstream err;
|
||||
err << "Invalid Sdo subindex '" << commandArgs[1] << "'!";
|
||||
throw MasterDeviceException(err.str());
|
||||
}
|
||||
data.sdo_entry_subindex = uval;
|
||||
|
||||
if (dataTypeStr != "") { // data type specified
|
||||
if (!(dataType = findDataType(dataTypeStr))) {
|
||||
stringstream err;
|
||||
err << "Invalid data type '" << dataTypeStr << "'!";
|
||||
throw MasterDeviceException(err.str());
|
||||
}
|
||||
} else { // no data type specified: fetch from dictionary
|
||||
ec_ioctl_slave_sdo_entry_t entry;
|
||||
|
||||
masterDev.open(MasterDevice::Read);
|
||||
|
||||
try {
|
||||
masterDev.getSdoEntry(&entry, slavePosition,
|
||||
data.sdo_index, data.sdo_entry_subindex);
|
||||
} catch (MasterDeviceException &e) {
|
||||
stringstream err;
|
||||
err << "Failed to determine Sdo entry data type. "
|
||||
<< "Please specify --type.";
|
||||
throw ExecutionFailureException(err);
|
||||
}
|
||||
if (!(dataType = findDataType(entry.data_type))) {
|
||||
stringstream err;
|
||||
err << "Pdo entry has unknown data type 0x"
|
||||
<< hex << setfill('0') << setw(4) << entry.data_type << "!"
|
||||
<< " Please specify --type.";
|
||||
throw ExecutionFailureException(err);
|
||||
}
|
||||
}
|
||||
|
||||
if (dataType->byteSize) {
|
||||
data.target_size = dataType->byteSize;
|
||||
} else {
|
||||
data.target_size = DefaultBufferSize;
|
||||
}
|
||||
|
||||
data.target = new uint8_t[data.target_size + 1];
|
||||
|
||||
masterDev.open(MasterDevice::Read);
|
||||
|
||||
try {
|
||||
masterDev.sdoUpload(&data);
|
||||
} catch (MasterDeviceException &e) {
|
||||
delete [] data.target;
|
||||
throw e;
|
||||
}
|
||||
|
||||
masterDev.close();
|
||||
|
||||
if (dataType->byteSize && data.data_size != dataType->byteSize) {
|
||||
stringstream err;
|
||||
err << "Data type mismatch. Expected " << dataType->name
|
||||
<< " with " << dataType->byteSize << " byte, but got "
|
||||
<< data.data_size << " byte.";
|
||||
throw MasterDeviceException(err.str());
|
||||
}
|
||||
|
||||
cout << setfill('0');
|
||||
switch (dataType->coeCode) {
|
||||
case 0x0002: // int8
|
||||
sval = *(int8_t *) data.target;
|
||||
cout << sval << " 0x" << hex << setw(2) << sval << endl;
|
||||
break;
|
||||
case 0x0003: // int16
|
||||
sval = le16tocpu(*(int16_t *) data.target);
|
||||
cout << sval << " 0x" << hex << setw(4) << sval << endl;
|
||||
break;
|
||||
case 0x0004: // int32
|
||||
sval = le32tocpu(*(int32_t *) data.target);
|
||||
cout << sval << " 0x" << hex << setw(8) << sval << endl;
|
||||
break;
|
||||
case 0x0005: // uint8
|
||||
uval = (unsigned int) *(uint8_t *) data.target;
|
||||
cout << uval << " 0x" << hex << setw(2) << uval << endl;
|
||||
break;
|
||||
case 0x0006: // uint16
|
||||
uval = le16tocpu(*(uint16_t *) data.target);
|
||||
cout << uval << " 0x" << hex << setw(4) << uval << endl;
|
||||
break;
|
||||
case 0x0007: // uint32
|
||||
uval = le32tocpu(*(uint32_t *) data.target);
|
||||
cout << uval << " 0x" << hex << setw(8) << uval << endl;
|
||||
break;
|
||||
case 0x0009: // string
|
||||
cout << string((const char *) data.target, data.data_size)
|
||||
<< endl;
|
||||
break;
|
||||
default:
|
||||
printRawData(data.target, data.data_size);
|
||||
break;
|
||||
}
|
||||
|
||||
delete [] data.target;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
|
@ -0,0 +1,92 @@
|
|||
/*****************************************************************************
|
||||
*
|
||||
* $Id$
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#include <iostream>
|
||||
#include <iomanip>
|
||||
using namespace std;
|
||||
|
||||
#include "globals.h"
|
||||
#include "coe_datatypes.h"
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
const char *help_sdos =
|
||||
"[OPTIONS]\n"
|
||||
"\n"
|
||||
"\n"
|
||||
"Command-specific options:\n";
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
void listSlaveSdos(uint16_t, bool);
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
void command_sdos(void)
|
||||
{
|
||||
masterDev.open(MasterDevice::Read);
|
||||
|
||||
if (slavePosition == -1) {
|
||||
unsigned int numSlaves = masterDev.slaveCount(), i;
|
||||
|
||||
for (i = 0; i < numSlaves; i++) {
|
||||
listSlaveSdos(i, true);
|
||||
}
|
||||
} else {
|
||||
listSlaveSdos(slavePosition, false);
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
void listSlaveSdos(
|
||||
uint16_t slavePosition,
|
||||
bool withHeader
|
||||
)
|
||||
{
|
||||
ec_ioctl_slave_t slave;
|
||||
ec_ioctl_slave_sdo_t sdo;
|
||||
ec_ioctl_slave_sdo_entry_t entry;
|
||||
unsigned int i, j;
|
||||
const CoEDataType *d;
|
||||
|
||||
masterDev.getSlave(&slave, slavePosition);
|
||||
|
||||
if (withHeader)
|
||||
cout << "=== Slave " << slavePosition << " ===" << endl;
|
||||
|
||||
for (i = 0; i < slave.sdo_count; i++) {
|
||||
masterDev.getSdo(&sdo, slavePosition, i);
|
||||
|
||||
cout << "Sdo 0x"
|
||||
<< hex << setfill('0')
|
||||
<< setw(4) << sdo.sdo_index
|
||||
<< ", \"" << sdo.name << "\"" << endl;
|
||||
|
||||
if (verbosity == Quiet)
|
||||
continue;
|
||||
|
||||
for (j = 0; j <= sdo.max_subindex; j++) {
|
||||
masterDev.getSdoEntry(&entry, slavePosition, -i, j);
|
||||
|
||||
cout << " 0x" << hex << setfill('0')
|
||||
<< setw(4) << sdo.sdo_index << ":"
|
||||
<< setw(2) << (unsigned int) entry.sdo_entry_subindex
|
||||
<< ", ";
|
||||
|
||||
if ((d = findDataType(entry.data_type))) {
|
||||
cout << d->name;
|
||||
} else {
|
||||
cout << "type " << setw(4) << entry.data_type;
|
||||
}
|
||||
|
||||
cout << ", " << dec << entry.bit_length << " bit, \""
|
||||
<< entry.description << "\"" << endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
|
@ -0,0 +1,157 @@
|
|||
/*****************************************************************************
|
||||
*
|
||||
* $Id$
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#include <iostream>
|
||||
#include <iomanip>
|
||||
using namespace std;
|
||||
|
||||
#include "globals.h"
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
const char *help_sii_read =
|
||||
"[OPTIONS]\n"
|
||||
"\n"
|
||||
"\n"
|
||||
"Command-specific options:\n";
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
struct CategoryName {
|
||||
uint16_t type;
|
||||
const char *name;
|
||||
};
|
||||
|
||||
static const CategoryName categoryNames[] = {
|
||||
{0x000a, "STRINGS"},
|
||||
{0x0014, "DataTypes"},
|
||||
{0x001e, "General"},
|
||||
{0x0028, "FMMU"},
|
||||
{0x0029, "SyncM"},
|
||||
{0x0032, "TXPDO"},
|
||||
{0x0033, "RXPDO"},
|
||||
{0x003c, "DC"},
|
||||
{}
|
||||
};
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
const char *getCategoryName(uint16_t type)
|
||||
{
|
||||
const CategoryName *cn = categoryNames;
|
||||
|
||||
while (cn->type) {
|
||||
if (cn->type == type) {
|
||||
return cn->name;
|
||||
}
|
||||
cn++;
|
||||
}
|
||||
|
||||
return "unknown";
|
||||
}
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
void command_sii_read(void)
|
||||
{
|
||||
ec_ioctl_slave_sii_t data;
|
||||
ec_ioctl_slave_t slave;
|
||||
unsigned int i;
|
||||
const uint16_t *categoryHeader;
|
||||
uint16_t categoryType, categorySize;
|
||||
stringstream err;
|
||||
|
||||
if (slavePosition < 0) {
|
||||
stringstream err;
|
||||
err << "'sii_read' requires a slave! Please specify --slave.";
|
||||
throw MasterDeviceException(err.str());
|
||||
}
|
||||
data.slave_position = slavePosition;
|
||||
|
||||
masterDev.open(MasterDevice::Read);
|
||||
|
||||
masterDev.getSlave(&slave, slavePosition);
|
||||
|
||||
if (!slave.sii_nwords)
|
||||
return;
|
||||
|
||||
data.offset = 0;
|
||||
data.nwords = slave.sii_nwords;
|
||||
data.words = new uint16_t[data.nwords];
|
||||
|
||||
try {
|
||||
masterDev.readSii(&data);
|
||||
} catch (MasterDeviceException &e) {
|
||||
delete [] data.words;
|
||||
throw e;
|
||||
}
|
||||
|
||||
if (verbosity == Verbose) {
|
||||
cout << "SII Area:" << hex << setfill('0');
|
||||
for (i = 0; i < min(data.nwords, 0x0040U) * 2; i++) {
|
||||
if (i % BreakAfterBytes) {
|
||||
cout << " ";
|
||||
} else {
|
||||
cout << endl << " ";
|
||||
}
|
||||
cout << setw(2) << (unsigned int) *((uint8_t *) data.words + i);
|
||||
}
|
||||
cout << endl;
|
||||
|
||||
if (data.nwords > 0x0040U) {
|
||||
// cycle through categories
|
||||
categoryHeader = data.words + 0x0040U;
|
||||
categoryType = le16tocpu(*categoryHeader);
|
||||
while (categoryType != 0xffff) {
|
||||
cout << "SII Category 0x" << hex
|
||||
<< setw(4) << categoryType
|
||||
<< " (" << getCategoryName(categoryType) << ")" << flush;
|
||||
|
||||
if (categoryHeader + 1 > data.words + data.nwords) {
|
||||
err << "SII data seem to be corrupted!";
|
||||
throw MasterDeviceException(err.str());
|
||||
}
|
||||
categorySize = le16tocpu(*(categoryHeader + 1));
|
||||
cout << ", " << dec << categorySize << " words" << flush;
|
||||
|
||||
if (categoryHeader + 2 + categorySize
|
||||
> data.words + data.nwords) {
|
||||
err << "SII data seem to be corrupted!";
|
||||
throw MasterDeviceException(err.str());
|
||||
}
|
||||
|
||||
cout << hex;
|
||||
for (i = 0; i < categorySize * 2U; i++) {
|
||||
if (i % BreakAfterBytes) {
|
||||
cout << " ";
|
||||
} else {
|
||||
cout << endl << " ";
|
||||
}
|
||||
cout << setw(2) << (unsigned int)
|
||||
*((uint8_t *) (categoryHeader + 2) + i);
|
||||
}
|
||||
cout << endl;
|
||||
|
||||
if (categoryHeader + 2 + categorySize + 1
|
||||
> data.words + data.nwords) {
|
||||
err << "SII data seem to be corrupted!";
|
||||
throw MasterDeviceException(err.str());
|
||||
}
|
||||
categoryHeader += 2 + categorySize;
|
||||
categoryType = le16tocpu(*categoryHeader);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (i = 0; i < data.nwords; i++) {
|
||||
uint16_t *w = data.words + i;
|
||||
cout << *(uint8_t *) w << *((uint8_t *) w + 1);
|
||||
}
|
||||
}
|
||||
|
||||
delete [] data.words;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
|
@ -0,0 +1,112 @@
|
|||
/*****************************************************************************
|
||||
*
|
||||
* $Id$
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#include <iostream>
|
||||
#include <iomanip>
|
||||
#include <fstream>
|
||||
using namespace std;
|
||||
|
||||
#include "globals.h"
|
||||
#include "sii_crc.h"
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
const char *help_sii_write =
|
||||
"[OPTIONS]\n"
|
||||
"\n"
|
||||
"\n"
|
||||
"Command-specific options:\n";
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
void command_sii_write(void)
|
||||
{
|
||||
stringstream err;
|
||||
ec_ioctl_slave_sii_t data;
|
||||
ifstream file;
|
||||
unsigned int byte_size;
|
||||
const uint16_t *categoryHeader;
|
||||
uint16_t categoryType, categorySize;
|
||||
uint8_t crc;
|
||||
|
||||
if (slavePosition < 0) {
|
||||
err << "'sii_write' requires a slave! Please specify --slave.";
|
||||
throw MasterDeviceException(err.str());
|
||||
}
|
||||
data.slave_position = slavePosition;
|
||||
|
||||
if (commandArgs.size() != 1) {
|
||||
err << "'ssi_write' takes exactly one argument!";
|
||||
throw MasterDeviceException(err.str());
|
||||
}
|
||||
|
||||
file.open(commandArgs[0].c_str(), ifstream::in | ifstream::binary);
|
||||
if (file.fail()) {
|
||||
err << "Failed to open '" << commandArgs[0] << "'!";
|
||||
throw MasterDeviceException(err.str());
|
||||
}
|
||||
|
||||
// get length of file
|
||||
file.seekg(0, ios::end);
|
||||
byte_size = file.tellg();
|
||||
file.seekg(0, ios::beg);
|
||||
|
||||
if (!byte_size || byte_size % 2) {
|
||||
stringstream err;
|
||||
err << "Invalid file size! Must be non-zero and even.";
|
||||
throw MasterDeviceException(err.str());
|
||||
}
|
||||
|
||||
data.nwords = byte_size / 2;
|
||||
if (data.nwords < 0x0041 && !force) {
|
||||
err << "SII data too short (" << data.nwords << " words)! Mimimum is"
|
||||
" 40 fixed words + 1 delimiter. Use --force to write anyway.";
|
||||
throw MasterDeviceException(err.str());
|
||||
}
|
||||
|
||||
// allocate buffer and read file into buffer
|
||||
data.words = new uint16_t[data.nwords];
|
||||
file.read((char *) data.words, byte_size);
|
||||
file.close();
|
||||
|
||||
if (!force) {
|
||||
// calculate checksum over words 0 to 6
|
||||
crc = calcSiiCrc((const uint8_t *) data.words, 14);
|
||||
if (crc != ((const uint8_t *) data.words)[14]) {
|
||||
err << "CRC incorrect. Must be 0x"
|
||||
<< hex << setfill('0') << setw(2) << (unsigned int) crc
|
||||
<< ". Use --force to write anyway.";
|
||||
throw MasterDeviceException(err.str());
|
||||
}
|
||||
|
||||
// cycle through categories to detect corruption
|
||||
categoryHeader = data.words + 0x0040U;
|
||||
categoryType = le16tocpu(*categoryHeader);
|
||||
while (categoryType != 0xffff) {
|
||||
if (categoryHeader + 1 > data.words + data.nwords) {
|
||||
err << "SII data seem to be corrupted! "
|
||||
<< "Use --force to write anyway.";
|
||||
throw MasterDeviceException(err.str());
|
||||
}
|
||||
categorySize = le16tocpu(*(categoryHeader + 1));
|
||||
if (categoryHeader + 2 + categorySize + 1
|
||||
> data.words + data.nwords) {
|
||||
err << "SII data seem to be corrupted! "
|
||||
"Use --force to write anyway.";
|
||||
throw MasterDeviceException(err.str());
|
||||
}
|
||||
categoryHeader += 2 + categorySize;
|
||||
categoryType = le16tocpu(*categoryHeader);
|
||||
}
|
||||
}
|
||||
|
||||
// send data to master
|
||||
masterDev.open(MasterDevice::ReadWrite);
|
||||
data.offset = 0;
|
||||
masterDev.writeSii(&data);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
|
@ -0,0 +1,254 @@
|
|||
/*****************************************************************************
|
||||
*
|
||||
* $Id$
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#include <iostream>
|
||||
#include <iomanip>
|
||||
#include <list>
|
||||
using namespace std;
|
||||
|
||||
#include "globals.h"
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
const char *help_slaves =
|
||||
"[OPTIONS]\n"
|
||||
"\n"
|
||||
"\n"
|
||||
"Command-specific options:\n";
|
||||
|
||||
void listSlaves(int);
|
||||
void showSlave(uint16_t);
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
void command_slaves()
|
||||
{
|
||||
masterDev.open(MasterDevice::Read);
|
||||
|
||||
if (verbosity == Verbose) {
|
||||
if (slavePosition == -1) {
|
||||
unsigned int numSlaves = masterDev.slaveCount(), i;
|
||||
|
||||
for (i = 0; i < numSlaves; i++) {
|
||||
showSlave(i);
|
||||
}
|
||||
} else {
|
||||
showSlave(slavePosition);
|
||||
}
|
||||
} else {
|
||||
listSlaves(slavePosition);
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
string slaveState(uint8_t state)
|
||||
{
|
||||
switch (state) {
|
||||
case 1: return "INIT";
|
||||
case 2: return "PREOP";
|
||||
case 4: return "SAFEOP";
|
||||
case 8: return "OP";
|
||||
default: return "???";
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
struct SlaveInfo {
|
||||
string pos;
|
||||
string alias;
|
||||
string relPos;
|
||||
string state;
|
||||
string flag;
|
||||
string name;
|
||||
};
|
||||
|
||||
void listSlaves(int slavePosition)
|
||||
{
|
||||
unsigned int numSlaves, i;
|
||||
ec_ioctl_slave_t slave;
|
||||
uint16_t lastAlias, aliasIndex;
|
||||
SlaveInfo slaveInfo;
|
||||
typedef list<SlaveInfo> SlaveInfoList;
|
||||
SlaveInfoList slaveInfoList;
|
||||
SlaveInfoList::const_iterator iter;
|
||||
stringstream str;
|
||||
unsigned int maxPosWidth = 0, maxAliasWidth = 0,
|
||||
maxRelPosWidth = 0, maxStateWidth = 0;
|
||||
|
||||
numSlaves = masterDev.slaveCount();
|
||||
|
||||
lastAlias = 0;
|
||||
aliasIndex = 0;
|
||||
for (i = 0; i < numSlaves; i++) {
|
||||
masterDev.getSlave(&slave, i);
|
||||
|
||||
if (slave.alias) {
|
||||
lastAlias = slave.alias;
|
||||
aliasIndex = 0;
|
||||
}
|
||||
|
||||
if (slavePosition == -1 || i == (unsigned int) slavePosition) {
|
||||
str << dec << i;
|
||||
slaveInfo.pos = str.str();
|
||||
str.clear();
|
||||
str.str("");
|
||||
|
||||
str << lastAlias;
|
||||
slaveInfo.alias = str.str();
|
||||
str.str("");
|
||||
|
||||
str << aliasIndex;
|
||||
slaveInfo.relPos = str.str();
|
||||
str.str("");
|
||||
|
||||
slaveInfo.state = slaveState(slave.state);
|
||||
slaveInfo.flag = (slave.error_flag ? 'E' : '+');
|
||||
|
||||
if (strlen(slave.name)) {
|
||||
slaveInfo.name = slave.name;
|
||||
} else {
|
||||
str << "0x" << hex << setfill('0')
|
||||
<< setw(8) << slave.vendor_id << ":0x"
|
||||
<< setw(8) << slave.product_code;
|
||||
slaveInfo.name = str.str();
|
||||
str.str("");
|
||||
}
|
||||
|
||||
|
||||
slaveInfoList.push_back(slaveInfo);
|
||||
|
||||
if (slaveInfo.pos.length() > maxPosWidth)
|
||||
maxPosWidth = slaveInfo.pos.length();
|
||||
if (slaveInfo.alias.length() > maxAliasWidth)
|
||||
maxAliasWidth = slaveInfo.alias.length();
|
||||
if (slaveInfo.relPos.length() > maxRelPosWidth)
|
||||
maxRelPosWidth = slaveInfo.relPos.length();
|
||||
if (slaveInfo.state.length() > maxStateWidth)
|
||||
maxStateWidth = slaveInfo.state.length();
|
||||
}
|
||||
|
||||
aliasIndex++;
|
||||
}
|
||||
|
||||
for (iter = slaveInfoList.begin(); iter != slaveInfoList.end(); iter++) {
|
||||
cout << setfill(' ') << right
|
||||
<< setw(maxPosWidth) << iter->pos << " "
|
||||
<< setw(maxAliasWidth) << iter->alias
|
||||
<< ":" << left
|
||||
<< setw(maxRelPosWidth) << iter->relPos << " "
|
||||
<< setw(maxStateWidth) << iter->state << " "
|
||||
<< iter->flag << " "
|
||||
<< iter->name << endl;
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
void showSlave(uint16_t slavePosition)
|
||||
{
|
||||
ec_ioctl_slave_t slave;
|
||||
list<string> protoList;
|
||||
list<string>::const_iterator protoIter;
|
||||
|
||||
masterDev.getSlave(&slave, slavePosition);
|
||||
|
||||
cout << "=== Slave " << dec << slavePosition << " ===" << endl;
|
||||
|
||||
if (slave.alias)
|
||||
cout << "Alias: " << slave.alias << endl;
|
||||
|
||||
cout
|
||||
<< "State: " << slaveState(slave.state) << endl
|
||||
<< "Flag: " << (slave.error_flag ? 'E' : '+') << endl
|
||||
<< "Identity:" << endl
|
||||
<< " Vendor Id: 0x"
|
||||
<< hex << setfill('0')
|
||||
<< setw(8) << slave.vendor_id << endl
|
||||
<< " Product code: 0x"
|
||||
<< setw(8) << slave.product_code << endl
|
||||
<< " Revision number: 0x"
|
||||
<< setw(8) << slave.revision_number << endl
|
||||
<< " Serial number: 0x"
|
||||
<< setw(8) << slave.serial_number << endl;
|
||||
|
||||
if (slave.mailbox_protocols) {
|
||||
cout << "Mailboxes:" << endl
|
||||
<< " RX: 0x"
|
||||
<< hex << setw(4) << slave.rx_mailbox_offset << "/"
|
||||
<< dec << slave.rx_mailbox_size
|
||||
<< ", TX: 0x"
|
||||
<< hex << setw(4) << slave.tx_mailbox_offset << "/"
|
||||
<< dec << slave.tx_mailbox_size << endl
|
||||
<< " Supported protocols: ";
|
||||
|
||||
if (slave.mailbox_protocols & EC_MBOX_AOE) {
|
||||
protoList.push_back("AoE");
|
||||
}
|
||||
if (slave.mailbox_protocols & EC_MBOX_EOE) {
|
||||
protoList.push_back("EoE");
|
||||
}
|
||||
if (slave.mailbox_protocols & EC_MBOX_COE) {
|
||||
protoList.push_back("CoE");
|
||||
}
|
||||
if (slave.mailbox_protocols & EC_MBOX_FOE) {
|
||||
protoList.push_back("FoE");
|
||||
}
|
||||
if (slave.mailbox_protocols & EC_MBOX_SOE) {
|
||||
protoList.push_back("SoE");
|
||||
}
|
||||
if (slave.mailbox_protocols & EC_MBOX_VOE) {
|
||||
protoList.push_back("VoE");
|
||||
}
|
||||
|
||||
for (protoIter = protoList.begin(); protoIter != protoList.end();
|
||||
protoIter++) {
|
||||
if (protoIter != protoList.begin())
|
||||
cout << ", ";
|
||||
cout << *protoIter;
|
||||
}
|
||||
cout << endl;
|
||||
}
|
||||
|
||||
if (slave.has_general_category) {
|
||||
cout << "General:" << endl
|
||||
<< " Group: " << slave.group << endl
|
||||
<< " Image name: " << slave.image << endl
|
||||
<< " Order number: " << slave.order << endl
|
||||
<< " Device name: " << slave.name << endl;
|
||||
|
||||
if (slave.mailbox_protocols & EC_MBOX_COE) {
|
||||
cout << " CoE details:" << endl
|
||||
<< " Enable Sdo: "
|
||||
<< (slave.coe_details.enable_sdo ? "yes" : "no") << endl
|
||||
<< " Enable Sdo Info: "
|
||||
<< (slave.coe_details.enable_sdo_info ? "yes" : "no") << endl
|
||||
<< " Enable Pdo Assign: "
|
||||
<< (slave.coe_details.enable_pdo_assign
|
||||
? "yes" : "no") << endl
|
||||
<< " Enable Pdo Configuration: "
|
||||
<< (slave.coe_details.enable_pdo_configuration
|
||||
? "yes" : "no") << endl
|
||||
<< " Enable Upload at startup: "
|
||||
<< (slave.coe_details.enable_upload_at_startup
|
||||
? "yes" : "no") << endl
|
||||
<< " Enable Sdo complete access: "
|
||||
<< (slave.coe_details.enable_sdo_complete_access
|
||||
? "yes" : "no") << endl;
|
||||
}
|
||||
|
||||
cout << " Flags:" << endl
|
||||
<< " Enable SafeOp: "
|
||||
<< (slave.general_flags.enable_safeop ? "yes" : "no") << endl
|
||||
<< " Enable notLRW: "
|
||||
<< (slave.general_flags.enable_not_lrw ? "yes" : "no") << endl
|
||||
<< " Current consumption: "
|
||||
<< dec << slave.current_on_ebus << " mA" << endl;
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
|
@ -0,0 +1,62 @@
|
|||
/*****************************************************************************
|
||||
*
|
||||
* $Id$
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#include <iostream>
|
||||
using namespace std;
|
||||
|
||||
#include "globals.h"
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
const char *help_states =
|
||||
"[OPTIONS]\n"
|
||||
"\n"
|
||||
"\n"
|
||||
"Command-specific options:\n";
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
void command_states(void)
|
||||
{
|
||||
string stateStr;
|
||||
uint8_t state;
|
||||
|
||||
if (commandArgs.size() != 1) {
|
||||
stringstream err;
|
||||
err << "'state' takes exactly one argument!";
|
||||
throw MasterDeviceException(err.str());
|
||||
}
|
||||
|
||||
stateStr = commandArgs[0];
|
||||
transform(stateStr.begin(), stateStr.end(),
|
||||
stateStr.begin(), (int (*) (int)) std::toupper);
|
||||
|
||||
if (stateStr == "INIT") {
|
||||
state = 0x01;
|
||||
} else if (stateStr == "PREOP") {
|
||||
state = 0x02;
|
||||
} else if (stateStr == "SAFEOP") {
|
||||
state = 0x04;
|
||||
} else if (stateStr == "OP") {
|
||||
state = 0x08;
|
||||
} else {
|
||||
stringstream err;
|
||||
err << "Invalid state '" << commandArgs[0] << "'!";
|
||||
throw MasterDeviceException(err.str());
|
||||
}
|
||||
|
||||
masterDev.open(MasterDevice::ReadWrite);
|
||||
|
||||
if (slavePosition == -1) {
|
||||
unsigned int i, numSlaves = masterDev.slaveCount();
|
||||
for (i = 0; i < numSlaves; i++)
|
||||
masterDev.requestState(i, state);
|
||||
} else {
|
||||
masterDev.requestState(slavePosition, state);
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
|
@ -0,0 +1,161 @@
|
|||
/*****************************************************************************
|
||||
*
|
||||
* $Id$
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#include <iostream>
|
||||
#include <iomanip>
|
||||
using namespace std;
|
||||
|
||||
#include "globals.h"
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
const char *help_xml =
|
||||
"[OPTIONS]\n"
|
||||
"\n"
|
||||
"\n"
|
||||
"Command-specific options:\n";
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
void generateSlaveXml(uint16_t);
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
void command_xml(void)
|
||||
{
|
||||
masterDev.open(MasterDevice::Read);
|
||||
|
||||
if (slavePosition == -1) {
|
||||
unsigned int numSlaves = masterDev.slaveCount(), i;
|
||||
|
||||
for (i = 0; i < numSlaves; i++) {
|
||||
generateSlaveXml(i);
|
||||
}
|
||||
} else {
|
||||
generateSlaveXml(slavePosition);
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
void generateSlaveXml(uint16_t slavePosition)
|
||||
{
|
||||
ec_ioctl_slave_t slave;
|
||||
ec_ioctl_slave_sync_t sync;
|
||||
ec_ioctl_slave_sync_pdo_t pdo;
|
||||
string pdoType;
|
||||
ec_ioctl_slave_sync_pdo_entry_t entry;
|
||||
unsigned int i, j, k;
|
||||
|
||||
masterDev.getSlave(&slave, slavePosition);
|
||||
|
||||
cout
|
||||
<< "<?xml version=\"1.0\" ?>" << endl
|
||||
<< " <EtherCATInfo>" << endl
|
||||
<< " <!-- Slave " << slave.position << " -->" << endl
|
||||
<< " <Vendor>" << endl
|
||||
<< " <Id>" << slave.vendor_id << "</Id>" << endl
|
||||
<< " </Vendor>" << endl
|
||||
<< " <Descriptions>" << endl
|
||||
<< " <Devices>" << endl
|
||||
<< " <Device>" << endl
|
||||
<< " <Type ProductCode=\"#x"
|
||||
<< hex << setfill('0') << setw(8) << slave.product_code
|
||||
<< "\" RevisionNo=\"#x"
|
||||
<< hex << setfill('0') << setw(8) << slave.revision_number
|
||||
<< "\">" << slave.order << "</Type>" << endl;
|
||||
|
||||
if (strlen(slave.name)) {
|
||||
cout
|
||||
<< " <Name><![CDATA["
|
||||
<< slave.name
|
||||
<< "]]></Name>" << endl;
|
||||
}
|
||||
|
||||
for (i = 0; i < slave.sync_count; i++) {
|
||||
masterDev.getSync(&sync, slavePosition, i);
|
||||
|
||||
cout
|
||||
<< " <Sm Enable=\"" << dec << (unsigned int) sync.enable
|
||||
<< "\" StartAddress=\"" << sync.physical_start_address
|
||||
<< "\" ControlByte=\"" << (unsigned int) sync.control_register
|
||||
<< "\" DefaultSize=\"" << sync.default_size
|
||||
<< "\" />" << endl;
|
||||
}
|
||||
|
||||
for (i = 0; i < slave.sync_count; i++) {
|
||||
masterDev.getSync(&sync, slavePosition, i);
|
||||
|
||||
for (j = 0; j < sync.pdo_count; j++) {
|
||||
masterDev.getPdo(&pdo, slavePosition, i, j);
|
||||
pdoType = (sync.control_register & 0x04 ? "R" : "T");
|
||||
pdoType += "xPdo";
|
||||
|
||||
cout
|
||||
<< " <" << pdoType
|
||||
<< " Sm=\"" << i << "\" Fixed=\"1\" Mandatory=\"1\">" << endl
|
||||
<< " <Index>#x"
|
||||
<< hex << setfill('0') << setw(4) << pdo.index
|
||||
<< "</Index>" << endl
|
||||
<< " <Name>" << pdo.name << "</Name>" << endl;
|
||||
|
||||
for (k = 0; k < pdo.entry_count; k++) {
|
||||
masterDev.getPdoEntry(&entry, slavePosition, i, j, k);
|
||||
|
||||
cout
|
||||
<< " <Entry>" << endl
|
||||
<< " <Index>#x"
|
||||
<< hex << setfill('0') << setw(4) << entry.index
|
||||
<< "</Index>" << endl;
|
||||
if (entry.index)
|
||||
cout
|
||||
<< " <SubIndex>"
|
||||
<< dec << (unsigned int) entry.subindex
|
||||
<< "</SubIndex>" << endl;
|
||||
|
||||
cout
|
||||
<< " <BitLen>"
|
||||
<< dec << (unsigned int) entry.bit_length
|
||||
<< "</BitLen>" << endl;
|
||||
|
||||
if (entry.index) {
|
||||
cout
|
||||
<< " <Name>" << entry.name
|
||||
<< "</Name>" << endl
|
||||
<< " <DataType>";
|
||||
|
||||
if (entry.bit_length == 1) {
|
||||
cout << "BOOL";
|
||||
} else if (!(entry.bit_length % 8)) {
|
||||
if (entry.bit_length <= 64)
|
||||
cout << "UINT" << (unsigned int) entry.bit_length;
|
||||
else
|
||||
cout << "STRING("
|
||||
<< (unsigned int) (entry.bit_length / 8)
|
||||
<< ")";
|
||||
} else {
|
||||
cerr << "Invalid bit length "
|
||||
<< (unsigned int) entry.bit_length << endl;
|
||||
}
|
||||
|
||||
cout << "</DataType>" << endl;
|
||||
}
|
||||
|
||||
cout << " </Entry>" << endl;
|
||||
}
|
||||
|
||||
cout
|
||||
<< " </" << pdoType << ">" << endl;
|
||||
}
|
||||
}
|
||||
|
||||
cout
|
||||
<< " </Device>" << endl
|
||||
<< " </Devices>" << endl
|
||||
<< " </Descriptions>" << endl
|
||||
<< "</EtherCATInfo>" << endl;
|
||||
}
|
||||
/*****************************************************************************/
|
||||
|
|
@ -0,0 +1,49 @@
|
|||
/*****************************************************************************
|
||||
*
|
||||
* $Id$
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#include "coe_datatypes.h"
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
static const CoEDataType dataTypes[] = {
|
||||
{"int8", 0x0002, 1},
|
||||
{"int16", 0x0003, 2},
|
||||
{"int32", 0x0004, 4},
|
||||
{"uint8", 0x0005, 1},
|
||||
{"uint16", 0x0006, 2},
|
||||
{"uint32", 0x0007, 4},
|
||||
{"string", 0x0009, 0},
|
||||
{"raw", 0xffff, 0},
|
||||
{}
|
||||
};
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
const CoEDataType *findDataType(const string &str)
|
||||
{
|
||||
const CoEDataType *d;
|
||||
|
||||
for (d = dataTypes; d->name; d++)
|
||||
if (str == d->name)
|
||||
return d;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
const CoEDataType *findDataType(uint16_t code)
|
||||
{
|
||||
const CoEDataType *d;
|
||||
|
||||
for (d = dataTypes; d->name; d++)
|
||||
if (code == d->coeCode)
|
||||
return d;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
/*****************************************************************************
|
||||
*
|
||||
* $Id$
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#include <inttypes.h>
|
||||
|
||||
#include <string>
|
||||
using namespace std;
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
struct CoEDataType {
|
||||
const char *name;
|
||||
uint16_t coeCode;
|
||||
unsigned int byteSize;
|
||||
};
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
const CoEDataType *findDataType(const string &);
|
||||
const CoEDataType *findDataType(uint16_t);
|
||||
|
||||
/*****************************************************************************/
|
||||
|
|
@ -22,6 +22,7 @@ enum Verbosity {
|
|||
};
|
||||
|
||||
extern string commandName;
|
||||
extern unsigned int masterIndex;
|
||||
extern int slavePosition;
|
||||
extern int domainIndex;
|
||||
extern vector<string> commandArgs;
|
||||
|
|
@ -87,3 +88,10 @@ class ExecutionFailureException:
|
|||
#endif
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
enum {BreakAfterBytes = 16};
|
||||
enum {DefaultBufferSize = 1024};
|
||||
|
||||
void printRawData(const uint8_t *, unsigned int);
|
||||
|
||||
/****************************************************************************/
|
||||
|
|
|
|||
129
tool/main.cpp
129
tool/main.cpp
|
|
@ -8,8 +8,10 @@
|
|||
#include <libgen.h> // basename()
|
||||
|
||||
#include <iostream>
|
||||
#include <iomanip>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <list>
|
||||
using namespace std;
|
||||
|
||||
#include "globals.h"
|
||||
|
|
@ -36,6 +38,7 @@ struct Command {
|
|||
const char *name;
|
||||
void (*func)(void);
|
||||
const char *helpString;
|
||||
const char *briefDesc;
|
||||
|
||||
int execute(void) const;
|
||||
void displayHelp(void) const;
|
||||
|
|
@ -43,72 +46,73 @@ struct Command {
|
|||
|
||||
/*****************************************************************************/
|
||||
|
||||
#define COMMAND(name) \
|
||||
#define DEFINE_EXTERN_COMMAND(name) \
|
||||
void command_##name(void); \
|
||||
extern const char *help_##name
|
||||
|
||||
#define INIT_COMMAND(name) {#name, command_##name, help_##name}
|
||||
#define INIT_COMMAND(name, desc) \
|
||||
{#name, command_##name, help_##name, desc}
|
||||
|
||||
COMMAND(alias);
|
||||
COMMAND(config);
|
||||
DEFINE_EXTERN_COMMAND(alias);
|
||||
DEFINE_EXTERN_COMMAND(config);
|
||||
DEFINE_EXTERN_COMMAND(data);
|
||||
DEFINE_EXTERN_COMMAND(debug);
|
||||
DEFINE_EXTERN_COMMAND(domains);
|
||||
DEFINE_EXTERN_COMMAND(master);
|
||||
DEFINE_EXTERN_COMMAND(pdos);
|
||||
DEFINE_EXTERN_COMMAND(sdos);
|
||||
DEFINE_EXTERN_COMMAND(sdo_download);
|
||||
DEFINE_EXTERN_COMMAND(sdo_upload);
|
||||
DEFINE_EXTERN_COMMAND(slaves);
|
||||
DEFINE_EXTERN_COMMAND(sii_read);
|
||||
DEFINE_EXTERN_COMMAND(sii_write);
|
||||
DEFINE_EXTERN_COMMAND(states);
|
||||
DEFINE_EXTERN_COMMAND(xml);
|
||||
|
||||
static const Command commands[] = {
|
||||
INIT_COMMAND(alias),
|
||||
INIT_COMMAND(config),
|
||||
INIT_COMMAND(alias, "Write alias addresses."),
|
||||
INIT_COMMAND(config, "Show bus configuration."),
|
||||
INIT_COMMAND(data, "Output binary domain process data."),
|
||||
INIT_COMMAND(debug, "Set the master's debug level."),
|
||||
INIT_COMMAND(domains, "Show domain information."),
|
||||
INIT_COMMAND(master, "Show master information."),
|
||||
INIT_COMMAND(pdos, "List Pdo assignment/mapping."),
|
||||
INIT_COMMAND(sdos, "List Sdo dictionaries."),
|
||||
INIT_COMMAND(sdo_download, "Write an Sdo entry."),
|
||||
INIT_COMMAND(sdo_upload, "Read an Sdo entry."),
|
||||
INIT_COMMAND(slaves, "Show slaves."),
|
||||
INIT_COMMAND(sii_read, "Output a slave's SII contents."),
|
||||
INIT_COMMAND(sii_write, "Write slave's SII contents."),
|
||||
INIT_COMMAND(states, "Request slave states."),
|
||||
INIT_COMMAND(xml, "Generate slave information xmls."),
|
||||
};
|
||||
|
||||
#if 0
|
||||
} else if (command == "data") {
|
||||
master.outputData(domainIndex);
|
||||
} else if (command == "debug") {
|
||||
master.setDebug(commandArgs);
|
||||
} else if (command == "domain") {
|
||||
master.showDomains(domainIndex);
|
||||
} else if (command == "master") {
|
||||
master.showMaster();
|
||||
} else if (command == "pdos") {
|
||||
master.listPdos(slavePosition);
|
||||
} else if (command == "sdos") {
|
||||
master.listSdos(slavePosition);
|
||||
} else if (command == "sdo_download" || command == "sd") {
|
||||
master.sdoDownload(slavePosition, dataTypeStr, commandArgs);
|
||||
} else if (command == "sdo_upload" || command == "su") {
|
||||
master.sdoUpload(slavePosition, dataTypeStr, commandArgs);
|
||||
} else if (command == "slave" || command == "slaves"
|
||||
|| command == "list" || command == "ls") {
|
||||
master.showSlaves(slavePosition);
|
||||
} else if (command == "sii_read" || command == "sr") {
|
||||
master.siiRead(slavePosition);
|
||||
} else if (command == "sii_write" || command == "sw") {
|
||||
master.siiWrite(slavePosition, force, commandArgs);
|
||||
} else if (command == "state") {
|
||||
master.requestStates(slavePosition, commandArgs);
|
||||
} else if (command == "xml") {
|
||||
master.generateXml(slavePosition);
|
||||
#endif
|
||||
static const Command *cmdEnd = commands + sizeof(commands) / sizeof(Command);
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
void printUsage()
|
||||
{
|
||||
const Command *cmd;
|
||||
size_t maxWidth = 0;
|
||||
|
||||
for (cmd = commands; cmd < cmdEnd; cmd++) {
|
||||
if (strlen(cmd->name) > maxWidth) {
|
||||
maxWidth = strlen(cmd->name);
|
||||
}
|
||||
}
|
||||
|
||||
cerr
|
||||
<< "Usage: " << binaryBaseName << " <COMMAND> [OPTIONS]" << endl
|
||||
<< "Commands:" << endl
|
||||
<< " alias Write alias addresses." << endl
|
||||
<< " config Show bus configuration." << endl
|
||||
<< " data Output binary domain process data." << endl
|
||||
<< " debug Set the master's debug level." << endl
|
||||
<< " domain Show domain information." << endl
|
||||
<< " master Show master information." << endl
|
||||
<< " pdos List Pdo assignment/mapping." << endl
|
||||
<< " sdo_download Write an Sdo entry." << endl
|
||||
<< " sdos List Sdo dictionaries." << endl
|
||||
<< " sdo_upload Read an Sdo entry." << endl
|
||||
<< " sii_read Output a slave's SII contents." << endl
|
||||
<< " sii_write Write slave's SII contents." << endl
|
||||
<< " slaves Show slaves." << endl
|
||||
<< " state Request slave states." << endl
|
||||
<< " xml Generate slave information xmls." << endl
|
||||
<< "Commands:" << endl;
|
||||
|
||||
cerr << left;
|
||||
for (cmd = commands; cmd < cmdEnd; cmd++) {
|
||||
cerr << " " << setw(maxWidth) << cmd->name
|
||||
<< " " << cmd->briefDesc << endl;
|
||||
}
|
||||
|
||||
cerr
|
||||
<< "Commands can be generously abbreviated." << endl
|
||||
<< "Global options:" << endl
|
||||
<< " --master -m <master> Index of the master to use. Default: 0"
|
||||
|
|
@ -117,8 +121,6 @@ void printUsage()
|
|||
<< endl
|
||||
<< " or 'all' for all slaves (default)."
|
||||
<< endl
|
||||
<< " --domain -d <index> Positive numerical index,"
|
||||
<< endl
|
||||
<< " or 'all' for all domains (default)."
|
||||
<< endl
|
||||
<< " --type -t <type> Forced Sdo data type." << endl
|
||||
|
|
@ -289,12 +291,11 @@ bool abbrevMatch(const string &abb, const string &full)
|
|||
|
||||
list<const Command *> getMatchingCommands(const string &cmdStr)
|
||||
{
|
||||
const Command *cmd, *endCmd =
|
||||
commands + sizeof(commands) / sizeof(Command);
|
||||
const Command *cmd;
|
||||
list<const Command *> res;
|
||||
|
||||
// find matching commands
|
||||
for (cmd = commands; cmd < endCmd; cmd++) {
|
||||
for (cmd = commands; cmd < cmdEnd; cmd++) {
|
||||
if (abbrevMatch(cmdStr, cmd->name)) {
|
||||
res.push_back(cmd);
|
||||
}
|
||||
|
|
@ -345,3 +346,19 @@ int main(int argc, char **argv)
|
|||
}
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
void printRawData(
|
||||
const uint8_t *data,
|
||||
unsigned int size
|
||||
)
|
||||
{
|
||||
cout << hex << setfill('0');
|
||||
while (size--) {
|
||||
cout << "0x" << setw(2) << (unsigned int) *data++;
|
||||
if (size)
|
||||
cout << " ";
|
||||
}
|
||||
cout << endl;
|
||||
}
|
||||
|
||||
/****************************************************************************/
|
||||
|
|
|
|||
|
|
@ -0,0 +1,50 @@
|
|||
/*****************************************************************************
|
||||
*
|
||||
* $Id$
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#include "sii_crc.h"
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/** Calculates the SII checksum field.
|
||||
*
|
||||
* The checksum is generated with the polynom x^8+x^2+x+1 (0x07) and an
|
||||
* initial value of 0xff (see IEC 61158-6-12 ch. 5.4).
|
||||
*
|
||||
* The below code was originally generated with PYCRC
|
||||
* http://www.tty1.net/pycrc
|
||||
*
|
||||
* ./pycrc.py --width=8 --poly=0x07 --reflect-in=0 --xor-in=0xff
|
||||
* --reflect-out=0 --xor-out=0 --generate c --algorithm=bit-by-bit
|
||||
*
|
||||
* \return CRC8
|
||||
*/
|
||||
uint8_t calcSiiCrc(
|
||||
const uint8_t *data, /**< pointer to data */
|
||||
size_t length /**< number of bytes in \a data */
|
||||
)
|
||||
{
|
||||
unsigned int i;
|
||||
uint8_t bit, byte, crc = 0x48;
|
||||
|
||||
while (length--) {
|
||||
byte = *data++;
|
||||
for (i = 0; i < 8; i++) {
|
||||
bit = crc & 0x80;
|
||||
crc = (crc << 1) | ((byte >> (7 - i)) & 0x01);
|
||||
if (bit) crc ^= 0x07;
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < 8; i++) {
|
||||
bit = crc & 0x80;
|
||||
crc <<= 1;
|
||||
if (bit) crc ^= 0x07;
|
||||
}
|
||||
|
||||
return crc;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
/*****************************************************************************
|
||||
*
|
||||
* $Id$
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#include <iostream>
|
||||
|
||||
uint8_t calcSiiCrc(const uint8_t *, size_t);
|
||||
|
||||
/*****************************************************************************/
|
||||
Loading…
Reference in New Issue