예제 #1
0
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;
		}
	}	
}
예제 #2
0
uint8_t queue_empty(){
    uint8_t save_reg = SREG;
    cli();
    CLI_SEI_BUG_MEMORY_BARRIER();

    uint8_t result = ((mb_tail == mb_head) && (movebuffer[mb_tail].live = 0))?255:0;

    MEMORY_BARRIER();
    SREG = save_reg;
    return result;
}
예제 #3
0
/// dump queue for emergency stop.
/// \todo effect on startpoint is undefined!
void queue_flush() {
	// Since the timer interrupt is disabled before this function
	// is called it is not strictly necessary to write the variables
	// inside an interrupt disabled block...
	uint8_t save_reg = SREG;
	cli();
	CLI_SEI_BUG_MEMORY_BARRIER();
	
	// flush queue
	mb_tail = mb_head;
	movebuffer[mb_head].live = 0;

	// disable timer
	setTimer(0);
	
	MEMORY_BARRIER();
	SREG = save_reg;
}
예제 #4
0
/*!	do stuff every 1/4 second

	called from clock_10ms(), do not call directly
*/
void clock_250ms() {
	#ifndef	NO_AUTO_IDLE
	if (temp_all_zero())	{
		if (steptimeout > (30 * 4)) {
			power_off();
		}
		else {
			uint8_t save_reg = SREG;
			cli();
			CLI_SEI_BUG_MEMORY_BARRIER();
			steptimeout++;
			MEMORY_BARRIER();
			SREG = save_reg;
		}
	}
	#endif

	ifclock(clock_flag_1s) {
		if (DEBUG_POSITION && (debug_flags & DEBUG_POSITION)) {
			// current position
			sersendf_P(PSTR("Pos: %ld,%ld,%ld,%ld,%lu\n"), current_position.X, current_position.Y, current_position.Z, current_position.E, current_position.F);

			// target position
			sersendf_P(PSTR("Dst: %ld,%ld,%ld,%ld,%lu\n"), movebuffer[mb_tail].endpoint.X, movebuffer[mb_tail].endpoint.Y, movebuffer[mb_tail].endpoint.Z, movebuffer[mb_tail].endpoint.E, movebuffer[mb_tail].endpoint.F);

			// Queue
			print_queue();

			// newline
			serial_writechar('\n');
		}
		// temperature
		/*		if (temp_get_target())
		temp_print();*/
	}
	#ifdef	TEMP_INTERCOM
	start_send();
	#endif
}
예제 #5
0
void clock_250ms() {
        debug_led_step();

        if (steptimeout > (30 * 4)) {
                power_off();
        }
        else if (heaters_all_off())	{
                uint8_t save_reg = SREG;
                cli();
                CLI_SEI_BUG_MEMORY_BARRIER();
                steptimeout++;
                MEMORY_BARRIER();
                SREG = save_reg;
        }
        
#ifdef	TEMP_INTERCOM
        start_send();
#endif

        ifclock(clock_flag_1s) {
                if (DEBUG_POSITION && (debug_flags & DEBUG_CLOCK)) sersendf_P(PSTR("1s"));
                if (DEBUG_POSITION && (debug_flags & DEBUG_POSITION)) {
                        // current position
                        sersendf_P(PSTR("Pos: %ld,%ld,%ld,%ld,%lu\n"), current_position.X, current_position.Y, current_position.Z, current_position.E, current_position.F);

                        // target position
                        sersendf_P(PSTR("Dst: %ld,%ld,%ld,%ld,%lu\n"), movebuffer[mb_tail].endpoint.X, movebuffer[mb_tail].endpoint.Y, movebuffer[mb_tail].endpoint.Z, movebuffer[mb_tail].endpoint.E, movebuffer[mb_tail].endpoint.F);

                        // Queue
                        print_queue();

                        // newline
                        serial_writechar('\n');
                }

                check_temp_achieved();
                if (DEBUG_POSITION && (debug_flags & DEBUG_CLOCK)) sersendf_P(PSTR("t"));
                
                
                ++seconds_counter;
                
                if (++idle_seconds>60)
                	working_seconds=0;
               	else
	                ++working_seconds;
                #ifdef OK_WHEN_IDLE
		if (idle_seconds>OK_WHEN_IDLE && seconds_counter-last_ok_time>OK_WHEN_IDLE)
		{
			sersendf_P(PSTR("ok (idle)\n"));
			last_ok_time=seconds_counter;
		}
		#endif 
		
		
                if (DEBUG_POSITION && (debug_flags & DEBUG_CLOCK)) sersendf_P(PSTR("r\n"));
                
                #if defined ALWAYS_CHECK_Z_MIN && defined Z_MIN_PIN
		if (z_min_pushed_flag) {
			sersendf_P(PSTR("ALERT!! PUSHING UNDERGROUND!!\n"));
			z_min_pushed_flag=0;
		}
		#endif
        }
        
}
예제 #6
0
/*! Specify how long until the step timer should fire.
	\param delay in CPU ticks

	This enables the step interrupt, but also disables interrupts globally.
	So, if you use it from inside the step interrupt, make sure to do so
	as late as possible. If you use it from outside the step interrupt,
	do a sei() after it to make the interrupt actually fire.
*/
void setTimer(uint32_t delay)
{
	uint16_t step_start = 0;
	#ifdef ACCELERATION_TEMPORAL
	uint16_t current_time;
	uint32_t earliest_time, actual_time;
	#endif /* ACCELERATION_TEMPORAL */

	// re-enable clock interrupt in case we're recovering from emergency stop
	TIMSK1 |= MASK(OCIE1B);

	// An interrupt would make all our timing calculations invalid,
	// so stop that here.
	cli();
	CLI_SEI_BUG_MEMORY_BARRIER();

	// Assume all steps belong to one move. Within one move the delay is
	// from one step to the next one, which should be more or less the same
	// as from one step interrupt to the next one. The last step interrupt happend
	// at OCR1A, so start delay from there.
	step_start = OCR1A;
	if (next_step_time == 0) {
		// new move, take current time as start value
		step_start = TCNT1;
	}
	next_step_time = delay;

	#ifdef ACCELERATION_TEMPORAL
	// 300 = safe number of cpu cycles until the interrupt actually happens
	current_time = TCNT1;
	earliest_time = (uint32_t)current_time + 300;
	if (current_time < step_start) // timer counter did overflow recently
		earliest_time += 0x00010000;
	actual_time = (uint32_t)step_start + next_step_time;

	// Setting the interrupt earlier than it can happen obviously doesn't
	// make sense. To keep the "belongs to one move" idea, add an extra,
	// remember this extra and compensate the extra if a longer delay comes in.
	if (earliest_time > actual_time) {
		step_extra_time += (earliest_time - actual_time);
		next_step_time = earliest_time - (uint32_t)step_start;
	}
	else if (step_extra_time) {
		if (step_extra_time < actual_time - earliest_time) {
			next_step_time -= step_extra_time;
			step_extra_time = 0;
		}
		else {
			step_extra_time -= (actual_time - earliest_time);
			next_step_time -= (actual_time - earliest_time);
		}
	}
	#endif /* ACCELERATION_TEMPORAL */

	// Now we know how long we actually want to delay, so set the timer.
	if (next_step_time < 65536) {
		// set the comparator directly to the next real step
		OCR1A = (next_step_time + step_start) & 0xFFFF;
	}
	else if (next_step_time < 75536) {
		// Next comparator interrupt would have to trigger another
		// interrupt within a short time (possibly within 1 cycle).
		// Avoid the impossible by firing the interrupt earlier.
		OCR1A = (step_start - 10000) & 0xFFFF;
		next_step_time += 10000;
	}
	else {
		OCR1A = step_start;
	}

	// Enable this interrupt, but only do it after disabling
	// global interrupts (see above). This will cause push any possible
	// timer1a interrupt to the far side of the return, protecting the 
	// stack from recursively clobbering memory.
	TIMSK1 |= MASK(OCIE1A);
}
예제 #7
0
파일: timer.c 프로젝트: triffid/avr-servo
/// specify how long until the step timer should fire
void setTimer(uint32_t delay)
{
	// save interrupt flag
	uint8_t sreg = SREG;
	uint16_t step_start = 0;
	
	// disable interrupts
	cli();
	CLI_SEI_BUG_MEMORY_BARRIER();
	
	// re-enable clock interrupt in case we're recovering from emergency stop
	TIMSK1 |= MASK(OCIE1B);

	if (delay > 0) {

		// if the delay is too small use a minimum delay so that there is time
		// to set everything up before the timer expires.

		if (delay < 17 )
			delay = 17;
		
		// Assume all steps belong to one move. Within one move the delay is
		// from one step to the next one, which should be more or less the same
		// as from one step interrupt to the next one. The last step interrupt happend
		// at OCR1A, so start delay from there.
		step_start = OCR1A;
		if (next_step_time == 0) {
			// new move, take current time as start value
			step_start = TCNT1;
		}

		next_step_time = delay;
		if (next_step_time < 65536) {
			// set the comparator directly to the next real step
			OCR1A = (next_step_time + step_start) & 0xFFFF;
		}
		else if (next_step_time < 75536) {
			// Next comparator interrupt would have to trigger another
			// interrupt within a short time (possibly within 1 cycle).
			// Avoid the impossible by firing the interrupt earlier.
			OCR1A = (step_start - 10000) & 0xFFFF;
			next_step_time += 10000;
		}
		else {
			OCR1A = step_start;
		}

		// Defer the enabling of the timer1_CompA interrupts.
		
		timer1_compa_deferred_enable = 1;
	} else {
		// flag: move has ended
		next_step_time = 0;
		TIMSK1 &= ~MASK(OCIE1A);
		timer1_compa_deferred_enable = 0;
	}

	// restore interrupt flag
	MEMORY_BARRIER();
	SREG = sreg;
}