AKM AK09970N 3D Magnetic Sensor with Programmable Switch

AK09970N.cpp

Committer:
Rhyme
Date:
2017-12-28
Revision:
1:2b2ead3e4efc

File content as of revision 1:2b2ead3e4efc:

#include "mbed.h"
#include "AK09970N.h"

/* Read only Registers */
#define REG_ID          0x00
#define REG_STATUS      0x10
#define REG_ST_X        0x11
#define REG_ST_Y        0x12
#define REG_ST_X_Y      0x13
#define REG_ST_Z        0x14
#define REG_ST_X_Z      0x15
#define REG_ST_Y_Z      0x16
#define REG_ST_X_Y_Z    0x17
#define REG_ST_BX       0x19
#define REG_ST_BY       0x1A
#define REG_ST_BX_BY    0x1B
#define REG_ST_BZ       0x1C
#define REG_ST_BX_BZ    0x1D
#define REG_ST_BY_BZ    0x1E
#define REG_ST_BX_BY_BZ 0x1F
/* Read/Write Registers */
#define REG_INT         0x20
#define REG_CONFIG      0x21
#define REG_THS_X1      0x22
#define REG_THS_X2      0x23
#define REG_THS_Y1      0x24
#define REG_THS_Y2      0x25
#define REG_THS_Z1      0x26
#define REG_THS_Z2      0x27
/* Special function */
#define REG_RESET       0x30
#define REG_I2C_Disable 0x31
#define REG_TEST1       0x40
#define REG_TEST2       0x41

AK09970N::AK09970N(PinName sda, PinName scl, int addr) : m_i2c(sda, scl), m_addr(addr<<1) {
    uint8_t data[2] ;
    // activate the peripheral
    _mode = 0 ; /* power-down mode */
    _sdr = 0 ; /* Sensor drive setting */
    _smr = 0 ; /* 0: High sensitivity 1: Wide measurement range */
    data[0] = REG_INT ;
    data[1] = 0x01 ;
    writeRegs(data, 2) ;
}

AK09970N::~AK09970N() { }

int AK09970N::readRegs(int addr, uint8_t * data, int len) {
    int result ;
    char t[1] = {addr};
    result = m_i2c.write(m_addr, t, 1, true);
    if (result == 0) {
        m_i2c.read(m_addr, (char *)data, len);
    }
    return( result ) ;
}

int AK09970N::writeRegs(uint8_t * data, int len) {
    int result ;
    result = m_i2c.write(m_addr, (char *)data, len);
    return( result ) ;
}

int AK09970N::software_reset(void)
{
    int result ;
    uint8_t data[2] = { REG_RESET, 0x01 } ;
    result = writeRegs(data, 2) ;
    return( result ) ;
}

int AK09970N::getID(uint16_t *CompanyID, uint16_t *DeviceID)
{
    int result ;
    uint8_t data[4] ;
    result = readRegs(REG_ID, data, 4) ;
    if (result == 0) {
        *CompanyID = data[0] ;
        *DeviceID = data[1] ;
    }
    return( result ) ;
}

/**
 * REG_STATUS 0x10
 * REG_STATUS[15:10] (reserved)
 * REG_STATUS[9] DOR : 0: Normal 1: Data overrun
 * REG_STATUS[8] ERRADC : 0: Normal 1: ADC overflow
 * REG_STATUS[7] ERRXY : 0: Normal 1: Magnetic sensor overflow (X and/or Y)
 * REG_STATUS[6] SWZ2 : exceed_THSeshold 2
 * REG_STATUS[5] SWZ1 : exceed_THSeshold 1
 * REG_STATUS[4] SWY2 : exceed_THSeshold 2
 * REG_STATUS[3] SWY1 : exceed_THSeshold 1
 * REG_STATUS[2] SWX2 : exceed THSeshold 2
 * REG_STATUS[1] SWX1 : exceed THSeshold 1
 * REG_STATUS[0] DRDY : 0: Normal 1: Data is ready
 */
