Home | History | Annotate | Download | only in adis16448
      1 //////////////////////////////////////////////////////////////////////////////////////
      2 // The MIT License (MIT)
      3 //
      4 // Submit Date: 03/09/2015
      5 // Author: Juan Jose Chong <juanjchong (at) 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 ////////////////////////////////////////////////////////////////////////////
     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 ////////////////////////////////////////////////////////////////////////////
     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 ////////////////////////////////////////////////////////////////////////////
    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 ////////////////////////////////////////////////////////////////////////////
    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 ////////////////////////////////////////////////////////////////////////////////////////////
    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 ////////////////////////////////////////////////////////////////////////////
    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 /////////////////////////////////////////////////////////////////////////////////////////
    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 /////////////////////////////////////////////////////////////////////////////////////////
    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 /////////////////////////////////////////////////////////////////////////////////////////
    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 /////////////////////////////////////////////////////////////////////////////////////////
    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 /////////////////////////////////////////////////////////////////////////////////////////
    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