More functions
Some other functions need to be implemented so that the driver can be fully (color mode) and efficiently driven.
Set led color
int dm163_set_color(const struct device *dev, uint32_t led, uint8_t num_colors,
const uint8_t *color);
This function sets a led color. color
contains the red, green, and blue component, in order. If some are missing, you can assume them to be 0. Don't forget to send the new channels value to the chip after doing so. As always, an incorrect led number or too great the number of colors will return -EINVAL
instead of 0.
This corresponds to the set_color
entry in the struct led_driver_api
definition.
Set channels in bulk
int dm163_write_channels(const struct device *dev, uint32_t start_channel,
uint32_t num_channels, const uint8_t *buf);
Write channels in bulk. Make sure you check the bounds. This corresponds to the write_channels
entry in the struct led_driver_api
definition.
Using the functions
You can now use the shell led set_color dm163 4 0 0 255
to display a beautiful blue led. Of course, it might be easier to stop the animation first to see it, and activate only one line.
Driving the whole matrix
Create a new image structure made of 8×3×8 channels representing the whole led matrix. Make a thread which waits on a semaphore and display the next line using led_write_channels()
when the semaphore is signaled. Make a timer signal the semaphore approximately every 1÷(8×60) second. Enjoy your beautiful image.
Prevent race conditions
There is a risk that some thread changes the brightness (and sends the brightness information to the DM163) while another thread is changing a channel color value (and sends this information to the DM163): both threads will try to talk to the DM163 at the same time.
Add a mutex to the dm163_data
structure, and take the mutex before flushing the colors or the brightness to the DM163.
To go further
Add a function with the following prototype in dm163_module/zephyr/dm163.h
:
void dm163_turn_off_row(const struct device *dev, const struct gpio_dt_spec *row);
(with the missing includes, and protection against multiple inclusion)
This function will remember the given row
in the dm163_data
structure. The next time flush_channels()
is sending data to the DM163, as soon as data for the first six leds have been sent, the given row
GPIO will be turned off. Then data for the remaining two leds will be sent and row
will be forgotten by storing NULL
instead.
By using this function, you might be able to turn a row off soon enough so that it has time to turn off completely before new data is latched, and late enough to keep a maximum of brightness. For example, this code
gpio_pin_set_dt(&rows[row], 0); // Turn row "row" off
led_write_channels(&dm163_dev, …); // Send data for row "row+1"
gpio_pin_set_dt(&rows[row+1], 1); // Turn row "row+1" on
would be replaced by
dm163_turn_off_row(&dm163_dev, &rows[row]); // Remember the row to turn off
led_write_channels(&dm163_dev, …); // Send data for row "row+1". As a side
// effect, row "row" will be turned off
// when 6/8th of the data has been sent.
gpio_pin_set_dt(&rows[row+1], 1);
and give a better visual effect.