A compilation of some hardware sensors and their shared programming interfaces.

MAG3110.h

Committer:
mgottscho
Date:
2014-03-19
Revision:
1:15396cab58d1
Parent:
0:8d34cc2ff388

File content as of revision 1:15396cab58d1:

/* MAG3110.h
 * Tested with mbed board: FRDM-KL46Z
 * Author: Mark Gottscho
 * mgottscho@ucla.edu
 */

#ifndef MAG3110_H
#define MAG3110_H

#include "mbed.h"
#include "I2CSensor.h"
#include "PeriodicSensor.h"


/**
 * This class allows for easy control of an MAG3110 magnetometer IC.
 */
class MAG3110 : public I2CSensor, public PeriodicSensor {
    public:
        /**
         * Enumeration of allowed ADC sampling data rates.
         * The device does sample averages such that
         * the output data rate ODR = ADC_RATE / OVERSMPL_RATIO in all cases except for when ADC_RATE is 80 Hz (min). In this case,
         * there are multiple ODR for the same ADC_RATE, OVERSMPL_RATIO combination.
         * Note that there are non-unique combinations for the same ODR.
         */
        typedef enum {
            AHZ1280, //1280 Hz
            AHZ640,  //640 Hz
            AHZ320,  //320 Hz
            AHZ160,  //160 Hz
            AHZ80    //80 Hz
        } adc_smpl_rate_t;
        
        /**
         * Enumeration of allowed oversampling ratios.
         * The device does sample averages such that
         * the output data rate ODR = ADC_RATE / OVERSMPL_RATIO in all cases except for when ADC_RATE is 80 Hz (min). In this case,
         * there are multiple ODR for the same ADC_RATE, OVERSMPL_RATIO combination.
         * Note that there are non-unique combinations for the same ODR.
         */
        typedef enum {
            O16, //16:1
            O32, //32:1
            O64, //64:1
            O128 //128:1
        } oversmpl_ratio_t;
        
        /**
         * Enumeration of possible output data rates.
         * The device does sample averages such that
         * the output data rate ODR = ADC_RATE / OVERSMPL_RATIO in all cases except for when ADC_RATE is 80 Hz (min). In this case,
         * there are multiple ODR for the same ADC_RATE, OVERSMPL_RATIO combination.
         * Note that there are non-unique combinations for the same ODR.
         */
        typedef enum {
            HZ80,   //80 Hz
            HZ40,   //40 Hz
            HZ20,   //20 Hz
            HZ10,   //10 Hz
            HZ5,    //5 Hz
            HZ2_5,  //2.5 Hz
            HZ1_25, //1.25 Hz
            HZ0_63, //0.63 Hz
            HZ0_31, //0.31 Hz
            HZ0_16, //0.16 Hz
            HZ0_08  //0.08 Hz
        } smpl_rate_t;
    
        /**
         * @param sda the pin identifier for SDA I2C signal
         * @param scl the pin identifier for SCL I2C signal
         * @param i2c_addr the 8-bit I2C address for this device. Note that LSB is a don't care.
         */
        MAG3110(PinName sda, PinName scl, int i2c_addr);
        
        /**
         *
         */
        ~MAG3110();
        
        /**
         * Self-initialization to some nice preset. You must ensure the device is first deactivated using setActive().
         */
        void selfInit();
        
        //I2C-specific methods
        
        /**
         * Implements the pure virtual method of the parent I2CSensor class.
         * @returns the 8-bit device identifier.
         */
        uint8_t whoAmI();
        
        //Device-specific methods
        
        /**
         * @returns true if the device is active
         */
        bool isActive();
        
        /**
         * @param activate if true, enables the device, else disables it
         */
        void setActive(bool activate);
        
        /**
         * @returns the 8-bit system mode status
         */
        uint8_t getSystemMode();
        
        /**
         * @param rate optional pointer, if provided, will be set to the output sampling rate
         * @param ratio optional pointer, if provided, will be set to the oversampling ratio
         * @param adc_rate optional pointer, if provided, will be set to the ADC rate
         */
        void getOutputSamplingParameters(smpl_rate_t *rate, oversmpl_ratio_t *ratio, adc_smpl_rate_t *adc_rate);
        
        /**
         * @param rate the enumerated value corresponding to the output data sample rate to use
         * @param ratio the number of ADC samples per output sample (averaged)
         * @param adc_rate optional pointer, set to the resulting adc_rate used for the combination of rate and ratio
         * @returns true if the operation succeeded and the first two parameters were correct
         */
        bool setOutputSamplingParameters(smpl_rate_t rate, oversmpl_ratio_t ratio, adc_smpl_rate_t *adc_rate);
        
        /**
         * @returns the value in the data register
         */
        uint8_t getDataRegisterStatus();
        
        
        //Device-specific data sampling methods
        /**
         * @param sampleNow if true, queries the device for the sample and returns it. if false, gets the last queried value.
         * The latter is preferred if this object is set up to sample using interrupts.
         * @returns a 16-bit value representing the latest data sample for the X dimension, centered at 0.
         */
        int16_t getX(bool sampleNow);
        
        /**
         * @param sampleNow if true, queries the device for the sample and returns it. if false, gets the last queried value.
         * The latter is preferred if this object is set up to sample using interrupts.
         * @returns a 16-bit value representing the latest data sample for the Y dimension, centered at 0.
         */
        int16_t getY(bool sampleNow);
        
