Commit | Line | Data |
---|---|---|
7b49793d | 1 | /* |
cd011f58 AW |
2 | This file is part of Smoothie (http://smoothieware.org/). The motion control part is heavily based on Grbl (https://github.com/simen/grbl). |
3 | Smoothie is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. | |
4 | Smoothie is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. | |
7b49793d | 5 | You should have received a copy of the GNU General Public License along with Smoothie. If not, see <http://www.gnu.org/licenses/>. |
cd011f58 AW |
6 | */ |
7 | ||
8 | ||
5673fe39 | 9 | #include "StepTicker.h" |
cd011f58 | 10 | |
3b1e82d2 AW |
11 | #include "libs/nuts_bolts.h" |
12 | #include "libs/Module.h" | |
13 | #include "libs/Kernel.h" | |
5673fe39 | 14 | #include "StepperMotor.h" |
c9cc5e06 | 15 | #include "StreamOutputPool.h" |
da3a10b9 | 16 | #include "system_LPC17xx.h" // mbed.h lib |
61134a65 | 17 | #include <math.h> |
bd0f7508 AW |
18 | #include <mri.h> |
19 | ||
9e089978 JM |
20 | #ifdef STEPTICKER_DEBUG_PIN |
21 | #include "gpio.h" | |
22 | extern GPIO stepticker_debug_pin; | |
23 | #endif | |
24 | ||
61134a65 JM |
25 | extern bool _isr_context; |
26 | ||
921bdb42 AW |
27 | // StepTicker handles the base frequency ticking for the Stepper Motors / Actuators |
28 | // It has a list of those, and calls their tick() functions at regular intervals | |
29 | // They then do Bresenham stuff themselves | |
3b1e82d2 | 30 | |
2fa50ca0 | 31 | StepTicker* StepTicker::global_step_ticker; |
3b1e82d2 | 32 | |
1fce036c | 33 | StepTicker::StepTicker(){ |
2fa50ca0 | 34 | StepTicker::global_step_ticker = this; |
93694d6b AW |
35 | |
36 | // Configure the timer | |
8aea2a35 | 37 | LPC_TIM0->MR0 = 10000000; // Initial dummy value for Match Register |
813727fb | 38 | LPC_TIM0->MCR = 3; // Match on MR0, reset on MR0, match on MR1 |
8aea2a35 | 39 | LPC_TIM0->TCR = 0; // Disable interrupt |
796c9f32 | 40 | |
8aea2a35 | 41 | LPC_SC->PCONP |= (1 << 2); // Power Ticker ON |
813727fb AW |
42 | LPC_TIM1->MR0 = 1000000; |
43 | LPC_TIM1->MCR = 1; | |
8aea2a35 | 44 | LPC_TIM1->TCR = 1; // Enable interrupt |
813727fb | 45 | |
7b49793d | 46 | // Default start values |
acf766a4 | 47 | this->a_move_finished = false; |
3b1acdaa | 48 | this->do_move_finished = false; |
bd0f7508 | 49 | this->reset_step_pins = false; |
3b1acdaa | 50 | this->set_frequency(100000); |
650ed0a8 | 51 | this->set_reset_delay(100); |
a157d099 | 52 | this->set_acceleration_ticks_per_second(1000); |
feb204be | 53 | this->last_duration = 0; |
1fce036c JM |
54 | this->num_motors= 0; |
55 | this->active_motor.reset(); | |
a157d099 | 56 | this->acceleration_tick_cnt= 0; |
3b1acdaa | 57 | this->do_acceleration_tick= false; |
796c9f32 | 58 | |
921bdb42 | 59 | NVIC_EnableIRQ(TIMER0_IRQn); // Enable interrupt handler |
813727fb | 60 | NVIC_EnableIRQ(TIMER1_IRQn); // Enable interrupt handler |
3b1e82d2 AW |
61 | } |
62 | ||
3eadcfee | 63 | StepTicker::~StepTicker() { |
3eadcfee JM |
64 | } |
65 | ||
921bdb42 | 66 | // Set the base stepping frequency |
1ad23cd3 | 67 | void StepTicker::set_frequency( float frequency ){ |
3b1e82d2 | 68 | this->frequency = frequency; |
9e089978 | 69 | this->period = floorf((SystemCoreClock/4.0F)/frequency); // SystemCoreClock/4 = Timer increments in a second |
feb204be | 70 | LPC_TIM0->MR0 = this->period; |
3b1e82d2 AW |
71 | if( LPC_TIM0->TC > LPC_TIM0->MR0 ){ |
72 | LPC_TIM0->TCR = 3; // Reset | |
73 | LPC_TIM0->TCR = 1; // Reset | |
74 | } | |
75 | } | |
76 | ||
921bdb42 | 77 | // Set the reset delay |
1ad23cd3 | 78 | void StepTicker::set_reset_delay( float seconds ){ |
9e089978 | 79 | this->delay = floorf((SystemCoreClock/4.0F)*seconds); // SystemCoreClock/4 = Timer increments in a second |
813727fb | 80 | LPC_TIM1->MR0 = this->delay; |
3b1e82d2 AW |
81 | } |
82 | ||
a157d099 JM |
83 | // this is the number of stepper ticks (100,000/sec) per acceleration tick |
84 | void StepTicker::set_acceleration_ticks_per_second(uint32_t acceleration_ticks_per_second) { | |
85 | this->acceleration_tick_period= floorf(this->frequency/acceleration_ticks_per_second); | |
3b1e82d2 AW |
86 | } |
87 | ||
acf766a4 | 88 | // Call signal_move_finished() on each active motor that asked to be signaled. We do this instead of inside of tick() so that |
6b080aff | 89 | // all tick()s are called before we do the move finishing |
acf766a4 | 90 | void StepTicker::signal_a_move_finished(){ |
4df07f88 MM |
91 | _isr_context = true; |
92 | ||
1fce036c JM |
93 | for (int motor = 0; motor < num_motors; motor++){ |
94 | if (this->active_motor[motor] && this->motor[motor]->is_move_finished){ | |
95 | this->motor[motor]->signal_move_finished(); | |
9e089978 | 96 | // Theoretically this does nothing and the reason for it is currently unknown and/or forgotten |
1fce036c | 97 | // if(this->motor[motor]->moving == false){ |
9e089978 JM |
98 | // if (motor > 0){ |
99 | // motor--; | |
100 | // bitmask >>= 1; | |
101 | // } | |
102 | // } | |
bd0f7508 | 103 | } |
bd0f7508 | 104 | } |
4df07f88 MM |
105 | |
106 | _isr_context = false; | |
bd0f7508 AW |
107 | } |
108 | ||
6b080aff | 109 | // Reset step pins on all active motors |
feb204be | 110 | inline void StepTicker::reset_tick(){ |
4df07f88 MM |
111 | _isr_context = true; |
112 | ||
1fce036c JM |
113 | for (int i = 0; i < num_motors; i++) { |
114 | if(this->active_motor[i]) | |
115 | this->motor[i]->unstep(); | |
3b1e82d2 | 116 | } |
4df07f88 MM |
117 | |
118 | _isr_context = false; | |
3b1e82d2 AW |
119 | } |
120 | ||
813727fb | 121 | extern "C" void TIMER1_IRQHandler (void){ |
7b49793d | 122 | LPC_TIM1->IR |= 1 << 0; |
2fa50ca0 | 123 | StepTicker::global_step_ticker->reset_tick(); |
813727fb AW |
124 | } |
125 | ||
921bdb42 | 126 | // The actual interrupt handler where we do all the work |
3b1e82d2 | 127 | extern "C" void TIMER0_IRQHandler (void){ |
2fa50ca0 JM |
128 | StepTicker::global_step_ticker->TIMER0_IRQHandler(); |
129 | } | |
b2b0b56d | 130 | |
16220afe JM |
131 | extern "C" void PendSV_Handler(void) { |
132 | StepTicker::global_step_ticker->PendSV_IRQHandler(); | |
133 | } | |
134 | ||
135 | // slightly lower priority than TIMER0, the whole end of block/start of block is done here allowing the timer to continue ticking | |
a157d099 | 136 | // also handles the acceleration tick |
3b1acdaa JM |
137 | void StepTicker::PendSV_IRQHandler (void) { |
138 | ||
139 | if(this->do_move_finished) { | |
140 | this->do_move_finished= false; | |
16220afe | 141 | |
a157d099 JM |
142 | #ifdef STEPTICKER_DEBUG_PIN |
143 | stepticker_debug_pin= 1; | |
144 | #endif | |
16220afe | 145 | |
a157d099 JM |
146 | this->signal_a_move_finished(); |
147 | ||
148 | #ifdef STEPTICKER_DEBUG_PIN | |
149 | stepticker_debug_pin= 0; | |
150 | #endif | |
151 | } | |
f095cddd | 152 | |
3b1acdaa JM |
153 | if(this->do_acceleration_tick) { |
154 | this->do_acceleration_tick= false; | |
155 | // call registered acceleration handlers | |
156 | for (size_t i = 0; i < acceleration_tick_handlers.size(); ++i) { | |
157 | acceleration_tick_handlers[i](); | |
158 | } | |
159 | } | |
16220afe JM |
160 | } |
161 | ||
2fa50ca0 | 162 | void StepTicker::TIMER0_IRQHandler (void){ |
8aea2a35 | 163 | // Reset interrupt register |
813727fb | 164 | LPC_TIM0->IR |= 1 << 0; |
16220afe | 165 | LPC_TIM0->MR0 = this->period; |
4464301d | 166 | |
7b49793d | 167 | // Step pins |
1fce036c JM |
168 | for (uint32_t motor = 0; motor < num_motors; motor++){ |
169 | if (this->active_motor[motor]){ | |
170 | this->motor[motor]->tick(); | |
12800c08 AW |
171 | } |
172 | } | |
4464301d | 173 | |
bd0f7508 | 174 | // We may have set a pin on in this tick, now we start the timer to set it off |
2fa50ca0 | 175 | if( this->reset_step_pins ){ |
bd0f7508 AW |
176 | LPC_TIM1->TCR = 3; |
177 | LPC_TIM1->TCR = 1; | |
2fa50ca0 | 178 | this->reset_step_pins = false; |
a157d099 JM |
179 | } |
180 | ||
181 | // do an acceleration tick, after we have done everything else | |
182 | if(++this->acceleration_tick_cnt >= this->acceleration_tick_period) { | |
183 | this->acceleration_tick_cnt= 0; | |
184 | this->do_acceleration_tick= true; | |
bd0f7508 | 185 | } |
61134a65 | 186 | |
3b1acdaa JM |
187 | if(this->a_move_finished) { |
188 | this->a_move_finished = false; | |
189 | this->do_move_finished= 1; | |
190 | } | |
191 | ||
bd0f7508 | 192 | // If a move finished in this tick, we have to tell the actuator to act accordingly |
3b1acdaa | 193 | if(this->do_move_finished || this->do_acceleration_tick){ |
f095cddd | 194 | // we delegate the slow stuff to the pendsv handler which will run as soon as this interrupt exits |
16220afe JM |
195 | //NVIC_SetPendingIRQ(PendSV_IRQn); this doesn't work |
196 | SCB->ICSR = 0x10000000; // SCB_ICSR_PENDSVSET_Msk; | |
bd0f7508 | 197 | } |
3b1e82d2 AW |
198 | } |
199 | ||
1fce036c JM |
200 | // returns index of the stepper motor in the array and bitset |
201 | int StepTicker::register_motor(StepperMotor* motor) | |
202 | { | |
203 | this->motor.push_back(motor); | |
204 | this->num_motors= this->motor.size(); | |
205 | return this->num_motors-1; | |
206 | } | |
bd0f7508 | 207 | |
1fce036c | 208 | // activate the specified motor, must have been registered |
670fa10b | 209 | void StepTicker::add_motor_to_active_list(StepperMotor* motor) |
6e0063ab | 210 | { |
1fce036c JM |
211 | bool enabled= active_motor.any(); // see if interrupt was previously enabled |
212 | active_motor[motor->index]= 1; | |
213 | if(!enabled) { | |
214 | LPC_TIM0->TCR = 1; // Enable interrupt | |
796c9f32 | 215 | } |
796c9f32 AW |
216 | } |
217 | ||
6b080aff | 218 | // Remove a stepper from the list of active motors |
670fa10b | 219 | void StepTicker::remove_motor_from_active_list(StepperMotor* motor) |
6e0063ab | 220 | { |
1fce036c JM |
221 | active_motor[motor->index]= 0; |
222 | // If we have no motor to work on, disable the whole interrupt | |
223 | if(this->active_motor.none()){ | |
224 | LPC_TIM0->TCR = 0; // Disable interrupt | |
796c9f32 | 225 | } |
796c9f32 | 226 | } |