001    /*----------------------------------------------------------------------------*/
002    /* Copyright (c) FIRST 2008-2012. All Rights Reserved.                        */
003    /* Open Source Software - may be modified and shared by FRC teams. The code   */
004    /* must be accompanied by the FIRST BSD license file in the root directory of */
005    /* the project.                                                               */
006    /*----------------------------------------------------------------------------*/
007    package edu.wpi.first.wpilibj;
008    
009    import edu.wpi.first.wpilibj.communication.UsageReporting;
010    
011    /**
012     *
013     * @author dtjones
014     */
015    public class ADXL345_I2C extends SensorBase {
016    
017        private static final byte kAddress = 0x3A;
018        private static final byte kPowerCtlRegister = 0x2D;
019        private static final byte kDataFormatRegister = 0x31;
020        private static final byte kDataRegister = 0x32;
021        private static final double kGsPerLSB = 0.00390625;
022        private static final byte kPowerCtl_Link = 0x20, kPowerCtl_AutoSleep = 0x10, kPowerCtl_Measure = 0x08, kPowerCtl_Sleep = 0x04;
023        private static final byte kDataFormat_SelfTest = (byte) 0x80, kDataFormat_SPI = 0x40, kDataFormat_IntInvert = 0x20, kDataFormat_FullRes = 0x08, kDataFormat_Justify = 0x04;
024    
025        public static class DataFormat_Range {
026    
027            /**
028             * The integer value representing this enumeration
029             */
030            public final byte value;
031            static final byte k2G_val = 0x00;
032            static final byte k4G_val = 0x01;
033            static final byte k8G_val = 0x02;
034            static final byte k16G_val = 0x03;
035            public static final DataFormat_Range k2G = new DataFormat_Range(k2G_val);
036            public static final DataFormat_Range k4G = new DataFormat_Range(k4G_val);
037            public static final DataFormat_Range k8G = new DataFormat_Range(k8G_val);
038            public static final DataFormat_Range k16G = new DataFormat_Range(k16G_val);
039    
040            private DataFormat_Range(byte value) {
041                this.value = value;
042            }
043        }
044    
045        public static class Axes {
046    
047            /**
048             * The integer value representing this enumeration
049             */
050            public final byte value;
051            static final byte kX_val = 0x00;
052            static final byte kY_val = 0x02;
053            static final byte kZ_val = 0x04;
054            public static final Axes kX = new Axes(kX_val);
055            public static final Axes kY = new Axes(kY_val);
056            public static final Axes kZ = new Axes(kZ_val);
057    
058            private Axes(byte value) {
059                this.value = value;
060            }
061        }
062    
063        public static class AllAxes {
064    
065            public double XAxis;
066            public double YAxis;
067            public double ZAxis;
068        }
069        private I2C m_i2c;
070    
071        /**
072         * Constructor.
073         *
074         * @param module The slot of the digital module that the sensor is plugged into.
075         * @param range The range (+ or -) that the accelerometer will measure.
076         */
077        public ADXL345_I2C(int moduleNumber, DataFormat_Range range) {
078            DigitalModule module = DigitalModule.getInstance(moduleNumber);
079            m_i2c = module.getI2C(kAddress);
080    
081            // Turn on the measurements
082            m_i2c.write(kPowerCtlRegister, kPowerCtl_Measure);
083            // Specify the data format to read
084            m_i2c.write(kDataFormatRegister, kDataFormat_FullRes | range.value);
085    
086            UsageReporting.report(UsageReporting.kResourceType_ADXL345, UsageReporting.kADXL345_I2C, moduleNumber-1);
087        }
088    
089        /**
090         * Get the acceleration of one axis in Gs.
091         *
092         * @param axis The axis to read from.
093         * @return Acceleration of the ADXL345 in Gs.
094         */
095        public double getAcceleration(Axes axis) {
096            byte[] rawAccel = new byte[2];
097            m_i2c.read(kDataRegister + axis.value, rawAccel.length, rawAccel);
098    
099            // Sensor is little endian... swap bytes
100            return accelFromBytes(rawAccel[0], rawAccel[1]);
101        }
102    
103        private double accelFromBytes(byte first, byte second) {
104            short tempLow = (short) (first & 0xff);
105            short tempHigh = (short) ((second << 8) & 0xff00);
106            return (tempLow | tempHigh) * kGsPerLSB;
107        }
108    
109        /**
110         * Get the acceleration of all axes in Gs.
111         *
112         * @return Acceleration measured on all axes of the ADXL345 in Gs.
113         */
114        public AllAxes getAccelerations() {
115            AllAxes data = new AllAxes();
116            byte[] rawData = new byte[6];
117            m_i2c.read(kDataRegister, rawData.length, rawData);
118    
119            // Sensor is little endian... swap bytes
120            data.XAxis = accelFromBytes(rawData[0], rawData[1]);
121            data.YAxis = accelFromBytes(rawData[2], rawData[3]);
122            data.ZAxis = accelFromBytes(rawData[4], rawData[5]);
123            return data;
124        }
125        
126        // TODO: Support LiveWindow
127    }