About
User Reference
C++ API
luafaudes
Developer
Links
libFAUDES online
libFAUDES

Sections

Index

iop_xdevice.cpp

Go to the documentation of this file.
00001 /** @file iop_xdevice.cpp Device container with vDevice interface */
00002 
00003 /*
00004    FAU Discrete Event Systems Library (libfaudes)
00005 
00006    Copyright (C) 2008, Thomas Moor
00007    Exclusive copyright is granted to Klaus Schmidt
00008 
00009 */
00010 
00011 
00012 
00013 #include "iop_xdevice.h"
00014 #include "sys/time.h"
00015 
00016 #include "iop_simplenet.h"
00017 #include "iop_comedi.h"
00018 #include "iop_wago.h"
00019 #include "iop_serial.h"
00020 #include "iop_d3ripURT.h" 
00021 #include "iop_d3ripDART.h"
00022 
00023 namespace faudes {
00024 
00025 /*
00026  **********************************************
00027  **********************************************
00028  **********************************************
00029 
00030  implementation: xDevice
00031 
00032  **********************************************
00033  **********************************************
00034  **********************************************
00035  */
00036 
00037 // std faudes
00038 FAUDES_TYPE_IMPLEMENTATION(DeviceContainer,xDevice,vDevice)
00039 
00040 // autoregister
00041 AutoRegisterType<xDevice> gRtiRegisterDeviceContainer("DeviceContainer");
00042 
00043 //constructor
00044 xDevice::xDevice(void) : vDevice() {
00045   FD_DHV("xDevice(" << mName << ")::xDevice()");
00046   mName="IoDevices";
00047   // have appropriate default label
00048   mDefaultLabel="DeviceContainer";
00049 
00050   // auto register fix: 
00051   // for some reasons the global register objects do not work properly.
00052   // since the xdevice is autoregeistered by the rti, we ask the constructor
00053   // to register the other devices
00054 
00055 #ifdef FAUDES_IODEVICE_SIMPLENET
00056   static AutoRegisterType<nDevice> gRtiIORegisterSimplenetDevice("SimplenetDevice");
00057 #endif
00058 #ifdef FAUDES_IODEVICE_COMEDI
00059   static AutoRegisterType<cDevice> gRtiIORegisterComediDevice("ComediDevice");
00060 #endif
00061 #ifdef FAUDES_IODEVICE_WAGO
00062   static AutoRegisterType<wDevice> gRtiIORegisterWagoDevice("WagoDevice");
00063 #endif
00064 #ifdef FAUDES_IODEVICE_SERIAL
00065   static AutoRegisterType<spiDevice> gRtiIORegisterSerialPiDevice("SpiDevice");
00066 #endif
00067 #ifdef FAUDES_IODEVICE_D3RIP_URT
00068   static AutoRegisterType<d3ripURTDevice> gRtiIORegisterD3ripUrtDevice("D3ripURTDevice");
00069 #endif
00070 #ifdef FAUDES_IODEVICE_D3RIP_DART
00071   static AutoRegisterType<d3ripDARTDevice> gRtiIORegisterD3ripDartDevice("D3ripDARTDevice");
00072 #endif
00073 
00074 }
00075 
00076 // destructor
00077 xDevice::~xDevice(void) {
00078   FD_DHV("xDevice(" << mName << ")::~xDevice()");
00079   // loop to free devices.
00080   Iterator dit;
00081   for(dit=Begin();dit!=End();dit++){
00082     delete (*dit);
00083   }
00084 }
00085 
00086 //FromTokenReader(rTr)
00087 xDevice* xDevice::FromTokenReader(TokenReader& rTr) {
00088   // construct from token reader
00089   FD_DHV("xDevice::FromTokenReader()");
00090   // allocate
00091   xDevice* dev=new xDevice();
00092   // read
00093   dev->DoRead(rTr);
00094   return dev;
00095 }
00096 
00097 //FromFile(rFilename)
00098 xDevice* xDevice::FromFile(const std::string& rFileName) {
00099   // construct from file
00100   FD_DHV("xDevice()::FromFile(" << rFileName <<")");
00101   // peek first token
00102   TokenReader tr(rFileName);
00103   return FromTokenReader(tr);
00104 }
00105 
00106 
00107 //Status(void)
00108 xDevice::DeviceState xDevice::Status(void){
00109 
00110   FD_DHV("xDevice(" << mName << ")::Status() ");
00111   //prepare result
00112   xDevice::DeviceState res;
00113   //vector to store states of all devices integrated in xdevice
00114   std::vector<xDevice::DeviceState> states;
00115   //vector iterator
00116   std::vector<DeviceState>::iterator vit;
00117   vit = states.begin();
00118   //device iterator
00119   iterator dit;
00120   //identify device state
00121   for(dit=Begin();dit!=End();dit++){
00122     //get state of current device and insert it in vector
00123     states.push_back((DeviceState)(*dit)->Status());
00124     //make sure it isnt the first entry
00125     if(vit != states.begin()){
00126       //if current entry doesnt equal previous
00127       //decide depending on last command
00128       if (*vit!=*vit--){
00129         //if last command was start: "StartUp"
00130         if(lastCommandWasStart){
00131           res = StartUp;
00132           break;
00133         }
00134         //if last command was stop: "ShutDown"
00135         if(!lastCommandWasStart){
00136           res = ShutDown;
00137           break;
00138         }
00139       }
00140     }
00141     //move on to next device
00142     vit++;
00143   }
00144   //if for-loop finished all entries of vector "states" are equal
00145   res =  *states.begin();
00146   return res;
00147 }
00148 
00149 // Start(void)
00150 void xDevice::Start(void) {
00151 
00152   FD_DHV("xDevice(" << mName <<")::Start()");
00153   // start implies reset
00154   Reset();
00155   //start all existing devices
00156   Iterator dit;
00157   for(dit = Begin();dit!=End();dit++){
00158     (*dit)->Start();
00159   }
00160   //remember this command
00161   lastCommandWasStart = true;
00162 }
00163 
00164 // Stop(void)
00165 void xDevice::Stop(void) {
00166 
00167   FD_DHV("xDevice(" << mName <<")::Stop()");
00168   // xDevice Reset
00169   Reset();
00170   // stop all existing devices
00171   Iterator dit;
00172   for(dit=Begin();dit!=End();dit++){
00173     (*dit)->Stop();
00174   }
00175   //remember this command
00176   lastCommandWasStart = false;
00177 }
00178 
00179 // Reset(void)
00180 void xDevice::Reset(void){
00181   //clear dynamic data
00182 
00183   FD_DHV("xDevice(" << mName <<")::Reset()");
00184   // device-iterator
00185   Iterator dit;
00186   for(dit=Begin();dit!=End();dit++){
00187     (*dit)->Reset();
00188   }
00189   // call base to reset time and fifo
00190   vDevice::Reset();
00191 }
00192 
00193 // Clear(void)
00194 void xDevice::Clear(void){
00195   //clear static data
00196 
00197   FD_DHV("xDevice(" << mName << ")::Clear()");
00198   // Stop running devices
00199   Stop();
00200   // device-iterator
00201   Iterator dit;
00202   // and clear all devices
00203   for(dit=Begin();dit!=End();dit++){
00204     (*dit)->Clear();
00205   }
00206   // destroy existing data
00207   for(dit=Begin();dit!=End();dit++){
00208     delete (*dit);
00209   }
00210   // compile with empty containers
00211   Compile();
00212 }
00213 
00214 // Insert(vDevice*)
00215 void xDevice::Insert(vDevice* device){
00216 
00217   FD_DHV("xDevice("<<mName<<")::Insert(" << device << "):" <<  device->Name());
00218   // insert any vdevice, but no xdevice
00219   if(dynamic_cast<xDevice*>(device)) {
00220     std::stringstream errstr;
00221     errstr << "Attempt to insert xDevice into xDevice";
00222     throw Exception("xDevice::Compile", errstr.str(), 550);
00223   }
00224   // add to mDevices
00225   mDevices.push_back(device);
00226   // and update compiled data
00227   Compile();
00228 }
00229 
00230 //Insert(rFilename)
00231 void xDevice::Insert(const std::string& rFileName){
00232   //inserts a device by filename
00233   FD_DHV("xDevice("<<mName<<")::Insert(rFileName)");
00234   //read device
00235   vDevice* pdev = vDevice::FromFile(rFileName);
00236   //insert device
00237   Insert(pdev);
00238   //and remember its name
00239   mDeviceNames.push_back(rFileName);
00240 }
00241 
00242 
00243 // Compile(void)
00244 void xDevice::Compile(void) {
00245   //build up internal data-structures
00246 
00247   FD_DHV("xDevice("<<mName<<")::Compile()");
00248   Stop();
00249   // build up (event-idx,int)-map and memorize all existing events
00250   // prepare containers
00251   mInputs.Clear();
00252   mOutputs.Clear();
00253   mInputToDevice.clear();
00254   mOutputToDevice.clear();
00255   // temporary container
00256   EventSet tmpSenEvents;
00257   EventSet tmpActEvents;
00258   // event-iterator
00259   EventSet::Iterator eit;
00260   // device-iterator
00261   Iterator dit;
00262   // helper
00263   int j;
00264   // iterate over existing devices
00265   for(dit=Begin(), j=0;  dit!=End(); dit++,j++){
00266     // get events by Index
00267     tmpSenEvents = (*dit)->Inputs();
00268     tmpActEvents = (*dit)->Outputs();
00269     //insert output-events in map
00270     for(eit=tmpActEvents.Begin();eit!=tmpActEvents.End();eit++){
00271       // test if actual event already exists in map
00272       if(mOutputs.Exists(*eit)){
00273         //throw exeption
00274         std::stringstream errstr;
00275         errstr << "Event already exists!";
00276         throw Exception("xDevice()::Compile", errstr.str(), 550);
00277       }
00278       mOutputToDevice[*eit] = j;
00279     }
00280     // memorize events
00281     mInputs.InsertSet(tmpSenEvents);
00282     mOutputs.InsertSet(tmpActEvents);
00283     // tell the device which mutex/condition-pair to use
00284     (*dit)->UseCondition(pWaitMutex,pWaitCondition);
00285     (*dit)->UseBuffer(pBufferMutex,pInputBuffer);
00286   }//end iteration over existing devices
00287   // set time scale from first device
00288   if(Size()!=0) (*Begin())->TimeScale(mTimeScale);
00289 }
00290 
00291 
00292 //Configure(event,attr)
00293 void xDevice::Configure(Idx event, const AttributeDeviceEvent& attr){
00294   (void) event; (void) attr;
00295   // cannot do vDevice style configuration of events
00296 
00297   FD_DHV("xDevice("<<mName<<")::Configure(Idx,attr): ");
00298   std::stringstream errstr;
00299   errstr << "Attempt to configure xDevice by event";
00300   throw Exception("xDevice::Configure(Idx,attr)", errstr.str(), 550);
00301 }
00302 
00303 //Configure(rEvents)
00304 void xDevice::Configure(const EventSet& rEvents){
00305   (void) rEvents;
00306   // cannot do vDevice style configuration of events
00307   
00308   FD_DHV("xDevice("<<mName<<")::Configure(rEvents)");
00309   std::stringstream errstr;
00310   errstr << "Attempt to configure xDevice by events";
00311   throw Exception("xDevice::Configure", errstr.str(), 550);
00312 }
00313 
00314 
00315 //CurrentTime(void)
00316 tpTime::Type xDevice::CurrentTime(void) {
00317 
00318   FD_DHV("xDevice("<<mName<<"): CurrentTime() ");
00319   // throw exception if there is no device
00320   if(Size()==0) {
00321     std::stringstream errstr;
00322     errstr << "xDevice owns no device!";
00323     throw Exception("xDevice::CurrentTime", errstr.str(),550);
00324   }
00325   // ask first device
00326   return (*Begin())->CurrentTime();
00327 }
00328 
00329 
00330 //CurrentTime(void)
00331 long int xDevice::CurrentTimeMs(void) {
00332   //debug flag: say hello
00333   FD_DHV("xDevice("<<mName<<")::CurrentTimeMs() ");
00334   // throw exception if there is no device
00335   if(Size()==0) {
00336     std::stringstream errstr;
00337     errstr << "xDevice owns no device!";
00338     throw Exception("xDevice::CurrentTimeMs", errstr.str(),550);
00339   }
00340   // ask first device
00341   return (*Begin())->CurrentTimeMs();
00342 }
00343 
00344 //CurrentTime(now)
00345 void xDevice::CurrentTime(tpTime::Type now) {
00346   //debug flag: say hello
00347   FD_DHV("xDevice("<<mName<<")::CurrentTime("<<now<<") ");
00348   // tell first device if such
00349   if(Size()!=0) (*Begin())->CurrentTime(now);
00350 }
00351 
00352 //CurrentTimeMs(now)
00353 void xDevice::CurrentTimeMs(long int nowms) {
00354   //debug flag: say hello
00355 
00356   FD_DHV("xDevice("<<mName<<")::CurrentTimeMs("<<nowms<<") ");
00357   // tell first device if such
00358   if(Size()!=0) (*Begin())->CurrentTimeMs(nowms);
00359 }
00360 
00361 //DoWrite(rTr,rLabel)
00362 void xDevice::DoWriteConfiguration(TokenWriter& rTw, const std::string& rLabel, const Type* pContext) const {
00363   (void) rTw;
00364 
00365   FD_DHV("xDevice("<<mName<<")::DoWriteConfiguration()");
00366   // hard coded begin
00367   rTw.WriteBegin("Devices");
00368   // define device-iterator
00369   Iterator dit;
00370   //iterate over all devices 
00371   for(Idx i=0; i<Size(); i++) {
00372     //if device was read from an extra file
00373     if(mDeviceNames.at(i) != ""){ 
00374       //write path to TokenWriter
00375       FD_DHV("xDevice("<<mName<<")::DoWrite(): "<<mDeviceNames.at(i));
00376       rTw.WriteString(mDeviceNames.at(i)); //TODO: relativ path-names
00377     }
00378     //else device was directly read from base-config-file
00379     else if(mDeviceNames.at(i) == ""){
00380       //write configuration 
00381       FD_DHV("xDevice("<<mName<<")::DoWrite(): "<<mDeviceNames.at(i));
00382       (mDevices.at(i))->Write(rTw);
00383     }
00384   } 
00385   rTw.WriteEnd("Devices");
00386 }
00387 
00388 
00389 // ResetRequest()
00390 bool xDevice::ResetRequest(void) {
00391   bool res=false;
00392   Iterator dit;
00393   for(dit=Begin();dit!=End();dit++){
00394     res = res | (*dit)->ResetRequest();
00395   }
00396   return res;
00397 }
00398 
00399 //DoRead(rTr,rLabel)
00400 void xDevice::DoReadConfiguration(TokenReader& rTr, const std::string& rLabel, const Type* pContext) {
00401   (void) rLabel; (void) pContext;
00402 
00403   FD_DHV("xDevice("<<mName<<")::DoReadConfiguration()");
00404   //prepare token
00405   Token token;
00406   //prepare string 
00407   std::string filename = "";      //to store filename
00408   std::string dirname = "";  //to store directory
00409   std::string path;          //to store absolut path
00410   // have default section
00411   std::string label = rLabel;
00412   if(label=="") label = "Devices";
00413   // read begin
00414   rTr.ReadBegin(label);
00415   // fill mDevices with devices specified in given file
00416   while(!rTr.Eos("Devices")){
00417     //peek token
00418     rTr.Peek(token);
00419     // if Token is a String we assume its the name of a file containing a device
00420     if(token.Type()==Token::String) {
00421       //read Token
00422       rTr.Get(token);
00423       //import filename
00424       filename = token.StringValue();
00425       //build up path to base-file
00426       if(rTr.SourceMode()==TokenReader::File) dirname = ExtractDirectory(rTr.FileName());
00427       //build up path to specified file
00428       path = dirname.append(filename);
00429       //insert device
00430       Insert(path);
00431       continue;
00432     }
00433     // if its not a file it has to be a device
00434     else if(token.Type()==Token::Begin) {
00435       // read device
00436       vDevice* devp = vDevice::FromTokenReader(rTr);
00437       // insert device mDevices
00438       Insert(devp);
00439       //record that this device was read inline
00440       mDeviceNames.push_back("");
00441     }    
00442   }
00443   rTr.ReadEnd(label);
00444 }
00445 
00446 
00447 // WriteOutput(Idx)
00448 void xDevice::WriteOutput(Idx output){
00449   FD_DHV("xDevice("<<mName<<")::WriteOutput()");
00450   // identify corresponding device(if idx is unique)
00451   int didx = mOutputToDevice[output];
00452   FD_DH("xDevice("<<mName<<")::WriteOutput(): " << output << " to " << didx);
00453   mDevices.at(didx)->WriteOutput(output);
00454 }
00455 
00456 
00457 // FlusgBufferes()
00458 void xDevice::FlushOutputs(void) {
00459   // iterate over all participating devices
00460   for(Iterator dit=Begin();  dit!=End(); dit++)
00461     (*dit)->FlushOutputs();
00462 }
00463 
00464 
00465 
00466 } // name space
00467 
00468 

libFAUDES 2.20s --- 2011.10.12 --- c++ source docu by doxygen