Skip to content

A Rust program to control bias lighting on Linux and Windows.

Notifications You must be signed in to change notification settings

iwanders/displaylight_rs

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

displaylight_rs

display_light_active

I've continued development on the screen_capture crate here.

This Rust workspace is a rewrite of my DisplayLight project. It colors leds mounted behind the monitor with the colors shown on the display at that location, this is known as bias lighting, (example gif).

Approach is still the same as in the original project:

  • Screen capture takes a snapshot of the screen and keeps it in shared memory.
  • Black border detection is performed to find the interesting region on the screen. Only allowing smooth transitions between border sizes to prevent flickerring in dark scenes.
  • Zones are created from this region of interest, each zone will map to one led.
  • Zones are sampled, sampled colors averaged to determine zone value and thus led color.
  • Led string is updated with the obtained values.

The hardware is now based on an STM32F103 'blue pill' development board. It is further described in the firmware directory, the firmware is also written in Rust.

Running on either Windows and on Linux is a matter of cargo run --release. Configuration lives in config and is selected based on the operating system. Performance is identical to the C++ version, running at ~3% of an i7-4770TE core when sampling a 1920x1080 image at 60 Hz.

The screen_capture crate used to obtain the screen captures is completely stand alone and could has been used outside of this project.

displaylight_fw

Firmware for displaylight_rs, target platform is an STM32F103 'blue pill' development board. Uses 288 rgb leds of the ws2811 type.

In bulletpoints

  • The main logic is in the Lights structure. The main file holds the setup and main loop.
  • If communication stops (PC turns off) leds fade gracefully.
  • TIM2 is used for global timekeeping, providing time difference.
  • USB Serial port is available and facilitates easy debug printing from anywhere using SPSC ringbuffers.
  • The SPI bus is used to create the signal for the LEDs.
  • Each ws2811 bit is sent by using a full byte on the SPI bus.
  • SPI bus runs at 6 MHz and transfers 228 * 3 * 8 = 5472 bytes for each full led update.
  • SPI write operation is done through a DMA channel, freeing up the MCU while writing to the leds.
  • Gamma correction is applied just before the LED's RGB channels are expanded into SPI bytes.

Circuit

The pcb to connect the STM32F103 to the uses a sacrificial led to ensure the signal gets converted from 3.3v to 5.0v logic level.

Test

cargo t --target x86_64-unknown-linux-gnu

Flash and run

Run openocd in this directory, then in another terminal run;

cargo r --profile firmware

Note on interrupts

usb_dev.poll(&mut [serial])

Is supposed to be called as many times as possible, preferably from an interrupt. But it seems that enabling NVIC::unmask(Interrupt::USB_LP_CAN_RX0); and calling it from that interrupt causes the interrupt to fire indefinitely on itself. Instead, this is just called from the main program loop.

License

License is MIT OR Apache-2.0.