Mindstorms 3rd Party ROBOTC Drivers RobotC
[Home] [Download] [Submit a bug/suggestion] [ROBOTC Forums] [Blog] [Support this project]

hitechnic-sensormux.h

Go to the documentation of this file.
00001 /*!@addtogroup HiTechnic
00002  * @{
00003  * @defgroup htsmux Sensor MUX
00004  * HiTechnic Sensor MUX Sensor
00005  * @{
00006  */
00007 
00008 /*
00009  * $Id: hitechnic-sensormux.h 133 2013-03-10 15:15:38Z xander $
00010  */
00011 
00012 #ifndef __HTSMUX_H__
00013 #define __HTSMUX_H__
00014 /** \file hitechnic-sensormux.h
00015  * \brief Commonly used functions used by drivers.
00016  *
00017  * common.h provides a number of frequently used functions that are useful for writing
00018  * drivers.
00019  * License: You may use this code as you wish, provided you give credit where its due.
00020  *
00021  * THIS CODE WILL ONLY WORK WITH ROBOTC VERSION 3.59 AND HIGHER. 
00022 
00023  *
00024  * Changelog:
00025  * - 0.1: Initial release, split off from common.h
00026  *
00027  * \author Xander Soldaat (xander_at_botbench.com)
00028  * \date 18 January 2011
00029  * \version 0.1
00030  */
00031 
00032 #pragma systemFile
00033 
00034 #ifndef __COMMON_H__
00035 #include "common.h"
00036 #endif
00037 
00038 #define __HTSMUX_SUPPORT__
00039 
00040 #ifndef SPORT
00041 #define SPORT(X)  (X / 4)         /*!< Convert tMUXSensor to sensor port number */
00042 #endif
00043 
00044 #ifndef MPORT
00045 #define MPORT(X)  (X % 4)         /*!< Convert tMUXSensor to MUX port number */
00046 #endif
00047 
00048 #ifndef MAX_ARR_SIZE
00049 /**
00050  * Maximum buffer size for byte_array, can be overridden in your own program.
00051  * It's 17 bytes big because the max I2C buffer size is 16, plus 1 byte to denote
00052  * packet length.
00053  */
00054 #define MAX_ARR_SIZE 17
00055 #endif
00056 
00057 #define HTSMUX_I2C_ADDR         0x10  /*!< HTSMUX I2C device address */
00058 #define HTSMUX_COMMAND          0x20  /*!< Command register */
00059 #define HTSMUX_STATUS           0x21  /*!< Status register */
00060 
00061 // Registers
00062 #define HTSMUX_MODE             0x00  /*!< Sensor mode register */
00063 #define HTSMUX_TYPE             0x01  /*!< Sensor type register */
00064 #define HTSMUX_I2C_COUNT        0x02  /*!< I2C byte count register */
00065 #define HTSMUX_I2C_DADDR        0x03  /*!< I2C device address register */
00066 #define HTSMUX_I2C_MADDR        0x04  /*!< I2C memory address register */
00067 #define HTSMUX_CH_OFFSET        0x22  /*!< Channel register offset */
00068 #define HTSMUX_CH_ENTRY_SIZE    0x05  /*!< Number of registers per sensor channel */
00069 
00070 #define HTSMUX_ANALOG           0x36  /*!< Analogue upper 8 bits register */
00071 #define HTSMUX_AN_ENTRY_SIZE    0x02  /*!< Number of registers per analogue channel */
00072 
00073 #define HTSMUX_I2C_BUF          0x40  /*!< I2C buffer register offset */
00074 #define HTSMUX_BF_ENTRY_SIZE    0x10  /*!< Number of registers per buffer */
00075 
00076 
00077 // Command fields
00078 #define HTSMUX_CMD_HALT         0x00  /*!< Halt multiplexer command */
00079 #define HTSMUX_CMD_AUTODETECT   0x01  /*!< Start auto-detect function command */
00080 #define HTSMUX_CMD_RUN          0x02  /*!< Start normal multiplexer operation command */
00081 
00082 // Status
00083 #define HTSMUX_STAT_NORMAL      0x00  /*!< Nothing going on, everything's fine */
00084 #define HTSMUX_STAT_BATT        0x01  /*!< No battery voltage detected status */
00085 #define HTSMUX_STAT_BUSY        0x02  /*!< Auto-dected in progress status */
00086 #define HTSMUX_STAT_HALT        0x04  /*!< Multiplexer is halted status */
00087 #define HTSMUX_STAT_ERROR       0x08  /*!< Command error detected status */
00088 #define HTSMUX_STAT_NOTHING     0xFF  /*!< Status hasn't really been set yet */
00089 
00090 // Channel modes
00091 #define HTSMUX_CHAN_NONE        0x00  /*!< Nothing configured - analogue sensor */
00092 #define HTSMUX_CHAN_I2C         0x01  /*!< I2C channel present channel mode */
00093 #define HTSMUX_CHAN_9V          0x02  /*!< Enable 9v supply on analogue pin channel mode */
00094 #define HTSMUX_CHAN_DIG0_HIGH   0x04  /*!< Drive pin 0 high channel mode */
00095 #define HTSMUX_CHAN_DIG1_HIGH   0x08  /*!< Drive pin 1 high channel mode */
00096 #define HTSMUX_CHAN_I2C_SLOW    0x10  /*!< Set slow I2C rate channel mode */
00097 
00098 
00099 /*!< Sensor types as detected by SMUX */
00100 typedef enum {
00101   HTSMUXAnalogue = 0x00,
00102   HTSMUXLegoUS = 0x01,
00103   HTSMUXCompass = 0x02,
00104   HTSMUXColor = 0x03,
00105   HTSMUXAccel = 0x04,
00106   HTSMUXIRSeeker = 0x05,
00107   HTSMUXProto = 0x06,
00108   HTSMUXColorNew = 0x07,
00109   HTSMUXAngle = 0x08,
00110   HTSMUXIRSeekerNew = 0x09,
00111   HTSMUXSensorCustom = 0x0E,
00112   HTSMUXSensorNone = 0x0F
00113 } HTSMUXSensorType;
00114 
00115 /*!< Sensor and SMUX port combinations */
00116 typedef enum {
00117   msensor_S1_1 = 0,
00118   msensor_S1_2 = 1,
00119   msensor_S1_3 = 2,
00120   msensor_S1_4 = 3,
00121   msensor_S2_1 = 4,
00122   msensor_S2_2 = 5,
00123   msensor_S2_3 = 6,
00124   msensor_S2_4 = 7,
00125   msensor_S3_1 = 8,
00126   msensor_S3_2 = 9,
00127   msensor_S3_3 = 10,
00128   msensor_S3_4 = 11,
00129   msensor_S4_1 = 12,
00130   msensor_S4_2 = 13,
00131   msensor_S4_3 = 14,
00132   msensor_S4_4 = 15
00133 } tMUXSensor;
00134 
00135 
00136 /*!< array to hold SMUX status info */
00137 ubyte HTSMUXstatus[4] = {HTSMUX_STAT_NOTHING, HTSMUX_STAT_NOTHING, HTSMUX_STAT_NOTHING, HTSMUX_STAT_NOTHING};
00138 
00139 /*!< Array for holding sensor types */
00140 HTSMUXSensorType HTSMUXSensorTypes[16] = {HTSMUXSensorNone, HTSMUXSensorNone, HTSMUXSensorNone, HTSMUXSensorNone,
00141                                           HTSMUXSensorNone, HTSMUXSensorNone, HTSMUXSensorNone, HTSMUXSensorNone,
00142                                           HTSMUXSensorNone, HTSMUXSensorNone, HTSMUXSensorNone, HTSMUXSensorNone,
00143                                           HTSMUXSensorNone, HTSMUXSensorNone, HTSMUXSensorNone, HTSMUXSensorNone};
00144 
00145 tByteArray HTSMUX_I2CRequest;     /*!< Array to hold I2C command data */
00146 tByteArray HTSMUX_I2CReply;       /*!< Array to hold I2C reply data */
00147 
00148 typedef ubyte tConfigParams[4];   /*!< Array to hold SMUX channel info */
00149 
00150 tConfigParams Analogue_config = {HTSMUX_CHAN_NONE, 0, 0, 0}; /*!< Array to hold SMUX config data for sensor */
00151 
00152 byte HTSMUXreadStatus(tSensors link);
00153 HTSMUXSensorType HTSMUXreadSensorType(tMUXSensor muxsensor);
00154 bool HTSMUXsendCommand(tSensors link, byte command);
00155 bool HTSMUXreadPort(tMUXSensor muxsensor, tByteArray &result, int numbytes, int offset = 0);
00156 bool HTSMUXsetMode(tMUXSensor muxsensor, byte mode);
00157 bool HTSMUXsetAnalogueActive(tMUXSensor muxsensor);
00158 bool HTSMUXsetAnalogueInactive(tMUXSensor muxsensor);
00159 int HTSMUXreadAnalogue(tMUXSensor muxsensor);
00160 bool HTSMUXreadPowerStatus(tSensors link);
00161 bool HTSMUXconfigChannel(tMUXSensor muxsensor, tConfigParams &configparams);
00162 
00163 
00164 /**
00165  * Read the status of the SMUX
00166  *
00167  * The status byte is made up of the following bits:\n
00168  *
00169  * | D7 | D6 | D4 | D3 | D2 | D1 | D1 |\n
00170  * - D1 - HTSMUX_STAT_BATT: No battery voltage detected
00171  * - D2 - HTSMUX_STAT_BUSY: Auto-dected in progress status
00172  * - D3 - HTSMUX_STAT_HALT: Multiplexer is halted
00173  * - D4 - HTSMUX_STAT_ERROR: Command error detected
00174  * @param link the SMUX port number
00175  * @return the status byte
00176  */
00177 byte HTSMUXreadStatus(tSensors link) {
00178   memset(HTSMUX_I2CRequest, 0, sizeof(tByteArray));
00179 
00180   HTSMUX_I2CRequest[0] = 2;               // Message size
00181   HTSMUX_I2CRequest[1] = HTSMUX_I2C_ADDR; // I2C Address
00182   HTSMUX_I2CRequest[2] = HTSMUX_STATUS;
00183 
00184   if (!writeI2C(link, HTSMUX_I2CRequest, HTSMUX_I2CReply, 1))
00185     return -1;
00186 
00187   return HTSMUX_I2CReply[0];
00188 }
00189 
00190 
00191 /**
00192  * Get the sensor type attached to specified SMUX port
00193  * @param muxsensor the SMUX sensor port number
00194  * @return the status byte
00195  */
00196 HTSMUXSensorType HTSMUXreadSensorType(tMUXSensor muxsensor) {
00197   return HTSMUXSensorTypes[muxsensor];
00198 }
00199 
00200 
00201 /**
00202  * Set the mode of a SMUX channel.
00203  *
00204  * Mode can be one or more of the following:
00205  * - HTSMUX_CHAN_I2C
00206  * - HTSMUX_CHAN_9V
00207  * - HTSMUX_CHAN_DIG0_HIGH
00208  * - HTSMUX_CHAN_DIG1_HIGH
00209  * - HTSMUX_CHAN_I2C_SLOW
00210  * @param muxsensor the SMUX sensor port number
00211  * @param mode the mode to set the channel to
00212  * @return true if no error occured, false if it did
00213  */
00214 bool HTSMUXsetMode(tMUXSensor muxsensor, byte mode) {
00215   tSensors link = (tSensors)SPORT(muxsensor);
00216   byte channel = MPORT(muxsensor);
00217 
00218   // If we're in the middle of a scan, abort this call
00219   if (HTSMUXstatus[link] == HTSMUX_STAT_BUSY) {
00220     return false;
00221   } else if (HTSMUXstatus[link] != HTSMUX_STAT_HALT) {
00222           // Always make sure the SMUX is in the halted state
00223           if (!HTSMUXsendCommand(link, HTSMUX_CMD_HALT))
00224             return false;
00225           wait1Msec(50);
00226         }
00227 
00228   memset(HTSMUX_I2CRequest, 0, sizeof(tByteArray));
00229 
00230   HTSMUX_I2CRequest[0] = 3;               // Message size
00231   HTSMUX_I2CRequest[1] = HTSMUX_I2C_ADDR; // I2C Address
00232   HTSMUX_I2CRequest[2] = HTSMUX_CH_OFFSET + HTSMUX_MODE + (HTSMUX_CH_ENTRY_SIZE * channel);
00233   HTSMUX_I2CRequest[3] = mode;
00234 
00235   return writeI2C(link, HTSMUX_I2CRequest);
00236 }
00237 
00238 
00239 /**
00240  * Set the mode of an analogue channel to Active (turn the light on)
00241  * @param muxsensor the SMUX sensor port number
00242  * @return true if no error occured, false if it did
00243  */
00244 bool HTSMUXsetAnalogueActive(tMUXSensor muxsensor) {
00245   if (HTSMUXSensorTypes[muxsensor] != HTSMUXSensorCustom)
00246     HTSMUXconfigChannel(muxsensor, Analogue_config);
00247 
00248   if (!HTSMUXsetMode(muxsensor, HTSMUX_CHAN_DIG0_HIGH))
00249     return false;
00250 
00251   return HTSMUXsendCommand((tSensors)SPORT(muxsensor), HTSMUX_CMD_RUN);
00252 }
00253 
00254 
00255 /**
00256  * Set the mode of an analogue channel to Inactive (turn the light off)
00257  * @param muxsensor the SMUX sensor port number
00258  * @return true if no error occured, false if it did
00259  */
00260 bool HTSMUXsetAnalogueInactive(tMUXSensor muxsensor) {
00261   if (HTSMUXSensorTypes[muxsensor] != HTSMUXSensorCustom)
00262     HTSMUXconfigChannel(muxsensor, Analogue_config);
00263 
00264   if (!HTSMUXsetMode(muxsensor, 0))
00265     return false;
00266 
00267   return HTSMUXsendCommand((tSensors)SPORT(muxsensor), HTSMUX_CMD_RUN);
00268 }
00269 
00270 
00271 /**
00272  * Send a command to the SMUX.
00273  *
00274  * command can be one of the following:
00275  * - HTSMUX_CMD_HALT
00276  * - HTSMUX_CMD_AUTODETECT
00277  * - HTSMUX_CMD_RUN
00278  *
00279  * in progress.
00280  * @param link the SMUX port number
00281  * @param command the command to be sent to the SMUX
00282  * @return true if no error occured, false if it did
00283  */
00284 bool HTSMUXsendCommand(tSensors link, byte command) {
00285   memset(HTSMUX_I2CRequest, 0, sizeof(tByteArray));
00286 
00287   HTSMUX_I2CRequest[0] = 3;               // Message size
00288   HTSMUX_I2CRequest[1] = HTSMUX_I2C_ADDR; // I2C Address
00289   HTSMUX_I2CRequest[2] = HTSMUX_COMMAND;
00290   HTSMUX_I2CRequest[3] = command;
00291 
00292   switch(command) {
00293     case HTSMUX_CMD_HALT:
00294         HTSMUXstatus[link] = HTSMUX_STAT_HALT;
00295         break;
00296     case HTSMUX_CMD_AUTODETECT:
00297         HTSMUXstatus[link] = HTSMUX_STAT_BUSY;
00298         break;
00299     case HTSMUX_CMD_RUN:
00300         HTSMUXstatus[link] = HTSMUX_STAT_NORMAL;
00301         break;
00302   }
00303 
00304   return writeI2C(link, HTSMUX_I2CRequest);
00305 }
00306 
00307 
00308 /**
00309  * Read the value returned by the sensor attached the SMUX. This function
00310  * is for I2C sensors.
00311  * @param muxsensor the SMUX sensor port number
00312  * @param result array to hold values returned from SMUX
00313  * @param numbytes the size of the I2C reply
00314  * @param offset the offset used to start reading from
00315  * @return true if no error occured, false if it did
00316  */
00317 bool HTSMUXreadPort(tMUXSensor muxsensor, tByteArray &result, int numbytes, int offset) {
00318   tSensors link = (tSensors)SPORT(muxsensor);
00319   byte channel = MPORT(muxsensor);
00320 
00321   memset(HTSMUX_I2CRequest, 0, sizeof(tByteArray));
00322   if (HTSMUXstatus[link] != HTSMUX_STAT_NORMAL)
00323     HTSMUXsendCommand(link, HTSMUX_CMD_RUN);
00324 
00325   HTSMUX_I2CRequest[0] = 2;                 // Message size
00326   HTSMUX_I2CRequest[1] = HTSMUX_I2C_ADDR;   // I2C Address
00327   HTSMUX_I2CRequest[2] = HTSMUX_I2C_BUF + (HTSMUX_BF_ENTRY_SIZE * channel) + offset;
00328 
00329   if (!writeI2C(link, HTSMUX_I2CRequest, HTSMUX_I2CReply, numbytes))
00330     return false;
00331 
00332   memcpy(result, HTSMUX_I2CReply, sizeof(tByteArray));
00333 
00334   return true;
00335 }
00336 
00337 
00338 /**
00339  * Read the value returned by the sensor attached the SMUX. This function
00340  * is for analogue sensors.
00341  * @param muxsensor the SMUX sensor port number
00342  * @return the value of the sensor or -1 if an error occurred.
00343  */
00344 int HTSMUXreadAnalogue(tMUXSensor muxsensor) {
00345   tSensors link = (tSensors)SPORT(muxsensor);
00346   byte channel = MPORT(muxsensor);
00347 
00348   memset(HTSMUX_I2CRequest, 0, sizeof(tByteArray));
00349   if (HTSMUXstatus[link] != HTSMUX_STAT_NORMAL)
00350     HTSMUXsendCommand(link, HTSMUX_CMD_RUN);
00351 
00352   if (HTSMUXSensorTypes[muxsensor] != HTSMUXSensorCustom)
00353     HTSMUXconfigChannel(muxsensor, Analogue_config);
00354 
00355   HTSMUX_I2CRequest[0] = 2;               // Message size
00356   HTSMUX_I2CRequest[1] = HTSMUX_I2C_ADDR;   // I2C Address
00357   HTSMUX_I2CRequest[2] = HTSMUX_ANALOG + (HTSMUX_AN_ENTRY_SIZE * channel);
00358 
00359   if (!writeI2C(link, HTSMUX_I2CRequest, HTSMUX_I2CReply, 2))
00360     return -1;
00361 
00362   return ((int)HTSMUX_I2CReply[0] * 4) + HTSMUX_I2CReply[1];
00363 }
00364 
00365 
00366 /**
00367  * Return a string for the sensor type.
00368  *
00369  * @param muxsensor the SMUX sensor port number
00370  * @param sensorName the string to hold the name of the sensor.
00371  */
00372 void HTSMUXsensorTypeToString(HTSMUXSensorType muxsensor, string &sensorName) {
00373   switch(muxsensor) {
00374     case HTSMUXAnalogue:    sensorName = "Analogue";      break;
00375     case HTSMUXLegoUS:      sensorName = "Ultra Sonic";   break;
00376     case HTSMUXCompass:     sensorName = "Compass";       break;
00377     case HTSMUXColor:       sensorName = "Colour";        break;
00378     case HTSMUXColorNew:    sensorName = "Colour New";    break;
00379     case HTSMUXAccel:       sensorName = "Accel";         break;
00380     case HTSMUXIRSeeker:    sensorName = "IR Seeker";     break;
00381     case HTSMUXProto:       sensorName = "Proto Board";   break;
00382     case HTSMUXIRSeekerNew: sensorName = "IR Seeker V2";  break;
00383     case HTSMUXSensorNone : sensorName = "No sensor";     break;
00384   }
00385 }
00386 
00387 
00388 /**
00389  * Check if the battery is low
00390  *
00391  * @param link the SMUX port number
00392  * @return true if there is a power source problem
00393  */
00394 bool HTSMUXreadPowerStatus(tSensors link) {
00395   if ((HTSMUXreadStatus(link) & HTSMUX_STAT_BATT) == HTSMUX_STAT_BATT)
00396     return true;
00397   else
00398     return false;
00399 }
00400 
00401 
00402 /**
00403  * Configure the SMUX for a specific sensor.\n
00404  * The parameters are as follows:
00405  * - Channel mode
00406  * - Number of bytes to request from attached sensor
00407  * - I2C address
00408  * - I2C register to request
00409  *
00410  * @param muxsensor the SMUX sensor port number
00411  * @param configparams parameters for the channel's configuration
00412  * @return true if there is a power source problem
00413  */
00414 bool HTSMUXconfigChannel(tMUXSensor muxsensor, tConfigParams &configparams) {
00415   memset(HTSMUX_I2CRequest, 0, sizeof(tByteArray));
00416 
00417   // Always make sure the SMUX is in the halted state
00418   if (!HTSMUXsendCommand((tSensors)SPORT(muxsensor), HTSMUX_CMD_HALT))
00419     return false;
00420         wait1Msec(50);
00421 
00422   HTSMUX_I2CRequest[0] = 7;               // Message size
00423   HTSMUX_I2CRequest[1] = HTSMUX_I2C_ADDR; // I2C Address
00424   HTSMUX_I2CRequest[2] = HTSMUX_CH_OFFSET + (HTSMUX_CH_ENTRY_SIZE * MPORT(muxsensor));
00425   HTSMUX_I2CRequest[3] = configparams[0];
00426   HTSMUX_I2CRequest[4] = 0x00;
00427   HTSMUX_I2CRequest[5] = configparams[1];
00428   HTSMUX_I2CRequest[6] = configparams[2];
00429   HTSMUX_I2CRequest[7] = configparams[3];
00430 
00431   if (!writeI2C((tSensors)SPORT(muxsensor), HTSMUX_I2CRequest))
00432     return false;
00433 
00434   HTSMUXSensorTypes[muxsensor] = HTSMUXSensorCustom;
00435   return HTSMUXsendCommand((tSensors)SPORT(muxsensor), HTSMUX_CMD_RUN);
00436 }
00437 
00438 
00439 #endif // __HTSMUX_H__
00440 /*
00441  * $Id: hitechnic-sensormux.h 133 2013-03-10 15:15:38Z xander $
00442  */
00443 /* @} */
00444 /* @} */