/* Start single shot measurement */
ret = vl6180_write_byte(client,
vl6180_chan_regs_table[addr].start_reg, VL6180_STARTSTOP); if (ret < 0) goto fail;
if (client->irq) {
time_left = wait_for_completion_timeout(&data->completion, HZ / 10); if (time_left == 0) {
ret = -ETIMEDOUT; goto fail;
}
} else { while (tries--) {
ret = vl6180_read_byte(client, VL6180_INTR_STATUS); if (ret < 0) goto fail;
if (ret & vl6180_chan_regs_table[addr].drdy_mask) break;
msleep(20);
}
if (tries < 0) {
ret = -EIO; goto fail;
}
}
/* Read result value from appropriate registers */
ret = vl6180_chan_regs_table[addr].word ?
vl6180_read_word(client, vl6180_chan_regs_table[addr].value_reg) :
vl6180_read_byte(client, vl6180_chan_regs_table[addr].value_reg); if (ret < 0) goto fail;
value = ret;
/* Clear the interrupt flag after data read */
ret = vl6180_write_byte(client, VL6180_INTR_CLEAR,
VL6180_CLEAR_ERROR | VL6180_CLEAR_ALS | VL6180_CLEAR_RANGE); if (ret < 0) goto fail;
/* * Available Ambient Light Sensor gain settings, 1/1000th, and * corresponding setting for the VL6180_ALS_GAIN register
*/ staticconstint vl6180_als_gain_tab[8] = {
1000, 1250, 1670, 2500, 5000, 10000, 20000, 40000
}; staticconst u8 vl6180_als_gain_tab_bits[8] = {
VL6180_ALS_GAIN_1, VL6180_ALS_GAIN_1_25,
VL6180_ALS_GAIN_1_67, VL6180_ALS_GAIN_2_5,
VL6180_ALS_GAIN_5, VL6180_ALS_GAIN_10,
VL6180_ALS_GAIN_20, VL6180_ALS_GAIN_40
};
staticint vl6180_read_raw(struct iio_dev *indio_dev, struct iio_chan_spec const *chan, int *val, int *val2, long mask)
{ struct vl6180_data *data = iio_priv(indio_dev); int ret;
switch (mask) { case IIO_CHAN_INFO_RAW:
ret = vl6180_measure(data, chan->address); if (ret < 0) return ret;
*val = ret;
return IIO_VAL_INT; case IIO_CHAN_INFO_INT_TIME:
*val = data->als_it_ms;
*val2 = 1000;
return IIO_VAL_FRACTIONAL;
case IIO_CHAN_INFO_SCALE: switch (chan->type) { case IIO_LIGHT: /* one ALS count is 0.32 Lux @ gain 1, IT 100 ms */
*val = 32000; /* 0.32 * 1000 * 100 */
*val2 = data->als_gain_milli * data->als_it_ms;
return IIO_VAL_FRACTIONAL;
case IIO_DISTANCE:
*val = 0; /* sensor reports mm, scale to meter */
*val2 = 1000; break; default: return -EINVAL;
}
return IIO_VAL_INT_PLUS_MICRO; case IIO_CHAN_INFO_HARDWAREGAIN:
*val = data->als_gain_milli;
*val2 = 1000;
return IIO_VAL_FRACTIONAL;
case IIO_CHAN_INFO_SAMP_FREQ: switch (chan->type) { case IIO_DISTANCE:
*val = data->range_meas_rate; return IIO_VAL_INT; case IIO_LIGHT:
*val = data->als_meas_rate; return IIO_VAL_INT; default: return -EINVAL;
}
iio_for_each_active_channel(indio_dev, bit) { if (vl6180_chan_regs_table[bit].word)
ret = vl6180_read_word(data->client,
vl6180_chan_regs_table[bit].value_reg); else
ret = vl6180_read_byte(data->client,
vl6180_chan_regs_table[bit].value_reg);
if (ret < 0) {
dev_err(&data->client->dev, "failed to read from value regs: %d\n", ret); return IRQ_HANDLED;
}
/* Clear the interrupt flag after data read */
ret = vl6180_write_byte(data->client, VL6180_INTR_CLEAR,
VL6180_CLEAR_ERROR | VL6180_CLEAR_ALS | VL6180_CLEAR_RANGE); if (ret < 0)
dev_err(&data->client->dev, "failed to clear irq: %d\n", ret);
ret = vl6180_read_byte(client, VL6180_MODEL_ID); if (ret < 0) return ret;
if (ret != VL6180_MODEL_ID_VAL) {
dev_err(&client->dev, "invalid model ID %02x\n", ret); return -ENODEV;
}
ret = vl6180_hold(data, true); if (ret < 0) return ret;
ret = vl6180_read_byte(client, VL6180_OUT_OF_RESET); if (ret < 0) return ret;
/* * Detect false reset condition here. This bit is always set when the * system comes out of reset.
*/ if (ret != 0x01)
dev_info(&client->dev, "device is not fresh out of reset\n");
/* Enable ALS and Range ready interrupts */
ret = vl6180_write_byte(client, VL6180_INTR_CONFIG,
VL6180_ALS_READY | VL6180_RANGE_READY); if (ret < 0) return ret;
ret = devm_iio_triggered_buffer_setup(&client->dev, indio_dev, NULL,
&vl6180_trigger_handler,
&iio_triggered_buffer_setup_ops); if (ret) return ret;
/* Default Range inter-measurement time: 50ms or 20000 mHz */
ret = vl6180_write_byte(client, VL6180_RANGE_INTER_MEAS_TIME,
vl6180_meas_reg_val_from_mhz(20000)); if (ret < 0) return ret;
data->range_meas_rate = 20000;
/* Default ALS inter-measurement time: 10ms or 100000 mHz */
ret = vl6180_write_byte(client, VL6180_ALS_INTER_MEAS_TIME,
vl6180_meas_reg_val_from_mhz(100000)); if (ret < 0) return ret;
data->als_meas_rate = 100000;
/* ALS integration time: 100ms */
data->als_it_ms = 100;
ret = vl6180_write_word(client, VL6180_ALS_IT, VL6180_ALS_IT_100); if (ret < 0) return ret;
/* ALS gain: 1 */
data->als_gain_milli = 1000;
ret = vl6180_write_byte(client, VL6180_ALS_GAIN, VL6180_ALS_GAIN_1); if (ret < 0) return ret;
ret = vl6180_write_byte(client, VL6180_OUT_OF_RESET, 0x00); if (ret < 0) return ret;
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.