Skip to content

Commit

Permalink
sensor: adxl345: Fix decoder for non-streaming mode
Browse files Browse the repository at this point in the history
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 <luisf@croxel.com>
  • Loading branch information
ubieda authored and kartben committed Jan 20, 2025
1 parent 2dba777 commit 283b519
Show file tree
Hide file tree
Showing 3 changed files with 67 additions and 40 deletions.
4 changes: 4 additions & 0 deletions drivers/sensor/adi/adxl345/adxl345.c
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand All @@ -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;
}

Expand Down
1 change: 1 addition & 0 deletions drivers/sensor/adi/adxl345/adxl345.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
102 changes: 62 additions & 40 deletions drivers/sensor/adi/adxl345/adxl345_decoder.c
Original file line number Diff line number Diff line change
Expand Up @@ -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[] = {
Expand All @@ -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)
{
Expand All @@ -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)
{
Expand Down Expand Up @@ -208,25 +222,33 @@ 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;
}

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;
}

*fit = 1;

return 0;
return 1;
}

static int adxl345_decoder_decode(const uint8_t *buffer, struct sensor_chan_spec chan_spec,
Expand Down

0 comments on commit 283b519

Please sign in to comment.