uint16_t AK09970N::getStatus(void) 
{
    int result ;
    uint8_t data[2] ;
    uint16_t status = 0 ;
    result = readRegs(REG_STATUS, data, 2) ;
    if (result == 0) { /* success */
        status = (data[0] << 8) | data[1] ;
    }
    return( status ) ;
}

int AK09970N::setINT(uint16_t value) 
{
    int result ;
    uint8_t data[3] ;
    data[0] = REG_INT ;
    data[1] = (value >> 8) & 0xFF ;
    data[2] = value & 0xFF ;
    result = writeRegs(data, 3) ;
    return(result) ;
}

uint16_t AK09970N::getINT(void) 
{
    int result ;
    uint8_t data[2] ;
    uint16_t value ;
    result = readRegs(REG_INT, data, 2) ;
    if (result == 0) {
        value = (data[0] << 8) | data[1] ;
    }
    return(value) ;
}

int AK09970N::setConfig(uint8_t config) 
{
    int result ;
    uint8_t data[2] ;
    data[0] = REG_CONFIG ;
    data[1] = config ;
    result = writeRegs(data, 2) ;
    _mode = config & 0x0F ; /* operation mode 0: power down 1: single 2~: other */
    _sdr = (config >> 4) & 0x01 ; /* Sensor drive setting */
    _smr = (config >> 5) & 0x01 ; /* Measurement range and sensitivity */
    return( result ) ;
}

uint8_t AK09970N::getConfig(void)
{
    int result ;
    uint8_t config = 0x00 ;
    result = readRegs(REG_CONFIG, &config, 1) ;
    if (result == 0) { /* read success, reflect each bits */
        _mode = config & 0x0F ;
        _sdr = (config >> 4) & 0x01 ;
        _smr = (config >> 5) & 0x01 ;
    }   
    return( config ) ;
}

int AK09970N::singleShot(void)
{
    int result ;
    uint8_t config ;
    config = (_smr << 5)|(_sdr << 4)|0x01 ;
    result = setConfig(config) ;
    return( result ) ;
}

float AK09970N::i2f(int16_t value) 
{
    float fvalue ;
    if (_smr) {
        fvalue = 0.0011 * ((float)value) ;
    } else {
        fvalue = 0.0031 * ((float)value) ;
    }
    return( fvalue ) ;
}

int AK09970N::getX(uint16_t *status, float *x) 
{
    int result ;
    int16_t hx ;
    result = getHX(status, &hx) ;
    if (result == 0) {
        *x = i2f(hx) ;
    }
    return(result) ;
}

int AK09970N::getY(uint16_t *status, float *y) 
{
    int result ;
    int16_t hy ;
    result = getHY(status, &hy) ;
    if (result == 0) {
        *y = i2f(hy) ;
    }
    return(result) ;    
}

int AK09970N::getZ(uint16_t *status, float *z) 
{
    int result ;
    int16_t hz ;
    result = getHZ(status, &hz) ;
    if (result == 0) {
        *z = i2f(hz) ;
    }
    return( result ) ;    
}
int AK09970N::getX_Y(uint16_t *status, float *x, float *y) 
{
    int result ;
    int16_t hx, hy ;
    result = getHX_HY(status, &hx, &hy) ;
    if (result == 0) {
        *x = i2f(hx) ;
        *y = i2f(hy) ;
    }
    return( result ) ;
}

int AK09970N::getX_Z(uint16_t *status, float *x, float *z) 
{
    int result ;
    int16_t hx, hz ;
    result = getHX_HZ(status, &hx, &hz) ;
    if (result == 0) {
        *x = i2f(hx) ;
        *z = i2f(hz) ;
    }
    return( result ) ;
}

int AK09970N::getY_Z(uint16_t *status, float *y, float *z) 
{
    int result ;
    int16_t hy, hz ;
    result = getHY_HZ(status, &hy, &hz) ;
    if (result == 0) {
        *y = i2f(hy) ;
        *z = i2f(hz) ;
    }
    return( result ) ;
}

