4#ifndef YARP_DEV_CIA402_ETHERCAT_MANAGER_H
5#define YARP_DEV_CIA402_ETHERCAT_MANAGER_H
14#include <unordered_map>
107 return m_map && (m_map->find(f) != m_map->end());
117 template <
typename T> T
get(
TxField f, T fallback = {})
const
119 static_assert(std::is_trivially_copyable_v<T>,
"TxView::get requires trivially copyable T");
121 auto it = m_map->find(f);
122 if (it == m_map->end())
127 const auto& fi = it->second;
128 if (fi.bitSize % 8 != 0 || fi.bitSize == 0)
132 const std::size_t byteSize = fi.bitSize / 8;
133 if (byteSize !=
sizeof(T) || byteSize == 0)
139 std::memcpy(&value, m_base + fi.byteOffset, byteSize);
144 const uint8_t* m_base{
nullptr};
145 const std::unordered_map<TxField, FieldInfo>* m_map{
nullptr};
200 return m_initialized;
206 return m_isOperational;
225 return m_expectedWkc;
234 m_pdoTimeoutUs = (usec > 0 ? usec : m_pdoTimeoutUs);
242 return m_pdoTimeoutUs;
267 template <
typename T>
268 Error readSDO(
int slaveIndex, uint16_t idx, uint8_t subIdx, T& out)
noexcept;
279 template <
typename T>
280 Error writeSDO(
int slaveIndex, uint16_t idx, uint8_t subIdx,
const T& value)
noexcept;
328 void errorMonitorLoop() noexcept;
335 bool indexValid(
int slaveIndex) const noexcept;
341 Error configurePDOMapping(
int s);
343 ecx_contextt m_ctx{};
344 bool m_portOpen{
false};
346 std::atomic<bool> m_initialized{
false};
347 std::atomic<bool> m_runWatch{
false};
348 std::thread m_watchThread;
349 std::atomic<bool> m_isOperational{
false};
351 std::vector<RxPDO*> m_rxPtr;
352 std::vector<uint8_t*> m_txRaw;
353 std::vector<std::unordered_map<TxField, FieldInfo>> m_txMap;
356 int m_expectedWkc{0};
357 int m_consecutivePdoErrors{0};
358 char m_ioMap[4096]{};
359 int m_pdoTimeoutUs{EC_TIMEOUTRET};
361 mutable std::mutex m_ioMtx;
363 static constexpr std::string_view m_kClassName =
"EthercatManager";
371 if (!m_initialized.load())
373 if (!indexValid(slaveIndex))
376 int size =
sizeof(T);
383 rc = ecx_SDOread(&m_ctx, slaveIndex, idx, subIdx,
false, &size, &out, EC_TIMEOUTRXM);
395 if (!m_initialized.load())
397 if (!indexValid(slaveIndex))
400 int size =
sizeof(T);
406 rc = ecx_SDOwrite(&m_ctx,
412 const_cast<T*
>(&value),
TxView getTxView(int slaveIndex) const noexcept
Obtain a typed, bounds-checked view over the TxPDO (slave→master).
EthercatManager(const EthercatManager &)=delete
bool isInitialized() const noexcept
Whether the manager has been successfully initialized.
int getWorkingCounter() const noexcept
Last Working Counter (WKC) observed from the previous cycle.
~EthercatManager()
Destructor, stops background monitoring and releases resources.
Error goPreOp() noexcept
Transition all slaves back to PRE-OP and stop monitoring.
void setPdoTimeoutUs(int usec) noexcept
Set receive timeout for PDO exchange (microseconds). Default is EC_TIMEOUTRET from SOEM....
EthercatManager()
Construct the manager (no I/O started).
int getExpectedWorkingCounter() const noexcept
Error enableDCSync0(uint32_t cycleNs, int32_t shiftNs=0) noexcept
Enable DC Sync0 for a slave.
Error init(const std::string &ifname) noexcept
Initialize the EtherCAT stack and configure slaves.
std::string getName(int slaveIndex) const noexcept
Get the name of a slave device.
int getPdoTimeoutUs() const noexcept
Get current receive timeout for PDO exchange (microseconds).
EthercatManager & operator=(const EthercatManager &)=delete
bool isOperational() const noexcept
Whether the ring is in OPERATIONAL state.
Error sendReceive() noexcept
Perform one cyclic send/receive exchange over the bus.
Error goOperational() noexcept
Transition all slaves to OPERATIONAL and start monitoring.
void dumpDiagnostics() noexcept
Print quick diagnostics about bus/slave state and WKC. Call this when a PDO exchange fails to get imm...
const RxPDO * getRxPDO(int slaveIndex) const noexcept
Access the RxPDO (master→slave) buffer for a given slave.
Error readSDO(int slaveIndex, uint16_t idx, uint8_t subIdx, T &out) noexcept
Read an SDO value from a slave (blocking call).
Error disableDCSync0() noexcept
Disable DC Sync0 for a slave.
Error
Error codes returned by EthercatManager APIs.
@ PdoExchangeFailed
Failed to exchange PDOs or read SDO.
@ SlavesNotOp
Slaves did not reach OP state.
@ ConfigFailed
PDO/SDO configuration failed.
@ InitFailed
Bus/stack initialization failed.
@ NoError
Operation completed successfully.
@ NotInitialized
Operation requires a prior successful init().
@ AlreadyInitialized
init() called more than once.
@ NoSlavesFound
No EtherCAT slaves were discovered.
@ InvalidSlaveIndex
Provided slave index is out of range (1..ec_slavecount).
Error writeSDO(int slaveIndex, uint16_t idx, uint8_t subIdx, const T &value) noexcept
Write an SDO value to a slave (blocking call).
Lightweight view over a slave's TxPDO image.
bool has(TxField f) const
Check if a given field is available in the current mapping.
TxView(const uint8_t *base, const std::unordered_map< TxField, FieldInfo > *map)
Construct a view.
T get(TxField f, T fallback={}) const
Read a field from the TxPDO image with a typed accessor.
TxField
Identifiers for fields read from a slave (TxPDO → master).
@ Velocity606C
0x606C: Velocity actual value
@ Enc2Pos2113_02
0x2113:02 Vendor enc2 position
@ SBC_6621_02
0x6621:02 Safe Brake Control status (exposed via PDO)
@ Enc2Vel2113_03
0x2113:03 Vendor enc2 velocity
@ OpModeDisplay
0x6061: Modes of operation display
@ Timestamp20F0
0x20F0: Timestamp (if supported)
@ PositionError6065
0x6065: Position demand value / error
@ Statusword
0x6041: Statusword
@ TemperatureDrive
0x2031:01 Temperature (if supported)
@ Position6064
0x6064: Position actual value
@ Torque6077
0x6077: Torque actual value
@ Enc1Pos2111_02
0x2111:02 Vendor enc1 position
@ Enc1Vel2111_03
0x2111:03 Vendor enc1 velocity
@ STO_6621_01
0x6621:01 Safe Torque Off status (exposed via PDO)
Metadata describing a field inside the raw TxPDO image.
TxField id
Logical field id.
uint32_t byteOffset
Byte offset from the base of the Tx image.
uint8_t bitSize
Size in bits (8/16/32).
Process Data Object written from master to slave (RxPDO).
int8_t OpMode
0x6060: Modes of operation
uint16_t Controlword
0x6040: Controlword
int32_t TargetPosition
0x607A: Target position
int16_t TargetTorque
0x6071: Target torque
int32_t TargetVelocity
0x60FF: Target velocity