BeeSTEM.H

Go to the documentation of this file.
00001 /*!@file Devices/BeeSTEM.H Interface to Rand Voorhies' BeeSTEM controller.*/
00002 
00003 // //////////////////////////////////////////////////////////////////// //
00004 // The iLab Neuromorphic Vision C++ Toolkit - Copyright (C) 2001 by the //
00005 // University of Southern California (USC) and the iLab at USC.         //
00006 // See http://iLab.usc.edu for information about this project.          //
00007 // //////////////////////////////////////////////////////////////////// //
00008 // Major portions of the iLab Neuromorphic Vision Toolkit are protected //
00009 // under the U.S. patent ``Computation of Intrinsic Perceptual Saliency //
00010 // in Visual Environments, and Applications'' by Christof Koch and      //
00011 // Laurent Itti, California Institute of Technology, 2001 (patent       //
00012 // pending; application number 09/912,225 filed July 23, 2001; see      //
00013 // http://pair.uspto.gov/cgi-bin/final/home.pl for current status).     //
00014 // //////////////////////////////////////////////////////////////////// //
00015 // This file is part of the iLab Neuromorphic Vision C++ Toolkit.       //
00016 //                                                                      //
00017 // The iLab Neuromorphic Vision C++ Toolkit is free software; you can   //
00018 // redistribute it and/or modify it under the terms of the GNU General  //
00019 // Public License as published by the Free Software Foundation; either  //
00020 // version 2 of the License, or (at your option) any later version.     //
00021 //                                                                      //
00022 // The iLab Neuromorphic Vision C++ Toolkit is distributed in the hope  //
00023 // that it will be useful, but WITHOUT ANY WARRANTY; without even the   //
00024 // implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR      //
00025 // PURPOSE.  See the GNU General Public License for more details.       //
00026 //                                                                      //
00027 // You should have received a copy of the GNU General Public License    //
00028 // along with the iLab Neuromorphic Vision C++ Toolkit; if not, write   //
00029 // to the Free Software Foundation, Inc., 59 Temple Place, Suite 330,   //
00030 // Boston, MA 02111-1307 USA.                                           //
00031 // //////////////////////////////////////////////////////////////////// //
00032 //
00033 // Primary maintainer for this file: Rand Voorhies <voorhies@usc.edu>
00034 // $HeadURL: svn://isvn.usc.edu/software/invt/trunk/saliency/src/Devices/BeeSTEM.H $
00035 
00036 #ifndef BEESTEM_H_DEFINED
00037 #define BEESTEM_H_DEFINED
00038 
00039 #include "Component/ModelComponent.H"
00040 #include "Component/ModelParam.H"
00041 #include "Devices/Serial.H"
00042 #include "Util/Types.H"
00043 #include "rutz/shared_ptr.h"
00044 
00045 #include <pthread.h>
00046 #include <stdarg.h>
00047 
00048 
00049 // Recursive template metaprogramming is used here to allow us to
00050 // define binary constants in the code, as we use these a lot in this
00051 // BeeSTEM program. See http://www.flipcode.com/cgi-bin/msg.cgi?
00052 // showThread=Tip-CPPCompileTimeBinConst&forum=totd&id=-1 for
00053 // additional info. NOTE: we have to be very careful not to have
00054 // leading zeros in our constants, otherwise they will be interpreted
00055 // as octal numbers by the compiler. The macro BIN below fixes that by
00056 // first forcing the interpretation of our constant as a double (which
00057 // may have leading zeros) and then casting it back to int and doing
00058 // the recursion. See Carlo Pescio's "Binary Constants Using Template
00059 // Metaprogramming," C/C++ Users Journal, February 1997 for a version
00060 // of that (which we here bugfixed for syntax).
00061 template<unsigned long int N> class binary
00062 { public: enum { bit = N % 10, value = bit + (((binary<N/10>::value)<<1)) }; };
00063 template <> class binary<0> { public: enum { bit = 0, value = 0 }; };
00064 #define BIN(N) (((byte(binary<(unsigned long int)(N##.0)>::value))))
00065 
00066 //! BeeSTEM event types
00067 /*!
00068   This is the EventType that is passed to an external event handler on an event trigger.
00069   For simplicity, COMPASS_HEADING_EVENT through MOTOR_E_CURR_EVENT are used internally to
00070   address our data buffer. If any events need to be added later, please just make sure to
00071   pay attention to how the data buffer size is initialized in the private section of this
00072   class, and how it is addressed in the accessor functions as well as the run loop.
00073 */
00074 enum BeeSTEMEventType {
00075   COMPASS_HEADING_EVENT  = 0,
00076   COMPASS_PITCH_EVENT    = 1,
00077   COMPASS_ROLL_EVENT     = 2,
00078   ACCEL_X_EVENT          = 3,
00079   ACCEL_Y_EVENT          = 4,
00080   INT_PRESS_EVENT        = 5,
00081   EXT_PRESS_EVENT        = 6,
00082   TEMP1_EVENT            = 7,
00083   TEMP2_EVENT            = 8,
00084   TEMP3_EVENT            = 9,
00085   DIG_IN_EVENT           = 10,
00086   ADC_IN_EVENT           = 11,
00087   MOTOR_A_CURR_EVENT     = 12,
00088   MOTOR_B_CURR_EVENT     = 13,
00089   MOTOR_C_CURR_EVENT     = 14,
00090   MOTOR_D_CURR_EVENT     = 15,
00091   MOTOR_E_CURR_EVENT     = 16,
00092   ECHO_REPLY_EVENT       = 17,
00093   RESET_EVENT            = 18,
00094   SW_OVERFLOW_EVENT      = 19,
00095   FRAMING_ERR_EVENT      = 20,
00096   OVR_ERR_EVENT          = 21,
00097   HMR3300_LOST_EVENT     = 22,
00098   ACCEL_LOST_EVENT       = 23,
00099   TEMP1_LOST_EVENT       = 24,
00100   TEMP2_LOST_EVENT       = 25,
00101   HMR_LEVELED_EVENT      = 26,
00102   ESTOP_EVENT            = 27,
00103   UNRECOGNIZED_EVENT     = 28,
00104   BAD_IN_CMD_SEQ_EVENT   = 29,
00105   BAD_OUT_CMD_SEQ_EVENT  = 30,
00106   RESET_ACK_EVENT        = 31,
00107   DATA_EVENT             = 32,
00108   HMR3300_CAL_EVENT      = 33,
00109   NO_EVENT               = 34
00110 };
00111 #define DATATOP MOTOR_E_CURR_EVENT
00112 
00113 //! BeeSTEM Reporting Masks
00114 /*! Quick and dirty way to turn on reporting for a feature or the
00115   BeeSTEM. Simply pass one of these masks to setReporting with
00116   a bool to turn reporting for that feature on or off */
00117 enum BeeSTEMReportingMask {
00118   HMR3300       = BIN(01100010),
00119   ACCELEROMETER = BIN(01100000),
00120   INT_PRESS     = BIN(01101010),
00121   EXT_PRESS     = BIN(01101100),
00122   TEMP1         = BIN(01100100),
00123   TEMP2         = BIN(01100110),
00124   TEMP3         = BIN(01101000),
00125   DIG_IN        = BIN(01101110),
00126   ADC_IN        = BIN(01110000),
00127   MOTOR_CURR    = BIN(01110010)
00128 };
00129 
00130 
00131 //! BeoChip event listener
00132 /*! The BeoChipListener gets called each time an event is received
00133   from the BeoChip. The BeoChipEventType is passed to the listener,
00134   allowing the user to determine the type of event received and to
00135   then interpret the event data also passed to the listener. By
00136   default, there is no listener, and users can just asynchronously
00137   query the BeoChip for its current internal state. If those queries
00138   come in too slowly, however, they may miss some events (e.g., a
00139   briefly pressed key). So, production code should define a derived
00140   class for BeoChipListener and register it with the BeoChip object,
00141   so that it will take action as soon as an event is received. */
00142 class BeeSTEMListener {
00143 public:
00144   //! Destructor
00145   virtual ~BeeSTEMListener();
00146 
00147   //! An event was received
00148   /*! This function will be called by the BeeSTEM once you have
00149     registered your BeeSTEMListener derivative with the BeeSTEM using
00150     BeeSTEM::setListener(). Beware that the call to event() will be
00151     from a thread running in the BeeSTEM and thus will operate in
00152     parallel with your main thread and main loop. See test-BeeSTEM.C
00153     for an example of how to synchronize a main loop with these
00154     asynchronous event calls. The following data will be passed along
00155     with the event type:
00156     <PRE>
00157     _type______________________dat1__________________dat2_
00158     COMPASS_HEADING             heading               0
00159     COMPASS_PITCH               pitch                 0
00160     COMPASS_ROLL                roll                  0
00161     ACCEL_X                     x-acceleration        0
00162     ACCEL_Y                     y-acceleration        0
00163     INT_PRESS                   internal pressure     0
00164     EXT_PRESS                   external pressure     0
00165     TEMP1                       temperature 1         0
00166     TEMP2                       temperature 2         0
00167     TEMP3                       temperature 3         0
00168     DIG_IN                      digital input byte    0
00169     ADC_IN                      spare adc value       0
00170     MOTOR_CURR                  current               motor number
00171     All Others                  0                     0
00172     </PRE>
00173   */
00174   virtual void event(const BeeSTEMEventType t, const unsigned char dat1,
00175                      const unsigned char dat2) = 0;
00176 };
00177 
00178 //! BeeSTEM.H Interface to Rand Voorhies' BeeSTEM device
00179 /*! Hardware interface Class. Contains interfaces to display to an
00180 LCD, a 2D Accelerometer/Compass, and extra high speed accelerometer,
00181 3 temperature sensors, internal & external pressure sensors, 8 digital I/O pins
00182 an ADC pin, 5 PWM outputs, and motor current readings. */
00183 class BeeSTEM : public ModelComponent
00184 {
00185 public:
00186   // ############################################################
00187   /*! @name Constructors, destructors and debugging */
00188   //@{
00189 
00190   //! Default constructor. See ModelComponent.H
00191   BeeSTEM(OptionManager& mgr,
00192           const std::string& descrName = "BeeSTEM",
00193           const std::string& tagName = "BeeSTEM",
00194           const char* dev = "/dev/ttyS0");
00195 
00196   //! Destructor
00197   ~BeeSTEM();
00198 
00199   //! Install a callback (listener) for BeeSTEM events
00200   /*! This callback will be called with the corresponding
00201     BeeSTEMEventType each time an event is received from the BeeSTEM. */
00202   void setListener(rutz::shared_ptr<BeeSTEMListener>& listener);
00203 
00204   //! Send an echo request
00205   /*! The BeeSTEM should reply with an Echo_Reply event if it is alive */
00206   bool echoRequest();
00207 
00208   //! Turn debug mode on/off
00209   /*! When in debug mode, the BeeSTEM sends an EchoReply for each command
00210     it receives. */
00211   bool debugMode(const bool on);
00212 
00213   //! Reset the BeeSTEM
00214   bool resetChip();
00215 
00216   //! Toggle the calibration mode of the HMR3300
00217   bool toggleCalibrateHMR3300();
00218 
00219   //! Level the HMR3300
00220   bool levelHMR3300();
00221 
00222   //@}
00223 
00224   // ############################################################
00225   /*! @name LCD functions */
00226   //@{
00227 
00228   //! Print some text
00229   /*! syntax is the same as printf(). Returns true on success. */
00230   bool lcdPrintf(const char *fmt, ...)
00231     // NOTE: this __attribute__ tells gcc that it should issue
00232     // printf-style warnings when compiling calls to
00233     // BeeSTEM::lcdPrintf(), treating the 2nd argument (fmt) as the
00234     // format string, and the 3rd and subsequent arguments as the
00235     // printf-style parameters (SUBNOTE: because this is a member
00236     // function, there is a hidden 'this' parameter that counts as arg
00237     // 1, so the listed arguments are counted starting from 2)
00238     __attribute__((format(__printf__, 2, 3)));
00239     ;
00240 
00241   //! Clear LCD screen
00242   bool lcdClear();
00243   //@}
00244 
00245   // ############################################################
00246   /*! @name PWM control functions */
00247   //@{
00248 
00249   //! Sets the speed of a motor. -100 is full reverse, and +100 is full forwards
00250   /*! Note that the [-100..+100] is only a percentage of the maximum possible
00251       PWM allowed by the BeeSTEM. See MotorControl.H of the BeeSTEM code for more. */
00252   bool setMotor(const int motor, signed char speed);
00253 
00254   //! Gets the current current consumption of a motor
00255   /*! Note that motor current monitoring must be explicitely turned on*/
00256   float getMotorCurrent(const int motor) const;
00257 
00258   //@}
00259 
00260   // ############################################################
00261   /*! @name Data aquisition and reporting functions */
00262   //! Tell the BeeSTEM to start (or stop) sending a data type over the serial connection.
00263   /*!   This function takes in a BeeSTEMReportingMask and a bool, and tells the BeeSTEM
00264       to start or stop monitoring and reporting a resource designated by the mask.
00265         Note that turning on too many reporting features may significantly slow down
00266       the device, so please only turn on what's needed.*/
00267   bool setReporting(const BeeSTEMReportingMask t, const bool on);
00268 
00269 
00270   //@}
00271 
00272   // ############################################################
00273   /*! @name Data Acquisition Functions */
00274   //@{
00275 
00276   //! Get Compass Heading
00277   byte getCompassHeading();
00278 
00279   //! Get Compass Pitch
00280   byte getCompassPitch();
00281 
00282   //! Get Compass Pitch
00283   byte getCompassRoll();
00284 
00285   //! Get High Speed Accelerometer X
00286   byte getAccelX();
00287 
00288   //! Get High Speed Accelerometer Y
00289   byte getAccelY();
00290 
00291   //! Get Internal Pressure
00292   byte getIntPress();
00293 
00294   //! Get External Pressure
00295   byte getExtPress();
00296 
00297   //! Get Temperature Zone 1
00298   byte getTemp1();
00299 
00300   //! Get Temperature Zone 2
00301   byte getTemp2();
00302 
00303   //! Get Temperature Zone 3
00304   byte getTemp3();
00305 
00306   //! Get current raw Analog value from the spare ADC pin
00307   byte getSpareADC();
00308 
00309   //! Get the current from a motor
00310   byte getMotorCurr(byte whichone);
00311 
00312   //! Get the value of a single digital input pin
00313   bool getDigitalIn(const int whichone);
00314 
00315   //! Get the value of all 8 digital input pins as a whole byte
00316   byte getDigitalIn();
00317 
00318 
00319   // ############################################################
00320   /*! @name Digital output function */
00321   //@{
00322 
00323   //! Turn a given digital output on/off
00324   /*! Valid range for outnum is [0..7] */
00325   bool setDigitalOut(const int outnum, const bool on);
00326 
00327   //@}
00328 
00329   //! This is our main running thread - don't call directly
00330   /*! Should have been protected, but is not because of pthread hack. */
00331   void run();
00332 
00333   //! send a byte to the BeeSTEM
00334   /*! You should never have to use this, use the other functions
00335     instead.  This function is made public just for testing the chip's
00336     robustness against a flood of random junk hitting it... See
00337     test-BeeSTEM.C */
00338   bool writeByte(const byte val, const bool uselock = true);
00339 
00340 protected:
00341   //! open the port and get started
00342   void start1();
00343 
00344   //! close the port and get stopped
00345   void stop2();
00346 
00347 private:
00348 
00349   nub::soft_ref<Serial> itsSerial;
00350   bool itsKeepgoing;
00351 
00352   rutz::shared_ptr<BeeSTEMListener> itsListener;
00353 
00354   pthread_t runner;
00355   pthread_mutex_t lock, serlock;
00356 
00357   //!Buffer for incoming data from the BeeSTEM
00358   byte* itsData;
00359 
00360   int itsCurrentMotorValues[5];
00361 
00362 };
00363 
00364 #endif
00365 
00366 // ######################################################################
00367 /* So things look consistent in everyone's emacs... */
00368 /* Local Variables: */
00369 /* indent-tabs-mode: nil */
00370 /* End: */
Generated on Sun May 8 08:40:37 2011 for iLab Neuromorphic Vision Toolkit by  doxygen 1.6.3