1 /*
2 * Copyright (c) 2020-2021 Vestas Wind Systems A/S
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7
8 #include <zephyr.h>
9 #include <drivers/pwm.h>
10 #include <logging/log.h>
11
12 LOG_MODULE_REGISTER(pwm_capture, CONFIG_PWM_LOG_LEVEL);
13
14 struct z_pwm_pin_capture_cb_data {
15 uint32_t period;
16 uint32_t pulse;
17 struct k_sem sem;
18 int status;
19 };
20
z_pwm_pin_capture_cycles_callback(const struct device * dev,uint32_t pwm,uint32_t period_cycles,uint32_t pulse_cycles,int status,void * user_data)21 static void z_pwm_pin_capture_cycles_callback(const struct device *dev,
22 uint32_t pwm,
23 uint32_t period_cycles,
24 uint32_t pulse_cycles,
25 int status,
26 void *user_data)
27 {
28 struct z_pwm_pin_capture_cb_data *data = user_data;
29
30 data->period = period_cycles;
31 data->pulse = pulse_cycles;
32 data->status = status;
33
34 k_sem_give(&data->sem);
35 }
36
z_impl_pwm_pin_capture_cycles(const struct device * dev,uint32_t pwm,pwm_flags_t flags,uint32_t * period,uint32_t * pulse,k_timeout_t timeout)37 int z_impl_pwm_pin_capture_cycles(const struct device *dev, uint32_t pwm,
38 pwm_flags_t flags, uint32_t *period,
39 uint32_t *pulse, k_timeout_t timeout)
40 {
41 struct z_pwm_pin_capture_cb_data data;
42 int err;
43
44 if ((flags & PWM_CAPTURE_MODE_MASK) == PWM_CAPTURE_MODE_CONTINUOUS) {
45 LOG_ERR("continuous capture mode only supported via callback");
46 return -ENOTSUP;
47 }
48
49 flags |= PWM_CAPTURE_MODE_SINGLE;
50 k_sem_init(&data.sem, 0, 1);
51
52 err = pwm_pin_configure_capture(dev, pwm, flags,
53 z_pwm_pin_capture_cycles_callback,
54 &data);
55 if (err) {
56 LOG_ERR("failed to configure pwm capture");
57 return err;
58 }
59
60 err = pwm_pin_enable_capture(dev, pwm);
61 if (err) {
62 LOG_ERR("failed to enable pwm capture");
63 return err;
64 }
65
66 err = k_sem_take(&data.sem, timeout);
67 if (err == -EAGAIN) {
68 (void)pwm_pin_disable_capture(dev, pwm);
69 (void)pwm_pin_configure_capture(dev, pwm, flags, NULL, NULL);
70 LOG_WRN("pwm capture timed out");
71 return err;
72 }
73
74 if (data.status == 0) {
75 if (period != NULL) {
76 *period = data.period;
77 }
78
79 if (pulse != NULL) {
80 *pulse = data.pulse;
81 }
82 }
83
84 return data.status;
85 }
86