<?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>Just getting started with Tasks and Events: PWM =&amp;gt; SAADC</title><link>https://devzone.nordicsemi.com/f/nordic-q-a/27967/just-getting-started-with-tasks-and-events-pwm-saadc</link><description>Coming from other embedded systems, I&amp;#39;m impressed with the flexibility and power of the Task/Event framework of the nRF52832. But with great flexibility comes great confusion! :) 
 I&amp;#39;d like to do something along these lines, written here in pidgin C</description><dc:language>en-US</dc:language><generator>Telligent Community 13</generator><lastBuildDate>Fri, 10 Apr 2020 01:09:02 GMT</lastBuildDate><atom:link rel="self" type="application/rss+xml" href="https://devzone.nordicsemi.com/f/nordic-q-a/27967/just-getting-started-with-tasks-and-events-pwm-saadc" /><item><title>RE: Just getting started with Tasks and Events: PWM =&gt; SAADC</title><link>https://devzone.nordicsemi.com/thread/244204?ContentTypeID=1</link><pubDate>Fri, 10 Apr 2020 01:09:02 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:e15c3415-d4d4-48f8-bf45-b7d9ce266719</guid><dc:creator>Felix</dc:creator><description>&lt;p&gt;Thank you Torborn;&amp;nbsp; why can&amp;#39;t the SDK provide examples like this instead of the overcomplicated macro hell it does;&amp;nbsp;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: Just getting started with Tasks and Events: PWM =&gt; SAADC</title><link>https://devzone.nordicsemi.com/thread/110353?ContentTypeID=1</link><pubDate>Thu, 07 Dec 2017 08:08:37 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:26277c9c-cab2-4e31-a9b4-5c54ae1cafda</guid><dc:creator>ovrebekk</dc:creator><description>&lt;p&gt;I am happy to help :)&lt;/p&gt;
&lt;p&gt;The best of luck with your project!&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: Just getting started with Tasks and Events: PWM =&gt; SAADC</title><link>https://devzone.nordicsemi.com/thread/110352?ContentTypeID=1</link><pubDate>Wed, 06 Dec 2017 14:33:01 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:60553977-4df2-4d75-8a3d-8c2d029ab4de</guid><dc:creator>rdpoor</dc:creator><description>&lt;p&gt;This is brilliant, and exactly the kind of answer I needed because it jump-starts my understanding of the PPI system &lt;em&gt;and&lt;/em&gt; prevents me from going down the wrong path.  Thank you very much for the prompt and detailed response!&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: Just getting started with Tasks and Events: PWM =&gt; SAADC</title><link>https://devzone.nordicsemi.com/thread/110351?ContentTypeID=1</link><pubDate>Wed, 06 Dec 2017 13:36:30 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:94f7bf7d-532f-40be-8db2-04cb79caddd7</guid><dc:creator>ovrebekk</dc:creator><description>&lt;p&gt;Hi&lt;/p&gt;
&lt;p&gt;You can indeed do a lot of fun stuff with the task/event system, but finding the best way to do things is not always easy ;)&lt;/p&gt;
&lt;p&gt;I don&amp;#39;t think the PWM module is the way to go here, unless you need to change the duty cycle of the two pins dynamically. Instead I would propose a method using a TIMER and the GPIOTE, together with the SAADC and the PPI.&lt;/p&gt;
&lt;p&gt;The TIMER modules have multiple compare registers, that can be used to trigger activities at different times through the PPI controller.&lt;/p&gt;
&lt;p&gt;I wrote a small example to show how you can have the timer toggle the pins and sample the ADC at different times:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;#define GPIOTE_CH_A 0
#define GPIOTE_CH_B 1

#define PIN_A       10
#define PIN_B       11

#define PPI_CH_A    0
#define PPI_CH_B    1
#define PPI_CH_C    2

#define DELAY_IO_FLIP_US    10
#define DELAY_ADC_SAMPLE_US 10

