StepTicker::StepTicker(){
global_step_ticker = this;
- LPC_TIM0->MR0 = 10000000; // Initial dummy value for Match Register
+ LPC_TIM0->MR0 = 10000000; // Initial dummy value for Match Register
LPC_TIM0->MCR = 3; // Match on MR0, reset on MR0, match on MR1
- LPC_TIM0->TCR = 1; // Enable interrupt
+ LPC_TIM0->TCR = 0; // Disable interrupt
- LPC_SC->PCONP |= (1 << 2); // Power Ticker ON
+ LPC_SC->PCONP |= (1 << 2); // Power Ticker ON
LPC_TIM1->MR0 = 1000000;
LPC_TIM1->MCR = 1;
- LPC_TIM1->TCR = 1; // Enable interrupt
+ LPC_TIM1->TCR = 1; // Enable interrupt
// Default start values
this->moves_finished = false;
this->set_frequency(0.001);
this->set_reset_delay(100);
this->last_duration = 0;
- for (int i = 0; i < 12; i++)
+ for (int i = 0; i < 12; i++){
this->active_motors[i] = NULL;
+ }
this->active_motor_bm = 0;
NVIC_EnableIRQ(TIMER0_IRQn); // Enable interrupt handler
// Call tick() on each active motor
inline void StepTicker::tick(){
_isr_context = true;
-
int i;
- uint32_t bm;
- for (i = 0, bm = 1; i < 12; i++, bm <<= 1)
- {
- if (this->active_motor_bm & bm)
- {
+ uint32_t bm = 1;
+ // We iterate over each active motor
+ for (i = 0; i < 12; i++, bm <<= 1){
+ if (this->active_motor_bm & bm){
this->active_motors[i]->tick();
}
}
-
_isr_context = false;
}
void StepTicker::signal_moves_finished(){
_isr_context = true;
- int i;
- uint32_t bm;
- for (i = 0, bm = 1; i < 12; i++, bm <<= 1)
- {
- if (this->active_motor_bm & bm)
- {
- if (this->active_motors[i]->is_move_finished)
- {
- this->active_motors[i]->signal_move_finished();
- if (this->active_motors[i]->moving == false)
- {
- if (i > 0)
- {
- i--;
- bm >>= 1;
+ uint16_t bitmask = 1;
+ for ( uint8_t motor = 0; motor < 12; motor++, bitmask <<= 1){
+ if (this->active_motor_bm & bitmask){
+ if(this->active_motors[motor]->is_move_finished){
+ this->active_motors[motor]->signal_move_finished();
+ if(this->active_motors[motor]->moving == false){
+ if (motor > 0){
+ motor--;
+ bitmask >>= 1;
}
}
}
// Reset step pins on all active motors
inline void StepTicker::reset_tick(){
+ LPC_GPIO3->FIOSET = 1<<25;
_isr_context = true;
int i;
}
_isr_context = false;
+ LPC_GPIO3->FIOCLR = 1<<25;
}
extern "C" void TIMER1_IRQHandler (void){
// The actual interrupt handler where we do all the work
extern "C" void TIMER0_IRQHandler (void){
- LPC_GPIO1->FIODIR |= 1<<18;
- LPC_GPIO1->FIOSET = 1<<18;
-
-// uint32_t initial_tc = LPC_TIM0->TC;
+ LPC_GPIO3->FIODIR |= 1<<25;
+ LPC_GPIO1->FIODIR |= 1<<22;
+ LPC_GPIO1->FIODIR |= 1<<23;
+ LPC_GPIO1->FIODIR |= 1<<30;
+ LPC_GPIO1->FIODIR |= 1<<31;
+ LPC_GPIO1->FIOSET = 1<<22;
+ // Reset interrupt register
LPC_TIM0->IR |= 1 << 0;
- // If no axes enabled, just ignore for now
- if( global_step_ticker->active_motor_bm == 0 ){
- LPC_GPIO1->FIOCLR = 1<<18;
- return;
- }
-
- // Do not get out of here before everything is nice and tidy
- LPC_TIM0->MR0 = 2000000;
-
// Step pins
- global_step_ticker->tick();
+ //global_step_ticker->tick();
+ _isr_context = true;
+ uint16_t bitmask = 1;
+ for (uint8_t motor = 0; motor < 12; motor++, bitmask <<= 1){
+ if (global_step_ticker->active_motor_bm & bitmask){
+ global_step_ticker->active_motors[motor]->tick();
+ }
+ }
+ _isr_context = false;
// We may have set a pin on in this tick, now we start the timer to set it off
if( global_step_ticker->reset_step_pins ){
LPC_TIM1->TCR = 3;
LPC_TIM1->TCR = 1;
global_step_ticker->reset_step_pins = false;
+ }else{
+ // Nothing happened, nothing after this really matters
+ // TODO : This could be a problem when we use Actuators instead of StepperMotors, because this flag is specific to step generation
+ LPC_TIM0->MR0 = global_step_ticker->period;
+ LPC_GPIO1->FIOCLR = 1<<22;
+ return;
}
-
+
// If a move finished in this tick, we have to tell the actuator to act accordingly
- if( global_step_ticker->moves_finished ){ global_step_ticker->signal_moves_finished(); }
-
-// uint32_t after_signal = LPC_TIM0->TC;
-
- // If we went over the duration an interrupt is supposed to last, we have a problem
- // That can happen tipically when we change blocks, where more than usual computation is done
- // This can be OK, if we take notice of it, which we do now
- if( LPC_TIM0->TC > global_step_ticker->period ){ // TODO: remove the size condition
-
- LPC_GPIO1->FIODIR |= 1<<19;
- LPC_GPIO1->FIOSET = 1<<19;
+ if( global_step_ticker->moves_finished ){
+
+ // Do not get out of here before everything is nice and tidy
+ LPC_TIM0->MR0 = 2000000;
+
+ global_step_ticker->signal_moves_finished();
+
+ // If we went over the duration an interrupt is supposed to last, we have a problem
+ // That can happen tipically when we change blocks, where more than usual computation is done
+ // This can be OK, if we take notice of it, which we do now
+ if( LPC_TIM0->TC > global_step_ticker->period ){ // TODO: remove the size condition
+
+ LPC_GPIO1->FIOCLR = 1<<22;
+ uint32_t start_tc = LPC_TIM0->TC;
+ LPC_GPIO1->FIOSET = 1<<22;
+
+ // How many ticks we want to skip ( this does not include the current tick, but we add the time we spent doing this computation last time )
+ uint32_t ticks_to_skip = ( ( LPC_TIM0->TC + global_step_ticker->last_duration ) / global_step_ticker->period );
+
+ // Next step is now to reduce this to how many steps we can *actually* skip
+ uint32_t ticks_we_actually_can_skip = ticks_to_skip;
+
+ int i;
+ uint32_t bm;
+ for (i = 0, bm = 1; i < 12; i++, bm <<= 1)
+ {
+ if (global_step_ticker->active_motor_bm & bm)
+ ticks_we_actually_can_skip =
+ min(ticks_we_actually_can_skip,
+ (uint32_t)((uint64_t)( (uint64_t)global_step_ticker->active_motors[i]->fx_ticks_per_step - (uint64_t)global_step_ticker->active_motors[i]->fx_counter ) >> 32)
+ );
+ }
- uint32_t start_tc = LPC_TIM0->TC;
+ // Adding to MR0 for this time is not enough, we must also increment the counters ourself artificially
+ for (i = 0, bm = 1; i < 12; i++, bm <<= 1)
+ {
+ if (global_step_ticker->active_motor_bm & bm)
+ global_step_ticker->active_motors[i]->fx_counter += (uint64_t)((uint64_t)(ticks_we_actually_can_skip)<<32);
+ }
- // How many ticks we want to skip ( this does not include the current tick, but we add the time we spent doing this computation last time )
- uint32_t ticks_to_skip = ( ( LPC_TIM0->TC + global_step_ticker->last_duration ) / global_step_ticker->period );
+ // When must we have our next MR0 ? ( +1 is here to account that we are actually doing a legit MR0 match here too, not only overtime )
+ LPC_TIM0->MR0 = ( ticks_to_skip + 1 ) * global_step_ticker->period;
- // Next step is now to reduce this to how many steps we can *actually* skip
- uint32_t ticks_we_actually_can_skip = ticks_to_skip;
+ // This is so that we know how long this computation takes, and we can take it into account next time
+ int difference = (int)(LPC_TIM0->TC) - (int)(start_tc);
+ if( difference > 0 ){ global_step_ticker->last_duration = (uint32_t)difference; }
- int i;
- uint32_t bm;
- for (i = 0, bm = 1; i < 12; i++, bm <<= 1)
- {
- if (global_step_ticker->active_motor_bm & bm)
- ticks_we_actually_can_skip =
- min(ticks_we_actually_can_skip,
- (uint32_t)((uint64_t)( (uint64_t)global_step_ticker->active_motors[i]->fx_ticks_per_step - (uint64_t)global_step_ticker->active_motors[i]->fx_counter ) >> 32)
- );
+ }else{
+ LPC_TIM0->MR0 = global_step_ticker->period;
}
- // Adding to MR0 for this time is not enough, we must also increment the counters ourself artificially
- for (i = 0, bm = 1; i < 12; i++, bm <<= 1)
- {
- if (global_step_ticker->active_motor_bm & bm)
- global_step_ticker->active_motors[i]->fx_counter += (uint64_t)((uint64_t)(ticks_we_actually_can_skip)<<32);
+ while( LPC_TIM0->TC > LPC_TIM0->MR0 ){
+ LPC_TIM0->MR0 += global_step_ticker->period;
}
- // When must we have our next MR0 ? ( +1 is here to account that we are actually doing a legit MR0 match here too, not only overtime )
- // LPC_TIM0->MR0 = ( ticks_we_actually_can_skip + 1 ) * global_step_ticker->period;
- LPC_TIM0->MR0 = ( ticks_to_skip + 1 ) * global_step_ticker->period;
-
- // This is so that we know how long this computation takes, and we can take it into account next time
- int difference = (int)(LPC_TIM0->TC) - (int)(start_tc);
- if( difference > 0 ){ global_step_ticker->last_duration = (uint32_t)difference; }
-
- //if( global_step_ticker->last_duration > 2000 || LPC_TIM0->MR0 > 2000 || LPC_TIM0->TC > 2000 || initial_tc > 2000 ){ __debugbreak(); }
-
- LPC_GPIO1->FIOCLR = 1<<19;
-
- }else{
- LPC_TIM0->MR0 = global_step_ticker->period;
}
- LPC_GPIO1->FIOCLR = 1<<18;
-
- while( LPC_TIM0->TC > LPC_TIM0->MR0 ){
- LPC_TIM0->MR0 += global_step_ticker->period;
- }
-
- LPC_GPIO1->FIOCLR = 1<<18;
+ LPC_GPIO1->FIOCLR = 1<<22;
}
if (this->active_motors[i] == motor)
{
this->active_motor_bm |= bm;
+ // If we have no motor to work on, disable the whole interrupt
+ if( this->active_motor_bm == 0 ){
+ LPC_TIM0->TCR = 0; // Disable interrupt
+ }else{
+ LPC_TIM0->TCR = 1; // Enable interrupt
+ }
return;
}
if (this->active_motors[i] == NULL)
{
this->active_motors[i] = motor;
this->active_motor_bm |= bm;
+ // If we have no motor to work on, disable the whole interrupt
+ if( this->active_motor_bm == 0 ){
+ LPC_TIM0->TCR = 0; // Disable interrupt
+ }else{
+ LPC_TIM0->TCR = 1; // Enable interrupt
+ }
return;
}
}
if (this->active_motors[i] == motor)
{
this->active_motor_bm &= ~bm;
+ // If we have no motor to work on, disable the whole interrupt
+ if( this->active_motor_bm == 0 ){
+ LPC_TIM0->TCR = 0; // Disable interrupt
+ }else{
+ LPC_TIM0->TCR = 1; // Enable interrupt
+ }
return;
}
}