It makes the LEDs go blink so you don't have to!
Firstly, this is not a perfect model of every system and does not claim to be. With that out of the way, Emblinkenator divides the world into 4 categories:
- An
LED- the single base unit. It has a position relative to theFixtureit's attached to. - A
Fixture- A hardware device with a string ofLEDs attached (at the moment limited to one string ofLEDs perFixture).LEDs are assumed to be connected in sequence such thatLED0 is closest to the data pin. AFixturehas a position relative to its parent, which may be the world or anInstallation. - An
Installation- A collection ofFixturesthat comprise a larger display (e.g. Hubs on a Dome). EachFixturethen has a position relative to theInstallation. TheInstallationhas a position relative to its parent, either the world or aGroup. - A
Group- A collection of otherGroups andInstallations. A group has a position relative to the world origin.
Some rules apply:
- A
Fixturecan only belong to oneInstallation. - An
Installationcan only belong to one group. - A
Groupcan only belong to one group.
Emblinkenator then maps an Animation onto either a Fixture, an Installation, or a Group.
An Animation is an instance of a shader written in WGSL that produces RGB values for every LED in the target. The Animation has access to information about the positions of LEDs within the target, the frame rate of the system, the current time, etc. Future work will allow auxiliary data to be provided to an Animation, e.g. data from a sensor.
A Fixture is then mapped to some hardware device such as an Arduino. Mappings to hardware devices are changeable on-the-fly, it is assumed that the target device has the right number of LEDs corresponding to the Fixture representation, or at least can handle recieving the wrong number of RGB values.
- Rust
- Some hardware with some LEDs attached
First, get set up with a Rust environment (Note: Right now WSL support is likely to be spotty due to limited access to GPU resources).
Then create a file called startup-config.json in the root directory of this project. Inside the emblinkenator directory there is a file called startup-config.json.example, copy the contents of this file to startup-config.json and change the settings to match your needs. This is a temporary measure until a UI is developed, it will create the initial configuration of the system. Note that the led_positions value is optional, if omitted all LED positions will be set to the world origin (0, 0, 0).
Next, or meanwhile, flash your hardware with some code that can receive a buffer of (X) RGB values where (X) is the number of LEDs attached to the hardware. At the moment the supported transport streams are a direct UDP connection, or a MQTT connection via a third-party broker. Example implementations for both are available for the NodeMCU platform in the examples/hardware directory.
Finally, run cargo run, and you should get some blinking LEDs! Or, you may get a Segfault.
WebGPU needs a very recent version of Vulkan in order to use the Vulkan backend, if that's not available for your system (or you don't fancy installing it) you can force Emblinkenator to use OpenGL as the backend by setting the WGPU_BACKEND environment variable to gl e.g. WGPU_BACKEND=gl cargo run. This may have a performance impact.
Logging is controlled by the RUST_LOG environment variable. If it is not set, the default is emblinkenator=info. Setting this to emblinkenator=debug will print debug messages for Emblinkenator only, setting it to debug will print debug statements from all linked Rust libraries (you have been warned!).
On first run, the config.json file will be generated. In there you can change the framerate (default is 1000/25) and frame buffer size (default is 10).