void enqueue(TARGET *t) { // don't call this function when the queue is full, but just in case, wait for a move to complete and free up the space for the passed target while (queue_full()) delay(WAITING_DELAY); uint8_t h = mb_head + 1; h &= (MOVEBUFFER_SIZE - 1); if (t != NULL) { dda_create(&movebuffer[h], t); } else { // it's a wait for temp movebuffer[h].waitfor_temp = 1; movebuffer[h].nullmove = 0; // set "step" timeout to maximum movebuffer[h].c = 0xFFFFFF00; } mb_head = h; // fire up in case we're not running yet if (isHwTimerEnabled(0) == 0) next_move(); }
void enqueue_home(TARGET *t, uint8_t endstop_check, uint8_t endstop_stop_cond) { // don't call this function when the queue is full, but just in case, wait for a move to complete and free up the space for the passed target while (queue_full()) delay(WAITING_DELAY); uint8_t h = mb_head + 1; h &= (MOVEBUFFER_SIZE - 1); DDA* new_movebuffer = &(movebuffer[h]); if (t != NULL) { dda_create(new_movebuffer, t); new_movebuffer->endstop_check = endstop_check; new_movebuffer->endstop_stop_cond = endstop_stop_cond; } else { // it's a wait for temp new_movebuffer->waitfor_temp = 1; new_movebuffer->nullmove = 0; } // make certain all writes to global memory // are flushed before modifying mb_head. MEMORY_BARRIER(); mb_head = h; uint8_t save_reg = SREG; cli(); CLI_SEI_BUG_MEMORY_BARRIER(); uint8_t isdead = (movebuffer[mb_tail].live == 0); MEMORY_BARRIER(); SREG = save_reg; if (isdead) { timer1_compa_deferred_enable = 0; next_move(); if (timer1_compa_deferred_enable) { uint8_t save_reg = SREG; cli(); CLI_SEI_BUG_MEMORY_BARRIER(); TIMSK1 |= MASK(OCIE1A); MEMORY_BARRIER(); SREG = save_reg; } } }
/// add a move to the movebuffer /// \note this function waits for space to be available if necessary, check queue_full() first if waiting is a problem /// This is the only function that modifies mb_head and it always called from outside an interrupt. void enqueue_home(TARGET *t, uint8_t endstop_check, uint8_t endstop_stop_cond) { // don't call this function when the queue is full, but just in case, wait for a move to complete and free up the space for the passed target while (queue_full()) delay_us(100); uint8_t h = mb_head + 1; h &= (MOVEBUFFER_SIZE - 1); DDA* new_movebuffer = &(movebuffer[h]); DDA* prev_movebuffer = (queue_empty() != 0) ? NULL : &movebuffer[mb_head]; if (t != NULL) { dda_create(new_movebuffer, t, prev_movebuffer); new_movebuffer->endstop_check = endstop_check; new_movebuffer->endstop_stop_cond = endstop_stop_cond; } else { // it's a wait for temp new_movebuffer->waitfor_temp = 1; new_movebuffer->nullmove = 0; } // make certain all writes to global memory // are flushed before modifying mb_head. MEMORY_BARRIER(); mb_head = h; uint8_t isdead; ATOMIC_START isdead = (movebuffer[mb_tail].live == 0); ATOMIC_END if (isdead) { next_move(); // Compensate for the cli() in setTimer(). sei(); } }
void enqueue_home(TARGET *t, unsigned char endstop_check, unsigned char endstop_stop_cond){ while(queue_full()){ for(int __i = 0;__i<5000;__i++); } unsigned char h = mb_head + 1; h &= (MOVEBUFFER_SIZE - 1); DDA *new_move = &movebuffer[h]; // Initialise queue entry to a known state. This also clears flags like // dda->live, dda->done and dda->wait_for_temp. new_move->allflags = 0; if (t != NULL) { new_move->endstop_check = endstop_check; new_move->endstop_stop_cond = endstop_stop_cond; } else { // it's a wait for temp new_move->waitfor_temp = 1; } dda_create(new_move, t); // make certain all writes to global memory // are flushed before modifying mb_head. mb_head = h; unsigned char isdead; isdead = (movebuffer[mb_tail].live == 0); if (isdead) { next_move(); } }