iop_wago.cppGo 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 |