GCC Code Coverage Report


Directory: ./
File: src/Domain.cpp
Date: 2026-09-23 16:22:15
Exec Total Coverage
Lines: 30 71 42.3%
Branches: 6 58 10.3%

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 ****************************************************************************/
22
23 #include "ecapp/Domain.h"
24
25 #include "ecapp/Master.h"
26 #include "ecapp/SubDevice.h"
27
28 #include <algorithm>
29 #include <stdexcept>
30 #include <vector>
31
32 /****************************************************************************/
33
34 namespace EcApp {
35
36 18 struct Domain::Impl
37 {
38 ec_domain_t *domain;
39 ec_domain_state_t state;
40 bool valid;
41 uint8_t *data;
42 uint32_t badCycles;
43 std::vector<SubDevice *> inputDevices;
44 std::vector<SubDevice *> outputDevices;
45 };
46
47 /****************************************************************************/
48
49 18 Domain::Domain(
50 pdserv *pdserv,
51 pdtask *task,
52 const std::string &prefix,
53 18 Master *master) :
54 18 impl(new Impl {NULL, {}, false, NULL, 0U})
55 {
56 18 impl->state.working_counter = 0;
57 18 impl->state.wc_state = EC_WC_ZERO;
58 18 impl->state.redundancy_active = 0;
59
60
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
18 if (pdserv && task) {
61 ✗ pdserv_signal(
62 ✗ task, 1, (prefix + "/WorkingCounter").c_str(), pd_uint32_T,
63 ✗ &impl->state.working_counter, 1, NULL);
64 ✗ pdserv_signal(
65 ✗ task, 1, (prefix + "/WorkingCounterState").c_str(),
66 ✗ pd_uint32_T, &impl->state.wc_state, 1, NULL);
67 ✗ pdserv_signal(
68 ✗ task, 1, (prefix + "/RedundancyActive").c_str(), pd_uint32_T,
69 ✗ &impl->state.redundancy_active, 1, NULL);
70 ✗ pdserv_signal(
71 ✗ task, 1, (prefix + "/Valid").c_str(), pd_boolean_T,
72 ✗ &impl->valid, 1, NULL);
73 ✗ pdserv_signal(
74 ✗ task, 1, (prefix + "/BadCycles").c_str(), pd_uint32_T,
75 ✗ &impl->badCycles, 1, NULL);
76 }
77
78
1/2
✓ Branch 0 taken 18 times.
✗ Branch 1 not taken.
18 if (!master) {
79 18 return;
80 }
81
82 ✗ if (!(impl->domain = ecrt_master_create_domain(master->getMaster()))) {
83 ✗ throw std::runtime_error("Domain creation failed!");
84 }
85 }
86
87 /****************************************************************************/
88
89 Domain::~Domain() = default;
90
91 /****************************************************************************/
92
93 ✗ ec_domain_t *Domain::getDomain()
94 {
95 ✗ return impl->domain;
96 }
97
98 /****************************************************************************/
99
100 74 uint8_t *Domain::getData() const
101 {
102 74 return impl->data;
103 }
104
105 /****************************************************************************/
106
107 ✗ bool Domain::isValid() const
108 {
109 ✗ return impl->valid;
110 }
111
112 /****************************************************************************/
113
114 ✗ void Domain::updateDataPointer()
115 {
116 ✗ if (impl->domain) {
117 ✗ impl->data = ecrt_domain_data(impl->domain);
118 }
119 }
120
121 /****************************************************************************/
122
123 ✗ void Domain::process(bool resetStats)
124 {
125 ✗ if (resetStats) {
126 ✗ impl->badCycles = 0U;
127 }
128
129 ✗ if (impl->domain) {
130 ✗ ecrt_domain_process(impl->domain);
131 ✗ ecrt_domain_state(impl->domain, &impl->state);
132 ✗ impl->valid = impl->state.wc_state == EC_WC_COMPLETE;
133 ✗ impl->badCycles += !impl->valid;
134 }
135 }
136
137 /****************************************************************************/
138
139 ✗ void Domain::queue()
140 {
141 ✗ if (impl->domain) {
142 ✗ ecrt_domain_queue(impl->domain);
143 }
144 }
145
146 /****************************************************************************/
147
148 14 void Domain::addInputDevice(SubDevice *device)
149 {
150 14 impl->inputDevices.push_back(device);
151 14 }
152
153 /****************************************************************************/
154
155 14 void Domain::removeInputDevice(SubDevice *device)
156 {
157 14 auto &devices = impl->inputDevices;
158
1/2
✓ Branch 1 taken 14 times.
✗ Branch 2 not taken.
14 devices.erase(
159
1/2
✓ Branch 3 taken 14 times.
✗ Branch 4 not taken.
28 std::remove(devices.begin(), devices.end(), device),
160 56 devices.end());
161 14 }
162
163 /****************************************************************************/
164
165 14 void Domain::addOutputDevice(SubDevice *device)
166 {
167 14 impl->outputDevices.push_back(device);
168 14 }
169
170 /****************************************************************************/
171
172 14 void Domain::removeOutputDevice(SubDevice *device)
173 {
174 14 auto &devices = impl->outputDevices;
175
1/2
✓ Branch 1 taken 14 times.
✗ Branch 2 not taken.
14 devices.erase(
176
1/2
✓ Branch 3 taken 14 times.
✗ Branch 4 not taken.
28 std::remove(devices.begin(), devices.end(), device),
177 56 devices.end());
178 14 }
179
180 /****************************************************************************/
181
182 ✗ void Domain::updateInputs()
183 {
184 ✗ for (auto *device : impl->inputDevices) {
185 ✗ device->updateInputs();
186 }
187 }
188
189 /****************************************************************************/
190
191 ✗ void Domain::updateOutputs()
192 {
193 ✗ for (auto *device : impl->outputDevices) {
194 ✗ device->updateOutputs();
195 }
196 }
197
198 } // namespace EcApp
199
200 /****************************************************************************/
201