2 #include <stepper-interrupt.h>
8 static StepperAccSeq *free_seq =
NULL;
11 stepper_allocate_seq()
14 if (!free_seq)
return NULL;
15 stepper_context.timer_channel->TC_IDR = AT91C_TC_CPCS | AT91C_TC_CPAS;
18 stepper_context.timer_channel->TC_IER = AT91C_TC_CPCS | AT91C_TC_CPAS;
24 stepper_free_seq(StepperAccSeq *seq)
29 stepper_context.timer_channel->TC_IDR = AT91C_TC_CPCS | AT91C_TC_CPAS;
30 while(s->next) s = s->next;
33 stepper_context.timer_channel->TC_IER = AT91C_TC_CPCS | AT91C_TC_CPAS;
37 stepper_state_init(StepperState *stepper)
39 stepper->step_count = 0;
41 stepper->acc_steps =
NULL;
42 stepper->run_steps =
NULL;
43 stepper->hold_steps =
NULL;
44 stepper->current_step = 0;
45 stepper->sequence_length = 0;
47 stepper->velocity = 0;
48 stepper->acceleration = 0;
49 stepper->step_full = 0;
50 stepper->step_frac = 0;
54 stepper->err_min = TIMER_FREQ;
55 stepper->err_max = -TIMER_FREQ;
61 stepper_init(AT91PS_TC
timer,
unsigned int id)
64 stepper_context.flags = 0;
65 stepper_context.timer_channel = timer;
66 stepper_context.steps =
NULL;
67 stepper_context.current_step =
NULL;
68 stepper_context.period_count = 0;
69 stepper_context.user_callback =
NULL;
71 for (s = 0; s < NUM_STEPPERS; s++) {
72 stepper_state_init(&stepper_context.steppers[s]);
74 timer->TC_CMR = (AT91C_TC_WAVE | AT91C_TC_WAVESEL_UP_AUTO
75 | AT91C_TC_CLKS_TIMER_DIV3_CLOCK);
76 timer->TC_RC = TIMER_FREQ / PPS;
77 timer->TC_RA = 0xffff;
78 timer->TC_IER = AT91C_TC_CPCS | AT91C_TC_CPAS;
79 *AT91C_PMC_PCER = (1 << id);
81 AT91C_AIC_SMR[id] = AT91C_AIC_SRCTYPE_INT_POSITIVE_EDGE | 7;
82 AT91C_AIC_SVR[id] = (
unsigned long)stepper_timer_interrupt;
83 *AT91C_AIC_IECR = (1 << id);
84 timer->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG;
88 stepper_init_io(
unsigned int stepper_index, uint32_t mask,
89 const uint32_t *acc,
const uint32_t *run,
90 const uint32_t *hold,
unsigned int nsteps)
93 if (stepper_index >= NUM_STEPPERS)
return;
94 state = &stepper_context.steppers[stepper_index];
96 stepper_context.timer_channel->TC_IDR = AT91C_TC_CPCS | AT91C_TC_CPAS;
98 state->io_mask = mask;
99 state->acc_steps = acc;
100 state->run_steps = run;
101 state->hold_steps = hold;
102 state->current_step = 0;
103 state->sequence_length = nsteps;
104 *AT91C_PIOA_OWER = mask;
105 *AT91C_PIOA_MDDR = mask;
107 *AT91C_PIOA_ODSR = ((*AT91C_PIOA_ODSR & ~mask)
108 | (state->hold_steps[0] & mask));
109 stepper_context.timer_channel->TC_IER = AT91C_TC_CPCS | AT91C_TC_CPAS;
110 *AT91C_PIOA_OER = mask;
128 stepper_add_acc_seq(
unsigned int stepper_index, StepperAccSeq *new_seq)
130 StepperResult res = STEPPER_ERR_TOO_LATE;
131 StepperAccSeq **seqp;
133 if (stepper_index >= NUM_STEPPERS)
return STEPPER_ERR_INDEX;
134 state = &stepper_context.steppers[stepper_index];
135 stepper_context.timer_channel->TC_IDR = AT91C_TC_CPCS | AT91C_TC_CPAS;
136 seqp = &state->acceleration_sequence;
137 while(*seqp && ((*seqp)->period < new_seq->period || ((*seqp)->period == new_seq->period && (*seqp)->acceleration == STEPPER_ACC_INVALID))) {
138 seqp = &(*seqp)->next;
140 if (new_seq->period > stepper_context.period_count + 1) {
142 if (*seqp) stepper_free_seq(*seqp);
146 stepper_context.timer_channel->TC_IER = AT91C_TC_CPCS | AT91C_TC_CPAS;
165 stepper_insert_callback(
unsigned int stepper_index,
unsigned int period)
167 StepperResult res = STEPPER_ERR_TOO_LATE;
168 StepperAccSeq **seqp;
170 if (stepper_index >= NUM_STEPPERS)
return STEPPER_ERR_INDEX;
171 state = &stepper_context.steppers[stepper_index];
172 stepper_context.timer_channel->TC_IDR = AT91C_TC_CPCS | AT91C_TC_CPAS;
173 seqp = &state->acceleration_sequence;
174 while(*seqp && (*seqp)->period < period) {
175 seqp = &(*seqp)->next;
177 if (period > stepper_context.period_count + 1) {
178 StepperAccSeq *new_seq = stepper_allocate_seq();
180 res = STEPPER_ERR_MEM;
182 new_seq->next = *seqp;
184 new_seq->period = period;
185 new_seq->acceleration = STEPPER_ACC_INVALID;
189 stepper_context.timer_channel->TC_IER = AT91C_TC_CPCS | AT91C_TC_CPAS;
194 stepper_add_acc(
unsigned int stepper_index,
unsigned int period,
long acc)
196 StepperAccSeq *seq = stepper_allocate_seq();
198 if (!seq)
return STEPPER_ERR_MEM;
200 seq->period = period;
201 seq->acceleration = acc;
202 return stepper_add_acc_seq(stepper_index, seq);
206 stepper_set_callback_proc(StepperUserCallback callback)
208 stepper_context.user_callback = callback;
212 stepper_current_period()
214 return stepper_context.period_count;
218 stepper_current_step(
unsigned int stepper_index)
220 StepperState *state = &stepper_context.steppers[stepper_index];
221 return state->step_count;
225 stepper_step_frac(
unsigned int stepper_index)
228 StepperState *state = &stepper_context.steppers[stepper_index];
229 stepper_context.timer_channel->TC_IDR = AT91C_TC_CPCS | AT91C_TC_CPAS;
230 s = state->step_full * DIST_SCALE + state->step_frac;
231 stepper_context.timer_channel->TC_IER = AT91C_TC_CPCS | AT91C_TC_CPAS;
236 stepper_current_velocity(
unsigned int stepper_index)
238 StepperState *state = &stepper_context.steppers[stepper_index];
239 return state->velocity;
245 stepper_velocity(
unsigned int stepper_index,
unsigned long period)
252 state = &stepper_context.steppers[stepper_index];
254 stepper_context.timer_channel->TC_IDR = AT91C_TC_CPCS | AT91C_TC_CPAS;
255 seq = state->acceleration_sequence;
256 a = state->acceleration;
258 t = stepper_context.period_count + 2;
260 while(seq && seq->period < period) {
261 v += a * (seq->period - t);
263 a = seq->acceleration;
266 stepper_context.timer_channel->TC_IER = AT91C_TC_CPCS | AT91C_TC_CPAS;
267 v += a * (period - t);
282 stepper_state_at(
unsigned int stepper_index,
unsigned long period,
283 long *velocity,
long long *position)
292 state = &stepper_context.steppers[stepper_index];
294 stepper_context.timer_channel->TC_IDR = AT91C_TC_CPCS | AT91C_TC_CPAS;
295 if (period < stepper_context.period_count + 2) {
296 stepper_context.timer_channel->TC_IER = AT91C_TC_CPCS | AT91C_TC_CPAS;
297 return STEPPER_ERR_TOO_LATE;
299 seq = state->acceleration_sequence;
300 a = state->acceleration;
302 t = stepper_context.period_count + 2;
303 s = state->step_full * (
long long)DIST_SCALE + state->step_frac;
304 while(seq && seq->period < period) {
305 dt = seq->period - t;
306 s += (a * (
long long)dt + 2 * v) * dt;
307 v += a * (seq->period - t);
309 a = seq->acceleration;
312 stepper_context.timer_channel->TC_IER = AT91C_TC_CPCS | AT91C_TC_CPAS;
314 *position = s + (a * (
long long)dt + (DIST_SCALE/VEL_SCALE) * v) * dt;
315 *velocity = v + a * dt;
322 stepper_set_velocity(
unsigned int stepper_index,
unsigned long *periodp,
323 unsigned long max_acc,
long final_speed)
325 long start_period = *periodp;
326 long v = stepper_velocity(stepper_index, start_period);
328 if (final_speed == v) {
329 return stepper_add_acc(stepper_index, start_period, 0);
332 long a = (final_speed > v) ? max_acc : -max_acc;
333 long t = ((long)(final_speed - v)) / a;
334 long diff = (final_speed - v) - t * a;
336 res = stepper_add_acc(stepper_index, start_period, a);
337 if (res != STEPPER_OK)
return res;
340 res = stepper_add_acc(stepper_index, start_period+t, diff);
341 if (res != STEPPER_OK)
return res;
344 *periodp = start_period+t;
345 return stepper_add_acc(stepper_index, start_period+t, 0);
351 stepper_timing_errors(
unsigned int stepper_index,
long *min,
long *max)
354 state = &stepper_context.steppers[stepper_index];
355 *min = state->err_min;
356 *max = state->err_max;
357 state->err_max = -TIMER_FREQ;
358 state->err_min = TIMER_FREQ;