Si7210 driver
Dependents: TBSense2_Sensor_Demo
Si7210.cpp@0:9bce98da584b, 2017-05-04 (annotated)
- Committer:
- stevew817
- Date:
- Thu May 04 12:15:44 2017 +0000
- Revision:
- 0:9bce98da584b
Initial WIP;
Who changed what in which revision?
User | Revision | Line number | New 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*)®, 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 |