Skip to content
92 changes: 47 additions & 45 deletions drivers/adc/adc_nrfx_saadc.c
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,7 @@
struct driver_data {
struct adc_context ctx;
uint8_t single_ended_channels;
uint8_t divide_single_ended_value;
uint8_t active_channel_cnt;
void *mem_reg;
void *user_buffer;
Expand Down Expand Up @@ -360,21 +361,22 @@
if (channel_cfg->differential) {
if (channel_cfg->input_negative == NRF_SAADC_GND) {
ch_cfg->mode = NRF_SAADC_MODE_SINGLE_ENDED;
/* Do not mark as single-ended to not correct negative values. */
m_data.single_ended_channels &= ~BIT(channel_cfg->channel_id);
m_data.single_ended_channels |= BIT(channel_cfg->channel_id);
m_data.divide_single_ended_value |= BIT(channel_cfg->channel_id);
} else {
ch_cfg->mode = NRF_SAADC_MODE_DIFFERENTIAL;
m_data.single_ended_channels &= ~BIT(channel_cfg->channel_id);
}
} else {
ch_cfg->mode = NRF_SAADC_MODE_SINGLE_ENDED;
m_data.single_ended_channels |= BIT(channel_cfg->channel_id);
m_data.divide_single_ended_value &= ~BIT(channel_cfg->channel_id);
}

nrfx_err_t ret = nrfx_saadc_channel_config(&cfg);

if (ret != NRFX_SUCCESS) {
LOG_ERR("Cannot configure channel %d: %d", channel_cfg->channel_id, ret);
LOG_ERR("Cannot configure channel %d: 0x%08x", channel_cfg->channel_id, ret);
return -EINVAL;
}

Expand Down Expand Up @@ -411,12 +413,13 @@
if (error != 0) {
LOG_ERR("DMM buffer allocation failed err=%d", error);
adc_context_complete(ctx, -EIO);
return;
}

nrfx_err_t nrfx_err =
nrfx_saadc_buffer_set(samples_buffer, m_data.active_channel_cnt);
if (nrfx_err != NRFX_SUCCESS) {
LOG_ERR("Failed to set buffer: %08x", nrfx_err);
LOG_ERR("Failed to set buffer: 0x%08x", nrfx_err);
adc_context_complete(ctx, -EIO);
}
}
Expand All @@ -430,7 +433,7 @@
nrfx_err_t ret = nrfx_saadc_mode_trigger();

if (ret != NRFX_SUCCESS) {
LOG_ERR("Cannot start sampling: %d", ret);
LOG_ERR("Cannot start sampling: 0x%08x", ret);
adc_context_complete(&m_data.ctx, -EIO);
}
}
Expand All @@ -443,7 +446,7 @@
}
}

static void adc_context_on_timer_expired(struct k_timer *timer_id)
static void external_timer_expired_handler(struct k_timer *timer_id)
{
ARG_UNUSED(timer_id);

Expand Down Expand Up @@ -537,49 +540,47 @@
return 0;
}

static inline void single_ended_channel_cut_negative_sample(uint16_t channel_bit,
uint8_t single_ended_channels,
int16_t **sample)
{
if ((channel_bit & single_ended_channels) && (**sample < 0)) {
**sample = 0;
}

(*sample)++;
}

static bool has_single_ended(const struct adc_sequence *sequence)
{
return sequence->channels & m_data.single_ended_channels;
}

