stepcompress: Flush periodically if adding more than 64K steps in a move

It's possible for a printer with very fine resolution to require a
large number of steps for a homing operation.  Instead of storing all
of those steps in memory, periodically flush the queue should more
than 64K steps be present.  This keeps a reasonable limit on the
amount of ram needed to store steps.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
This commit is contained in:
Kevin O'Connor 2016-12-31 13:21:53 -05:00
parent 73c4be3fd3
commit 8e797e6830
1 changed files with 51 additions and 27 deletions

View File

@ -356,6 +356,8 @@ stepcompress_flush(struct stepcompress *sc, uint64_t move_clock)
static void static void
set_next_step_dir(struct stepcompress *sc, int sdir) set_next_step_dir(struct stepcompress *sc, int sdir)
{ {
if (sc->sdir == sdir)
return;
sc->sdir = sdir; sc->sdir = sdir;
stepcompress_flush(sc, UINT64_MAX); stepcompress_flush(sc, UINT64_MAX);
uint32_t msg[3] = { uint32_t msg[3] = {
@ -367,23 +369,35 @@ set_next_step_dir(struct stepcompress *sc, int sdir)
} }
// Check if the internal queue needs to be expanded, and expand if so // Check if the internal queue needs to be expanded, and expand if so
static inline void static void
check_expand(struct stepcompress *sc, int sdir, int count) _check_expand(struct stepcompress *sc, uint64_t *qn)
{ {
if (sdir != sc->sdir) sc->queue_next = qn;
set_next_step_dir(sc, sdir); if (qn - sc->queue_pos > 65535 + 2000)
if (sc->queue_next + count > sc->queue_end) // No point in keeping more than 64K steps in memory
expand_queue(sc, count); stepcompress_flush(sc, *(qn - 65535));
expand_queue(sc, 1);
}
static inline void
check_expand(struct stepcompress *sc, uint64_t **pqn, uint64_t **pqend)
{
if (likely(*pqn < *pqend))
return;
_check_expand(sc, *pqn);
*pqn = sc->queue_next;
*pqend = sc->queue_end;
} }
// Schedule a step event at the specified step_clock time // Schedule a step event at the specified step_clock time
void void
stepcompress_push(struct stepcompress *sc, double step_clock, int32_t sdir) stepcompress_push(struct stepcompress *sc, double step_clock, int32_t sdir)
{ {
sdir = !!sdir; set_next_step_dir(sc, !!sdir);
check_expand(sc, sdir, 1);
step_clock += 0.5; step_clock += 0.5;
*sc->queue_next++ = step_clock; uint64_t *qn = sc->queue_next, *qend = sc->queue_end;
check_expand(sc, &qn, &qend);
*qn++ = step_clock;
sc->queue_next = qn;
} }
// Schedule 'steps' number of steps with a constant time between steps // Schedule 'steps' number of steps with a constant time between steps
@ -407,18 +421,20 @@ stepcompress_push_factor(struct stepcompress *sc
, sc->oid, steps, step_offset, clock_offset, factor); , sc->oid, steps, step_offset, clock_offset, factor);
return 0; return 0;
} }
check_expand(sc, sdir, count); set_next_step_dir(sc, sdir);
int res = sdir ? count : -count;
// Calculate each step time // Calculate each step time
uint64_t *qn = sc->queue_next, *end = &qn[count];
clock_offset += 0.5; clock_offset += 0.5;
double pos = step_offset + .5; double pos = step_offset + .5;
while (qn < end) { uint64_t *qn = sc->queue_next, *qend = sc->queue_end;
while (count--) {
check_expand(sc, &qn, &qend);
*qn++ = clock_offset + pos*factor; *qn++ = clock_offset + pos*factor;
pos += 1.0; pos += 1.0;
} }
sc->queue_next = qn; sc->queue_next = qn;
return sdir ? count : -count; return res;
} }
// Schedule 'steps' number of steps using the formula: // Schedule 'steps' number of steps using the formula:
@ -442,19 +458,21 @@ stepcompress_push_sqrt(struct stepcompress *sc, double steps, double step_offset
, factor); , factor);
return 0; return 0;
} }
check_expand(sc, sdir, count); set_next_step_dir(sc, sdir);
int res = sdir ? count : -count;
// Calculate each step time // Calculate each step time
uint64_t *qn = sc->queue_next, *end = &qn[count];
clock_offset += 0.5; clock_offset += 0.5;
double pos = step_offset + .5 + sqrt_offset/factor; double pos = step_offset + .5 + sqrt_offset/factor;
while (qn < end) { uint64_t *qn = sc->queue_next, *qend = sc->queue_end;
while (count--) {
check_expand(sc, &qn, &qend);
double v = safe_sqrt(pos*factor); double v = safe_sqrt(pos*factor);
*qn++ = clock_offset + (factor >= 0. ? v : -v); *qn++ = clock_offset + (factor >= 0. ? v : -v);
pos += 1.0; pos += 1.0;
} }
sc->queue_next = qn; sc->queue_next = qn;
return sdir ? count : -count; return res;
} }
// Schedule 'count' number of steps using the delta kinematic const speed // Schedule 'count' number of steps using the delta kinematic const speed
@ -476,16 +494,18 @@ stepcompress_push_delta_const(
, closest_height2, height, movez_r, inv_velocity); , closest_height2, height, movez_r, inv_velocity);
return 0; return 0;
} }
check_expand(sc, step_dist > 0., count); set_next_step_dir(sc, step_dist > 0.);
int res = step_dist > 0. ? count : -count;
// Calculate each step time // Calculate each step time
uint64_t *qn = sc->queue_next, *end = &qn[count];
clock_offset += 0.5; clock_offset += 0.5;
start_pos += movexy_r*closestxy_d; start_pos += movexy_r*closestxy_d;
height += .5 * step_dist; height += .5 * step_dist;
uint64_t *qn = sc->queue_next, *qend = sc->queue_end;
if (!movez_r) { if (!movez_r) {
// Optmized case for common XY only moves (no Z movement) // Optmized case for common XY only moves (no Z movement)
while (qn < end) { while (count--) {
check_expand(sc, &qn, &qend);
double v = safe_sqrt(closest_height2 - height*height); double v = safe_sqrt(closest_height2 - height*height);
double pos = start_pos + (step_dist > 0. ? -v : v); double pos = start_pos + (step_dist > 0. ? -v : v);
*qn++ = clock_offset + pos * inv_velocity; *qn++ = clock_offset + pos * inv_velocity;
@ -494,14 +514,16 @@ stepcompress_push_delta_const(
} else if (!movexy_r) { } else if (!movexy_r) {
// Optmized case for Z only moves // Optmized case for Z only moves
double v = (step_dist > 0. ? -end_height : end_height); double v = (step_dist > 0. ? -end_height : end_height);
while (qn < end) { while (count--) {
check_expand(sc, &qn, &qend);
double pos = start_pos + movez_r*height + v; double pos = start_pos + movez_r*height + v;
*qn++ = clock_offset + pos * inv_velocity; *qn++ = clock_offset + pos * inv_velocity;
height += step_dist; height += step_dist;
} }
} else { } else {
// General case (handles XY+Z moves) // General case (handles XY+Z moves)
while (qn < end) { while (count--) {
check_expand(sc, &qn, &qend);
double relheight = movexy_r*height - movez_r*closestxy_d; double relheight = movexy_r*height - movez_r*closestxy_d;
double v = safe_sqrt(closest_height2 - relheight*relheight); double v = safe_sqrt(closest_height2 - relheight*relheight);
double pos = start_pos + movez_r*height + (step_dist > 0. ? -v : v); double pos = start_pos + movez_r*height + (step_dist > 0. ? -v : v);
@ -510,7 +532,7 @@ stepcompress_push_delta_const(
} }
} }
sc->queue_next = qn; sc->queue_next = qn;
return step_dist > 0. ? count : -count; return res;
} }
// Schedule 'count' number of steps using delta kinematic acceleration // Schedule 'count' number of steps using delta kinematic acceleration
@ -532,14 +554,16 @@ stepcompress_push_delta_accel(
, closest_height2, height, movez_r, accel_multiplier); , closest_height2, height, movez_r, accel_multiplier);
return 0; return 0;
} }
check_expand(sc, step_dist > 0., count); set_next_step_dir(sc, step_dist > 0.);
int res = step_dist > 0. ? count : -count;
// Calculate each step time // Calculate each step time
uint64_t *qn = sc->queue_next, *end = &qn[count];
clock_offset += 0.5; clock_offset += 0.5;
start_pos += movexy_r*closestxy_d; start_pos += movexy_r*closestxy_d;
height += .5 * step_dist; height += .5 * step_dist;
while (qn < end) { uint64_t *qn = sc->queue_next, *qend = sc->queue_end;
while (count--) {
check_expand(sc, &qn, &qend);
double relheight = movexy_r*height - movez_r*closestxy_d; double relheight = movexy_r*height - movez_r*closestxy_d;
double v = safe_sqrt(closest_height2 - relheight*relheight); double v = safe_sqrt(closest_height2 - relheight*relheight);
double pos = start_pos + movez_r*height + (step_dist > 0. ? -v : v); double pos = start_pos + movez_r*height + (step_dist > 0. ? -v : v);
@ -548,7 +572,7 @@ stepcompress_push_delta_accel(
height += step_dist; height += step_dist;
} }
sc->queue_next = qn; sc->queue_next = qn;
return step_dist > 0. ? count : -count; return res;
} }
// Reset the internal state of the stepcompress object // Reset the internal state of the stepcompress object