int AK09970N::getX_Y_Z(uint16_t *status, float *x, float *y, float *z) 
{
    int result ;
    int16_t hx, hy, hz ;
    result = getHX_HY_HZ(status, &hx, &hy, &hz) ;
    if (result == 0) {
        *x = i2f(hx) ;
        *y = i2f(hy) ;
        *z = i2f(hz) ;
    }
    return( result ) ;
}
  
int AK09970N::getHX(uint16_t *status, int16_t *x) 
{
    int result ;
    uint8_t data[4] ;
    result = readRegs(REG_ST_X, data, 4) ;
    if (result == 0) { /* success */
        *status = (data[0] << 8) | data[1] ;
        *x = (int16_t)((data[2] << 8) | data[3]) ;
    }
    return( result ) ;
}

int AK09970N::getHY(uint16_t *status, int16_t *y) 
{
    int result ;
    uint8_t data[4] ;
    result = readRegs(REG_ST_Y, data, 4) ;
    if (result == 0) { /* success */
        *status = (data[0] << 8) | data[1] ;
        *y = (int16_t)((data[2] << 8) | data[3]) ;
    }
    return( result ) ;
}

int AK09970N::getHZ(uint16_t *status, int16_t *z) 
{
    int result ;
    uint8_t data[4] ;
    result = readRegs(REG_ST_Z, data, 4) ;
    if (result == 0) { /* success */
        *status = (data[0] << 8) | data[1] ;
        *z = (int16_t)((data[2] << 8) | data[3]) ;
    }
    return( result ) ;
}

int AK09970N::getHX_HY(uint16_t *status, int16_t *x, int16_t *y) 
{
    int result ;
    uint8_t data[6] ;
    result = readRegs(REG_ST_X_Y, data, 6) ;
    if (result == 0) { /* success */
        *status = (data[0] << 8) | data[1] ;
        *y = (int16_t)((data[2] << 8) | data[3]) ;
        *x = (int16_t)((data[4] << 8) | data[5]) ;
    }
    return( result ) ;
}

int AK09970N::getHX_HZ(uint16_t *status, int16_t *x, int16_t *z) 
{
    int result ;
    uint8_t data[6] ;
    result = readRegs(REG_ST_X_Z, data, 6) ;
    if (result == 0) { /* success */
        *status = (data[0] << 8) | data[1] ;
        *z = (int16_t)((data[2] << 8) | data[3]) ;
        *x = (int16_t)((data[4] << 8) | data[5]) ;
    }
    return( result ) ;
}

int AK09970N::getHY_HZ(uint16_t *status, int16_t *y, int16_t *z) 
{
    int result ;
    uint8_t data[6] ;
    result = readRegs(REG_ST_Y_Z, data, 6) ;
    if (result == 0) { /* success */
        *status = (data[0] << 8) | data[1] ;
        *z = (int16_t)((data[2] << 8) | data[3]) ;
        *y = (int16_t)((data[4] << 8) | data[5]) ;
    }
    return( result ) ;
}

int AK09970N::getHX_HY_HZ(uint16_t *status, int16_t *x, int16_t *y, int16_t *z) 
{
    int result ;
    uint8_t data[8] ;
    result = readRegs(REG_ST_X_Y_Z, data, 8) ;
    if (result == 0) { /* success */
        *status = (data[0] << 8) | data[1] ;
        *z = (int16_t)((data[2] << 8) | data[3]) ;
        *y = (int16_t)((data[4] << 8) | data[5]) ;
        *x = (int16_t)((data[6] << 8) | data[7]) ;
    }
    return( result ) ;    
}

/* get measured data 8bit versions */
int AK09970N::getBX(uint16_t *status, int8_t *x) 
{
    int result ;
    uint8_t data[3] ;
    result = readRegs(REG_ST_BX, data, 3) ;
    if (result == 0) { /* success */
        *status = (data[0] << 8) | data[1] ;
        *x = (int8_t)data[2] ; 
    }
    return( result ) ;
}

