forked from PaulStoffregen/Tlc5940
-
Notifications
You must be signed in to change notification settings - Fork 1
/
tlc_fades.h
211 lines (187 loc) · 7.28 KB
/
tlc_fades.h
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
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
/* Copyright (c) 2009 by Alex Leone <acleone ~AT~ gmail.com>
This file is part of the Arduino TLC5940 Library.
The Arduino TLC5940 Library is free software: you can redistribute it
and/or modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
The Arduino TLC5940 Library is distributed in the hope that it will be
useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with The Arduino TLC5940 Library. If not, see
<http://www.gnu.org/licenses/>. */
#ifndef TLC_FADES_H
#define TLC_FADES_H
/** \file
TLC fading functions. */
#include <avr/interrupt.h>
#include "Tlc5940.h"
#if defined(ARDUINO) && ARDUINO >= 100
#include "Arduino.h"
#else
#include "WProgram.h"
#endif
#ifndef TLC_FADE_BUFFER_LENGTH
/** The default fade buffer length (24). Uses 24*13 = 312 bytes of ram. */
#define TLC_FADE_BUFFER_LENGTH 24
#endif
/** Data for a single fade */
struct Tlc_Fade {
TLC_CHANNEL_TYPE channel; /**< channel this fade is on */
int16_t startValue; /**< value when the fade starts (0 - 4095) */
int16_t changeValue; /**< start + changeValue = endValue (0 - 4095) */
uint32_t startMillis; /**< millis() when to start */
uint32_t endMillis; /**< millis() when to end */
} tlc_fadeBuffer[TLC_FADE_BUFFER_LENGTH];
/** The current fade buffer size */
uint8_t tlc_fadeBufferSize;
uint8_t tlc_updateFades();
uint8_t tlc_updateFades(uint32_t currentMillis);
uint8_t tlc_addFade(struct Tlc_Fade *fade);
uint8_t tlc_addFade(TLC_CHANNEL_TYPE channel, int16_t startValue,
int16_t endValue, uint32_t startMillis, uint32_t endMillis);
uint8_t tlc_isFading(TLC_CHANNEL_TYPE channel);
uint8_t tlc_removeFades(TLC_CHANNEL_TYPE channel);
static void tlc_removeFadeFromBuffer(struct Tlc_Fade *current,
struct Tlc_Fade *end);
/** \addtogroup ExtendedFunctions
\code #include "tlc_fades.h" \endcode
- uint8_t tlc_updateFades() - updates all fades
- uint8_t tlc_updateFades(uint32_t currentMillis) - updates fades using
currentMillis as the current time
- uint8_t tlc_addFade(struct Tlc_Fade *fade) - copies fade into the
fade buffer
- uint8_t tlc_addFade(TLC_CHANNEL_TYPE channel, int16_t startValue,
int16_t endValue, uint32_t startMillis, uint32_t endMillis) - adds
a fade to the fade buffer
- uint8_t tlc_isFading(TLC_CHANNEL_TYPE channel) - returns 1 if there's
a fade on this channel in the buffer
- uint8_t tlc_removeFades(TLC_CHANNEL_TYPE channel) - removes all fades
on channel */
/* @{ */
/** Adds a fade to the buffer.
\param fade the fade to be copied into the buffer
\returns 0 if the fade buffer is full, fadeBufferSize if added successfully
*/
uint8_t tlc_addFade(struct Tlc_Fade *fade)
{
if (tlc_fadeBufferSize == TLC_FADE_BUFFER_LENGTH) {
return 0; // fade buffer full
}
struct Tlc_Fade *p = tlc_fadeBuffer + tlc_fadeBufferSize++;
p->channel = fade->channel;
p->startValue = fade->startValue;
p->changeValue = fade->changeValue;
p->startMillis = fade->startMillis;
p->endMillis = fade->endMillis;
return tlc_fadeBufferSize;
}
/** Adds a fade to the fade buffer.
\param channel the ouput channel this fade is on
\param startValue the value at the start of the fade
\param endValue the value at the end of the fade
\param startMillis the millis() when to start the fade
\param endMillis the millis() when to end the fade
\returns 0 if the fade buffer is full, fadeBufferSize if added successfully
*/
uint8_t tlc_addFade(TLC_CHANNEL_TYPE channel, int16_t startValue,
int16_t endValue, uint32_t startMillis, uint32_t endMillis)
{
if (tlc_fadeBufferSize == TLC_FADE_BUFFER_LENGTH) {
return 0; // fade buffer full
}
struct Tlc_Fade *p = tlc_fadeBuffer + tlc_fadeBufferSize++;
p->channel = channel;
p->startValue = startValue;
p->changeValue = endValue - startValue;
p->startMillis = startMillis;
p->endMillis = endMillis;
return tlc_fadeBufferSize;
}
/** Checks to see if any fades are happening on channel
\param channel the channel to check
\returns 1 if there is a fade in the buffer on this channel, 0 otherwise */
uint8_t tlc_isFading(TLC_CHANNEL_TYPE channel)
{
struct Tlc_Fade *end = tlc_fadeBuffer + tlc_fadeBufferSize;
for (struct Tlc_Fade *p = tlc_fadeBuffer; p < end; p++) {
if (p->channel == channel) {
return 1;
}
}
return 0;
}
/** Removes any fades from the fade buffer on this channel.
\param channel which channel the fades are on
\returns how many fades were removed */
uint8_t tlc_removeFades(TLC_CHANNEL_TYPE channel)
{
uint8_t removed = 0;
struct Tlc_Fade *end = tlc_fadeBuffer + tlc_fadeBufferSize;
for (struct Tlc_Fade *p = tlc_fadeBuffer; p < end; p++) {
if (p->channel == channel) {
removed++;
tlc_removeFadeFromBuffer(p, --end);
}
}
return removed;
}
/** Copies the end of the buffer to the current and decrements
tlc_fadeBufferSize. This will change the end of the buffer (pass by
reference)
\param current the fade to be removed
\param endp the end of the fade buffer (pointer to pointer) */
static void tlc_removeFadeFromBuffer(struct Tlc_Fade *current,
struct Tlc_Fade *endp)
{
if (endp != current) { // if this is not the last fade
current->channel = endp->channel;
current->startValue = endp->startValue;
current->changeValue = endp->changeValue;
current->startMillis = endp->startMillis;
current->endMillis = endp->endMillis;
}
tlc_fadeBufferSize--;
}
/** Updates fades using millis()
\returns 0 if there are no fades left in the buffer. */
uint8_t tlc_updateFades()
{
return tlc_updateFades(millis());
}
/** Updates any running fades.
\param currentMillis the current millis() time.
\returns 0 if there are no fades left in the buffer. */
uint8_t tlc_updateFades(uint32_t currentMillis)
{
struct Tlc_Fade *end = tlc_fadeBuffer + tlc_fadeBufferSize;
uint8_t needsUpdate = 0;
for (struct Tlc_Fade *p = tlc_fadeBuffer; p < end;){
if (currentMillis >= p->endMillis) { // fade done
Tlc.set(p->channel, p->startValue + p->changeValue);
needsUpdate = 1;
tlc_removeFadeFromBuffer(p, --end);
continue;
} else {
uint32_t startMillis = p->startMillis;
if (currentMillis >= startMillis) {
Tlc.set(p->channel, p->startValue + p->changeValue
* (int32_t)(currentMillis - startMillis)
/ (int32_t)(p->endMillis - startMillis));
needsUpdate = 1;
}
}
p++;
}
if (needsUpdate) {
Tlc.update();
if (tlc_fadeBufferSize == 0) {
while (tlc_needXLAT)
;
}
}
return tlc_fadeBufferSize;
}
/* @} */
#endif