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

libFAUDES 2.20d --- 2011.04.26 --- c++ source docu by doxygen