From 812c2316cee4304ac40d005be6dc2553815c38ae Mon Sep 17 00:00:00 2001 From: Luis Ubieda Date: Tue, 31 Dec 2024 17:25:10 -0500 Subject: [PATCH 1/4] sensor: adxl345: Add get_size_info API Used by the sensor-shell in order to retrieve values, otherwise it crashes. Signed-off-by: Luis Ubieda --- drivers/sensor/adi/adxl345/adxl345_decoder.c | 23 ++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/drivers/sensor/adi/adxl345/adxl345_decoder.c b/drivers/sensor/adi/adxl345/adxl345_decoder.c index 7a1bf53cb0584..b6a661a681841 100644 --- a/drivers/sensor/adi/adxl345/adxl345_decoder.c +++ b/drivers/sensor/adi/adxl345/adxl345_decoder.c @@ -259,10 +259,33 @@ static bool adxl345_decoder_has_trigger(const uint8_t *buffer, enum sensor_trigg } } +static int adxl345_get_size_info(struct sensor_chan_spec channel, size_t *base_size, + size_t *frame_size) +{ + __ASSERT_NO_MSG(base_size != NULL); + __ASSERT_NO_MSG(frame_size != NULL); + + if (channel.chan_type >= SENSOR_CHAN_ALL) { + return -ENOTSUP; + } + + switch (channel.chan_type) { + case SENSOR_CHAN_ACCEL_XYZ: + *base_size = sizeof(struct sensor_three_axis_data); + *frame_size = sizeof(struct sensor_three_axis_sample_data); + return 0; + default: + break; + } + + return -ENOTSUP; +} + SENSOR_DECODER_API_DT_DEFINE() = { .get_frame_count = adxl345_decoder_get_frame_count, .decode = adxl345_decoder_decode, .has_trigger = adxl345_decoder_has_trigger, + .get_size_info = adxl345_get_size_info, }; int adxl345_get_decoder(const struct device *dev, const struct sensor_decoder_api **decoder) From eb6066b6ccfb1d00397caebdbb0a05a7abad8b25 Mon Sep 17 00:00:00 2001 From: Luis Ubieda Date: Tue, 31 Dec 2024 17:26:12 -0500 Subject: [PATCH 2/4] sensor: adxl345: Fix decoder for non-streaming mode The following fixes have been applied to this decoder: - The Q-scale factor was fixed, both for full-scale and non full-scale modes. - The data-type decoded is struct sensor_three_axis_data, as it should for read/decode API. Signed-off-by: Luis Ubieda --- drivers/sensor/adi/adxl345/adxl345.c | 4 + drivers/sensor/adi/adxl345/adxl345.h | 1 + drivers/sensor/adi/adxl345/adxl345_decoder.c | 102 +++++++++++-------- 3 files changed, 67 insertions(+), 40 deletions(-) diff --git a/drivers/sensor/adi/adxl345/adxl345.c b/drivers/sensor/adi/adxl345/adxl345.c index adeaae828b266..2ad60d42c9b87 100644 --- a/drivers/sensor/adi/adxl345/adxl345.c +++ b/drivers/sensor/adi/adxl345/adxl345.c @@ -281,6 +281,7 @@ int adxl345_read_sample(const struct device *dev, { int16_t raw_x, raw_y, raw_z; uint8_t axis_data[6], status1; + struct adxl345_dev_data *data = dev->data; if (!IS_ENABLED(CONFIG_ADXL345_TRIGGER)) { do { @@ -303,6 +304,9 @@ int adxl345_read_sample(const struct device *dev, sample->y = raw_y; sample->z = raw_z; + sample->selected_range = data->selected_range; + sample->is_full_res = data->is_full_res; + return 0; } diff --git a/drivers/sensor/adi/adxl345/adxl345.h b/drivers/sensor/adi/adxl345/adxl345.h index 1a3f1eed58ba1..8bc25f5034028 100644 --- a/drivers/sensor/adi/adxl345/adxl345.h +++ b/drivers/sensor/adi/adxl345/adxl345.h @@ -205,6 +205,7 @@ struct adxl345_sample { uint8_t res: 7; #endif /* CONFIG_ADXL345_STREAM */ uint8_t selected_range; + bool is_full_res; int16_t x; int16_t y; int16_t z; diff --git a/drivers/sensor/adi/adxl345/adxl345_decoder.c b/drivers/sensor/adi/adxl345/adxl345_decoder.c index b6a661a681841..1f39fb9d1d141 100644 --- a/drivers/sensor/adi/adxl345/adxl345_decoder.c +++ b/drivers/sensor/adi/adxl345/adxl345_decoder.c @@ -6,17 +6,42 @@ #include "adxl345.h" -#ifdef CONFIG_ADXL345_STREAM +/** The q-scale factor will always be the same, as the nominal LSB/g + * changes at the same rate the selected shift parameter per range: + * + * - At 2G: 256 LSB/g, 10-bits resolution. + * - At 4g: 128 LSB/g, 10-bits resolution. + * - At 8g: 64 LSB/g, 10-bits resolution. + * - At 16g 32 LSB/g, 10-bits resolution. + */ +static const uint32_t qscale_factor_no_full_res[] = { + /* (1.0 / Resolution-LSB-per-g * (2^31 / 2^5) * SENSOR_G / 1000000 */ + [ADXL345_RANGE_2G] = UINT32_C(2570754), + /* (1.0 / Resolution-LSB-per-g) * (2^31 / 2^6) * SENSOR_G / 1000000 */ + [ADXL345_RANGE_4G] = UINT32_C(2570754), + /* (1.0 / Resolution-LSB-per-g) * (2^31 / 2^7) ) * SENSOR_G / 1000000 */ + [ADXL345_RANGE_8G] = UINT32_C(2570754), + /* (1.0 / Resolution-LSB-per-g) * (2^31 / 2^8) ) * SENSOR_G / 1000000 */ + [ADXL345_RANGE_16G] = UINT32_C(2570754), +}; -#define SENSOR_SCALING_FACTOR (SENSOR_G / (16 * 1000 / 100)) -static const uint32_t accel_period_ns[] = { - [ADXL345_ODR_12HZ] = UINT32_C(1000000000) / 12, - [ADXL345_ODR_25HZ] = UINT32_C(1000000000) / 25, - [ADXL345_ODR_50HZ] = UINT32_C(1000000000) / 50, - [ADXL345_ODR_100HZ] = UINT32_C(1000000000) / 100, - [ADXL345_ODR_200HZ] = UINT32_C(1000000000) / 200, - [ADXL345_ODR_400HZ] = UINT32_C(1000000000) / 400, +/** Sensitivities based on Range: + * + * - At 2G: 256 LSB/g, 10-bits resolution. + * - At 4g: 256 LSB/g, 11-bits resolution. + * - At 8g: 256 LSB/g, 12-bits resolution. + * - At 16g 256 LSB/g, 13-bits resolution. + */ +static const uint32_t qscale_factor_full_res[] = { + /* (1.0 / Resolution-LSB-per-g) * (2^31 / 2^5) * SENSOR_G / 1000000 */ + [ADXL345_RANGE_2G] = UINT32_C(2570754), + /* (1.0 / Resolution-LSB-per-g) * (2^31 / 2^6) * SENSOR_G / 1000000 */ + [ADXL345_RANGE_4G] = UINT32_C(1285377), + /* (1.0 / Resolution-LSB-per-g) * (2^31 / 2^7) ) * SENSOR_G / 1000000 */ + [ADXL345_RANGE_8G] = UINT32_C(642688), + /* (1.0 / Resolution-LSB-per-g) * (2^31 / 2^8) ) * SENSOR_G / 1000000 */ + [ADXL345_RANGE_16G] = UINT32_C(321344), }; static const uint32_t range_to_shift[] = { @@ -26,30 +51,6 @@ static const uint32_t range_to_shift[] = { [ADXL345_RANGE_16G] = 8, }; -/* (1 / sensitivity) * (pow(2,31) / pow(2,shift)) * (unit_scaler) */ -static const uint32_t qscale_factor_no_full_res[] = { - /* (1.0 / ADXL362_ACCEL_2G_LSB_PER_G) * (2^31 / 2^5) * SENSOR_G / 1000000 */ - [ADXL345_RANGE_2G] = UINT32_C(2569011), - /* (1.0 / ADXL362_ACCEL_4G_LSB_PER_G) * (2^31 / 2^6) * SENSOR_G / 1000000 */ - [ADXL345_RANGE_4G] = UINT32_C(642253), - /* (1.0 / ADXL362_ACCEL_8G_LSB_PER_G) * (2^31 / 2^7) ) * SENSOR_G / 1000000 */ - [ADXL345_RANGE_8G] = UINT32_C(160563), - /* (1.0 / ADXL362_ACCEL_8G_LSB_PER_G) * (2^31 / 2^8) ) * SENSOR_G / 1000000 */ - [ADXL345_RANGE_16G] = UINT32_C(40141), -}; - -/* (1 / sensitivity) * (pow(2,31) / pow(2,shift)) * (unit_scaler) */ -static const uint32_t qscale_factor_full_res[] = { - /* (1.0 / ADXL362_ACCEL_2G_LSB_PER_G) * (2^31 / 2^5) * SENSOR_G / 1000000 */ - [ADXL345_RANGE_2G] = UINT32_C(2569011), - /* (1.0 / ADXL362_ACCEL_4G_LSB_PER_G) * (2^31 / 2^6) * SENSOR_G / 1000000 */ - [ADXL345_RANGE_4G] = UINT32_C(1284506), - /* (1.0 / ADXL362_ACCEL_8G_LSB_PER_G) * (2^31 / 2^7) ) * SENSOR_G / 1000000 */ - [ADXL345_RANGE_8G] = UINT32_C(642253), - /* (1.0 / ADXL362_ACCEL_8G_LSB_PER_G) * (2^31 / 2^8) ) * SENSOR_G / 1000000 */ - [ADXL345_RANGE_16G] = UINT32_C(321126), -}; - static inline void adxl345_accel_convert_q31(q31_t *out, int16_t sample, int32_t range, uint8_t is_full_res) { @@ -76,15 +77,28 @@ static inline void adxl345_accel_convert_q31(q31_t *out, int16_t sample, int32_t } break; } + *out = sample * qscale_factor_full_res[range]; } else { if (sample & BIT(9)) { sample |= ADXL345_COMPLEMENT; } + *out = sample * qscale_factor_no_full_res[range]; } - - *out = sample * qscale_factor_no_full_res[range]; } +#ifdef CONFIG_ADXL345_STREAM + +#define SENSOR_SCALING_FACTOR (SENSOR_G / (16 * 1000 / 100)) + +static const uint32_t accel_period_ns[] = { + [ADXL345_ODR_12HZ] = UINT32_C(1000000000) / 12, + [ADXL345_ODR_25HZ] = UINT32_C(1000000000) / 25, + [ADXL345_ODR_50HZ] = UINT32_C(1000000000) / 50, + [ADXL345_ODR_100HZ] = UINT32_C(1000000000) / 100, + [ADXL345_ODR_200HZ] = UINT32_C(1000000000) / 200, + [ADXL345_ODR_400HZ] = UINT32_C(1000000000) / 400, +}; + static int adxl345_decode_stream(const uint8_t *buffer, struct sensor_chan_spec chan_spec, uint32_t *fit, uint16_t max_count, void *data_out) { @@ -208,7 +222,12 @@ static int adxl345_decode_sample(const struct adxl345_sample *data, struct sensor_chan_spec chan_spec, uint32_t *fit, uint16_t max_count, void *data_out) { - struct sensor_value *out = (struct sensor_value *)data_out; + struct sensor_three_axis_data *out = (struct sensor_three_axis_data *)data_out; + + memset(out, 0, sizeof(struct sensor_three_axis_data)); + out->header.base_timestamp_ns = k_ticks_to_ns_floor64(k_uptime_ticks()); + out->header.reading_count = 1; + out->shift = range_to_shift[data->selected_range]; if (*fit > 0) { return -ENOTSUP; @@ -216,9 +235,12 @@ static int adxl345_decode_sample(const struct adxl345_sample *data, switch (chan_spec.chan_type) { case SENSOR_CHAN_ACCEL_XYZ: - adxl345_accel_convert(out++, data->x); - adxl345_accel_convert(out++, data->y); - adxl345_accel_convert(out, data->z); + adxl345_accel_convert_q31(&out->readings->x, data->x, data->selected_range, + data->is_full_res); + adxl345_accel_convert_q31(&out->readings->y, data->y, data->selected_range, + data->is_full_res); + adxl345_accel_convert_q31(&out->readings->z, data->z, data->selected_range, + data->is_full_res); break; default: return -ENOTSUP; @@ -226,7 +248,7 @@ static int adxl345_decode_sample(const struct adxl345_sample *data, *fit = 1; - return 0; + return 1; } static int adxl345_decoder_decode(const uint8_t *buffer, struct sensor_chan_spec chan_spec, From 68ad46b51d7258060fcff3f453058520e4d0baf5 Mon Sep 17 00:00:00 2001 From: Luis Ubieda Date: Tue, 14 Jan 2025 19:26:53 -0500 Subject: [PATCH 3/4] sensor: adxl345: Only enable FIFO Stream with Sensor Stream is enabled Otherwise with its default configuration (25-Hz, 32-level FIFO), getting individual samples could be up to 1-second old. Signed-off-by: Luis Ubieda --- drivers/sensor/adi/adxl345/adxl345.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/sensor/adi/adxl345/adxl345.c b/drivers/sensor/adi/adxl345/adxl345.c index 2ad60d42c9b87..14463392bb7e2 100644 --- a/drivers/sensor/adi/adxl345/adxl345.c +++ b/drivers/sensor/adi/adxl345/adxl345.c @@ -457,11 +457,13 @@ static int adxl345_init(const struct device *dev) return -ENODEV; } +#if CONFIG_ADXL345_STREAM rc = adxl345_reg_write_byte(dev, ADXL345_FIFO_CTL_REG, ADXL345_FIFO_STREAM_MODE); if (rc < 0) { LOG_ERR("FIFO enable failed\n"); return -EIO; } +#endif rc = adxl345_reg_write_byte(dev, ADXL345_DATA_FORMAT_REG, ADXL345_RANGE_8G); if (rc < 0) { From 18682118eb245482d59cce4f37c1b34815bc5fe9 Mon Sep 17 00:00:00 2001 From: Luis Ubieda Date: Tue, 14 Jan 2025 19:31:20 -0500 Subject: [PATCH 4/4] sensor: adxl345: Disable Sensor Streaming by default Have the application enable this feature explicitcly, so that simple applications do not need to disable this to get the expected behavior. Signed-off-by: Luis Ubieda --- drivers/sensor/adi/adxl345/Kconfig | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/sensor/adi/adxl345/Kconfig b/drivers/sensor/adi/adxl345/Kconfig index cb3680a86c574..481ddd404ad86 100644 --- a/drivers/sensor/adi/adxl345/Kconfig +++ b/drivers/sensor/adi/adxl345/Kconfig @@ -37,7 +37,6 @@ endchoice config ADXL345_STREAM bool "Use FIFO to stream data" select ADXL345_TRIGGER - default y depends on (SPI_RTIO || I2C_RTIO) depends on SENSOR_ASYNC_API help