Skip to content

Instantly share code, notes, and snippets.

@motters
Last active October 18, 2021 21:24
Show Gist options
  • Save motters/f17a2043ee3fd42481ddf8d07b2d00f9 to your computer and use it in GitHub Desktop.
Save motters/f17a2043ee3fd42481ddf8d07b2d00f9 to your computer and use it in GitHub Desktop.
Counting falling edges from PWM using PPI & a Timer
#include <zephyr.h>
#include <device.h>
#include <drivers/pwm.h>
#include <drivers/adc.h>
#include <devicetree.h>
#include <nrfx_gpiote.h>
#include <nrfx_ppi.h>
#include <nrfx_timer.h>
#include <nrfx_lpcomp.h>
// PWM will drive an LED for testing
#define OUTPUT_PIN DT_GPIO_PIN(DT_ALIAS(led0), gpios)
// Get the alias for pwm_led0 from the device tree
#define PWM_LED0_NODE DT_ALIAS(pwm_led0)
// Check if pwm_led0 is ok to use
#if DT_NODE_HAS_STATUS(PWM_LED0_NODE, okay)
// Get the control pin the led is attached to
#define PWM_CTLR DT_PWMS_CTLR(PWM_LED0_NODE)
// Get the channel the led is attached to
#define PWM_CHANNEL DT_PWMS_CHANNEL(PWM_LED0_NODE)
// Get any flags set by pwm_led in the device tree
#define PWM_FLAGS DT_PWMS_FLAGS(PWM_LED0_NODE)
#else
#error "Unsupported board: pwm-led0 devicetree alias is not defined"
#define PWM_CTLR DT_INVALID_NODE
#define PWM_CHANNEL 0
#define PWM_FLAGS 0
#endif
static nrfx_timer_t m_counter = NRFX_TIMER_INSTANCE(2);
static void dummy(nrfx_gpiote_pin_t pin, nrf_gpiote_polarity_t action)
{
printk("pulse\r\n");
}
static void compare_handler(nrf_timer_event_t event_type, void* p_context)
{
printk("compare\r\n");
nrfx_timer_clear(&m_counter);
}
void main(void)
{
// Welcome message
printk("Count PWM pulses %s", CONFIG_BOARD);
// Connect GPIOTE_0 IRQ to nrfx_gpiote_irq_handler
IRQ_DIRECT_CONNECT(DT_IRQN(DT_NODELABEL(gpiote)), 0, nrfx_gpiote_irq_handler, 0);
IRQ_DIRECT_CONNECT(DT_IRQN(DT_NODELABEL(timer2)), 0, nrfx_timer_2_irq_handler, 0);
//
// Counter setup
//
// Set timer as a counter
nrfx_timer_config_t tmr_config = NRFX_TIMER_DEFAULT_CONFIG;
tmr_config.mode = NRF_TIMER_MODE_COUNTER;
tmr_config.bit_width = NRF_TIMER_BIT_WIDTH_32;
// Setup timer @todo disable call back
nrfx_timer_init(&m_counter, &tmr_config, compare_handler);
nrfx_timer_compare(&m_counter, NRF_TIMER_CC_CHANNEL1, 100, true);
//nrfx_timer_clear(&m_counter);
nrfx_timer_enable(&m_counter);
//
// GPIOE setup
//
// Initialize GPIOTE
nrfx_gpiote_init(0);
nrfx_gpiote_in_config_t const in_config = {
.sense = NRF_GPIOTE_POLARITY_HITOLO,
.pull = NRF_GPIO_PIN_NOPULL,
.is_watcher = true,
.hi_accuracy = true,
.skip_gpio_setup = true,
};
// Initialize input pin to generate event on high to low transition
// (falling edge) and call dummy()
nrfx_gpiote_in_init(OUTPUT_PIN, &in_config, dummy);
// Create the event to detect
// Leave interrupt enabled for debugging (interrupt is called)
nrfx_gpiote_in_event_enable(OUTPUT_PIN, true);
//
// PPI
//
// Get an allocated PPI Channel
nrf_ppi_channel_t channel_in;
nrfx_ppi_channel_alloc(&channel_in);
// Trigger timer count task when GPIOTE pin go from low to high.
nrfx_ppi_channel_assign(channel_in,
nrfx_gpiote_in_event_addr_get(OUTPUT_PIN),
nrfx_timer_task_address_get(&m_counter, NRF_TIMER_TASK_COUNT)); // NRF_TIMER_TASK_CAPTURE1 NRF_TIMER_TASK_COUNT
// Enable PII
nrfx_ppi_channel_enable(channel_in);
//
// PWM Setup (@note PWM works ok, flashes LED.)
//
// Create an empty device structure
const struct device *pwm;
// Get the pwm from the pwm controller
pwm = DEVICE_DT_GET(PWM_CTLR);
// Check if the pwm device is ready to use
if (!device_is_ready(pwm)) {
printk("Error: PWM device %s is not ready\n", pwm->name);
return;
}
// Try a max period of 1uS
uint32_t max_period = 250000;
// Slow pulse 50% duty
pwm_pin_set_usec(pwm, PWM_CHANNEL,
max_period, max_period / 2U, PWM_FLAGS);
// Program runtime
while (1) {
printk("value %lu", nrfx_timer_capture(&m_counter, NRF_TIMER_CC_CHANNEL0));
// Sleep for four seconds to allow user to see the flashing change
k_sleep(K_SECONDS(4U));
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment