led: run update function as reactor callback

Update functions could be called within the flush/lookahead context
If the update function internally does pause()
That would lead to the unpredictable execution of time-critical functions

Signed-off-by: Timofey Titovets <nefelim4ag@gmail.com>
This commit is contained in:
Timofey Titovets
2025-10-11 15:10:13 +02:00
committed by KevinOConnor
parent aea8d8e0a1
commit 6a8b823a45
4 changed files with 14 additions and 12 deletions

View File

@@ -10,6 +10,7 @@ from . import output_pin
class LEDHelper:
def __init__(self, config, update_func, led_count=1):
self.printer = config.get_printer()
self.mutex = self.printer.get_reactor().mutex()
self.update_func = update_func
self.led_count = led_count
self.need_transmit = False
@@ -59,11 +60,16 @@ class LEDHelper:
def _check_transmit(self, print_time=None):
if not self.need_transmit:
return
# Just avoid any race conditions
led_state = self.led_state
self.need_transmit = False
try:
self.update_func(self.led_state, print_time)
except self.printer.command_error as e:
logging.exception("led update transmit error")
def reactor_cb(eventtime):
try:
with self.mutex:
self.update_func(led_state, print_time)
except self.printer.command_error as e:
logging.exception("led update transmit error")
self.printer.get_reactor().register_callback(reactor_cb)
cmd_SET_LED_help = "Set the color of an LED"
def cmd_SET_LED(self, gcmd):
# Parse parameters

View File

@@ -16,7 +16,6 @@ MAX_MCU_SIZE = 500 # Sanity check on LED chain length
class PrinterNeoPixel:
def __init__(self, config):
self.printer = printer = config.get_printer()
self.mutex = printer.get_reactor().mutex()
# Configure neopixel
ppins = printer.lookup_object('pins')
pin_params = ppins.lookup_pin(config.get('pin'))
@@ -99,11 +98,8 @@ class PrinterNeoPixel:
else:
logging.info("Neopixel update did not succeed")
def update_leds(self, led_state, print_time):
def reactor_bgfunc(eventtime):
with self.mutex:
self.update_color_data(led_state)
self.send_data(print_time)
self.printer.get_reactor().register_callback(reactor_bgfunc)
self.update_color_data(led_state)
self.send_data(print_time)
def get_status(self, eventtime=None):
return self.led_helper.get_status(eventtime)

View File

@@ -27,7 +27,7 @@ class PCA9533:
minclock = 0
if print_time is not None:
minclock = self.i2c.get_mcu().print_time_to_clock(print_time)
self.i2c.i2c_write_noack([PCA9533_PLS0, ls0], minclock=minclock,
self.i2c.i2c_write([PCA9533_PLS0, ls0], minclock=minclock,
reqclock=BACKGROUND_PRIORITY_CLOCK)
def get_status(self, eventtime):
return self.led_helper.get_status(eventtime)

View File

@@ -37,7 +37,7 @@ class PCA9632:
if self.prev_regs.get(reg) == val:
return
self.prev_regs[reg] = val
self.i2c.i2c_write_noack([reg, val], minclock=minclock,
self.i2c.i2c_write([reg, val], minclock=minclock,
reqclock=BACKGROUND_PRIORITY_CLOCK)
def handle_connect(self):
#Configure MODE1