Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix threading for python gui #116

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 0 additions & 3 deletions fl16-inputmodules/src/control.rs
Original file line number Diff line number Diff line change
Expand Up @@ -202,9 +202,7 @@ pub enum Command {
GetFps,
SetPowerMode(u8),
GetPowerMode,
/// Set the animation period in milliseconds
SetAnimationPeriod(u16),
/// Get the animation period in milliseconds
GetAnimationPeriod,
#[cfg(feature = "ledmatrix")]
SetPwmFreq(PwmFreqArg),
Expand Down Expand Up @@ -251,7 +249,6 @@ pub struct B1DIsplayState {
pub screensaver: Option<ScreenSaverState>,
pub power_mode: PowerMode,
pub fps_config: FpsConfig,
/// Animation period in microseconds
pub animation_period: u64,
}

Expand Down
1 change: 0 additions & 1 deletion fl16-inputmodules/src/matrix.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,6 @@ pub struct LedmatrixState {
pub sleeping: SleepState,
/// State of the current game, if any
pub game: Option<GameState>,
/// Animation period in microseconds
pub animation_period: u64,
/// Current LED PWM frequency
pub pwm_freq: PwmFreqArg,
Expand Down
14 changes: 1 addition & 13 deletions inputmodule-control/src/inputmodule.rs
Original file line number Diff line number Diff line change
Expand Up @@ -90,12 +90,6 @@ fn match_serialdevs(
// Find all supported Framework devices
for p in ports {
if let SerialPortType::UsbPort(usbinfo) = &p.port_type {
// macOS creates a /dev/cu.* and /dev/tty.* device.
// The latter can only be used for reading, not writing, so we have to ignore it.
#[cfg(target_os = "macos")]
if !p.port_name.starts_with("/dev/tty.") {
continue;
}
if usbinfo.vid == FRAMEWORK_VID && pids.contains(&usbinfo.pid) {
compatible_devs.push(p.port_name.clone());
}
Expand Down Expand Up @@ -1006,13 +1000,7 @@ fn animation_fps_cmd(serialdev: &str, arg: Option<u16>) {
.expect("Failed to open port");

if let Some(fps) = arg {
const MS: u16 = 1000;
if fps < MS {
// It would need to set the animation period lower than 1ms
println!("Unable to set FPS over 1000");
return;
}
let period = (MS / fps).to_le_bytes();
let period = (1000 / fps).to_le_bytes();
simple_cmd_port(&mut port, Command::AnimationPeriod, &[period[0], period[1]]);
} else {
simple_cmd_port(&mut port, Command::AnimationPeriod, &[]);
Expand Down
22 changes: 15 additions & 7 deletions python/inputmodule/gui/gui_threading.py
Original file line number Diff line number Diff line change
@@ -1,21 +1,29 @@
# Global GUI variables
STOP_THREAD = False
DISCONNECTED_DEVS = []
STATUS = ''

def set_status(status):
global STATUS
STATUS = status

def get_status():
global STATUS
return STATUS

def stop_thread():
global STOP_THREAD
STOP_THREAD = True
global STATUS
STATUS = 'STOP_THREAD'


def reset_thread():
global STOP_THREAD
STOP_THREAD = False
global STATUS
if STATUS == 'STOP_THREAD':
STATUS = ''


def is_thread_stopped():
global STOP_THREAD
return STOP_THREAD
global STATUS
return STATUS == 'STOP_THREAD'


def is_dev_disconnected(dev):
Expand Down
26 changes: 18 additions & 8 deletions python/inputmodule/gui/ledmatrix.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,22 +6,26 @@
reset_thread,
is_thread_stopped,
is_dev_disconnected,
set_status,
get_status,
)
from inputmodule.inputmodule.ledmatrix import (
light_leds,
show_string,
eq,
breathing,
animate,
)
from inputmodule.inputmodule import brightness


def countdown(dev, seconds):
"""Run a countdown timer. Lighting more LEDs every 100th of a seconds.
Until the timer runs out and every LED is lit"""
animate(dev, False)
set_status('countdown')
start = datetime.now()
target = seconds * 1_000_000
while True:
while get_status() == 'countdown':
if is_thread_stopped() or is_dev_disconnected(dev.device):
reset_thread()
return
Expand All @@ -37,15 +41,17 @@ def countdown(dev, seconds):

time.sleep(0.01)

light_leds(dev, 306)
breathing(dev)
# blinking(dev)
if get_status() == 'countdown':
light_leds(dev, 306)
breathing(dev)
# blinking(dev)


def blinking(dev):
"""Blink brightness high/off every second.
Keeps currently displayed grid"""
while True:
set_status('blinking')
while get_status() == 'blinking':
if is_thread_stopped() or is_dev_disconnected(dev.device):
reset_thread()
return
Expand All @@ -57,7 +63,9 @@ def blinking(dev):

def random_eq(dev):
"""Display an equlizer looking animation with random values."""
while True:
animate(dev, False)
set_status('random_eq')
while get_status() == 'random_eq':
if is_thread_stopped() or is_dev_disconnected(dev.device):
reset_thread()
return
Expand All @@ -72,7 +80,9 @@ def random_eq(dev):
def clock(dev):
"""Render the current time and display.
Loops forever, updating every second"""
while True:
animate(dev, False)
set_status('clock')
while get_status() == 'clock':
if is_thread_stopped() or is_dev_disconnected(dev.device):
reset_thread()
return
Expand Down
12 changes: 9 additions & 3 deletions python/inputmodule/inputmodule/ledmatrix.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
send_serial,
brightness,
)
from inputmodule.gui.gui_threading import get_status, set_status

WIDTH = 9
HEIGHT = 34
Expand Down Expand Up @@ -69,6 +70,8 @@ def percentage(dev, p):
def animate(dev, b: bool):
"""Tell the firmware to start/stop animation.
Scrolls the currently saved grid vertically down."""
if b:
set_status('animate')
send_command(dev, CommandVals.Animate, [b])


Expand Down Expand Up @@ -104,6 +107,7 @@ def image_bl(dev, image_file):

def camera(dev):
"""Play a live view from the webcam, for fun"""
set_status('camera')
with serial.Serial(dev.device, 115200) as s:
import cv2

Expand All @@ -120,7 +124,7 @@ def camera(dev):
end_x = min(dim[1], start_x + WIDTH)

# Pre-process the video into resized, cropped, grayscale frames
while True:
while get_status() == 'camera':
ret, frame = capture.read()
if not ret:
print("Failed to capture video frames")
Expand All @@ -142,6 +146,7 @@ def camera(dev):


def video(dev, video_file):
set_status('video')
"""Resize and play back a video"""
with serial.Serial(dev.device, 115200) as s:
import cv2
Expand All @@ -161,7 +166,7 @@ def video(dev, video_file):
processed = []

# Pre-process the video into resized, cropped, grayscale frames
while True:
while get_status() == 'video':
ret, frame = capture.read()
if not ret:
print("Failed to read video frames")
Expand Down Expand Up @@ -294,8 +299,9 @@ def all_brightnesses(dev):
def breathing(dev):
"""Animate breathing brightness.
Keeps currently displayed grid"""
set_status('breathing')
# Bright ranges appear similar, so we have to go through those faster
while True:
while get_status() == 'breathing':
# Go quickly from 250 to 50
for i in range(10):
time.sleep(0.03)
Expand Down
Loading