-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathws281x.c
121 lines (106 loc) · 3.76 KB
/
ws281x.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
/*
* File: ws281x.h
* Author: Jan Kubovy <jan@kubovy.eu>
*/
#include "ws281x.h"
#if defined WS281x_BUFFER && defined WS281x_INDICATORS
uint8_t WS281x_ledTempR[WS281x_LED_COUNT];
uint8_t WS281x_ledTempG[WS281x_LED_COUNT];
uint8_t WS281x_ledTempB[WS281x_LED_COUNT];
uint16_t WS281x_counter = 0;
void (*WS281x_Switcher)(bool);
void WS281x_setSwitcher(void (* Switcher)(bool)) {
WS281x_Switcher = Switcher;
}
inline void WS281x_show(void) {
for (uint8_t i = 0; i < WS281x_LED_COUNT; i++) {
#ifdef WS281x_GRB
WS281x_BUFFER = WS281x_ledTempG[i];
__delay_us(15);
WS281x_BUFFER = WS281x_ledTempR[i];
__delay_us(15);
WS281x_BUFFER = WS281x_ledTempB[i];
__delay_us(15);
#else
WS281x_BUFFER = WS281x_ledTempR[i];
__delay_us(15);
WS281x_BUFFER = WS281x_ledTempG[i];
__delay_us(15);
WS281x_BUFFER = WS281x_ledTempB[i];
__delay_us(15);
#endif
}
__delay_us(50);
}
#ifdef WS281x_TIMER_PERIOD
void WS281x_update(void) {
uint8_t percent; // Percent in bytes (0-255) where 255 = 100%
for (uint8_t led = 0; led < WS281x_LED_COUNT; led++) {
switch(WS281x_ledPattern[led]) {
case WS281x_PATTERN_LIGHT:
percent = WS281x_ledMax[led];
break;
case WS281x_PATTERN_BLINK:
percent = (WS281x_counter / WS281x_ledDelay[led]) % 2 ? WS281x_ledMax[led] : WS281x_ledMin[led];
break;
case WS281x_PATTERN_FADE_IN:
percent = (WS281x_counter * WS281x_SPEED / WS281x_ledDelay[led]) % 100;
percent = ((uint16_t) (WS281x_ledMax[led] - WS281x_ledMin[led]) * percent) / 99 + WS281x_ledMin[led];
break;
case WS281x_PATTERN_FADE_OUT:
percent = (WS281x_counter * WS281x_SPEED / WS281x_ledDelay[led]) % 100;
percent = WS281x_ledMax[led] - ((uint16_t) (WS281x_ledMax[led] - WS281x_ledMin[led]) * percent) / 99;
break;
case WS281x_PATTERN_FADE_TOGGLE:
percent = (WS281x_counter * WS281x_SPEED * 2 / WS281x_ledDelay[led]) % 200;
percent = percent > 100 ? 200 - percent : percent;
percent = (WS281x_ledMax[led] - WS281x_ledMin[led]) * percent / 100 + WS281x_ledMin[led];
break;
}
WS281x_ledTempR[led] = ((uint16_t) WS281x_ledRed[led]) * percent / 255 * WS281x_MAX / 255;
WS281x_ledTempG[led] = ((uint16_t) WS281x_ledGreen[led]) * percent / 255 * WS281x_MAX / 255;
WS281x_ledTempB[led] = ((uint16_t) WS281x_ledBlue[led]) * percent / 255 * WS281x_MAX / 255;
}
WS281x_counter++;
WS281x_show();
}
#endif
void WS281x_set(uint8_t led, WS281x_Pattern_t pattern, uint8_t r, uint8_t g,
uint8_t b, uint16_t delay, uint8_t min, uint8_t max) {
if (WS281x_Switcher) WS281x_Switcher(true);
#ifdef WS281x_SW_LAT
WS281x_SW_LAT = true;
#endif
WS281x_ledPattern[led] = pattern;
WS281x_ledRed[led] = r;
WS281x_ledGreen[led] = g;
WS281x_ledBlue[led] = b;
WS281x_ledTempR[led] = r;
WS281x_ledTempG[led] = g;
WS281x_ledTempB[led] = b;
#ifdef WS281x_TIMER_PERIOD
WS281x_ledDelay[led] = delay / WS281x_TIMER_PERIOD;
#endif
//ledCounter[led] = 0;
WS281x_ledMin[led] = min;
WS281x_ledMax[led] = max;
#ifndef WS281x_TIMER_PERIOD
WS281x_show();
#endif
}
void WS281x_off(void) {
WS281x_all(0x00, 0x00, 0x00);
//#ifndef WS281x_TIMER_PERIOD
WS281x_show();
//#endif
if (WS281x_Switcher) WS281x_Switcher(false);
#ifdef WS281x_SW_LAT
WS281x_SW_LAT = false;
#endif
}
inline void WS281x_all(uint8_t r, uint8_t g, uint8_t b) {
for (uint8_t led = 0; led < WS281x_LED_COUNT; led++) {
WS281x_set(led, WS281x_PATTERN_LIGHT, r, g, b, 0, 0, 255);
}
}
#endif