<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="https://devzone.nordicsemi.com/cfs-file/__key/system/syndication/rss.xsl" media="screen"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Interfacing SAADC with BLE: Timer issue?</title><link>https://devzone.nordicsemi.com/f/nordic-q-a/97954/interfacing-saadc-with-ble-timer-issue</link><description>Hi, 
 I&amp;#39;m trying to combine the SAADC example with the ble_app_template (nRF 5 SDK 17.1.0, currently I&amp;#39;m on nRF52 DK, later we will use a custom board with nRF52832). I want to sample data at 16 kHz (Sampling interval = 4 ms, samples in buffer = 64) and</description><dc:language>en-US</dc:language><generator>Telligent Community 13</generator><lastBuildDate>Tue, 02 May 2023 09:43:14 GMT</lastBuildDate><atom:link rel="self" type="application/rss+xml" href="https://devzone.nordicsemi.com/f/nordic-q-a/97954/interfacing-saadc-with-ble-timer-issue" /><item><title>RE: Interfacing SAADC with BLE: Timer issue?</title><link>https://devzone.nordicsemi.com/thread/423230?ContentTypeID=1</link><pubDate>Tue, 02 May 2023 09:43:14 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:df939959-e52d-4737-8c1a-2b339ffa02bb</guid><dc:creator>Moritz_S</dc:creator><description>&lt;p&gt;I changed everything to continuous mode, so I could remove the nrf_drv_timer library. Everything works fine now.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: Interfacing SAADC with BLE: Timer issue?</title><link>https://devzone.nordicsemi.com/thread/423215?ContentTypeID=1</link><pubDate>Tue, 02 May 2023 08:58:44 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:7f050fff-81eb-423f-80dc-e2977a3cd07b</guid><dc:creator>Sigurd</dc:creator><description>&lt;p&gt;Hi,&lt;/p&gt;
[quote user="Moritz_S"]I&amp;#39;m thinking about switching the code to the ADC&amp;#39;s continuous mode. In my opinion this would&amp;nbsp;avoid the problem we discuss here [/quote]
&lt;p&gt;&lt;span&gt;I believe&amp;nbsp;continuous&amp;nbsp;mode&amp;nbsp;should&amp;nbsp;&lt;/span&gt;improve this situation. Let me know if that was not case.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: Interfacing SAADC with BLE: Timer issue?</title><link>https://devzone.nordicsemi.com/thread/417098?ContentTypeID=1</link><pubDate>Thu, 23 Mar 2023 13:23:15 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:3f3f7179-bc10-46ae-accb-bb9ea5d80ebb</guid><dc:creator>Moritz_S</dc:creator><description>&lt;p&gt;Hi,&lt;/p&gt;
&lt;p&gt;yes, absolutely. I&amp;#39;m using the m_adc_evt_counter provided in the SDK&amp;#39;s SAADC example. You can check the code below (I included all the includes but removed irrelevant code).&lt;br /&gt;&lt;br /&gt;I&amp;#39;m thinking about switching the code to the ADC&amp;#39;s continuous mode. In my opinion this would&amp;nbsp;avoid the problem we discuss here or do you think this problem is caused by something else and that I would face it also in the continuous mode?&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="c_cpp"&gt;#include &amp;quot;nordic_common.h&amp;quot;
#include &amp;quot;nrf.h&amp;quot;

#include &amp;quot;app_error.h&amp;quot;
#include &amp;quot;app_timer.h&amp;quot;
#include &amp;quot;app_util_platform.h&amp;quot;

#include &amp;quot;ble.h&amp;quot;
#include &amp;quot;ble_hci.h&amp;quot;
#include &amp;quot;ble_srv_common.h&amp;quot;
#include &amp;quot;ble_advdata.h&amp;quot;
#include &amp;quot;ble_advertising.h&amp;quot;
#include &amp;quot;ble_conn_params.h&amp;quot;
#include &amp;quot;nrf_sdh.h&amp;quot;
#include &amp;quot;nrf_sdh_soc.h&amp;quot;
#include &amp;quot;nrf_sdh_ble.h&amp;quot;
#include &amp;quot;fds.h&amp;quot;
#include &amp;quot;peer_manager.h&amp;quot;
#include &amp;quot;peer_manager_handler.h&amp;quot;
#include &amp;quot;bsp_btn_ble.h&amp;quot;
#include &amp;quot;sensorsim.h&amp;quot;
#include &amp;quot;ble_conn_state.h&amp;quot;
#include &amp;quot;nrf_ble_gatt.h&amp;quot;
#include &amp;quot;nrf_ble_qwr.h&amp;quot;
#include &amp;quot;nrf_pwr_mgmt.h&amp;quot;
#include &amp;quot;nrf_gpio.h&amp;quot;