static void correct_single_ended(const struct adc_sequence *sequence, nrf_saadc_value_t *buffer,
uint16_t buffer_size)
uint16_t num_samples)
{
uint8_t selected_channels = sequence->channels;
uint8_t single_ended_channels = m_data.single_ended_channels;
int16_t *sample = (int16_t *)buffer;
uint8_t selected_channels = sequence->channels;
uint8_t divide_mask = m_data.divide_single_ended_value;
uint8_t single_ended_mask = m_data.single_ended_channels;

for (uint16_t channel_bit = BIT(0); channel_bit <= single_ended_channels;
channel_bit <<= 1) {
if (!(channel_bit & selected_channels)) {
continue;
}

if (m_data.internal_timer_enabled) {
if (!(channel_bit & single_ended_channels)) {
continue;
if (m_data.internal_timer_enabled) {
if (selected_channels & divide_mask) {
for (int i = 0; i < num_samples; i++) {
sample[i] /= 2;
}

for (int i = 0; i < buffer_size; i++) {
} else {
for (int i = 0; i < num_samples; i++) {
if (sample[i] < 0) {
sample[i] = 0;
}
}
} else {
single_ended_channel_cut_negative_sample(channel_bit, single_ended_channels,
&sample);
}
return;
}

for (uint16_t channel_bit = BIT(0); channel_bit <= single_ended_mask; channel_bit <<= 1) {
if (!(channel_bit & selected_channels)) {
continue;
}

if (channel_bit & single_ended_mask) {
if (channel_bit & divide_mask) {
*sample /= 2;
} else if (*sample < 0) {
*sample = 0;
}
}
sample++;
}
}

Expand Down Expand Up @@ -647,6 +648,7 @@
}

if ((active_channel_cnt == 1) && (sequence->options != NULL) &&
(sequence->options->callback == NULL) &&
(sequence->options->interval_us <= ADC_INTERNAL_TIMER_INTERVAL_MAX_US) &&
(sequence->options->interval_us > 0)) {

Expand Down Expand Up @@ -680,12 +682,12 @@
m_data.active_channel_cnt = active_channel_cnt;
m_data.user_buffer = sequence->buffer;

error = dmm_buffer_in_prepare(m_data.mem_reg, m_data.user_buffer,
(m_data.internal_timer_enabled
? (NRFX_SAADC_SAMPLES_TO_BYTES(active_channel_cnt) *
(1 + sequence->options->extra_samplings))
: NRFX_SAADC_SAMPLES_TO_BYTES(active_channel_cnt)),
&samples_buffer);
error = dmm_buffer_in_prepare(
m_data.mem_reg, m_data.user_buffer,
(m_data.internal_timer_enabled
? NRFX_SAADC_SAMPLES_TO_BYTES(1 + sequence->options->extra_samplings)
: NRFX_SAADC_SAMPLES_TO_BYTES(active_channel_cnt)),
&samples_buffer);
if (error != 0) {
LOG_ERR("DMM buffer allocation failed err=%d", error);
return error;
Expand All @@ -697,10 +699,10 @@
nrfx_err = nrfx_saadc_buffer_set(
samples_buffer,
(m_data.internal_timer_enabled
? (active_channel_cnt * (1 + sequence->options->extra_samplings))
? (1 + sequence->options->extra_samplings)
: active_channel_cnt));
if (nrfx_err != NRFX_SUCCESS) {

Check notice on line 704 in drivers/adc/adc_nrfx_saadc.c

View workflow job for this annotation

GitHub Actions / Run compliance checks on patch series (PR)

You may want to run clang-format on this change

drivers/adc/adc_nrfx_saadc.c:704 - nrfx_err = nrfx_saadc_buffer_set( - samples_buffer, - (m_data.internal_timer_enabled - ? (1 + sequence->options->extra_samplings) - : active_channel_cnt)); + nrfx_err = nrfx_saadc_buffer_set(samples_buffer, + (m_data.internal_timer_enabled + ? (1 + sequence->options->extra_samplings) + : active_channel_cnt));
LOG_ERR("Failed to set buffer: %08x", nrfx_err);
LOG_ERR("Failed to set buffer: 0x%08x", nrfx_err);
return -EINVAL;
}

Expand Down Expand Up @@ -746,8 +748,8 @@
dmm_buffer_in_release(
m_data.mem_reg, m_data.user_buffer,
(m_data.internal_timer_enabled
? (NRFX_SAADC_SAMPLES_TO_BYTES(m_data.active_channel_cnt) *
(1 + m_data.ctx.sequence.options->extra_samplings))
? NRFX_SAADC_SAMPLES_TO_BYTES(
1 + m_data.ctx.sequence.options->extra_samplings)
: NRFX_SAADC_SAMPLES_TO_BYTES(m_data.active_channel_cnt)),
event->data.done.p_buffer);

Expand All @@ -772,7 +774,7 @@
{
nrfx_err_t err;

k_timer_init(&m_data.timer, adc_context_on_timer_expired, NULL);
k_timer_init(&m_data.timer, external_timer_expired_handler, NULL);

/* The priority value passed here is ignored (see nrfx_glue.h). */
err = nrfx_saadc_init(0);
Expand Down
Loading