GCC Code Coverage Report


Directory: src/
File: src/Delay.cpp
Date: 2026-09-03 17:04:53
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