#include &amp;quot;nrf_log.h&amp;quot;
#include &amp;quot;nrf_log_ctrl.h&amp;quot;
#include &amp;quot;nrf_log_default_backends.h&amp;quot;

#include &amp;quot;boards.h&amp;quot;
#include &amp;quot;nrf_queue.h&amp;quot;

// FROM SAADC EXAMPLE
#include &amp;quot;nrf_drv_saadc.h&amp;quot;
#include &amp;quot;nrf_drv_ppi.h&amp;quot;
#include &amp;quot;nrf_drv_timer.h&amp;quot;

static const nrf_drv_timer_t m_timer = NRF_DRV_TIMER_INSTANCE(2);
static nrf_saadc_value_t     m_buffer_pool[2][SAMPLES_IN_BUFFER];
static nrf_ppi_channel_t     m_ppi_channel;
static uint32_t              m_adc_evt_counter;

static const nrf_drv_saadc_config_t saadc_config = {
    .resolution = NRF_SAADC_RESOLUTION_12BIT,
    .oversample = NRF_SAADC_OVERSAMPLE_DISABLED,
    .interrupt_priority = 6,
    .low_power_mode = false
};

void timer_handler(nrf_timer_event_t event_type, void * p_context)
{
    NRF_LOG_INFO(&amp;quot;Timer called&amp;quot;);
}

void saadc_sampling_event_init(void)
{
    ret_code_t err_code;

    err_code = nrf_drv_ppi_init();
    APP_ERROR_CHECK(err_code);

    nrf_drv_timer_config_t timer_cfg = NRF_DRV_TIMER_DEFAULT_CONFIG;
    timer_cfg.bit_width = NRF_TIMER_BIT_WIDTH_32;
    err_code = nrf_drv_timer_init(&amp;amp;m_timer, &amp;amp;timer_cfg, timer_handler);
    APP_ERROR_CHECK(err_code);

    /* setup m_timer for compare event every 4 ms */
    uint32_t ticks = nrf_drv_timer_ms_to_ticks(&amp;amp;m_timer, SAMPLING_INTERVAL_MS);

    nrf_drv_timer_extended_compare(&amp;amp;m_timer,
                                   NRF_TIMER_CC_CHANNEL0,
                                   ticks,
                                   NRF_TIMER_SHORT_COMPARE0_CLEAR_MASK,
                                   false);
    nrf_drv_timer_enable(&amp;amp;m_timer);

    uint32_t timer_compare_event_addr = nrf_drv_timer_compare_event_address_get(&amp;amp;m_timer,
                                                                                NRF_TIMER_CC_CHANNEL0);
    uint32_t saadc_sample_task_addr   = nrf_drv_saadc_sample_task_get();

    /* setup ppi channel so that timer compare event is triggering sample task in SAADC */
    err_code = nrf_drv_ppi_channel_alloc(&amp;amp;m_ppi_channel);
    APP_ERROR_CHECK(err_code);

    err_code = nrf_drv_ppi_channel_assign(m_ppi_channel,
                                          timer_compare_event_addr,
                                          saadc_sample_task_addr);
    APP_ERROR_CHECK(err_code);
}


static int saadc_sampling_event_enable(void)
{
    uint32_t err_code = nrf_drv_ppi_channel_enable(m_ppi_channel);
    APP_ERROR_CHECK(err_code);

    return err_code;
}

static int saadc_sampling_event_disable(void)
{
    uint32_t err_code = nrf_drv_ppi_channel_disable(m_ppi_channel);
    APP_ERROR_CHECK(err_code);

    return err_code;
}


void saadc_callback(nrf_drv_saadc_evt_t const * p_event)
{
    if (p_event-&amp;gt;type == NRF_DRV_SAADC_EVT_DONE)
    {
        ret_code_t err_code;

        err_code = nrf_drv_saadc_buffer_convert(p_event-&amp;gt;data.done.p_buffer, SAMPLES_IN_BUFFER);
        APP_ERROR_CHECK(err_code);

        bytes_recv += (SAMPLES_IN_BUFFER * 2);
        sample_no += SAMPLES_IN_BUFFER;

        err_code = nrf_queue_write(&amp;amp;m_queue, &amp;amp;p_event-&amp;gt;data.done.p_buffer, (size_t) SAMPLES_IN_BUFFER);
        if (err_code != NRF_SUCCESS)
        {
            if (err_code == NRF_ERROR_NO_MEM)
            {
                NRF_LOG_DEBUG(&amp;quot;Queue full&amp;quot;);
            }
            else
            {
                APP_ERROR_CHECK(err_code);
            }
        }

        m_adc_evt_counter++;

        if ((m_adc_evt_counter%21) == 0) {
            NRF_LOG_INFO(&amp;quot;Bytes added to queue: %d&amp;quot;, bytes_recv);
            NRF_LOG_INFO(&amp;quot;ADC events: %d&amp;quot;, m_adc_evt_counter);
            NRF_LOG_INFO(&amp;quot;SAADC Callback: Current queue utilization: %d&amp;quot;, ((int) nrf_queue_utilization_get(&amp;amp;m_queue)));
        }
    }
}


