GCC Code Coverage Report


Directory: src/
File: src/Delay.cpp
Date: 2026-09-16 13:46:10
Exec Total Coverage
Lines: 0 101 0.0%
Branches: 0 112 0.0%

Line Branch Exec Source
1 /*****************************************************************************
2 *
3 * Copyright (C) 2021 Jonathan Grahl <jonathan.grahl@igh.de>
4 * 2021 Florian Pose <florian.pose@igh.de>
5 *
6 * This file is part of the reta library (realtime-automation).
7 *
8 * The reta library is free software: you can redistribute it and/or modify
9 * it under the terms of the GNU Lesser General Public License as published
10 * by the Free Software Foundation, either version 3 of the License, or (at
11 * your option) any later version.
12 *
13 * The reta library is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
16 * General Public License for more details.
17 *
18 * You should have received a copy of the GNU Lesser General Public License
19 * along with the reta library. If not, see <http://www.gnu.org/licenses/>.
20 *
21 ****************************************************************************/
22
23 #include "reta/Delay.h"
24
25 #include "Base.h"
26
27 using namespace Reta;
28 using namespace std;
29
30 /****************************************************************************/
31
32 ✗ struct RETA_LOCAL Delay::Impl : public Base
33 {
34 Impl(shared_ptr<Task>, const string &, double, unsigned int);
35
36 shared_ptr<Task> task;
37
38 enum State { Up, Down, Delaying };
39
40 vector<State> state;
41 vector<double> elapsedTime;
42 vector<double> remainingTime;
43 double delayTime;
44 vector<uint8_t> output;
45 };
46
47 /****************************************************************************/
48
49 ✗ Delay::Impl::Impl(
50 shared_ptr<Task> task,
51 const string &prefix,
52 double initDelayTime,
53 ✗ unsigned int width) :
54 Base {prefix},
55 task {task},
56 state(width, Down),
57 elapsedTime(width, 0.0),
58 remainingTime(width, 0.0),
59 delayTime {initDelayTime},
60 ✗ output(width, false)
61 {
62 ✗ checkZeroWidth(width);
63
64 ✗ pdserv *pdserv {task->getPdServ()};
65 ✗ pdtask *pdtask {task->getPdTask()};
66
67 ✗ pdserv_signal(
68 ✗ pdtask, 1, (prefix + "/State").c_str(), pd_sint32_T, state.data(),
69 state.size(), NULL);
70
71 ✗ pdserv_parameter(
72 ✗ pdserv, (prefix + "/Delay").c_str(), 0666, pd_double_T,
73 ✗ &delayTime, 1, NULL, NULL, NULL);
74 ✗ pdserv_signal(
75 ✗ pdtask, 1, (prefix + "/ElapsedTime").c_str(), pd_double_T,
76 ✗ elapsedTime.data(), elapsedTime.size(), NULL);
77 ✗ pdserv_signal(
78 ✗ pdtask, 1, (prefix + "/RemainingTime").c_str(), pd_double_T,
79 ✗ remainingTime.data(), remainingTime.size(), NULL);
80
81 ✗ pdserv_signal(
82 ✗ pdtask, 1, (prefix + "/Output").c_str(), pd_boolean_T,
83 ✗ output.data(), output.size(), NULL);
84 }
85
86 /****************************************************************************/
87
88 ✗ Delay::Delay(
89 shared_ptr<Task> task,
90 const string &prefix,
91 double initDelayTime,
92 ✗ unsigned int width) :
93 ✗ impl {make_unique<Impl>(task, prefix, initDelayTime, width)}
94 {}
95
96 /****************************************************************************/
97
98 ✗ Delay::~Delay()
99 {}
100
101 /****************************************************************************/
102
103 ✗ void Delay::setDelay(double time)
104 {
105 ✗ impl->checkNegativeInput(time);
106 ✗ impl->delayTime = time;
107 }
108
109 /****************************************************************************/
110
111 ✗ void Delay::updateDown(bool start, bool reset)
112 {
113 ✗ updateDown(vector<uint8_t> {start}, reset);
114 }
115
116 /****************************************************************************/
117
118 ✗ void Delay::updateDown(function<bool(unsigned int)> start, bool reset)
119 {
120 ✗ vector<uint8_t> startVector(impl->state.size());
121 ✗ for (unsigned int i = 0; i < impl->state.size(); i++) {
122 ✗ startVector[i] = start(i);
123 }
124
125 ✗ updateDown(startVector, reset);
126 }
127
128 /****************************************************************************/
129
130 /** Delay with falling edge.
131 * As long as the timer is counting to the given delay time, the output is
132 * kept up, respectively true. After reaching the delay time the edge is
133 * falling and the output becomes false. It is possible to reset the delay.
134 */
135 ✗ void Delay::updateDown(const vector<uint8_t> &start, bool reset)
136 {
137 ✗ impl->checkSize(start, impl->state);
138
139 ✗ for (unsigned int i = 0; i < impl->state.size(); i++) {
140 ✗ switch (impl->state[i]) {
141 ✗ case Impl::State::Up:
142 ✗ if (!start[i] || reset) {
143 ✗ if (!reset && impl->delayTime > 0.0) {
144 ✗ impl->elapsedTime[i] = 0.0;
145 ✗ impl->state[i] = Impl::State::Delaying;
146 }
147 else {
148 ✗ impl->output[i] = false;
149 ✗ impl->state[i] = Impl::State::Down;
150 }
151 }
152 ✗ break;
153
154 ✗ case Impl::State::Delaying:
155 ✗ if (start[i] && !reset) {
156 ✗ impl->state[i] = Impl::State::Up;
157 }
158 else {
159 ✗ impl->elapsedTime[i] += impl->task->getPeriod();
160 ✗ if (reset || impl->elapsedTime[i] > impl->delayTime) {
161 ✗ impl->output[i] = false;
162 ✗ impl->state[i] = Impl::State::Down;
163 }
164 }
165 ✗ break;
166
167 ✗ default:
168 ✗ if (start[i] && !reset) {
169 ✗ impl->output[i] = true;
170 ✗ impl->state[i] = Impl::State::Up;
171 }
172 }
173
174 ✗ impl->remainingTime[i] = impl->delayTime - impl->elapsedTime[i];
175 }
176 }
177
178 /****************************************************************************/
179
180 ✗ void Delay::updateUp(bool start)
181 {
182 ✗ updateUp(vector<uint8_t> {start});
183 }
184
185 /****************************************************************************/
186
187 ✗ void Delay::updateUp(function<bool(unsigned int)> start)
188 {
189 ✗ vector<uint8_t> startVector(impl->state.size());
190 ✗ for (unsigned int i = 0; i < impl->state.size(); i++) {
191 ✗ startVector[i] = start(i);
192 }
193
194 ✗ updateUp(startVector);
195 }
196
197 /****************************************************************************/
198
199 /** Delay with rising edge.
200 * As long as the timer is counting to the given delay time, the ouput is kept
201 * down, respectively false. After reaching the delay time the edge is rising
202 * and the output becomes true.
203 */
204 ✗ void Delay::updateUp(const vector<uint8_t> &start)
205 {
206 ✗ impl->checkSize(start, impl->state);
207
208 ✗ for (unsigned int i = 0; i < impl->state.size(); i++) {
209 ✗ switch (impl->state[i]) {
210 ✗ case Impl::State::Delaying:
211 ✗ if (start[i]) {
212 ✗ impl->elapsedTime[i] += impl->task->getPeriod();
213 ✗ if (impl->elapsedTime[i] >= impl->delayTime) {
214 ✗ impl->output[i] = true;
215 ✗ impl->state[i] = Impl::State::Up;
216 }
217 }
218 else {
219 ✗ impl->state[i] = Impl::State::Down;
220 }
221 ✗ break;
222
223 ✗ case Impl::State::Up:
224 ✗ if (!start[i]) {
225 ✗ impl->output[i] = false;
226 ✗ impl->state[i] = Impl::State::Down;
227 }
228 ✗ break;
229
230 ✗ default:
231 ✗ if (start[i]) {
232 ✗ if (impl->delayTime > 0.0) {
233 ✗ impl->elapsedTime[i] = 0.0;
234 ✗ impl->state[i] = Impl::State::Delaying;
235 }
236 else {
237 ✗ impl->output[i] = true;
238 ✗ impl->state[i] = Impl::State::Up;
239 }
240 }
241 }
242
243 ✗ impl->remainingTime[i] = impl->delayTime - impl->elapsedTime[i];
244 }
245 }
246
247 /****************************************************************************/
248
249 ✗ bool Delay::getOutput(unsigned int i) const
250 {
251 ✗ return impl->output.at(i);
252 }
253
254 /****************************************************************************/
255
256 ✗ vector<uint8_t> Delay::getOutputVector() const
257 {
258 ✗ return impl->output;
259 }
260
261 /****************************************************************************/
262
263 ✗ bool Delay::anyOutput() const
264 {
265 ✗ for (auto output : impl->output) {
266 ✗ if (output) {
267 ✗ return output;
268 }
269 }
270
271 ✗ return false;
272 }
273
274 /****************************************************************************/
275