Last active
October 18, 2021 21:24
-
-
Save motters/f17a2043ee3fd42481ddf8d07b2d00f9 to your computer and use it in GitHub Desktop.
Counting falling edges from PWM using PPI & a Timer
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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