samples: drivers: pwm: event: Add sample
Add a simple sample demonstrating how the PWM event API can be used to precisely time 5 periods of a PWM signal. Signed-off-by: Jaro Van Landschoot <jaro.vanlandschoot@basalte.be>
This commit is contained in:
committed by
Anas Nashif
parent
1becebc8f9
commit
9be9684b53
8
samples/drivers/pwm/event/CMakeLists.txt
Normal file
8
samples/drivers/pwm/event/CMakeLists.txt
Normal file
@@ -0,0 +1,8 @@
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
cmake_minimum_required(VERSION 3.20.0)
|
||||
|
||||
find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE})
|
||||
project(pwm_event)
|
||||
|
||||
target_sources(app PRIVATE src/main.c)
|
||||
38
samples/drivers/pwm/event/README.rst
Normal file
38
samples/drivers/pwm/event/README.rst
Normal file
@@ -0,0 +1,38 @@
|
||||
.. zephyr:code-sample:: event
|
||||
:name: PWM Event
|
||||
:relevant-api: pwm_interface
|
||||
|
||||
Events on a PWM signal.
|
||||
|
||||
Overview
|
||||
********
|
||||
This sample provides an example application using the :ref:`PWM API <pwm_api>` event
|
||||
API to get events on a PWM signal. The sample demonstrates how events can be used to
|
||||
precisely time x periods of a PWM signal. A usecase for this would be the transmitting
|
||||
part of an IR remote, where precise pulse timing is needed.
|
||||
|
||||
Requirements
|
||||
************
|
||||
|
||||
This sample requires the support of the :ref:`PWM API <pwm_api>` event API.
|
||||
|
||||
Building and Running
|
||||
********************
|
||||
|
||||
.. zephyr-app-commands::
|
||||
:zephyr-app: samples/drivers/pwm/event
|
||||
:host-os: unix
|
||||
:board: sam4s_xplained
|
||||
:goals: run
|
||||
:compact:
|
||||
|
||||
Sample Output
|
||||
=============
|
||||
|
||||
When capturing the signal using an oscilloscope or logic analyzer, it should look like
|
||||
the following repeating sequence (after a startup transient)
|
||||
|
||||
.. code-block::
|
||||
|
||||
┌─┐ ┌─┐ ┌─┐ ┌─┐ ┌─┐ ┌─┐ ┌─┐ ┌─┐ ┌─┐ ┌─┐
|
||||
─┘ └─┘ └─┘ └─┘ └─┘ └───────────────────┘ └─┘ └─┘ └─┘ └─┘ └─────
|
||||
13
samples/drivers/pwm/event/boards/sam4s_xplained.overlay
Normal file
13
samples/drivers/pwm/event/boards/sam4s_xplained.overlay
Normal file
@@ -0,0 +1,13 @@
|
||||
/*
|
||||
* Copyright (c) 2025 Basalte bv
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
&pinctrl {
|
||||
pwm0_default: pwm0_default {
|
||||
group1 {
|
||||
pinmux = <PA11B_PWM_PWMH0>;
|
||||
};
|
||||
};
|
||||
};
|
||||
2
samples/drivers/pwm/event/prj.conf
Normal file
2
samples/drivers/pwm/event/prj.conf
Normal file
@@ -0,0 +1,2 @@
|
||||
CONFIG_PWM=y
|
||||
CONFIG_PWM_EVENT=y
|
||||
12
samples/drivers/pwm/event/sample.yml
Normal file
12
samples/drivers/pwm/event/sample.yml
Normal file
@@ -0,0 +1,12 @@
|
||||
sample:
|
||||
name: PWM event
|
||||
description: precisely time 5 PWM periods using the PWM event API
|
||||
common:
|
||||
tags:
|
||||
- drivers
|
||||
- pwm
|
||||
depends_on: pwm
|
||||
tests:
|
||||
sample.drivers.pwm.event:
|
||||
platform_allow:
|
||||
- sam4s_xplained
|
||||
69
samples/drivers/pwm/event/src/main.c
Normal file
69
samples/drivers/pwm/event/src/main.c
Normal file
@@ -0,0 +1,69 @@
|
||||
/*
|
||||
* Copyright (c) 2025 Basalte bv
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <zephyr/drivers/pwm.h>
|
||||
#include <zephyr/dt-bindings/pwm/pwm.h>
|
||||
#include <zephyr/kernel.h>
|
||||
|
||||
#define N_PERIODS 5
|
||||
|
||||
#define PWM_CHANNEL 0
|
||||
#define PWM_PERIOD_NS (1 * NSEC_PER_MSEC)
|
||||
#define PWM_FLAGS PWM_POLARITY_NORMAL
|
||||
|
||||
static struct pwm_event_callback callback;
|
||||
|
||||
static bool pwm_idle;
|
||||
static uint8_t counter;
|
||||
|
||||
static void pwm_callback_handler(const struct device *dev, struct pwm_event_callback *cb,
|
||||
uint32_t channel, pwm_events_t events)
|
||||
{
|
||||
ARG_UNUSED(channel);
|
||||
ARG_UNUSED(events);
|
||||
int ret;
|
||||
|
||||
if (++counter == N_PERIODS) {
|
||||
pwm_idle = !pwm_idle;
|
||||
counter = 0;
|
||||
|
||||
ret = pwm_set(dev, PWM_CHANNEL, PWM_PERIOD_NS, pwm_idle ? 0 : PWM_PERIOD_NS / 2,
|
||||
PWM_FLAGS);
|
||||
if (ret < 0) {
|
||||
printk("failed to set pwm (%d)\n", ret);
|
||||
(void)pwm_remove_event_callback(dev, cb);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
const struct device *const dev = DEVICE_DT_GET(DT_ALIAS(pwm_0));
|
||||
int ret;
|
||||
|
||||
if (!device_is_ready(dev)) {
|
||||
printk("device is not ready\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
ret = pwm_set(dev, PWM_CHANNEL, PWM_PERIOD_NS, PWM_PERIOD_NS / 2, PWM_FLAGS);
|
||||
if (ret < 0) {
|
||||
printk("failed to set idle (%d)\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
pwm_init_event_callback(&callback, pwm_callback_handler, PWM_CHANNEL,
|
||||
PWM_EVENT_TYPE_PERIOD);
|
||||
|
||||
ret = pwm_add_event_callback(dev, &callback);
|
||||
if (ret < 0) {
|
||||
printk("failed to add event callback (%d)\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
Reference in New Issue
Block a user