1 /*
2  * Copyright (c) 2016 Intel Corporation
3  * Copyright (c) 2020 Nordic Semiconductor ASA
4  *
5  * SPDX-License-Identifier: Apache-2.0
6  */
7 
8 /**
9  * @file Sample app to demonstrate PWM-based LED fade
10  */
11 
12 #include <zephyr/kernel.h>
13 #include <zephyr/sys/printk.h>
14 #include <zephyr/device.h>
15 #include <zephyr/drivers/pwm.h>
16 
17 #define PWM_LED_ALIAS(i) DT_ALIAS(_CONCAT(pwm_led, i))
18 #define PWM_LED_IS_OKAY(i) DT_NODE_HAS_STATUS_OKAY(DT_PARENT(PWM_LED_ALIAS(i)))
19 #define PWM_LED(i, _) IF_ENABLED(PWM_LED_IS_OKAY(i), (PWM_DT_SPEC_GET(PWM_LED_ALIAS(i)),))
20 
21 #define MAX_LEDS 10
22 static const struct pwm_dt_spec pwm_leds[] = {LISTIFY(MAX_LEDS, PWM_LED, ())};
23 
24 #define NUM_STEPS	50U
25 #define SLEEP_MSEC	25U
26 
main(void)27 int main(void)
28 {
29 	uint32_t pulse_widths[ARRAY_SIZE(pwm_leds)];
30 	uint32_t steps[ARRAY_SIZE(pwm_leds)];
31 	uint8_t dirs[ARRAY_SIZE(pwm_leds)];
32 	int ret;
33 
34 	printk("PWM-based LED fade. Found %d LEDs\n", ARRAY_SIZE(pwm_leds));
35 
36 	for (size_t i = 0; i < ARRAY_SIZE(pwm_leds); i++) {
37 		pulse_widths[i] = 0;
38 		steps[i] = pwm_leds[i].period / NUM_STEPS;
39 		dirs[i] = 1U;
40 		if (!pwm_is_ready_dt(&pwm_leds[i])) {
41 			printk("Error: PWM device %s is not ready\n", pwm_leds[i].dev->name);
42 			return 0;
43 		}
44 	}
45 
46 	while (1) {
47 		for (size_t i = 0; i < ARRAY_SIZE(pwm_leds); i++) {
48 			ret = pwm_set_pulse_dt(&pwm_leds[i], pulse_widths[i]);
49 			if (ret) {
50 				printk("Error %d: failed to set pulse width for LED %d\n", ret, i);
51 			}
52 			printk("LED %d: Using pulse width %d%%\n", i,
53 			       100 * pulse_widths[i] / pwm_leds[i].period);
54 
55 			if (dirs[i] == 1) {
56 				if (pulse_widths[i] + steps[i] >= pwm_leds[i].period) {
57 					pulse_widths[i] = pwm_leds[i].period;
58 					dirs[i] = 0U;
59 				} else {
60 					pulse_widths[i] += steps[i];
61 				}
62 			} else {
63 				if (pulse_widths[i] <= steps[i]) {
64 					pulse_widths[i] = 0;
65 					dirs[i] = 1U;
66 				} else {
67 					pulse_widths[i] -= steps[i];
68 				}
69 			}
70 		}
71 
72 		k_sleep(K_MSEC(SLEEP_MSEC));
73 	}
74 	return 0;
75 }
76