iop_comedi.cpp

Go to the documentation of this file.
00001  
00002 /** @file iop_comedi.cpp Low-level access to physical device over comedi-driver*/
00003 
00004 /*
00005    FAU Discrete Event Systems Library (libfaudes)
00006 
00007    Copyright (C) 2008, Thomas Moor
00008    Exclusive copyright is granted to Klaus Schmidt
00009 
00010 */
00011 
00012 
00013 // include header
00014 #include "iop_comedi.h"
00015 
00016 namespace faudes {
00017 
00018 // only compile for comedi support
00019 #ifdef FAUDES_IODEVICE_COMEDI
00020 
00021 // std faudes, incl dummy
00022 FAUDES_TYPE_IMPLEMENTATION(ComediDevice,cDevice,sDevice)
00023 
00024 // autoregister
00025 AutoRegisterType<cDevice> gRtiRegisterComediDevice("ComediDevice");
00026 
00027 //constructor
00028 cDevice::cDevice(void) : sDevice(), mDev(0) {
00029   FD_DHV("cDevice(" << mName << ")::cDevice()");
00030   // have appropriate default label for token io
00031   mDefaultLabel = "ComediDevice";
00032   // invalidate images
00033   mpInputImage=NULL;
00034   mpOutputImage=NULL;
00035 }
00036 
00037 //deconstructor
00038 cDevice::~cDevice(void) {
00039   FD_DHV("cDevice(" << mName << ")::~cDevice()");
00040   Stop();
00041 }
00042 
00043 //DoWrite(rTr,rLabel,pContext)
00044 void cDevice::DoWritePreface(TokenWriter& rTw, const std::string& rLabel,  const Type* pContext) const {
00045   FD_DHV("cDevice("<<mName<<")::DoWritePreface()");
00046   //call base
00047   sDevice::DoWritePreface(rTw,"",pContext);
00048   // write mSystemFile
00049   Token sysf;
00050   sysf.SetBegin("DeviceFile");
00051   sysf.InsAttribute("value",mSystemFile);
00052   rTw << sysf;
00053 }
00054 
00055 
00056 //DoReadPreface(rTr,rLabel,pContext)
00057 void cDevice::DoReadPreface(TokenReader& rTr,const std::string& rLabel, const Type* pContext){
00058   FD_DHV("cDevice("<<mName<<")::DoReadPreface()");
00059   //call base
00060   sDevice::DoReadPreface(rTr,"",pContext);
00061 
00062   // sense and digest pre 2.16 format
00063   Token token;
00064   rTr.Peek(token);
00065   if(token.IsString()) {
00066     mSystemFile = rTr.ReadString();
00067     return;
00068   }
00069   
00070   // loop my members
00071   while(true) {
00072     Token token;
00073     rTr.Peek(token);
00074     // system file
00075     if(token.IsBegin("DeviceFile")) {
00076       rTr.ReadBegin("DeviceFile", token);
00077       mSystemFile=token.AttributeStringValue("value");
00078       rTr.ReadEnd("DeviceFile");
00079       continue;
00080     }
00081     // break on unknown
00082     break;
00083   }
00084 }
00085 
00086 
00087 // Start(void)
00088 void cDevice::Start(void) {
00089   //open comedi-device  
00090   if(mState!=Down) return;
00091   FD_DH("cDevice(" << mName << ")::Start(): open devices");
00092   mDev=comedi_open(mSystemFile.c_str());
00093 
00094   // throw exception if opening device failed
00095   if(!mDev) {
00096     std::stringstream errstr;
00097     errstr << "cannot open device /dev/comedi0 (inputs)";
00098     throw Exception("cDevice()::Start()", errstr.str(), 552);
00099   }
00100 
00101   // check some properties on input card
00102   for(int bit=0; bit<=mMaxBitAddress; bit++) {
00103  
00104     // map to subdevice/channel
00105     int sub=bit/32;
00106     int chan=bit%32;
00107 
00108 
00109     // dio config is not implemented for advantech boards (?)
00110     /*
00111     ComediInt32 res;
00112     // get info
00113     if(comedi_dio_get_config(mDev, sub, chan, &res) !=0) {
00114       std::stringstream errstr;
00115       errstr << "cannot open device " << mSystemFile << ": no digital io at bit address " << bit;
00116       throw Exception("cDevice()::Start()", errstr.str(), 552);
00117     }
00118     // is there a comedi input?
00119     if((!mInputPosEdgeIndexMap[bit].Empty()) || (!mInputNegEdgeIndexMap[bit].Empty())) {
00120       if(res != COMEDI_INPUT) {
00121         std::stringstream errstr;
00122         errstr << "cannot open device " << mSystemFile << ": no digital input at bit address " << bit;
00123         throw Exception("cDevice()::Start()", errstr.str(), 552);
00124       }
00125     }
00126     // is there a comedi output?
00127     if(!mOutputLevelIndexMap[bit].Empty()) {
00128       if(res != COMEDI_OUTPUT) {
00129         std::stringstream errstr;
00130         errstr << "cannot open device " << mSystemFile << ": no digital output at bit address " << bit;
00131         throw Exception("cDevice()::Start()", errstr.str(), 552);
00132       }
00133     }
00134     */
00135 
00136     // at least we can test whether we can read inputs
00137     lsampl_t val;
00138     if((!mInputPosEdgeIndexMap[bit].Empty()) || (!mInputNegEdgeIndexMap[bit].Empty())) {
00139       if(comedi_data_read(mDev,sub,chan,0,AREF_GROUND,&val)!=1) {
00140         std::stringstream errstr;
00141         errstr << "cannot open device " << mSystemFile << ": failed to test read from digital input at bit address " << bit;
00142         throw Exception("cDevice()::Start()", errstr.str(), 552);
00143       }
00144     }
00145 
00146   }
00147 
00148   // allocate image
00149   mComediSubdevs = (mMaxBitAddress / 32) + 1;
00150   if(mComediSubdevs<=0) mComediSubdevs=1;
00151   mpInputImage = new ComediInt32[mComediSubdevs];
00152   mpOutputImage = new ComediInt32[mComediSubdevs];
00153   // precompute mask
00154   for(int bit=0; bit<32; ++bit) mComediMask[bit] = 0x000000001U << bit;
00155   // call base
00156   sDevice::Start();
00157 }
00158 
00159 
00160 // Stop()
00161 void cDevice::Stop(void) {
00162   //close comedi-device
00163   if(mState != Up && mState != StartUp) return;
00164   FD_DHV("cDevice(" << mName << ")::Stop()");
00165   // call base
00166   sDevice::Stop();
00167   // close device
00168   comedi_close(mDev);
00169   mDev=0;
00170   // invalidate buffers
00171   delete mpInputImage;
00172   delete mpOutputImage;
00173   mpInputImage=NULL;
00174   mpOutputImage=NULL;
00175 }
00176 
00177 
00178 
00179 // Input Hook: we use a bit image (libFAUDES 2.23)
00180 bool cDevice::DoReadSignalsPre(void) {
00181   // read all bits to buffer
00182   for(int sub =0 ; sub<mComediSubdevs; ++sub) 
00183     comedi_dio_bitfield2(mDev, sub, 0, &mpInputImage[sub], 0);
00184   // never fail (i.e. ignore errors)
00185   return true;
00186 }
00187 
00188 
00189 // Input Hook: bit image does not need further attention
00190 void cDevice::DoReadSignalsPost(void) {
00191 }
00192 
00193 
00194 //ReadSignal(int)
00195 bool cDevice::DoReadSignal(int bit){
00196   // pre libFAUDES 2.23 bit-read (for reference)
00197   /*
00198   lsampl_t input=0;
00199   comedi_data_read(mDev,bit/32,bit%32,0,AREF_GROUND,&input);
00200   return (input!=0);
00201   */
00202   // read from buffer
00203   return (mpInputImage[bit/32] & mComediMask[bit%32]) != 0;
00204 }
00205 
00206 
00207 // Output Hook: we use bit-write
00208 bool cDevice::DoWriteSignalsPre(void) { return true; }
00209 void cDevice::DoWriteSignalsPost(void) {}
00210 
00211 
00212 //WriteSignal(int,int)
00213 void cDevice::DoWriteSignal(int bit, bool value){
00214   // write one actuator value, adressed by bit number (0 to 63);
00215   // ignore error
00216   lsampl_t output= (value ? 1 : 0);
00217   comedi_data_write(mDev,bit/32,bit%32,0,AREF_GROUND,output);
00218 }
00219 
00220 
00221 #endif // if comedi
00222 
00223 } // namespace
00224 
00225 

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