Clang-formatted fake library.

This commit is contained in:
Florian Pose 2025-07-24 11:49:14 +02:00
parent 04c4db80c3
commit 49e82079dc
3 changed files with 723 additions and 625 deletions

93
.clang-format Normal file
View File

@ -0,0 +1,93 @@
---
Language: Cpp
AccessModifierOffset: -2
AlignAfterOpenBracket: AlwaysBreak
AlignConsecutiveAssignments: false
AlignConsecutiveDeclarations: false
AlignConsecutiveMacros: false
AlignEscapedNewlines: DontAlign
AlignOperands: false
AlignTrailingComments: true
AllowAllConstructorInitializersOnNextLine: true
AllowAllArgumentsOnNextLine: false
AllowAllParametersOfDeclarationOnNextLine: false
AllowShortBlocksOnASingleLine: Never
AllowShortCaseLabelsOnASingleLine: false
AllowShortFunctionsOnASingleLine: InlineOnly
AllowShortIfStatementsOnASingleLine: Never
AllowShortLoopsOnASingleLine: false
AlwaysBreakAfterDefinitionReturnType: None
AlwaysBreakAfterReturnType: None
AlwaysBreakBeforeMultilineStrings: false
AlwaysBreakTemplateDeclarations: No
BinPackArguments: false
BinPackParameters: false
BraceWrapping:
AfterCaseLabel: false
AfterClass: true
AfterControlStatement: Never
AfterEnum: false
AfterFunction: true
AfterNamespace: false
AfterStruct: true
AfterUnion: true
AfterExternBlock: false
BeforeCatch: true
BeforeElse: true
IndentBraces: false
SplitEmptyFunction: false
SplitEmptyRecord: false
SplitEmptyNamespace: false
BreakBeforeBinaryOperators: NonAssignment
BreakBeforeBraces: Custom # Same as 'BraceWrapping'
BreakBeforeTernaryOperators: true
BreakConstructorInitializers: AfterColon
BreakInheritanceList: AfterColon
BreakStringLiterals: true
ColumnLimit: 78
CompactNamespaces: true
ConstructorInitializerAllOnOneLineOrOnePerLine: true
ConstructorInitializerIndentWidth: 4
ContinuationIndentWidth: 8
Cpp11BracedListStyle: true
DeriveLineEnding: true
DerivePointerAlignment: false
FixNamespaceComments: true
IncludeBlocks: Preserve
IndentAccessModifiers: true
IndentCaseLabels: true
IndentGotoLabels: true
IndentPPDirectives: None
IndentWidth: 4
InsertBraces: true
KeepEmptyLinesAtTheStartOfBlocks: false
MaxEmptyLinesToKeep: 2
NamespaceIndentation: None
PackConstructorInitializers: Never
PointerAlignment: Right
ReflowComments: true
SortIncludes: false
SortUsingDeclarations: true
SpaceAfterCStyleCast: true
SpaceAfterLogicalNot: false
SpaceAfterTemplateKeyword: true
SpaceBeforeAssignmentOperators: true
SpaceBeforeCpp11BracedList: true
SpaceBeforeCtorInitializerColon: false
SpaceBeforeInheritanceColon: false
SpaceBeforeParens: ControlStatements
SpaceBeforeRangeBasedForLoopColon: true
SpaceBeforeSquareBrackets: false
SpaceInEmptyBlock: false
SpaceInEmptyParentheses: false
SpacesBeforeTrailingComments: 2
SpacesInAngles: false
SpacesInCStyleCastParentheses: false
SpacesInConditionalStatement: false
SpacesInContainerLiterals: false
SpacesInParentheses: false
SpacesInSquareBrackets: false
Standard: Auto
TabWidth: 2
UseTab: Never
...

View File

