iop_wago.cpp
Go to the documentation of this file.
1 /** @file iop_wago.cpp provides access to wago-kbus*/
2 
3 /*
4  FAU Discrete Event Systems Library (libfaudes)
5 
6  Copyright (C) 2009, Thomas Wittmann, Thomas Moor.
7  Copyright (C) 2010, Thomas Moor.
8 
9 */
10 
11 
12 // include header
13 #include "iop_wago.h"
14 
15 // only compile for use with wago-ipc
16 #ifdef FAUDES_IODEVICE_WAGO
17 
18 // Include functions from "wago_ipc_kbus.c"
19 extern "C" {
20  // Start the kbus_thread used to build up the data-structures used to access the process-image.
21  extern void start_kbus_thread(void);
22  // Update a user-copy of the kbus process-image data-structures
23  extern void kbus_update_image(void);
24  // Test if failures occured which make reading form kbus impossible
25  extern int kbus_running(void);
26 }
27 
28 namespace faudes {
29 
30 
31 // std faudes, incl dummy
32 FAUDES_TYPE_IMPLEMENTATION(WagoDevice,wDevice,sDevice)
33 
34 // autoregister
35 AutoRegisterType<wDevice> gRtiRegisterWagoDevice("WagoDevice");
36 
37 //constructor
38 wDevice::wDevice(void) : sDevice() {
39  FD_DHV("wDevice(" << mName << ")::wDevice()");
40  // have appropriate default label for token io
41  mDefaultLabel = "WagoDevice";
42  // pointer to kbus-I/O-image
43  pInputImage=0;
44  pOutputImage=0;
45  // no kbus-failure before kbus was even started
46  mKbusOk=true;
47 }
48 
49 //deconstructor
50 wDevice::~wDevice(void) {
51  FD_DHV("wDevice(" << mName << ")::~wDevice()");
52  Stop();
53 }
54 
55 // Start(void)
56 void wDevice::Start(void) {
57  // device is only functional in synchronous mode
58  mSyncWrite=true;
59  //open wago-device
60  if(mState!=Down) return;
61  FD_DH("wDevice(" << mName << ")::Start(): open devices");
62  // initialize kbus
63  int res = kbus_init();
64  // set up kbus-thread
65  start_kbus_thread();
66  FD_DHV("wDevice(" << mName << ")::Start(): res = " << res );
67  // throw execption if opening kbus failed
68  if(res != 0) {
69  std::stringstream errstr;
70  errstr << "cannot open kbus";
71  throw Exception("wDevice()::Start()", errstr.str(), 552);
72  }
73  // invalidate images
74  pInputImage=0;
75  pOutputImage=0;
76  // call base (incl. reset)
78  // pessimistic: assume kbus-failure during start-up, let background thread figure
79  mKbusOk=false;
80  mState=StartUp;
81 }//end Start()
82 
83 // Stop()
84 void wDevice::Stop(void) {
85  //close kbus interface
86  if(mState != Up && mState != StartUp) return;
87  FD_DHV("wDevice(" << mName << ")::Stop()");
88  // close kbus
89  kbus_shutdown();
90  // call base
91  sDevice::Stop();
92 
93 }
94 
95 //DoWrite(rTr,rLabel,pContext)
96 void wDevice::DoWritePreface(TokenWriter& rTw, const std::string& rLabel, const Type* pContext) const {
97  //dummy for token-output
98  FD_DHV("wDevice("<<mName<<")::DoWritePreface()");
99  //call base
100  sDevice::DoWritePreface(rTw,"",pContext);
101 }
102 
103 
104 //DoReadPreface(rTr,rLabel,pContext)
105 void wDevice::DoReadPreface(TokenReader& rTr,const std::string& rLabel, const Type* pContext){
106  //dummy for token-input
107  FD_DHV("wDevice("<<mName<<")::DoReadPreface()");
108  //call base
109  sDevice::DoReadPreface(rTr,"",pContext);
110 }
111 
112 
113 // DoReadSignalsPre(void)
114 bool wDevice::DoReadSignalsPre(void) {
115 
116  static int okcnt=0;
117 
118  // We still have a valid input image: fine
119  if(pInputImage) return true;
120 
121  // Prevent simultanuous reading and writing since this may
122  // block the kbus thread.
123  if(pOutputImage) return false;
124 
125  // Get input-image and lock kbus-mutex
126  pInputImage=(char*) kbus_lock_input_image();
127  // Test wether reading was valid
128  int kok= kbus_running();
129  // If reading was not valid...
130  if(kok==0) {
131  // ... track and report ...
132  if(mKbusOk) FD_WARN("wDevice(" << mName << ")::DoReadSignalsPre(): kbus error and friends ");
133  // ... invalidate input-image ...
134  pInputImage=0;
135  // ... releaset the mutex and ...
136  kbus_release_io_image();
137  // advertise failure
138  mKbusOk=false;
139  okcnt=0;
140  }
141  // If reading is valid ...
142  if(kok!=0) {
143  // ... wait for stable result ...
144  if(!mKbusOk) {
145  okcnt++;
146  if(okcnt>50) {
147  FD_WARN("wDevice(" << mName << ")::DoReadSignalsPre(): kbus recovered");
148  mKbusOk=true;
149  }
150  // ... release image while waiting.
151  if(!mKbusOk) kbus_release_io_image();
152  }
153  }
154  // return result
155  return mKbusOk;
156 }
157 
158 
159 // DoReadSignalsPost(void)
160 void wDevice::DoReadSignalsPost(void) {
161  // If the input-image is still valid, we assume that we hold the mutex
162  // and, hence, must now release it.
163  if(pInputImage) kbus_release_io_image();
164  // invalidate input-image.
165  pInputImage=0;
166 }
167 
168 
169 //ReadSignal(int)
170 bool wDevice::DoReadSignal(int bit){
171  // Read one input value, addressed by bit number (0 to 63);
172 
173  // Determine byte and bit address
174  int byte = bit / 8;
175  bit = bit % 8;
176 
177  // Read bit
178  return ( pInputImage[byte] & (0x01 << (bit)) ) != 0x00;
179 }
180 
181 
182 // DoWriteSignalsPre(void)
183 bool wDevice::DoWriteSignalsPre(void) {
184  // We have a valid input image: error, prevent simultaneous read/write
185  if(pInputImage) return false;
186  // We have a valid output image: fine
187  if(pOutputImage) return true;
188  // Get an image and lock it
189  pOutputImage=(char*) kbus_lock_output_image();
190  // Done
191  return true;
192 }
193 
194 
195 
196 // DoWrtieSignalsPost(void)
197 void wDevice::DoWriteSignalsPost(void) {
198  // If there is an valid output-image, release kbus-mutex...
199  if(pOutputImage) kbus_release_io_image();
200  // ...and invalidate image.
201  pOutputImage=0;
202 }
203 
204 
205 //DoWriteSignal(int,int)
206 void wDevice::DoWriteSignal(int bit, bool value){
207  // Write one actor value, adressed by bit number (0 to 63);
208 
209  // Determine byte and bit addresse.
210  int byte = (bit) / 8;
211  bit = (bit) % 8;
212  // Report
213  FD_DHV("wDevice(" << mName << ")::DoWriteSignal(int): bit " << bit << " in byte " << byte);
214 
215  // Write value to output-image using bit-operations
216  // Write a "1", or...
217  if(value) pOutputImage[byte] |= (0x1 << (bit));
218  // ... write a "0"
219  else pOutputImage[byte] &= ~(0x1 << (bit));
220 }
221 
222 
223 } // namespace
224 
225 #endif // end wago-support

libFAUDES 2.24g --- 2014.09.15 --- c++ api documentaion by doxygen