Si7210 driver

Dependents:   TBSense2_Sensor_Demo

Committer:
stevew817
Date:
Thu May 04 12:15:44 2017 +0000
Revision:
0:9bce98da584b
Initial WIP;

Who changed what in which revision?

UserRevisionLine numberNew contents of line
stevew817 0:9bce98da584b 1 #include "Si7210.h"
stevew817 0:9bce98da584b 2
stevew817 0:9bce98da584b 3 #define OTP_BUSY_MASK 1
stevew817 0:9bce98da584b 4 #define OTP_READ_EN_MASK 2
stevew817 0:9bce98da584b 5 #define NUM_HALL_DEVICES 3
stevew817 0:9bce98da584b 6 #define STOP_MASK 2
stevew817 0:9bce98da584b 7 #define SLTIMEENA_MASK 1
stevew817 0:9bce98da584b 8 #define SW_TAMPER_MASK 0xFC
stevew817 0:9bce98da584b 9 #define SL_FAST_MASK 2
stevew817 0:9bce98da584b 10 #define SLEEP_MASK 1
stevew817 0:9bce98da584b 11 #define ONEBURST_MASK 4
stevew817 0:9bce98da584b 12
stevew817 0:9bce98da584b 13 namespace silabs {
stevew817 0:9bce98da584b 14 Si7210::Si7210(PinName sda, PinName scl, uint8_t address)
stevew817 0:9bce98da584b 15 {
stevew817 0:9bce98da584b 16 _i2c = new I2C(sda, scl);
stevew817 0:9bce98da584b 17 _i2c->frequency(400000);
stevew817 0:9bce98da584b 18 _address = address;
stevew817 0:9bce98da584b 19 _ownI2C = true;
stevew817 0:9bce98da584b 20
stevew817 0:9bce98da584b 21 // Initialize members
stevew817 0:9bce98da584b 22 _temperatureOffset = 0;
stevew817 0:9bce98da584b 23 _temperatureGain = 0;
stevew817 0:9bce98da584b 24 _rawTemperature = 0;
stevew817 0:9bce98da584b 25 _rawField = 0;
stevew817 0:9bce98da584b 26 _range = RANGE_20mT;
stevew817 0:9bce98da584b 27 }
stevew817 0:9bce98da584b 28
stevew817 0:9bce98da584b 29 Si7210::Si7210(I2C *i2c_bus, uint8_t address)
stevew817 0:9bce98da584b 30 {
stevew817 0:9bce98da584b 31 _i2c = i2c_bus;
stevew817 0:9bce98da584b 32 _address = address;
stevew817 0:9bce98da584b 33 _ownI2C = false;
stevew817 0:9bce98da584b 34
stevew817 0:9bce98da584b 35 // Initialize members
stevew817 0:9bce98da584b 36 _temperatureOffset = 0;
stevew817 0:9bce98da584b 37 _temperatureGain = 0;
stevew817 0:9bce98da584b 38 _rawTemperature = 0;
stevew817 0:9bce98da584b 39 _rawField = 0;
stevew817 0:9bce98da584b 40 _range = RANGE_20mT;
stevew817 0:9bce98da584b 41 }
stevew817 0:9bce98da584b 42
stevew817 0:9bce98da584b 43 Si7210::~Si7210()
stevew817 0:9bce98da584b 44 {
stevew817 0:9bce98da584b 45 if (_ownI2C) {
stevew817 0:9bce98da584b 46 delete _i2c;
stevew817 0:9bce98da584b 47 }
stevew817 0:9bce98da584b 48 }
stevew817 0:9bce98da584b 49
stevew817 0:9bce98da584b 50 int Si7210::getTemperature()
stevew817 0:9bce98da584b 51 {
stevew817 0:9bce98da584b 52 // we operate on 11 fractional bits.
stevew817 0:9bce98da584b 53 int offset;
stevew817 0:9bce98da584b 54 int64_t temperature;
stevew817 0:9bce98da584b 55
stevew817 0:9bce98da584b 56 if (_temperatureOffset == 0 &&
stevew817 0:9bce98da584b 57 _temperatureGain == 0) {
stevew817 0:9bce98da584b 58 /* read out compensation values */
stevew817 0:9bce98da584b 59 writeRegister(SI72XX_OTP_ADDR, 0x1DU);
stevew817 0:9bce98da584b 60 writeRegister(SI72XX_OTP_CTRL, OTP_READ_EN_MASK);
stevew817 0:9bce98da584b 61 readRegister(SI72XX_OTP_DATA, (uint8_t*)&_temperatureOffset);
stevew817 0:9bce98da584b 62
stevew817 0:9bce98da584b 63 writeRegister(SI72XX_OTP_ADDR, 0x1EU);
stevew817 0:9bce98da584b 64 writeRegister(SI72XX_OTP_CTRL, OTP_READ_EN_MASK);
stevew817 0:9bce98da584b 65 readRegister(SI72XX_OTP_DATA, (uint8_t*)&_temperatureGain);
stevew817 0:9bce98da584b 66 }
stevew817 0:9bce98da584b 67
stevew817 0:9bce98da584b 68 temperature = ((int64_t)_rawTemperature * (int64_t)_rawTemperature) * (-21) / 10000;
stevew817 0:9bce98da584b 69 temperature += ((1522 * _rawTemperature) / 10);
stevew817 0:9bce98da584b 70 temperature -= 273000;
stevew817 0:9bce98da584b 71
stevew817 0:9bce98da584b 72
stevew817 0:9bce98da584b 73 // offset = val@0x1D / 16 = val@0x1D / 2048 * 128
stevew817 0:9bce98da584b 74 offset = (int32_t)_temperatureOffset * 1000 / 16;
stevew817 0:9bce98da584b 75 // gain = 1 + val@0x1E
stevew817 0:9bce98da584b 76 // temperature = raw * gain + offset
stevew817 0:9bce98da584b 77 temperature = temperature + (temperature * _temperatureGain / 2048) + offset;
stevew817 0:9bce98da584b 78 // return temperature
stevew817 0:9bce98da584b 79 return temperature;
stevew817 0:9bce98da584b 80 }
stevew817 0:9bce98da584b 81
stevew817 0:9bce98da584b 82 /*
stevew817 0:9bce98da584b 83 * Get last measured field strength
stevew817 0:9bce98da584b 84 * return: int32_t = field strength in micro-Tesla.
stevew817 0:9bce98da584b 85 */
stevew817 0:9bce98da584b 86 int Si7210::getFieldStrength()
stevew817 0:9bce98da584b 87 {
stevew817 0:9bce98da584b 88 switch(_range) {
stevew817 0:9bce98da584b 89 case RANGE_20mT:
stevew817 0:9bce98da584b 90 return (_rawField / 4) + _rawField; // rawField * 1.25
stevew817 0:9bce98da584b 91 case RANGE_200mT:
stevew817 0:9bce98da584b 92 return (_rawField * 12) + (_rawField / 2); //rawField * 12.5
stevew817 0:9bce98da584b 93 default:
stevew817 0:9bce98da584b 94 return 0;
stevew817 0:9bce98da584b 95 }
stevew817 0:9bce98da584b 96 }
stevew817 0:9bce98da584b 97
stevew817 0:9bce98da584b 98 /*
stevew817 0:9bce98da584b 99 * Set measurement range.
stevew817 0:9bce98da584b 100 * Return true if successful, false if device is not responding.
stevew817 0:9bce98da584b 101 */
stevew817 0:9bce98da584b 102 bool Si7210::setFieldStrength(Si7210_range_t range)
stevew817 0:9bce98da584b 103 {
stevew817 0:9bce98da584b 104 _range = range;
stevew817 0:9bce98da584b 105 }
stevew817 0:9bce98da584b 106
stevew817 0:9bce98da584b 107 /*
stevew817 0:9bce98da584b 108 * Perform measurement of magnetic field.
stevew817 0:9bce98da584b 109 * Return true if new data available
stevew817 0:9bce98da584b 110 */
stevew817 0:9bce98da584b 111 bool Si7210::fetchFieldStrength()
stevew817 0:9bce98da584b 112 {
stevew817 0:9bce98da584b 113 uint8_t temp = 0x04;
stevew817 0:9bce98da584b 114 readRegister(SI72XX_DSPSIGM, &temp);
stevew817 0:9bce98da584b 115 if(temp & 0x80) {
stevew817 0:9bce98da584b 116 /* Fresh data available */
stevew817 0:9bce98da584b 117 _rawField = 0;
stevew817 0:9bce98da584b 118 _rawField += (temp & 0x7FU) * 256;
stevew817 0:9bce98da584b 119 readRegister(SI72XX_DSPSIGL, &temp);
stevew817 0:9bce98da584b 120 _rawField += temp;
stevew817 0:9bce98da584b 121 _rawField -= 16384U;
stevew817 0:9bce98da584b 122 return true;
stevew817 0:9bce98da584b 123 }
stevew817 0:9bce98da584b 124 return false;
stevew817 0:9bce98da584b 125 }
stevew817 0:9bce98da584b 126
stevew817 0:9bce98da584b 127 bool Si7210::measureOnce()
stevew817 0:9bce98da584b 128 {
stevew817 0:9bce98da584b 129 uint8_t temp;
stevew817 0:9bce98da584b 130 wakeup();
stevew817 0:9bce98da584b 131 readRegister(SI72XX_POWER_CTRL, &temp);
stevew817 0:9bce98da584b 132 temp = (temp & 0xF0) | 0xA; // Stop control loop
stevew817 0:9bce98da584b 133 writeRegister(SI72XX_POWER_CTRL, temp);
stevew817 0:9bce98da584b 134
stevew817 0:9bce98da584b 135 if (_range == RANGE_200mT) {
stevew817 0:9bce98da584b 136 writeRegister(SI72XX_OTP_ADDR, 0x27U);
stevew817 0:9bce98da584b 137 writeRegister(SI72XX_OTP_CTRL, OTP_READ_EN_MASK);
stevew817 0:9bce98da584b 138 readRegister(SI72XX_OTP_DATA, &temp);
stevew817 0:9bce98da584b 139 writeRegister(SI72XX_A0, temp);
stevew817 0:9bce98da584b 140 writeRegister(SI72XX_OTP_ADDR, 0x28U);
stevew817 0:9bce98da584b 141 writeRegister(SI72XX_OTP_CTRL, OTP_READ_EN_MASK);
stevew817 0:9bce98da584b 142 readRegister(SI72XX_OTP_DATA, &temp);
stevew817 0:9bce98da584b 143 writeRegister(SI72XX_A1, temp);
stevew817 0:9bce98da584b 144 writeRegister(SI72XX_OTP_ADDR, 0x29U);
stevew817 0:9bce98da584b 145 writeRegister(SI72XX_OTP_CTRL, OTP_READ_EN_MASK);
stevew817 0:9bce98da584b 146 readRegister(SI72XX_OTP_DATA, &temp);
stevew817 0:9bce98da584b 147 writeRegister(SI72XX_A2, temp);
stevew817 0:9bce98da584b 148 writeRegister(SI72XX_OTP_ADDR, 0x2AU);
stevew817 0:9bce98da584b 149 writeRegister(SI72XX_OTP_CTRL, OTP_READ_EN_MASK);
stevew817 0:9bce98da584b 150 readRegister(SI72XX_OTP_DATA, &temp);
stevew817 0:9bce98da584b 151 writeRegister(SI72XX_A3, temp);
stevew817 0:9bce98da584b 152 writeRegister(SI72XX_OTP_ADDR, 0x2BU);
stevew817 0:9bce98da584b 153 writeRegister(SI72XX_OTP_CTRL, OTP_READ_EN_MASK);
stevew817 0:9bce98da584b 154 readRegister(SI72XX_OTP_DATA, &temp);
stevew817 0:9bce98da584b 155 writeRegister(SI72XX_A4, temp);
stevew817 0:9bce98da584b 156 writeRegister(SI72XX_OTP_ADDR, 0x2CU);
stevew817 0:9bce98da584b 157 writeRegister(SI72XX_OTP_CTRL, OTP_READ_EN_MASK);
stevew817 0:9bce98da584b 158 readRegister(SI72XX_OTP_DATA, &temp);
stevew817 0:9bce98da584b 159 writeRegister(SI72XX_A5, temp);
stevew817 0:9bce98da584b 160 }
stevew817 0:9bce98da584b 161
stevew817 0:9bce98da584b 162 writeRegister(SI72XX_CTRL4, 0x44); // Use a burst of 4 samples
stevew817 0:9bce98da584b 163 temp = 0x4;
stevew817 0:9bce98da584b 164 writeRegister(SI72XX_DSPSIGSEL, temp); // Select field strength data
stevew817 0:9bce98da584b 165
stevew817 0:9bce98da584b 166 readRegister(SI72XX_POWER_CTRL, &temp);
stevew817 0:9bce98da584b 167 temp = (temp & 0xF0) | 0x0C; // Start measurement
stevew817 0:9bce98da584b 168 writeRegister(SI72XX_POWER_CTRL, temp);
stevew817 0:9bce98da584b 169
stevew817 0:9bce98da584b 170 do {
stevew817 0:9bce98da584b 171 readRegister(SI72XX_POWER_CTRL, &temp);
stevew817 0:9bce98da584b 172 } while ( (temp & 0x80) != 0 );
stevew817 0:9bce98da584b 173
stevew817 0:9bce98da584b 174 fetchFieldStrength();
stevew817 0:9bce98da584b 175
stevew817 0:9bce98da584b 176 writeRegister(SI72XX_CTRL4, 0x0); // Don't burst
stevew817 0:9bce98da584b 177 temp = 0x1;
stevew817 0:9bce98da584b 178 writeRegister(SI72XX_DSPSIGSEL, temp); // Select temperature data
stevew817 0:9bce98da584b 179
stevew817 0:9bce98da584b 180 readRegister(SI72XX_POWER_CTRL, &temp);
stevew817 0:9bce98da584b 181 temp = (temp & 0xF0) | 0x0C; // Start measurement
stevew817 0:9bce98da584b 182 writeRegister(SI72XX_POWER_CTRL, temp);
stevew817 0:9bce98da584b 183
stevew817 0:9bce98da584b 184 readRegister(SI72XX_DSPSIGM, &temp);
stevew817 0:9bce98da584b 185 _rawTemperature = 0;
stevew817 0:9bce98da584b 186 _rawTemperature += 32 * (temp & 0x7F);
stevew817 0:9bce98da584b 187 readRegister(SI72XX_DSPSIGL, &temp);
stevew817 0:9bce98da584b 188 _rawTemperature += (temp >> 3);
stevew817 0:9bce98da584b 189
stevew817 0:9bce98da584b 190 sleep();
stevew817 0:9bce98da584b 191 return true;
stevew817 0:9bce98da584b 192 }
stevew817 0:9bce98da584b 193
stevew817 0:9bce98da584b 194 bool Si7210::check()
stevew817 0:9bce98da584b 195 {
stevew817 0:9bce98da584b 196 uint8_t temp;
stevew817 0:9bce98da584b 197 wakeup();
stevew817 0:9bce98da584b 198 readRegister(SI72XX_HREVID, &temp);
stevew817 0:9bce98da584b 199 sleep();
stevew817 0:9bce98da584b 200
stevew817 0:9bce98da584b 201 return true;
stevew817 0:9bce98da584b 202 }
stevew817 0:9bce98da584b 203
stevew817 0:9bce98da584b 204 bool Si7210::wakeup()
stevew817 0:9bce98da584b 205 {
stevew817 0:9bce98da584b 206 uint8_t temp;
stevew817 0:9bce98da584b 207 if(_i2c->read(_address, (char*)&temp, 1) == 0) return true;
stevew817 0:9bce98da584b 208 return false;
stevew817 0:9bce98da584b 209 }
stevew817 0:9bce98da584b 210
stevew817 0:9bce98da584b 211 bool Si7210::sleep()
stevew817 0:9bce98da584b 212 {
stevew817 0:9bce98da584b 213 uint8_t temp;
stevew817 0:9bce98da584b 214 readRegister(SI72XX_CTRL3, &temp);
stevew817 0:9bce98da584b 215 temp &= 0xFEU; // Clear sltimena
stevew817 0:9bce98da584b 216 writeRegister(SI72XX_CTRL3, temp);
stevew817 0:9bce98da584b 217 readRegister(SI72XX_POWER_CTRL, &temp);
stevew817 0:9bce98da584b 218 temp = (temp & 0xF8U) | 0x01; // clear STOP and set SLEEP
stevew817 0:9bce98da584b 219 return writeRegister(SI72XX_POWER_CTRL, temp);
stevew817 0:9bce98da584b 220 }
stevew817 0:9bce98da584b 221
stevew817 0:9bce98da584b 222 bool Si7210::readRegister(uint8_t reg, uint8_t *result)
stevew817 0:9bce98da584b 223 {
stevew817 0:9bce98da584b 224 _i2c->write(_address, (const char*)&reg, 1, true);
stevew817 0:9bce98da584b 225 return _i2c->read(_address, (char*)result, 1) == 0;
stevew817 0:9bce98da584b 226 }
stevew817 0:9bce98da584b 227
stevew817 0:9bce98da584b 228 bool Si7210::writeRegister(uint8_t reg, uint8_t data)
stevew817 0:9bce98da584b 229 {
stevew817 0:9bce98da584b 230 uint8_t buffer[2] = {reg, data};
stevew817 0:9bce98da584b 231 return _i2c->write(_address, (const char*)buffer, 2) == 0;
stevew817 0:9bce98da584b 232 }
stevew817 0:9bce98da584b 233
stevew817 0:9bce98da584b 234 } // namespace silabs