This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

PWM - Demo 1 Event Handler

For simplicity, I extracted the Demo 1 routine from the "pwm_driver" example which has 5 demos 'cause I thought it is simpler.

The code is shown below:

#include <stdbool.h>
#include <stdint.h>
#include "boards.h"
#include "nrf_drv_pwm.h"
#include "app_util_platform.h"
#include "app_error.h"
#include "boards.h"
#include "bsp.h"

#include "nrf_log.h"
#include "nrf_log_ctrl.h"
#include "nrf_log_default_backends.h"

static nrf_drv_pwm_t m_pwm0 = NRF_DRV_PWM_INSTANCE(0);

static uint16_t const              m_demo1_top  = 10000;
static uint16_t const              m_demo1_step = 50;
static uint8_t                     m_demo1_phase;
static nrf_pwm_values_individual_t m_demo1_seq_values;
static nrf_pwm_sequence_t const    m_demo1_seq =
{
    .values.p_individual = &m_demo1_seq_values,
    .length              = NRF_PWM_VALUES_LENGTH(m_demo1_seq_values),
    .repeats             = 0,
    .end_delay           = 0
};

static void demo1_handler( nrf_drv_pwm_evt_type_t event_type )
{
    if( event_type == NRF_DRV_PWM_EVT_FINISHED )
    {  
        uint8_t channel = m_demo1_phase >> 1;
        bool down       = m_demo1_phase & 1;
        bool next_phase = false;
        
        uint16_t * p_channels = (uint16_t*)&m_demo1_seq_values;
        uint16_t value = p_channels[channel];
        
        if(down)
        {
            value -= m_demo1_step;
            if( value == 0 )
            {
                next_phase = true;
            }
        }else
        {
            value += m_demo1_step;
            if( value >= m_demo1_top )
            {
                next_phase = true;
            }
        }
        p_channels[channel] = value;
        
        if (next_phase)
        {
            if (++m_demo1_phase >= 2 * NRF_PWM_CHANNEL_COUNT)
            {
                m_demo1_phase = 0;
            }
        }
    }
}

/**
 * @brief Function for application main entry.
 */
int main(void)
{
    uint32_t err_code;

    nrf_drv_pwm_config_t const config0 = 
    {
        .output_pins = 
        {
            BSP_LED_0 | NRF_DRV_PWM_PIN_INVERTED, // channel 0
            BSP_LED_1 | NRF_DRV_PWM_PIN_INVERTED, // channel 1
            BSP_LED_3 | NRF_DRV_PWM_PIN_INVERTED, // channel 2
            BSP_LED_2 | NRF_DRV_PWM_PIN_INVERTED  // channel 3
        },
        .irq_priority = APP_IRQ_PRIORITY_LOWEST,
        .base_clock   = NRF_PWM_CLK_1MHz,
        .count_mode   = NRF_PWM_MODE_UP,
        .top_value    = 10000,
        .load_mode    = NRF_PWM_LOAD_INDIVIDUAL,
        .step_mode    = NRF_PWM_STEP_AUTO
    };
    err_code = nrf_drv_pwm_init(&m_pwm0, &config0, demo1_handler);
    APP_ERROR_CHECK(err_code);
    
    m_demo1_seq_values.channel_0 = 0;
    m_demo1_seq_values.channel_1 = 0;
    m_demo1_seq_values.channel_2 = 0;
    m_demo1_seq_values.channel_3 = 0;
    m_demo1_phase                = 0;
    
    (void)nrf_drv_pwm_simple_playback(&m_pwm0, &m_demo1_seq, 1, 
                                      NRF_DRV_PWM_FLAG_LOOP);
    
    while (true)
    {
        // Wait for an event.
        __WFE();

        // Clear the event register.
        __SEV();
        __WFE();

        NRF_LOG_FLUSH();
    }
}

Can you please explain in detail what is going on inside the demo1_handler?

I can't seem to understand.

Thank you.

Parents
  • You have read the description, and watched what the demo does, haven't you?

    https://infocenter.nordicsemi.com/index.jsp?topic=%2Fcom.nordic.infocenter.sdk5.v15.0.0%2Fpwm_hw_example.html

    On an nRF52DK (PCA10040), with four LEDs, it fades each one up and then down in turn:

    1. Fade LED1 up, then down
    2. Fade LED2 up, then down
    3. Fade LED3 up, then down
    4. Fade LED4 up, then down
    5. repeat from 1.

    I do agree that Nordic could explain this much better, but the easiest way to understand this type of thing is to follow what happens in the debugger.

    The first thing to note is what the m_demo1_phase variable does:

    static uint8_t                     m_demo1_phase;           // 0: Fading up   LED 1
                                                                // 1: Fading down LED 1
    
                                                                // 2: Fading up   LED 2
                                                                // 3: Fading down LED 2
                                                                
                                                                // 4: Fading up   LED 3
                                                                // 5: Fading down LED 3
                                                                
                                                                // 6: Fading up   LED 4
                                                                // 7: Fading down LED 4
    
                                                                // So: Evens are fading Up;
                                                                //     Odds  are fading Down.
    
    

    Which then explains what's happening here

    uint8_t channel    = m_demo1_phase >> 1;
    bool    down       = m_demo1_phase & 1;

    The rest is just incrementing up to max during the fade-up, and then decrementing down to min for the fade down.

    When the decrement reaches minimum, the next channel (ie, the next LED) is selected.

Reply
  • You have read the description, and watched what the demo does, haven't you?

    https://infocenter.nordicsemi.com/index.jsp?topic=%2Fcom.nordic.infocenter.sdk5.v15.0.0%2Fpwm_hw_example.html

    On an nRF52DK (PCA10040), with four LEDs, it fades each one up and then down in turn:

    1. Fade LED1 up, then down
    2. Fade LED2 up, then down
    3. Fade LED3 up, then down
    4. Fade LED4 up, then down
    5. repeat from 1.

    I do agree that Nordic could explain this much better, but the easiest way to understand this type of thing is to follow what happens in the debugger.

    The first thing to note is what the m_demo1_phase variable does:

    static uint8_t                     m_demo1_phase;           // 0: Fading up   LED 1
                                                                // 1: Fading down LED 1
    
                                                                // 2: Fading up   LED 2
                                                                // 3: Fading down LED 2
                                                                
                                                                // 4: Fading up   LED 3
                                                                // 5: Fading down LED 3
                                                                
                                                                // 6: Fading up   LED 4
                                                                // 7: Fading down LED 4
    
                                                                // So: Evens are fading Up;
                                                                //     Odds  are fading Down.
    
    

    Which then explains what's happening here

    uint8_t channel    = m_demo1_phase >> 1;
    bool    down       = m_demo1_phase & 1;

    The rest is just incrementing up to max during the fade-up, and then decrementing down to min for the fade down.

    When the decrement reaches minimum, the next channel (ie, the next LED) is selected.

Children
No Data
Related