GCC Code Coverage Report


Directory: ./
File: src/devices/Ex25xx.h
Date: 2026-09-23 16:22:15
Exec Total Coverage
Lines: 1 1 100.0%
Branches: 0 0 -%

Line Branch Exec Source
1 /*****************************************************************************
2 *
3 * This file is part of the ecapp library (EtherCAT application devices).
4 *
5 * Copyright (C) 2026 Florian Pose <fp@igh.de>
6 *
7 * The ecapp library is free software: you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public License
9 * as published by the Free Software Foundation, version 3 of the
10 * License.
11 *
12 * The ecapp library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with the ecapp library. If not, see
19 * <https://www.gnu.org/licenses/>.
20 *
21 * Beckhoff pulse-train output terminals: EL2521 (1Ch., RS422),
22 * EL2521-0024 (1Ch., 24V DC), EL2521-0025 (1Ch., 24V DC, negative
23 * switching), EL2522 (2Ch.). The three EL2521-xxxx suffixes share one
24 * product code -- same electronics, only the output driver stage
25 * differs (same convention already used for EL3062/EL3062-0030 in
26 * Ex3xxx.cpp; verify against your own hardware's SII if this ever turns
27 * out to differ). This grouping is an implementation detail --
28 * application code never names Ex25xx directly, it goes through
29 * createSubDevice("EL2521") / createSubDevice("EL2522") and gets an
30 * EcApp::SubDevice back.
31 *
32 * Always configured in the terminal's "erweiterter Betriebsmodus"
33 * (extended operating mode) -- not the EL2521-xxxx's legacy/normal
34 * mode (Ctrl/Data Out, Status/Data In at 0x7000/0x6000), and not
35 * Distributed-Clocks synchronous operation (SM-synchronous/FreeRun
36 * instead; the EL2522's "continues position" variant, which needs
37 * DC-Synchron, is not implemented -- ecapp does not configure DC for
38 * any device yet). EL2521-xxxx uses the "Standard 16 Bit (MDP
39 * 253/511)" predefined PDO assignment; EL2522 the factory-default
40 * "2 Ch. Standard 32 Bit (MDP 253/511)".
41 *
42 * Both families place their PTO (pulse-train generator) CoE objects at
43 * 0x7000/0x6000/0x8000 (etc.) plus 0x10 per "channel slot": EL2522
44 * channel 1 sits at slot 0, channel 2 at slot 1; EL2521-xxxx's single
45 * channel sits at slot 1 (slot 0 -- 0x7000/0x6000/0x8000 -- stays
46 * reserved there for the legacy-mode-compatible Ctrl/Data-Out,
47 * Status/Data-In, Feature-object pairing this driver does not use).
48 * Type::slot[] below records that per channel, which is what lets one
49 * shared constructor/update loop serve both families.
50 *
51 * ENC (counter/encoder) CoE objects follow the same per-channel-slot
52 * scheme for EL2522 (channel 1 at 0x7020/0x6020, channel 2 at
53 * 0x7030/0x6030), but NOT for EL2521-xxxx: its single ENC block stays
54 * at the unshifted 0x7020/0x6020 even though its PTO block is at slot
55 * 1. Type::encSlot[] records that separately from Type::slot[].
56 *
57 ****************************************************************************/
58
59 #ifndef ECAPP_EX25XX_H
60 #define ECAPP_EX25XX_H
61
62 /****************************************************************************/
63
64 #include "ecapp/Mode.h"
65 #include "ecapp/PulseTrainOutput.h"
66
67 #include <ecrt.h> // EtherCAT realtime interface
68 #include <stdint.h>
69 #include <string>
70 #include <vector>
71
72 /****************************************************************************/
73
74 namespace EcApp {
75
76 class Master;
77 class Domain;
78
79 struct Ex25xxType;
80
81 template <Mode mode>
82 class Ex25xxAdapter; // Ex25xx.cpp -- the SubDevice wrapping this class,
83 // friended below so it can reach every channel
84 // vector directly for pdserv publishing.
85
86 template <Mode mode>
87 2 class Ex25xx
88 {
89 friend class Ex25xxAdapter<mode>;
90
91 public:
92 enum Type { EL2521, EL2521_0024, EL2521_0025, EL2522, NumTypes };
93
94 Ex25xx(Master *, uint16_t, uint16_t, Domain *, Domain *, Type);
95
96 void updateInputs();
97 void updateOutputs();
98
99 /** See PulseTrainOutput::configure(). */
100 void configure(
101 unsigned int channel,
102 PulseTrainOutputMode outputMode,
103 bool negativeLogic,
104 bool travelDistanceControl);
105
106 unsigned int numChannels() const;
107 bool hasInputTZ() const;
108
109 private:
110 const Ex25xxType &type;
111 ec_slave_config_t *sc;
112 Domain *const domainOut;
113 Domain *const domainIn;
114
115 std::vector<bool> configured;
116
117 // Outputs, one entry per channel
118 std::vector<uint8_t> frequencySelect;
119 std::vector<uint8_t> disableRamp;
120 std::vector<uint8_t> goCounter;
121 std::vector<int16_t> frequencyValue;
122 std::vector<int32_t> targetCounterValue; // 16-bit range on a
123 // non-"wide" type -- see
124 // Type::wide
125 std::vector<uint8_t> setCounter;
126 std::vector<int32_t> setCounterValue; // see targetCounterValue
127
128 // Inputs, one entry per channel
129 std::vector<uint8_t> selAckEndCounter;
130 std::vector<uint8_t> rampActive;
131 std::vector<uint8_t> statusInputTarget; // only if hasInputTZ()
132 std::vector<uint8_t> statusInputZero; // only if hasInputTZ()
133 std::vector<uint8_t> error;
134 std::vector<uint8_t> setCounterDone;
135 std::vector<uint8_t> counterUnderflow;
136 std::vector<uint8_t> counterOverflow;
137 std::vector<int32_t> counterValue; // see targetCounterValue
138
139 // PDO offsets (output side), one entry per channel
140 std::vector<int> offFrequencySelect;
141 std::vector<unsigned int> offFrequencySelectBit;
142 std::vector<int> offDisableRamp;
143 std::vector<unsigned int> offDisableRampBit;
144 std::vector<int> offGoCounter;
145 std::vector<unsigned int> offGoCounterBit;
146 std::vector<int> offFrequencyValue;
147 std::vector<int> offTargetCounterValue;
148 std::vector<int> offSetCounter;
149 std::vector<unsigned int> offSetCounterBit;
150 std::vector<int> offSetCounterValue;
151
152 // PDO offsets (input side), one entry per channel
153 std::vector<int> offSelAckEndCounter;
154 std::vector<unsigned int> offSelAckEndCounterBit;
155 std::vector<int> offRampActive;
156 std::vector<unsigned int> offRampActiveBit;
157 std::vector<int> offStatusInputTarget;
158 std::vector<unsigned int> offStatusInputTargetBit;
159 std::vector<int> offStatusInputZero;
160 std::vector<unsigned int> offStatusInputZeroBit;
161 std::vector<int> offError;
162 std::vector<unsigned int> offErrorBit;
163 std::vector<int> offSetCounterDone;
164 std::vector<unsigned int> offSetCounterDoneBit;
165 std::vector<int> offCounterUnderflow;
166 std::vector<unsigned int> offCounterUnderflowBit;
167 std::vector<int> offCounterOverflow;
168 std::vector<unsigned int> offCounterOverflowBit;
169 std::vector<int> offCounterValue;
170 };
171
172 } // namespace EcApp
173
174 #endif // ECAPP_EX25XX_H
175
176 /****************************************************************************/
177