static int saadc_init(void)
{
    uint32_t err_code;
    nrf_saadc_channel_config_t channel_config =
        NRF_DRV_SAADC_DEFAULT_CHANNEL_CONFIG_SE(NRF_SAADC_INPUT_AIN0);

    //err_code = nrf_drv_saadc_init(NULL, saadc_callback);
    err_code = nrf_drv_saadc_init(&amp;amp;saadc_config, saadc_callback);
    APP_ERROR_CHECK(err_code);

    err_code = nrf_drv_saadc_channel_init(0, &amp;amp;channel_config);
    APP_ERROR_CHECK(err_code);

    err_code = nrf_drv_saadc_buffer_convert(m_buffer_pool[0], SAMPLES_IN_BUFFER);
    APP_ERROR_CHECK(err_code);

    err_code = nrf_drv_saadc_buffer_convert(m_buffer_pool[1], SAMPLES_IN_BUFFER);
    APP_ERROR_CHECK(err_code);

    return err_code;
}

/**@brief Function for application main entry.
 */
int main(void)
{
    bool erase_bonds;
    uint32_t err_code;
    uint32_t reading_from_queue = 0;
    uint8_t len_m16_array = (sizeof(m16_array) / sizeof(uint16_t));

    // Initialize.
    log_init();
    timers_init();
    buttons_leds_init(&amp;amp;erase_bonds);
    power_management_init();

    // Go to system-off mode (this function will not return; wakeup will cause a reset).
    uint32_t wdt_reset;
    wdt_reset = NRF_POWER-&amp;gt;RESETREAS;
    NRF_LOG_INFO(&amp;quot;reset: 0x%08x&amp;quot;, wdt_reset);
    if (NRF_POWER-&amp;gt;RESETREAS == (0x00000004))
    {
        nrf_pwr_mgmt_shutdown(NRF_PWR_MGMT_SHUTDOWN_GOTO_SYSOFF);
    }

    // Initialize BLE
    ble_stack_init();
    gap_params_init();
    gatt_init();
    services_init();
    advertising_init();
    conn_params_init();
    peer_manager_init();

    // Initialize SAADC
    err_code = saadc_init();
    if (err_code == NRF_SUCCESS)
    {
        NRF_LOG_INFO(&amp;quot;SAADC successfully initialized.&amp;quot;);
    }
    else
    {
        NRF_LOG_INFO(&amp;quot;Error initializing SAADC.&amp;quot;);
    }

    saadc_sampling_event_init();
    
    // Start advertising
    advertising_start(erase_bonds);

    for (;;)
    {
        if (audio_transfer)
        {
            if (saadc_active != true)
            {
                err_code = saadc_sampling_event_enable();

                if (err_code == NRF_SUCCESS)
                {
                    saadc_active = true;
                    NRF_LOG_INFO(&amp;quot;SAADC started.\n&amp;quot;);
                } 
                else
                {
                    NRF_LOG_INFO(&amp;quot;Error starting SAADC.\n&amp;quot;);
                }
            }

            #ifdef SsRF01
                nrf_gpio_pin_toggle(LED_1);
            #elif BOARD_PCA10040
                nrf_gpio_pin_toggle(LED_3);
            #endif

            // set back err_code
            err_code = NRF_SUCCESS;

            if (nrf_queue_utilization_get(&amp;amp;m_queue) &amp;gt; len_m16_array)
            {
                err_code = nrf_queue_read(&amp;amp;m_queue, &amp;amp;m16_array, (size_t) len_m16_array);
                reading_from_queue += 1;

                uint8_t x = sizeof(m16_array);

                if (err_code == NRF_SUCCESS)
                {
                    for (int i = 0; i &amp;lt; len_m16_array; i+=2)
                    {
                        m_array[i] = (uint8_t)((m16_array[i] &amp;amp; 0xFF00) &amp;gt;&amp;gt; 8);
                        m_array[i+1] = (uint8_t)(m16_array[i] &amp;amp; 0x00FF);
                    }

                    err_code = send_m_array();
                    bytes_read_from_buffer += data_length;
                }
                else if (err_code == NRF_ERROR_NOT_FOUND)
                {
                    NRF_LOG_DEBUG(&amp;quot;Not enough data in queue.&amp;quot;);
                    NRF_LOG_INFO(&amp;quot;Current queue utilization: %d&amp;quot;, ((int) nrf_queue_utilization_get(&amp;amp;m_queue)));
                }
                else
                {
                    APP_ERROR_CHECK(err_code);
                }
            }
        }

        if ((!audio_transfer) &amp;amp;&amp;amp;
            (saadc_active)
           )
        {
            saadc_sampling_event_disable();
            saadc_active = false;

            NRF_LOG_INFO(&amp;quot;ADC events: %d&amp;quot;, m_adc_evt_counter);
        }

        idle_state_handle();
        NRF_LOG_FLUSH();
    }

    bsp_board_leds_off();
}&lt;/pre&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: Interfacing SAADC with BLE: Timer issue?</title><link>https://devzone.nordicsemi.com/thread/417084?ContentTypeID=1</link><pubDate>Thu, 23 Mar 2023 13:04:20 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:6d3c9c34-9003-4622-bfca-81550cd0f637</guid><dc:creator>Sigurd</dc:creator><description>&lt;p&gt;Only 40 calls seems low.&lt;/p&gt;
&lt;p&gt;Could you post how your code looks like now?&lt;/p&gt;
&lt;p&gt;How are you measuring the number of calls?&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: Interfacing SAADC with BLE: Timer issue?</title><link>https://devzone.nordicsemi.com/thread/416590?ContentTypeID=1</link><pubDate>Tue, 21 Mar 2023 14:24:38 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:a0dbeaf5-2c7e-4451-aeac-318048f11f58</guid><dc:creator>Moritz_S</dc:creator><description>&lt;p&gt;over 10 seconds&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: Interfacing SAADC with BLE: Timer issue?</title><link>https://devzone.nordicsemi.com/thread/416588?ContentTypeID=1</link><pubDate>Tue, 21 Mar 2023 14:17:55 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:b7b9c4d0-aefc-43a4-9072-8d19bd7458f1</guid><dc:creator>Sigurd</dc:creator><description>[quote user="Moritz_S"]I&amp;#39;m only getting ~ 40 calls to saadc_callback().&amp;nbsp;[/quote]
&lt;p&gt;Over how long time?&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: Interfacing SAADC with BLE: Timer issue?</title><link>https://devzone.nordicsemi.com/thread/416579?ContentTypeID=1</link><pubDate>Tue, 21 Mar 2023 14:06:32 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:9e716246-b636-4d7c-ae56-4c737ffa9cad</guid><dc:creator>Moritz_S</dc:creator><description>&lt;p&gt;Hi,&lt;br /&gt;thanks for the quick response. Using your suggestion, I&amp;#39;m only getting ~ 40 calls to saadc_callback().&amp;nbsp;The calculated number of ticks seems correct when using a 16 MHz clock, but why does this not reflect in the number of calls?&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: Interfacing SAADC with BLE: Timer issue?</title><link>https://devzone.nordicsemi.com/thread/416572?ContentTypeID=1</link><pubDate>Tue, 21 Mar 2023 13:51:25 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:a0cf5f78-0ec0-4ad2-82e1-f355b72863a9</guid><dc:creator>Sigurd</dc:creator><description>&lt;p&gt;Hi,&lt;/p&gt;
&lt;p&gt;Try this:&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="text"&gt;    /* setup m_timer for compare event every 4 ms */
    uint32_t ticks = nrf_drv_timer_ms_to_ticks(&amp;amp;m_timer, SAMPLING_INTERVAL_MS);          // yields 64.000
    //uint32_t ticks_us = nrf_drv_timer_us_to_ticks(&amp;amp;m_timer, SAMPLING_INTERVAL_US);
    //uint32_t ticks = APP_TIMER_TICKS(SAMPLING_INTERVAL_MS);                                 // yields 66
    
    nrf_drv_timer_extended_compare(&amp;amp;m_timer,
                                   NRF_TIMER_CC_CHANNEL0,
                                   ticks,
                                   NRF_TIMER_SHORT_COMPARE0_CLEAR_MASK,
                                   false);
    nrf_drv_timer_enable(&amp;amp;m_timer);&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;APP_TIMER_TICKS() is for the application timer, &amp;quot;app_timer&amp;quot;,(it uses the RTC peripheral), but you are using nrf_drv_timer here(it uses the TIMER &lt;span&gt;peripheral&lt;/span&gt;), so you cannot use app_timer macros for the nrf_driver_timer, it&amp;#39;s 2 different libraries.&amp;nbsp;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item></channel></rss>