Skip to content

Commit 5ee9d7a

Browse files
dimitrije-lilicmmahadevan108
authored andcommitted
driver: sensor: adxl345: Bug fix for q31_t conv
This is a bug fix for adxl345_accel_convert_q31 functions. Functions are used to convert samples received from sensor to q31_t format when RTIO stream is used. Signed-off-by: Dimitrije Lilic <[email protected]>
1 parent 5030938 commit 5ee9d7a

File tree

4 files changed

+96
-18
lines changed

4 files changed

+96
-18
lines changed

drivers/sensor/adi/adxl345/adxl345.c

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -438,7 +438,7 @@ static int adxl345_init(const struct device *dev)
438438
#ifdef CONFIG_ADXL345_TRIGGER
439439
const struct adxl345_dev_config *cfg = dev->config;
440440
#endif
441-
uint8_t dev_id;
441+
uint8_t dev_id, full_res;
442442

443443
data->sample_number = 0;
444444

@@ -459,12 +459,14 @@ static int adxl345_init(const struct device *dev)
459459
return -EIO;
460460
}
461461

462-
rc = adxl345_reg_write_byte(dev, ADXL345_DATA_FORMAT_REG, ADXL345_RANGE_16G);
462+
rc = adxl345_reg_write_byte(dev, ADXL345_DATA_FORMAT_REG, ADXL345_RANGE_8G);
463463
if (rc < 0) {
464464
LOG_ERR("Data format set failed\n");
465465
return -EIO;
466466
}
467467

468+
data->selected_range = ADXL345_RANGE_8G;
469+
468470
rc = adxl345_reg_write_byte(dev, ADXL345_RATE_REG, ADXL345_RATE_25HZ);
469471
if (rc < 0) {
470472
LOG_ERR("Rate setting failed\n");
@@ -497,11 +499,16 @@ static int adxl345_init(const struct device *dev)
497499
if (rc) {
498500
return rc;
499501
}
500-
rc = adxl345_interrupt_config(dev, ADXL345_INT_MAP_WATERMARK_MSK);
502+
rc = adxl345_interrupt_config(dev, ADXL345_INT_MAP_WATERMARK_MSK);
501503
if (rc) {
502504
return rc;
503505
}
504506
#endif
507+
508+
rc = adxl345_reg_read_byte(dev, ADXL345_DATA_FORMAT_REG, &full_res);
509+
uint8_t is_full_res_set = (full_res & ADXL345_DATA_FORMAT_FULL_RES) != 0;
510+
511+
data->is_full_res = is_full_res_set;
505512
return 0;
506513
}
507514

drivers/sensor/adi/adxl345/adxl345.h

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -40,13 +40,14 @@
4040
#define SAMPLE_NUM 0x1F
4141

4242
/* Registers */
43-
#define ADXL345_DEVICE_ID_REG 0x00
44-
#define ADXL345_RATE_REG 0x2c
45-
#define ADXL345_POWER_CTL_REG 0x2d
46-
#define ADXL345_DATA_FORMAT_REG 0x31
47-
#define ADXL345_X_AXIS_DATA_0_REG 0x32
48-
#define ADXL345_FIFO_CTL_REG 0x38
49-
#define ADXL345_FIFO_STATUS_REG 0x39
43+
#define ADXL345_DEVICE_ID_REG 0x00
44+
#define ADXL345_RATE_REG 0x2c
45+
#define ADXL345_POWER_CTL_REG 0x2d
46+
#define ADXL345_DATA_FORMAT_REG 0x31
47+
#define ADXL345_DATA_FORMAT_FULL_RES 0x08
48+
#define ADXL345_X_AXIS_DATA_0_REG 0x32
49+
#define ADXL345_FIFO_CTL_REG 0x38
50+
#define ADXL345_FIFO_STATUS_REG 0x39
5051

5152
#define ADXL345_PART_ID 0xe5
5253

@@ -58,6 +59,7 @@
5859
#define ADXL345_ENABLE_MEASURE_BIT (1 << 3)
5960
#define ADXL345_FIFO_STREAM_MODE (1 << 7)
6061
#define ADXL345_FIFO_COUNT_MASK 0x3f
62+
#define ADXL345_COMPLEMENT_MASK(x) GENMASK(15, (x))
6163
#define ADXL345_COMPLEMENT 0xfc00
6264