int AK09970N::getBY(uint16_t *status, int8_t *y) 
{
    int result ;
    uint8_t data[3] ;
    result = readRegs(REG_ST_BY, data, 3) ;
    if (result == 0) { /* success */
        *status = (data[0] << 8) | data[1] ;
        *y = (int8_t)data[2] ; 
    }
    return( result ) ;
}

int AK09970N::getBZ(uint16_t *status, int8_t *z) 
{
    int result ;
    uint8_t data[3] ;
    result = readRegs(REG_ST_BZ, data, 3) ;
    if (result == 0) { /* success */
        *status = (data[0] << 8) | data[1] ;
        *z = (int8_t)data[2] ; 
    }
    return( result ) ;
}

int AK09970N::getBX_BY(uint16_t *status, int8_t *x, int8_t *y) 
{
    int result ;
    uint8_t data[4] ;
    result = readRegs(REG_ST_BX_BY, data, 4) ;
    if (result == 0) { /* success */
        *status = (data[0] << 8) | data[1] ;
        *y = (int8_t)data[2] ;
        *x = (int8_t)data[3] ; 
    }
    return( result ) ;
}

int AK09970N::getBX_BZ(uint16_t *status, int8_t *x, int8_t *z) 
{
    int result ;
    uint8_t data[4] ;
    result = readRegs(REG_ST_BX_BZ, data, 4) ;
    if (result == 0) { /* success */
        *status = (data[0] << 8) | data[1] ;
        *z = (int8_t)data[2] ;
        *x = (int8_t)data[3] ; 
    }
    return( result ) ;
}

int AK09970N::getBY_BZ(uint16_t *status, int8_t *y, int8_t *z)
{
    int result ;
    uint8_t data[4] ;
    result = readRegs(REG_ST_BY_BZ, data, 4) ;
    if (result == 0) { /* success */
        *status = (data[0] << 8) | data[1] ;
        *z = (int8_t)data[2] ;
        *y = (int8_t)data[3] ; 
    }
    return( result ) ;
}

int AK09970N::getBX_BY_BZ(uint16_t *status, int8_t *x, int8_t *y, int8_t *z) 
{
    int result ;
    uint8_t data[5] ;
    result = readRegs(REG_ST_BX_BY_BZ, data, 4) ;
    if (result == 0) { /* success */
        *status = (data[0] << 8) | data[1] ;
        *z = (int8_t)data[2] ;
        *y = (int8_t)data[3] ; 
        *x = (int8_t)data[4] ;
    }
    return( result ) ;    
}
  
int AK09970N::getTHS_X1(int16_t *bop, int16_t *brp) 
{
    int result ;
    uint8_t data[4] ;
    result = readRegs(REG_THS_X1, data, 4) ;
    if (result == 0) { /* success */
        *bop = (int16_t)((data[0] << 8) | data[1]) ;
        *brp = (int16_t)((data[2] << 8) | data[3]) ;
    }
    return( result ) ;
}

int AK09970N::getTHS_X2(int16_t *bop, int16_t *brp) 
{
    int result ;
    uint8_t data[4] ;
    result = readRegs(REG_THS_X2, data, 4) ;
    if (result == 0) { /* success */
        *bop = (int16_t)((data[0] << 8) | data[1]) ;
        *brp = (int16_t)((data[2] << 8) | data[3]) ;
    }
    return( result ) ;    
}

int AK09970N::getTHS_Y1(int16_t *bop, int16_t *brp) 
{
    int result ;
    uint8_t data[4] ;
    result = readRegs(REG_THS_Y1, data, 4) ;
    if (result == 0) { /* success */
        *bop = (int16_t)((data[0] << 8) | data[1]) ;
        *brp = (int16_t)((data[2] << 8) | data[3]) ;
    }
    return( result ) ;    
}

