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/kernel.h>
9 #include <zephyr/drivers/pwm.h>
10 #include <zephyr/logging/log.h>
11
12 LOG_MODULE_REGISTER(pwm_capture, CONFIG_PWM_LOG_LEVEL);
13
14 struct z_pwm_capture_cb_data {
15 uint32_t period;
16 uint32_t pulse;
17 struct k_sem sem;
18 int status;
19 };
20
z_pwm_capture_cycles_callback(const struct device * dev,uint32_t channel,uint32_t period_cycles,uint32_t pulse_cycles,int status,void * user_data)21 static void z_pwm_capture_cycles_callback(const struct device *dev,
22 uint32_t channel,
23 uint32_t period_cycles,
24 uint32_t pulse_cycles, int status,
25 void *user_data)
26 {
27 struct z_pwm_capture_cb_data *data = user_data;
28
29 data->period = period_cycles;
30 data->pulse = pulse_cycles;
31 data->status = status;
32
33 k_sem_give(&data->sem);
34 }
35
z_impl_pwm_capture_cycles(const struct device * dev,uint32_t channel,pwm_flags_t flags,uint32_t * period,uint32_t * pulse,k_timeout_t timeout)36 int z_impl_pwm_capture_cycles(const struct device *dev, uint32_t channel,
37 pwm_flags_t flags, uint32_t *period,
38 uint32_t *pulse, k_timeout_t timeout)
39 {
40 struct z_pwm_capture_cb_data data;
41 int err;
42
43 if ((flags & PWM_CAPTURE_MODE_MASK) == PWM_CAPTURE_MODE_CONTINUOUS) {
44 LOG_ERR("continuous capture mode only supported via callback");
45 return -ENOTSUP;
46 }
47
48 flags |= PWM_CAPTURE_MODE_SINGLE;
49 k_sem_init(&data.sem, 0, 1);
50
51 err = pwm_configure_capture(dev, channel, flags,
52 z_pwm_capture_cycles_callback, &data);
53 if (err) {
54 LOG_ERR("failed to configure pwm capture");
55 return err;
56 }
57
58 err = pwm_enable_capture(dev, channel);
59 if (err) {
60 LOG_ERR("failed to enable pwm capture");
61 return err;
62 }
63
64 err = k_sem_take(&data.sem, timeout);
65 if (err == -EAGAIN) {
66 (void)pwm_disable_capture(dev, channel);
67 (void)pwm_configure_capture(dev, channel, flags, NULL, NULL);
68 LOG_WRN("pwm capture timed out");
69 return err;
70 }
71
72 if (data.status == 0) {
73 if (period != NULL) {
74 *period = data.period;
75 }
76
77 if (pulse != NULL) {
78 *pulse = data.pulse;
79 }
80 }
81
82 return data.status;
83 }
84