GCC Code Coverage Report


Directory: src/
File: src/Blinker.cpp
Date: 2026-09-03 17:04:53
Exec Total Coverage
Lines: 40 54 74.1%
Branches: 25 54 46.3%

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/Blinker.h"
24
25 #include "Base.h"
26
27 #include <cmath> // fmod()
28
29 using namespace Reta;
30 using namespace std;
31
32 /****************************************************************************/
33
34 1 struct RETA_LOCAL Blinker::Impl : public Base
35 {
36 Impl(shared_ptr<Task>, const string &, double, unsigned int);
37
38 shared_ptr<Task> task;
39
40 vector<double> period;
41 vector<double> dutyCycle;
42 vector<uint8_t> lastEnable;
43 vector<double> time;
44 vector<uint8_t> output;
45 };
46
47 /****************************************************************************/
48
49 1 Blinker::Impl::Impl(
50 shared_ptr<Task> task,
51 const string &prefix,
52 double periodIn,
53 1 unsigned int width) :
54 Base {prefix},
55 task {task},
56 period(width, periodIn),
57 dutyCycle(width, 0.5),
58 lastEnable(width, false),
59 time(width, 0.0),
60
5/10
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 9 taken 1 times.
✗ Branch 10 not taken.
✓ Branch 14 taken 1 times.
✗ Branch 15 not taken.
✓ Branch 19 taken 1 times.
✗ Branch 20 not taken.
✓ Branch 24 taken 1 times.
✗ Branch 25 not taken.
1 output(width, false)
61 {
62
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 checkZeroWidth(width);
63
64
1/2
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
1 pdserv *pdserv {task->getPdServ()};
65
1/2
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
1 pdtask *pdtask {task->getPdTask()};
66
67
1/2
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
2 pdserv_parameter(
68
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
2 pdserv, (prefix + "/Period").c_str(), 0666, pd_double_T,
69 1 period.data(), period.size(), NULL, NULL, NULL);
70
1/2
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
2 pdserv_parameter(
71
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
2 pdserv, (prefix + "/DutyCycle").c_str(), 0666, pd_double_T,
72 1 dutyCycle.data(), dutyCycle.size(), NULL, NULL, NULL);
73
1/2
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
2 pdserv_signal(
74
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
2 pdtask, 1, (prefix + "/Output").c_str(), pd_boolean_T,
75 1 output.data(), output.size(), NULL);
76 1 }
77
78 /****************************************************************************/
79
80 1 Blinker::Blinker(
81 shared_ptr<Task> task,
82 const string &prefix,
83 double period,
84 1 unsigned int width) :
85 1 impl {make_unique<Impl>(task, prefix, period, width)}
86 1 {}
87
88 /****************************************************************************/
89
90 1 Blinker::~Blinker()
91 1 {}
92
93 /****************************************************************************/
94
95 47 void Blinker::update(bool enable)
96 {
97
1/2
✓ Branch 2 taken 47 times.
✗ Branch 3 not taken.
94 vector<uint8_t> enableVector = {enable};
98
1/2
✓ Branch 1 taken 47 times.
✗ Branch 2 not taken.
47 update(enableVector);
99 47 }
100
101 /****************************************************************************/
102 void Blinker::update(function<bool(unsigned int)> enable)
103 {
104 vector<uint8_t> enableVector(impl->output.size());
105 for (unsigned int i = 0; i < impl->output.size(); i++) {
106 enableVector[i] = enable(i);
107 }
108
109 update(enableVector);
110 }
111
112 /****************************************************************************/
113
114 47 void Blinker::update(const vector<uint8_t> &enable)
115 {
116 47 impl->checkSize(enable, impl->output);
117
118
2/2
✓ Branch 2 taken 47 times.
✓ Branch 3 taken 47 times.
94 for (unsigned int i = 0; i < impl->output.size(); i++) {
119
5/6
✓ Branch 2 taken 47 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 45 times.
✓ Branch 6 taken 2 times.
✓ Branch 7 taken 45 times.
✓ Branch 8 taken 2 times.
47 if (impl->period[i] > 0.0 && enable[i]) {
120
2/2
✓ Branch 2 taken 42 times.
✓ Branch 3 taken 3 times.
45 if (impl->lastEnable[i]) {
121 42 impl->time[i] += impl->task->getPeriod();
122 }
123 else {
124 3 impl->time[i] = 0.0;
125 }
126 45 impl->output[i] =
127 45 fmod(impl->time[i], impl->period[i]) / impl->period[i]
128 45 < impl->dutyCycle[i];
129 }
130 else {
131 2 impl->output[i] = false;
132 }
133
134 47 impl->lastEnable[i] = enable[i];
135 }
136 47 }
137
138 /****************************************************************************/
139
140 bool Blinker::getOutput(unsigned int i) const
141 {
142 return impl->output.at(i);
143 }
144
145 /****************************************************************************/
146
147
148 vector<uint8_t> Blinker::getOutputVector() const
149 {
150 return impl->output;
151 }
152
153 /****************************************************************************/
154
155 bool Blinker::anyOutput() const
156 {
157 for (auto output : impl->output) {
158 if (output) {
159 return output;
160 }
161 }
162
163 return false;
164 }
165
166 /****************************************************************************/
167