@ -25,12 +25,13 @@
#include <cstring> #include <cstring>
#include <fstream> #include <fstream>
#include <ios>
#include <iterator>
#include <sstream> #include <sstream>
#include <string> #include <string>
#include <utility>
#include <unordered_set> #include <unordered_set>
#include <iterator> #include <utility>
#include <ios>
#include <sys/stat.h> #include <sys/stat.h>
/****************************************************************************/ /****************************************************************************/
@ -49,28 +50,23 @@ static std::ostream &operator<<(std::ostream &os, const ec_address &a)
static void add_spaces(std::ostream &out, int const num) static void add_spaces(std::ostream &out, int const num)
{ {
for (int i = 0; i < num; ++i) for (int i = 0; i < num; ++i) {
{
out << ' '; out << ' ';
} }
} }
template <typename Map, typename Func> template <typename Map, typename Func> static void
static void map2Json(std::ostream &out, const Map &map, Func &&print_func, map2Json(std::ostream &out, const Map &map, Func &&print_func, int indent = 0)
int indent = 0)
{ {
indent += 4; indent += 4;
out << "{"; out << "{";
bool is_first = true; bool is_first = true;
for (const auto &kv : map) for (const auto &kv : map) {
{ if (is_first) {
if (is_first)
{
out << '\n'; out << '\n';
is_first = false; is_first = false;
} }
else else {
{
out << ",\n"; out << ",\n";
} }
add_spaces(out, indent); add_spaces(out, indent);
@ -84,11 +80,14 @@ static void map2Json(std::ostream &out, const Map &map, Func &&print_func,
out << "}"; out << "}";
} }
/*****************************************************************************
* Pdo
****************************************************************************/
size_t pdo::sizeInBytes() const size_t pdo::sizeInBytes() const
{ {
size_t ans = 0; size_t ans = 0;
for (const auto &entry : entries) for (const auto &entry : entries) {
{
ans += entry.bit_length; ans += entry.bit_length;
} }
return (ans + 7) / 8; return (ans + 7) / 8;
@ -97,10 +96,8 @@ size_t pdo::sizeInBytes() const
Offset pdo::findEntry(uint16_t idx, uint8_t subindex) const Offset pdo::findEntry(uint16_t idx, uint8_t subindex) const
{ {
size_t offset_bits = 0; size_t offset_bits = 0;
for (const auto &entry : entries) for (const auto &entry : entries) {
{ if (entry.index == idx && entry.subindex == subindex) {
if (entry.index == idx && entry.subindex == subindex)
{
return Offset(offset_bits / 8, offset_bits % 8); return Offset(offset_bits / 8, offset_bits % 8);
} }
offset_bits += entry.bit_length; offset_bits += entry.bit_length;
@ -112,10 +109,8 @@ Offset pdo::findEntryByPos(unsigned int entry_pos) const
{ {
size_t offset_bits = 0; size_t offset_bits = 0;
unsigned int pos {0}; unsigned int pos {0};
for (const auto &entry : entries) for (const auto &entry : entries) {
{ if (pos == entry_pos) {
if (pos == entry_pos)
{
return Offset(offset_bits / 8, offset_bits % 8); return Offset(offset_bits / 8, offset_bits % 8);
} }
offset_bits += entry.bit_length; offset_bits += entry.bit_length;
@ -156,8 +151,7 @@ void ecrt_release_master(ec_master_t *master)
* Master * Master
****************************************************************************/ ****************************************************************************/
int ecrt_master_reserve( int ecrt_master_reserve(ec_master_t *master /**< EtherCAT master */
ec_master_t *master /**< EtherCAT master */
) )
{ {
return 0; return 0;
@ -165,8 +159,9 @@ int ecrt_master_reserve(
static const char *getPrefix() static const char *getPrefix()
{ {
if (const auto ans = getenv("FAKE_EC_PREFIX")) if (const auto ans = getenv("FAKE_EC_PREFIX")) {
return ans; return ans;
}
return "/FakeEtherCAT"; return "/FakeEtherCAT";
} }
@ -176,8 +171,8 @@ ec_domain *ec_master::createDomain()
return &domains.back(); return &domains.back();
} }
ec_domain_t *ecrt_master_create_domain( ec_domain_t *
ec_master_t *master /**< EtherCAT master. */ ecrt_master_create_domain(ec_master_t *master /**< EtherCAT master. */
) )
{ {
return master->createDomain(); return master->createDomain();
@ -192,24 +187,25 @@ ec_slave_config_t *ec_master::slave_config(
{ {
const ec_address address {alias, position}; const ec_address address {alias, position};
const auto it = slaves.find(address); const auto it = slaves.find(address);
if (it != slaves.end()) if (it != slaves.end()) {
{
if (it->second.vendor_id == vendor_id if (it->second.vendor_id == vendor_id
&& it->second.product_code == product_code) && it->second.product_code == product_code) {
return &it->second; return &it->second;
else }
{ else {
std::cerr << "Attempted to reconfigure slave (" << alias std::cerr << "Attempted to reconfigure slave (" << alias << ","
<< "," << position << ")!\n"; << position << ")!\n";
return nullptr; return nullptr;
} }
} }
else else {
{ return &slaves.insert(std::make_pair<ec_address, ec_slave_config>(
return &slaves.insert(std::make_pair<ec_address, ec_address {address},
ec_slave_config>(ec_address{address}, ec_slave_config {
ec_slave_config{address, vendor_id, address,
product_code})).first->second; vendor_id,
product_code}))
.first->second;
} }
} }
@ -235,8 +231,8 @@ int ecrt_master_select_reference_clock(
int ecrt_master( int ecrt_master(
ec_master_t *master, /**< EtherCAT master */ ec_master_t *master, /**< EtherCAT master */
ec_master_info_t *master_info /**< Structure that will output the ec_master_info_t *master_info /**< Structure that will output
information */ the information */
) )
{ {
master_info->slave_count = 0; master_info->slave_count = 0;
@ -400,38 +396,38 @@ int ecrt_master_read_idn(
int ec_master::activate() int ec_master::activate()
{ {
for (auto &domain : domains) for (auto &domain : domains) {
{ if (domain.activate()) {
if (domain.activate())
return -1; return -1;
} }
}
{ {
std::ofstream out(rt_ipc_dir + "/" + rt_ipc_name + "_slaves.json"); std::ofstream out(rt_ipc_dir + "/" + rt_ipc_name + "_slaves.json");
if (!out.is_open()) if (!out.is_open()) {
{
std::cerr << "could not dump json.\n"; std::cerr << "could not dump json.\n";
return -1; return -1;
} }
out << "{\n \"slaves\": "; out << "{\n \"slaves\": ";
map2Json(out, slaves, [](std::ostream &out, map2Json(
const ec_slave_config &slave) out,
{ slave.dumpJson(out, 8); }, 4); slaves,
[](std::ostream &out, const ec_slave_config &slave) {
slave.dumpJson(out, 8);
},
4);
out << "\n}\n"; out << "\n}\n";
} }
return rtipc_prepare(rt_ipc.get()); return rtipc_prepare(rt_ipc.get());
} }
int ecrt_master_activate( int ecrt_master_activate(ec_master_t *master /**< EtherCAT master. */
ec_master_t *master /**< EtherCAT master. */
) )
{ {
try try {
{
return master->activate(); return master->activate();
} }
catch (const std::exception &e) catch (const std::exception &e) {
{
std::cerr << "Could not activate: " << e.what() << '\n'; std::cerr << "Could not activate: " << e.what() << '\n';
return -1; return -1;
} }
@ -447,8 +443,7 @@ int ec_master::deactivate()
return 0; return 0;
} }
int ecrt_master_deactivate( int ecrt_master_deactivate(ec_master_t *master /**< EtherCAT master. */
ec_master_t *master /**< EtherCAT master. */
) )
{ {
return master->deactivate(); return master->deactivate();
@ -462,15 +457,13 @@ int ecrt_master_set_send_interval(
return 0; return 0;
} }
int ecrt_master_send( int ecrt_master_send(ec_master_t *master /**< EtherCAT master. */
ec_master_t *master /**< EtherCAT master. */
) )
{ {
return 0; return 0;
} }
int ecrt_master_receive( int ecrt_master_receive(ec_master_t *master /**< EtherCAT master. */
ec_master_t *master /**< EtherCAT master. */
) )
{ {
return 0; return 0;
@ -524,8 +517,7 @@ int ecrt_master_sync_reference_clock_to(
return 0; return 0;
} }
int ecrt_master_sync_slave_clocks( int ecrt_master_sync_slave_clocks(ec_master_t *master /**< EtherCAT master. */
ec_master_t *master /**< EtherCAT master. */
) )
{ {
return 0; return 0;
@ -554,8 +546,7 @@ uint32_t ecrt_master_sync_monitor_process(
return 32; return 32;
} }
int ecrt_master_reset( int ecrt_master_reset(ec_master_t *master /**< EtherCAT master. */
ec_master_t *master /**< EtherCAT master. */
) )
{ {
return 0; return 0;
@ -563,18 +554,16 @@ int ecrt_master_reset(
static int mkpath(const std::string &file_path) static int mkpath(const std::string &file_path)
{ {
if (file_path.empty()) if (file_path.empty()) {
return 0; return 0;
}
std::size_t offset = 0; std::size_t offset = 0;
do do {
{
offset = file_path.find('/', offset + 1); offset = file_path.find('/', offset + 1);
const auto subpath = file_path.substr(0, offset); const auto subpath = file_path.substr(0, offset);
if (mkdir(subpath.c_str(), 0755) == -1) if (mkdir(subpath.c_str(), 0755) == -1) {
{ if (errno != EEXIST) {
if (errno != EEXIST)
{
return -1; return -1;
} }
} }
@ -585,8 +574,7 @@ static int mkpath(const std::string &file_path)
static std::string getRtIpcDir(int idx) static std::string getRtIpcDir(int idx)
{ {
std::string ans; std::string ans;
if (const auto e = getenv("FAKE_EC_HOMEDIR")) if (const auto e = getenv("FAKE_EC_HOMEDIR")) {
{
ans = e + std::string("/") + std::to_string(idx); ans = e + std::string("/") + std::to_string(idx);
} }
ans = "/tmp/FakeEtherCAT/" + std::to_string(idx); ans = "/tmp/FakeEtherCAT/" + std::to_string(idx);
@ -598,13 +586,11 @@ static const char *getName()
{ {
static const char *default_name = "FakeEtherCAT"; static const char *default_name = "FakeEtherCAT";
if (const auto ans = getenv("FAKE_EC_NAME")) if (const auto ans = getenv("FAKE_EC_NAME")) {
{
return ans; return ans;
} }
std::cerr std::cerr << "\nThe environment variable \"FAKE_EC_NAME\" is not set.\n"
<< "\nThe environment variable \"FAKE_EC_NAME\" is not set.\n"
<< "Using the default value \"" << default_name << "\".\n" << "Using the default value \"" << default_name << "\".\n"
<< "Please consider to set unique names when using multiple" << "Please consider to set unique names when using multiple"
<< " instances.\n\n"; << " instances.\n\n";
@ -617,8 +603,7 @@ ec_master::ec_master(int id):
rt_ipc_name(getName()), rt_ipc_name(getName()),
rt_ipc(rtipc_create(rt_ipc_name.c_str(), rt_ipc_dir.c_str())), rt_ipc(rtipc_create(rt_ipc_name.c_str(), rt_ipc_dir.c_str())),
id_(id) id_(id)
{ {}
}
/***************************************************************************** /*****************************************************************************
* Slave Configuration * Slave Configuration
@ -687,7 +672,6 @@ int ecrt_slave_config_pdo_mapping_add(
for (auto smIt = sc->sync_managers.begin(); for (auto smIt = sc->sync_managers.begin();
smIt != sc->sync_managers.end(); smIt != sc->sync_managers.end();
++smIt) { ++smIt) {
auto pdo_it = smIt->second.pdos.find(pdo_index); auto pdo_it = smIt->second.pdos.find(pdo_index);
if (pdo_it == smIt->second.pdos.end()) { if (pdo_it == smIt->second.pdos.end()) {
continue; continue;
@ -736,28 +720,25 @@ int ecrt_slave_config_pdos(
configurations. */ configurations. */
) )
{ {
if (!syncs) if (!syncs) {
return 0; return 0;
for (unsigned int sync_idx = 0; sync_idx < n_syncs; ++sync_idx) }
{ for (unsigned int sync_idx = 0; sync_idx < n_syncs; ++sync_idx) {
if (syncs[sync_idx].index == 0xff) if (syncs[sync_idx].index == 0xff) {
{
return 0; return 0;
} }
auto &syncManager = sc->sync_managers[syncs[sync_idx].index]; auto &syncManager = sc->sync_managers[syncs[sync_idx].index];
syncManager.dir = syncs[sync_idx].dir; syncManager.dir = syncs[sync_idx].dir;
for (unsigned int i = 0; i < syncs[sync_idx].n_pdos; ++i) for (unsigned int i = 0; i < syncs[sync_idx].n_pdos; ++i) {
{
const auto &in_pdo = syncs[sync_idx].pdos[i]; const auto &in_pdo = syncs[sync_idx].pdos[i];
if (in_pdo.n_entries == 0 || !in_pdo.entries) if (in_pdo.n_entries == 0 || !in_pdo.entries) {
{
std::cerr << "Default mapping not supported."; std::cerr << "Default mapping not supported.";
return -1; return -1;
} }
auto &out_pdo = syncManager.pdos[in_pdo.index]; auto &out_pdo = syncManager.pdos[in_pdo.index];
for (unsigned int pdo_entry_idx = 0; for (unsigned int pdo_entry_idx = 0;
pdo_entry_idx < in_pdo.n_entries; ++pdo_entry_idx) pdo_entry_idx < in_pdo.n_entries;
{ ++pdo_entry_idx) {
out_pdo.entries.push_back(in_pdo.entries[pdo_entry_idx]); out_pdo.entries.push_back(in_pdo.entries[pdo_entry_idx]);
} }
} }
@ -775,30 +756,25 @@ int ecrt_slave_config_reg_pdo_entry(
is desired */ is desired */
) )
{ {
for (auto sync_it : sc->sync_managers) for (auto sync_it : sc->sync_managers) {
{ for (auto pdo_it : sync_it.second.pdos) {
for (auto pdo_it : sync_it.second.pdos) const auto offset =
{ pdo_it.second.findEntry(entry_index, entry_subindex);
const auto offset = pdo_it.second.findEntry(entry_index, if (offset != NotFound) {
entry_subindex);
if (offset != NotFound)
{
const auto domain_offset = const auto domain_offset =
domain->map(*sc, sync_it.first, pdo_it.first); domain->map(*sc, sync_it.first, pdo_it.first);
if (domain_offset != -1) if (domain_offset != -1) {
{ if (bit_position) {
if (bit_position)
*bit_position = offset.bits; *bit_position = offset.bits;
else if (offset.bits) }
{ else if (offset.bits) {
std::cerr << "Pdo Entry is not byte aligned" std::cerr << "Pdo Entry is not byte aligned"
<< " but bit offset is ignored!\n"; << " but bit offset is ignored!\n";
return -1; return -1;
} }
return domain_offset + offset.bytes; return domain_offset + offset.bytes;
} }
else else {
{
return -1; return -1;
} }
} }
@ -828,8 +804,7 @@ int ecrt_slave_config_reg_pdo_entry_pos(
} }
const auto offset = pdo_it->second.findEntryByPos(entry_pos); const auto offset = pdo_it->second.findEntryByPos(entry_pos);
if (offset != NotFound) if (offset != NotFound) {
{
return -1; return -1;
} }
@ -841,8 +816,7 @@ int ecrt_slave_config_reg_pdo_entry_pos(
if (bit_position) { if (bit_position) {
*bit_position = offset.bits; *bit_position = offset.bits;
} }
else if (offset.bits) else if (offset.bits) {
{
std::cerr << "Pdo Entry is not byte aligned" std::cerr << "Pdo Entry is not byte aligned"
<< " but bit offset is ignored!\n"; << " but bit offset is ignored!\n";
return -1; return -1;
@ -894,8 +868,12 @@ int ecrt_slave_config_sdo16(
{ {
uint8_t buf[sizeof(value)]; uint8_t buf[sizeof(value)];
memcpy(&buf, &value, sizeof(value)); memcpy(&buf, &value, sizeof(value));
return ecrt_slave_config_sdo(sc, sdo_index, sdo_subindex, return ecrt_slave_config_sdo(
buf, sizeof(buf)); sc,
sdo_index,
sdo_subindex,
buf,
sizeof(buf));
} }
int ecrt_slave_config_sdo32( int ecrt_slave_config_sdo32(
@ -907,8 +885,12 @@ int ecrt_slave_config_sdo32(
{ {
uint8_t buf[sizeof(value)]; uint8_t buf[sizeof(value)];
memcpy(&buf, &value, sizeof(value)); memcpy(&buf, &value, sizeof(value));
return ecrt_slave_config_sdo(sc, sdo_index, sdo_subindex, return ecrt_slave_config_sdo(
buf, sizeof(buf)); sc,
sdo_index,
sdo_subindex,
buf,
sizeof(buf));
} }
int ecrt_slave_config_complete_sdo( int ecrt_slave_config_complete_sdo(
@ -1003,8 +985,8 @@ int ecrt_slave_config_idn(
ec_slave_config_t *sc, /**< Slave configuration. */ ec_slave_config_t *sc, /**< Slave configuration. */
uint8_t drive_no, /**< Drive number. */ uint8_t drive_no, /**< Drive number. */
uint16_t idn, /**< SoE IDN. */ uint16_t idn, /**< SoE IDN. */
ec_al_state_t state, /**< AL state in which to write the IDN (PREOP or ec_al_state_t state, /**< AL state in which to write
SAFEOP). */ the IDN (PREOP or SAFEOP). */
const uint8_t *data, /**< Pointer to the data. */ const uint8_t *data, /**< Pointer to the data. */
size_t size /**< Size of the \a data. */ size_t size /**< Size of the \a data. */
) )
@ -1093,17 +1075,25 @@ int ecrt_domain_reg_pdo_entry_list(
ec_slave_config_t *sc; ec_slave_config_t *sc;
int ret; int ret;
for (reg = pdo_entry_regs; reg->index; reg++) for (reg = pdo_entry_regs; reg->index; reg++) {
{
if (!(sc = ecrt_master_slave_config( if (!(sc = ecrt_master_slave_config(
domain->getMaster(), reg->alias, domain->getMaster(),
reg->position, reg->vendor_id, reg->product_code))) reg->alias,
reg->position,
reg->vendor_id,
reg->product_code))) {
return -ENOENT; return -ENOENT;
}
if ((ret = ecrt_slave_config_reg_pdo_entry( if ((ret = ecrt_slave_config_reg_pdo_entry(
sc, reg->index, reg->subindex, domain, sc,
reg->bit_position)) < 0) reg->index,
reg->subindex,
domain,
reg->bit_position))
< 0) {
return ret; return ret;
}
*reg->offset = ret; *reg->offset = ret;
} }
@ -1111,35 +1101,31 @@ int ecrt_domain_reg_pdo_entry_list(
return 0; return 0;
} }
size_t ecrt_domain_size( size_t ecrt_domain_size(const ec_domain_t *domain /**< Domain. */
const ec_domain_t *domain /**< Domain. */
) )
{ {
return domain->getSize(); return domain->getSize();
} }
uint8_t *ecrt_domain_data( uint8_t *ecrt_domain_data(const ec_domain_t *domain)
const ec_domain_t *domain)
{ {
return domain->getData(); return domain->getData();
} }
int ecrt_domain_process( int ecrt_domain_process(ec_domain_t *domain)
ec_domain_t *domain)
{ {
return domain->process(); return domain->process();
} }
int ecrt_domain_queue( int ecrt_domain_queue(ec_domain_t *domain)
ec_domain_t *domain)
{ {
return domain->queue(); return domain->queue();
} }
int ecrt_domain_state( int ecrt_domain_state(
const ec_domain_t *domain, /**< Domain. */ const ec_domain_t *domain, /**< Domain. */
ec_domain_state_t *state /**< Pointer to a state object to store the ec_domain_state_t *state /**< Pointer to a state object to
information. */ store the information. */
) )
{ {
state->working_counter = domain->getNumSlaves(); state->working_counter = domain->getNumSlaves();
@ -1149,9 +1135,10 @@ int ecrt_domain_state(
} }
ec_domain::ec_domain(rtipc *rtipc, const char *prefix, ec_master_t *master): ec_domain::ec_domain(rtipc *rtipc, const char *prefix, ec_master_t *master):
rt_group(rtipc_create_group(rtipc, 1.0)), prefix(prefix), master(master) rt_group(rtipc_create_group(rtipc, 1.0)),
{ prefix(prefix),
} master(master)
{}
int ec_domain::activate() int ec_domain::activate()
{ {
@ -1159,29 +1146,39 @@ int ec_domain::activate()
connected.resize(mapped_pdos.size()); connected.resize(mapped_pdos.size());
size_t idx = 0; size_t idx = 0;
for (const auto &pdo : mapped_pdos) for (const auto &pdo : mapped_pdos) {
{
slaves.insert(pdo.slave_address.getCombined()); slaves.insert(pdo.slave_address.getCombined());
void *rt_pdo = nullptr; void *rt_pdo = nullptr;
char buf[512]; char buf[512];
const auto fmt = snprintf(buf, sizeof(buf), "%s/%d/%08X/%04X", const auto fmt = snprintf(
prefix, master->getId(), pdo.slave_address.getCombined(), buf,
sizeof(buf),
"%s/%d/%08X/%04X",
prefix,
master->getId(),
pdo.slave_address.getCombined(),
pdo.pdo_index); pdo.pdo_index);
if (fmt < 0 || fmt >= (int)sizeof(buf)) if (fmt < 0 || fmt >= (int) sizeof(buf)) {
{
return -ENOBUFS; return -ENOBUFS;
} }
switch (pdo.dir) switch (pdo.dir) {
{
case EC_DIR_OUTPUT: case EC_DIR_OUTPUT:
rt_pdo = rtipc_txpdo(rt_group, buf, rtipc_uint8_T, rt_pdo = rtipc_txpdo(
data.data() + pdo.offset, pdo.size_bytes); rt_group,
buf,
rtipc_uint8_T,
data.data() + pdo.offset,
pdo.size_bytes);
std::cerr << "Registering " << buf << " as Output\n"; std::cerr << "Registering " << buf << " as Output\n";
break; break;
case EC_DIR_INPUT: case EC_DIR_INPUT:
rt_pdo = rtipc_rxpdo(rt_group, buf, rtipc_uint8_T, rt_pdo = rtipc_rxpdo(
data.data() + pdo.offset, pdo.size_bytes, rt_group,
buf,
rtipc_uint8_T,
data.data() + pdo.offset,
pdo.size_bytes,
connected.data() + idx); connected.data() + idx);
std::cerr << "Registering " << buf << " as Input\n"; std::cerr << "Registering " << buf << " as Input\n";
break; break;
@ -1189,8 +1186,7 @@ int ec_domain::activate()
std::cerr << "Unknown direction " << pdo.dir << '\n'; std::cerr << "Unknown direction " << pdo.dir << '\n';
return -1; return -1;
} }
if (!rt_pdo) if (!rt_pdo) {
{
std::cerr << "Failed to register RtIPC PDO\n"; std::cerr << "Failed to register RtIPC PDO\n";
return -1; return -1;
} }
@ -1213,26 +1209,32 @@ int ec_domain::queue()
return 0; return 0;
} }
ssize_t ec_domain::map(ec_slave_config const &config, ssize_t ec_domain::map(
unsigned int syncManager, uint16_t pdo_index) ec_slave_config const &config,
unsigned int syncManager,
uint16_t pdo_index)
{ {
if (activated_) if (activated_) {
return -1; return -1;
for (const auto &pdo : mapped_pdos) }
{ for (const auto &pdo : mapped_pdos) {
if (pdo.slave_address == config.address if (pdo.slave_address == config.address
&& syncManager == pdo.syncManager && syncManager == pdo.syncManager && pdo_index == pdo.pdo_index) {
&& pdo_index == pdo.pdo_index)
{
// already mapped; // already mapped;
return pdo.offset; return pdo.offset;
} }
} }
const auto ans = data.size(); const auto ans = data.size();
const auto size = const auto size = config.sync_managers.at(syncManager)
config.sync_managers.at(syncManager).pdos.at(pdo_index).sizeInBytes(); .pdos.at(pdo_index)
mapped_pdos.emplace_back(ans, size, config.address, syncManager, .sizeInBytes();
pdo_index, config.sync_managers.at(syncManager).dir); mapped_pdos.emplace_back(
ans,
size,
config.address,
syncManager,
pdo_index,
config.sync_managers.at(syncManager).dir);
data.resize(ans + size); data.resize(ans + size);
return ans; return ans;
} }
@ -1252,43 +1254,41 @@ int ecrt_sdo_request_index(
int ecrt_sdo_request_timeout( int ecrt_sdo_request_timeout(
ec_sdo_request_t *req, /**< SDO request. */ ec_sdo_request_t *req, /**< SDO request. */
uint32_t timeout /**< Timeout in milliseconds. Zero means no uint32_t timeout /**< Timeout in milliseconds. Zero
timeout. */ means no timeout. */
) )
{ {
return 0; return 0;
} }
uint8_t *ecrt_sdo_request_data( uint8_t *
const ec_sdo_request_t *req /**< SDO request. */ ecrt_sdo_request_data(const ec_sdo_request_t *req /**< SDO request. */
) )
{ {
return nullptr; return nullptr;
} }
size_t ecrt_sdo_request_data_size( size_t
const ec_sdo_request_t *req /**< SDO request. */ ecrt_sdo_request_data_size(const ec_sdo_request_t *req /**< SDO request. */
) )
{ {
return 0; return 0;
} }
ec_request_state_t ecrt_sdo_request_state( ec_request_state_t
ec_sdo_request_t *req /**< SDO request. */ ecrt_sdo_request_state(ec_sdo_request_t *req /**< SDO request. */
) )
{ {
return EC_REQUEST_ERROR; return EC_REQUEST_ERROR;
} }
int ecrt_sdo_request_write( int ecrt_sdo_request_write(ec_sdo_request_t *req /**< SDO request. */
ec_sdo_request_t *req /**< SDO request. */
) )
{ {
return 0; return 0;
} }
int ecrt_sdo_request_read( int ecrt_sdo_request_read(ec_sdo_request_t *req /**< SDO request. */
ec_sdo_request_t *req /**< SDO request. */
) )
{ {
return 0; return 0;
@ -1309,43 +1309,41 @@ int ecrt_soe_request_idn(
int ecrt_soe_request_timeout( int ecrt_soe_request_timeout(
ec_soe_request_t *req, /**< SoE request. */ ec_soe_request_t *req, /**< SoE request. */
uint32_t timeout /**< Timeout in milliseconds. Zero means no uint32_t timeout /**< Timeout in milliseconds. Zero
timeout. */ means no timeout. */
) )
{ {
return 0; return 0;
} }
uint8_t *ecrt_soe_request_data( uint8_t *
const ec_soe_request_t *req /**< SoE request. */ ecrt_soe_request_data(const ec_soe_request_t *req /**< SoE request. */
) )
{ {
return nullptr; return nullptr;
} }
size_t ecrt_soe_request_data_size( size_t
const ec_soe_request_t *req /**< SoE request. */ ecrt_soe_request_data_size(const ec_soe_request_t *req /**< SoE request. */
) )
{ {
return 0; return 0;
} }
ec_request_state_t ecrt_soe_request_state( ec_request_state_t
ec_soe_request_t *req /**< SoE request. */ ecrt_soe_request_state(ec_soe_request_t *req /**< SoE request. */
) )
{ {
return EC_REQUEST_ERROR; return EC_REQUEST_ERROR;
} }
int ecrt_soe_request_write( int ecrt_soe_request_write(ec_soe_request_t *req /**< SoE request. */
ec_soe_request_t *req /**< SoE request. */
) )
{ {
return 0; return 0;
} }
int ecrt_soe_request_read( int ecrt_soe_request_read(ec_soe_request_t *req /**< SoE request. */
ec_soe_request_t *req /**< SoE request. */
) )
{ {
return 0; return 0;
@ -1375,15 +1373,15 @@ int ecrt_voe_handler_received_header(
return 0; return 0;
} }
uint8_t *ecrt_voe_handler_data( uint8_t *
const ec_voe_handler_t *voe /**< VoE handler. */ ecrt_voe_handler_data(const ec_voe_handler_t *voe /**< VoE handler. */
) )
{ {
return nullptr; return nullptr;
} }
size_t ecrt_voe_handler_data_size( size_t
const ec_voe_handler_t *voe /**< VoE handler. */ ecrt_voe_handler_data_size(const ec_voe_handler_t *voe /**< VoE handler. */
) )
{ {
return 0; return 0;
@ -1397,22 +1395,20 @@ int ecrt_voe_handler_write(
return 0; return 0;
} }
int ecrt_voe_handler_read( int ecrt_voe_handler_read(ec_voe_handler_t *voe /**< VoE handler. */
ec_voe_handler_t *voe /**< VoE handler. */
) )
{ {
return 0; return 0;
} }
int ecrt_voe_handler_read_nosync( int ecrt_voe_handler_read_nosync(ec_voe_handler_t *voe /**< VoE handler. */
ec_voe_handler_t *voe /**< VoE handler. */
) )
{ {
return 0; return 0;
} }
ec_request_state_t ecrt_voe_handler_execute( ec_request_state_t
ec_voe_handler_t *voe /**< VoE handler. */ ecrt_voe_handler_execute(ec_voe_handler_t *voe /**< VoE handler. */
) )
{ {
return EC_REQUEST_ERROR; return EC_REQUEST_ERROR;
@ -1422,15 +1418,15 @@ ec_request_state_t ecrt_voe_handler_execute(
* Register request * Register request
****************************************************************************/ ****************************************************************************/
uint8_t *ecrt_reg_request_data( uint8_t *
const ec_reg_request_t *req /**< Register request. */ ecrt_reg_request_data(const ec_reg_request_t *req /**< Register request. */
) )
{ {
return nullptr; return nullptr;
} }
ec_request_state_t ecrt_reg_request_state( ec_request_state_t
const ec_reg_request_t *req /**< Register request. */ ecrt_reg_request_state(const ec_reg_request_t *req /**< Register request. */
) )
{ {
return EC_REQUEST_ERROR; return EC_REQUEST_ERROR;
@ -1494,16 +1490,18 @@ void ec_slave_config::dumpJson(std::ostream &out, int indent) const
out << "\"product_id\": " << product_code << ",\n"; out << "\"product_id\": " << product_code << ",\n";
add_spaces(out, indent); add_spaces(out, indent);
out << "\"sdos\": "; out << "\"sdos\": ";
map2Json(out, sdos, map2Json(
[](std::ostream &out, const std::basic_string<uint8_t> &value) out,
{ sdos,
[](std::ostream &out, const std::basic_string<uint8_t> &value) {
out << "\"0x"; out << "\"0x";
for (const auto s : value) { for (const auto s : value) {
out << std::hex << std::setfill('0') out << std::hex << std::setfill('0') << std::setw(2)
<< std::setw(2) << (unsigned)s; << (unsigned) s;
} }
out << '"'; out << '"';
}, indent); },
indent);
out << '\n'; out << '\n';
add_spaces(out, indent - 4); add_spaces(out, indent - 4);
out << "}"; out << "}";

View File

@ -38,8 +38,10 @@ struct Offset
int bytes; int bytes;
int bits; int bits;
constexpr Offset(int bytes, constexpr Offset(int bytes, int bits):
int bits) : bytes(bytes), bits(bits) {} bytes(bytes),
bits(bits)
{}
constexpr bool operator!=(const Offset &other) const noexcept constexpr bool operator!=(const Offset &other) const noexcept
{ {
@ -67,14 +69,15 @@ struct syncManager
class ec_address class ec_address
{ {
private:
uint32_t value; uint32_t value;
public: public:
ec_address(uint16_t alias, /**< Slave alias. */ ec_address(
uint16_t position /**< Slave position. */) uint16_t alias, /**< Slave alias. */
: value(static_cast<uint32_t>(alias) << 16 | position) uint16_t position /**< Slave position. */):
{ value(static_cast<uint32_t>(alias) << 16 | position)
} {}
uint16_t getAlias() const { return value >> 16; } uint16_t getAlias() const { return value >> 16; }
uint16_t getPosition() const { return value & 0xFFFF; } uint16_t getPosition() const { return value & 0xFFFF; }
@ -94,14 +97,15 @@ public:
class sdo_address class sdo_address
{ {
private:
uint32_t value; uint32_t value;
public: public:
sdo_address(uint16_t index, /**< Slave alias. */ sdo_address(
uint8_t subindex /**< Slave position. */) uint16_t index, /**< Slave alias. */
: value(static_cast<uint32_t>(index) << 8 | subindex) uint8_t subindex /**< Slave position. */):
{ value(static_cast<uint32_t>(index) << 8 | subindex)
} {}
uint16_t getIndex() const { return value >> 8; } uint16_t getIndex() const { return value >> 8; }
uint8_t getSubIndex() const { return value & 0xFF; } uint8_t getSubIndex() const { return value & 0xFF; }
@ -129,17 +133,17 @@ struct ec_slave_config
ec_slave_config( ec_slave_config(
ec_address address, ec_address address,
uint32_t vendor_id, /**< Expected vendor ID. */ uint32_t vendor_id, /**< Expected vendor ID. */
uint32_t product_code /**< Expected product code. */) uint32_t product_code /**< Expected product code. */):
: address(address), vendor_id(vendor_id), product_code(product_code) address(address),
{ vendor_id(vendor_id),
} product_code(product_code)
{}
void dumpJson(std::ostream &out, int indent) const; void dumpJson(std::ostream &out, int indent) const;
}; };
struct ec_domain struct ec_domain
{ {
private: private:
struct PdoMap struct PdoMap
{ {
@ -150,16 +154,19 @@ private:
uint16_t pdo_index; uint16_t pdo_index;
ec_direction_t dir; ec_direction_t dir;
PdoMap( PdoMap(size_t offset,
size_t offset,
size_t size_bytes, size_t size_bytes,
ec_address slave_address, ec_address slave_address,
unsigned int syncManager, unsigned int syncManager,
uint16_t pdo_index, uint16_t pdo_index,
ec_direction_t dir) ec_direction_t dir):
: offset(offset), size_bytes(size_bytes), slave_address(slave_address), syncManager(syncManager), pdo_index(pdo_index), dir(dir) offset(offset),
{ size_bytes(size_bytes),
} slave_address(slave_address),
syncManager(syncManager),
pdo_index(pdo_index),
dir(dir)
{}
}; };
std::vector<uint8_t> data; std::vector<uint8_t> data;
@ -172,19 +179,20 @@ private:
size_t numSlaves = 0; size_t numSlaves = 0;
public: public:
explicit ec_domain(struct rtipc *rtipc, const char *prefix, ec_master_t *master); explicit ec_domain(
struct rtipc *rtipc,
const char *prefix,
ec_master_t *master);
uint8_t *getData() const uint8_t *getData() const
{ {
if (!activated_) if (!activated_) {
return nullptr; return nullptr;
}
return const_cast<uint8_t *>(data.data()); return const_cast<uint8_t *>(data.data());
} }
size_t getSize() const size_t getSize() const { return data.size(); }
{
return data.size();
}
int activate(); int activate();
int process(); int process();
@ -192,7 +200,9 @@ public:
size_t getNumSlaves() const { return numSlaves; } size_t getNumSlaves() const { return numSlaves; }
ssize_t map(ec_slave_config const &config, unsigned int syncManager, ssize_t
map(ec_slave_config const &config,
unsigned int syncManager,
uint16_t pdo_index); uint16_t pdo_index);
ec_master_t *getMaster() const { return master; } ec_master_t *getMaster() const { return master; }
@ -203,10 +213,7 @@ struct ec_master
private: private:
struct RtIpcDeleter struct RtIpcDeleter
{ {
void operator()(struct rtipc *r) const void operator()(struct rtipc *r) const { rtipc_exit(r); }
{
rtipc_exit(r);
}
}; };
std::string rt_ipc_dir; std::string rt_ipc_dir;