aboutsummaryrefslogtreecommitdiffstats
path: root/klippy/stepcompress.c
diff options
context:
space:
mode:
authorKevin O'Connor <kevin@koconnor.net>2017-02-06 11:37:03 -0500
committerKevin O'Connor <kevin@koconnor.net>2017-02-06 12:17:50 -0500
commit19ed67331d7c957cc26f750b7d3cce23688753e4 (patch)
tree65c892f501734d11aaa048e0c9df84f2bb4829f0 /klippy/stepcompress.c
parent667b72870f122c5cb08a3abf7c692f824e24383c (diff)
downloadkutter-19ed67331d7c957cc26f750b7d3cce23688753e4.tar.gz
kutter-19ed67331d7c957cc26f750b7d3cce23688753e4.tar.xz
kutter-19ed67331d7c957cc26f750b7d3cce23688753e4.zip
stepcompress: Propagate errors back to python code
Propagate error codes back to the python code and raise an exception on an error. Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
Diffstat (limited to 'klippy/stepcompress.c')
-rw-r--r--klippy/stepcompress.c163
1 files changed, 107 insertions, 56 deletions
diff --git a/klippy/stepcompress.c b/klippy/stepcompress.c
index e7d09572..5b401cbe 100644
--- a/klippy/stepcompress.c
+++ b/klippy/stepcompress.c
@@ -31,8 +31,6 @@ struct stepcompress {
uint64_t *queue, *queue_end, *queue_pos, *queue_next;
// Internal tracking
uint32_t max_error;
- // Error checking
- uint32_t errors;
// Message generation
uint64_t last_step_clock, homing_clock;
struct list_head msg_queue;
@@ -224,27 +222,28 @@ compress_bisect_add(struct stepcompress *sc)
* Step compress checking
****************************************************************/
+#define ERROR_RET -989898989
+
// Verify that a given 'step_move' matches the actual step times
-static void
+static int
check_line(struct stepcompress *sc, struct step_move move)
{
if (!CHECK_LINES)
- return;
+ return 0;
if (move.count == 1) {
if (move.interval != (uint32_t)(*sc->queue_pos - sc->last_step_clock)
|| *sc->queue_pos < sc->last_step_clock) {
errorf("Count 1 point out of range: %d %d %d"
, move.interval, move.count, move.add);
- sc->errors++;
+ return ERROR_RET;
}
- return;
+ return 0;
}
- int err = 0;
if (!move.count || (!move.interval && !move.add)
|| move.interval >= 0x80000000) {
errorf("Point out of range: %d %d %d"
, move.interval, move.count, move.add);
- err++;
+ return ERROR_RET;
}
uint32_t interval = move.interval, p = 0;
uint16_t i;
@@ -254,16 +253,16 @@ check_line(struct stepcompress *sc, struct step_move move)
if (p < point.minp || p > point.maxp) {
errorf("Point %d of %d: %d not in %d:%d"
, i+1, move.count, p, point.minp, point.maxp);
- err++;
+ return ERROR_RET;
}
if (interval >= 0x80000000) {
errorf("Point %d of %d: interval overflow %d"
, i+1, move.count, interval);
- err++;
+ return ERROR_RET;
}
interval += move.add;
}
- sc->errors += err;
+ return 0;
}
@@ -317,14 +316,16 @@ stepcompress_free(struct stepcompress *sc)
}
// Convert previously scheduled steps into commands for the mcu
-static void
+static int
stepcompress_flush(struct stepcompress *sc, uint64_t move_clock)
{
if (sc->queue_pos >= sc->queue_next)
- return;
+ return 0;
while (move_clock > sc->last_step_clock) {
struct step_move move = compress_bisect_add(sc);
- check_line(sc, move);
+ int ret = check_line(sc, move);
+ if (ret)
+ return ret;
uint32_t msg[5] = {
sc->queue_step_msgid, sc->oid, move.interval, move.count, move.add
@@ -350,54 +351,70 @@ stepcompress_flush(struct stepcompress *sc, uint64_t move_clock)
}
sc->queue_pos += move.count;
}
+ return 0;
}
// Send the set_next_step_dir command
-static void
+static int
set_next_step_dir(struct stepcompress *sc, int sdir)
{
if (sc->sdir == sdir)
- return;
+ return 0;
sc->sdir = sdir;
- stepcompress_flush(sc, UINT64_MAX);
+ int ret = stepcompress_flush(sc, UINT64_MAX);
+ if (ret)
+ return ret;
uint32_t msg[3] = {
sc->set_next_step_dir_msgid, sc->oid, sdir ^ sc->invert_sdir
};
struct queue_message *qm = message_alloc_and_encode(msg, 3);
qm->req_clock = sc->homing_clock ?: sc->last_step_clock;
list_add_tail(&qm->node, &sc->msg_queue);
+ return 0;
}
// Check if the internal queue needs to be expanded, and expand if so
-static void
+static int
_check_expand(struct stepcompress *sc, uint64_t *qn)
{
sc->queue_next = qn;
- if (qn - sc->queue_pos > 65535 + 2000)
+ if (qn - sc->queue_pos > 65535 + 2000) {
// No point in keeping more than 64K steps in memory
- stepcompress_flush(sc, *(qn - 65535));
+ int ret = stepcompress_flush(sc, *(qn - 65535));
+ if (ret)
+ return ret;
+ }
expand_queue(sc, 1);
+ return 0;
}
-static inline void
+static inline int
check_expand(struct stepcompress *sc, uint64_t **pqn, uint64_t **pqend)
{
if (likely(*pqn < *pqend))
- return;
- _check_expand(sc, *pqn);
+ return 0;
+ int ret = _check_expand(sc, *pqn);
+ if (ret)
+ return ret;
*pqn = sc->queue_next;
*pqend = sc->queue_end;
+ return 0;
}
// Schedule a step event at the specified step_clock time
-void
+int
stepcompress_push(struct stepcompress *sc, double step_clock, int32_t sdir)
{
- set_next_step_dir(sc, !!sdir);
+ int ret = set_next_step_dir(sc, !!sdir);
+ if (ret)
+ return ret;
step_clock += 0.5;
uint64_t *qn = sc->queue_next, *qend = sc->queue_end;
- check_expand(sc, &qn, &qend);
+ ret = check_expand(sc, &qn, &qend);
+ if (ret)
+ return ret;
*qn++ = step_clock;
sc->queue_next = qn;
+ return 0;
}
// Schedule 'steps' number of steps with a constant time between steps
@@ -416,12 +433,16 @@ stepcompress_push_factor(struct stepcompress *sc
}
int count = steps + .5 - step_offset;
if (count <= 0 || count > 10000000) {
- if (count && steps)
+ if (count && steps) {
errorf("push_factor invalid count %d %f %f %f %f"
, sc->oid, steps, step_offset, clock_offset, factor);
+ return ERROR_RET;
+ }
return 0;
}
- set_next_step_dir(sc, sdir);
+ int ret = set_next_step_dir(sc, sdir);
+ if (ret)
+ return ret;
int res = sdir ? count : -count;
// Calculate each step time
@@ -429,7 +450,9 @@ stepcompress_push_factor(struct stepcompress *sc
double pos = step_offset + .5;
uint64_t *qn = sc->queue_next, *qend = sc->queue_end;
while (count--) {
- check_expand(sc, &qn, &qend);
+ int ret = check_expand(sc, &qn, &qend);
+ if (ret)
+ return ret;
*qn++ = clock_offset + pos*factor;
pos += 1.0;
}
@@ -452,13 +475,17 @@ stepcompress_push_sqrt(struct stepcompress *sc, double steps, double step_offset
}
int count = steps + .5 - step_offset;
if (count <= 0 || count > 10000000) {
- if (count && steps)
+ if (count && steps) {
errorf("push_sqrt invalid count %d %f %f %f %f %f"
, sc->oid, steps, step_offset, clock_offset, sqrt_offset
, factor);
+ return ERROR_RET;
+ }
return 0;
}
- set_next_step_dir(sc, sdir);
+ int ret = set_next_step_dir(sc, sdir);
+ if (ret)
+ return ret;
int res = sdir ? count : -count;
// Calculate each step time
@@ -466,7 +493,9 @@ stepcompress_push_sqrt(struct stepcompress *sc, double steps, double step_offset
double pos = step_offset + .5 + sqrt_offset/factor;
uint64_t *qn = sc->queue_next, *qend = sc->queue_end;
while (count--) {
- check_expand(sc, &qn, &qend);
+ int ret = check_expand(sc, &qn, &qend);
+ if (ret)
+ return ret;
double v = safe_sqrt(pos*factor);
*qn++ = clock_offset + (factor >= 0. ? v : -v);
pos += 1.0;
@@ -488,13 +517,17 @@ stepcompress_push_delta_const(
double end_height = safe_sqrt(closest_height2 - reldist*reldist);
int count = (end_height - height + movez_r*dist) / step_dist + .5;
if (count <= 0 || count > 10000000) {
- if (count)
+ if (count) {
errorf("push_delta_const invalid count %d %d %f %f %f %f %f %f %f %f"
, sc->oid, count, clock_offset, dist, step_dist, start_pos
, closest_height2, height, movez_r, inv_velocity);
+ return ERROR_RET;
+ }
return 0;
}
- set_next_step_dir(sc, step_dist > 0.);
+ int ret = set_next_step_dir(sc, step_dist > 0.);
+ if (ret)
+ return ret;
int res = step_dist > 0. ? count : -count;
// Calculate each step time
@@ -505,7 +538,9 @@ stepcompress_push_delta_const(
if (!movez_r) {
// Optmized case for common XY only moves (no Z movement)
while (count--) {
- check_expand(sc, &qn, &qend);
+ int ret = check_expand(sc, &qn, &qend);
+ if (ret)
+ return ret;
double v = safe_sqrt(closest_height2 - height*height);
double pos = start_pos + (step_dist > 0. ? -v : v);
*qn++ = clock_offset + pos * inv_velocity;
@@ -515,7 +550,9 @@ stepcompress_push_delta_const(
// Optmized case for Z only moves
double v = (step_dist > 0. ? -end_height : end_height);
while (count--) {
- check_expand(sc, &qn, &qend);
+ int ret = check_expand(sc, &qn, &qend);
+ if (ret)
+ return ret;
double pos = start_pos + movez_r*height + v;
*qn++ = clock_offset + pos * inv_velocity;
height += step_dist;
@@ -523,7 +560,9 @@ stepcompress_push_delta_const(
} else {
// General case (handles XY+Z moves)
while (count--) {
- check_expand(sc, &qn, &qend);
+ int ret = check_expand(sc, &qn, &qend);
+ if (ret)
+ return ret;
double relheight = movexy_r*height - movez_r*closestxy_d;
double v = safe_sqrt(closest_height2 - relheight*relheight);
double pos = start_pos + movez_r*height + (step_dist > 0. ? -v : v);
@@ -548,13 +587,17 @@ stepcompress_push_delta_accel(
double end_height = safe_sqrt(closest_height2 - reldist*reldist);
int count = (end_height - height + movez_r*dist) / step_dist + .5;
if (count <= 0 || count > 10000000) {
- if (count)
+ if (count) {
errorf("push_delta_accel invalid count %d %d %f %f %f %f %f %f %f %f"
, sc->oid, count, clock_offset, dist, step_dist, start_pos
, closest_height2, height, movez_r, accel_multiplier);
+ return ERROR_RET;
+ }
return 0;
}
- set_next_step_dir(sc, step_dist > 0.);
+ int ret = set_next_step_dir(sc, step_dist > 0.);
+ if (ret)
+ return ret;
int res = step_dist > 0. ? count : -count;
// Calculate each step time
@@ -563,7 +606,9 @@ stepcompress_push_delta_accel(
height += .5 * step_dist;
uint64_t *qn = sc->queue_next, *qend = sc->queue_end;
while (count--) {
- check_expand(sc, &qn, &qend);
+ int ret = check_expand(sc, &qn, &qend);
+ if (ret)
+ return ret;
double relheight = movexy_r*height - movez_r*closestxy_d;
double v = safe_sqrt(closest_height2 - relheight*relheight);
double pos = start_pos + movez_r*height + (step_dist > 0. ? -v : v);
@@ -576,38 +621,40 @@ stepcompress_push_delta_accel(
}
// Reset the internal state of the stepcompress object
-void
+int
stepcompress_reset(struct stepcompress *sc, uint64_t last_step_clock)
{
- stepcompress_flush(sc, UINT64_MAX);
+ int ret = stepcompress_flush(sc, UINT64_MAX);
+ if (ret)
+ return ret;
sc->last_step_clock = last_step_clock;
sc->sdir = -1;
+ return 0;
}
// Indicate the stepper is in homing mode (or done homing if zero)
-void
+int
stepcompress_set_homing(struct stepcompress *sc, uint64_t homing_clock)
{
- stepcompress_flush(sc, UINT64_MAX);
+ int ret = stepcompress_flush(sc, UINT64_MAX);
+ if (ret)
+ return ret;
sc->homing_clock = homing_clock;
+ return 0;
}
// Queue an mcu command to go out in order with stepper commands
-void
+int
stepcompress_queue_msg(struct stepcompress *sc, uint32_t *data, int len)
{
- stepcompress_flush(sc, UINT64_MAX);
+ int ret = stepcompress_flush(sc, UINT64_MAX);
+ if (ret)
+ return ret;
struct queue_message *qm = message_alloc_and_encode(data, len);
qm->req_clock = sc->homing_clock ?: sc->last_step_clock;
list_add_tail(&qm->node, &sc->msg_queue);
-}
-
-// Return the count of internal errors found
-uint32_t
-stepcompress_get_errors(struct stepcompress *sc)
-{
- return sc->errors;
+ return 0;
}
@@ -693,13 +740,16 @@ heap_replace(struct steppersync *ss, uint64_t req_clock)
}
// Find and transmit any scheduled steps prior to the given 'move_clock'
-void
+int
steppersync_flush(struct steppersync *ss, uint64_t move_clock)
{
// Flush each stepcompress to the specified move_clock
int i;
- for (i=0; i<ss->sc_num; i++)
- stepcompress_flush(ss->sc_list[i], move_clock);
+ for (i=0; i<ss->sc_num; i++) {
+ int ret = stepcompress_flush(ss->sc_list[i], move_clock);
+ if (ret)
+ return ret;
+ }
// Order commands by the reqclock of each pending command
struct list_head msgs;
@@ -739,4 +789,5 @@ steppersync_flush(struct steppersync *ss, uint64_t move_clock)
// Transmit commands
if (!list_empty(&msgs))
serialqueue_send_batch(ss->sq, ss->cq, &msgs);
+ return 0;
}