1 //////////////////////////////////////////////////////////////////////////////////////
2 // The MIT License (MIT)
3 //
4 // Submit Date: 03/09/2015
5 // Author: Juan Jose Chong <juanjchong@gmail.com>
6 // Copyright (c) 2015 Juan Jose Chong
7 //
8 //////////////////////////////////////////////////////////////////////////////////////
9 // adis16448.cxx
10 //////////////////////////////////////////////////////////////////////////////////////
11 //
12 // This library runs on an Intel Edison and uses mraa to acquire data
13 // from an ADIS16448. This data is then scaled and printed onto the terminal.
14 //
15 // This software has been tested to connect to an ADIS16448 through a level shifter
16 // such as the TI TXB0104. The SPI lines (DIN, DOUT, SCLK, /CS) are all wired through
17 // the level shifter and the ADIS16448 is also being powered by the Intel Edison.
18 //
19 // Permission is hereby granted, free of charge, to any person obtaining
20 // a copy of this software and associated documentation files (the
21 // "Software"), to deal in the Software without restriction, including
22 // without limitation the rights to use, copy, modify, merge, publish,
23 // distribute, sublicense, and/or sell copies of the Software, and to
24 // permit persons to whom the Software is furnished to do so, subject to
25 // the following conditions:
26 //
27 // The above copyright notice and this permission notice shall be
28 // included in all copies or substantial portions of the Software.
29 //
30 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
31 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
32 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
33 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
34 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
35 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
36 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
37 //
38 //////////////////////////////////////////////////////////////////////////////////////
39 #include <iostream>
40 #include <string>
41 #include <stdexcept>
42 #include <unistd.h>
43 #include <stdlib.h>
44 #include <functional>
45 #include <string.h>
46 
47 #include "adis16448.h"
48 
49 using namespace upm;
50 
51 ////////////////////////////////////////////////////////////////////////////
52 // Constructor with configurable CS, DR, and RST
53 ////////////////////////////////////////////////////////////////////////////
54 // RST - Hardware reset pin
55 ////////////////////////////////////////////////////////////////////////////
ADIS16448(int bus,int rst)56 ADIS16448::ADIS16448(int bus, int rst)
57 {
58 // Configure I/O
59         //Initialize RST pin
60         if ( !(_rst = mraa_gpio_init(rst)) )
61           {
62             throw std::invalid_argument(std::string(__FUNCTION__) +
63                                         ": mraa_gpio_init() failed, invalid pin?");
64             return;
65           }
66 	mraa_gpio_dir(_rst, MRAA_GPIO_IN); //Set direction as INPUT
67 
68         // Configure SPI
69         if ( !(_spi = mraa_spi_init(bus)) )
70           {
71             throw std::invalid_argument(std::string(__FUNCTION__) +
72                                         ": mraa_spi_init() failed");
73             return;
74           }
75         configSPI();
76 }
77 
78 ////////////////////////////////////////////////////////////////////////////
79 // Destructor - Stops SPI and Closes all GPIO used. Reports an error if
80 // unable to close either properly.
81 ////////////////////////////////////////////////////////////////////////////
~ADIS16448()82 ADIS16448::~ADIS16448()
83 {
84 // Close SPI bus
85 	mraa_result_t error;
86 	error = mraa_spi_stop(_spi);
87 	if(error != MRAA_SUCCESS)
88 	{
89 		mraa_result_print(error);
90 	}
91 // Close GPIO
92 	error = mraa_gpio_close(_rst);
93 	if(error != MRAA_SUCCESS)
94 	{
95 		mraa_result_print(error);
96 	}
97 }
98 
99 ////////////////////////////////////////////////////////////////////////////
100 // Performs hardware reset by setting _RST pin low for 2 seconds.
101 ////////////////////////////////////////////////////////////////////////////
resetDUT()102 void ADIS16448::resetDUT()
103 {
104 	mraa_gpio_write(_rst, 0);
105 	usleep(100000); //Sleep for 100ms
106 	mraa_gpio_write(_rst, 1);
107 	usleep(1000000); //Sleep for 1s
108 }
109 
110 ////////////////////////////////////////////////////////////////////////////
111 // Sets SPI bit order, clock divider, and data mode. This function is useful
112 // when there are multiple SPI devices using different settings.
113 ////////////////////////////////////////////////////////////////////////////
configSPI()114 void ADIS16448::configSPI() {
115 	mraa_spi_frequency(_spi, 1000000); //Set SPI frequency to 1MHz
116 
117         if ( mraa_spi_mode(_spi, MRAA_SPI_MODE3) != MRAA_SUCCESS )
118           {
119             throw std::invalid_argument(std::string(__FUNCTION__) +
120                                         ": mraa_spi_mode() failed");
121             return;
122           }
123 	//Set # of bits per word
124 
125         if ( mraa_spi_bit_per_word(_spi, 16) != MRAA_SUCCESS )
126           {
127             throw std::invalid_argument(std::string(__FUNCTION__) +
128                                         ": mraa_spi_bit_per_word() failed");
129             return;
130           }
131 }
132 
133 ////////////////////////////////////////////////////////////////////////////////////////////
134 // Reads two bytes (one word) in two sequential registers over SPI
135 ////////////////////////////////////////////////////////////////////////////////////////////
136 // regAddr - register address from the lookup table in ADIS16448.h
137 // return - (int) signed 16 bit 2's complement number
138 ////////////////////////////////////////////////////////////////////////////////////////////
regRead(uint8_t regAddr)139 int16_t ADIS16448::regRead(uint8_t regAddr)
140 {
141 	configSPI(); //Set up SPI (useful when multiple SPI devices present on bus)
142 // Write register address to be read
143 	uint8_t buf[2]; //Allocate write buffer
144 	memset(buf, 0, sizeof(uint8_t)*2); //Initialize buffer and write 0s
145 	buf[1] = regAddr; //Write the user-requested register address to the buffer
146 	mraa_spi_write_buf(_spi, buf, 2); //Write the buffer onto the SPI port
147 
148 	usleep(20); //Delay to not violate read rate (210us)
149 
150 // Read data from register requested
151 	buf[1] = 0; //Clear contents of write buffer
152 	uint8_t* x = mraa_spi_write_buf(_spi, buf, 2); //Write 0x0000 to SPI and read data requested above
153 	int16_t _dataOut = (x[1] << 8) | (x[0] & 0xFF);; //Concatenate upper and lower bytes
154 
155 	usleep(20); //delay to not violate read rate (210us)
156 	return(_dataOut);
157 }
158 ////////////////////////////////////////////////////////////////////////////
159 // Writes one byte of data to the specified register over SPI
160 ////////////////////////////////////////////////////////////////////////////
161 // regAddr - register address from the lookup table
162 // regData - data to be written to the register
163 ////////////////////////////////////////////////////////////////////////////
regWrite(uint8_t regAddr,uint16_t regData)164 void ADIS16448::regWrite(uint8_t regAddr,uint16_t regData)
165 {
166 	configSPI();
167 // Separate the 16 bit command word into two bytes
168 	uint16_t addr = (((regAddr & 0x7F) | 0x80) << 8); //Check that the address is 7 bits, flip the sign bit
169 	uint16_t lowWord = (addr | (regData & 0xFF));
170 	uint16_t highWord = ((addr | 0x100) | ((regData >> 8) & 0xFF));
171 // Write the low byte to the SPI bus
172 	uint8_t lbuf[2]; //Allocate write buffer
173 	memset(lbuf, 0, sizeof(uint8_t)*2); //Fill low buffer with 0's
174 	lbuf[0] = (lowWord >> 8);
175 	lbuf[1] = (lowWord);
176 	mraa_spi_write_buf(_spi, lbuf, 2); //Write the buffer to the SPI port
177 
178 	usleep(20);
179 
180 // Write the high byte to the SPI bus
181 	uint8_t hbuf[2]; //Allocate write buffer
182 	memset(hbuf, 0, sizeof(uint8_t)*2); //Fill high buffer with 0's
183 	hbuf[0] = (highWord >> 8);
184 	hbuf[1] = (highWord);
185 	mraa_spi_write_buf(_spi, hbuf, 2); //Write the buffer to the SPI port
186 
187 	usleep(20);
188 
189 }
190 /////////////////////////////////////////////////////////////////////////////////////////
191 // Converts accelerometer data output from the sensorRead() function and returns
192 // acceleration in g's
193 /////////////////////////////////////////////////////////////////////////////////////////
194 // sensorData - data output from sensorRead()
195 // return - (float) signed/scaled accelerometer in G's
196 /////////////////////////////////////////////////////////////////////////////////////////
accelScale(int16_t sensorData)197 float ADIS16448::accelScale(int16_t sensorData)
198 {
199 	float finalData = sensorData * 0.000833; // multiply by accel sensitivity (250uG/LSB)
200 	return finalData;
201 }
202 /////////////////////////////////////////////////////////////////////////////////////////////
203 // Converts gyro data output from the sensorRead() function and returns gyro rate in deg/sec
204 /////////////////////////////////////////////////////////////////////////////////////////////
205 // sensorData - data output from sensorRead()
206 // return - (float) signed/scaled gyro in degrees/sec
207 /////////////////////////////////////////////////////////////////////////////////////////
gyroScale(int16_t sensorData)208 float ADIS16448::gyroScale(int16_t sensorData)
209 {
210 	float finalData = sensorData * 0.04; //multiply by gyro sensitivity (0.005 LSB/dps)
211 	return finalData;
212 }
213 /////////////////////////////////////////////////////////////////////////////////////////////
214 // Converts temperature data output from the sensorRead() function and returns temperature
215 // in degrees Celcius
216 /////////////////////////////////////////////////////////////////////////////////////////////
217 // sensorData - data output from sensorRead()
218 // return - (float) signed/scaled temperature in degrees Celcius
219 /////////////////////////////////////////////////////////////////////////////////////////
tempScale(int16_t sensorData)220 float ADIS16448::tempScale(int16_t sensorData)
221 {
222 	float finalData = (sensorData * 0.07386) + 31; //multiply by temperature scale and add 31 to equal 0x0000
223 	return finalData;
224 }
225 /////////////////////////////////////////////////////////////////////////////////////////////
226 // Converts barometer data output from sensorRead() function and returns pressure in bar
227 /////////////////////////////////////////////////////////////////////////////////////////////
228 // sensorData - data output from sensorRead()
229 // return - (float) signed/scaled temperature in degrees Celcius
230 /////////////////////////////////////////////////////////////////////////////////////////
pressureScale(int16_t sensorData)231 float ADIS16448::pressureScale(int16_t sensorData)
232 {
233 	float finalData = (sensorData * 0.02); //multiply by gyro sensitivity (0.005 LSB/dps)
234 	return finalData;
235 }
236 /////////////////////////////////////////////////////////////////////////////////////////////
237 // Converts magnetometer output from sensorRead() function and returns magnetic field
238 // reading in Gauss
239 /////////////////////////////////////////////////////////////////////////////////////////////
240 // sensorData - data output from sensorRead()
241 // return - (float) signed/scaled temperature in degrees Celcius
242 /////////////////////////////////////////////////////////////////////////////////////////
magnetometerScale(int16_t sensorData)243 float ADIS16448::magnetometerScale(int16_t sensorData)
244 {
245 	float finalData = (sensorData * 0.0001429); //multiply by sensor resolution (142.9uGa LSB/dps)
246 	return finalData;
247 }
248