library for AMS ENS210 temperature and humidity sensor

Dependents:   rIoTwear-temp-humid

AMS_ENS210.cpp

Committer:
UHSLMarcus
Date:
2017-01-17
Revision:
0:7088b1bdc2e5
Child:
1:94a79c88c105

File content as of revision 0:7088b1bdc2e5:


#include "AMS_ENS201.h"

AMS_ENS210::AMS_ENS210(I2C * i2c) : 
    _temp_mode(CONFIG_TEMP_OP_MODE), 
    _humid_mode(CONFIG_HUMID_OP_MODE), 
    _power_mode(CONFIG_POWER_MODE),
    _reset(0) 
{ 
    _i2c = i2c;
}

AMS_ENS210::AMS_ENS210(I2C * i2c, bool temp_single_shot, bool humid_single_shot) : 
    _temp_mode(temp_single_shot), 
    _humid_mode(humid_single_shot), 
    _power_mode(CONFIG_POWER_MODE),
    _reset(0)  
{ 
    _i2c = i2c;
}

AMS_ENS210::AMS_ENS210(I2C * i2c, bool temp_single_shot, bool humid_single_shot, bool low_power) : 
    _temp_mode(temp_single_shot), 
    _humid_mode(humid_single_shot), 
    _power_mode(low_power),
    _reset(0) 
{
    _i2c = i2c;
}

AMS_ENS210::AMS_ENS210() {}

bool AMS_ENS210::init() {
    
    return write_config();
     
}

bool AMS_ENS210::reset() {
    
    _reset = true;
    bool success = write_config(true, false);
    _reset = false;
    
    return success;
    
}

bool AMS_ENS210::power_mode(bool low_power) {
    _power_mode = low_power;
    write_config(true, false);
}

bool AMS_ENS210::power_mode() {
    return read_config(true, false)[0] & 1; // just mask bit 0
}

bool AMS_ENS210::temp_mode(bool single_shot) {
    _temp_mode = single_shot;
    write_config(false, true);
}

bool AMS_ENS210::temp_mode() {
    return read_config(false, true)[0] & 1; // just mask bit 0
}

bool AMS_ENS210::humid_mode(bool single_shot) {
    _humid_mode = single_shot;
    write_config(false, true);
}

bool AMS_ENS210::humid_mode() {
    return read_config(false, true)[0] & 0b10; // just mask bit 1
}

void AMS_ENS210::i2c_interface(I2C * i2c) {
    _i2c = i2c;
}

bool AMS_ENS210::start(bool temp, bool humid) {
    char cmd[2] = {SENS_START, 0 | temp | (humid << 1)}
    return _i2c->write(SLAVE_ADDR, cmd, 2) == 2;
}

bool AMS_ENS210::stop(bool temp, bool humid) {
    char cmd[2] = {SENS_STOP, 0 | temp | (humid << 1)}
    return _i2c->write(SLAVE_ADDR, cmd, 2) == 2;
}

bool AMS_ENS210::temp_is_measuring() {
    char[1] output;
    i2c_read(SENS_STATUS, output, 1);
    return output[0] & 1;          
}
        
bool AMS_ENS210::humid_is _measuring() {
    char[1] output;
    i2c_read(SENS_STATUS, output, 1);
    return output[0] >> 1 & 1;  
}

bool AMS_ENS210::temp_has_data() {
    if (temp_mode()) {                                  // when in single shot mode make sure sensor has started first
        if (!temp_is_measuring())                       
            start(true, false);                         // set start bit if sensor is idle
    }
    
    char output[3];
    i2c_read(SENS_TEMP, output, 3);
    
    // do crc7
                                                        // Store read data to avoid reading from I2C again
    temp_reading = 0 | output[0] | (output[1] << 8);    // bytes 1 and 2 make the 16 bit data
    
    return output[3] & 1;                               // bit 0 of byte 3 is the valid flag
}

bool AMS_ENS210::humid_has_data() {
    if (humid_mode()) {                                 // when in single shot mode make sure sensor has started first                                                   
        if (!humid_is_measuring())                      
            start(false, true);                         // set start bit if sensor is idle
    }
    
    char output[3];
    i2c_read(SENS_HUMID, output, 3);
    
    // do crc7
                                                        // Store read data to avoid reading from I2C again
    temp_reading = 0 | output[0] | (output[1] << 8);    // bytes 1 and 2 make the 16 bit data
    
    return output[3] & 1;                               // bit 0 of byte 3 is the valid flag
}

uint16_t AMS_ENS210::temp_read() {
    
    uint16_t reading = 0;
    
    if (temp_mode()) {                                      // when in single shot mode, data is read and saved in temp_has_data()
        reading = temp_reading;
    } else {
        char output[3];
        i2c_read(SENS_TEMP, output, 3);
        
        // do crc7
        if (output[3] & 1)                                  // bit 0 of byte 3 is the valid flag
            reading = 0 | output[0] | (output[1] << 8);     // bytes 1 and 2 make the 16 bit data
    }
    
    return reading;
}

uint16_t AMS_ENS210::humid_read() {
    uint16_t reading = 0;
    
    if (humid_mode()) {                                     // when in single shot mode, data is read and saved in humid_has_data()
        reading = humid_reading;
    } else {
        char output[3];
        i2c_read(SENS_HUMID, output, 3);
        
        // do crc7
        if (output[3] & 1)                                  // bit 0 of byte 3 is the valid flag
            reading = 0 | output[0] | (output[1] << 8);     // bytes 1 and 2 make the 16 bit data
    }
    
    return reading;
}

/*** Private ***/

bool AMS_ENS210::write_config(bool system, bool sensor) {
    int w_bytes = 0;
    char cmd[2];
    
    if (system) {
        cmd[0] = SYS_CONFIG;
        cmd[1] = 0 | _power_mode | _reset << 7; // bit 0 of SYS_CTRL is power mode, bit 7 is reset
        w_bytes += _i2c->write(SLAVE_ADDR, cmd, 2);
    }
    
    if (sensor) {
        cmd[0] = SENS_OP_MODE;
        cmd[1] = 0 | _temp_mode | (_humid_mode << 1); // bit 0 is temp mode, bit 1 is humid mode
        w_bytes += _i2c->write(SLAVE_ADDR, cmd, 2);
    }
    
    return w_bytes == (system + sensor)*2; // add error reporting/handling later...
}

const char *AMS_ENS210::read_config(bool system, bool sensor) {
    
    static char output[2];
    
    if (system)
        i2c_read(SYS_CONFIG, output, 1);
    
    if (sensor)
        i2c_read(SYS_CONFIG, output+system, 1);
    
    return output;
        
}

int AMS_ENS210::i2c_read(char reg_addr, char* output, int len) {
    
    int read_count = 0;
    
    _i2c->start();                                          // send start condition for write
    if(_i2c->write(SLAVE_ADDR_W) == 1) {                    // write slave address
        if(_i2c->write(reg_addr) == 1) {                    // write register address
            _i2c->start();                                  // send another start condition for read
            for (int i = 0; < len) {                        // read len bytes
                output[i] = _i2c->read(i < len-1 ? 1 : 0);  // ack all reads aside from the final one (i == len-1)
                read_count++;
            }
        }
    }
    _i2c->stop();                                           // send stop condition 
    
    return read_count;
}