6365
#define ADXL345_MAX_FIFO_SIZE 32
@@ -149,6 +151,8 @@ struct adxl345_dev_data {
149151
int16_t bufy[ADXL345_MAX_FIFO_SIZE];
150152
int16_t bufz[ADXL345_MAX_FIFO_SIZE];
151153
struct adxl345_fifo_config fifo_config;
154+
uint8_t is_full_res;
155+
uint8_t selected_range;
152156
#ifdef CONFIG_ADXL345_TRIGGER
153157
struct gpio_callback gpio_cb;
154158

@@ -182,6 +186,8 @@ struct adxl345_dev_data {
182186

183187
struct adxl345_fifo_data {
184188
uint8_t is_fifo: 1;
189+
uint8_t is_full_res: 1;
190+
uint8_t selected_range: 2;
185191
uint8_t sample_set_size: 4;
186192
uint8_t int_status;
187193
uint16_t accel_odr: 4;
@@ -194,6 +200,7 @@ struct adxl345_sample {
194200
uint8_t is_fifo: 1;
195201
uint8_t res: 7;
196202
#endif /* CONFIG_ADXL345_STREAM */
203+
uint8_t selected_range;
197204
int16_t x;
198205
int16_t y;
199206
int16_t z;

drivers/sensor/adi/adxl345/adxl345_decoder.c

Lines changed: 70 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -19,13 +19,70 @@ static const uint32_t accel_period_ns[] = {
1919
[ADXL345_ODR_400HZ] = UINT32_C(1000000000) / 400,
2020
};
2121

22-
static inline void adxl345_accel_convert_q31(q31_t *out, uint16_t sample)
22+
static const uint32_t range_to_shift[] = {
23+
[ADXL345_RANGE_2G] = 5,
24+
[ADXL345_RANGE_4G] = 6,
25+
[ADXL345_RANGE_8G] = 7,
26+
[ADXL345_RANGE_16G] = 8,
27+
};
28+
29+
/* (1 / sensitivity) * (pow(2,31) / pow(2,shift)) * (unit_scaler) */
30+
static const uint32_t qscale_factor_no_full_res[] = {
31+
/* (1.0 / ADXL362_ACCEL_2G_LSB_PER_G) * (2^31 / 2^5) * SENSOR_G / 1000000 */
32+
[ADXL345_RANGE_2G] = UINT32_C(2569011),
33+
/* (1.0 / ADXL362_ACCEL_4G_LSB_PER_G) * (2^31 / 2^6) * SENSOR_G / 1000000 */
34+
[ADXL345_RANGE_4G] = UINT32_C(642253),
35+
/* (1.0 / ADXL362_ACCEL_8G_LSB_PER_G) * (2^31 / 2^7) ) * SENSOR_G / 1000000 */
36+
[ADXL345_RANGE_8G] = UINT32_C(160563),
37+
/* (1.0 / ADXL362_ACCEL_8G_LSB_PER_G) * (2^31 / 2^8) ) * SENSOR_G / 1000000 */
38+
[ADXL345_RANGE_16G] = UINT32_C(40141),
39+
};
40+
41+
/* (1 / sensitivity) * (pow(2,31) / pow(2,shift)) * (unit_scaler) */
42+
static const uint32_t qscale_factor_full_res[] = {
43+
/* (1.0 / ADXL362_ACCEL_2G_LSB_PER_G) * (2^31 / 2^5) * SENSOR_G / 1000000 */
44+
[ADXL345_RANGE_2G] = UINT32_C(2569011),
45+
/* (1.0 / ADXL362_ACCEL_4G_LSB_PER_G) * (2^31 / 2^6) * SENSOR_G / 1000000 */
46+
[ADXL345_RANGE_4G] = UINT32_C(1284506),
47+
/* (1.0 / ADXL362_ACCEL_8G_LSB_PER_G) * (2^31 / 2^7) ) * SENSOR_G / 1000000 */
48+
[ADXL345_RANGE_8G] = UINT32_C(642253),
49+
/* (1.0 / ADXL362_ACCEL_8G_LSB_PER_G) * (2^31 / 2^8) ) * SENSOR_G / 1000000 */
50+
[ADXL345_RANGE_16G] = UINT32_C(321126),
51+
};
52+
53+
static inline void adxl345_accel_convert_q31(q31_t *out, int16_t sample, int32_t range,
54+
uint8_t is_full_res)
2355
{
24-
if (sample & BIT(9)) {
25-
sample |= ADXL345_COMPLEMENT;
56+
if (is_full_res) {
57+
switch (range) {
58+
case ADXL345_RANGE_2G:
59+
if (sample & BIT(9)) {
60+
sample |= ADXL345_COMPLEMENT_MASK(10);
61+
}
62+
break;
63+
case ADXL345_RANGE_4G:
64+
if (sample & BIT(10)) {
65+
sample |= ADXL345_COMPLEMENT_MASK(11);
66+
}
67+
break;
68+
case ADXL345_RANGE_8G:
69+
if (sample & BIT(11)) {
70+
sample |= ADXL345_COMPLEMENT_MASK(12);
71+
}
72+
break;
73+
case ADXL345_RANGE_16G:
74+
if (sample & BIT(12)) {
75+
sample |= ADXL345_COMPLEMENT_MASK(13);
76+
}
77+
break;
78+
}
79+
} else {
80+
if (sample & BIT(9)) {
81+
sample |= ADXL345_COMPLEMENT;
82+
}
2683
}
27-
int32_t micro_ms2 = ((sample * SENSOR_G) / 32);
28-
*out = CLAMP((((int64_t)micro_ms2) + (micro_ms2 % 1000000)), INT32_MIN, INT32_MAX);
84+
85+
*out = sample * qscale_factor_no_full_res[range];
2986
}
3087

3188
static int adxl345_decode_stream(const uint8_t *buffer, struct sensor_chan_spec chan_spec,
@@ -46,11 +103,13 @@ static int adxl345_decode_stream(const uint8_t *buffer, struct sensor_chan_spec
46103
memset(data, 0, sizeof(struct sensor_three_axis_data));
47104
data->header.base_timestamp_ns = enc_data->timestamp;
48105
data->header.reading_count = 1;
106+
data->shift = range_to_shift[enc_data->selected_range];
49107

50108
buffer += sizeof(struct adxl345_fifo_data);
51109

52110
uint8_t sample_set_size = enc_data->sample_set_size;
53111
uint64_t period_ns = accel_period_ns[enc_data->accel_odr];
112+
uint8_t is_full_res = enc_data->is_full_res;
54113

55114
/* Calculate which sample is decoded. */
56115
if ((uint8_t *)*fit >= buffer) {
@@ -73,13 +132,16 @@ static int adxl345_decode_stream(const uint8_t *buffer, struct sensor_chan_spec
73132
data->readings[count].timestamp_delta = sample_num * period_ns;
74133
uint8_t buff_offset = 0;
75134

76-
adxl345_accel_convert_q31(&data->readings[count].x, *(int16_t *)buffer);
135+
adxl345_accel_convert_q31(&data->readings[count].x, *(int16_t *)buffer,
136+
enc_data->selected_range, is_full_res);
77137
buff_offset = 2;
78138
adxl345_accel_convert_q31(&data->readings[count].y,
79-
*(int16_t *)(buffer + buff_offset));
139+
*(int16_t *)(buffer + buff_offset),
140+
enc_data->selected_range, is_full_res);
80141
buff_offset += 2;
81142
adxl345_accel_convert_q31(&data->readings[count].z,
82-
*(int16_t *)(buffer + buff_offset));
143+
*(int16_t *)(buffer + buff_offset),
144+
enc_data->selected_range, is_full_res);
83145
break;
84146
default:
85147
return -ENOTSUP;

drivers/sensor/adi/adxl345/adxl345_stream.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,8 @@ static void adxl345_process_fifo_samples_cb(struct rtio *r, const struct rtio_sq
157157
hdr->is_fifo = 1;
158158
hdr->timestamp = data->timestamp;
159159
hdr->int_status = data->status1;
160+
hdr->is_full_res = data->is_full_res;
161+
hdr->selected_range = data->selected_range;
160162
hdr->accel_odr = cfg->odr;
161163
hdr->sample_set_size = sample_set_size;
162164

0 commit comments

Comments
 (0)