iop_wago.cpp

Go to the documentation of this file.
00001 /** @file iop_wago.cpp provides access to wago-kbus*/
00002 
00003 /*
00004    FAU Discrete Event Systems Library (libfaudes)
00005 
00006    Copyright (C) 2009, Thomas Wittmann, Thomas Moor.
00007    Copyright (C) 2010, Thomas Moor.
00008 
00009 */
00010 
00011 
00012 // include header
00013 #include "iop_wago.h"
00014 
00015 // only compile for use with wago-ipc
00016 #ifdef FAUDES_IODEVICE_WAGO
00017 
00018 // Include functions from "wago_ipc_kbus.c"
00019 extern "C" {
00020   // Start the kbus_thread used to build up the data-structures used to access the process-image.
00021   extern void start_kbus_thread(void);
00022   // Update a user-copy of the kbus process-image data-structures
00023   extern void kbus_update_image(void);
00024   // Test if failures occured which make reading form kbus impossible
00025   extern int kbus_running(void);
00026 }
00027 
00028 namespace faudes {
00029 
00030 
00031 // std faudes, incl dummy
00032 FAUDES_TYPE_IMPLEMENTATION(WagoDevice,wDevice,sDevice)
00033 
00034 // autoregister
00035 AutoRegisterType<wDevice> gRtiRegisterWagoDevice("WagoDevice");
00036 
00037 //constructor
00038 wDevice::wDevice(void) : sDevice() {
00039   FD_DHV("wDevice(" << mName << ")::wDevice()");
00040   // have appropriate default label for token io
00041   mDefaultLabel = "WagoDevice";
00042   // pointer to kbus-I/O-image 
00043   pInputImage=0;
00044   pOutputImage=0;
00045   // no kbus-failure before kbus was even started
00046   mKbusOk=true;
00047 }
00048 
00049 //deconstructor
00050 wDevice::~wDevice(void) {
00051   FD_DHV("wDevice(" << mName << ")::~wDevice()");
00052   Stop();
00053 }
00054 
00055 // Start(void)
00056 void wDevice::Start(void) {
00057   // device is only functional in synchronous mode
00058   mSyncWrite=true;
00059   //open wago-device
00060   if(mState!=Down) return;
00061   FD_DH("wDevice(" << mName << ")::Start(): open devices");
00062   // initialize kbus
00063   int res = kbus_init();
00064   // set up kbus-thread
00065   start_kbus_thread();
00066   FD_DHV("wDevice(" << mName << ")::Start(): res = " << res );
00067   // throw execption if opening kbus failed
00068   if(res != 0) {
00069     std::stringstream errstr;
00070     errstr << "cannot open kbus";
00071     throw Exception("wDevice()::Start()", errstr.str(), 552);
00072   }
00073   // invalidate images
00074   pInputImage=0;
00075   pOutputImage=0;
00076   // call base (incl. reset)
00077   sDevice::Start();
00078   // pessimistic: assume  kbus-failure during start-up, let background thread figure
00079   mKbusOk=false;
00080   mState=StartUp;
00081 }//end Start()
00082 
00083 // Stop()
00084 void wDevice::Stop(void) {
00085   //close kbus interface
00086   if(mState != Up && mState != StartUp) return;
00087   FD_DHV("wDevice(" << mName << ")::Stop()");
00088   // close kbus 
00089   kbus_shutdown();
00090   // call base
00091   sDevice::Stop();
00092   
00093 }
00094 
00095 //DoWrite(rTr,rLabel,pContext)
00096 void wDevice::DoWritePreface(TokenWriter& rTw, const std::string& rLabel,  const Type* pContext) const {
00097   //dummy for token-output
00098   FD_DHV("wDevice("<<mName<<")::DoWritePreface()");
00099   //call base
00100   sDevice::DoWritePreface(rTw,"",pContext);
00101 }
00102 
00103 
00104 //DoReadPreface(rTr,rLabel,pContext)
00105 void wDevice::DoReadPreface(TokenReader& rTr,const std::string& rLabel, const Type* pContext){
00106   //dummy for token-input
00107   FD_DHV("wDevice("<<mName<<")::DoReadPreface()");
00108   //call base
00109   sDevice::DoReadPreface(rTr,"",pContext);
00110 }
00111 
00112 
00113 // DoReadSignalsPre(void)
00114 bool wDevice::DoReadSignalsPre(void) {
00115 
00116   static int okcnt=0;
00117 
00118   // We still have a valid input image: fine
00119   if(pInputImage) return true;
00120 
00121   // Prevent simultanuous reading and writing since this may
00122   // block the kbus thread.
00123   if(pOutputImage) return false;
00124 
00125   // Get input-image and lock kbus-mutex
00126   pInputImage=(char*) kbus_lock_input_image();
00127   // Test wether reading was valid
00128   int kok= kbus_running();   
00129   // If reading was not valid...
00130   if(kok==0) {
00131     // ... track and report ...
00132     if(mKbusOk) FD_WARN("wDevice(" << mName << ")::DoReadSignalsPre(): kbus error and friends ");    
00133     // ... invalidate input-image ...
00134     pInputImage=0;
00135     // ... releaset the mutex and ...
00136     kbus_release_io_image(); 
00137     // advertise failure
00138     mKbusOk=false;   
00139     okcnt=0;
00140   } 
00141   // If reading is valid ...
00142   if(kok!=0) {
00143     // ... wait for stable result ...
00144     if(!mKbusOk) {
00145       okcnt++;
00146       if(okcnt>50) {
00147          FD_WARN("wDevice(" << mName << ")::DoReadSignalsPre(): kbus recovered");    
00148          mKbusOk=true;
00149       }
00150       // ... release image while waiting.
00151       if(!mKbusOk) kbus_release_io_image();
00152     }
00153   }
00154   // return result
00155   return mKbusOk;
00156 }
00157 
00158 
00159 // DoReadSignalsPost(void)
00160 void wDevice::DoReadSignalsPost(void) {
00161   // If the input-image is still valid, we assume that we hold the mutex
00162   // and, hence, must now release it.
00163   if(pInputImage)   kbus_release_io_image();
00164   // invalidate input-image.
00165   pInputImage=0;
00166 }
00167 
00168 
00169 //ReadSignal(int)
00170 bool wDevice::DoReadSignal(int bit){
00171   // Read one input value, addressed by bit number (0 to 63);
00172 
00173   // Determine byte and bit address
00174   int byte = bit / 8;
00175   bit = bit % 8;
00176 
00177   // Read bit
00178   return ( pInputImage[byte] & (0x01 << (bit)) ) != 0x00;
00179 }
00180 
00181 
00182 // DoWriteSignalsPre(void)
00183 bool wDevice::DoWriteSignalsPre(void) {
00184   // We have a valid input image: error, prevent simultaneous read/write
00185   if(pInputImage) return false;
00186   // We have a valid output image: fine
00187   if(pOutputImage) return true;
00188   // Get an image and lock it
00189   pOutputImage=(char*) kbus_lock_output_image();
00190   // Done
00191   return true;
00192 }
00193 
00194 
00195 
00196 // DoWrtieSignalsPost(void)
00197 void wDevice::DoWriteSignalsPost(void) {
00198   // If there is an valid output-image, release kbus-mutex...
00199   if(pOutputImage)   kbus_release_io_image();
00200   // ...and invalidate image.
00201   pOutputImage=0;
00202 }
00203 
00204 
00205 //DoWriteSignal(int,int)
00206 void wDevice::DoWriteSignal(int bit, bool value){
00207   // Write one actor value, adressed by bit number (0 to 63);
00208   
00209   // Determine byte and bit addresse.
00210   int byte = (bit) / 8;
00211   bit = (bit) % 8;
00212   // Report 
00213   FD_DHV("wDevice(" << mName << ")::DoWriteSignal(int): bit " << bit << " in byte " << byte);
00214  
00215   // Write value to output-image using bit-operations
00216   // Write a "1", or...
00217   if(value) pOutputImage[byte] |= (0x1 << (bit));
00218   // ... write a "0"
00219   else pOutputImage[byte] &= ~(0x1 << (bit));
00220 }
00221 
00222 
00223 } // namespace
00224 
00225 #endif // end wago-support

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