iomonitor.cpp
Go to the documentation of this file.
1/** @file iomonitor.cpp Test utility for IO devices
2
3
4This tutorial demonstrates elementary access to external signals
5via the class faudes::vDevice. It can be used as a test uitility
6for device configuration.
7
8
9@ingroup Tutorials
10
11@include iomonitor.cpp
12
13*/
14
15
16#include "libfaudes.h"
17
18#include <signal.h>
19
20using namespace faudes;
21
22///////////////////////////////////////////////////////
23// clean exit on signals
24
25// iomonitor clean-up on exit
26void iomonitor_exit(void);
27
28// signal handler recursion flag
29volatile sig_atomic_t signal_in_progress = 0;
30
31// signal handler to stop devices
32void catch_signal(int sig) {
33 // detect recursion, pass on
34 if(signal_in_progress) raise(sig);
36 // report
37 std::cerr << "iomonitor: signal: " << faudes_strsignal(sig) << std::endl;
38 // call my exit function
40 // re-install default handler
41 signal(sig, SIG_DFL);
42 // pass on signal
43 raise(sig);
44}
45
46// iomonitor clean-up on exit
47void iomonitor_exit(void) {
48 // stop all devices
50}
51
52
53///////////////////////////////////////////////////////
54//Basic handling
55
56// list all known events
57void ListEvents(const vDevice* dev) {
58 std::cout<< "% ###############################################################" << std::endl;
59 std::cout<< "% # InputEvents" << std::endl;
60 dev->Inputs().Write();
61 std::cout<< "% ###############################################################" << std::endl;
62 std::cout<< "% # OutputEvents " << std::endl;
63 dev->Outputs().Write();
64 std::cout<< "% ###############################################################" << std::endl;
65}
66
67
68///////////////////////////////////////////////////////
69// Query Time
70
71// read time
72void ReadTime(vDevice* dev) {
73
74 // read and report
75 std::cout << "% ###############################################################" << std::endl;
76 std::cout << "% # ReadTime: current time in ftu: " << dev->CurrentTime() << std::endl;
77 std::cout << "% # ReadTime: using scale: " << dev->TimeScale() << std::endl;
78
79}
80
81
82///////////////////////////////////////////////////////
83//Signal-I/O
84
85// read signal value
87 // declare static buffer
88 static bool* samplePrevious=0;
89 static bool* sampleCurrent=0;
90 static int sampleSize=-1;
91 // allocate memory for buffer
92 if(sampleSize != dev->MaxBitAddress()+1) {
93 sampleSize = dev->MaxBitAddress()+1;
94 if(samplePrevious!=0) delete samplePrevious;
95 if(sampleCurrent!=0) delete sampleCurrent;
96 samplePrevious= new bool[sampleSize];
97 sampleCurrent= new bool[sampleSize];
98 }
99 // read and report
100 std::cout << "% ###############################################################" << std::endl;
101 for(int bit=0; bit<sampleSize; bit++) {
102 samplePrevious[bit]=sampleCurrent[bit];
103 }
104 for(int bit=0; bit<sampleSize; bit++) {
105 sampleCurrent[bit]=dev->ReadSignal(bit);
106 }
107 std::cout << "% # ReadValue: current input reading: " << std::endl;
108 for(int bit=0; bit<sampleSize; bit++) {
109 std::cout<< "@" << (bit < 10 ? "0" : "") << bit << ":" << sampleCurrent[bit] << " ";
110 if((bit%8)==7 || bit+1==sampleSize) std::cout << std::endl;
111 }
112 std::cout <<"% # ReadValue: edges wrt previous reading: " << std::endl;
113 int cnt =0;
114 for(int bit=0; bit<sampleSize; bit++) {
115 if(samplePrevious[bit]!=sampleCurrent[bit]) {
116 std::cout<< "@"<< (bit < 10 ? "0" : "") << bit << ":" << sampleCurrent[bit] << " ";
117 if((cnt%8)==7 || bit+1==sampleSize) std::cout << std::endl;
118 cnt+=1;
119 }
120 }
121 std::cout << "% ###############################################################" << std::endl;
122}
123
124
125// poll input signals
127 std::cout<<"ReadInputs: time (secs) to monitor input signals: ";
128 faudes_mstime_t time_all;
129 std::cin>>time_all;
130 time_all*=1000; // convert to msecs
131 std::cout<<"ReadEvents: time (msecs) to sleep between two polls: ";
132 faudes_mstime_t time_delta;
133 std::cin>>time_delta;
134 // reset all input data so far
135 sdev->Reset();
136 // report performace, part 1
137 faudes_systime_t time_start, time_stop;
138 faudes_gettimeofday(&time_start);
139
140 // declare static buffer
141 static bool* samplePrevious=0;
142 static bool* sampleCurrent=0;
143 static int sampleSize=-1;
144 // allocate memory for buffer
145 if(sampleSize != sdev->MaxBitAddress()+1) {
146 sampleSize = sdev->MaxBitAddress()+1;
147 if(samplePrevious!=0) delete samplePrevious;
148 if(sampleCurrent!=0) delete sampleCurrent;
149 samplePrevious= new bool[sampleSize];
150 sampleCurrent= new bool[sampleSize];
151 }
152 // reset buffer
153 for(int bit=0; bit<sampleSize; bit++) {
154 samplePrevious[bit]=false;
155 sampleCurrent[bit]=false;
156 }
157
158 // loop until time is up
159 bool edges=true;
160 for(int time_togo=time_all; time_togo>0; time_togo-=time_delta) {
161 // read
162 for(int bit=0; bit<sampleSize; bit++) {
163 sampleCurrent[bit]=sdev->ReadSignal(bit);
164 if(sampleCurrent[bit] != samplePrevious[bit]) edges=true;
165 }
166 // report
167 if(edges) {
168 std::cout << "% ###############################################################" << std::endl;
169 for(int bit=0; bit<sampleSize; bit++) {
170 std::cout<< "@"<< (bit < 10 ? "0" : "") << bit << ":" << sampleCurrent[bit];
171 if(sampleCurrent[bit] != samplePrevious[bit])
172 std::cout << "! ";
173 else
174 std::cout << " ";
175 if((bit%8)==7 || bit+1==sampleSize) std::cout << std::endl;
176 }
177 }
178 // copy
179 for(int bit=0; bit<sampleSize; bit++) {
180 samplePrevious[bit]=sampleCurrent[bit];
181 }
182 // clear edge detection
183 edges=0;
184 // sleep
185 faudes_usleep(1000*time_delta);
186 };
187
188 // report performance, part2
189 faudes_gettimeofday(&time_stop);
190 faudes_mstime_t diffms;
191 faudes_diffsystime(time_stop,time_start,&diffms);
192 std::cout << "# performance: overall time: " << diffms << "ms" << std::endl;
193 std::cout << "# performance: sleep time: " << time_all << "ms" << std::endl;
194 std::cout << "# performance: process time per loop: " <<
195 ((double) (diffms - time_all)) / (time_all/time_delta)<< "ms" << std::endl;
196}
197
198// write signal value
200 int bit, val;
201 std::cout<<"WriteValue: enter bit address (or -1 to exit): ";
202 std::cin>>bit;
203 if(bit<0) return;
204 std::cout<<"WriteValue: enter value (or -1 to exit): ";
205 std::cin>>val;
206 if(val<0) return;
207 std::cout<<"WriteValue: setting output " << bit << " to value " << val << std::endl;
208 sdev->WriteSignal(bit,val!=0);
209}
210
211//////////////////////////////////////////////////////////////
212//Event-handling
213
214// execute output event
216 std::cout<<"WriteOutput: enter event by name: ";
217 std::string testEvent;
218 std::cin>>testEvent;
219 if(!dev->Outputs().Exists(testEvent)) {
220 std::cout<<"Unknown output event " << std::endl;
221 return;
222 }
223 faudes::Idx fev= dev->Outputs().Index(testEvent);
224 dev->WriteOutput(fev);
225 dev->FlushOutputs();
226}
227
228
229// poll input events
231 std::cout<<"ReadInputs: time (secs) to monitor input events: ";
232 faudes_mstime_t time_all;
233 std::cin>>time_all;
234 time_all*=1000; // convert to msecs
235 std::cout<<"ReadEvents: time (msecs) to sleep between two polls: ";
236 faudes_mstime_t time_delta;
237 std::cin>>time_delta;
238 // reset all input data so far
239 dev->Reset();
240 // report performace, part 1
241 faudes_systime_t time_start, time_stop;
242 faudes_gettimeofday(&time_start);
243
244 // loop until time is up
245 for(int time_togo=time_all; time_togo>0; time_togo-=time_delta) {
246 Idx sev=dev->ReadInput();
247 if(sev!=0)
248 std::cout<<"ReadInputs: event " << dev->Inputs().SymbolicName(sev) << std::endl;
249 faudes_usleep(1000*time_delta);
250 };
251
252 // report performance, part2
253 faudes_gettimeofday(&time_stop);
254 faudes_mstime_t diffms;
255 faudes_diffsystime(time_stop,time_start,&diffms);
256 std::cout << "# performance: overall time: " << diffms << "ms" << std::endl;
257 std::cout << "# performance: sleep time: " << time_all << "ms" << std::endl;
258 std::cout << "# performance: process time per loop: " <<
259 ((double) (diffms - time_all)) / (time_all/time_delta)<< "ms" << std::endl;
260
261}
262
263// WaitInputEvent(vDevice* dev)
265 std::cout<<"Enter max. duration (in faudes-time units) to wait for a input-event to occur"<<std::endl;
266 std::cout<<"Note: 1 faudes-time unit is configured to " << dev->TimeScale() << " msecs" <<std::endl;
267 Time::Type duration;
268 std::cin>>duration;
269 EventSet occuredEvents;
270 //wait for input-event to occur
271 dev->WaitInputs(duration);
272 //identify occured events
273 while(Idx sev=dev->ReadInput()) occuredEvents.Insert(sev);
274 //report occured events
275 if(!occuredEvents.Empty()) std::cout << occuredEvents.ToString();
276 else std::cout<<"No event recognized";
277}
278
279// FlushInputEvent(vDevice* dev)
281 //identify occured events
282 EventSet occuredEvents;
283 while(Idx sev=dev->ReadInput()) occuredEvents.Insert(sev);
284 //report occured events
285 if(!occuredEvents.Empty()) std::cout << occuredEvents.ToString();
286 else std::cout<<"No event recognized";
287}
288
289
290//////////////////////////////////////////////////////////////
291//User-Interface loop
292
293int main(int argc, char* argv[]) {
294
295 // debugging autoregistration :-(
296 /*
297 std::cerr << " ====== auto registration " << std::endl;
298 TypeRegistry::G()->Write();
299 std::cerr << " ====== registration " << std::endl;
300 AutoRegisterType<cDevice> gRtiLocalIOReg("ComediDevice");
301 TypeRegistry::G()->Write();
302 */
303
304 // install my signal handler
306
307 // first argument has to be filename
308 if(argc!=2) {
309 std::cerr << "iomonitor: " << VersionString() << std::endl;
310 std::cerr << "usage: iomonitor <device-file>" << std::endl;
311 return -1;
312 }
313
314#ifdef FAUDES_NETWORK
315#ifdef FAUDES_WINDOWS
316 // initialise winsocks
317 WSADATA wsaData;
318 if(WSAStartup(MAKEWORD(2,2), &wsaData)!=0) {
319 std::cerr << "iomonitor: failed to initialize winsocks" << std::endl;
320 return -1;
321 }
322#endif
323#endif
324
325 //initialize vDevice
326 FD_DH("Initialize vDevice");
327 std::cout << "iomonitor: instantiate device from file" << std::endl;
328 vDevice* dev;
329 dev=vDevice::FromFile(std::string(argv[1]));
330 sDevice* sdev=dynamic_cast<sDevice*>(dev);
331
332 //start vDevice
333 std::cout << "iomonitor: starting device " << std::endl;
334 dev->Start();
335
336 //loop until device is up
337 while(dev->Status()!=vDevice::Up){;}
338
339 // loop until user terminates
340 while(true) {
341
342 // set up cheap console userinterface
343 std::cout << std::endl;
344 std::cout << std::endl;
345 std::cout << "# iomonitor commands are:" << std::endl;
346 std::cout << "#" << std::endl;
347 std::cout << "# read faudes event via wait (re)" << std::endl;
348 std::cout << "# read faudes events via polling (pe)" << std::endl;
349 std::cout << "# flush faudes input events (fe)" << std::endl;
350 if(sdev) std::cout << "# read signal value by bitaddress (rs)" << std::endl;
351 if(sdev) std::cout << "# read signal values via polling (ps)" << std::endl;
352 std::cout << "#" << std::endl;
353 std::cout << "# write faudes event (we)" << std::endl;
354 if(sdev) std::cout << "# write signal value by bitaddress (ws)" << std::endl;
355 std::cout << "#" << std::endl;
356 std::cout << "# device time (time)" << std::endl;
357 std::cout << "# reset device (reset)" << std::endl;
358 std::cout << "# list all device events (list) " << std::endl;
359 std::cout << "# exit (exit) " << std::endl;
360 std::cout << "#" << std::endl;
361 std::cout << ">";
362 // get user-choice
363 std::string choice;
364 std::cin >> choice;
365 //execute user-choice
366 if(choice=="exit") break;
367 if(choice=="reset") {dev->Reset();};
368 if(choice=="time") ReadTime(dev);
369 if(choice=="list") ListEvents(dev);
370 if(choice=="pe") PollInputEvents(dev);
371 if(choice=="re") WaitInputEvent(dev);
372 if(choice=="fe") FlushInputEvents(dev);
373 if(sdev && choice=="rs") ReadSignalValue(sdev);
374 if(sdev && choice=="ps") PollInputSignals(sdev);
375 if(choice=="we") WriteOutputEvent(dev);
376 if(sdev && choice=="ws") WriteSignalValue(sdev);
377
378 }
379
380 std::cout << "# iomonitor: done " << std::endl;
381 std::cout << "##########################################" << std::endl;
382
383
384 FD_DH("Stopping vDevice");
385
386 //stop background thread
387 dev->Stop();
388
389 return 0;
390}
391
392
393
int main()
void faudes_termsignal(void(*sighandler)(int))
const char * faudes_strsignal(int sig)
void faudes_usleep(long int usec)
void faudes_diffsystime(const faudes_systime_t &end, const faudes_systime_t &begin, faudes_systime_t *res)
bool Exists(const Idx &rIndex) const
void SymbolicName(Idx index, const std::string &rName)
bool Insert(const Idx &rIndex)
Idx Index(const std::string &rName) const
std::string ToString(const std::string &rLabel="", const Type *pContext=0) const
void Write(const Type *pContext=0) const
int MaxBitAddress(void) const
void WriteSignal(int bitaddr, bool value)
virtual void Reset(void)
bool ReadSignal(int bitaddr)
virtual const EventSet & Inputs(void) const
virtual void TimeScale(unsigned int scale)
static void StopAll(void)
virtual DeviceState Status(void)
virtual void Stop(void)
virtual void Start(void)
virtual void WriteOutput(Idx output)=0
virtual void Reset(void)
static vDevice * FromFile(const std::string &rFileName)
virtual Idx ReadInput(void)
virtual bool WaitInputs(Time::Type duration)
virtual Time::Type CurrentTime(void)
virtual void FlushOutputs(void)
virtual const EventSet & Outputs(void) const
bool Empty(void) const
void PollInputSignals(sDevice *sdev)
void WaitInputEvent(vDevice *dev)
void ReadTime(vDevice *dev)
Definition iomonitor.cpp:72
void iomonitor_exit(void)
Definition iomonitor.cpp:47
void ListEvents(const vDevice *dev)
Definition iomonitor.cpp:57
void FlushInputEvents(vDevice *dev)
volatile sig_atomic_t signal_in_progress
Definition iomonitor.cpp:29
void WriteOutputEvent(vDevice *dev)
void PollInputEvents(vDevice *dev)
void WriteSignalValue(sDevice *sdev)
void ReadSignalValue(sDevice *dev)
Definition iomonitor.cpp:86
void catch_signal(int sig)
Definition iomonitor.cpp:32
#define FD_DH(message)
Definition iop_vdevice.h:27
uint32_t Idx
std::string VersionString()

libFAUDES 2.33k --- 2025.09.16 --- c++ api documentaion by doxygen