Fade is a simple line-oriented language. It has basic looping constructs, conditionals, user-defined functions, and built-in functions.
Variable names can be any combination of alpha, numeric, and underscore characters, except for those reserved by the language. The first character cannot be a number.
Variables are locally scoped within a specific function.
There are four types of values in Fade. All typing is implicit and determined by usage.
integers are 4-byte integer values.
Example:
345
Floats are 4-byte floating-point values
Example:
13.13
Strings are sequences of characters with opening and closing double-quotes.
Example:
"Here is some text"
All integer or float values are implemented as single-valued arrays. Indexes are zero-based.
An array of values can be defined as a constant:
a = {1, 2, 3}
or can be created using array references:
a[0] = 1
a[1] = 2
a[2] = 3
Expressions and operators use a "C-style" syntax.
The following operators are supported, in order of precedance:
Operator | Description | Example |
MyFunc(...) | Function call | GetValue(1, b) |
[] | Array reference | val[33] |
() | Parentheses | (x + 5) * 2 |
+, - | Unary plus or minus | +33, -15.5 |
*, /, % | Binary multiplication, division, and modulus | 15 * 35 |
+, - | Binary plus or minus | x + 128 |
<, <=, >, >= | Relational | q > 55 |
==, != | Equality and inequality | value == 1 |
&& | Logical AND | value == 15 && test > 0 |
|| | Logical OR | value == 10 || debug != 0 |
= | Assignment | result = 15 * (35 + a) |
Implements a loop.
for <variable> <first>:<last>[:<increment>]
variable | The counter variable for the loop |
first | The value for the first iteration of the loop |
last | The value of the last iteration of the loop |
increment | The increment of the counter variable each iteration. Will be 1 if it is omitted. |
The for loop will execute, starting with the first value and terminating when the value exceeds the last value. The increment is 1 if not specified.
Example:
for channel 32:1:-1
Di(1,channel,{red, green, blue})
D(10,channel,{0, 0, 0})
A(3)
endfor
Implements a while loop
while <condition>
condition | The condition to evaluate. Zero (0) is false, any non-zero value is true. |
The while loop will execute as long as the condition is true.
if <condition>
condition | The condition to evaluate. Zero (0) is false, any non-zero value is true. |
Implements a condition statement.
Example:
if x == 1
Pl("one")
elseif x== 2
Pl("two")
else
Pl("other")
endif
Assignment is technically an operator, but is listed here for completeness.
<variable or array reference> = <value>
Examples:
x = y * y
g[x] = 33
Breaks out of a for loop and continues execution in the next statement after the endfor
Returns a value from a function.
Example:
return result
Functions may be defined and called:
func <name>(<parameterList>)
name | The name of the function |
parameterList | A list of zero or more parameters |
Declares a function.
Example:
func GetColor(colorNumber)
if (colorNumber == 0)
return {1, 0, 0}
elseif (colorNumber == 1)
return {1, 1, 0}
elseif (colorNumber == 2)
return {0, 1, 0}
endif
endfunc
Call a function.
Example:
color = GetColor(x)
Perform the animation for a given number of cycles.
A(<cycleCount>)
int cycleCount | The number of cycles to animate |
The A() function drives the led hardware to perform all currently defined animations for the specified number of cycles.
Once a fade is completed, that led channel will remain at the final brightness value until a new fade for that channel is defined and executed. If there are no defined animations, calling the A() function merely delay by the specified cycle count.
ConfigButton defines a button that can be used to control program flow.
ConfigButton (<buttonNumber>, <buttonType>, <buttonPin>, <param 1>, <param 2>, <param 3> , <param 4>)
int buttonNumber | The number of this button, from 0 to 9 |
string buttonType | The physical hardware type of the button. |
int buttonPin | The physical pin to use for the button. |
int param | A parameter specific to the button type |
The following table defines the supported button types:
"TOUCH" | A touch button implemented using the ESP32's built-in touch support. The param parameter defines the touch threshold used to determine whether the contact is touched or not |
"ACTIVELOW" | A electrical button that will be true when the specified button pin is low. |
See ReadButton() to read button values. For touch buttons, see Debug("DebugButtonNumber") to determine an appropriate threshold value.
The ESP-32 supports touch buttons on pins 0, 2, 4, 12, 13, 14, 15, 27, 32, 33
Examples:
ConfigButton (0, "TOUCH", 15, 20)
Defines a touch button connected to pin 15 of the ESP32 and use 20 as the touch threshold value.
ConfigLed defines one or more LEDs that the system can animate.
ConfigLed (<ledStringNumber>, <ledStringType>, <ledCount>, <param 1>, ... , <param n>)
int ledStringNumber | The number of this string. Fade supports up to 16 led strings. They must be defined sequentially, starting with string number zero. |
string ledStringType | The physical hardware type of the string. |
int ledCount | The number of leds in the string |
int param | Parameters specific to the physical hardware type of the string |
The following table defines the supported string types:
"WS2812" or "RGB" | A string of WS2812-compatible (aka "neopixel") addressable leds. The <ledCount> parameter defines the number of leds on the string, and <param 1> defines the physical pin the strip is connected to. |
"APA102" | A string of <ledCount> APA102 addressable leds. The ESP supports two different sets of SPI hardware, known as VSPI and HSPI. param 1: Choose VSPI (0) or HSPI (1). There are 4 pins that are used by default for each set of hardware: VSPI: SCLK = 18 MISO = 19 MOSI = 23 SS = 5 HSPI: SCLK = 14 MISO = 12 MOSI = 13 SS = 15 The 4 pins can be defined directly: param 2: SCLK param 3: MISO param 4: MOSI param 5: SS SCLK is connected to the clock input on the LED strip, and MOSI is connected to the data input. MISO and SS are not connected. |
"PWM" | A non-addressable LED controlled through PWM. This feature uses the ESP-32's built in LED control hardware. 1-4 leds can be defined in a single statement, and the physical pins are defined using parameters 1-4. |
"Servo" | A servo motor controller with 1-2 mS pulses. This feature uses the ESP32's built-in LED control hardware. Specify 1 for the ledCount and the pin the servo is connected to. |
"UdpSender" | Takes animation data and sends it over the network to a remote
ESP. Specify the ledCount as normal. param 1: The number of values per pixel to send param 2: The universe number. This must match with the number of the receiver param 3: The UDP port to send the data on |
"UdpReceiver" | Takes animation data from a UdpSender and uses it on this
system. ledCount must be set to zero. param 1: The universe number. Must match the sender param 2: The UDP port to listen on. param 3: The starting channel to copy from the UDP data to this system param 4: The number of channels to copy to this system. |
Examples:
ConfigLed (0, "RGB", 8, 27)
ConfigLed (1, "PWM", 3, 17, 16, 4)
ConfigLed (2, "Servo", 1, 31)
Configures a string of 8 WS2812 leds connected to pin 27 as the first string, followed by 3 individually controlled PWM leds on pins 17, 16, and 4, followed by a single servo attached to pin 31
When animating, leds 0-7 will be the WS2812 leds, leds 8-10 will be the PWM ones, and led 11 will be the servo.
Remoting provides the ability to define a set of leds/channels that look like they are implemented on the local ESP but are actually sent over the local network to remote ESP(s).
On the local ESP - the one that is running the animation - the UdpSender LED type is configured just like the other types. The UDP port is specified and a universe number is also specified so that multiple remoted scenarios could be run on the same network and port.
ConfigLed(1, "UdpSender", 16, 155, 4021)
This defines LED group 1 as 16 pixels/channels, transmitting on port 4021 and using universe 155
The UdpReceiver led type is used to pull the Udp data off the network and put it into the local system. The port and universe are specified and must match the UdpSender values. The receiver should be defined as the first group, and the led count must be zero.
ConfigLed(0, "UdpReceiver", 0, 15, 4211, 8,
8)
ConfigLed(1, "Servo",
4, 4, 5, 6 ,7)
ConfigLed(2, "Servo", 4, 8, 9, 10, 11)
A(100000)
The receiver is listening on port 4211 and universe 15. The first 8 specifies that the first 8 channels in the data should be skipped and after that the next 8 should be copied into the system.
The Servo configs after that specify two blocks of 4 servos, each connected to a different pin.
D and Di define a fade for the animation system to perform.
D(<cycleCount>, <ledIndex>, <targetBrightness>)
Di(<cycleCount>, <ledIndex>, <targetBrightness>)
int cycleCount | The number of animation cycles over which to perform the fade |
int ledIndex | The index of the led to animate. Led indexes run from zero to n-1, where n is the number of LEDs defined across all led groups. |
brightness targetBrightness | The target brightness for the led |
The cycleCount parameter is used to control how fast the fade occurs, expressed in 10 millisecond units.
The targetBrightnessparameter defines the target brightness, and the format depends upon the type of underlying LED hardware. For PWM leds, it is a single floating point value. For addressable LEDs, it is a series of values.
The Di function is used to simplify code when only a single fade operation is required by also performing the animation; it is equivalent to:
D(<cycleCount>, <ledIndex>, <targetBrightness>)
A(<cycleCount>)
Examples:
D(100, 3, 1.0)
Define a fade led #3 to full brightness over the next 100 cycles (1 second)
D(30, 5, {1.0, 0.0, 0.0})
D(30, 6, {0.0, 0.5, 0.0})
Define two fades that will occur over the next 30 cycles; led #5 will fade to
red and led #6 will fade to 50% green.
Debug sets a debugging flag.
Debug (<debugFlag>, <value>)
string debugFlag | The debug flag to set |
int value | The value to set for the flag |
The Fade animation system provides debug flags that can make understanding system behavior easier. The following debug flags are defined
"LogStatements" | Every statement that is executed will be logged to the Serial console. |
"LogHeapFreeOnAllocation" | The amount of free heap memory is logged when allocations are performed. |
"DebugTouchButtonValues" | Logs the current button touch value whenever the button value is read. Used to determine an appropriate threshold number |
"DebugPrintOverUdp" | Sends all print output over the network using UDP broadcast messages. Useful for remote debugging. WinFade can read and display these messages, or you could use a utility like wireshark |
Converts a Hue-Saturation-Value color to an RGB Color
HsvToRgb (<hue>, <saturation>, <value>)
float hue | The hue value from 0-359 |
float saturation | The saturation from 0-1 |
float value | The intensity value from 0-1 |
Min and Max return the minimum or maximum of all the values passed in.
Min(<value>,...)
Max(<value>,...)
value | A numeric value |
Prints one or more values to the serial subsystem
P(<value>,...)
Pl(<value>,...)
value | A string, integer, or brightness value |
Pl performs the print operation followed by a new line.
Rand generates a pseudo-random number between the minimum and maximum value, inclusive.
Rand(<minimumValue>, <maximumValue>)
int minimumValue | The smallest number to generate |
int maximumValue | The largest number to generate |
ReadButton reads the current value of a button to determine if it is pressed.
int ReadButton (<buttonNumber>)
int buttonNumber | The number of this button, from 0 to 9 |
This function returns 1 if the button is pressed and 0 if the button is not pressed.
Examples:
if ReadButton (0) == 1
endif
S and Si define a fade for the animation system to perform for multiple leds.
S(<cycleCount>, <firstLedTargetBrightness>, ..., <lastLedTargetBrightness>)
Si(<cycleCount>, <firstLedTargetBrightness>, ..., <lastLedTargetBrightness>)
int cycleCount | The number of animation cycles over which to perform the fade |
target brightness list | A list of target brightnesses for the leds |
The S and Si functions are used to define a fade that is performed on multiple LEDs using the same cycle count.
The cycleCount parameter is used to control how fast the fade occurs, expressed in 10 millisecond units.
The target brightness list defines the target brightness for the leds, starting with led #0 and continuing based on the number of values listed
The Si function is used to simplify code when only a single fade operation is required by also performing the animation. See Di for more information.
Examples:
S(100, 1.0)
Define a fade for led #0 to full brightness over one second.
Si(200, {1.0, 0.0, 0.0}, {0.0, 1.0, 0.0}, {0.0, 0.0, 1.0} )
Define three fades that will occur over the next 200 cycles; led #0 will fade to
red, #1 to green, and #2 to blue. This is equivalent to:
D(200, 0, {1.0, 0.0, 0.0})
D(200, 1, {0.0, 1.0, 0.0})
D(200, 2, {0.0, 0.0, 1.0} )
A(200)