GCC Code Coverage Report


Directory: src/
File: src/Message.cpp
Date: 2026-09-03 17:04:53
Exec Total Coverage
Lines: 0 69 0.0%
Branches: 0 98 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/Message.h"
24
25 #include "Base.h"
26
27 #include <sstream>
28 #include <time.h>
29
30 using namespace Reta;
31 using namespace std;
32
33 /****************************************************************************/
34
35 struct RETA_LOCAL Message::Impl : public Base
36 {
37 Impl(shared_ptr<Task>, const string &, unsigned int width, int priority);
38
39 shared_ptr<Task> task;
40
41 int priority;
42 vector<uint8_t> enable;
43 vector<uint8_t> state;
44 vector<uint8_t> prevState;
45 vector<double> time;
46 vector<string> texts;
47 vector<const char *> textArray;
48 struct pdevent *event;
49 };
50
51 /****************************************************************************/
52
53 Message::Impl::Impl(
54 shared_ptr<Task> task,
55 const string &prefix,
56 unsigned int width,
57 int priorityInit) :
58 Base {prefix},
59 task {task},
60 priority {priorityInit},
61 enable(width, true),
62 state(width, false),
63 prevState(width, false),
64 time(width, 0.0),
65 texts(width, string()),
66 textArray(width, nullptr),
67 event {nullptr}
68 {
69 checkZeroWidth(width);
70
71 pdserv *pdserv {task->getPdServ()};
72 pdtask *pdtask {task->getPdTask()};
73
74 pdserv_parameter(
75 pdserv, (prefix + "/Enable").c_str(), 0666, pd_boolean_T,
76 enable.data(), enable.size(), NULL, NULL, NULL);
77 pdserv_signal(
78 pdtask, 1, (prefix + "/state").c_str(), pd_boolean_T,
79 state.data(), state.size(), NULL);
80 pdserv_signal(
81 pdtask, 1, (prefix + "/time").c_str(), pd_double_T, time.data(),
82 time.size(), NULL);
83
84 event = pdserv_event(pdserv, (prefix + "/Event").c_str(), width);
85
86 for (unsigned int i = 0; i < width; i++) {
87 stringstream str;
88 str << prefix << "/Event";
89 if (width > 1) {
90 str << "/" << i;
91 }
92 texts[i] = str.str();
93 textArray[i] = texts[i].c_str();
94 }
95
96 pdserv_event_set_text(event, textArray.data());
97 }
98
99 /****************************************************************************/
100
101 Message::Message(
102 shared_ptr<Task> task,
103 const string &prefix,
104 unsigned int width,
105 int priority) :
106 impl {make_unique<Impl>(task, prefix, width, priority)}
107 {}
108
109 /****************************************************************************/
110
111 Message::~Message()
112 {}
113
114 /****************************************************************************/
115
116 void Message::update(bool input, bool acknowledge)
117 {
118 update(vector<uint8_t> {input}, acknowledge);
119 }
120
121 /****************************************************************************/
122
123 void Message::update(function<bool(unsigned int)> input, bool acknowledge)
124 {
125 vector<uint8_t> inputVector(impl->state.size());
126
127 for (unsigned int i = 0; i < impl->state.size(); i++) {
128 inputVector[i] = input(i);
129 }
130
131 update(inputVector, acknowledge);
132 }
133
134 /****************************************************************************/
135
136 void Message::update(const vector<uint8_t> &input, bool acknowledge)
137 {
138 impl->checkSize(input, impl->state);
139
140 struct timespec t = {};
141
142 for (unsigned int i = 0; i < impl->state.size(); i++) {
143 impl->prevState[i] = impl->state[i];
144
145 if (input[i] && impl->enable[i] && !impl->state[i]) {
146 if (!t.tv_sec) {
147 clock_gettime(CLOCK_REALTIME, &t);
148 }
149
150 impl->time[i] = (double) t.tv_sec + (double) t.tv_nsec * 1e-9;
151 impl->state[i] = true;
152
153 pdserv_event_set(impl->event, i, impl->priority, &t);
154 }
155 else if (acknowledge) {
156 impl->time[i] = 0.0;
157 impl->state[i] = false;
158
159 if (!t.tv_sec) {
160 clock_gettime(CLOCK_REALTIME, &t);
161 }
162 pdserv_event_reset(impl->event, i, &t);
163 }
164 }
165 }
166
167 /****************************************************************************/
168
169 bool Message::getState(unsigned int i) const
170 {
171 return impl->state.at(i);
172 }
173
174 /****************************************************************************/
175
176 vector<uint8_t> Message::getStateVector() const
177 {
178 return impl->state;
179 }
180
181 /****************************************************************************/
182
183 bool Message::anyState() const
184 {
185 for (auto state : impl->state) {
186 if (state) {
187 return state;
188 }
189 }
190
191 return false;
192 }
193
194 /****************************************************************************/
195
196 bool Message::getRising(unsigned int i) const
197 {
198 return impl->state.at(i) && !impl->prevState.at(i);
199 }
200
201 /****************************************************************************/
202
203 bool Message::anyRising() const
204 {
205 for (unsigned int i = 0; i < impl->state.size(); i++) {
206 if (getRising(i)) {
207 return true;
208 }
209 }
210
211 return false;
212 }
213
214 /****************************************************************************/
215