eCompass (6-axes electronic compass) / Electronic Compass with Three-axis Magnetic Field Sensor and Three-axis Accelerometer by Bosch Sensortech

Dependents:   BLE_EddystoneBeacon_w_ACC_TY51822

BMC050.cpp

Committer:
kenjiArai
Date:
2014-09-07
Revision:
1:b022f8d7884d
Parent:
0:8de5e2fd5c48
Child:
2:93141eb80862

File content as of revision 1:b022f8d7884d:

/*
 * mbed library program 
 *  BMC050 COMPASS 6 AXIS, made by Bosch Sensortec
 *      http://jp.bosch-sensortec.com/content/language1/html/5033.htm
 *
 * Copyright (c) 2014 Kenji Arai / JH1PJL
 *  http://www.page.sannet.ne.jp/kenjia/index.html
 *  http://mbed.org/users/kenjiArai/
 *      Created: July      19th, 2014 
 *      Revised: September  7th, 2014
 *
 * 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 "BMC050.h"

BMC050::BMC050 (PinName p_sda, PinName p_scl,
    const BMC050ACC_TypeDef *acc_parameter, const BMC050MAG_TypeDef *mag_parameter) :
    i2c(p_sda, p_scl) {
    initialize (acc_parameter, mag_parameter);
}

BMC050::BMC050 (I2C& p_i2c,
    const BMC050ACC_TypeDef *acc_parameter, const BMC050MAG_TypeDef *mag_parameter) : i2c(p_i2c) {
    initialize (acc_parameter, mag_parameter);
}

void BMC050::initialize (const BMC050ACC_TypeDef *acc_parameter,
                         const BMC050MAG_TypeDef *mag_parameter) {
    /////////////// Magnetometer Configuration /////////////////
    // after power-on, mag chip is keeping "Suspend mode"!!
    //      -> Need to go "Normal mode" via "Sleep mode"
    // step 1/start 
    mag_addr = mag_parameter->addr;
    if (mag_addr != BMC050_MAG_NOT_USED_ADDR) {
        dbf[0] = BMC050_M_POWER_MODE;
        dbf[1] = 0x01;  // Power control bit on
        i2c.write(mag_addr, dbf, 2);
        dbf[0] = BMC050_M_OPERATION;
        dbf[1] = 0;
        i2c.write(mag_addr, dbf, 2);
    }
    /////////////// Accelerometer configuration ////////////////
    // Check acc chip is available of not
    // step 1/start
    acc_addr = acc_parameter->addr;
    dbf[0] = BMC050_A_WHO_AM_I; 
    i2c.write(acc_addr, dbf, 1); 
    i2c.read(acc_addr, dbf, 1);
    if (dbf[0] == I_AM_BMC050_ACC){ acc_ready = 1;
    } else {                        acc_ready = 0; }
    /////////////// Magnetometer Configuration /////////////////
    // after power-on, mag chip is keeping "Suspend mode"!!
    //      -> Need to go "Normal mode" via "Sleep mode"
    // step 2 
    if (mag_addr != BMC050_MAG_NOT_USED_ADDR) {
        i2c.write(mag_addr, dbf, 2);
        dbf[0] = BMC050_M_OPERATION;
        dbf[1] = 0;
        i2c.write(mag_addr, dbf, 2);
    }
    /////////////// Accelerometer configuration ////////////////
    // step 2/last
    if ( acc_ready == 1){
        // set g-range
        dbf[0] = BMC050_A_G_RANGE;
        dbf[1] = acc_parameter->g_range;
        switch (dbf[1]){
        case BMC050_FS_2G:
            fs_factor_acc = 256;
            break;
        case BMC050_FS_4G:
            fs_factor_acc = 128;
            break;
        case BMC050_FS_8G:
            fs_factor_acc = 64;
            break;
        case BMC050_FS_16G:
            fs_factor_acc = 32;
            break;
        default:
            fs_factor_acc = 256;
            dbf[1] = BMC050_FS_2G;
        }          
        i2c.write(acc_addr, dbf, 2);
        // set bandwidth
        dbf[1] = acc_parameter->bandwith;
        if (dbf[1] == BMC050_NOT_FILTERED){
            dbf[0] = BMC050_A_FILTER;
            dbf[1] = 0x80;
        } else {
            dbf[0] = BMC050_A_BANDWIDTH;
        }
        i2c.write(acc_addr, dbf, 2);
    }
    /////////////// Magnetometer Configuration /////////////////
    // Check mag chip is available of not
    // step 3/last
    if (mag_addr != BMC050_MAG_NOT_USED_ADDR) {
        dbf[0] = BMC050_M_WHO_AM_I; 
        i2c.write(mag_addr, dbf, 1); 
        i2c.read(mag_addr, dbf, 1);
        if (dbf[0] == I_AM_BMC050_MAG){ mag_ready = 1;
        } else {                        mag_ready = 0; }
        if ( mag_ready == 1){
            // set output data rate
            dbf[0] = BMC050_M_OPERATION;
            dbf[1] = mag_parameter->data_rate;
            i2c.write(mag_addr, dbf, 2);
        }
    }      
}

/////////////// Accelerometer ///////////////////
void BMC050::read_data_acc(float *dt) {
char data[6];

    if (acc_ready == 0){
        dt[0] = dt[1] = dt[2] = 0;
        return;  
    }
    // X,Y &Z
    dbf[0] = BMC050_A_OUT_X_L; 
    i2c.write(acc_addr, dbf, 1, true); 
    i2c.read(acc_addr, data, 6, false);
    // change data type
    dt[0] = float((short(data[1] << 8 | data[0] & 0xc0))>> 6) * GRAVITY / fs_factor_acc;
    dt[1] = float((short(data[3] << 8 | data[2] & 0xc0))>> 6) * GRAVITY / fs_factor_acc;
    dt[2] = float((short(data[5] << 8 | data[4] & 0xc0))>> 6) * GRAVITY / fs_factor_acc;
}

/////////////// Accelerometer ///////////////////
void BMC050::read_mg_acc(float *dt) {
char data[6];

    if (acc_ready == 0){
        dt[0] = 0;
        dt[1] = 0;
        dt[2] = 0;
        return;  
    }
    // X,Y &Z
    dbf[0] = BMC050_A_OUT_X_L; 
    i2c.write(acc_addr, dbf, 1, true); 
    i2c.read(acc_addr, data, 6, false);
    // change data type
    dt[0] = float((short(data[1] << 8 | data[0] & 0xc0))>> 6) / fs_factor_acc;
    dt[1] = float((short(data[3] << 8 | data[2] & 0xc0))>> 6) / fs_factor_acc;
    dt[2] = float((short(data[5] << 8 | data[4] & 0xc0))>> 6) / fs_factor_acc;
}

/////////////// Magnetometer ////////////////////
void BMC050::read_data_mag(float *dt) {
char data[6];

    if (mag_ready == 0){
        dt[0] = dt[1] = dt[2] = 0;
        return;  
    }
    // X,Y &Z
    dbf[0] = BMC050_M_OUT_X_L; 
    i2c.write(mag_addr, dbf, 1, true); 
    i2c.read(mag_addr, data, 6, false);
    // change data type
    dt[0] = float((short(data[1] << 8 | data[0] & 0xf8))>> 3);
    dt[1] = float((short(data[3] << 8 | data[2] & 0xf8))>> 3);
    dt[2] = float((short(data[5] << 8 | data[4] & 0xfe))>> 1);
}

/////////////// Accelerometer ///////////////////
float BMC050::read_temp() {
    dbf[0] = BMC050_A_OUT_TEMP; 
    i2c.write(acc_addr, dbf, 1); 
    i2c.read(acc_addr, dbf, 1);
    return ((float)dbf[0] * 0.5 + 24.0);
}

/////////////// Accelerometer ///////////////////
uint8_t BMC050::read_id_acc() {
    dbf[0] = BMC050_A_WHO_AM_I; 
    i2c.write(acc_addr, dbf, 1); 
    i2c.read(acc_addr, dbf, 1);
    return (uint8_t)dbf[0];
}

/////////////// Magnetometer ////////////////////
uint8_t BMC050::read_id_mag() {
    dbf[0] = BMC050_M_WHO_AM_I; 
    i2c.write(mag_addr, dbf, 1); 
    i2c.read(mag_addr, dbf, 1);
    return (uint8_t)dbf[0];
}

/////////////// Accelerometer ///////////////////
uint8_t BMC050::data_ready_acc() {
    if (acc_ready == 1){
        dbf[0] = BMC050_A_OUT_X_L; 
        i2c.write(acc_addr, dbf, 1); 
        i2c.read(acc_addr, dbf, 1);
        if (!(dbf[0] & 0x01)){
            return 0;
        }
    }
    return 1;
}

/////////////// Magnetometer ////////////////////
uint8_t BMC050::data_ready_mag() {
    if (mag_ready == 1){
        dbf[0] = BMC050_M_HALL_L; 
        i2c.write(mag_addr, dbf, 1); 
        i2c.read(mag_addr, dbf, 1);
        if (!(dbf[0] & 0x01)){
            return 0;
        }
    }
    return 1;
}

/////////////// Accelerometer ///////////////////
uint8_t BMC050::read_reg_acc(uint8_t addr) {
    if (acc_ready == 1){
        dbf[0] = addr; 
        i2c.write(acc_addr, dbf, 1); 
        i2c.read(acc_addr, dbf, 1);
    } else {
        dbf[0] = 0xff;
    }
    return (uint8_t)dbf[0];
}

/////////////// Magnetometer ////////////////////
uint8_t BMC050::read_reg_mag(uint8_t addr) {
    if (mag_ready == 1){
        dbf[0] = addr; 
        i2c.write(mag_addr, dbf, 1); 
        i2c.read(mag_addr, dbf, 1);
    } else {
        dbf[0] = 0xff;
    }
    return (uint8_t)dbf[0];
}

/////////////// Accelerometer ///////////////////
void BMC050::write_reg_acc(uint8_t addr, uint8_t data) {
    if (acc_ready == 1){
        dbf[0] = addr;
        dbf[1] = data; 
        i2c.write(acc_addr, dbf, 2); 
    }
}

/////////////// Magnetometer ////////////////////
void BMC050::write_reg_mag(uint8_t addr, uint8_t data) {
    if (mag_ready == 1){
        dbf[0] = addr;
        dbf[1] = data; 
        i2c.write(mag_addr, dbf, 2); 
    }
}

/////////////// Common //////////////////////////
void BMC050::frequency(int hz) {
    i2c.frequency(hz);
}