JDI_MIP on ThunderBoardSense2(Silicon-Labs)

JDI_MIP (LPM013M126A) Sample on ThunderBoard2(Silicon-Labs)

/media/uploads/STakayama/mip8_tb2_sample0_.jpg LPM013M126A /media/uploads/STakayama/mip8_tb2_sample1.jpg

Links

https://os.mbed.com/teams/JapanDisplayInc/

https://os.mbed.com/teams/JapanDisplayInc/wiki/MIP-reflective-color-display

Si7210/Si7210.cpp

Committer:
STakayama
Date:
2019-01-22
Revision:
13:9fb661dd4b2a
Parent:
10:525bcf8907fc

File content as of revision 13:9fb661dd4b2a:

#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*)&reg, 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