diff options
Diffstat (limited to 'klippy/chelper/stepcompress.c')
-rw-r--r-- | klippy/chelper/stepcompress.c | 96 |
1 files changed, 30 insertions, 66 deletions
diff --git a/klippy/chelper/stepcompress.c b/klippy/chelper/stepcompress.c index 7b92e3db..4847bf16 100644 --- a/klippy/chelper/stepcompress.c +++ b/klippy/chelper/stepcompress.c @@ -1,9 +1,9 @@ // Stepper pulse schedule compression // -// Copyright (C) 2016-2018 Kevin O'Connor <kevin@koconnor.net> +// Copyright (C) 2016-2020 Kevin O'Connor <kevin@koconnor.net> // // This file may be distributed under the terms of the GNU GPLv3 license. -// + // The goal of this code is to take a series of scheduled stepper // pulse times and compress them into a handful of commands that can // be efficiently transmitted and executed on a microcontroller (mcu). @@ -32,7 +32,7 @@ struct stepcompress { uint32_t *queue, *queue_end, *queue_pos, *queue_next; // Internal tracking uint32_t max_error; - double mcu_time_offset, mcu_freq; + double mcu_time_offset, mcu_freq, last_step_print_time; // Message generation uint64_t last_step_clock; struct list_head msg_queue; @@ -261,6 +261,14 @@ stepcompress_free(struct stepcompress *sc) free(sc); } +// Determine the "print time" of the last_step_clock +static void +calc_last_step_print_time(struct stepcompress *sc) +{ + double lsc = sc->last_step_clock; + sc->last_step_print_time = sc->mcu_time_offset + (lsc - .5) / sc->mcu_freq; +} + // Convert previously scheduled steps into commands for the mcu static int stepcompress_flush(struct stepcompress *sc, uint64_t move_clock) @@ -289,6 +297,7 @@ stepcompress_flush(struct stepcompress *sc, uint64_t move_clock) } sc->queue_pos += move.count; } + calc_last_step_print_time(sc); return 0; } @@ -304,6 +313,7 @@ stepcompress_flush_far(struct stepcompress *sc, uint64_t abs_step_clock) qm->min_clock = sc->last_step_clock; sc->last_step_clock = qm->req_clock = abs_step_clock; list_add_tail(&qm->node, &sc->msg_queue); + calc_last_step_print_time(sc); return 0; } @@ -335,6 +345,7 @@ stepcompress_reset(struct stepcompress *sc, uint64_t last_step_clock) return ret; sc->last_step_clock = last_step_clock; sc->sdir = -1; + calc_last_step_print_time(sc); return 0; } @@ -359,12 +370,7 @@ stepcompress_set_time(struct stepcompress *sc { sc->mcu_time_offset = time_offset; sc->mcu_freq = mcu_freq; -} - -double -stepcompress_get_mcu_freq(struct stepcompress *sc) -{ - return sc->mcu_freq; + calc_last_step_print_time(sc); } uint32_t @@ -379,33 +385,10 @@ stepcompress_get_step_dir(struct stepcompress *sc) return sc->sdir; } - -/**************************************************************** - * Queue management - ****************************************************************/ - // Maximium clock delta between messages in the queue #define CLOCK_DIFF_MAX (3<<28) -// Create a cursor for inserting clock times into the queue -inline struct queue_append -queue_append_start(struct stepcompress *sc, double print_time, double adjust) -{ - double print_clock = (print_time - sc->mcu_time_offset) * sc->mcu_freq; - return (struct queue_append) { - .sc = sc, .qnext = sc->queue_next, .qend = sc->queue_end, - .last_step_clock_32 = sc->last_step_clock, - .clock_offset = (print_clock - (double)sc->last_step_clock) + adjust }; -} - -// Finalize a cursor created with queue_append_start() -inline void -queue_append_finish(struct queue_append qa) -{ - qa.sc->queue_next = qa.qnext; -} - -// Slow path for queue_append() +// Slow path for stepcompress_append() static int queue_append_slow(struct stepcompress *sc, double rel_sc) { @@ -453,42 +436,23 @@ queue_append_slow(struct stepcompress *sc, double rel_sc) return 0; } -// Add a clock time to the queue (flushing the queue if needed) +// Add a step time to the queue (flushing the queue if needed) inline int -queue_append(struct queue_append *qa, double step_clock) +stepcompress_append(struct stepcompress *sc, int sdir + , double print_time, double step_time) { - double rel_sc = step_clock + qa->clock_offset; - if (likely(!(qa->qnext >= qa->qend || rel_sc >= (double)CLOCK_DIFF_MAX))) { - *qa->qnext++ = qa->last_step_clock_32 + (uint32_t)rel_sc; - return 0; + if (unlikely(sdir != sc->sdir)) { + int ret = set_next_step_dir(sc, sdir); + if (ret) + return ret; } - // Call queue_append_slow() to handle queue expansion and integer overflow - struct stepcompress *sc = qa->sc; - uint64_t old_last_step_clock = sc->last_step_clock; - sc->queue_next = qa->qnext; - int ret = queue_append_slow(sc, rel_sc); - if (ret) - return ret; - qa->qnext = sc->queue_next; - qa->qend = sc->queue_end; - qa->last_step_clock_32 = sc->last_step_clock; - qa->clock_offset -= sc->last_step_clock - old_last_step_clock; - return 0; -} - -inline int -queue_append_set_next_step_dir(struct queue_append *qa, int sdir) -{ - struct stepcompress *sc = qa->sc; - uint64_t old_last_step_clock = sc->last_step_clock; - sc->queue_next = qa->qnext; - int ret = set_next_step_dir(sc, sdir); - if (ret) - return ret; - qa->qnext = sc->queue_next; - qa->qend = sc->queue_end; - qa->last_step_clock_32 = sc->last_step_clock; - qa->clock_offset -= sc->last_step_clock - old_last_step_clock; + double offset = print_time - sc->last_step_print_time; + double rel_sc = (step_time + offset) * sc->mcu_freq; + if (unlikely(sc->queue_next >= sc->queue_end + || rel_sc >= (double)CLOCK_DIFF_MAX)) + // Slow path to handle queue expansion and integer overflow + return queue_append_slow(sc, rel_sc); + *sc->queue_next++ = (uint32_t)sc->last_step_clock + (uint32_t)rel_sc; return 0; } |