drivers: sensor: ccs811: rework data fetch to prepare for non-polled use
The original implementation relied on the DATA_READY bit of the STATUS register to indicate when a reading was available. This bit remains clear for the first several readings produced by the CCS811. When INT_DATARDY is set in MEAS_MODE the nINT signal will remain asserted until ALG_RESULT_DATA is read. If this is treated as a LEVEL signal, which is the common case in Zephyr, gating the read of ALG_RESULT_DATA on DATA_READY means the signal will never be cleared, and the interrupt callback will be repeated immediately. Since the STATUS register value is part of the ALG_RESULT_DATA block just read the whole thing, and provide its content to the user only if the DATA_READY bit is set. Signed-off-by: Peter A. Bigot <pab@pabigot.com>
This commit is contained in:
parent
21e68d4b81
commit
29c5f30ed2
1 changed files with 19 additions and 29 deletions
|
@ -73,11 +73,10 @@ static inline u8_t error_from_status(int status)
|
||||||
static int ccs811_sample_fetch(struct device *dev, enum sensor_channel chan)
|
static int ccs811_sample_fetch(struct device *dev, enum sensor_channel chan)
|
||||||
{
|
{
|
||||||
struct ccs811_data *drv_data = dev->driver_data;
|
struct ccs811_data *drv_data = dev->driver_data;
|
||||||
|
int rc;
|
||||||
int tries;
|
int tries;
|
||||||
u16_t buf[4];
|
u16_t buf[4];
|
||||||
u8_t cmd;
|
|
||||||
int status;
|
int status;
|
||||||
int rv = -EIO;
|
|
||||||
|
|
||||||
/* Check data ready flag for the measurement interval */
|
/* Check data ready flag for the measurement interval */
|
||||||
#ifdef CONFIG_CCS811_DRIVE_MODE_1
|
#ifdef CONFIG_CCS811_DRIVE_MODE_1
|
||||||
|
@ -88,50 +87,41 @@ static int ccs811_sample_fetch(struct device *dev, enum sensor_channel chan)
|
||||||
tries = 601;
|
tries = 601;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
while (tries-- > 0) {
|
do {
|
||||||
|
const u8_t cmd = CCS811_REG_ALG_RESULT_DATA;
|
||||||
|
|
||||||
set_wake(drv_data, true);
|
set_wake(drv_data, true);
|
||||||
status = fetch_status(drv_data->i2c);
|
rc = i2c_write_read(drv_data->i2c, DT_INST_0_AMS_CCS811_BASE_ADDRESS,
|
||||||
if (status < 0) {
|
&cmd, sizeof(cmd),
|
||||||
goto out;
|
(u8_t *)buf, sizeof(buf));
|
||||||
|
|
||||||
|
set_wake(drv_data, false);
|
||||||
|
if (rc < 0) {
|
||||||
|
return -EIO;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
status = buf[2];
|
||||||
if (status & CCS811_STATUS_ERROR) {
|
if (status & CCS811_STATUS_ERROR) {
|
||||||
LOG_ERR("CCS811 ERROR ID %02x",
|
LOG_ERR("CCS811 ERROR ID %02x",
|
||||||
error_from_status(status));
|
error_from_status(status));
|
||||||
goto out;
|
return -EIO;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((status & CCS811_STATUS_DATA_READY) || tries == 0) {
|
if (status & CCS811_STATUS_DATA_READY) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
set_wake(drv_data, false);
|
|
||||||
k_sleep(K_MSEC(100));
|
k_sleep(K_MSEC(100));
|
||||||
}
|
} while (--tries > 0);
|
||||||
|
|
||||||
if (!(status & CCS811_STATUS_DATA_READY)) {
|
if (!(status & CCS811_STATUS_DATA_READY)) {
|
||||||
LOG_ERR("Sensor data not available");
|
return -EIO;
|
||||||
goto out;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
cmd = CCS811_REG_ALG_RESULT_DATA;
|
|
||||||
if (i2c_write_read(drv_data->i2c, DT_INST_0_AMS_CCS811_BASE_ADDRESS,
|
|
||||||
&cmd, sizeof(cmd),
|
|
||||||
(u8_t *)buf, 8) < 0) {
|
|
||||||
LOG_ERR("Failed to read conversion data.");
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
|
|
||||||
drv_data->co2 = sys_be16_to_cpu(buf[0]);
|
drv_data->co2 = sys_be16_to_cpu(buf[0]);
|
||||||
drv_data->voc = sys_be16_to_cpu(buf[1]);
|
drv_data->voc = sys_be16_to_cpu(buf[1]);
|
||||||
drv_data->status = buf[2] & 0xff;
|
drv_data->status = status;
|
||||||
drv_data->error = buf[2] >> 8;
|
drv_data->error = error_from_status(status);
|
||||||
drv_data->resistance = sys_be16_to_cpu(buf[3]);
|
drv_data->resistance = sys_be16_to_cpu(buf[3]);
|
||||||
rv = 0;
|
return 0;
|
||||||
|
|
||||||
out:
|
|
||||||
set_wake(drv_data, false);
|
|
||||||
return rv;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int ccs811_channel_get(struct device *dev,
|
static int ccs811_channel_get(struct device *dev,
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue