1 /*
2  * Copyright (c) 2016 Intel Corporation
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 /**
8  * @file Sample app to utilize APA102C LED.
9  *
10  * The APA102/C requires 5V data and clock signals, so logic
11  * level shifter (preferred) or pull-up resistors are needed.
12  * Make sure the pins are 5V tolerant if using pull-up
13  * resistors.
14  *
15  * WARNING: the APA102C are very bright even at low settings.
16  * Protect your eyes and do not look directly into those LEDs.
17  */
18 
19 #include <zephyr/kernel.h>
20 
21 #include <zephyr/sys/printk.h>
22 
23 #include <zephyr/device.h>
24 #include <zephyr/drivers/gpio.h>
25 /* in millisecond */
26 #define SLEEPTIME	K_MSEC(250)
27 
28 #define GPIO_DATA_PIN	16
29 #define GPIO_CLK_PIN	19
30 #define GPIO_NAME	"GPIO_"
31 
32 #define APA102C_START_FRAME	0x00000000
33 #define APA102C_END_FRAME	0xFFFFFFFF
34 
35 /* The LED is very bright. So to protect the eyes,
36  * brightness is set very low, and RGB values are
37  * set low too.
38  */
39 uint32_t rgb[] = {
40 	0xE1000010,
41 	0xE1001000,
42 	0xE1100000,
43 	0xE1101010,
44 };
45 #define NUM_RGB		4
46 
47 /* Number of LEDS linked together */
48 #define NUM_LEDS	1
49 
send_rgb(const struct device * gpio_dev,uint32_t rgb)50 void send_rgb(const struct device *gpio_dev, uint32_t rgb)
51 {
52 	int i;
53 
54 	for (i = 0; i < 32; i++) {
55 		/* MSB goes in first */
56 		gpio_pin_set_raw(gpio_dev, GPIO_DATA_PIN, (rgb & BIT(31)) != 0);
57 
58 		/* Latch data into LED */
59 		gpio_pin_set_raw(gpio_dev, GPIO_CLK_PIN, 1);
60 		gpio_pin_set_raw(gpio_dev, GPIO_CLK_PIN, 0);
61 
62 		rgb <<= 1;
63 	}
64 }
65 
main(void)66 int main(void)
67 {
68 	const struct device *gpio_dev;
69 	int ret;
70 	int idx = 0;
71 	int leds = 0;
72 
73 	gpio_dev = DEVICE_DT_GET(DT_ALIAS(gpio_0));
74 	if (!device_is_ready(gpio_dev)) {
75 		printk("GPIO device %s is not ready!\n", gpio_dev->name);
76 		return 0;
77 	}
78 
79 	/* Setup GPIO output */
80 	ret = gpio_pin_configure(gpio_dev, GPIO_DATA_PIN, GPIO_OUTPUT);
81 	if (ret) {
82 		printk("Error configuring " GPIO_NAME "%d!\n", GPIO_DATA_PIN);
83 	}
84 
85 	ret = gpio_pin_configure(gpio_dev, GPIO_CLK_PIN, GPIO_OUTPUT);
86 	if (ret) {
87 		printk("Error configuring " GPIO_NAME "%d!\n", GPIO_CLK_PIN);
88 	}
89 
90 	while (1) {
91 		send_rgb(gpio_dev, APA102C_START_FRAME);
92 
93 		for (leds = 0; leds < NUM_LEDS; leds++) {
94 			send_rgb(gpio_dev, rgb[(idx + leds) % NUM_RGB]);
95 		}
96 
97 		/* If there are more LEDs linked together,
98 		 * then what NUM_LEDS is, the NUM_LEDS+1
99 		 * LED is going to be full bright.
100 		 */
101 		send_rgb(gpio_dev, APA102C_END_FRAME);
102 
103 		idx++;
104 		if (idx >= NUM_RGB) {
105 			idx = 0;
106 		}
107 
108 		k_sleep(SLEEPTIME);
109 	}
110 	return 0;
111 }
112