Si7210 driver
Dependents: TBSense2_Sensor_Demo
Si7210.cpp
- Committer:
- stevew817
- Date:
- 2017-05-04
- Revision:
- 0:9bce98da584b
File content as of revision 0:9bce98da584b:
#include "Si7210.h" #define OTP_BUSY_MASK 1 #define OTP_READ_EN_MASK 2 #define NUM_HALL_DEVICES 3 #define STOP_MASK 2 #define SLTIMEENA_MASK 1 #define SW_TAMPER_MASK 0xFC #define SL_FAST_MASK 2 #define SLEEP_MASK 1 #define ONEBURST_MASK 4 namespace silabs { Si7210::Si7210(PinName sda, PinName scl, uint8_t address) { _i2c = new I2C(sda, scl); _i2c->frequency(400000); _address = address; _ownI2C = true; // Initialize members _temperatureOffset = 0; _temperatureGain = 0; _rawTemperature = 0; _rawField = 0; _range = RANGE_20mT; } Si7210::Si7210(I2C *i2c_bus, uint8_t address) { _i2c = i2c_bus; _address = address; _ownI2C = false; // Initialize members _temperatureOffset = 0; _temperatureGain = 0; _rawTemperature = 0; _rawField = 0; _range = RANGE_20mT; } Si7210::~Si7210() { if (_ownI2C) { delete _i2c; } } int Si7210::getTemperature() { // we operate on 11 fractional bits. int offset; int64_t temperature; if (_temperatureOffset == 0 && _temperatureGain == 0) { /* read out compensation values */ writeRegister(SI72XX_OTP_ADDR, 0x1DU); writeRegister(SI72XX_OTP_CTRL, OTP_READ_EN_MASK); readRegister(SI72XX_OTP_DATA, (uint8_t*)&_temperatureOffset); writeRegister(SI72XX_OTP_ADDR, 0x1EU); writeRegister(SI72XX_OTP_CTRL, OTP_READ_EN_MASK); readRegister(SI72XX_OTP_DATA, (uint8_t*)&_temperatureGain); } temperature = ((int64_t)_rawTemperature * (int64_t)_rawTemperature) * (-21) / 10000; temperature += ((1522 * _rawTemperature) / 10); temperature -= 273000; // offset = val@0x1D / 16 = val@0x1D / 2048 * 128 offset = (int32_t)_temperatureOffset * 1000 / 16; // gain = 1 + val@0x1E // temperature = raw * gain + offset temperature = temperature + (temperature * _temperatureGain / 2048) + offset; // return temperature return temperature; } /* * Get last measured field strength * return: int32_t = field strength in micro-Tesla. */ int Si7210::getFieldStrength() { switch(_range) { case RANGE_20mT: return (_rawField / 4) + _rawField; // rawField * 1.25 case RANGE_200mT: return (_rawField * 12) + (_rawField / 2); //rawField * 12.5 default: return 0; } } /* * Set measurement range. * Return true if successful, false if device is not responding. */ bool Si7210::setFieldStrength(Si7210_range_t range) { _range = range; } /* * Perform measurement of magnetic field. * Return true if new data available */ bool Si7210::fetchFieldStrength() { uint8_t temp = 0x04; readRegister(SI72XX_DSPSIGM, &temp); if(temp & 0x80) { /* Fresh data available */ _rawField = 0; _rawField += (temp & 0x7FU) * 256; readRegister(SI72XX_DSPSIGL, &temp); _rawField += temp; _rawField -= 16384U; return true; } return false; } bool Si7210::measureOnce() { uint8_t temp; wakeup(); readRegister(SI72XX_POWER_CTRL, &temp); temp = (temp & 0xF0) | 0xA; // Stop control loop writeRegister(SI72XX_POWER_CTRL, temp); if (_range == RANGE_200mT) { writeRegister(SI72XX_OTP_ADDR, 0x27U); writeRegister(SI72XX_OTP_CTRL, OTP_READ_EN_MASK); readRegister(SI72XX_OTP_DATA, &temp); writeRegister(SI72XX_A0, temp); writeRegister(SI72XX_OTP_ADDR, 0x28U); writeRegister(SI72XX_OTP_CTRL, OTP_READ_EN_MASK); readRegister(SI72XX_OTP_DATA, &temp); writeRegister(SI72XX_A1, temp); writeRegister(SI72XX_OTP_ADDR, 0x29U); writeRegister(SI72XX_OTP_CTRL, OTP_READ_EN_MASK); readRegister(SI72XX_OTP_DATA, &temp); writeRegister(SI72XX_A2, temp); writeRegister(SI72XX_OTP_ADDR, 0x2AU); writeRegister(SI72XX_OTP_CTRL, OTP_READ_EN_MASK); readRegister(SI72XX_OTP_DATA, &temp); writeRegister(SI72XX_A3, temp); writeRegister(SI72XX_OTP_ADDR, 0x2BU); writeRegister(SI72XX_OTP_CTRL, OTP_READ_EN_MASK); readRegister(SI72XX_OTP_DATA, &temp); writeRegister(SI72XX_A4, temp); writeRegister(SI72XX_OTP_ADDR, 0x2CU); writeRegister(SI72XX_OTP_CTRL, OTP_READ_EN_MASK); readRegister(SI72XX_OTP_DATA, &temp); writeRegister(SI72XX_A5, temp); } writeRegister(SI72XX_CTRL4, 0x44); // Use a burst of 4 samples temp = 0x4; writeRegister(SI72XX_DSPSIGSEL, temp); // Select field strength data readRegister(SI72XX_POWER_CTRL, &temp); temp = (temp & 0xF0) | 0x0C; // Start measurement writeRegister(SI72XX_POWER_CTRL, temp); do { readRegister(SI72XX_POWER_CTRL, &temp); } while ( (temp & 0x80) != 0 ); fetchFieldStrength(); writeRegister(SI72XX_CTRL4, 0x0); // Don't burst temp = 0x1; writeRegister(SI72XX_DSPSIGSEL, temp); // Select temperature data readRegister(SI72XX_POWER_CTRL, &temp); temp = (temp & 0xF0) | 0x0C; // Start measurement writeRegister(SI72XX_POWER_CTRL, temp); readRegister(SI72XX_DSPSIGM, &temp); _rawTemperature = 0; _rawTemperature += 32 * (temp & 0x7F); readRegister(SI72XX_DSPSIGL, &temp); _rawTemperature += (temp >> 3); sleep(); return true; } bool Si7210::check() { uint8_t temp; wakeup(); readRegister(SI72XX_HREVID, &temp); sleep(); return true; } bool Si7210::wakeup() { uint8_t temp; if(_i2c->read(_address, (char*)&temp, 1) == 0) return true; return false; } bool Si7210::sleep() { uint8_t temp; readRegister(SI72XX_CTRL3, &temp); temp &= 0xFEU; // Clear sltimena writeRegister(SI72XX_CTRL3, temp); readRegister(SI72XX_POWER_CTRL, &temp); temp = (temp & 0xF8U) | 0x01; // clear STOP and set SLEEP return writeRegister(SI72XX_POWER_CTRL, temp); } bool Si7210::readRegister(uint8_t reg, uint8_t *result) { _i2c->write(_address, (const char*)®, 1, true); return _i2c->read(_address, (char*)result, 1) == 0; } bool Si7210::writeRegister(uint8_t reg, uint8_t data) { uint8_t buffer[2] = {reg, data}; return _i2c->write(_address, (const char*)buffer, 2) == 0; } } // namespace silabs