|
@@ -88,6 +88,26 @@ int8_t SilentMode;
|
|
volatile long count_position[NUM_AXIS] = { 0, 0, 0, 0};
|
|
volatile long count_position[NUM_AXIS] = { 0, 0, 0, 0};
|
|
volatile signed char count_direction[NUM_AXIS] = { 1, 1, 1, 1};
|
|
volatile signed char count_direction[NUM_AXIS] = { 1, 1, 1, 1};
|
|
|
|
|
|
|
|
+#ifdef LIN_ADVANCE
|
|
|
|
+
|
|
|
|
+ uint16_t ADV_NEVER = 65535;
|
|
|
|
+
|
|
|
|
+ static uint16_t nextMainISR = 0;
|
|
|
|
+ static uint16_t nextAdvanceISR = ADV_NEVER;
|
|
|
|
+ static uint16_t eISR_Rate = ADV_NEVER;
|
|
|
|
+
|
|
|
|
+ static volatile int e_steps; //Extrusion steps to be executed by the stepper
|
|
|
|
+ static int final_estep_rate; //Speed of extruder at cruising speed
|
|
|
|
+ static int current_estep_rate; //The current speed of the extruder
|
|
|
|
+ static int current_adv_steps; //The current pretension of filament expressed in steps
|
|
|
|
+
|
|
|
|
+ #define ADV_RATE(T, L) (e_steps ? (T) * (L) / abs(e_steps) : ADV_NEVER)
|
|
|
|
+ #define _NEXT_ISR(T) nextMainISR = T
|
|
|
|
+
|
|
|
|
+#else
|
|
|
|
+ #define _NEXT_ISR(T) OCR1A = T
|
|
|
|
+#endif
|
|
|
|
+
|
|
//===========================================================================
|
|
//===========================================================================
|
|
//=============================functions ============================
|
|
//=============================functions ============================
|
|
//===========================================================================
|
|
//===========================================================================
|
|
@@ -308,24 +328,27 @@ FORCE_INLINE void trapezoid_generator_reset() {
|
|
step_loops_nominal = step_loops;
|
|
step_loops_nominal = step_loops;
|
|
acc_step_rate = current_block->initial_rate;
|
|
acc_step_rate = current_block->initial_rate;
|
|
acceleration_time = calc_timer(acc_step_rate);
|
|
acceleration_time = calc_timer(acc_step_rate);
|
|
- OCR1A = acceleration_time;
|
|
|
|
-
|
|
|
|
-// SERIAL_ECHO_START;
|
|
|
|
-// SERIAL_ECHOPGM("advance :");
|
|
|
|
-// SERIAL_ECHO(current_block->advance/256.0);
|
|
|
|
-// SERIAL_ECHOPGM("advance rate :");
|
|
|
|
-// SERIAL_ECHO(current_block->advance_rate/256.0);
|
|
|
|
-// SERIAL_ECHOPGM("initial advance :");
|
|
|
|
-// SERIAL_ECHO(current_block->initial_advance/256.0);
|
|
|
|
-// SERIAL_ECHOPGM("final advance :");
|
|
|
|
-// SERIAL_ECHOLN(current_block->final_advance/256.0);
|
|
|
|
-
|
|
|
|
|
|
+ _NEXT_ISR(acceleration_time);
|
|
|
|
+
|
|
|
|
+ #ifdef LIN_ADVANCE
|
|
|
|
+ if (current_block->use_advance_lead) {
|
|
|
|
+ current_estep_rate = ((unsigned long)acc_step_rate * current_block->abs_adv_steps_multiplier8) >> 17;
|
|
|
|
+ final_estep_rate = (current_block->nominal_rate * current_block->abs_adv_steps_multiplier8) >> 17;
|
|
|
|
+ }
|
|
|
|
+ #endif
|
|
}
|
|
}
|
|
|
|
|
|
// "The Stepper Driver Interrupt" - This timer interrupt is the workhorse.
|
|
// "The Stepper Driver Interrupt" - This timer interrupt is the workhorse.
|
|
// It pops blocks from the block_buffer and executes them by pulsing the stepper pins appropriately.
|
|
// It pops blocks from the block_buffer and executes them by pulsing the stepper pins appropriately.
|
|
-ISR(TIMER1_COMPA_vect)
|
|
|
|
-{
|
|
|
|
|
|
+ISR(TIMER1_COMPA_vect) {
|
|
|
|
+ #ifdef LIN_ADVANCE
|
|
|
|
+ advance_isr_scheduler();
|
|
|
|
+ #else
|
|
|
|
+ isr();
|
|
|
|
+ #endif
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+void isr() {
|
|
// If there is no current block, attempt to pop one from the buffer
|
|
// If there is no current block, attempt to pop one from the buffer
|
|
if (current_block == NULL) {
|
|
if (current_block == NULL) {
|
|
// Anything in the buffer?
|
|
// Anything in the buffer?
|
|
@@ -343,13 +366,13 @@ ISR(TIMER1_COMPA_vect)
|
|
#ifdef Z_LATE_ENABLE
|
|
#ifdef Z_LATE_ENABLE
|
|
if(current_block->steps_z > 0) {
|
|
if(current_block->steps_z > 0) {
|
|
enable_z();
|
|
enable_z();
|
|
- OCR1A = 2000; //1ms wait
|
|
|
|
|
|
+ _NEXT_ISR(2000); //1ms wait
|
|
return;
|
|
return;
|
|
}
|
|
}
|
|
#endif
|
|
#endif
|
|
}
|
|
}
|
|
else {
|
|
else {
|
|
- OCR1A=2000; // 1kHz.
|
|
|
|
|
|
+ _NEXT_ISR(2000); // 1kHz.
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
@@ -553,6 +576,15 @@ ISR(TIMER1_COMPA_vect)
|
|
#ifndef AT90USB
|
|
#ifndef AT90USB
|
|
MSerial.checkRx(); // Check for serial chars.
|
|
MSerial.checkRx(); // Check for serial chars.
|
|
#endif
|
|
#endif
|
|
|
|
+
|
|
|
|
+ #ifdef LIN_ADVANCE
|
|
|
|
+ counter_e += current_block->steps_e;
|
|
|
|
+ if (counter_e > 0) {
|
|
|
|
+ counter_e -= current_block->step_event_count;
|
|
|
|
+ count_position[E_AXIS] += count_direction[E_AXIS];
|
|
|
|
+ ((out_bits&(1<<E_AXIS))!=0) ? --e_steps : ++e_steps;
|
|
|
|
+ }
|
|
|
|
+ #endif
|
|
|
|
|
|
counter_x += current_block->steps_x;
|
|
counter_x += current_block->steps_x;
|
|
if (counter_x > 0) {
|
|
if (counter_x > 0) {
|
|
@@ -596,6 +628,7 @@ ISR(TIMER1_COMPA_vect)
|
|
#endif
|
|
#endif
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ #ifndef LIN_ADVANCE
|
|
counter_e += current_block->steps_e;
|
|
counter_e += current_block->steps_e;
|
|
if (counter_e > 0) {
|
|
if (counter_e > 0) {
|
|
WRITE_E_STEP(!INVERT_E_STEP_PIN);
|
|
WRITE_E_STEP(!INVERT_E_STEP_PIN);
|
|
@@ -603,9 +636,21 @@ ISR(TIMER1_COMPA_vect)
|
|
count_position[E_AXIS]+=count_direction[E_AXIS];
|
|
count_position[E_AXIS]+=count_direction[E_AXIS];
|
|
WRITE_E_STEP(INVERT_E_STEP_PIN);
|
|
WRITE_E_STEP(INVERT_E_STEP_PIN);
|
|
}
|
|
}
|
|
|
|
+ #endif
|
|
step_events_completed += 1;
|
|
step_events_completed += 1;
|
|
if(step_events_completed >= current_block->step_event_count) break;
|
|
if(step_events_completed >= current_block->step_event_count) break;
|
|
}
|
|
}
|
|
|
|
+
|
|
|
|
+ #ifdef LIN_ADVANCE
|
|
|
|
+ if (current_block->use_advance_lead) {
|
|
|
|
+ const int delta_adv_steps = current_estep_rate - current_adv_steps;
|
|
|
|
+ current_adv_steps += delta_adv_steps;
|
|
|
|
+ e_steps += delta_adv_steps;
|
|
|
|
+ }
|
|
|
|
+ // If we have esteps to execute, fire the next advance_isr "now"
|
|
|
|
+ if (e_steps) nextAdvanceISR = 0;
|
|
|
|
+ #endif
|
|
|
|
+
|
|
// Calculare new timer value
|
|
// Calculare new timer value
|
|
unsigned short timer;
|
|
unsigned short timer;
|
|
unsigned short step_rate;
|
|
unsigned short step_rate;
|
|
@@ -620,8 +665,15 @@ ISR(TIMER1_COMPA_vect)
|
|
|
|
|
|
// step_rate to timer interval
|
|
// step_rate to timer interval
|
|
timer = calc_timer(acc_step_rate);
|
|
timer = calc_timer(acc_step_rate);
|
|
- OCR1A = timer;
|
|
|
|
|
|
+ _NEXT_ISR(timer);
|
|
acceleration_time += timer;
|
|
acceleration_time += timer;
|
|
|
|
+
|
|
|
|
+ #ifdef LIN_ADVANCE
|
|
|
|
+ if (current_block->use_advance_lead) {
|
|
|
|
+ current_estep_rate = ((uint32_t)acc_step_rate * current_block->abs_adv_steps_multiplier8) >> 17;
|
|
|
|
+ }
|
|
|
|
+ eISR_Rate = ADV_RATE(timer, step_loops);
|
|
|
|
+ #endif
|
|
}
|
|
}
|
|
else if (step_events_completed > (unsigned long int)current_block->decelerate_after) {
|
|
else if (step_events_completed > (unsigned long int)current_block->decelerate_after) {
|
|
MultiU24X24toH16(step_rate, deceleration_time, current_block->acceleration_rate);
|
|
MultiU24X24toH16(step_rate, deceleration_time, current_block->acceleration_rate);
|
|
@@ -639,11 +691,25 @@ ISR(TIMER1_COMPA_vect)
|
|
|
|
|
|
// step_rate to timer interval
|
|
// step_rate to timer interval
|
|
timer = calc_timer(step_rate);
|
|
timer = calc_timer(step_rate);
|
|
- OCR1A = timer;
|
|
|
|
|
|
+ _NEXT_ISR(timer);
|
|
deceleration_time += timer;
|
|
deceleration_time += timer;
|
|
|
|
+
|
|
|
|
+ #ifdef LIN_ADVANCE
|
|
|
|
+ if (current_block->use_advance_lead) {
|
|
|
|
+ current_estep_rate = ((uint32_t)step_rate * current_block->abs_adv_steps_multiplier8) >> 17;
|
|
|
|
+ }
|
|
|
|
+ eISR_Rate = ADV_RATE(timer, step_loops);
|
|
|
|
+ #endif
|
|
}
|
|
}
|
|
else {
|
|
else {
|
|
- OCR1A = OCR1A_nominal;
|
|
|
|
|
|
+ #ifdef LIN_ADVANCE
|
|
|
|
+ if (current_block->use_advance_lead)
|
|
|
|
+ current_estep_rate = final_estep_rate;
|
|
|
|
+
|
|
|
|
+ eISR_Rate = ADV_RATE(OCR1A_nominal, step_loops_nominal);
|
|
|
|
+ #endif
|
|
|
|
+
|
|
|
|
+ _NEXT_ISR(OCR1A_nominal);
|
|
// ensure we're running at the correct step rate, even if we just came off an acceleration
|
|
// ensure we're running at the correct step rate, even if we just came off an acceleration
|
|
step_loops = step_loops_nominal;
|
|
step_loops = step_loops_nominal;
|
|
}
|
|
}
|
|
@@ -656,6 +722,67 @@ ISR(TIMER1_COMPA_vect)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+#ifdef LIN_ADVANCE
|
|
|
|
+
|
|
|
|
+ // Timer interrupt for E. e_steps is set in the main routine.
|
|
|
|
+
|
|
|
|
+ void advance_isr() {
|
|
|
|
+
|
|
|
|
+ nextAdvanceISR = eISR_Rate;
|
|
|
|
+
|
|
|
|
+ #define SET_E_STEP_DIR(INDEX) \
|
|
|
|
+ if (e_steps) WRITE(E## INDEX ##_DIR_PIN, e_steps < 0 ? INVERT_E## INDEX ##_DIR : !INVERT_E## INDEX ##_DIR)
|
|
|
|
+
|
|
|
|
+ #define START_E_PULSE(INDEX) \
|
|
|
|
+ if (e_steps) WRITE(E## INDEX ##_STEP_PIN, !INVERT_E_STEP_PIN)
|
|
|
|
+
|
|
|
|
+ #define STOP_E_PULSE(INDEX) \
|
|
|
|
+ if (e_steps) { \
|
|
|
|
+ e_steps < 0 ? ++e_steps : --e_steps; \
|
|
|
|
+ WRITE(E## INDEX ##_STEP_PIN, INVERT_E_STEP_PIN); \
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ SET_E_STEP_DIR(0);
|
|
|
|
+
|
|
|
|
+ for (uint8_t i = step_loops; i--;) {
|
|
|
|
+ START_E_PULSE(0);
|
|
|
|
+
|
|
|
|
+ STOP_E_PULSE(0);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ void advance_isr_scheduler() {
|
|
|
|
+ // 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 != ADV_NEVER)
|
|
|
|
+ nextAdvanceISR -= nextMainISR;
|
|
|
|
+ // Will call Stepper::isr on the next interrupt
|
|
|
|
+ nextMainISR = 0;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // Don't run the ISR faster than possible
|
|
|
|
+ if (OCR1A < TCNT1 + 16) OCR1A = TCNT1 + 16;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+#endif // LIN_ADVANCE
|
|
|
|
+
|
|
void st_init()
|
|
void st_init()
|
|
{
|
|
{
|
|
digipot_init(); //Initialize Digipot Motor Current
|
|
digipot_init(); //Initialize Digipot Motor Current
|
|
@@ -843,6 +970,11 @@ void st_init()
|
|
OCR1A = 0x4000;
|
|
OCR1A = 0x4000;
|
|
TCNT1 = 0;
|
|
TCNT1 = 0;
|
|
ENABLE_STEPPER_DRIVER_INTERRUPT();
|
|
ENABLE_STEPPER_DRIVER_INTERRUPT();
|
|
|
|
+
|
|
|
|
+ #ifdef LIN_ADVANCE
|
|
|
|
+ e_steps = 0;
|
|
|
|
+ current_adv_steps = 0;
|
|
|
|
+ #endif
|
|
|
|
|
|
enable_endstops(true); // Start with endstops active. After homing they can be disabled
|
|
enable_endstops(true); // Start with endstops active. After homing they can be disabled
|
|
sei();
|
|
sei();
|