Main Page | Class Hierarchy | Alphabetical List | Class List | File List | Class Members | Related Pages | Examples

ArVersalogicIO.cpp

00001 /*
00002 MobileRobots Advanced Robotics Interface for Applications (ARIA)
00003 Copyright (C) 2004, 2005 ActivMedia Robotics LLC
00004 Copyright (C) 2006, 2007 MobileRobots Inc.
00005 
00006      This program is free software; you can redistribute it and/or modify
00007      it under the terms of the GNU General Public License as published by
00008      the Free Software Foundation; either version 2 of the License, or
00009      (at your option) any later version.
00010 
00011      This program is distributed in the hope that it will be useful,
00012      but WITHOUT ANY WARRANTY; without even the implied warranty of
00013      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014      GNU General Public License for more details.
00015 
00016      You should have received a copy of the GNU General Public License
00017      along with this program; if not, write to the Free Software
00018      Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00019 
00020 If you wish to redistribute ARIA under different terms, contact 
00021 MobileRobots for information about a commercial version of ARIA at 
00022 robots@mobilerobots.com or 
00023 MobileRobots Inc, 19 Columbia Drive, Amherst, NH 03031; 800-639-9481
00024 */
00025 
00026 #include "ArExport.h"
00027 #include "ariaOSDef.h"
00028 #include "ArVersalogicIO.h"
00029 #include "ariaInternal.h"
00030 
00031 #include <sys/ioctl.h>
00032 #include <fcntl.h>
00033 
00034 /* These are taken from the amrio_dev.h file, which is part of the amrio module itself */
00035 
00036 #define AMRIO_MAJOR_NUM       (250)
00037 #define AMRIO_MODULE_NAME     ("amrio")
00038 
00039 #define ANALOG_GET_VALUE                _IOWR('v', 1, unsigned int)
00040 #define ANALOG_SET_PORT                 _IOWR('v', 2, unsigned char)
00041 #define DIGITAL_GET_NUM_BANKS           _IOWR('v', 3, int)
00042 #define DIGITAL_SET_BANK0               _IOWR('v', 4, unsigned char)
00043 #define DIGITAL_SET_BANK1               _IOWR('v', 5, unsigned char)
00044 #define DIGITAL_SET_BANK2               _IOWR('v', 6, unsigned char)
00045 #define DIGITAL_SET_BANK3               _IOWR('v', 7, unsigned char)
00046 #define DIGITAL_SET_BANK_DIR_IN         _IOWR('v', 8, int)
00047 #define DIGITAL_SET_BANK_DIR_OUT        _IOWR('v', 9, int)
00048 #define DIGITAL_GET_BANK0               _IOWR('v', 10, unsigned char)
00049 #define DIGITAL_GET_BANK1               _IOWR('v', 11, unsigned char)
00050 #define DIGITAL_GET_BANK2               _IOWR('v', 12, unsigned char)
00051 #define DIGITAL_GET_BANK3               _IOWR('v', 13, unsigned char)
00052 #define GET_SPECIAL_CONTROL_REGISTER    _IOWR('v', 14, unsigned char)
00053 
00054 ArMutex ArVersalogicIO::myMutex;
00055 
00065 AREXPORT ArVersalogicIO::ArVersalogicIO(const char * dev) :
00066   myDisconnectCB(this, &ArVersalogicIO::closeIO)
00067 {
00068   myNumBanks = 0;
00069 
00070   myDigitalBank0 = 0;
00071   myDigitalBank1 = 0;
00072   myDigitalBank2 = 0;
00073   myDigitalBank3 = 0;
00074 
00075   ArLog::log(ArLog::Terse, "ArVersalogicIO::ArVersalogicIO: opening device %s", dev);
00076   myFD = open(dev, O_RDWR);
00077 
00078   if (myFD == -1)
00079   {
00080     ArLog::log(ArLog::Terse, "ArVersalogicIO::ArVersalogicIO: open %s failed.  Disabling class", dev);
00081     myEnabled = false;
00082   }
00083   else
00084   {
00085     if(ioctl(myFD, DIGITAL_GET_NUM_BANKS, &myNumBanks))
00086       ArLog::log(ArLog::Terse, "ArVersalogicIO::ArVersalogicIO: failed to get the number of digital IO banks");
00087     // set the digital banks to inputs so as to not drive anything
00088     int i;
00089     for(i=0;i<myNumBanks;i++)
00090       setDigitalBankDirection(i, DIGITAL_INPUT);
00091     myEnabled = true;
00092 
00093     // check to see if the analog works
00094     double val;
00095     ArLog::log(ArLog::Verbose, "ArVersalogicIO::ArVersalogicIO: testing analog functionality");
00096     if ((ioctl(myFD, ANALOG_SET_PORT, 0) != 0) || (ioctl(myFD,ANALOG_GET_VALUE, &val) != 0))
00097     {
00098       ArLog::log(ArLog::Verbose, "ArVersalogicIO::ArVersalogicIO: analog conversion failed.  Disabling analog functionality");
00099       myAnalogEnabled = false;
00100     }
00101     else
00102     {
00103       ArLog::log(ArLog::Verbose, "ArVersalogicIO::ArVersalogicIO: analog conversion succeeded.");
00104       myAnalogEnabled = true;
00105     }
00106 
00107     Aria::addExitCallback(&myDisconnectCB);
00108     ArLog::log(ArLog::Terse, "ArVersalogicIO::ArVersalogicIO: device opened");
00109   }
00110 }
00111 
00114 AREXPORT ArVersalogicIO::~ArVersalogicIO(void)
00115 {
00116   if (myEnabled)
00117     closeIO();
00118 }
00119 
00122 AREXPORT bool ArVersalogicIO::closeIO(void)
00123 {
00124   myEnabled = false;
00125 
00126   if (close(myFD) == -1)
00127   {
00128     ArLog::log(ArLog::Terse, "ArVersalogicIO::~ArVersalogicIO: close failed on file descriptor!");
00129     return false;
00130   }
00131   else
00132   {
00133     ArLog::log(ArLog::Terse, "ArVersalogicIO::~ArVersalogicIO: closed device");
00134     return true;
00135   }
00136 }
00137 
00144 AREXPORT bool ArVersalogicIO::getAnalogValueRaw(int port, int *val)
00145 {
00146   if (!myEnabled || !myAnalogEnabled)
00147     return false;
00148 
00149   unsigned int tmp;
00150 
00151   if (ioctl(myFD, ANALOG_SET_PORT, port) != 0)
00152   {
00153     ArLog::log(ArLog::Terse, "ArVersalogicIO::getAnalogValueRaw: failed to set analog port %d", port);
00154     return false;
00155   }
00156 
00157   if (ioctl(myFD, ANALOG_GET_VALUE, &tmp) != 0)
00158   {
00159     ArLog::log(ArLog::Terse, "ArVersalogicIO::getAnalogValueRaw: failed to get analog port %d", port);
00160     return false;
00161   }
00162 
00163   *val = (int) tmp;
00164 
00165   return true;
00166 }
00167 
00175 AREXPORT bool ArVersalogicIO::getAnalogValue(int port, double *val)
00176 {
00177   int tmp;
00178 
00179   // the reading is 4096 units, for a range of 0-5V
00180   if (getAnalogValueRaw(port, &tmp)) {
00181     *val = 5 * (tmp/4096.0);
00182     return true;
00183   }
00184   else {
00185     return false;
00186   }
00187 }
00188 
00189 // this doesn't work, yet
00190 AREXPORT ArVersalogicIO::Direction ArVersalogicIO::getDigitalBankDirection(int bank)
00191 {
00192   return DIGITAL_OUTPUT;
00193 }
00194 
00195 AREXPORT bool ArVersalogicIO::setDigitalBankDirection(int bank, Direction dir)
00196 {
00197   if (!myEnabled)
00198     return false;
00199 
00200   if (dir == DIGITAL_INPUT)
00201   {
00202     if (ioctl(myFD, DIGITAL_SET_BANK_DIR_IN, bank) != 0)
00203       return false;
00204   }
00205   else if (dir == DIGITAL_OUTPUT)
00206   {
00207     if (ioctl(myFD, DIGITAL_SET_BANK_DIR_OUT, bank) != 0)
00208       return false;
00209   }
00210   else
00211   {
00212     ArLog::log(ArLog::Verbose, "ArVersalogicIO::setDigitalBankDirection: invalid argument for direction");
00213     return false;
00214   }
00215 
00216   return true;
00217 }
00218 
00224 AREXPORT bool ArVersalogicIO::getDigitalBankInputs(int bank, unsigned char *val)
00225 {
00226   if (!myEnabled)
00227     return false;
00228 
00229   if (bank < 0 || bank > myNumBanks - 1)
00230     return false;
00231 
00232   unsigned char tmp;
00233   switch (bank)
00234   {
00235     case 0:
00236       if (ioctl(myFD, DIGITAL_GET_BANK0, &tmp) != 0)
00237     return false;
00238       break;
00239     case 1:
00240       if (ioctl(myFD, DIGITAL_GET_BANK1, &tmp) != 0)
00241     return false;
00242       break;
00243     case 2:
00244       if (ioctl(myFD, DIGITAL_GET_BANK2, &tmp) != 0)
00245     return false;
00246       break;
00247     case 3:
00248       if (ioctl(myFD, DIGITAL_GET_BANK3, &tmp) != 0)
00249     return false;
00250       break;
00251     default:
00252       return false;
00253   }
00254 
00255   // bitwise negate it because the hardware calls a 'high' off
00256   *val = ~tmp;
00257   return true;
00258 }
00259 
00260 
00268 AREXPORT bool ArVersalogicIO::getDigitalBankOutputs(int bank, unsigned char *val)
00269 {
00270   if (!myEnabled)
00271     return false;
00272 
00273   if (bank < 0 || bank > myNumBanks - 1)
00274     return false;
00275 
00276   // should check for input vs. output
00277   switch (bank)
00278   {
00279     case 0:
00280       *val = myDigitalBank0;
00281       break;
00282     case 1:
00283       *val = myDigitalBank1;
00284       break;
00285     case 2:
00286       *val = myDigitalBank2;
00287       break;
00288     case 3:
00289       *val = myDigitalBank3;
00290       break;
00291   }
00292 
00293   return true;
00294 }
00295 
00304 AREXPORT bool ArVersalogicIO::setDigitalBankOutputs(int bank, unsigned char val)
00305 {
00306   if (!myEnabled)
00307     return false;
00308 
00309   if (bank < 0 || bank > myNumBanks - 1)
00310     return false;
00311 
00312   // bitwise negate val because the hardware calls a 'high' off
00313   switch (bank)
00314   {
00315     case 0:
00316       if (ioctl(myFD, DIGITAL_SET_BANK0, ~val) != 0)
00317     return false;
00318       myDigitalBank0 = val;
00319       break;
00320     case 1:
00321       if (ioctl(myFD, DIGITAL_SET_BANK1, ~val) != 0)
00322     return false;
00323       myDigitalBank1 = val;
00324       break;
00325     case 2:
00326       if (ioctl(myFD, DIGITAL_SET_BANK2, ~val) != 0)
00327     return false;
00328       myDigitalBank2 = val;
00329       break;
00330     case 3:
00331       if (ioctl(myFD, DIGITAL_SET_BANK3, ~val) != 0)
00332     return false;
00333       myDigitalBank3 = val;
00334       break;
00335     default:
00336       return false;
00337   }
00338 
00339   return true;
00340 }
00341 
00348 AREXPORT bool ArVersalogicIO::getSpecialControlRegister(unsigned char *val)
00349 {
00350   if (!myEnabled)
00351     return false;
00352 
00353   unsigned char tmp;
00354   if (ioctl(myFD, GET_SPECIAL_CONTROL_REGISTER, &tmp) != 0)
00355     return false;
00356 
00357   *val = tmp;
00358   return true;
00359 }

Generated on Tue Feb 20 10:51:42 2007 for Aria by  doxygen 1.4.0