GCC Code Coverage Report


Directory: ./
File: src/devices/EL6692.h
Date: 2026-09-23 16:22:15
Exec Total Coverage
Lines: 14 14 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 * EL6692: an EtherCAT-Bridge terminal, sold and used in pairs -- one
22 * "Primary" and one "Secondary" half, each on its own EtherCAT
23 * segment/master, tunnelling raw process data between the two. Its
24 * RxPDO (0x1600) and TxPDO (0x1a00) mapping objects start out empty
25 * and accept application-chosen entries (confirmed against the real
26 * terminal: "ethercat pdos -v" shows both at DefaultSize 0), unlike
27 * every other terminal in this library, whose PDO layout is fixed by
28 * its type. See EcApp::VariablePdo for the public capability this
29 * implements. Both halves share one product code, so one device
30 * class/registration covers both; which one an installation calls
31 * "Primary" and "Secondary" is purely a slave-position/wiring fact,
32 * invisible to ecapp.
33 *
34 ****************************************************************************/
35
36 #ifndef ECAPP_EL6692_H
37 #define ECAPP_EL6692_H
38
39 /****************************************************************************/
40
41 #include "ecapp/Mode.h"
42 #include "ecapp/SubDevice.h" // ChannelValue
43 #include "ecapp/VariablePdo.h" // PdoChannel
44
45 #include <ecrt.h> // EtherCAT realtime interface
46 #include <stdint.h>
47 #include <string>
48 #include <vector>
49
50 /****************************************************************************/
51
52 namespace EcApp {
53
54 class Master;
55 class Domain;
56
57 template <Mode mode>
58 class EL6692Adapter; // EL6692.cpp -- the SubDevice wrapping this class,
59 // friended below so it can reach the per-channel
60 // value/commanded/driven/forcedValue/enableForcing
61 // directly for pdserv publishing.
62
63 template <Mode mode>
64 1 class EL6692
65 {
66 friend class EL6692Adapter<mode>;
67
68 public:
69 EL6692(Master *, uint16_t, uint16_t, Domain *domainOut, Domain *domainIn);
70
71 /** See EcApp::VariablePdo -- what the adapter (defined in the
72 * .cpp) forwards its VariablePdo::configure() call to. */
73 void configure(
74 const std::vector<PdoChannel> &inputs,
75 const std::vector<PdoChannel> &outputs);
76
77 void updateInputs();
78 void updateOutputs();
79
80 /** Declared inputs only -- the built-in "Connected" diagnosis
81 * channel (see the .cpp) is not counted here, it is added
82 * directly to the adapter's inputKinds_ instead, since it exists
83 * independently of anything the application declares. */
84 2 unsigned int numInputs() const
85 {
86 2 return static_cast<unsigned int>(inputs_.size());
87 }
88 3 unsigned int numOutputs() const
89 {
90 3 return static_cast<unsigned int>(outputs_.size());
91 }
92
93 ChannelValue getInput(unsigned int index) const;
94 void setOutput(unsigned int index, const ChannelValue &value);
95
96 /** Name/type accessors the adapter (see the .cpp) uses to build
97 * its own ChannelKind list once configure() has run --
98 * outputs have no getInput()-style value accessor (SubDevice's
99 * generic API is write-only for outputs, see SubDevice.h), so
100 * outputChannelType() hands back a channel's type tag directly
101 * instead. */
102 2 const std::string &inputChannelName(unsigned int index) const
103 {
104 2 return inputs_.at(index).name;
105 }
106 2 const std::string &outputChannelName(unsigned int index) const
107 {
108 2 return outputs_.at(index).name;
109 }
110 2 ChannelValue outputChannelType(unsigned int index) const
111 {
112 2 return outputs_.at(index).commanded;
113 }
114
115 /** Inverted "External device not connected" bit of the fixed
116 * TxPDO 0x1a01, always mapped alongside 0x1a00 -- see
117 * configure(). true once the bridge's peer half is present
118 * and the link between the two masters is up. */
119 1 bool connected() const { return connected_; }
120
121 private:
122 /** One declared channel. Every one of the ChannelValue members
123 * below is created holding the same alternative (see
124 * configure()) and never changes which alternative is
125 * active afterwards, so taking the address of that alternative
126 * (done once, in configure(), for pdserv registration) stays
127 * valid for the channel's lifetime -- see rawAddress() in the
128 * .cpp. */
129 4 struct InChannel
130 {
131 std::string name;
132 int offset = -1;
133 unsigned int bit = 0;
134 ChannelValue value;
135 };
136
137 10 struct OutChannel
138 {
139 std::string name;
140 bool forcible;
141 int offset = -1;
142 unsigned int bit = 0;
143 ChannelValue commanded; // written via setOutput()/writeOutput()
144 ChannelValue forcedValue; // pdserv parameter, only if forcible
145 ChannelValue driven; // actually written to the wire
146 uint8_t enableForcing = 0; // pdserv parameter, only if forcible
147 };
148
149 ec_slave_config_t *sc;
150 Domain *const domainOut;
151 Domain *const domainIn;
152
153 std::vector<InChannel> inputs_;
154 std::vector<OutChannel> outputs_;
155
156 // Fixed diagnosis PDO 0x1a01, mapped alongside the variable
157 // 0x1a00 on every instance -- see configure().
158 int offConnected = -1;
159 unsigned int bitConnected = 0;
160 uint8_t connected_ = 0;
161 };
162
163 } // namespace EcApp
164
165 #endif // ECAPP_EL6692_H
166
167 /****************************************************************************/
168