int AK09970N::getTHS_Y2(int16_t *bop, int16_t *brp) 
{
    int result ;
    uint8_t data[4] ;
    result = readRegs(REG_THS_Y2, data, 4) ;
    if (result == 0) { /* success */
        *bop = (int16_t)((data[0] << 8) | data[1]) ;
        *brp = (int16_t)((data[2] << 8) | data[3]) ;
    }
    return( result ) ;    
}

int AK09970N::getTHS_Z1(int16_t *bop, int16_t *brp) 
{
    int result ;
    uint8_t data[4] ;
    result = readRegs(REG_THS_Z1, data, 4) ;
    if (result == 0) { /* success */
        *bop = (int16_t)((data[0] << 8) | data[1]) ;
        *brp = (int16_t)((data[2] << 8) | data[3]) ;
    }
    return( result ) ;    
}

int AK09970N::getTHS_Z2(int16_t *bop, int16_t *brp)
{
    int result ;
    uint8_t data[4] ;
    result = readRegs(REG_THS_Z2, data, 4) ;
    if (result == 0) { /* success */
        *bop = (int16_t)((data[0] << 8) | data[1]) ;
        *brp = (int16_t)((data[2] << 8) | data[3]) ;
    }
    return( result ) ;    
}
  
int AK09970N::setTHS_X1(int16_t bop, int16_t brp)
{
    int result ;
    uint8_t data[5] ;
    data[0] = REG_THS_X1 ;
    data[1] = (bop >> 8) & 0xFF ;
    data[2] = bop & 0xFF ;
    data[3] = (brp >> 8) & 0xFF ;
    data[4] = brp & 0xFF ;
    result = writeRegs(data, 5) ;
    return( result ) ;    
}

int AK09970N::setTHS_X2(int16_t bop, int16_t brp) 
{
    int result ;
    uint8_t data[5] ;
    data[0] = REG_THS_X2 ;
    data[1] = (bop >> 8) & 0xFF ;
    data[2] = bop & 0xFF ;
    data[3] = (brp >> 8) & 0xFF ;
    data[4] = brp & 0xFF ;
    result = writeRegs(data, 5) ;
    return( result ) ;    
}

int AK09970N::setTHS_Y1(int16_t bop, int16_t brp) 
{
    int result ;
    uint8_t data[5] ;
    data[0] = REG_THS_Y1 ;
    data[1] = (bop >> 8) & 0xFF ;
    data[2] = bop & 0xFF ;
    data[3] = (brp >> 8) & 0xFF ;
    data[4] = brp & 0xFF ;
    result = writeRegs(data, 5) ;
    return( result ) ;    
}

int AK09970N::setTHS_Y2(int16_t bop, int16_t brp) 
{
    int result ;
    uint8_t data[5] ;
    data[0] = REG_THS_Y2 ;
    data[1] = (bop >> 8) & 0xFF ;
    data[2] = bop & 0xFF ;
    data[3] = (brp >> 8) & 0xFF ;
    data[4] = brp & 0xFF ;
    result = writeRegs(data, 5) ;
    return( result ) ;    
}

int AK09970N::setTHS_Z1(int16_t bop, int16_t brp) 
{
    int result ;
    uint8_t data[5] ;
    data[0] = REG_THS_Z1 ;
    data[1] = (bop >> 8) & 0xFF ;
    data[2] = bop & 0xFF ;
    data[3] = (brp >> 8) & 0xFF ;
    data[4] = brp & 0xFF ;
    result = writeRegs(data, 5) ;
    return( result ) ;    
}

int AK09970N::setTHS_Z2(int16_t bop, int16_t brp) 
{
    int result ;
    uint8_t data[5] ;
    data[0] = REG_THS_Z2 ;
    data[1] = (bop >> 8) & 0xFF ;
    data[2] = bop & 0xFF ;
    data[3] = (brp >> 8) & 0xFF ;
    data[4] = brp & 0xFF ;
    result = writeRegs(data, 5) ;
    return( result ) ;    
}