#include #include #include #include "common/swaglog.h" #include "bmx055_magn.hpp" static int16_t parse_xy(uint8_t lsb, uint8_t msb){ // 13 bit uint16_t combined = (uint16_t(msb) << 5) | uint16_t(lsb >> 3); return int16_t(combined << 3) / (1 << 3); } static int16_t parse_z(uint8_t lsb, uint8_t msb){ // 15 bit uint16_t combined = (uint16_t(msb) << 7) | uint16_t(lsb >> 1); return int16_t(combined << 1) / (1 << 1); } /* static uint16_t parse_rhall(uint8_t lsb, uint8_t msb){ // 14 bit return (uint16_t(msb) << 6) | uint16_t(lsb >> 2); } */ BMX055_Magn::BMX055_Magn(I2CBus *bus) : I2CSensor(bus) {} int BMX055_Magn::init(){ int ret; uint8_t buffer[1]; // suspend -> sleep ret = set_register(BMX055_MAGN_I2C_REG_PWR_0, 0x01); if(ret < 0){ LOGE("Enabling power failed: %d", ret); goto fail; } usleep(5 * 1000); // wait until the chip is powered on // read chip ID ret = read_register(BMX055_MAGN_I2C_REG_ID, buffer, 1); if(ret < 0){ LOGE("Reading chip ID failed: %d", ret); goto fail; } if(buffer[0] != BMX055_MAGN_CHIP_ID){ LOGE("Chip ID wrong. Got: %d, Expected %d", buffer[0], BMX055_MAGN_CHIP_ID); return -1; } // TODO: perform self-test // 9 REPXY and 15 REPZ for 100 Hz // 3 REPXY and 3 REPZ for > 300 Hz ret = set_register(BMX055_MAGN_I2C_REG_REPXY, (3 - 1) / 2); if (ret < 0){ goto fail; } ret = set_register(BMX055_MAGN_I2C_REG_REPZ, 3 - 1); if (ret < 0){ goto fail; } return 0; fail: return ret; } void BMX055_Magn::get_event(cereal::SensorEventData::Builder &event){ uint64_t start_time = nanos_since_boot(); uint8_t buffer[8]; int len = read_register(BMX055_MAGN_I2C_REG_DATAX_LSB, buffer, sizeof(buffer)); assert(len == sizeof(buffer)); bool ready = buffer[6] & 0x1; if (ready){ float x = parse_xy(buffer[0], buffer[1]); float y = parse_xy(buffer[2], buffer[3]); float z = parse_z(buffer[4], buffer[5]); //uint16_t rhall = parse_rhall(buffer[5], buffer[6]); // TODO: convert to micro tesla: // https://github.com/BoschSensortec/BMM150-Sensor-API/blob/master/bmm150.c#L1614 event.setSource(cereal::SensorEventData::SensorSource::BMX055); event.setVersion(1); event.setSensor(SENSOR_MAGNETOMETER_UNCALIBRATED); event.setType(SENSOR_TYPE_MAGNETIC_FIELD_UNCALIBRATED); event.setTimestamp(start_time); float xyz[] = {x, y, z}; auto svec = event.initMagneticUncalibrated(); svec.setV(xyz); svec.setStatus(true); } // The BMX055 Magnetometer has no FIFO mode. Self running mode only goes // up to 30 Hz. Therefore we put in forced mode, and request measurements // at a 100 Hz. When reading the registers we have to check the ready bit // To verify the measurement was comleted this cycle. set_register(BMX055_MAGN_I2C_REG_MAG, BMX055_MAGN_FORCED); }