Adaptive screen updates for all kinds of displays

The target here is to update the screens of graphical and char base
displays as fast as possible, without draining the planner buffer too much.

For that measure the time it takes to draw and transfer one
(partial) screen to the display. Build a max. value from that.
Because ther can be large differences, depending on how much the display
updates are interrupted, the max value is decreased by one ms/s. This way
it can shrink again.
On the other side we keep track on how much time it takes to empty the
planner buffer.
Now we draw the next (partial) display update only then, when we do not
drain the planner buffer to much. We draw only when the time in the
buffer is two times larger than a update takes, or the buffer is empty anyway.

When we have begun to draw a screen we do not wait until the next 100ms
time slot comes. We draw the next partial screen as fast as possible, but
give the system a chance to refill the buffers a bit.

When we see, during drawing a screen, the screen contend has changed,
we stop the current draw and begin to draw the new content from the top.
This commit is contained in:
AnHardt
2016-12-12 14:35:02 +01:00
parent 0772c8e55f
commit d0e24e0876
23 changed files with 98 additions and 644 deletions

View File

@ -145,7 +145,7 @@ float Planner::previous_speed[NUM_AXIS],
Planner::position_float[NUM_AXIS] = { 0 };
#endif
#if ENABLED(ENSURE_SMOOTH_MOVES)
#if ENABLED(ULTRA_LCD)
volatile uint32_t Planner::block_buffer_runtime_us = 0;
#endif
@ -985,30 +985,21 @@ void Planner::_buffer_line(const float &a, const float &b, const float &c, const
const uint8_t moves_queued = movesplanned();
// Slow down when the buffer starts to empty, rather than wait at the corner for a buffer refill
unsigned long segment_time = lround(1000000.0 / inverse_mm_s);
#if ENABLED(SLOWDOWN)
// Segment time im micro seconds
unsigned long segment_time = lround(1000000.0 / inverse_mm_s);
if (moves_queued > 1 && moves_queued < (BLOCK_BUFFER_SIZE) / 2) {
if (segment_time < min_segment_time) {
// buffer is draining, add extra time. The amount of time added increases if the buffer is still emptied more.
inverse_mm_s = 1000000.0 / (segment_time + lround(2 * (min_segment_time - segment_time) / moves_queued));
#if defined(XY_FREQUENCY_LIMIT) || ENABLED(ENSURE_SMOOTH_MOVES)
#if defined(XY_FREQUENCY_LIMIT) || ENABLED(ULTRA_LCD)
segment_time = lround(1000000.0 / inverse_mm_s);
#endif
}
}
#endif
#if ENABLED(ENSURE_SMOOTH_MOVES)
#if DISABLED(SLOWDOWN)
unsigned long segment_time = lround(1000000.0 / inverse_mm_s);
#endif
if (segment_time < (MIN_BLOCK_TIME) * 1000UL) {
// buffer will be draining, set to MIN_BLOCK_TIME.
inverse_mm_s = 1000000.0 / (1000.0 * (MIN_BLOCK_TIME));
segment_time = (MIN_BLOCK_TIME) * 1000UL;
}
block->segment_time = segment_time;
#if ENABLED(ULTRA_LCD)
CRITICAL_SECTION_START
block_buffer_runtime_us += segment_time;
CRITICAL_SECTION_END