Now you can download a copy of these docs so you can use them offline! Download now
ADXL345_SPI.cpp
1 /*----------------------------------------------------------------------------*/
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 
13 const uint8_t ADXL345_SPI::kPowerCtlRegister;
14 const uint8_t ADXL345_SPI::kDataFormatRegister;
15 const uint8_t ADXL345_SPI::kDataRegister;
16 constexpr double ADXL345_SPI::kGsPerLSB;
17 
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 
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 
68 ADXL345_SPI::ADXL345_SPI(uint8_t moduleNumber, uint32_t clk, uint32_t mosi, uint32_t miso,
69  uint32_t 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 
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_t)(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 
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 
139 double ADXL345_SPI::GetAcceleration(ADXL345_SPI::Axes axis)
140 {
141  int16_t rawAccel = 0;
142  if(m_spi)
143  {
144  m_spi->Write(((kAddress_Read | kAddress_MultiByte | kDataRegister) + (uint8_t)axis) << 16);
145  rawAccel = (uint16_t)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 
159 {
160  AllAxes data = {0.0};
161  int16_t 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_t 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_t 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_t)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 
virtual double GetAcceleration(Axes axis)
void Init(DigitalOutput *clk, DigitalOutput *mosi, DigitalInput *miso, DigitalOutput *cs, DataFormat_Range range)
Definition: ADXL345_SPI.cpp:86
ADXL345_SPI(DigitalOutput &clk, DigitalOutput &mosi, DigitalInput &miso, DigitalOutput &cs, DataFormat_Range range=kRange_2G)
Definition: ADXL345_SPI.cpp:27
uint32_t GetBitsPerWord()
Definition: SPI.cpp:187
void SetSlaveSelect(DigitalOutput *ss, tFrameMode mode=kChipSelect, bool activeLow=false)
Definition: SPI.cpp:263
void SetSampleDataOnRising()
Definition: SPI.cpp:247
virtual uint32_t Read(bool initiate=false)
Definition: SPI.cpp:466
virtual AllAxes GetAccelerations()
virtual void ClearReceivedData()
Definition: SPI.cpp:521
virtual void Write(uint32_t data)
Definition: SPI.cpp:434
void SetClockActiveLow()
Definition: SPI.cpp:344
Definition: SPI.h:24
void SetBitsPerWord(uint32_t bits)
Definition: SPI.cpp:176
virtual void ApplyConfig()
Definition: SPI.cpp:361
virtual ~ADXL345_SPI()
void Set(uint32_t value)
DigitalOutput * GetSlaveSelect(tFrameMode *mode=NULL, bool *activeLow=NULL)
Definition: SPI.cpp:327
void SetMSBFirst()
Definition: SPI.cpp:220

Generated on Sat Apr 26 2014 12:26:45 for WPILibC++ by doxygen 1.8.6