Hello,
I'm trying to use PPI over PWM to, at the end of one single PWM period, disable the PWM and switch one GPIO (later, I'll use it for more complex task, but I start with this).
I wrote this (partial) code below (base on SDK & some example I found here) but it does not work. The PWM continues, and the GPIO stays clear (here led is active with the GPIO at 0). Any idea of what I'm doing wrong ? Did I missed something ?
Thanks in advance,
Julien
static nrf_ppi_channel_t m_ppi_channel1;
static void ppi_init(void)
{
uint32_t err_code = NRF_SUCCESS;
volatile int toto;
err_code = nrf_drv_ppi_init();
APP_ERROR_CHECK(err_code);
/* Configure 1st available PPI channel to stop PWM when the first PWM period is finished,
*/
err_code = nrf_drv_ppi_channel_alloc(&m_ppi_channel1);
APP_ERROR_CHECK(err_code);
err_code = nrf_drv_ppi_channel_assign(m_ppi_channel1,
nrf_drv_pwm_event_address_get(&m_pwm0,
NRF_PWM_EVENT_PWMPERIODEND),
nrf_drv_pwm_task_address_get(&m_pwm0,
NRF_PWM_TASK_STOP));
APP_ERROR_CHECK(err_code);
nrfx_gpiote_out_config_t config = GPIOTE_CONFIG_OUT_TASK_TOGGLE(true);
err_code = nrf_drv_gpiote_out_init(REAR_LED, &config);
APP_ERROR_CHECK(err_code);
uint32_t gpiote_task_addr = nrf_drv_gpiote_set_task_addr_get(REAR_LED);
// 2nd task activated from the event NRF_PWM_EVENT_PWMPERIODEND, the GPIO READ_LED is set.
err_code = nrf_drv_ppi_channel_fork_assign(m_ppi_channel1, gpiote_task_addr);
// Enable configured PPI channel
err_code = nrf_drv_ppi_channel_enable(m_ppi_channel1);
APP_ERROR_CHECK(err_code);
nrf_drv_gpiote_out_task_enable(REAR_LED);
}
void LED_init(void)
{
cc_drv_gpio_output(REAR_LED);
// For test, activate READ lead
cc_drv_gpio_clear(REAR_LED);
{
nrf_drv_pwm_config_t const config0 =
{
.output_pins =
{
RED, // channel 0
GREEN, // channel 1
BLUE, // channel 2
NRF_DRV_PWM_PIN_NOT_USED, // channel 3
},
.irq_priority = APP_IRQ_PRIORITY_LOW,
.base_clock = NRF_PWM_CLK_1MHz,
.count_mode = NRF_PWM_MODE_UP,
.top_value = PWM_PERIOD,
.load_mode = NRF_PWM_LOAD_INDIVIDUAL,
.step_mode = NRF_PWM_STEP_AUTO
};
APP_ERROR_CHECK(nrf_drv_pwm_init(&m_pwm0, &config0, 0)); // No call back
ppi_init();
{
nrf_pwm_sequence_t const seq0 = { .values.p_individual = &seq0_values,
.length =
NRF_PWM_VALUES_LENGTH(seq0_values),
.repeats = 0,
.end_delay = 0 };
APP_ERROR_CHECK(nrf_drv_pwm_simple_playback(
&m_pwm0, &seq0, 1,
NRF_DRV_PWM_FLAG_LOOP | NRF_DRV_PWM_FLAG_SIGNAL_END_SEQ0));
}
cc_set_pwm_3ch_duty_cycle_(50, 50, 50, LOW);
}
typedef enum {
PWM_POLARITY_HIGH = 0x8000,
PWM_POLARITY_LOW = 0,
} PWM_POLARITY;
static CC_UINT16 choose_polarity(bool polarity)
{
if (polarity)
return PWM_POLARITY_HIGH;
return PWM_POLARITY_LOW;
}
static CC_UINT16 get_pwm_percentage(CC_UCHAR value)
{
return ((value * PWM_PERIOD) / 100);
}
void cc_set_pwm_3ch_duty_cycle_(CC_UCHAR pin0_dc, CC_UCHAR pin1_dc,
CC_UCHAR pin2_dc, bool polarity)
{
seq0_values.channel_0 =
get_pwm_percentage(pin0_dc) | choose_polarity(polarity);
seq0_values.channel_1 =
get_pwm_percentage(pin1_dc) | choose_polarity(polarity);
seq0_values.channel_2 =
get_pwm_percentage(pin2_dc) | choose_polarity(polarity);
seq0_values.channel_3 = 0;
}
