AKM AK09970N 3D Magnetic Sensor with Programmable Switch
Diff: AK09970N.cpp
- Revision:
- 1:2b2ead3e4efc
diff -r 0d5779fc90fe -r 2b2ead3e4efc AK09970N.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/AK09970N.cpp Thu Dec 28 07:24:03 2017 +0000 @@ -0,0 +1,588 @@ +#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 ) ; +}