yarf 0.1
Yet Another RepRap Firmware
|
00001 /* 00002 * block_handler.c 00003 * 00004 * Copyright 2011 Pieter Agten 00005 * 00006 * This file is part of Yarf. 00007 * 00008 * Yarf is free software: you can redistribute it and/or modify 00009 * it under the terms of the GNU General Public License as published by 00010 * the Free Software Foundation, either version 3 of the License, or 00011 * (at your option) any later version. 00012 * 00013 * Yarf is distributed in the hope that it will be useful, 00014 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00015 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00016 * GNU General Public License for more details. 00017 * 00018 * You should have received a copy of the GNU General Public License 00019 * along with Yarf. If not, see <http://www.gnu.org/licenses/>. 00020 */ 00021 00030 #include "block_handler.h" 00031 00032 #include "yarf.h" 00033 #include "movement/planner_queue.h" 00034 #include "hardware/steppers.h" 00035 #include "hardware/endstops.h" 00036 #include "hardware/usart.h" 00037 #include "scheduling/realtime_timer.h" 00038 #include "util/math.h" 00039 #include "advance.h" 00040 00041 #include <stdlib.h> 00042 #include <util/delay.h> 00043 #include <util/atomic.h> 00044 00049 #define BLOCK_HANDLER_START_DELAY_TICKS 1L 00050 00054 static bool handler_running; 00055 00061 static realtime_task_t handler_task; 00062 00063 00067 static block_t *b; 00068 00069 00074 static steps_t counter[NUM_AXES]; 00075 00076 00077 #if ADVANCE_ALGORITHM 00078 00082 static volatile int32_t e_steps; 00083 00091 static int32_t previous_advance; 00092 00101 static uint8_t extruder_tick_state; 00102 #endif 00103 00108 static void 00109 block_progress_init(void) 00110 { 00111 int axis; 00112 for(axis = 0; axis < NUM_AXES; ++axis) { 00113 counter[axis] = -(b->nb_steps/2); 00114 } 00115 } 00116 00122 static inline void 00123 enable_steppers(void) 00124 { 00125 if (b->steps[X_AXIS] != 0) { 00126 stepper_enable_x(); 00127 } 00128 if (b->steps[Y_AXIS] != 0) { 00129 stepper_enable_y(); 00130 } 00131 if (b->steps[Z_AXIS] != 0) { 00132 stepper_enable_z(); 00133 } 00134 if (b->steps[E_AXIS] != 0) { 00135 stepper_enable_e(); 00136 } 00137 } 00138 00143 static inline void 00144 disable_steppers(void) 00145 { 00146 #if !STEPPER_HOLD_X 00147 stepper_disable_x(); 00148 #endif 00149 #if !STEPPER_HOLD_Y 00150 stepper_disable_y(); 00151 #endif 00152 #if !STEPPER_HOLD_Z 00153 stepper_disable_z(); 00154 #endif 00155 #if !STEPPER_HOLD_E && !ADVANCE_ALGORITHM 00156 stepper_disable_e(); 00157 #endif 00158 } 00159 00163 static inline void 00164 block_finished(void) 00165 { 00166 b = NULL; 00167 00168 /* Remove the block from the tail of the queue */ 00169 plan_q_discard_tail(); 00170 00171 /* Disable the stepper motors that need not be held */ 00172 disable_steppers(); 00173 } 00174 00178 static inline void 00179 cancel_block(void) 00180 { 00181 block_finished(); 00182 rttimer_schedule_ticks(&handler_task,1); 00183 } 00184 00185 00186 #if ADVANCE_ALGORITHM 00187 //TODO: enable/disable interrupt 00188 00197 static inline void 00198 block_handler_extruder_tick(void) 00199 { 00200 /* Set the timer 1 A top value */ 00201 OCR1A += EXTRUDER_TIMER_TICKS; 00202 TIFR1 |= _BV(OCF1A); 00203 00204 /* Check the USART0 receive buffer, to prevent data overrun */ 00205 usart0_try_read_character(); 00206 00207 if (extruder_tick_state == 0) { 00208 extruder_tick_state = 1; 00209 stepper_e_step_low(); 00210 } else { 00211 extruder_tick_state = 0; 00212 if (e_steps == 0) { 00213 return; 00214 } 00215 00216 if (e_steps < 0) { 00217 stepper_e_dir_neg(); 00218 e_steps += 1; 00219 } else if (e_steps > 0) { 00220 stepper_e_dir_pos(); 00221 e_steps -= 1; 00222 } 00223 stepper_e_step_high(); 00224 } 00225 } 00226 00231 ISR(TIMER1_COMPA_vect, ISR_BLOCK) 00232 { 00233 block_handler_extruder_tick(); 00234 } 00235 00236 #endif 00237 00238 00243 static inline void 00244 update_advance(void) 00245 { 00246 #if ADVANCE_ALGORITHM 00247 b->advance = advance_get_value(b); 00248 #endif 00249 } 00250 00268 static void 00269 block_handler_run(void) 00270 { 00271 if (b == NULL) { 00272 /* Get new block to execute from the planning queue */ 00273 b = plan_q_tail(); 00274 if (b == NULL) { 00275 /* No blocks to be executed */ 00276 handler_running = false; 00277 return; 00278 } else { 00279 block_progress_init(); 00280 enable_steppers(); 00281 } 00282 } 00283 00284 00285 /* Make sure all the stepper inputs are low */ 00286 stepper_x_step_low(); 00287 stepper_y_step_low(); 00288 stepper_z_step_low(); 00289 #if !ADVANCE_ALGORITHM 00290 stepper_e_step_low(); 00291 #endif 00292 00293 00294 /* Setup the steppers' direction pins and check the endstops */ 00295 uint8_t collisions = 0; 00296 if (b->steps[X_AXIS] < 0) { 00297 stepper_x_dir_neg(); 00298 if (endstop_x_min()) { 00299 collisions |= _BV(X_AXIS_NEG); 00300 } 00301 } else if (b->steps[X_AXIS] > 0) { 00302 stepper_x_dir_pos(); 00303 if (endstop_x_max()) { 00304 collisions |= _BV(X_AXIS_POS); 00305 } 00306 } 00307 if (b->steps[Y_AXIS] < 0) { 00308 stepper_y_dir_neg(); 00309 if (endstop_y_min()) { 00310 collisions |= _BV(Y_AXIS_NEG); 00311 } 00312 } else if (b->steps[Y_AXIS] > 0) { 00313 stepper_y_dir_pos(); 00314 if (endstop_y_max()) { 00315 collisions |= _BV(Y_AXIS_POS); 00316 } 00317 } 00318 if (b->steps[Z_AXIS] < 0) { 00319 stepper_z_dir_neg(); 00320 if (endstop_z_min()) { 00321 collisions |= _BV(Z_AXIS_NEG); 00322 } 00323 } else if (b->steps[Z_AXIS] > 0) { 00324 stepper_z_dir_pos(); 00325 if (endstop_z_max()) { 00326 collisions |= _BV(Z_AXIS_POS); 00327 } 00328 } 00329 #if !ADVANCE_ALGORITHM 00330 if (b->steps[E_AXIS] < 0) { 00331 stepper_e_dir_neg(); 00332 } else { 00333 stepper_e_dir_pos(); 00334 } 00335 #endif 00336 00337 if (collisions) { 00338 b->collision_handler(collisions); 00339 cancel_block(); 00340 return; 00341 } 00342 00343 /* Step all the steppers that need to step */ 00344 counter[X_AXIS] += labs(b->steps[X_AXIS]); 00345 if (counter[X_AXIS] > 0) { 00346 counter[X_AXIS] -= b->nb_steps; 00347 stepper_x_step_high(); 00348 } 00349 counter[Y_AXIS] += labs(b->steps[Y_AXIS]); 00350 if (counter[Y_AXIS] > 0) { 00351 counter[Y_AXIS] -= b->nb_steps; 00352 stepper_y_step_high(); 00353 } 00354 counter[Z_AXIS] += labs(b->steps[Z_AXIS]); 00355 if (counter[Z_AXIS] > 0) { 00356 counter[Z_AXIS] -= b->nb_steps; 00357 stepper_z_step_high(); 00358 } 00359 #if !ADVANCE_ALGORITHM 00360 counter[E_AXIS] += labs(b->steps[E_AXIS]); 00361 if (counter[E_AXIS] > 0) { 00362 counter[E_AXIS] -= b->nb_steps; 00363 stepper_e_step_high(); 00364 } 00365 #else 00366 /* Calculate E steps to take */ 00367 counter[E_AXIS] += labs(b->steps[E_AXIS]); 00368 if (counter[E_AXIS] > 0) { 00369 counter[E_AXIS] -= b->nb_steps; 00370 if (b->steps[E_AXIS] < 0) { 00371 e_steps -= 1; 00372 } else { 00373 e_steps += 1; 00374 } 00375 } 00376 /* Do advance steps */ 00377 e_steps += (b->advance - previous_advance); 00378 previous_advance = b->advance; 00379 block_handler_extruder_tick(); 00380 #endif 00381 00382 00383 00384 /* Reschedule the timer */ 00385 b->nb_steps_completed += 1; 00386 fxp16u16_t diff = fxp16u16_div_uint16(2*b->timer_ticks, b->acceleration_step); 00387 if (b->nb_steps_completed < b->acceleration_end) { 00388 /* We're in the acceleration slope */ 00389 if (b->timer_ticks - b->plateau_timer_ticks > diff) { // overflow detection 00390 b->timer_ticks -= diff; 00391 } else { 00392 b->timer_ticks = b->plateau_timer_ticks; 00393 } 00394 00395 b->acceleration_step += 4; 00396 update_advance(); 00397 } else if (b->nb_steps_completed >= b->deceleration_start) { 00398 /* We're in the deceleration slope */ 00399 if (b->timer_ticks < b->exit_timer_ticks && 00400 b->exit_timer_ticks - b->timer_ticks > diff) { // overflow detection 00401 b->timer_ticks += diff; 00402 } else { 00403 b->timer_ticks = b->exit_timer_ticks; 00404 } 00405 00406 if (b->acceleration_step > 4) { 00407 b->acceleration_step -= 4; 00408 } else { 00409 b->acceleration_step = 1; 00410 } 00411 update_advance(); 00412 } else { 00413 b->timer_ticks = b->plateau_timer_ticks; 00414 } 00415 rttimer_schedule_ticks(&handler_task, fxp16u16_to_uint16(b->timer_ticks)); 00416 00417 00418 /* Check if we're done with this block */ 00419 if (b->nb_steps_completed >= b->nb_steps) { 00420 block_finished(); 00421 } 00422 } 00423 00424 00425 00426 void 00427 block_handler_init(void) 00428 { 00429 rttimer_init(); 00430 00431 b = NULL; 00432 handler_running = false; 00433 handler_task.f = block_handler_run; 00434 00435 #if ADVANCE_ALGORITHM 00436 e_steps = 0; 00437 previous_advance = 0; 00438 extruder_tick_state = 0; 00439 #endif 00440 } 00441 00442 void 00443 block_handler_start(void) 00444 { 00445 if (! handler_running) { 00446 handler_running = true; 00447 rttimer_schedule_ticks(&handler_task, BLOCK_HANDLER_START_DELAY_TICKS); 00448 } 00449 } 00450 00451 void 00452 block_handler_pause(void) 00453 { 00454 ATOMIC_BLOCK(ATOMIC_RESTORESTATE) { 00455 if (handler_running) { 00456 rttimer_cancel(); 00457 handler_running = false; 00458 } 00459 } 00460 } 00461 00462 void 00463 block_handler_stop(void) 00464 { 00465 ATOMIC_BLOCK(ATOMIC_RESTORESTATE) { 00466 if (handler_running) { 00467 rttimer_cancel(); 00468 if (b != NULL) { 00469 block_finished(); 00470 } 00471 handler_running = false; 00472 } 00473 } 00474 } 00475 00476 bool 00477 block_handler_running(void) 00478 { 00479 return handler_running; 00480 }