Overview
The app itself is very simple and consists of very few files. It basically provides an HTTP interface so it is able to receive commands from other components, initializes the core and updates it in an infinite loop.
The infinite loop only stops if an unexpected error happens or the program
receives a SIGINT or SIGTERM signal for example Ctrl + C is pressed. Once
the loop stops, the program terminates the HTTP server and makes a signal for
the LED strips to turn off all the LEDs. It might happen that the program stops
unexpectedly, in this case the LEDs stop in the last working state until the
controller is restarted.
Core initialize
To initialize the core it has to provide 3 functions:
- Log function
It is a simple function that receives a char* and returns nothing. For now it
only puts the received parameter to the standard output. In the future it should
be upgraded to use a proper log library.
- Random function
This function receives 2 integer parameters which determines the range and returns a random integer. To make it happen it uses the C++11 random library and its default random engine with a uniform integer distribution.
- Delay function
This function receives a delay value a callback function and its void**
arguments. It has to call the callback function with its arguments after the
specified time. Obviously this waiting cannot be blocking so it has to create a
different thread. It uses the C++11 thread
library to achieve this.
This thread is detached since doesn't have to synchronize with any other
threads. With the help of the
sleep_for
function it waits for the specified time in a non-blocking manner then it just
simply calls the callback function.
Main loop
The main loop is the one that calls the tick function of the core that constantly updates the state of the LEDs and calls a function which fills a buffer with the data. The buffer fill function is called for every LED of every strip and it receives the color data in an array of size 3. Each element of the array represents the intensity of the R,G,B colors respectively. The task of this function is to convert this representation of the LED colors and forward it to the library that creates the digital signal.
The main loop has to be called periodically to update the state of the LEDs. The more frequently it is called the smoother the animations are but it also takes more computing power. For now, it is set to execute 60 times every second uniformly, but it might have to be changed in the future based on the length of the strips and the Raspberry PI version.
Dependencies
The component has 2 dependencies besides the core.
rpi_ws281x
The rpi_ws281x makes it possible to control the pins of the Raspberry programmatically. It has to be initialized with the length of the connected LED strips and a few other metadata. A simple Raspberry is able to control 2 different strips on 2 independent channels. These channels can be initialized differently.
The render function of this library is called in the main loop after the tick function fills the buffer for every LED. The render function expects an array filled with 32 bit numbers each representing an array. The first 8 bit represents the R channel, the second 8 bit represents the G channel and the third 8 bit represents the B channel. The last 8 bit is not used. This is the representation that has to be made by the buffer fill function.
cpp-httplib
The cpp-httplib makes it possible to create an HTTP server and this is key to control the animations from other components like a web based frontend or a mobile device. The exact interface is detailed in the HTTP interface section.