1 #include <stepper-interrupt.h>
2 #include <interrupt-utils.h>
8 StepperContext stepper_context;
12 do_step(StepperTimerStep *step)
14 const uint32_t *io_steps;
15 StepperState *state = step->state;
18 if (step->power >= STEPPER_POWER_ACC) {
19 io_steps = state->acc_steps;
20 }
else if (step->power >= STEPPER_POWER_RUN) {
21 io_steps = state->run_steps;
23 io_steps = state->hold_steps;
26 if (step->direction == STEPPER_DIRECTION_FORWARD){
29 if (++state->current_step == state->sequence_length)
30 state->current_step = 0;
34 if (state->current_step-- == 0)
35 state->current_step = state->sequence_length-1;
37 *AT91C_PIOA_ODSR = (*AT91C_PIOA_ODSR & ~state->io_mask)
38 | (io_steps[state->current_step] & state->io_mask);
41 long err = ((long)stepper_context.timer_channel->TC_CV - (
long)step->time);
42 if (err >= (TIMER_FREQ/PPS/2)) {
43 err -= TIMER_FREQ/PPS;
44 }
else if (err < -(TIMER_FREQ/PPS/2)) {
45 err += TIMER_FREQ/PPS;
47 if (err < state->err_min) state->err_min = err;
48 if (err > state->err_max) state->err_max = err;
55 set_hold(StepperState *state) {
56 *AT91C_PIOA_ODSR = (*AT91C_PIOA_ODSR & ~state->io_mask)
57 | (state->hold_steps[state->current_step] & state->io_mask);
62 StepperTimerStep *current =stepper_context.current_step;
63 AT91PS_TC
timer = stepper_context.timer_channel;
64 unsigned int now = timer->TC_CV;
65 while (current && current->time <= now) {
67 current = current->next;
69 timer->TC_RA = current->time;
72 stepper_context.current_step = current;
77 mulsu48_16(int64_t a, uint32_t b)
84 solve_dist(
long long s,
long a,
long long v,
unsigned long t_low,
unsigned long t_high)
86 long long s_low = mulsu48_16((a*(
long)t_low+ v), t_low);
87 long long s_high = mulsu48_16((a*(
long)t_high + v), t_high);
88 if (s >= s_low && s <= s_high) {
89 while(t_low + 2 < t_high) {
90 unsigned long t = (t_high + t_low) / 2;
91 long long s_mid = mulsu48_16((a*(
long)t + v), t);
101 while(t_low + 1 < t_high) {
102 unsigned long t = (t_high + t_low) / 2;
103 long long s_mid = mulsu48_16((a*(
long)t + v), t);
113 return (t_high + t_low) / 2;
118 static StepperTimerStep step_heap[2][HEAP_SIZE];
119 static unsigned short heap_pos = 0;
120 static unsigned char current_heap = 0;
122 static StepperTimerStep *
125 if (heap_pos >= HEAP_SIZE)
return NULL;
126 return &step_heap[current_heap][heap_pos++];
137 insert_step(StepperTimerStep **at, StepperState *state,
138 unsigned int time, uint8_t direction, uint8_t power)
140 StepperTimerStep *new_step;
141 while(*at && (*at)->time <= time) {
144 new_step = allocate_step();
145 if (!new_step)
return at;
146 new_step->next = *at;
147 new_step->state = state;
148 new_step->time = time;
149 new_step->direction = direction;
150 new_step->power = power;
153 return &new_step->next;
158 get_power(StepperState *state)
160 if (state->acceleration != 0)
return STEPPER_POWER_ACC;
161 if (state->velocity == 0)
return STEPPER_POWER_HOLD;
162 return STEPPER_POWER_RUN;
165 #define SQ(x) ((x)*(x))
166 #define S_SCALING ((2LL*SQ((long long)TIMER_FREQ)) / DIST_SCALE )
167 #define V_SCALING (2LL*TIMER_FREQ/VEL_SCALE)
171 step_interval(StepperState *state)
174 long long v = state->velocity * V_SCALING;
175 long long a = state->acceleration;
177 StepperTimerStep **at = &stepper_context.steps;
178 if (state->n_steps >= 0) {
179 long long s = -state->step_frac * S_SCALING;
180 for (i = 0; i < state->n_steps; i++) {
181 s+= DIST_SCALE * S_SCALING;
182 t = solve_dist(s, a, v, t, TIMER_FREQ/PPS);
184 at = insert_step(at, state, t, STEPPER_DIRECTION_FORWARD, get_power(state));
187 long long s = (DIST_SCALE - state->step_frac) * S_SCALING;
188 for (i = 0; i < -state->n_steps; i++) {
189 s-= DIST_SCALE * S_SCALING;
190 t = solve_dist(s, a, v, t, TIMER_FREQ/PPS);
192 at = insert_step(at, state, t, STEPPER_DIRECTION_BACKWARD, get_power(state));
197 setup_speed(StepperState *state)
203 step_frac = (state->acceleration + 2 * state->velocity
205 steps = step_frac / DIST_SCALE;
206 step_frac -= steps * DIST_SCALE;
208 step_frac += DIST_SCALE;
214 state->n_steps = steps;
215 step_interval(state);
216 state->velocity += state->acceleration;
217 state->step_frac = step_frac;
218 state->step_full += steps;
225 StepperTimerStep *current =stepper_context.current_step;
229 current = current->next;
232 stepper_context.current_step = stepper_context.steps;
233 stepper_context.steps =
NULL;
234 if (stepper_context.current_step) {
235 stepper_context.timer_channel->TC_RA = stepper_context.current_step->time;
237 stepper_context.timer_channel->TC_RA = 0xffff;
241 stepper_context.period_count++;
242 *AT91C_AIC_EOICR = 0;
243 for(s = 0; s < NUM_STEPPERS; s++) {
244 StepperState *state = &stepper_context.steppers[s];
245 StepperAccSeq *acc_seq;
246 if (state->acceleration == 0 && state->velocity == 0) {
248 stepper_context.timer_channel->TC_IDR = AT91C_TC_CPCS | AT91C_TC_CPAS;
250 stepper_context.timer_channel->TC_IER = AT91C_TC_CPCS | AT91C_TC_CPAS;
252 while ((acc_seq = state->acceleration_sequence)
253 && acc_seq->period == stepper_context.period_count + 1) {
254 state->acceleration_sequence = acc_seq->next;
255 if (acc_seq->acceleration == STEPPER_ACC_INVALID) {
256 if (stepper_context.user_callback) {
257 stepper_context.user_callback(s, stepper_context.period_count);
260 state->acceleration = acc_seq->acceleration;
262 acc_seq->next =
NULL;
263 stepper_free_seq(acc_seq);
265 setup_speed(&stepper_context.steppers[s]);
272 static void stepper_int_safe() __attribute((noinline));
277 status = stepper_context.timer_channel->TC_SR;
278 if (status & AT91C_TC_CPAS) {
282 if (status & AT91C_TC_CPCS) {
285 *AT91C_AIC_EOICR = 0;
290 void NACKEDFUNC stepper_timer_interrupt (
void) {