static void timer_init(void)
{
    // Set up the timer for a 1MHz rate, configure 2 different delays, and have it auto clear on CC[1]
    ADC_TIMER-&amp;gt;PRESCALER = 4;
    ADC_TIMER-&amp;gt;CC[0] = DELAY_IO_FLIP_US;
    ADC_TIMER-&amp;gt;CC[1] = DELAY_IO_FLIP_US + DELAY_ADC_SAMPLE_US;
    ADC_TIMER-&amp;gt;SHORTS = TIMER_SHORTS_COMPARE1_CLEAR_Msk;
    
    // Set up pin A in toggle mode, inital value low
    NRF_GPIOTE-&amp;gt;CONFIG[GPIOTE_CH_A] = GPIOTE_CONFIG_MODE_Task       &amp;lt;&amp;lt; GPIOTE_CONFIG_MODE_Pos | 
                                      GPIOTE_CONFIG_OUTINIT_Low     &amp;lt;&amp;lt; GPIOTE_CONFIG_OUTINIT_Pos |
                                      GPIOTE_CONFIG_POLARITY_Toggle &amp;lt;&amp;lt; GPIOTE_CONFIG_POLARITY_Pos |
                                      PIN_A                         &amp;lt;&amp;lt; GPIOTE_CONFIG_PSEL_Pos;
    
    // Set up pin B in toggle mode, initial value high
    NRF_GPIOTE-&amp;gt;CONFIG[GPIOTE_CH_B] = GPIOTE_CONFIG_MODE_Task       &amp;lt;&amp;lt; GPIOTE_CONFIG_MODE_Pos | 
                                      GPIOTE_CONFIG_OUTINIT_High    &amp;lt;&amp;lt; GPIOTE_CONFIG_OUTINIT_Pos |
                                      GPIOTE_CONFIG_POLARITY_Toggle &amp;lt;&amp;lt; GPIOTE_CONFIG_POLARITY_Pos |
                                      PIN_B                         &amp;lt;&amp;lt; GPIOTE_CONFIG_PSEL_Pos;
    
    // Have CC[0] in the timer toggle both pin A and pin B (using the FORK feature to control two tasks)
    NRF_PPI-&amp;gt;CH[PPI_CH_A].EEP   = (uint32_t)&amp;amp;ADC_TIMER-&amp;gt;EVENTS_COMPARE[0];
    NRF_PPI-&amp;gt;CH[PPI_CH_A].TEP   = (uint32_t)&amp;amp;NRF_GPIOTE-&amp;gt;TASKS_OUT[GPIOTE_CH_A];
    NRF_PPI-&amp;gt;FORK[PPI_CH_A].TEP = (uint32_t)&amp;amp;NRF_GPIOTE-&amp;gt;TASKS_OUT[GPIOTE_CH_B];
    NRF_PPI-&amp;gt;CHENSET = (1 &amp;lt;&amp;lt; PPI_CH_A);
    
    // Have CC[1] trigger an ADC sample
    NRF_PPI-&amp;gt;CH[PPI_CH_B].EEP   = (uint32_t)&amp;amp;ADC_TIMER-&amp;gt;EVENTS_COMPARE[1];
    NRF_PPI-&amp;gt;CH[PPI_CH_B].TEP   = (uint32_t)&amp;amp;NRF_SAADC-&amp;gt;TASKS_SAMPLE;
    NRF_PPI-&amp;gt;CHENSET = (1 &amp;lt;&amp;lt; PPI_CH_B);
    
    // Stop the timer once the ADC buffer is full
    NRF_PPI-&amp;gt;CH[PPI_CH_C].EEP   = (uint32_t)&amp;amp;NRF_SAADC-&amp;gt;EVENTS_END;
    NRF_PPI-&amp;gt;CH[PPI_CH_C].TEP   = (uint32_t)&amp;amp;ADC_TIMER-&amp;gt;TASKS_STOP;
    NRF_PPI-&amp;gt;CHENSET = (1 &amp;lt;&amp;lt; PPI_CH_C);      
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I haven&amp;#39;t included the ADC configuration, but essentially the length of the configured buffer will determine how long the total operation will take. When the END event in the SAADC module occurs the timer will be stopped, and you can use the same event to trigger an interrupt.&lt;/p&gt;
&lt;p&gt;To start the operation simply activate the START tasks of the timer and ADC:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;static void adc_read()
{
    NRF_SAADC-&amp;gt;TASKS_START = 1;
    ADC_TIMER-&amp;gt;TASKS_START = 1;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Please be aware that the code compiles, but is not tested ;)&lt;/p&gt;
&lt;p&gt;Best regards&lt;br /&gt;
Torbørn&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item></channel></rss>