First draft of Unified Stepper / E Advance ISR

This commit is contained in:
Sebastianv650
2016-12-12 20:30:02 +01:00
committed by Scott Lahteine
parent 451ba5df01
commit 84c685f8b5
20 changed files with 104 additions and 201 deletions

View File

@ -91,8 +91,9 @@ volatile uint32_t Stepper::step_events_completed = 0; // The number of step even
#if ENABLED(ADVANCE) || ENABLED(LIN_ADVANCE)
uint8_t Stepper::old_OCR0A = 0;
volatile uint8_t Stepper::eISR_Rate = 200; // Keep the ISR at a low rate until needed
uint16_t Stepper::nextMainISR = 0,
Stepper::nextAdvanceISR = 65535,
Stepper::eISR_Rate = 65535;
#if ENABLED(LIN_ADVANCE)
volatile int Stepper::e_steps[E_STEPPERS];
@ -328,16 +329,23 @@ void Stepper::set_directions() {
* 2000 1 KHz - sleep rate
* 4000 500 Hz - init rate
*/
ISR(TIMER1_COMPA_vect) { Stepper::isr(); }
ISR(TIMER1_COMPA_vect) {
#if ENABLED(ADVANCE) || ENABLED(LIN_ADVANCE)
Stepper::advance_isr_scheduler();
#else
Stepper::isr();
#endif
}
void Stepper::isr() {
//Disable Timer0 ISRs and enable global ISR again to capture UART events (incoming chars)
#if ENABLED(ADVANCE) || ENABLED(LIN_ADVANCE)
CBI(TIMSK0, OCIE0A); //estepper ISR
#define _ENABLE_ISRs() cli(); SBI(TIMSK0, OCIE0B); ENABLE_STEPPER_DRIVER_INTERRUPT()
#if DISABLED(ADVANCE) && DISABLED(LIN_ADVANCE)
//Disable Timer0 ISRs and enable global ISR again to capture UART events (incoming chars)
CBI(TIMSK0, OCIE0B); //Temperature ISR
DISABLE_STEPPER_DRIVER_INTERRUPT();
sei();
#endif
CBI(TIMSK0, OCIE0B); //Temperature ISR
DISABLE_STEPPER_DRIVER_INTERRUPT();
sei();
if (cleaning_buffer_counter) {
--cleaning_buffer_counter;
@ -346,13 +354,8 @@ void Stepper::isr() {
#ifdef SD_FINISHED_RELEASECOMMAND
if (!cleaning_buffer_counter && (SD_FINISHED_STEPPERRELEASE)) enqueue_and_echo_commands_P(PSTR(SD_FINISHED_RELEASECOMMAND));
#endif
OCR1A = 200; // Run at max speed - 10 KHz
//re-enable ISRs
#if ENABLED(ADVANCE) || ENABLED(LIN_ADVANCE)
SBI(TIMSK0, OCIE0A);
#endif
SBI(TIMSK0, OCIE0B);
ENABLE_STEPPER_DRIVER_INTERRUPT();
_NEXT_ISR(200); // Run at max speed - 10 KHz
_ENABLE_ISRs(); // re-enable ISRs
return;
}
@ -381,12 +384,8 @@ void Stepper::isr() {
#if ENABLED(Z_LATE_ENABLE)
if (current_block->steps[Z_AXIS] > 0) {
enable_z();
OCR1A = 2000; // Run at slow speed - 1 KHz
#if ENABLED(ADVANCE) || ENABLED(LIN_ADVANCE)
SBI(TIMSK0, OCIE0A);
#endif
SBI(TIMSK0, OCIE0B);
ENABLE_STEPPER_DRIVER_INTERRUPT();
_NEXT_ISR(2000); // Run at slow speed - 1 KHz
_ENABLE_ISRs(); // re-enable ISRs
return;
}
#endif
@ -396,12 +395,8 @@ void Stepper::isr() {
// #endif
}
else {
OCR1A = 2000; // Run at slow speed - 1 KHz
#if ENABLED(ADVANCE) || ENABLED(LIN_ADVANCE)
SBI(TIMSK0, OCIE0A);
#endif
SBI(TIMSK0, OCIE0B);
ENABLE_STEPPER_DRIVER_INTERRUPT();
_NEXT_ISR(2000); // Run at slow speed - 1 KHz
_ENABLE_ISRs(); // re-enable ISRs
return;
}
}
@ -586,7 +581,7 @@ void Stepper::isr() {
#if ENABLED(ADVANCE) || ENABLED(LIN_ADVANCE)
// If we have esteps to execute, fire the next advance_isr "now"
if (e_steps[TOOL_E_INDEX]) OCR0A = TCNT0 + 2;
if (e_steps[TOOL_E_INDEX]) nextAdvanceISR = 0;
#endif
// Calculate new timer value
@ -600,7 +595,7 @@ void Stepper::isr() {
// step_rate to timer interval
uint16_t timer = calc_timer(acc_step_rate);
OCR1A = timer;
_NEXT_ISR(timer);
acceleration_time += timer;
#if ENABLED(LIN_ADVANCE)
@ -637,7 +632,7 @@ void Stepper::isr() {
#endif // ADVANCE or LIN_ADVANCE
#if ENABLED(ADVANCE) || ENABLED(LIN_ADVANCE)
eISR_Rate = (timer >> 3) * step_loops / abs(e_steps[TOOL_E_INDEX]); //>> 3 is divide by 8. Reason: Timer 1 runs at 16/8=2MHz, Timer 0 at 16/64=0.25MHz. ==> 2/0.25=8.
eISR_Rate = !e_steps[TOOL_E_INDEX] ? 65535 : timer * step_loops / abs(e_steps[TOOL_E_INDEX]);
#endif
}
else if (step_events_completed > (uint32_t)current_block->decelerate_after) {
@ -653,7 +648,7 @@ void Stepper::isr() {
// step_rate to timer interval
uint16_t timer = calc_timer(step_rate);
OCR1A = timer;
_NEXT_ISR(timer);
deceleration_time += timer;
#if ENABLED(LIN_ADVANCE)
@ -688,7 +683,7 @@ void Stepper::isr() {
#endif // ADVANCE or LIN_ADVANCE
#if ENABLED(ADVANCE) || ENABLED(LIN_ADVANCE)
eISR_Rate = (timer >> 3) * step_loops / abs(e_steps[TOOL_E_INDEX]);
eISR_Rate = !e_steps[TOOL_E_INDEX] ? 65535 : timer * step_loops / abs(e_steps[TOOL_E_INDEX]);
#endif
}
else {
@ -698,40 +693,37 @@ void Stepper::isr() {
if (current_block->use_advance_lead)
current_estep_rate[TOOL_E_INDEX] = final_estep_rate;
eISR_Rate = (OCR1A_nominal >> 3) * step_loops_nominal / abs(e_steps[TOOL_E_INDEX]);
eISR_Rate = !e_steps[TOOL_E_INDEX] ? 65535 : OCR1A_nominal * step_loops_nominal / abs(e_steps[TOOL_E_INDEX]);
#endif
OCR1A = OCR1A_nominal;
_NEXT_ISR(OCR1A_nominal);
// ensure we're running at the correct step rate, even if we just came off an acceleration
step_loops = step_loops_nominal;
}
NOLESS(OCR1A, TCNT1 + 16);
#if DISABLED(ADVANCE) && DISABLED(LIN_ADVANCE)
NOLESS(OCR1A, TCNT1 + 16);
#endif
// If current block is finished, reset pointer
if (all_steps_done) {
current_block = NULL;
planner.discard_current_block();
}
#if ENABLED(ADVANCE) || ENABLED(LIN_ADVANCE)
SBI(TIMSK0, OCIE0A);
#if DISABLED(ADVANCE) && DISABLED(LIN_ADVANCE)
_ENABLE_ISRs(); // re-enable ISRs
#endif
SBI(TIMSK0, OCIE0B);
ENABLE_STEPPER_DRIVER_INTERRUPT();
}
#if ENABLED(ADVANCE) || ENABLED(LIN_ADVANCE)
// Timer interrupt for E. e_steps is set in the main routine;
// Timer 0 is shared with millies
ISR(TIMER0_COMPA_vect) { Stepper::advance_isr(); }
void Stepper::advance_isr() {
old_OCR0A += eISR_Rate;
OCR0A = old_OCR0A;
nextAdvanceISR = eISR_Rate;
#define SET_E_STEP_DIR(INDEX) \
if (e_steps[INDEX]) E## INDEX ##_DIR_WRITE(e_steps[INDEX] < 0 ? INVERT_E## INDEX ##_DIR : !INVERT_E## INDEX ##_DIR)
@ -795,6 +787,46 @@ void Stepper::isr() {
}
void Stepper::advance_isr_scheduler() {
// Disable Timer0 ISRs and enable global ISR again to capture UART events (incoming chars)
CBI(TIMSK0, OCIE0B); // Temperature ISR
DISABLE_STEPPER_DRIVER_INTERRUPT();
sei();
// Run main stepping ISR if flagged
if (!nextMainISR) isr();
// Run Advance stepping ISR if flagged
if (!nextAdvanceISR) advance_isr();
// Is the next advance ISR scheduled before the next main ISR?
if (nextAdvanceISR <= nextMainISR) {
// Set up the next interrupt
OCR1A = nextAdvanceISR;
// New interval for the next main ISR
if (nextMainISR) nextMainISR -= nextAdvanceISR;
// Will call Stepper::advance_isr on the next interrupt
nextAdvanceISR = 0;
}
else {
// The next main ISR comes first
OCR1A = nextMainISR;
// New interval for the next advance ISR, if any
if (nextAdvanceISR && nextAdvanceISR != 65535)
nextAdvanceISR -= nextMainISR;
// Will call Stepper::isr on the next interrupt
nextMainISR = 0;
}
// Don't run the ISR faster than possible
NOLESS(OCR1A, TCNT1 + 16);
// Restore original ISR settings
cli();
SBI(TIMSK0, OCIE0B);
ENABLE_STEPPER_DRIVER_INTERRUPT();
}
#endif // ADVANCE or LIN_ADVANCE
void Stepper::init() {
@ -981,12 +1013,6 @@ void Stepper::init() {
#endif
}
#if defined(TCCR0A) && defined(WGM01)
CBI(TCCR0A, WGM01);
CBI(TCCR0A, WGM00);
#endif
SBI(TIMSK0, OCIE0A);
#endif // ADVANCE or LIN_ADVANCE
endstops.enable(true); // Start with endstops active. After homing they can be disabled