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

libFAUDES 2.32b --- 2024.03.01 --- c++ api documentaion by doxygen