diff options
Diffstat (limited to 'thirdparty/nRF5_SDK_15.0.0_a53641a/modules/nrfx/drivers/src/nrfx_saadc.c')
-rw-r--r-- | thirdparty/nRF5_SDK_15.0.0_a53641a/modules/nrfx/drivers/src/nrfx_saadc.c | 639 |
1 files changed, 639 insertions, 0 deletions
diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/modules/nrfx/drivers/src/nrfx_saadc.c b/thirdparty/nRF5_SDK_15.0.0_a53641a/modules/nrfx/drivers/src/nrfx_saadc.c new file mode 100644 index 0000000..4ab3409 --- /dev/null +++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/modules/nrfx/drivers/src/nrfx_saadc.c @@ -0,0 +1,639 @@ +/** + * Copyright (c) 2015 - 2018, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#include <nrfx.h> + +#if NRFX_CHECK(NRFX_SAADC_ENABLED) +#include <nrfx_saadc.h> + +#define NRFX_LOG_MODULE SAADC +#include <nrfx_log.h> + +#define EVT_TO_STR(event) \ + (event == NRF_SAADC_EVENT_STARTED ? "NRF_SAADC_EVENT_STARTED" : \ + (event == NRF_SAADC_EVENT_END ? "NRF_SAADC_EVENT_END" : \ + (event == NRF_SAADC_EVENT_DONE ? "NRF_SAADC_EVENT_DONE" : \ + (event == NRF_SAADC_EVENT_RESULTDONE ? "NRF_SAADC_EVENT_RESULTDONE" : \ + (event == NRF_SAADC_EVENT_CALIBRATEDONE ? "NRF_SAADC_EVENT_CALIBRATEDONE" : \ + (event == NRF_SAADC_EVENT_STOPPED ? "NRF_SAADC_EVENT_STOPPED" : \ + "UNKNOWN EVENT")))))) + + +typedef enum +{ + NRF_SAADC_STATE_IDLE = 0, + NRF_SAADC_STATE_BUSY = 1, + NRF_SAADC_STATE_CALIBRATION = 2 +} nrf_saadc_state_t; + + +typedef struct +{ + nrf_saadc_input_t pselp; + nrf_saadc_input_t pseln; +} nrf_saadc_psel_buffer; + +/** @brief SAADC control block.*/ +typedef struct +{ + nrfx_saadc_event_handler_t event_handler; ///< Event handler function pointer. + volatile nrf_saadc_value_t * p_buffer; ///< Sample buffer. + volatile uint16_t buffer_size; ///< Size of the sample buffer. + volatile nrf_saadc_value_t * p_secondary_buffer; ///< Secondary sample buffer. + volatile nrf_saadc_state_t adc_state; ///< State of the SAADC. + uint32_t limits_enabled_flags; ///< Enabled limits flags. + uint16_t secondary_buffer_size; ///< Size of the secondary buffer. + uint16_t buffer_size_left; ///< When low power mode is active indicates how many samples left to convert on current buffer. + nrf_saadc_psel_buffer psel[NRF_SAADC_CHANNEL_COUNT]; ///< Pin configurations of SAADC channels. + nrfx_drv_state_t state; ///< Driver initialization state. + uint8_t active_channels; ///< Number of enabled SAADC channels. + bool low_power_mode; ///< Indicates if low power mode is active. + bool conversions_end; ///< When low power mode is active indicates end of conversions on current buffer. +} nrfx_saadc_cb_t; + +static nrfx_saadc_cb_t m_cb; + +#define LOW_LIMIT_TO_FLAG(channel) ((2 * channel + 1)) +#define HIGH_LIMIT_TO_FLAG(channel) ((2 * channel)) +#define FLAG_IDX_TO_EVENT(idx) ((nrf_saadc_event_t)((uint32_t)NRF_SAADC_EVENT_CH0_LIMITH + \ + 4 * idx)) +#define LIMIT_EVENT_TO_CHANNEL(event) (uint8_t)(((uint32_t)event - \ + (uint32_t)NRF_SAADC_EVENT_CH0_LIMITH) / 8) +#define LIMIT_EVENT_TO_LIMIT_TYPE(event)((((uint32_t)event - (uint32_t)NRF_SAADC_EVENT_CH0_LIMITH) & 4) \ + ? NRF_SAADC_LIMIT_LOW : NRF_SAADC_LIMIT_HIGH) +#define HW_TIMEOUT 10000 + +void nrfx_saadc_irq_handler(void) +{ + if (nrf_saadc_event_check(NRF_SAADC_EVENT_END)) + { + nrf_saadc_event_clear(NRF_SAADC_EVENT_END); + NRFX_LOG_DEBUG("Event: %s.", EVT_TO_STR(NRF_SAADC_EVENT_END)); + + if (!m_cb.low_power_mode || m_cb.conversions_end) + { + nrfx_saadc_evt_t evt; + evt.type = NRFX_SAADC_EVT_DONE; + evt.data.done.p_buffer = (nrf_saadc_value_t *)m_cb.p_buffer; + evt.data.done.size = m_cb.buffer_size; + + if (m_cb.p_secondary_buffer == NULL) + { + m_cb.adc_state = NRF_SAADC_STATE_IDLE; + } + else + { + m_cb.buffer_size_left = m_cb.secondary_buffer_size; + m_cb.p_buffer = m_cb.p_secondary_buffer; + m_cb.buffer_size = m_cb.secondary_buffer_size; + m_cb.p_secondary_buffer = NULL; + if (!m_cb.low_power_mode) + { + nrf_saadc_task_trigger(NRF_SAADC_TASK_START); + } + } + m_cb.event_handler(&evt); + m_cb.conversions_end = false; + } + } + if (m_cb.low_power_mode && nrf_saadc_event_check(NRF_SAADC_EVENT_STARTED)) + { + nrf_saadc_event_clear(NRF_SAADC_EVENT_STARTED); + NRFX_LOG_DEBUG("Event: %s.", EVT_TO_STR(NRF_SAADC_EVENT_STARTED)); + + if (m_cb.buffer_size_left > m_cb.active_channels) + { + // More samples to convert than for single event. + m_cb.buffer_size_left -= m_cb.active_channels; + nrf_saadc_buffer_init((nrf_saadc_value_t *)&m_cb.p_buffer[m_cb.buffer_size - + m_cb.buffer_size_left], + m_cb.active_channels); + } + else if ((m_cb.buffer_size_left == m_cb.active_channels) && + + (m_cb.p_secondary_buffer != NULL)) + { + // Samples to convert for one event, prepare next buffer. + m_cb.conversions_end = true; + m_cb.buffer_size_left = 0; + nrf_saadc_buffer_init((nrf_saadc_value_t *)m_cb.p_secondary_buffer, + m_cb.active_channels); + } + else if (m_cb.buffer_size_left == m_cb.active_channels) + { + // Samples to convert for one event, but no second buffer. + m_cb.conversions_end = true; + m_cb.buffer_size_left = 0; + } + nrf_saadc_event_clear(NRF_SAADC_EVENT_END); + nrf_saadc_task_trigger(NRF_SAADC_TASK_SAMPLE); + } + if (nrf_saadc_event_check(NRF_SAADC_EVENT_CALIBRATEDONE)) + { + nrf_saadc_event_clear(NRF_SAADC_EVENT_CALIBRATEDONE); + NRFX_LOG_DEBUG("Event: %s.", EVT_TO_STR(NRF_SAADC_EVENT_CALIBRATEDONE)); + m_cb.adc_state = NRF_SAADC_STATE_IDLE; + + nrfx_saadc_evt_t evt; + evt.type = NRFX_SAADC_EVT_CALIBRATEDONE; + m_cb.event_handler(&evt); + } + if (nrf_saadc_event_check(NRF_SAADC_EVENT_STOPPED)) + { + nrf_saadc_event_clear(NRF_SAADC_EVENT_STOPPED); + NRFX_LOG_DEBUG("Event: %s.", EVT_TO_STR(NRF_SAADC_EVENT_STOPPED)); + m_cb.adc_state = NRF_SAADC_STATE_IDLE; + } + else + { + uint32_t limit_flags = m_cb.limits_enabled_flags; + uint32_t flag_idx; + nrf_saadc_event_t event; + + while (limit_flags) + { + flag_idx = __CLZ(limit_flags); + limit_flags &= ~((1UL << 31) >> flag_idx); + event = FLAG_IDX_TO_EVENT(flag_idx); + if (nrf_saadc_event_check(event)) + { + nrf_saadc_event_clear(event); + nrfx_saadc_evt_t evt; + evt.type = NRFX_SAADC_EVT_LIMIT; + evt.data.limit.channel = LIMIT_EVENT_TO_CHANNEL(event); + evt.data.limit.limit_type = LIMIT_EVENT_TO_LIMIT_TYPE(event); + NRFX_LOG_DEBUG("Event limit, channel: %d, limit type: %d.", + evt.data.limit.channel, + evt.data.limit.limit_type); + m_cb.event_handler(&evt); + } + } + } +} + + +nrfx_err_t nrfx_saadc_init(nrfx_saadc_config_t const * p_config, + nrfx_saadc_event_handler_t event_handler) +{ + NRFX_ASSERT(p_config); + NRFX_ASSERT(event_handler); + nrfx_err_t err_code; + + if (m_cb.state != NRFX_DRV_STATE_UNINITIALIZED) + { + err_code = NRFX_ERROR_INVALID_STATE; + NRFX_LOG_WARNING("Function: %s, error code: %s.", + __func__, + NRFX_LOG_ERROR_STRING_GET(err_code)); + return err_code; + } + + m_cb.event_handler = event_handler; + nrf_saadc_resolution_set(p_config->resolution); + nrf_saadc_oversample_set(p_config->oversample); + m_cb.low_power_mode = p_config->low_power_mode; + m_cb.state = NRFX_DRV_STATE_INITIALIZED; + m_cb.adc_state = NRF_SAADC_STATE_IDLE; + m_cb.active_channels = 0; + m_cb.limits_enabled_flags = 0; + m_cb.conversions_end = false; + + nrf_saadc_int_disable(NRF_SAADC_INT_ALL); + nrf_saadc_event_clear(NRF_SAADC_EVENT_END); + nrf_saadc_event_clear(NRF_SAADC_EVENT_STARTED); + NRFX_IRQ_PRIORITY_SET(SAADC_IRQn, p_config->interrupt_priority); + NRFX_IRQ_ENABLE(SAADC_IRQn); + nrf_saadc_int_enable(NRF_SAADC_INT_END); + + if (m_cb.low_power_mode) + { + nrf_saadc_int_enable(NRF_SAADC_INT_STARTED); + } + + nrf_saadc_enable(); + + err_code = NRFX_SUCCESS; + NRFX_LOG_INFO("Function: %s, error code: %s.", __func__, NRFX_LOG_ERROR_STRING_GET(err_code)); + + return err_code; +} + + +void nrfx_saadc_uninit(void) +{ + NRFX_ASSERT(m_cb.state != NRFX_DRV_STATE_UNINITIALIZED); + + nrf_saadc_int_disable(NRF_SAADC_INT_ALL); + NRFX_IRQ_DISABLE(SAADC_IRQn); + nrf_saadc_task_trigger(NRF_SAADC_TASK_STOP); + + // Wait for ADC being stopped. + bool result; + NRFX_WAIT_FOR(nrf_saadc_event_check(NRF_SAADC_EVENT_STOPPED), HW_TIMEOUT, 0, result); + NRFX_ASSERT(result); + + nrf_saadc_disable(); + m_cb.adc_state = NRF_SAADC_STATE_IDLE; + + for (uint32_t channel = 0; channel < NRF_SAADC_CHANNEL_COUNT; ++channel) + { + if (m_cb.psel[channel].pselp != NRF_SAADC_INPUT_DISABLED) + { + nrfx_err_t err_code = nrfx_saadc_channel_uninit(channel); + NRFX_ASSERT(err_code == NRFX_SUCCESS); + } + } + + m_cb.state = NRFX_DRV_STATE_UNINITIALIZED; +} + + +nrfx_err_t nrfx_saadc_channel_init(uint8_t channel, + nrf_saadc_channel_config_t const * const p_config) +{ + NRFX_ASSERT(m_cb.state != NRFX_DRV_STATE_UNINITIALIZED); + NRFX_ASSERT(channel < NRF_SAADC_CHANNEL_COUNT); + // Oversampling can be used only with one channel. + NRFX_ASSERT((nrf_saadc_oversample_get() == NRF_SAADC_OVERSAMPLE_DISABLED) || + (m_cb.active_channels == 0)); + NRFX_ASSERT((p_config->pin_p <= NRF_SAADC_INPUT_VDD) && + (p_config->pin_p > NRF_SAADC_INPUT_DISABLED)); + NRFX_ASSERT(p_config->pin_n <= NRF_SAADC_INPUT_VDD); + + nrfx_err_t err_code; + + // A channel can only be initialized if the driver is in the idle state. + if (m_cb.adc_state != NRF_SAADC_STATE_IDLE) + { + err_code = NRFX_ERROR_BUSY; + NRFX_LOG_WARNING("Function: %s, error code: %s.", + __func__, + NRFX_LOG_ERROR_STRING_GET(err_code)); + return err_code; + } + +#ifdef NRF52_PAN_74 + if ((p_config->acq_time == NRF_SAADC_ACQTIME_3US) || + (p_config->acq_time == NRF_SAADC_ACQTIME_5US)) + { + nrf_saadc_disable(); + } +#endif //NRF52_PAN_74 + + if (m_cb.psel[channel].pselp == NRF_SAADC_INPUT_DISABLED) + { + ++m_cb.active_channels; + } + m_cb.psel[channel].pselp = p_config->pin_p; + m_cb.psel[channel].pseln = p_config->pin_n; + nrf_saadc_channel_init(channel, p_config); + nrf_saadc_channel_input_set(channel, p_config->pin_p, p_config->pin_n); + +#ifdef NRF52_PAN_74 + if ((p_config->acq_time == NRF_SAADC_ACQTIME_3US) || + (p_config->acq_time == NRF_SAADC_ACQTIME_5US)) + { + nrf_saadc_enable(); + } +#endif //NRF52_PAN_74 + + NRFX_LOG_INFO("Channel initialized: %d.", channel); + err_code = NRFX_SUCCESS; + NRFX_LOG_INFO("Function: %s, error code: %s.", __func__, NRFX_LOG_ERROR_STRING_GET(err_code)); + return err_code; +} + + +nrfx_err_t nrfx_saadc_channel_uninit(uint8_t channel) +{ + NRFX_ASSERT(channel < NRF_SAADC_CHANNEL_COUNT); + NRFX_ASSERT(m_cb.state != NRFX_DRV_STATE_UNINITIALIZED); + + nrfx_err_t err_code; + + // A channel can only be uninitialized if the driver is in the idle state. + if (m_cb.adc_state != NRF_SAADC_STATE_IDLE) + { + err_code = NRFX_ERROR_BUSY; + NRFX_LOG_WARNING("Function: %s, error code: %s.", + __func__, + NRFX_LOG_ERROR_STRING_GET(err_code)); + return err_code; + } + + if (m_cb.psel[channel].pselp != NRF_SAADC_INPUT_DISABLED) + { + --m_cb.active_channels; + } + m_cb.psel[channel].pselp = NRF_SAADC_INPUT_DISABLED; + m_cb.psel[channel].pseln = NRF_SAADC_INPUT_DISABLED; + nrf_saadc_channel_input_set(channel, NRF_SAADC_INPUT_DISABLED, NRF_SAADC_INPUT_DISABLED); + nrfx_saadc_limits_set(channel, NRFX_SAADC_LIMITL_DISABLED, NRFX_SAADC_LIMITH_DISABLED); + NRFX_LOG_INFO("Channel denitialized: %d.", channel); + + err_code = NRFX_SUCCESS; + NRFX_LOG_INFO("Function: %s, error code: %s.", __func__, NRFX_LOG_ERROR_STRING_GET(err_code)); + return err_code; +} + + +uint32_t nrfx_saadc_sample_task_get(void) +{ + return nrf_saadc_task_address_get( + m_cb.low_power_mode ? NRF_SAADC_TASK_START : NRF_SAADC_TASK_SAMPLE); +} + + +nrfx_err_t nrfx_saadc_sample_convert(uint8_t channel, nrf_saadc_value_t * p_value) +{ + nrfx_err_t err_code; + + if (m_cb.adc_state != NRF_SAADC_STATE_IDLE) + { + err_code = NRFX_ERROR_BUSY; + NRFX_LOG_WARNING("Function: %s error code: %s.", + __func__, + NRFX_LOG_ERROR_STRING_GET(err_code)); + return err_code; + } + m_cb.adc_state = NRF_SAADC_STATE_BUSY; + nrf_saadc_int_disable(NRF_SAADC_INT_STARTED | NRF_SAADC_INT_END); + nrf_saadc_buffer_init(p_value, 1); + if (m_cb.active_channels > 1) + { + for (uint32_t i = 0; i < NRF_SAADC_CHANNEL_COUNT; ++i) + { + nrf_saadc_channel_input_set(i, NRF_SAADC_INPUT_DISABLED, NRF_SAADC_INPUT_DISABLED); + } + } + nrf_saadc_channel_input_set(channel, m_cb.psel[channel].pselp, m_cb.psel[channel].pseln); + nrf_saadc_task_trigger(NRF_SAADC_TASK_START); + nrf_saadc_task_trigger(NRF_SAADC_TASK_SAMPLE); + + bool result; + NRFX_WAIT_FOR(nrf_saadc_event_check(NRF_SAADC_EVENT_END), HW_TIMEOUT, 0, result); + NRFX_ASSERT(result); + + nrf_saadc_event_clear(NRF_SAADC_EVENT_STARTED); + nrf_saadc_event_clear(NRF_SAADC_EVENT_END); + + NRFX_LOG_INFO("Conversion value: %d, channel %d.", *p_value, channel); + + if (m_cb.active_channels > 1) + { + for (uint32_t i = 0; i < NRF_SAADC_CHANNEL_COUNT; ++i) + { + nrf_saadc_channel_input_set(i, m_cb.psel[i].pselp, m_cb.psel[i].pseln); + } + } + + if (m_cb.low_power_mode) + { + nrf_saadc_int_enable(NRF_SAADC_INT_STARTED | NRF_SAADC_INT_END); + } + else + { + nrf_saadc_int_enable(NRF_SAADC_INT_END); + } + + m_cb.adc_state = NRF_SAADC_STATE_IDLE; + + err_code = NRFX_SUCCESS; + NRFX_LOG_WARNING("Function: %s, error code: %s.", + __func__, + NRFX_LOG_ERROR_STRING_GET(err_code)); + return err_code; +} + + +nrfx_err_t nrfx_saadc_buffer_convert(nrf_saadc_value_t * p_buffer, uint16_t size) +{ + NRFX_ASSERT(m_cb.state != NRFX_DRV_STATE_UNINITIALIZED); + NRFX_ASSERT((size % m_cb.active_channels) == 0); + nrfx_err_t err_code; + + nrf_saadc_int_disable(NRF_SAADC_INT_END | NRF_SAADC_INT_CALIBRATEDONE); + if (m_cb.adc_state == NRF_SAADC_STATE_CALIBRATION) + { + nrf_saadc_int_enable(NRF_SAADC_INT_END | NRF_SAADC_INT_CALIBRATEDONE); + err_code = NRFX_ERROR_BUSY; + NRFX_LOG_WARNING("Function: %s, error code: %s.", + __func__, + NRFX_LOG_ERROR_STRING_GET(err_code)); + return err_code; + } + if (m_cb.adc_state == NRF_SAADC_STATE_BUSY) + { + if ( m_cb.p_secondary_buffer) + { + nrf_saadc_int_enable(NRF_SAADC_INT_END); + err_code = NRFX_ERROR_BUSY; + NRFX_LOG_WARNING("Function: %s, error code: %s.", + __func__, + NRFX_LOG_ERROR_STRING_GET(err_code)); + return err_code; + } + else + { + m_cb.p_secondary_buffer = p_buffer; + m_cb.secondary_buffer_size = size; + if (!m_cb.low_power_mode) + { + while (nrf_saadc_event_check(NRF_SAADC_EVENT_STARTED) == 0); + nrf_saadc_event_clear(NRF_SAADC_EVENT_STARTED); + nrf_saadc_buffer_init(p_buffer, size); + } + nrf_saadc_int_enable(NRF_SAADC_INT_END); + err_code = NRFX_SUCCESS; + NRFX_LOG_WARNING("Function: %s, error code: %s.", + __func__, + NRFX_LOG_ERROR_STRING_GET(err_code)); + return err_code; + } + } + nrf_saadc_int_enable(NRF_SAADC_INT_END); + m_cb.adc_state = NRF_SAADC_STATE_BUSY; + + m_cb.p_buffer = p_buffer; + m_cb.buffer_size = size; + m_cb.p_secondary_buffer = NULL; + + NRFX_LOG_INFO("Function: %s, buffer length: %d, active channels: %d.", + __func__, + size, + m_cb.active_channels); + + if (m_cb.low_power_mode) + { + m_cb.buffer_size_left = size; + nrf_saadc_buffer_init(p_buffer, m_cb.active_channels); + } + else + { + nrf_saadc_buffer_init(p_buffer, size); + nrf_saadc_event_clear(NRF_SAADC_EVENT_STARTED); + nrf_saadc_task_trigger(NRF_SAADC_TASK_START); + } + + err_code = NRFX_SUCCESS; + NRFX_LOG_INFO("Function: %s, error code: %s.", __func__, NRFX_LOG_ERROR_STRING_GET(err_code)); + return err_code; +} + + +nrfx_err_t nrfx_saadc_sample() +{ + NRFX_ASSERT(m_cb.state != NRFX_DRV_STATE_UNINITIALIZED); + + nrfx_err_t err_code = NRFX_SUCCESS; + if (m_cb.adc_state != NRF_SAADC_STATE_BUSY) + { + err_code = NRFX_ERROR_INVALID_STATE; + } + else if (m_cb.low_power_mode) + { + nrf_saadc_task_trigger(NRF_SAADC_TASK_START); + } + else + { + nrf_saadc_task_trigger(NRF_SAADC_TASK_SAMPLE); + } + + NRFX_LOG_INFO("Function: %s, error code: %s.", __func__, NRFX_LOG_ERROR_STRING_GET(err_code)); + return err_code; +} + + +nrfx_err_t nrfx_saadc_calibrate_offset() +{ + NRFX_ASSERT(m_cb.state != NRFX_DRV_STATE_UNINITIALIZED); + + nrfx_err_t err_code; + + if (m_cb.adc_state != NRF_SAADC_STATE_IDLE) + { + err_code = NRFX_ERROR_BUSY; + NRFX_LOG_WARNING("Function: %s, error code: %s.", + __func__, + NRFX_LOG_ERROR_STRING_GET(err_code)); + return err_code; + } + + m_cb.adc_state = NRF_SAADC_STATE_CALIBRATION; + + nrf_saadc_event_clear(NRF_SAADC_EVENT_CALIBRATEDONE); + nrf_saadc_int_enable(NRF_SAADC_INT_CALIBRATEDONE); + nrf_saadc_task_trigger(NRF_SAADC_TASK_CALIBRATEOFFSET); + err_code = NRFX_SUCCESS; + NRFX_LOG_INFO("Function: %s, error code: %s.", + __func__, + NRFX_LOG_ERROR_STRING_GET(err_code)); + return err_code; +} + + +bool nrfx_saadc_is_busy(void) +{ + return (m_cb.adc_state != NRF_SAADC_STATE_IDLE); +} + + +void nrfx_saadc_abort(void) +{ + if (nrfx_saadc_is_busy()) + { + nrf_saadc_event_clear(NRF_SAADC_EVENT_STOPPED); + nrf_saadc_int_enable(NRF_SAADC_INT_STOPPED); + nrf_saadc_task_trigger(NRF_SAADC_TASK_STOP); + + if (m_cb.adc_state == NRF_SAADC_STATE_CALIBRATION) + { + m_cb.adc_state = NRF_SAADC_STATE_IDLE; + } + else + { + // Wait for ADC being stopped. + bool result; + NRFX_WAIT_FOR((m_cb.adc_state != NRF_SAADC_STATE_IDLE), HW_TIMEOUT, 0, result); + NRFX_ASSERT(result); + } + + nrf_saadc_int_disable(NRF_SAADC_INT_STOPPED); + + m_cb.p_buffer = 0; + m_cb.p_secondary_buffer = 0; + NRFX_LOG_INFO("Conversion aborted."); + } +} + + +void nrfx_saadc_limits_set(uint8_t channel, int16_t limit_low, int16_t limit_high) +{ + NRFX_ASSERT(m_cb.state != NRFX_DRV_STATE_UNINITIALIZED); + NRFX_ASSERT(m_cb.event_handler); // only non blocking mode supported + NRFX_ASSERT(limit_low >= NRFX_SAADC_LIMITL_DISABLED); + NRFX_ASSERT(limit_high <= NRFX_SAADC_LIMITH_DISABLED); + NRFX_ASSERT(limit_low < limit_high); + nrf_saadc_channel_limits_set(channel, limit_low, limit_high); + + uint32_t int_mask = nrf_saadc_limit_int_get(channel, NRF_SAADC_LIMIT_LOW); + if (limit_low == NRFX_SAADC_LIMITL_DISABLED) + { + m_cb.limits_enabled_flags &= ~(0x80000000 >> LOW_LIMIT_TO_FLAG(channel)); + nrf_saadc_int_disable(int_mask); + } + else + { + m_cb.limits_enabled_flags |= (0x80000000 >> LOW_LIMIT_TO_FLAG(channel)); + nrf_saadc_int_enable(int_mask); + } + + int_mask = nrf_saadc_limit_int_get(channel, NRF_SAADC_LIMIT_HIGH); + if (limit_high == NRFX_SAADC_LIMITH_DISABLED) + { + m_cb.limits_enabled_flags &= ~(0x80000000 >> HIGH_LIMIT_TO_FLAG(channel)); + nrf_saadc_int_disable(int_mask); + } + else + { + m_cb.limits_enabled_flags |= (0x80000000 >> HIGH_LIMIT_TO_FLAG(channel)); + nrf_saadc_int_enable(int_mask); + } +} +#endif // NRFX_CHECK(NRFX_SAADC_ENABLED) |