diff --git a/docs/MCU_Commands.md b/docs/MCU_Commands.md index 921f402a..79425a2e 100644 --- a/docs/MCU_Commands.md +++ b/docs/MCU_Commands.md @@ -133,15 +133,13 @@ This section lists some commonly used config commands. see the description of the 'set_pwm_out' and 'config_digital_out' commands for parameter description. -* `config_soft_pwm_out oid=%c pin=%u cycle_ticks=%u value=%c +* `config_soft_pwm_out oid=%c pin=%u value=%c default_value=%c max_duration=%u` : This command creates an internal micro-controller object for software implemented PWM. Unlike hardware pwm pins, a software pwm object does not require any special hardware support (other than the ability to configure the - pin as a digital output GPIO). Because the output switching is - implemented in the micro-controller software, it is recommended that - the cycle_ticks parameter correspond to a time of 10ms or greater. - See the description of the 'set_pwm_out' and 'config_digital_out' + pin as a digital output GPIO). See the description of + the 'set_pwm_out' and 'config_digital_out' commands for parameter description. * `config_analog_in oid=%c pin=%u` : This command is used to configure @@ -203,9 +201,13 @@ only of interest to developers looking to gain insight into Klipper. a hardware PWM output pin. See the 'schedule_digital_out' and 'config_pwm_out' commands for more info. -* `schedule_soft_pwm_out oid=%c clock=%u on_ticks=%u` : Schedules a - change to a software PWM output pin. See the 'schedule_digital_out' - and 'config_soft_pwm_out' commands for more info. +* `schedule_soft_pwm_out oid=%c clock=%u on_ticks=%u off_ticks=%u` : Schedules a + change to a software PWM output pin. The parameters 'on_ticks' and 'off_ticks' + define for how many ticks the pin will be on and off, respectively. + Because the output switching is implemented in the micro-controller software, + it is recommended that the sum of on_ticks and off_ticks parameters + corresponds to a time of 10ms or greater. See the 'schedule_digital_out' and + 'config_soft_pwm_out' commands for more info. * `query_analog_in oid=%c clock=%u sample_ticks=%u sample_count=%c rest_ticks=%u min_value=%hu max_value=%hu` : This command sets up a diff --git a/klippy/mcu.py b/klippy/mcu.py index c919d88e..70e6b969 100644 --- a/klippy/mcu.py +++ b/klippy/mcu.py @@ -233,28 +233,35 @@ class MCU_pwm: return self._oid = self._mcu.create_oid() self._mcu.add_config_cmd( - "config_soft_pwm_out oid=%d pin=%s cycle_ticks=%d value=%d" + "config_soft_pwm_out oid=%d pin=%s value=%d" " default_value=%d max_duration=%d" - % (self._oid, self._pin, cycle_ticks, - self._start_value >= 1.0, self._shutdown_value >= 0.5, + % (self._oid, self._pin, self._start_value >= 1.0, + self._shutdown_value >= 0.5, self._mcu.seconds_to_clock(self._max_duration))) curtime = self._mcu.get_printer().get_reactor().monotonic() printtime = self._mcu.estimated_print_time(curtime) self._last_clock = self._mcu.print_time_to_clock(printtime + 0.100) svalue = int(self._start_value * self._pwm_max + 0.5) self._mcu.add_config_cmd( - "schedule_soft_pwm_out oid=%d clock=%d on_ticks=%d" - % (self._oid, self._last_clock, svalue), is_init=True) + "schedule_soft_pwm_out oid=%d clock=%d on_ticks=%d off_ticks=%d" + % (self._oid, self._last_clock, svalue, cycle_ticks - svalue), + is_init=True) self._set_cmd = self._mcu.lookup_command( - "schedule_soft_pwm_out oid=%c clock=%u on_ticks=%u", + "schedule_soft_pwm_out oid=%c clock=%u on_ticks=%u off_ticks=%u", cq=cmd_queue) def set_pwm(self, print_time, value): + cycle_ticks = self._mcu.seconds_to_clock(self._cycle_time) clock = self._mcu.print_time_to_clock(print_time) if self._invert: value = 1. - value - value = int(max(0., min(1., value)) * self._pwm_max + 0.5) - self._set_cmd.send([self._oid, clock, value], - minclock=self._last_clock, reqclock=clock) + on_ticks = int(max(0., min(1., value)) * float(cycle_ticks) + 0.5) + if self._hardware_pwm: + self._set_cmd.send([self._oid, clock, on_ticks], + minclock=self._last_clock, reqclock=clock) + else: + off_ticks = cycle_ticks - on_ticks + self._set_cmd.send([self._oid, clock, on_ticks, off_ticks], + minclock=self._last_clock, reqclock=clock) self._last_clock = clock class MCU_adc: diff --git a/src/gpiocmds.c b/src/gpiocmds.c index 91d97b75..e6bf4671 100644 --- a/src/gpiocmds.c +++ b/src/gpiocmds.c @@ -110,7 +110,7 @@ struct soft_pwm_s { struct timer timer; uint32_t on_duration, off_duration, end_time; uint32_t next_on_duration, next_off_duration; - uint32_t max_duration, cycle_time; + uint32_t max_duration; struct gpio_out pin; uint8_t default_value, flags; }; @@ -172,32 +172,31 @@ soft_pwm_load_event(struct timer *timer) void command_config_soft_pwm_out(uint32_t *args) { - struct gpio_out pin = gpio_out_setup(args[1], !!args[3]); + struct gpio_out pin = gpio_out_setup(args[1], !!args[2]); struct soft_pwm_s *s = oid_alloc(args[0], command_config_soft_pwm_out , sizeof(*s)); s->pin = pin; - s->cycle_time = args[2]; - s->default_value = !!args[4]; - s->max_duration = args[5]; + s->default_value = !!args[3]; + s->max_duration = args[4]; s->flags = s->default_value ? SPF_ON : 0; } DECL_COMMAND(command_config_soft_pwm_out, - "config_soft_pwm_out oid=%c pin=%u cycle_ticks=%u value=%c" + "config_soft_pwm_out oid=%c pin=%u value=%c" " default_value=%c max_duration=%u"); void command_schedule_soft_pwm_out(uint32_t *args) { struct soft_pwm_s *s = oid_lookup(args[0], command_config_soft_pwm_out); - uint32_t time = args[1], next_on_duration = args[2], next_off_duration; + uint32_t time = args[1], next_on_duration = args[2], + next_off_duration = args[3]; uint8_t next_flags = SPF_CHECK_END | SPF_HAVE_NEXT; - if (next_on_duration == 0 || next_on_duration >= s->cycle_time) { + if (next_on_duration == 0 || next_off_duration == 0) { next_flags |= next_on_duration ? SPF_NEXT_ON : 0; if (!!next_on_duration != s->default_value && s->max_duration) next_flags |= SPF_NEXT_CHECK_END; next_on_duration = next_off_duration = 0; } else { - next_off_duration = s->cycle_time - next_on_duration; next_flags |= SPF_NEXT_ON | SPF_NEXT_TOGGLING; if (s->max_duration) next_flags |= SPF_NEXT_CHECK_END; @@ -221,7 +220,7 @@ command_schedule_soft_pwm_out(uint32_t *args) irq_enable(); } DECL_COMMAND(command_schedule_soft_pwm_out, - "schedule_soft_pwm_out oid=%c clock=%u on_ticks=%u"); + "schedule_soft_pwm_out oid=%c clock=%u on_ticks=%u off_ticks=%u"); void soft_pwm_shutdown(void)