diff --git a/drivers/sensor/ccs811/ccs811.c b/drivers/sensor/ccs811/ccs811.c index c878ba62a88..0b54b7a83a5 100644 --- a/drivers/sensor/ccs811/ccs811.c +++ b/drivers/sensor/ccs811/ccs811.c @@ -70,6 +70,13 @@ static inline u8_t error_from_status(int status) return status >> 8; } +const struct ccs811_result_type *ccs811_result(struct device *dev) +{ + struct ccs811_data *drv_data = dev->driver_data; + + return &drv_data->result; +} + int ccs811_baseline_fetch(struct device *dev) { const u8_t cmd = CCS811_REG_BASELINE; @@ -176,55 +183,30 @@ int ccs811_envdata_update(struct device *dev, static int ccs811_sample_fetch(struct device *dev, enum sensor_channel chan) { struct ccs811_data *drv_data = dev->driver_data; + struct ccs811_result_type *rp = &drv_data->result; + const u8_t cmd = CCS811_REG_ALG_RESULT_DATA; int rc; - int tries; u16_t buf[4]; - int status; + unsigned int status; - /* Check data ready flag for the measurement interval */ -#ifdef CONFIG_CCS811_DRIVE_MODE_1 - tries = 11; -#elif defined(CONFIG_CCS811_DRIVE_MODE_2) - tries = 101; -#elif defined(CONFIG_CCS811_DRIVE_MODE_3) - tries = 601; -#endif - - do { - const u8_t cmd = CCS811_REG_ALG_RESULT_DATA; - - set_wake(drv_data, true); - rc = i2c_write_read(drv_data->i2c, DT_INST_0_AMS_CCS811_BASE_ADDRESS, - &cmd, sizeof(cmd), - (u8_t *)buf, sizeof(buf)); - - set_wake(drv_data, false); - if (rc < 0) { - return -EIO; - } - - status = buf[2]; - if (status & CCS811_STATUS_ERROR) { - LOG_ERR("CCS811 ERROR ID %02x", - error_from_status(status)); - return -EIO; - } - - if (status & CCS811_STATUS_DATA_READY) { - break; - } - - k_sleep(K_MSEC(100)); - } while (--tries > 0); - if (!(status & CCS811_STATUS_DATA_READY)) { + set_wake(drv_data, true); + rc = i2c_write_read(drv_data->i2c, DT_INST_0_AMS_CCS811_BASE_ADDRESS, + &cmd, sizeof(cmd), + (u8_t *)buf, sizeof(buf)); + set_wake(drv_data, false); + if (rc < 0) { return -EIO; } - drv_data->co2 = sys_be16_to_cpu(buf[0]); - drv_data->voc = sys_be16_to_cpu(buf[1]); - drv_data->status = status; - drv_data->error = error_from_status(status); - drv_data->raw = sys_be16_to_cpu(buf[3]); - return 0; + + rp->co2 = sys_be16_to_cpu(buf[0]); + rp->voc = sys_be16_to_cpu(buf[1]); + status = sys_le16_to_cpu(buf[2]); /* sic */ + rp->status = status; + rp->error = error_from_status(status); + rp->raw = sys_be16_to_cpu(buf[3]); + + /* @todo APP FW 1.1 may not set DATA_READY. */ + return (rp->status & CCS811_STATUS_DATA_READY) ? 0 : -EAGAIN; } static int ccs811_channel_get(struct device *dev, @@ -232,16 +214,17 @@ static int ccs811_channel_get(struct device *dev, struct sensor_value *val) { struct ccs811_data *drv_data = dev->driver_data; + const struct ccs811_result_type *rp = &drv_data->result; u32_t uval; switch (chan) { case SENSOR_CHAN_CO2: - val->val1 = drv_data->co2; + val->val1 = rp->co2; val->val2 = 0; break; case SENSOR_CHAN_VOC: - val->val1 = drv_data->voc; + val->val1 = rp->voc; val->val2 = 0; break; @@ -249,7 +232,7 @@ static int ccs811_channel_get(struct device *dev, /* * Raw ADC readings are contained in least significant 10 bits */ - uval = ((drv_data->raw & CCS811_RAW_VOLTAGE_MSK) + uval = ((rp->raw & CCS811_RAW_VOLTAGE_MSK) >> CCS811_RAW_VOLTAGE_POS) * CCS811_RAW_VOLTAGE_SCALE; val->val1 = uval / 1000000U; val->val2 = uval % 1000000; @@ -260,7 +243,7 @@ static int ccs811_channel_get(struct device *dev, * Current readings are contained in most * significant 6 bits in microAmps */ - uval = ((drv_data->raw & CCS811_RAW_CURRENT_MSK) + uval = ((rp->raw & CCS811_RAW_CURRENT_MSK) >> CCS811_RAW_CURRENT_POS) * CCS811_RAW_CURRENT_SCALE; val->val1 = uval / 1000000U; val->val2 = uval % 1000000; diff --git a/drivers/sensor/ccs811/ccs811.h b/drivers/sensor/ccs811/ccs811.h index 486cff71915..c8618d11dc4 100644 --- a/drivers/sensor/ccs811/ccs811.h +++ b/drivers/sensor/ccs811/ccs811.h @@ -11,6 +11,7 @@ #include #include #include +#include /* Registers */ #define CCS811_REG_STATUS 0x00 @@ -29,17 +30,7 @@ #define CCS881_HW_ID 0x81 #define CCS811_HW_VERSION 0x10 -/* Status register fields */ -#define CCS811_STATUS_ERROR BIT(0) -#define CCS811_STATUS_DATA_READY BIT(3) -#define CCS811_STATUS_APP_VALID BIT(4) -#define CCS811_STATUS_FW_MODE BIT(7) - /* Measurement modes */ -#define CCS811_MODE_IDLE 0x00 -#define CCS811_MODE_IAQ_1SEC 0x10 -#define CCS811_MODE_IAQ_10SEC 0x20 -#define CCS811_MODE_IAQ_60SEC 0x30 #define CCS811_MODE_RAW_DATA 0x40 #define CCS811_MODE_DATARDY 0x08 #define CCS811_MODE_THRESH 0x04 @@ -85,11 +76,7 @@ struct ccs811_data { #ifdef DT_INST_0_AMS_CCS811_WAKE_GPIOS_CONTROLLER struct device *wake_gpio; #endif - u16_t co2; - u16_t voc; - u16_t raw; - u8_t status; - u8_t error; + struct ccs811_result_type result; u8_t mode; }; diff --git a/include/drivers/sensor/ccs811.h b/include/drivers/sensor/ccs811.h index 47e4074c957..65617529895 100644 --- a/include/drivers/sensor/ccs811.h +++ b/include/drivers/sensor/ccs811.h @@ -22,6 +22,65 @@ extern "C" { #include #include +/* Status register fields */ +#define CCS811_STATUS_ERROR BIT(0) +#define CCS811_STATUS_DATA_READY BIT(3) +#define CCS811_STATUS_APP_VALID BIT(4) +#define CCS811_STATUS_FW_MODE BIT(7) + +/* Error register fields */ +#define CCS811_ERROR_WRITE_REG_INVALID BIT(0) +#define CCS811_ERROR_READ_REG_INVALID BIT(1) +#define CCS811_ERROR_MEASMODE_INVALID BIT(2) +#define CCS811_ERROR_MAX_RESISTANCE BIT(3) +#define CCS811_ERROR_HEATER_FAULT BIT(4) +#define CCS811_ERROR_HEATER_SUPPLY BIT(5) + +/* Measurement mode constants */ +#define CCS811_MODE_IDLE 0x00 +#define CCS811_MODE_IAQ_1SEC 0x10 +#define CCS811_MODE_IAQ_10SEC 0x20 +#define CCS811_MODE_IAQ_60SEC 0x30 +#define CCS811_MODE_IAQ_RAW_250MSEC 0x40 + +/** @brief Information collected from the sensor on each fetch. */ +struct ccs811_result_type { + /** Equivalent carbon dioxide in parts-per-million volume (ppmv). */ + u16_t co2; + + /** + * Equivalent total volatile organic compounts in + * parts-per-billion volume. + */ + u16_t voc; + + /** Raw voltage and current measured by sensor. */ + u16_t raw; + + /** Sensor status at completion of most recent fetch. */ + u8_t status; + + /** + * Sensor error flags at completion of most recent fetch. + * + * Note that errors are cleared when read. + */ + u8_t error; +}; + +/** + * @brief Access storage for the most recent data read from the sensor. + * + * This content of the object referenced is updated by + * sensor_fetch_sample(), except for ccs811_result_type::mode which is + * set on driver initialization. + * + * @param dev Pointer to the sensor device + * + * @return a pointer to the result information. + */ +const struct ccs811_result_type *ccs811_result(struct device *dev); + /** * @brief Fetch the current value of the BASELINE register. *