<?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>Triggering SAADC sampling in synchronous with GPIO HITOLOW transition.</title><link>https://devzone.nordicsemi.com/f/nordic-q-a/71603/triggering-saadc-sampling-in-synchronous-with-gpio-hitolow-transition</link><description>Product: nrf52840 DK 
 Softdevice: 17.0.2 
 
 Hello, 
 
 I would like to start with a very humble statement that I am new to this nrf52 SoCs and would appreciate any of your help. 
 I am working on a project with a photodiode and two LEDs with different</description><dc:language>en-US</dc:language><generator>Telligent Community 13</generator><lastBuildDate>Mon, 22 Feb 2021 10:21:40 GMT</lastBuildDate><atom:link rel="self" type="application/rss+xml" href="https://devzone.nordicsemi.com/f/nordic-q-a/71603/triggering-saadc-sampling-in-synchronous-with-gpio-hitolow-transition" /><item><title>RE: Triggering SAADC sampling in synchronous with GPIO HITOLOW transition.</title><link>https://devzone.nordicsemi.com/thread/295527?ContentTypeID=1</link><pubDate>Mon, 22 Feb 2021 10:21:40 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:214ecf0b-efb4-4b95-bd8f-4c3d37abfe6d</guid><dc:creator>J&amp;#248;rgen Holmefjord</dc:creator><description>&lt;p&gt;Thanks, it is clear now.&lt;/p&gt;
