/* measurement needs to be stopped before sending commands */ if (cmd != CMD_SET_AMB_PRESSURE) {
ret = scd4x_send_command(state, CMD_STOP_MEAS); if (ret) return ret;
}
/* execution time */
msleep_interruptible(500);
ret = scd4x_i2c_xfer(state, buf, SCD4X_WRITE_BUF_SIZE, buf, 0); if (ret) return ret;
/* start measurement, except for forced calibration command */ if ((cmd != CMD_FRC) && (cmd != CMD_SET_AMB_PRESSURE)) {
ret = scd4x_send_command(state, CMD_START_MEAS); if (ret) return ret;
}
return0;
}
staticint scd4x_write_and_fetch(struct scd4x_state *state, enum scd4x_cmd cmd,
uint16_t arg, void *response, int response_sz)
{ struct i2c_client *client = state->client; char buf[SCD4X_READ_BUF_SIZE]; char *rsp = response; int i, ret; char crc;
ret = scd4x_write(state, CMD_FRC, arg); if (ret) goto err;
/* execution time */
msleep_interruptible(400);
/* CRC byte for every 2 bytes of data */
response_sz += response_sz / 2;
ret = i2c_master_recv(client, buf, response_sz); if (ret < 0) goto err; if (ret != response_sz) {
ret = -EIO; goto err;
}
for (i = 0; i < response_sz; i += 3) {
crc = crc8(scd4x_crc8_table, buf + i, 2, CRC8_INIT_VALUE); if (crc != buf[i + 2]) {
dev_err(&client->dev, "CRC error\n");
ret = -EIO; goto err;
}
staticint scd4x_read_meas(struct scd4x_state *state, uint16_t *meas)
{ int i, ret;
__be16 buf[3];
ret = scd4x_read(state, CMD_READ_MEAS, buf, sizeof(buf)); if (ret) return ret;
for (i = 0; i < ARRAY_SIZE(buf); i++)
meas[i] = be16_to_cpu(buf[i]);
return0;
}
staticint scd4x_wait_meas_poll(struct scd4x_state *state)
{ struct i2c_client *client = state->client; int tries = 6; int ret;
do {
__be16 bval;
uint16_t val;
ret = scd4x_read(state, CMD_GET_DATA_READY, &bval, sizeof(bval)); if (ret) return -EIO;
val = be16_to_cpu(bval);
/* new measurement available */ if (val & 0x7FF) return0;
msleep_interruptible(1000);
} while (--tries);
/* try to start sensor on timeout */
ret = scd4x_send_command(state, CMD_START_MEAS); if (ret)
dev_err(&client->dev, "failed to start measurement: %d\n", ret);
return -ETIMEDOUT;
}
staticint scd4x_read_poll(struct scd4x_state *state, uint16_t *buf)
{ int ret;
ret = scd4x_wait_meas_poll(state); if (ret) return ret;
return scd4x_read_meas(state, buf);
}
staticint scd4x_read_channel(struct scd4x_state *state, int chan)
{ int ret;
uint16_t buf[3];
ret = scd4x_read_poll(state, buf); if (ret) return ret;
return buf[chan];
}
staticint scd4x_read_raw(struct iio_dev *indio_dev, struct iio_chan_spec const *chan, int *val, int *val2, long mask)
{ struct scd4x_state *state = iio_priv(indio_dev); int ret;
__be16 tmp;
switch (mask) { case IIO_CHAN_INFO_RAW: if (chan->output) {
mutex_lock(&state->lock);
ret = scd4x_read(state, CMD_GET_AMB_PRESSURE, &tmp, sizeof(tmp));
mutex_unlock(&state->lock);
if (ret) return ret;
*val = be16_to_cpu(tmp); return IIO_VAL_INT;
}
if (!iio_device_claim_direct(indio_dev)) return -EBUSY;
mutex_lock(&state->lock);
ret = scd4x_read_channel(state, chan->address);
mutex_unlock(&state->lock);
iio_device_release_direct(indio_dev); if (ret < 0) return ret;
staticint scd4x_read_avail(struct iio_dev *indio_dev, struct iio_chan_spec const *chan, constint **vals, int *type, int *length, long mask)
{ switch (mask) { case IIO_CHAN_INFO_RAW:
*vals = scd4x_pressure_calibbias_available;
*type = IIO_VAL_INT;
return IIO_AVAIL_RANGE;
}
return -EINVAL;
}
staticint scd4x_write_raw(struct iio_dev *indio_dev, struct iio_chan_spec const *chan, int val, int val2, long mask)
{ struct scd4x_state *state = iio_priv(indio_dev); int ret = 0;
switch (mask) { case IIO_CHAN_INFO_CALIBBIAS:
mutex_lock(&state->lock);
ret = scd4x_write(state, CMD_SET_TEMP_OFFSET, val);
mutex_unlock(&state->lock);
return ret; case IIO_CHAN_INFO_RAW: switch (chan->type) { case IIO_PRESSURE: if (val < SCD4X_PRESSURE_COMP_MIN_MBAR ||
val > SCD4X_PRESSURE_COMP_MAX_MBAR) return -EINVAL;
mutex_lock(&state->lock);
ret = scd4x_write(state, CMD_SET_AMB_PRESSURE, val);
mutex_unlock(&state->lock);
mutex_lock(&state->lock);
ret = scd4x_write(state, CMD_SET_ASC, value);
mutex_unlock(&state->lock); if (ret)
dev_err(dev, "failed to set automatic calibration");
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.