iomonitor.cpp

Go to the documentation of this file.
00001 /** @file iomonitor.cpp  Test utility for IO devices
00002 
00003 
00004 This tutorial demonstrates elementary access to external signals
00005 via the class faudes::vDevice. It can be used as a test uitility
00006 for device configuration. 
00007 
00008 
00009 @ingroup Tutorials
00010 
00011 @include iomonitor.cpp
00012 
00013 */
00014 
00015 
00016 #include "libfaudes.h"
00017 
00018 #include <signal.h>
00019 
00020 using namespace faudes;
00021 
00022 ///////////////////////////////////////////////////////
00023 // clean exit on signals
00024 
00025 // iomonitor clean-up on exit
00026 void iomonitor_exit(void);
00027 
00028 // signal handler recursion flag
00029 volatile sig_atomic_t signal_in_progress = 0;
00030 
00031 // signal handler to stop devices
00032 void catch_signal(int sig) {
00033   // detect recursion, pass on
00034   if(signal_in_progress) raise(sig);
00035   signal_in_progress = 1;
00036   // report
00037   std::cerr << "iomonitor: signal: " << faudes_strsignal(sig) << std::endl;
00038   // call my exit function
00039   iomonitor_exit();
00040   // re-install default handler
00041   signal(sig, SIG_DFL);
00042   // pass on signal
00043   raise(sig);
00044 }
00045 
00046 // iomonitor clean-up on exit
00047 void iomonitor_exit(void) {
00048   // stop all devices
00049   vDevice::StopAll();
00050 }
00051 
00052 
00053 ///////////////////////////////////////////////////////
00054 //Basic handling
00055 
00056 // list all known events
00057 void ListEvents(const vDevice* dev) {
00058   std::cout<< "% ###############################################################" << std::endl;
00059   std::cout<< "% # InputEvents" << std::endl;
00060   dev->Inputs().Write();
00061   std::cout<< "% ###############################################################" << std::endl;
00062   std::cout<< "% # OutputEvents " << std::endl;
00063   dev->Outputs().Write();
00064   std::cout<< "% ###############################################################" << std::endl;
00065 }
00066 
00067 
00068 ///////////////////////////////////////////////////////
00069 // Query Time
00070 
00071 // read time
00072 void ReadTime(vDevice* dev) {
00073 
00074   // read and report
00075   std::cout << "% ###############################################################" << std::endl;
00076   std::cout << "% # ReadTime: current time in ftu: " << dev->CurrentTime() << std::endl;
00077   std::cout << "% # ReadTime: using scale: " << dev->TimeScale() << std::endl;
00078 
00079 }
00080 
00081 
00082 ///////////////////////////////////////////////////////
00083 //Signal-I/O
00084 
00085 // read signal value
00086 void ReadSignalValue(sDevice* dev) {
00087   // declare static buffer
00088   static bool* samplePrevious=0;
00089   static bool* sampleCurrent=0;
00090   static int sampleSize=-1;
00091   // allocate memory for buffer
00092   if(sampleSize != dev->MaxBitAddress()+1) {
00093     sampleSize = dev->MaxBitAddress()+1;
00094     if(samplePrevious!=0) delete samplePrevious;
00095     if(sampleCurrent!=0) delete sampleCurrent;
00096     samplePrevious= new bool[sampleSize];
00097     sampleCurrent= new bool[sampleSize];
00098   }
00099   // read and report
00100   std::cout << "% ###############################################################" << std::endl;
00101   for(int bit=0; bit<sampleSize; bit++) {
00102     samplePrevious[bit]=sampleCurrent[bit];
00103   }
00104   for(int bit=0; bit<sampleSize; bit++) {
00105     sampleCurrent[bit]=dev->ReadSignal(bit);
00106   }
00107   std::cout << "% # ReadValue: current input reading: " << std::endl;
00108   for(int bit=0; bit<sampleSize; bit++) {
00109     std::cout<< "@" << (bit < 10 ? "0" : "") << bit << ":" << sampleCurrent[bit] << "   ";
00110     if((bit%8)==7 || bit+1==sampleSize) std::cout << std::endl;
00111   }
00112   std::cout <<"% # ReadValue: edges wrt previous reading: " << std::endl;
00113   int cnt =0;
00114   for(int bit=0; bit<sampleSize; bit++) {
00115     if(samplePrevious[bit]!=sampleCurrent[bit]) {
00116       std::cout<< "@"<< (bit < 10 ? "0" : "") << bit << ":" << sampleCurrent[bit] << "   ";
00117       if((cnt%8)==7 || bit+1==sampleSize) std::cout << std::endl;
00118       cnt+=1;
00119     }
00120   }   
00121   std::cout << "% ###############################################################" << std::endl;
00122 }
00123 
00124 
00125 // poll input signals
00126 void PollInputSignals(sDevice* sdev){
00127   std::cout<<"ReadInputs: time (secs) to monitor input signals: ";    
00128   int time_all;
00129   std::cin>>time_all;
00130   time_all*=1000; // convert to msecs
00131   std::cout<<"ReadEvents: time (msecs) to sleep between two polls: ";    
00132   int  time_delta;
00133   std::cin>>time_delta;
00134   // reset all input data so far
00135   sdev->Reset();
00136   // report performace, part 1
00137   struct timeval time_start, time_stop;
00138   gettimeofday(&time_start,NULL);
00139 
00140   // declare static buffer
00141   static bool* samplePrevious=0;
00142   static bool* sampleCurrent=0;
00143   static int sampleSize=-1;
00144   // allocate memory for buffer
00145   if(sampleSize != sdev->MaxBitAddress()+1) {
00146     sampleSize = sdev->MaxBitAddress()+1;
00147     if(samplePrevious!=0) delete samplePrevious;
00148     if(sampleCurrent!=0) delete sampleCurrent;
00149     samplePrevious= new bool[sampleSize];
00150     sampleCurrent= new bool[sampleSize];
00151   }
00152   // reset buffer
00153   for(int bit=0; bit<sampleSize; bit++) {
00154     samplePrevious[bit]=false;
00155     sampleCurrent[bit]=false;
00156   }
00157 
00158   // loop until time is up
00159   bool edges=true;
00160   for(int time_togo=time_all; time_togo>0; time_togo-=time_delta) {
00161     // read
00162     for(int bit=0; bit<sampleSize; bit++) {
00163       sampleCurrent[bit]=sdev->ReadSignal(bit);
00164       if(sampleCurrent[bit] != samplePrevious[bit]) edges=true;
00165     }
00166     // report
00167     if(edges) {
00168       std::cout << "% ###############################################################" << std::endl;
00169       for(int bit=0; bit<sampleSize; bit++) {
00170   std::cout<< "@"<< (bit < 10 ? "0" : "") << bit << ":" << sampleCurrent[bit];
00171         if(sampleCurrent[bit] != samplePrevious[bit]) 
00172     std::cout << "!  ";
00173         else
00174           std::cout << "   ";
00175         if((bit%8)==7 || bit+1==sampleSize) std::cout << std::endl;
00176       }
00177     }
00178     // copy
00179     for(int bit=0; bit<sampleSize; bit++) {
00180       samplePrevious[bit]=sampleCurrent[bit];
00181     }
00182     // clear edge detection 
00183     edges=0;
00184     // sleep
00185     faudes_usleep(1000*time_delta);
00186   };
00187 
00188   // report performance, part2
00189   gettimeofday(&time_stop,NULL);
00190   double time_diff= ( time_stop.tv_sec - time_start.tv_sec
00191     + (time_stop.tv_usec - time_start.tv_usec) / 1000000.0 ) * 1000.0;
00192   double time_sleep=time_all; 
00193   std::cout << "# performance: overall time: " << time_diff << "ms" << std::endl;
00194   std::cout << "# performance: sleep time:   " << time_sleep << "ms" << std::endl;
00195   std::cout << "# performance: process time per loop:   " << 
00196     (time_diff - time_sleep) / (time_all/time_delta)<< "ms" << std::endl;
00197 }
00198 
00199 // write signal value
00200 void WriteSignalValue(sDevice* sdev) {
00201   int bit, val;
00202   std::cout<<"WriteValue: enter bit address (or -1 to exit): ";
00203   std::cin>>bit;
00204   if(bit<0) return;
00205   std::cout<<"WriteValue: enter value (or -1 to exit): ";
00206   std::cin>>val;
00207   if(val<0) return;
00208   std::cout<<"WriteValue: setting output " << bit << " to value " << val << std::endl;
00209   sdev->WriteSignal(bit,val!=0);
00210 }
00211 
00212 //////////////////////////////////////////////////////////////
00213 //Event-handling
00214 
00215 // execute output event
00216 void WriteOutputEvent(vDevice* dev) {
00217   std::cout<<"WriteOutput: enter event by name: ";  
00218   std::string testEvent;
00219   std::cin>>testEvent;
00220   if(!dev->Outputs().Exists(testEvent)) {
00221     std::cout<<"Unknown output event " << std::endl;  
00222     return;
00223   }
00224   faudes::Idx fev= dev->Outputs().Index(testEvent);
00225   dev->WriteOutput(fev);
00226   dev->FlushOutputs();
00227 }
00228 
00229 
00230 // poll input events
00231 void PollInputEvents(vDevice* dev){
00232   std::cout<<"ReadInputs: time (secs) to monitor input events: ";    
00233   int time_all;
00234   std::cin>>time_all;
00235   time_all*=1000; // convert to msecs
00236   std::cout<<"ReadEvents: time (msecs) to sleep between two polls: ";    
00237   int  time_delta;
00238   std::cin>>time_delta;
00239   // reset all input data so far
00240   dev->Reset();
00241   // report performace, part 1
00242   struct timeval time_start, time_stop;
00243   gettimeofday(&time_start,NULL);
00244 
00245   // loop until time is up
00246   for(int time_togo=time_all; time_togo>0; time_togo-=time_delta) {
00247     Idx sev=dev->ReadInput();
00248     if(sev!=0) 
00249       std::cout<<"ReadInputs: event " << dev->Inputs().SymbolicName(sev) << std::endl;
00250     faudes_usleep(1000*time_delta);
00251   };
00252 
00253   // report performance, part2
00254   gettimeofday(&time_stop,NULL);
00255   double time_diff= ( time_stop.tv_sec - time_start.tv_sec
00256     + (time_stop.tv_usec - time_start.tv_usec) / 1000000.0 ) * 1000.0;
00257   double time_sleep=time_all; 
00258   std::cout << "# performance: overall time: " << time_diff << "ms" << std::endl;
00259   std::cout << "# performance: sleep time:   " << time_sleep << "ms" << std::endl;
00260   std::cout << "# performance: process time per loop:   " << 
00261     (time_diff - time_sleep) / (time_all/time_delta)<< "ms" << std::endl;
00262 }
00263 
00264 // WaitInputEvent(vDevice* dev)
00265 void WaitInputEvent(vDevice* dev){
00266   std::cout<<"Enter max. duration (in faudes-time units) to wait for a input-event to occur"<<std::endl;
00267   std::cout<<"Note: 1 faudes-time unit is configured to " << dev->TimeScale() << " msecs" <<std::endl;
00268   tpTime::Type duration;
00269   std::cin>>duration;
00270   EventSet occuredEvents;
00271   //wait for input-event to occur
00272   dev->WaitInputs(duration); 
00273   //identify occured events
00274   while(Idx sev=dev->ReadInput()) occuredEvents.Insert(sev); 
00275   //report occured events
00276   if(!occuredEvents.Empty()) std::cout << occuredEvents.ToString();
00277   else std::cout<<"No event recognized";
00278 }
00279 
00280 // FlushInputEvent(vDevice* dev)
00281 void FlushInputEvents(vDevice* dev){
00282   //identify occured events
00283   EventSet occuredEvents;
00284   while(Idx sev=dev->ReadInput()) occuredEvents.Insert(sev); 
00285   //report occured events
00286   if(!occuredEvents.Empty()) std::cout << occuredEvents.ToString();
00287   else std::cout<<"No event recognized";
00288 }
00289 
00290 
00291 //////////////////////////////////////////////////////////////
00292 //User-Interface loop
00293 
00294 int main(int argc, char* argv[]) {
00295 
00296   // debugging autoregistration :-( 
00297   /*
00298   std::cerr << " ====== auto registration " << std::endl;
00299   TypeRegistry::G()->Write(); 
00300   std::cerr << " ====== registration " << std::endl;
00301   AutoRegisterType<cDevice> gRtiLocalIOReg("ComediDevice");
00302   TypeRegistry::G()->Write(); 
00303   */
00304 
00305   // install my signal handler
00306   faudes_termsignal(catch_signal);
00307 
00308   // first argument has to be filename
00309   if(argc!=2) {
00310     std::cerr << "iomonitor: " << VersionString()  << std::endl;
00311     std::cerr << "usage: iomonitor <device-file>" << std::endl;
00312     return -1;
00313   }
00314 
00315 #ifdef FAUDES_NETWORK
00316 #ifdef FAUDES_WINDOWS
00317   // initialise winsocks
00318   WSADATA wsaData;
00319   if(WSAStartup(MAKEWORD(2,2), &wsaData)!=0) {
00320     std::cerr << "iomonitor: failed to initialize winsocks" << std::endl;
00321     return -1;
00322   }
00323 #endif
00324 #endif
00325 
00326   //initialize vDevice
00327   FD_DH("Initialize vDevice");
00328   std::cout << "iomonitor: instantiate device from file" << std::endl;
00329   vDevice* dev;
00330   dev=vDevice::FromFile(std::string(argv[1]));
00331   sDevice* sdev=dynamic_cast<sDevice*>(dev);
00332 
00333   //start vDevice
00334   std::cout << "iomonitor: starting device " << std::endl;
00335   dev->Start();
00336 
00337   //loop until device is up
00338   while(dev->Status()!=vDevice::Up){;}
00339 
00340   // loop until user terminates
00341   while(true) {
00342 
00343   // set up cheap console userinterface
00344   std::cout << std::endl;
00345   std::cout << std::endl;
00346   std::cout << "# iomonitor commands are:" << std::endl;
00347   std::cout << "#" << std::endl;
00348   std::cout << "#   read faudes event via wait           (re)" << std::endl;
00349   std::cout << "#   read faudes events via polling       (pe)" << std::endl;
00350   std::cout << "#   flush faudes input events            (fe)" << std::endl;
00351   if(sdev) std::cout << "#   read signal value by bitaddress      (rs)" << std::endl;
00352   if(sdev) std::cout << "#   read signal values via polling       (ps)" << std::endl;
00353   std::cout << "#" << std::endl;
00354   std::cout << "#   write faudes event               (we)" << std::endl;
00355   if(sdev) std::cout << "#   write signal value by bitaddress     (ws)" << std::endl;
00356   std::cout << "#" << std::endl;
00357   std::cout << "#   device time                    (time)" << std::endl;
00358   std::cout << "#   reset device                   (reset)" << std::endl;
00359   std::cout << "#   list all device events             (list) " << std::endl;
00360   std::cout << "#   exit                               (exit) " << std::endl;
00361   std::cout << "#" << std::endl;
00362   std::cout << ">";
00363   // get user-choice
00364   std::string choice;
00365   std::cin >> choice;
00366   //execute user-choice
00367   if(choice=="exit") break;
00368   if(choice=="reset") {dev->Reset();};
00369   if(choice=="time") ReadTime(dev);
00370   if(choice=="list") ListEvents(dev); 
00371   if(choice=="pe") PollInputEvents(dev);
00372   if(choice=="re") WaitInputEvent(dev);
00373   if(choice=="fe") FlushInputEvents(dev);
00374   if(sdev && choice=="rs") ReadSignalValue(sdev);   
00375   if(sdev && choice=="ps") PollInputSignals(sdev);   
00376   if(choice=="we") WriteOutputEvent(dev); 
00377   if(sdev && choice=="ws") WriteSignalValue(sdev);  
00378 
00379   }
00380   
00381   std::cout << "# iomonitor: done " << std::endl;
00382   std::cout << "##########################################" << std::endl;
00383 
00384  
00385   FD_DH("Stopping vDevice");
00386 
00387   //stop background thread  
00388   dev->Stop();
00389   
00390   return 0;
00391 }
00392 
00393 
00394 

libFAUDES 2.23h --- 2014.04.03 --- c++ api documentaion by doxygen