        /**
         * @param sampleNow if true, queries the device for the sample and returns it. if false, gets the last queried value.
         * The latter is preferred if this object is set up to sample using interrupts.
         * @returns a 16-bit value representing the latest data sample for the Z dimension, centered at 0.
         */
        int16_t getZ(bool sampleNow);
        
        /**
         * @param sampleNow if true, queries the device for the sample and returns it. if false, gets the last queried value.
         * The latter is preferred if this object is set up to sample using interrupts.
         * Returns the latest X data reading as a float in uT
         */
        float getFloatX(bool sampleNow);
        
        /**
         * @param sampleNow if true, queries the device for the sample and returns it. if false, gets the last queried value.
         * The latter is preferred if this object is set up to sample using interrupts.
         * Returns the latest Y data reading as a float in uT
         */
        float getFloatY(bool sampleNow);
        
        /**
         * @param sampleNow if true, queries the device for the sample and returns it. if false, gets the last queried value.
         * The latter is preferred if this object is set up to sample using interrupts.
         * Returns the latest Z data reading as a float in uT
         */
        float getFloatZ(bool sampleNow);

        /**
         * Get the die temperature. Note that the actual sensor range is only -40C to 125C, so not all outputs are valid.
         * @returns 8-bit die temperature data
         */
        int8_t getDieTemp();   
        
        /**
         * @returns the die temperature in deg Celsius. Note that the actual sensor range is only -40C to 125C, so not all possible outputs may be valid.
         */
        float getFloatDieTemp();
     
    private:
        /**
         * Interrupt service routine for fetching magnetometer data from the device.
         */
        virtual void __sample_data_ISR();
    
        ///////////////// CONSTANTS /////////////////////
        
        //Device register addresses
        static const uint8_t DR_STATUS =        0x00;
        static const uint8_t OUT_X_MSB =        0x01;
        static const uint8_t OUT_X_LSB =        0x02;
        static const uint8_t OUT_Y_MSB =        0x03;
        static const uint8_t OUT_Y_LSB =        0x04;
        static const uint8_t OUT_Z_MSB =        0x05;
        static const uint8_t OUT_Z_LSB =        0x06;
        static const uint8_t WHO_AM_I =         0x07;
        static const uint8_t SYSMOD =           0x08;
        static const uint8_t OFF_X_MSB =        0x09;
        static const uint8_t OFF_X_LSB =        0x0A;
        static const uint8_t OFF_Y_MSB =        0x0B;
        static const uint8_t OFF_Y_LSB =        0x0C;
        static const uint8_t OFF_Z_MSB =        0x0D;
        static const uint8_t OFF_Z_LSB =        0x0E;
        static const uint8_t DIE_TEMP =         0x0F;
        static const uint8_t CTRL_REG1 =        0x10;
        static const uint8_t CTRL_REG2 =        0x11; 
        
        //Register masks
        static const uint8_t DR_STATUS_ZYXOW_MASK =                 0x80; //b1000 0000
        static const uint8_t DR_STATUS_ZOW_MASK =                   0x40; //b0100 0000
        static const uint8_t DR_STATUS_YOW_MASK =                   0x20; //b0010 0000
        static const uint8_t DR_STATUS_XOW_MASK =                   0x10; //b0001 0000
        static const uint8_t DR_STATUS_ZYXDR_MASK =                 0x08; //b0000 1000
        static const uint8_t DR_STATUS_ZDR_MASK =                   0x04; //b0000 0100
        static const uint8_t DR_STATUS_YDR_MASK =                   0x02; //b0000 0010
        static const uint8_t DR_STATUS_XDR_MASK =                   0x01; //b0000 0001
        static const uint8_t SYSMOD_MASK =                          0x03; //b0000 0011
        static const uint8_t OFF_X_LSB_MASK =                       0xFE; //b1111 1110
        static const uint8_t OFF_Y_LSB_MASK =                       0xFE; //b1111 1110
        static const uint8_t OFF_Z_LSB_MASK =                       0xFE; //b1111 1110
        static const uint8_t CTRL_REG1_DR_MASK =                    0xB0; //b1110 0000
        static const uint8_t CTRL_REG1_OS_MASK =                    0x18; //b0001 1000
        static const uint8_t CTRL_REG1_FR_MASK =                    0x04; //b0000 0100
        static const uint8_t CTRL_REG1_TM_MASK =                    0x02; //b0000 0010
        static const uint8_t CTRL_REG1_AC_MASK =                    0x01; //b0000 0001
        static const uint8_t CTRL_REG2_AUTO_MRST_EN_MASK =          0x80; //b1000 0000
        static const uint8_t CTRL_REG2_RAW_MASK =                   0x20; //b0010 0000
        static const uint8_t CTRL_REG2_MAG_RST_MASK =               0x10; //b0001 0000
        
        //Mapping of data values
        static const float TEMP_DIV = 1; //deg Celsius/level. Note that 8-bit range is -128C to 127C, but the sensor can only do -40C to 125C.
        static const float DATA_CONVERSION = 0.10; //uT/level
        
        //////////////// VARIABLES /////////////////////
        //MAG3110 state ("cached" from the values actually on the device)
        volatile int16_t __x;
        volatile int16_t __y;
        volatile int16_t __z;
        
        bool __active;
        adc_smpl_rate_t __adc_rate;
        oversmpl_ratio_t __ratio;
        smpl_rate_t __rate;
};

#endif