AKM AK09970N 3D Magnetic Sensor with Programmable Switch

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 ) ;    
+}