LIS3DH through spi

Dependents:   SimpleBLE-ObCP_ENSMM_V2019_Test_BLE SimpleBLE-ObCP_ENSMM_V2019_Test_BLE_S Roller_catcher_tests_fonctionnel SimpleBLE-ObCp_test-BLE_envoi ... more

LIS3DH.cpp

Committer:
franzle
Date:
2017-03-15
Revision:
0:ce2396b1c9a1

File content as of revision 0:ce2396b1c9a1:

/*
 * mbed library program
 *  LIS3DH MEMS motion sensor: 3-axis "nano" accelerometer, made by STMicroelectronics
 *      http://www.st-japan.co.jp/web/jp/catalog/sense_power/FM89/SC444/PF250725
 *
 * Copyright (c) 2014,'15 Kenji Arai / JH1PJL
 *  http://www.page.sannet.ne.jp/kenjia/index.html
 *  http://mbed.org/users/kenjiArai/
 *      Created: July      14th, 2014
 *      Revised: December  12th, 2015
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
 * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE
 * AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
 * DAMAGES OR OTHER  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */

#include "LIS3DH.h"

LIS3DH::LIS3DH (PinName p_mosi, PinName p_miso, PinName p_sclk, PinName p_ssel, uint8_t data_rate, uint8_t fullscale) : _spi(p_mosi, p_miso, p_sclk), _cs(p_ssel)
{
    _spi.frequency(4000000);
    init (data_rate, fullscale);
}

LIS3DH::LIS3DH (PinName p_mosi, PinName p_miso, PinName p_sclk, PinName p_ssel) : _spi(p_mosi, p_miso, p_sclk), _cs(p_ssel)
{
    _spi.frequency(4000000);
    init (LIS3DH_DR_NR_LP_50HZ, LIS3DH_FS_8G);
}

void LIS3DH::readRegs(uint8_t addr, uint8_t * data, int len) {
    _cs = 0 ;
    for (int i = 0 ; i < len ; i++ ) {    
       _spi.write((addr+i)|0x80) ;  // specify address to read
       data[i] = _spi.write((addr+i)|0x80) ; 
    } 
    _spi.write(0x00) ; // to terminate read mode
    _cs = 1 ;
}

void LIS3DH::writeRegs(uint8_t * data, int len) {
   _cs = 0 ;
   for (int i = 0 ; i < len ; i++ ) {
      _spi.write(data[i]) ;
   }
   _cs = 1 ;
}

void LIS3DH::write_reg(uint8_t addr, uint8_t data8)
{
    uint8_t data[2] ;
    data[0] = addr ;
    data[1] = data8 ;
    writeRegs(data, 2) ;
}

uint8_t LIS3DH::read_reg(uint8_t addr)
{
    uint8_t data[1] ;    
    readRegs(addr, data, 1) ;
    return( data[0] ) ;
}

void LIS3DH::write16(uint8_t addr, uint16_t data16)
{
    uint8_t data[3] ;
    data[0] = addr ;
    data[1] = (data16 >> 8) & 0xFF ;
    data[2] = data16 & 0xFF ;
    writeRegs(data, 3) ;
}

uint16_t LIS3DH::read16(uint8_t addr)
{
    uint8_t data[2] ;
    uint16_t value = 0 ;
    readRegs(addr, data, 2) ;
    value = (data[0] << 8) | data[1] ;
    return( value ) ;
}


void LIS3DH::init(uint8_t data_rate, uint8_t fullscale)
{
    _spi.frequency(4000000);
    dt[0] = read_reg(LIS3DH_WHO_AM_I);
    if (dt[0] == I_AM_LIS3DH) {
        acc_ready = 1;
    } else {
        acc_ready = 0;
        return;     // acc chip is NOT on I2C line then terminate
    }
    
    write_reg(LIS3DH_CTRL_REG1, (0x07|(data_rate << 4))); //  Reg.1
    write_reg(LIS3DH_CTRL_REG4, (0x08|(fullscale << 4))); //  Reg.4
    
    switch (fullscale) {
        case LIS3DH_FS_2G:
            fs_factor = LIS3DH_SENSITIVITY_2G;
            break;
        case LIS3DH_FS_4G:
            fs_factor = LIS3DH_SENSITIVITY_4G;
            break;
        case LIS3DH_FS_8G:
            fs_factor = LIS3DH_SENSITIVITY_8G;
            break;
        case LIS3DH_FS_16G:
            fs_factor = LIS3DH_SENSITIVITY_16G;
            break;
        default:
            ;
    }
}

void LIS3DH::read_mg_data(float *dt_usr)
{
    uint8_t data[6];

    if (acc_ready == 0) {
        dt_usr[0] = 0;
        dt_usr[1] = 0;
        dt_usr[2] = 0;
        return;
    }
    readRegs(LIS3DH_OUT_X_L, data, 6); 
    // change data type
#if OLD_REV // Fixed bugs -> (1) unit is not mg but g (2) shift right 4bit = /16
    dt_usr[0] = float(short((data[1] << 8) | data[0])) * fs_factor / 15;
    dt_usr[1] = float(short((data[3] << 8) | data[2])) * fs_factor / 15;
    dt_usr[2] = float(short((data[5] << 8) | data[4])) * fs_factor / 15;
#else
    dt_usr[0] = float(short((data[1] << 8) | data[0]) >> 4) * fs_factor;
    dt_usr[1] = float(short((data[3] << 8) | data[2]) >> 4) * fs_factor;
    dt_usr[2] = float(short((data[5] << 8) | data[4]) >> 4) * fs_factor;
#endif
}

void LIS3DH::read_data(float *dt_usr)
{
    uint8_t data[6];

    if (acc_ready == 0) {
        dt_usr[0] = 0;
        dt_usr[1] = 0;
        dt_usr[2] = 0;
        return;
    }
    readRegs(LIS3DH_OUT_X_L, data, 6); 
    // change data type
#if OLD_REV // Fixed bugs -> shift right 4bit = /16 (not /15)
    dt_usr[0] = float(short((data[1] << 8) | data[0])) * fs_factor / 15 * GRAVITY;
    dt_usr[1] = float(short((data[3] << 8) | data[2])) * fs_factor / 15 * GRAVITY;
    dt_usr[2] = float(short((data[5] << 8) | data[4])) * fs_factor / 15 * GRAVITY;
#else
    dt_usr[0] = float(short((data[1] << 8) | data[0]) >> 4) * fs_factor * GRAVITY;
    dt_usr[1] = float(short((data[3] << 8) | data[2]) >> 4) * fs_factor * GRAVITY;
    dt_usr[2] = float(short((data[5] << 8) | data[4]) >> 4) * fs_factor * GRAVITY;
#endif
}

uint8_t LIS3DH::read_id()
{
    dt[0] = read_reg(LIS3DH_WHO_AM_I);
    return dt[0];
}

uint8_t LIS3DH::data_ready()
{
    if (acc_ready == 1) { //device initialized correctly
        dt[0] = read_reg(LIS3DH_STATUS_REG_AUX);
        if (!(dt[0] & 0x01)) {
            return 0;
        }
    }
    return 1;
}

void LIS3DH::set_frequency(int hz)
{
    _spi.frequency(hz);
}