JDI_MIP on ThunderBoardSense2(Silicon-Labs)

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers Si7210.cpp Source File

Si7210.cpp

00001 #include "Si7210.h"
00002 
00003 #define OTP_BUSY_MASK         1
00004 #define OTP_READ_EN_MASK      2
00005 #define NUM_HALL_DEVICES      3
00006 #define STOP_MASK             2
00007 #define SLTIMEENA_MASK        1
00008 #define SW_TAMPER_MASK        0xFC
00009 #define SL_FAST_MASK          2
00010 #define SLEEP_MASK            1
00011 #define ONEBURST_MASK         4
00012 
00013 namespace silabs {
00014 Si7210::Si7210(PinName sda, PinName scl, uint8_t address)
00015 {
00016     _i2c = new I2C(sda, scl);
00017     _i2c->frequency(400000);
00018     _address = address;
00019     _ownI2C = true;
00020     
00021     // Initialize members
00022     _temperatureOffset = 0;
00023     _temperatureGain = 0;
00024     _rawTemperature = 0;
00025     _rawField = 0;
00026     _range = RANGE_20mT;
00027 }
00028 
00029 Si7210::Si7210(I2C *i2c_bus, uint8_t address)
00030 {
00031     _i2c = i2c_bus;
00032     _address = address;
00033     _ownI2C = false;
00034     
00035     // Initialize members
00036     _temperatureOffset = 0;
00037     _temperatureGain = 0;
00038     _rawTemperature = 0;
00039     _rawField = 0;
00040     _range = RANGE_20mT;
00041 }
00042 
00043 Si7210::~Si7210()
00044 {
00045     if (_ownI2C) {
00046         delete _i2c;
00047     }
00048 }
00049 
00050 int Si7210::getTemperature()
00051 {
00052     // we operate on 11 fractional bits.
00053     int offset;
00054     int64_t temperature;
00055     
00056     if (_temperatureOffset == 0 &&
00057         _temperatureGain == 0) {
00058         /* read out compensation values */
00059         writeRegister(SI72XX_OTP_ADDR, 0x1DU);
00060         writeRegister(SI72XX_OTP_CTRL, OTP_READ_EN_MASK);
00061         readRegister(SI72XX_OTP_DATA, (uint8_t*)&_temperatureOffset);
00062         
00063         writeRegister(SI72XX_OTP_ADDR, 0x1EU);
00064         writeRegister(SI72XX_OTP_CTRL, OTP_READ_EN_MASK);
00065         readRegister(SI72XX_OTP_DATA, (uint8_t*)&_temperatureGain);
00066     }
00067     
00068     temperature = ((int64_t)_rawTemperature * (int64_t)_rawTemperature) * (-21) / 10000;
00069     temperature += ((1522 * _rawTemperature) / 10);
00070     temperature -= 273000;
00071     
00072     
00073     // offset = val@0x1D / 16 = val@0x1D / 2048 * 128
00074     offset = (int32_t)_temperatureOffset * 1000 / 16;
00075     // gain = 1 + val@0x1E
00076     // temperature = raw * gain + offset
00077     temperature = temperature + (temperature * _temperatureGain / 2048) + offset;
00078     // return temperature
00079     return temperature;
00080 }
00081 
00082 /*
00083  * Get last measured field strength
00084  * return: int32_t = field strength in micro-Tesla.
00085  */
00086 int Si7210::getFieldStrength()
00087 {   
00088     switch(_range) {
00089         case RANGE_20mT:
00090             return (_rawField / 4) + _rawField; // rawField * 1.25
00091         case RANGE_200mT:
00092             return (_rawField * 12) + (_rawField / 2); //rawField * 12.5
00093         default:
00094             return 0;
00095     }
00096 }
00097 
00098 /*
00099  * Set measurement range.
00100  * Return true if successful, false if device is not responding.
00101  */
00102 bool Si7210::setFieldStrength(Si7210_range_t range)
00103 {
00104     _range = range;
00105 }
00106 
00107 /*
00108  * Perform measurement of magnetic field.
00109  * Return true if new data available
00110  */
00111 bool Si7210::fetchFieldStrength()
00112 {
00113     uint8_t temp = 0x04;
00114     readRegister(SI72XX_DSPSIGM, &temp);
00115     if(temp & 0x80) {
00116         /* Fresh data available */
00117         _rawField = 0;
00118         _rawField += (temp & 0x7FU) * 256;
00119         readRegister(SI72XX_DSPSIGL, &temp);
00120         _rawField += temp;
00121         _rawField -= 16384U;
00122         return true;
00123     }
00124     return false;
00125 }
00126 
00127 bool Si7210::measureOnce()
00128 {
00129     uint8_t temp;
00130     wakeup();
00131     readRegister(SI72XX_POWER_CTRL, &temp);
00132     temp = (temp & 0xF0) | 0xA; // Stop control loop
00133     writeRegister(SI72XX_POWER_CTRL, temp);
00134     
00135     if (_range == RANGE_200mT) {
00136         writeRegister(SI72XX_OTP_ADDR, 0x27U);
00137         writeRegister(SI72XX_OTP_CTRL, OTP_READ_EN_MASK);
00138         readRegister(SI72XX_OTP_DATA, &temp);
00139         writeRegister(SI72XX_A0, temp);
00140         writeRegister(SI72XX_OTP_ADDR, 0x28U);
00141         writeRegister(SI72XX_OTP_CTRL, OTP_READ_EN_MASK);
00142         readRegister(SI72XX_OTP_DATA, &temp);
00143         writeRegister(SI72XX_A1, temp);
00144         writeRegister(SI72XX_OTP_ADDR, 0x29U);
00145         writeRegister(SI72XX_OTP_CTRL, OTP_READ_EN_MASK);
00146         readRegister(SI72XX_OTP_DATA, &temp);
00147         writeRegister(SI72XX_A2, temp);
00148         writeRegister(SI72XX_OTP_ADDR, 0x2AU);
00149         writeRegister(SI72XX_OTP_CTRL, OTP_READ_EN_MASK);
00150         readRegister(SI72XX_OTP_DATA, &temp);
00151         writeRegister(SI72XX_A3, temp);
00152         writeRegister(SI72XX_OTP_ADDR, 0x2BU);
00153         writeRegister(SI72XX_OTP_CTRL, OTP_READ_EN_MASK);
00154         readRegister(SI72XX_OTP_DATA, &temp);
00155         writeRegister(SI72XX_A4, temp);
00156         writeRegister(SI72XX_OTP_ADDR, 0x2CU);
00157         writeRegister(SI72XX_OTP_CTRL, OTP_READ_EN_MASK);
00158         readRegister(SI72XX_OTP_DATA, &temp);
00159         writeRegister(SI72XX_A5, temp);
00160     }
00161     
00162     writeRegister(SI72XX_CTRL4, 0x44); // Use a burst of 4 samples
00163     temp = 0x4;
00164     writeRegister(SI72XX_DSPSIGSEL, temp); // Select field strength data
00165     
00166     readRegister(SI72XX_POWER_CTRL, &temp);
00167     temp = (temp & 0xF0) | 0x0C; // Start measurement
00168     writeRegister(SI72XX_POWER_CTRL, temp);
00169     
00170     do {
00171         readRegister(SI72XX_POWER_CTRL, &temp);
00172     } while ( (temp & 0x80) != 0 );
00173     
00174     fetchFieldStrength();
00175     
00176     writeRegister(SI72XX_CTRL4, 0x0); // Don't burst
00177     temp = 0x1;
00178     writeRegister(SI72XX_DSPSIGSEL, temp); // Select temperature data
00179     
00180     readRegister(SI72XX_POWER_CTRL, &temp);
00181     temp = (temp & 0xF0) | 0x0C; // Start measurement
00182     writeRegister(SI72XX_POWER_CTRL, temp);
00183     
00184     readRegister(SI72XX_DSPSIGM, &temp);
00185     _rawTemperature = 0;
00186     _rawTemperature += 32 * (temp & 0x7F);
00187     readRegister(SI72XX_DSPSIGL, &temp);
00188     _rawTemperature += (temp >> 3);
00189     
00190     sleep();
00191     return true;
00192 }
00193 
00194 bool Si7210::check()
00195 {
00196     uint8_t temp;
00197     wakeup();
00198     readRegister(SI72XX_HREVID, &temp);
00199     sleep();
00200     
00201     return true;
00202 }
00203 
00204 bool Si7210::wakeup()
00205 {
00206     uint8_t temp;
00207     if(_i2c->read(_address, (char*)&temp, 1) == 0) return true;
00208     return false;
00209 }
00210 
00211 bool Si7210::sleep()
00212 {
00213     uint8_t temp;
00214     readRegister(SI72XX_CTRL3, &temp);
00215     temp &= 0xFEU; // Clear sltimena
00216     writeRegister(SI72XX_CTRL3, temp);
00217     readRegister(SI72XX_POWER_CTRL, &temp);
00218     temp = (temp & 0xF8U) | 0x01; // clear STOP and set SLEEP
00219     return writeRegister(SI72XX_POWER_CTRL, temp);
00220 }
00221 
00222 bool Si7210::readRegister(uint8_t reg, uint8_t *result)
00223 {
00224     _i2c->write(_address, (const char*)&reg, 1, true);
00225     return _i2c->read(_address, (char*)result, 1) == 0;
00226 }
00227 
00228 bool Si7210::writeRegister(uint8_t reg, uint8_t data)
00229 {
00230     uint8_t buffer[2] = {reg, data};
00231     return _i2c->write(_address, (const char*)buffer, 2) == 0;
00232 }
00233 
00234 } // namespace silabs