&lt;p&gt;The CONNECTED event is a software event, so this cannot be used to trigger any tasks through PPI. You will have to trigger the tasks from software. You can also use an additional compare event to trigger the tasks through PPI very close after the event is received. If you do not require the GPIO to toggle exactly when the CONNECTED event is received, you can start the timer in software to toggle the GPIO after the first 10ms have passed.&lt;/p&gt;
&lt;p&gt;As far as I can see, you should be able to use the timer compare event that toggles the GPIO to trigger the START task of the timer that triggers SAADC sampling. This should trigger the first sampling 100us after the GPIO toggles. If you want to trigger a sample at the same time that the GPIO is toggled, you can also trigger the SAMPLE task from the timer event that toggles the GPIO(s). If you set a SAADC buffer size equal to the number of samples between GPIO toggling, you should be able to use the compare events from the GPIO timer to START the SAADC sampling at the regular interval that you have shown in your timing diagram.&lt;/p&gt;
[quote user="Kalrz "]I am confused about where to allocate the PPI event and tasks. Is it inside the callback handler of the SAADC?[/quote]
&lt;p&gt;The address of the tasks and events are static and documented in the&amp;nbsp;&lt;a title="Registers" href="https://infocenter.nordicsemi.com/topic/ps_nrf52840/saadc.html?cp=4_0_0_5_22_8#topic"&gt;Registers&lt;/a&gt;&amp;nbsp;section of each peripheral chapter in the product specifications. You should be able to configure this at any location in your code.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: Triggering SAADC sampling in synchronous with GPIO HITOLOW transition.</title><link>https://devzone.nordicsemi.com/thread/295401?ContentTypeID=1</link><pubDate>Fri, 19 Feb 2021 16:31:28 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:b6fd1680-2282-4d37-8290-7b1ca12b0846</guid><dc:creator>Kalrz </dc:creator><description>&lt;p&gt;Hai Jorgen,&lt;/p&gt;
&lt;p&gt;Sorry, I should have been more clear.&lt;/p&gt;
[quote userid="14926" url="~/f/nordic-q-a/71603/triggering-saadc-sampling-in-synchronous-with-gpio-hitolow-transition/295048#295048"]Can you create a timing diagram that shows the toggling of the LEDs and when you want the SAADC sampling to happen?[/quote]
&lt;p&gt;&lt;a href="https://devzone.nordicsemi.com/resized-image/__size/320x240/__key/communityserver-discussions-components-files/4/7532.img.jpg"&gt;/resized-image/__size/320x240/__key/communityserver-discussions-components-files/4/7532.img.jpg&lt;/a&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;(Please inform me if the image is not clear enough. I am not sure about it)&lt;/p&gt;
&lt;p&gt;At the moment both the GPIOs are triggered via PPI using a single timer. SAADC sampling is triggered every 0.1ms using another timer through PPI. These two methods are clearly mentioned in my previous reply. Now as you can see from the timing diagram, I need my GPIO and SAADC sampling to be triggered at the CONNECTED event from the BLE application (As you suggested). How can I connect the CONNECTED event, GPIOs, and SAADC to be all triggered at the same time through PPI? Is it possible for you to provide a brief line of code just to show how it should be carried out? I am confused about where to allocate the PPI event and tasks. Is it inside the callback handler of the SAADC?&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Thanks.&lt;/p&gt;
&lt;p&gt;Best regards.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: Triggering SAADC sampling in synchronous with GPIO HITOLOW transition.</title><link>https://devzone.nordicsemi.com/thread/295048?ContentTypeID=1</link><pubDate>Thu, 18 Feb 2021 10:27:51 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:e9176231-af97-4b5c-8fe9-401c3fc5acf5</guid><dc:creator>J&amp;#248;rgen Holmefjord</dc:creator><description>[quote user="Kalrz "]So should I use the same timer for both SAADC and GPIOs? ( which i believe is not the solution). Or should I use a separate PPI channel to assign the two timers (timer instance 1 and 2) to each other and then use another PPI channel to assign the timer instance 2 with SAADC for triggering sample? I don&amp;#39;t quite understand this. So can you please elaborate?[/quote]
&lt;p&gt;I may have misunderstood how and when you want to sample the SAADC. Can you create a timing diagram that shows the toggling of the LEDs and when you want the SAADC sampling to happen?&lt;/p&gt;
[quote user="Kalrz "]&lt;blockquote&gt;&lt;div&gt;&lt;a href="https://devzone.nordicsemi.com/f/nordic-q-a/71603/triggering-saadc-sampling-in-synchronous-with-gpio-hitolow-transition/294434#294434"&gt;Jørgen Holmefjord said:&lt;/a&gt;&lt;/div&gt;&lt;div&gt; separate GPIOTE channel as input (configured as watcher), and physically connect the output and input pins together externally.&lt;/div&gt;&lt;/blockquote&gt;&lt;div&gt;&lt;/div&gt;
&lt;p&gt;At the moment, I would prefer any other method without an additional external physical connection.&lt;/p&gt;[/quote]
&lt;p&gt;If things are triggered by events over PPI, it should be possible to synchronize it with PPI forks, or multiple PPI channels, but it depends on how things are triggered, and the required timing accuracy.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: Triggering SAADC sampling in synchronous with GPIO HITOLOW transition.</title><link>https://devzone.nordicsemi.com/thread/294491?ContentTypeID=1</link><pubDate>Mon, 15 Feb 2021 20:59:40 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:9c5d8b9f-6e92-4167-b883-8a9fc66c5aee</guid><dc:creator>Kalrz </dc:creator><description>&lt;p&gt;Hello Jorgen,&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;Thank for the reply.&lt;/p&gt;
&lt;p&gt;So let me see if I understood you correctly. Yes the GPIOs are configured in the output of GPIOTE.&amp;nbsp;&lt;pre class="ui-code" data-mode="c_cpp"&gt;    nrf_drv_gpiote_out_config_t config1 = GPIOTE_CONFIG_OUT_TASK_TOGGLE(true);
    nrf_drv_gpiote_out_config_t config2 = GPIOTE_CONFIG_OUT_TASK_TOGGLE(true);
   
    uint32_t err_code;

    err_code = nrfx_gpiote_out_init(GPIO_OUTPUT_PIN_NUMBER1, &amp;amp;config1);
    APP_ERROR_CHECK(err_code);
    err_code = nrfx_gpiote_out_init(GPIO_OUTPUT_PIN_NUMBER2, &amp;amp;config2);
    APP_ERROR_CHECK(err_code);&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;I have two PPI channels allocated for task and event mapping.&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="c_cpp"&gt;    nrf_ppi_channel_t ppi_channel1;
    nrf_ppi_channel_t ppi_channel2;
    
    err_code = nrf_drv_ppi_channel_alloc(&amp;amp;ppi_channel1);
    APP_ERROR_CHECK(err_code);
    err_code = nrf_drv_ppi_channel_alloc(&amp;amp;ppi_channel2);
    APP_ERROR_CHECK(err_code);&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;Then I use a timer to trigger at each 20ms. With the use of the code below, I manage to toggle the GPIOs alternatively.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="c_cpp"&gt;uint32_t ticks_RED = nrfx_timer_ms_to_ticks(&amp;amp;timer, 20);

    nrf_drv_timer_compare(&amp;amp;timer, NRF_TIMER_CC_CHANNEL0, (ticks_RED/2), true);
    nrf_drv_timer_extended_compare(&amp;amp;timer, NRF_TIMER_CC_CHANNEL1, ticks_RED, NRF_TIMER_SHORT_COMPARE1_CLEAR_MASK, true);&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;Then I get the address of both event and task and assign them to each PPI channel and finally enable the channels and gpiote. PPI, timer and GPIOTE are initialized inside the main()&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="c_cpp"&gt;    compare_evt_addr1 = nrf_drv_timer_event_address_get(&amp;amp;timer, NRF_TIMER_EVENT_COMPARE0);
    gpiote_task_addr1 = nrf_drv_gpiote_out_task_addr_get(GPIO_OUTPUT_PIN_NUMBER1);

    compare_evt_addr2 = nrf_drv_timer_event_address_get(&amp;amp;timer, NRF_TIMER_EVENT_COMPARE1);
    gpiote_task_addr2 = nrf_drv_gpiote_out_task_addr_get(GPIO_OUTPUT_PIN_NUMBER2);
    
    err_code = nrf_drv_ppi_channel_assign(ppi_channel1, compare_evt_addr1, gpiote_task_addr1);
    APP_ERROR_CHECK(err_code);
    err_code = nrf_drv_ppi_channel_assign(ppi_channel2, compare_evt_addr2, gpiote_task_addr2);
    APP_ERROR_CHECK(err_code);
    
    err_code = nrf_drv_ppi_channel_enable(ppi_channel1);
    APP_ERROR_CHECK(err_code);
    err_code = nrf_drv_ppi_channel_enable(ppi_channel2);
    APP_ERROR_CHECK(err_code);

    nrf_drv_gpiote_out_task_enable(GPIO_OUTPUT_PIN_NUMBER1);
    nrf_drv_gpiote_out_task_enable(GPIO_OUTPUT_PIN_NUMBER2);&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;/***************************SAADC*****************************/&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;For the SAADC right now I am using a single channel with 12-bit resolution.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Here in SAADC I need to sample every 1ms or even lesser than that. Let&amp;#39;s say 1ms. So I have a separate timer instance initialized for triggering sampling. Here I use PPI where the timer compare event of timer instance (2) is triggering sample task in SAADC.&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="c_cpp"&gt;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 1ms */
    uint32_t ticks = nrf_drv_timer_ms_to_ticks(&amp;amp;m_timer, 1);
    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);
}

