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/*----------------------------------------------------------------------------*/
007package edu.wpi.first.wpilibj;
008
009import edu.wpi.first.wpilibj.communication.FRCNetworkCommunicationsLibrary.tInstances;
010import edu.wpi.first.wpilibj.communication.FRCNetworkCommunicationsLibrary.tResourceType;
011import edu.wpi.first.wpilibj.communication.UsageReporting;
012import edu.wpi.first.wpilibj.interfaces.Accelerometer;
013import edu.wpi.first.wpilibj.livewindow.LiveWindow;
014import edu.wpi.first.wpilibj.livewindow.LiveWindowSendable;
015import edu.wpi.first.wpilibj.tables.ITable;
016
017/**
018 *
019 * @author dtjones
020 */
021public class ADXL345_I2C extends SensorBase implements Accelerometer, LiveWindowSendable {
022
023        private static final byte kAddress = 0x1D;
024        private static final byte kPowerCtlRegister = 0x2D;
025        private static final byte kDataFormatRegister = 0x31;
026        private static final byte kDataRegister = 0x32;
027        private static final double kGsPerLSB = 0.00390625;
028        private static final byte kPowerCtl_Link = 0x20, kPowerCtl_AutoSleep = 0x10, kPowerCtl_Measure = 0x08, kPowerCtl_Sleep = 0x04;
029        private static final byte kDataFormat_SelfTest = (byte) 0x80, kDataFormat_SPI = 0x40, kDataFormat_IntInvert = 0x20, kDataFormat_FullRes = 0x08, kDataFormat_Justify = 0x04;
030
031        public static class Axes {
032
033                /**
034                 * The integer value representing this enumeration
035                 */
036                public final byte value;
037                static final byte kX_val = 0x00;
038                static final byte kY_val = 0x02;
039                static final byte kZ_val = 0x04;
040                public static final Axes kX = new Axes(kX_val);
041                public static final Axes kY = new Axes(kY_val);
042                public static final Axes kZ = new Axes(kZ_val);
043
044                private Axes(byte value) {
045                        this.value = value;
046                }
047        }
048
049        public static class AllAxes {
050
051                public double XAxis;
052                public double YAxis;
053                public double ZAxis;
054        }
055        private I2C m_i2c;
056
057        /**
058         * Constructor.
059         * @param port The I2C port the accelerometer is attached to
060         * @param range The range (+ or -) that the accelerometer will measure.
061         */
062        public ADXL345_I2C(I2C.Port port, Range range) {
063                m_i2c = new I2C(port, kAddress);
064
065                // Turn on the measurements
066                m_i2c.write(kPowerCtlRegister, kPowerCtl_Measure);
067
068                setRange(range);
069
070                UsageReporting.report(tResourceType.kResourceType_ADXL345, tInstances.kADXL345_I2C);
071                LiveWindow.addSensor("ADXL345_I2C", port.getValue(), this);
072        }
073
074        /** {inheritdoc} */
075        @Override
076        public void setRange(Range range) {
077                byte value = 0;
078
079                switch(range) {
080                case k2G:
081                        value = 0;
082                        break;
083                case k4G:
084                        value = 1;
085                        break;
086                case k8G:
087                        value = 2;
088                        break;
089                case k16G:
090                        value = 3;
091                        break;
092                }
093
094                // Specify the data format to read
095                m_i2c.write(kDataFormatRegister, kDataFormat_FullRes | value);
096        }
097
098        /** {@inheritDoc} */
099        @Override
100        public double getX() {
101                return getAcceleration(Axes.kX);
102        }
103
104        /** {@inheritDoc} */
105        @Override
106        public double getY() {
107                return getAcceleration(Axes.kY);
108        }
109
110        /** {@inheritDoc} */
111        @Override
112        public double getZ() {
113                return getAcceleration(Axes.kZ);
114        }
115
116        /**
117         * Get the acceleration of one axis in Gs.
118         *
119         * @param axis The axis to read from.
120         * @return Acceleration of the ADXL345 in Gs.
121         */
122        public double getAcceleration(Axes axis) {
123                byte[] rawAccel = new byte[2];
124                m_i2c.read(kDataRegister + axis.value, rawAccel.length, rawAccel);
125
126                // Sensor is little endian... swap bytes
127                return accelFromBytes(rawAccel[0], rawAccel[1]);
128        }
129
130        private double accelFromBytes(byte first, byte second) {
131                short tempLow = (short) (first & 0xff);
132                short tempHigh = (short) ((second << 8) & 0xff00);
133                return (tempLow | tempHigh) * kGsPerLSB;
134        }
135
136        /**
137         * Get the acceleration of all axes in Gs.
138         *
139         * @return An object containing the acceleration measured on each axis of the ADXL345 in Gs.
140         */
141        public AllAxes getAccelerations() {
142                AllAxes data = new AllAxes();
143                byte[] rawData = new byte[6];
144                m_i2c.read(kDataRegister, rawData.length, rawData);
145
146                // Sensor is little endian... swap bytes
147                data.XAxis = accelFromBytes(rawData[0], rawData[1]);
148                data.YAxis = accelFromBytes(rawData[2], rawData[3]);
149                data.ZAxis = accelFromBytes(rawData[4], rawData[5]);
150                return data;
151        }
152
153        public String getSmartDashboardType(){
154                return "3AxisAccelerometer";
155        }
156
157        private ITable m_table;
158
159        /** {@inheritDoc} */
160        public void initTable(ITable subtable) {
161                m_table = subtable;
162                updateTable();
163        }
164
165        /** {@inheritDoc} */
166        public void updateTable() {
167                if (m_table != null) {
168                        m_table.putNumber("X", getX());
169                        m_table.putNumber("Y", getY());
170                        m_table.putNumber("Z", getZ());
171                }
172        }
173
174        /** {@inheritDoc} */
175        public ITable getTable(){
176                return m_table;
177        }
178
179        public void startLiveWindowMode() {}
180        public void stopLiveWindowMode() {}
181}