/* * Sensor does not support repeated start so instead of * sending two i2c messages in a row we just send one by one.
*/
ret = i2c_master_send(client, txbuf, txsize); if (ret < 0) return ret; if (ret != txsize) return -EIO;
if (!rxsize) return 0;
ret = i2c_master_recv(client, rxbuf, rxsize); if (ret < 0) return ret; if (ret != rxsize) return -EIO;
return 0;
}
staticint sps30_i2c_command(struct sps30_state *state, u16 cmd, void *arg, size_t arg_size, void *rsp, size_t rsp_size)
{ /* * Internally sensor stores measurements in a following manner: * * PM1: upper two bytes, crc8, lower two bytes, crc8 * PM2P5: upper two bytes, crc8, lower two bytes, crc8 * PM4: upper two bytes, crc8, lower two bytes, crc8 * PM10: upper two bytes, crc8, lower two bytes, crc8 * * What follows next are number concentration measurements and * typical particle size measurement which we omit.
*/ unsignedchar buf[SPS30_I2C_MAX_BUF_SIZE]; unsignedchar *tmp; unsignedchar crc;
size_t i; int ret;
put_unaligned_be16(cmd, buf);
i = 2;
if (rsp) { /* each two bytes are followed by a crc8 */
rsp_size += rsp_size / 2;
} else {
tmp = arg;
while (arg_size) {
buf[i] = *tmp++;
buf[i + 1] = *tmp++;
buf[i + 2] = crc8(sps30_i2c_crc8_table, buf + i, 2, CRC8_INIT_VALUE);
arg_size -= 2;
i += 3;
}
}
ret = sps30_i2c_xfer(state, buf, i, buf, rsp_size); if (ret) return ret;
/* validate received data and strip off crc bytes */
tmp = rsp; for (i = 0; i < rsp_size; i += 3) {
crc = crc8(sps30_i2c_crc8_table, buf + i, 2, CRC8_INIT_VALUE); if (crc != buf[i + 2]) {
dev_err(state->dev, "data integrity check failed\n"); return -EIO;
}
*tmp++ = buf[i];
*tmp++ = buf[i + 1];
}
return 0;
}
staticint sps30_i2c_start_meas(struct sps30_state *state)
{ /* request BE IEEE754 formatted data */ unsignedchar buf[] = { 0x03, 0x00 };
staticint sps30_i2c_reset(struct sps30_state *state)
{ int ret;
ret = sps30_i2c_command(state, SPS30_I2C_RESET, NULL, 0, NULL, 0);
msleep(500); /* * Power-on-reset causes sensor to produce some glitch on i2c bus and * some controllers end up in error state. Recover simply by placing * some data on the bus, for example STOP_MEAS command, which * is NOP in this case.
*/
sps30_i2c_stop_meas(state);
return ret;
}
staticbool sps30_i2c_meas_ready(struct sps30_state *state)
{ unsignedchar buf[2]; int ret;
ret = sps30_i2c_command(state, SPS30_I2C_MEAS_READY, NULL, 0, buf, sizeof(buf)); if (ret) returnfalse;
return buf[1];
}
staticint sps30_i2c_read_meas(struct sps30_state *state, __be32 *meas, size_t num)
{ /* measurements are ready within a second */ if (msleep_interruptible(1000)) return -EINTR;
if (!sps30_i2c_meas_ready(state)) return -ETIMEDOUT;
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.