SlaveRegisterReadingScheduler.h
Go to the documentation of this file.
1#pragma once
2
3#include <atomic>
4#include <condition_variable>
5#include <mutex>
6#include <thread>
7
8#include "EtherCATFrame.h"
9#include "SlaveRegisters.h"
10
12{
13 /**
14 * @class SlaveRegisterReadingScheduler
15 * @ingroup Library-ethercat
16 * @brief Brief description of class SlaveRegisterReadingScheduler.
17 *
18 * Detailed description of class SlaveRegisterReadingScheduler.
19 */
21 {
22 public:
24 const std::vector<RegisterDataList>* requestedRegisters);
25
26 static void
28 std::vector<RegisterDataList>* requestedRegisters);
29
30
31 SlaveRegisterReadingScheduler(std::uint16_t slaveCount,
32 unsigned int updatePeriodInMS,
33 std::vector<datatypes::RegisterEnum> registerList);
35
36 const std::vector<RegisterDataList>& getRegisterData();
37
39 bool allRegistersUpdated() const;
40
41 private:
42 std::vector<RegisterDataList> registerData;
43
44 EtherCATFrameList* frameList;
45
46 void updateLoop();
47 unsigned int updatePeriodInMS{1};
48 std::thread errorRegisterUpdateThread;
49 std::atomic_bool errorRegisterUpdateThreadRunning{true};
50
51 std::condition_variable cv_readNextRegisters;
52 std::mutex mutex_readNextRegisters;
53 std::atomic_bool readyToReadNextRegisters{true};
54 std::atomic_bool areAllRegistersUpdated{false};
55
56 private:
57 /*!
58 * \brief Turn a map of which registers to read into a vector of addresses that must be read.
59 *
60 * Multi-byte registers are accounted for - every byte is added to the list individually.
61 * The returned list is sorted.
62 * \param toRead the register read map to turn into a list of addresses
63 * \return the sorted list of addresses
64 */
65 static std::vector<int> registerReadMapToAddressList(const RegisterDataList& toRead);
66
67 /*!
68 * \brief Calculate the optimal separation of registers into intervals for PDUs.
69 *
70 * Note that the intervals may not be optimal once you pack them into EtherCAT frames
71 * because their size might lead to suboptimal fittings. Usually, the intervals
72 * shouldn't be that large though (an Ethernet frame fits 1500 bytes of payload, after all).
73 *
74 * The interval ends are exclusive (i.e., the interval is [start, end)).
75 * \param toRead the registers to fit into intervals
76 * \return a list of intervals that cover the registers optimally
77 */
78 static std::vector<std::pair<int, int>>
79 createFrameIntervals(const RegisterDataList& toRead);
80
81 /*!
82 * \brief Create the PDUMetaData for a PDU in an EtherCAT frame.
83 * \param pduInterval the PDU interval (associated with a slave) to generate metadata for
84 * \param pduOffset the offset of the PDU relative to the start of the EtherCATFrame
85 * \return the PDU metadata
86 */
87 static PDUMetaData createPDUMetaData(std::tuple<uint16_t, int, int> pduInterval,
88 size_t pduOffset);
89
90 /*!
91 * \brief Create an EtherCATFrame that reads all the given address intervals via FPRD
92 * if sent on the EtherCAT bus.
93 * \param slaveAssignedPDUIntervals the PDU intervals to fit in an EtherCATFrame
94 * \return the EtherCATFrame along with its metadata
95 * \exception std::length_error iff the PDUs are too long to fit in an EtherCAT frame
96 */
97 static std::pair<EtherCATFrame, EtherCATFrameMetaData>
98 createEtherCATFrame(std::vector<std::tuple<uint16_t, int, int>> slaveAssignedPDUIntervals);
99
100 /*!
101 * \brief Create an EtherCATFrameList from the given address intervals.
102 *
103 * The frames will be generated to contain every interval for every slave.
104 *
105 * This method will try to fit the PDUs into the frames in order,
106 * starting a new frame if the next PDU doesn't fit. That is not optimal.
107 * If it bugs you, write something smarter.
108 * \param pduIntervals The address intervals to fit into EtherCAT frames
109 */
110 static EtherCATFrameList* createEtherCATFrameList(
111 const std::vector<std::pair<std::uint16_t, std::vector<std::pair<int, int>>>>&
112 pduIntervals);
113 };
114
115} // namespace armarx::control::ethercat
SlaveRegisterReadingScheduler(std::uint16_t slaveCount, unsigned int updatePeriodInMS, std::vector< datatypes::RegisterEnum > registerList)
static void updateRegisterDataFromEtherCATFrameList(const EtherCATFrameList *frameList, std::vector< RegisterDataList > *requestedRegisters)
static EtherCATFrameList * createEtherCATFrameListFromRegisterDataList(const std::vector< RegisterDataList > *requestedRegisters)
The EtherCATFrameList struct holds a list of EtherCAT frames that can be scheduled in round-robin-sty...
The PDUMetaData struct holds information about the structure of a PDU.
Brief description of struct RegisterDataList.