replicape: Only call note_pwm_enable() in main thread

The pca9685_pwm set_pwm() code can be called from a background thread
(when the pin controls a heater).  Propagate updates to the main
thread for enable tracking.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
This commit is contained in:
Kevin O'Connor 2023-01-12 19:43:46 -05:00
parent 1a693c18d6
commit 6026a99ad8
1 changed files with 17 additions and 11 deletions

View File

@ -21,6 +21,7 @@ class pca9685_pwm:
raise pins.error("Pin type not supported on replicape")
self._mcu = replicape.host_mcu
self._mcu.register_config_callback(self._build_config)
self._reactor = self._mcu.get_printer().get_reactor()
self._bus = REPLICAPE_PCA9685_BUS
self._address = REPLICAPE_PCA9685_ADDRESS
self._cycle_time = REPLICAPE_PCA9685_CYCLE_TIME
@ -28,6 +29,7 @@ class pca9685_pwm:
self._oid = None
self._invert = pin_params['invert']
self._start_value = self._shutdown_value = float(self._invert)
self._is_enable = not not self._start_value
self._is_static = False
self._last_clock = 0
self._pwm_max = 0.
@ -53,6 +55,7 @@ class pca9685_pwm:
self._is_static = is_static
self._replicape.note_pwm_start_value(
self._channel, self._start_value, self._shutdown_value)
self._is_enable = not not self._start_value
def _build_config(self):
self._pwm_max = self._mcu.get_constant_float("PCA9685_MAX")
cycle_ticks = self._mcu.seconds_to_clock(self._cycle_time)
@ -80,7 +83,12 @@ class pca9685_pwm:
if self._invert:
value = 1. - value
value = int(max(0., min(1., value)) * self._pwm_max + 0.5)
self._replicape.note_pwm_enable(print_time, self._channel, value)
is_enable = not not value
if is_enable != self._is_enable:
self._is_enable = is_enable
self._reactor.register_async_callback(
(lambda e, s=self, pt=print_time, ie=is_enable:
s._replicape.note_pwm_enable(pt, s._channel, ie)))
self._set_cmd.send([self._oid, clock, value],
minclock=self._last_clock, reqclock=clock)
self._last_clock = clock
@ -148,7 +156,7 @@ class servo_pwm:
pin_resolver.reserve_pin(resv1, config_name)
pin_resolver.reserve_pin(resv2, config_name)
def setup_cycle_time(self, cycle_time, hardware_pwm=False):
self.mcu_pwm.setup_cycle_time(cycle_time, True);
self.mcu_pwm.setup_cycle_time(cycle_time, True)
ReplicapeStepConfig = {
'disable': None,
@ -171,6 +179,7 @@ class Replicape:
self.mcu_pwm_enable = ppins.setup_pin('digital_out', enable_pin)
self.mcu_pwm_enable.setup_max_duration(0.)
self.mcu_pwm_start_value = self.mcu_pwm_shutdown_value = False
self.last_pwm_enable_time = 0.
# Setup power pins
self.pins = {
"power_e": (pca9685_pwm, 5), "power_h": (pca9685_pwm, 3),
@ -180,7 +189,6 @@ class Replicape:
self.servo_pins = {
"servo0": 3, "servo1": 2 }
# Setup stepper config
self.last_stepper_time = 0.
self.stepper_dacs = {}
shift_registers = [1, 0, 0, 1, 1]
for port, name in enumerate('xyzeh'):
@ -227,18 +235,17 @@ class Replicape:
self.mcu_pwm_enable.setup_start_value(
self.mcu_pwm_start_value, self.mcu_pwm_shutdown_value)
self.enabled_channels[channel] = not not start_value
def note_pwm_enable(self, print_time, channel, value):
is_enable = not not value
if self.enabled_channels[channel] == is_enable:
# Nothing to do
return
def note_pwm_enable(self, print_time, channel, is_enable):
self.enabled_channels[channel] = is_enable
# Check if need to set the pca9685 enable pin
pe_time = max(print_time, self.last_pwm_enable_time + PIN_MIN_TIME)
on_channels = [1 for c, e in self.enabled_channels.items() if e]
if not on_channels:
self.mcu_pwm_enable.set_digital(print_time, 0)
self.mcu_pwm_enable.set_digital(pe_time, 0)
self.last_pwm_enable_time = pe_time
elif is_enable and len(on_channels) == 1:
self.mcu_pwm_enable.set_digital(print_time, 1)
self.mcu_pwm_enable.set_digital(pe_time, 1)
self.last_pwm_enable_time = pe_time
# Check if need to set the stepper enable lines
if channel not in self.stepper_dacs:
return
@ -250,7 +257,6 @@ class Replicape:
sr = self.sr_enabled
else:
return
print_time = max(print_time, self.last_stepper_time + PIN_MIN_TIME)
clock = self.host_mcu.print_time_to_clock(print_time)
self.sr_spi.spi_send(sr, minclock=clock, reqclock=clock)
def setup_pin(self, pin_type, pin_params):