blob: d97d33cde47fdae93661f77ab691b3395dcd6d2a [file] [log] [blame]
jerrymf1579332013-02-07 01:56:28 +00001/*----------------------------------------------------------------------------*/
2/* Copyright (c) FIRST 2008. All Rights Reserved. */
3/* Open Source Software - may be modified and shared by FRC teams. The code */
4/* must be accompanied by the FIRST BSD license file in $(WIND_BASE)/WPILib. */
5/*----------------------------------------------------------------------------*/
6
7#include "ADXL345_SPI.h"
8#include "DigitalInput.h"
9#include "DigitalOutput.h"
10#include "NetworkCommunication/UsageReporting.h"
11#include "SPI.h"
12
13const UINT8 ADXL345_SPI::kPowerCtlRegister;
14const UINT8 ADXL345_SPI::kDataFormatRegister;
15const UINT8 ADXL345_SPI::kDataRegister;
16const double ADXL345_SPI::kGsPerLSB;
17
18/**
19 * Constructor.
20 *
21 * @param clk The GPIO the clock signal is wired to.
22 * @param mosi The GPIO the MOSI (Master Out Slave In) signal is wired to.
23 * @param miso The GPIO the MISO (Master In Slave Out) signal is wired to.
24 * @param cs The GPIO the CS (Chip Select) signal is wired to.
25 * @param range The range (+ or -) that the accelerometer will measure.
26 */
27ADXL345_SPI::ADXL345_SPI(DigitalOutput &clk, DigitalOutput &mosi, DigitalInput &miso,
28 DigitalOutput &cs, DataFormat_Range range)
29 : m_clk (NULL)
30 , m_mosi (NULL)
31 , m_miso (NULL)
32 , m_cs (NULL)
33 , m_spi (NULL)
34{
35 Init(&clk, &mosi, &miso, &cs, range);
36}
37
38/**
39 * Constructor.
40 *
41 * @param clk The GPIO the clock signal is wired to.
42 * @param mosi The GPIO the MOSI (Master Out Slave In) signal is wired to.
43 * @param miso The GPIO the MISO (Master In Slave Out) signal is wired to.
44 * @param cs The GPIO the CS (Chip Select) signal is wired to.
45 * @param range The range (+ or -) that the accelerometer will measure.
46 */
47ADXL345_SPI::ADXL345_SPI(DigitalOutput *clk, DigitalOutput *mosi, DigitalInput *miso,
48 DigitalOutput *cs, DataFormat_Range range)
49 : m_clk (NULL)
50 , m_mosi (NULL)
51 , m_miso (NULL)
52 , m_cs (NULL)
53 , m_spi (NULL)
54{
55 Init(clk, mosi, miso, cs, range);
56}
57
58/**
59 * Constructor.
60 *
61 * @param moduleNumber The digital module with the sensor attached.
62 * @param clk The GPIO the clock signal is wired to.
63 * @param mosi The GPIO the MOSI (Master Out Slave In) signal is wired to.
64 * @param miso The GPIO the MISO (Master In Slave Out) signal is wired to.
65 * @param cs The GPIO the CS (Chip Select) signal is wired to.
66 * @param range The range (+ or -) that the accelerometer will measure.
67 */
68ADXL345_SPI::ADXL345_SPI(UINT8 moduleNumber, UINT32 clk, UINT32 mosi, UINT32 miso,
69 UINT32 cs, ADXL345_SPI::DataFormat_Range range)
70 : m_clk (NULL)
71 , m_mosi (NULL)
72 , m_miso (NULL)
73 , m_cs (NULL)
74 , m_spi (NULL)
75{
76 m_clk = new DigitalOutput(moduleNumber, clk);
77 m_mosi = new DigitalOutput(moduleNumber, mosi);
78 m_miso = new DigitalInput(moduleNumber, miso);
79 m_cs = new DigitalOutput(moduleNumber, cs);
80 Init(m_clk, m_mosi, m_miso, m_cs, range);
81}
82
83/**
84 * Internal common init function.
85 */
86void ADXL345_SPI::Init(DigitalOutput *clk, DigitalOutput *mosi, DigitalInput *miso,
87 DigitalOutput *cs, DataFormat_Range range)
88{
89 if (clk != NULL && mosi != NULL && miso != NULL && cs != NULL)
90 {
91 m_spi = new SPI(clk, mosi, miso);
92 m_spi->SetMSBFirst();
93 m_spi->SetSampleDataOnRising();
94 m_spi->SetSlaveSelect(cs, SPI::kChipSelect, false);
95 m_spi->SetClockActiveLow();
96 // 8-bit address and 8-bit data
97 m_spi->SetBitsPerWord(16);
98 m_spi->ApplyConfig();
99 m_spi->ClearReceivedData();
100
101 // Turn on the measurements
102 m_spi->Write((kPowerCtlRegister << 8) | kPowerCtl_Measure);
103 m_spi->Read();
104 // Specify the data format to read
105 m_spi->Write((kDataFormatRegister << 8) | kDataFormat_FullRes | (UINT8)(range & 0x03));
106 m_spi->Read();
107
108 // 8-bit address and 16-bit data
109 m_spi->SetBitsPerWord(24);
110 m_spi->ApplyConfig();
111
112 nUsageReporting::report(nUsageReporting::kResourceType_ADXL345, nUsageReporting::kADXL345_SPI);
113 }
114}
115
116/**
117 * Destructor.
118 */
119ADXL345_SPI::~ADXL345_SPI()
120{
121 delete m_spi;
122 m_spi = NULL;
123 delete m_cs;
124 m_cs = NULL;
125 delete m_miso;
126 m_miso = NULL;
127 delete m_mosi;
128 m_mosi = NULL;
129 delete m_clk;
130 m_clk = NULL;
131}
132
133/**
134 * Get the acceleration of one axis in Gs.
135 *
136 * @param axis The axis to read from.
137 * @return Acceleration of the ADXL345 in Gs.
138 */
139double ADXL345_SPI::GetAcceleration(ADXL345_SPI::Axes axis)
140{
141 INT16 rawAccel = 0;
142 if(m_spi)
143 {
144 m_spi->Write(((kAddress_Read | kAddress_MultiByte | kDataRegister) + (UINT8)axis) << 16);
145 rawAccel = (UINT16)m_spi->Read();
146
147 // Sensor is little endian... swap bytes
148 rawAccel = ((rawAccel >> 8) & 0xFF) | (rawAccel << 8);
149 }
150 return rawAccel * kGsPerLSB;
151}
152
153/**
154 * Get the acceleration of all axes in Gs.
155 *
156 * @return Acceleration measured on all axes of the ADXL345 in Gs.
157 */
158ADXL345_SPI::AllAxes ADXL345_SPI::GetAccelerations()
159{
160 AllAxes data = {0.0};
161 INT16 rawData[3];
162 if (m_spi)
163 {
164 SPI::tFrameMode mode;
165 bool activeLow;
166
167 // Backup original settings.
168 DigitalOutput *cs = m_spi->GetSlaveSelect(&mode, &activeLow);
169 UINT32 bitsPerWord = m_spi->GetBitsPerWord();
170
171 // Initialize the chip select to inactive.
172 cs->Set(activeLow);
173
174 // Control the chip select manually.
175 m_spi->SetSlaveSelect(NULL);
176 // 8-bit address
177 m_spi->SetBitsPerWord(8);
178 m_spi->ApplyConfig();
179
180 // Assert chip select.
181 cs->Set(!activeLow);
182
183 // Select the data address.
184 m_spi->Write(kAddress_Read | kAddress_MultiByte | kDataRegister);
185 m_spi->Read();
186
187 // 16-bits for each axis
188 m_spi->SetBitsPerWord(16);
189 m_spi->ApplyConfig();
190
191 for (INT32 i=0; i<3; i++)
192 {
193 // SPI Interface can't read enough data in a single transaction to read all axes at once.
194 rawData[i] = (UINT16)m_spi->Read(true);
195 // Sensor is little endian... swap bytes
196 rawData[i] = ((rawData[i] >> 8) & 0xFF) | (rawData[i] << 8);
197 }
198
199 // Deassert chip select.
200 cs->Set(activeLow);
201
202 // Restore original settings.
203 m_spi->SetSlaveSelect(cs, mode, activeLow);
204 m_spi->SetBitsPerWord(bitsPerWord);
205 m_spi->ApplyConfig();
206
207 data.XAxis = rawData[0] * kGsPerLSB;
208 data.YAxis = rawData[1] * kGsPerLSB;
209 data.ZAxis = rawData[2] * kGsPerLSB;
210 }
211 return data;
212}
213