void saadc_callback(nrf_drv_saadc_evt_t const * p_event)
{

    //NRF_LOG_INFO(&amp;quot;SAADC event is %d&amp;quot;, p_event-&amp;gt;type);
    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);
        
        uint16_t value;
        value = p_event-&amp;gt;data.done.p_buffer[];
        for(i=0; i&amp;lt;SAMPLES_IN_BUFFER; i++)
        {
        NRF_LOG_INFO(&amp;quot;%d&amp;quot;, p_event-&amp;gt;data.done.p_buffer[i]);
        }
    }
}&lt;/pre&gt;.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
[quote userid="14926" url="~/f/nordic-q-a/71603/triggering-saadc-sampling-in-synchronous-with-gpio-hitolow-transition/294434#294434"]You either need to use the event that toggles the GPIO to start the TIMER/SAADC sampling through PPI,[/quote]
&lt;p&gt;If I am not wrong, the event that toggles the GPIO is&amp;nbsp;&lt;pre class="ui-code" data-mode="text"&gt;compare_evt_addr1 = nrf_drv_timer_event_address_get(&amp;amp;timer, NRF_TIMER_EVENT_COMPARE0);&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;So should I use the same timer for both SAADC and GPIOs? ( which i believe is not the solution). Or should I use a separate PPI channel to assign the two timers (timer instance 1 and 2) to each other and then use another PPI channel to assign the timer instance 2 with SAADC for triggering sample? I don&amp;#39;t quite understand this. So can you please elaborate?&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
[quote userid="14926" url="~/f/nordic-q-a/71603/triggering-saadc-sampling-in-synchronous-with-gpio-hitolow-transition/294434#294434"] separate GPIOTE channel as input (configured as watcher), and physically connect the output and input pins together externally.[/quote]
&lt;p&gt;At the moment, I would prefer any other method without an additional external physical connection.&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;Thanks in advance.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: Triggering SAADC sampling in synchronous with GPIO HITOLOW transition.</title><link>https://devzone.nordicsemi.com/thread/294434?ContentTypeID=1</link><pubDate>Mon, 15 Feb 2021 15:36:40 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:78494610-4f36-46d9-9304-af0e102af314</guid><dc:creator>J&amp;#248;rgen Holmefjord</dc:creator><description>&lt;p&gt;Hi,&lt;/p&gt;
[quote user=""]&lt;p&gt;1. How can I use the interrupt at the rising edge of the GPIO1 to trigger the SAADC sampling? This is crucial because the first 100 readings from the SAADC will be the analog value from the photosensor caused due to LED1 and the next 100 readings will be generated due to&amp;nbsp;LED2.&amp;nbsp;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;2. Is this approach the correct method or is there&lt;strong&gt; any other better method&lt;/strong&gt;?&lt;/p&gt;[/quote]
&lt;p&gt;If GPIO1 is configured as an output in GPIOTE, you will not get any interrupt on the rising edge of this GPIO. You either need to use the event that toggles the GPIO to start the TIMER/SAADC sampling through PPI, or setup a separate GPIOTE channel as input (configured as watcher), and physically connect the output and input pins together externally.&lt;/p&gt;
[quote user=""]3. This question covers a different issue but still, I would like to ask. My application is using a BLE features to send the analog value to a central device. Values are sent to the central device inside the saadc_callback handler. If I had to start the sampling and the GPIO output state transition only after a successful connection is established with the central device, what would be the right way to program the firmware? Are there existing example codes explaining similar usage? (I believe the answer is YES. But I was not able to find any. Please help me out with this.)[/quote]
&lt;p&gt;The simplest solution would be to enable the PPI channel(s) when you receive the CONNECTED event in the application, and similarly, disable the PPI channel(s) when you receive the DISCONNECTED event.&lt;/p&gt;
&lt;p&gt;Best regards,&lt;br /&gt;Jørgen&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item></channel></rss>