reprap: Progress
[simavr] / examples / board_reprap / src / stepper.c
1 /*
2         stepper.c
3
4         Copyright 2008-2012 Michel Pollet <buserror@gmail.com>
5
6         This file is part of simavr.
7
8         simavr is free software: you can redistribute it and/or modify
9         it under the terms of the GNU General Public License as published by
10         the Free Software Foundation, either version 3 of the License, or
11         (at your option) any later version.
12
13         simavr is distributed in the hope that it will be useful,
14         but WITHOUT ANY WARRANTY; without even the implied warranty of
15         MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16         GNU General Public License for more details.
17
18         You should have received a copy of the GNU General Public License
19         along with simavr.  If not, see <http://www.gnu.org/licenses/>.
20  */
21
22 #include <stdlib.h>
23 #include <string.h>
24 #include <stdio.h>
25
26 #include "sim_avr.h"
27 #include "stepper.h"
28
29 static void
30 stepper_dir_hook(
31                 struct avr_irq_t * irq,
32                 uint32_t value,
33                 void * param )
34 {
35         stepper_p p = (stepper_p)param;
36         printf("%s (%s) %d\n", __func__, p->name, value);
37         p->dir = !!value;
38 }
39
40 static void
41 stepper_enable_hook(
42                 struct avr_irq_t * irq,
43                 uint32_t value,
44                 void * param )
45 {
46         stepper_p p = (stepper_p)param;
47         p->enable = !!value;
48         printf("%s (%s) %d pos %.4f\n", __func__, p->name, p->enable != 0, p->position);
49         avr_raise_irq(p->irq + IRQ_STEPPER_ENDSTOP_OUT, p->position == p->endstop);
50 }
51
52 static void
53 stepper_step_hook(
54                 struct avr_irq_t * irq,
55                 uint32_t value,
56                 void * param )
57 {
58         stepper_p p = (stepper_p)param;
59         if (!p->enable)
60                 return;
61         if (value)
62                 return;
63         p->position += (p->dir ? -1.0 : 1.0) / p->steps_per_mm;
64         if (p->position < 0)
65                 p->position = 0;
66         if (p->max_position > 0 && p->position > p->max_position)
67                 p->position = p->max_position;
68         printf("%s (%s) %.4f\n", __func__, p->name, p->position);
69         union {
70                 float f;
71                 uint32_t i;
72         } m = { .f = p->position };
73         avr_raise_irq(p->irq + IRQ_STEPPER_POSITION_OUT, m.i);
74         avr_raise_irq(p->irq + IRQ_STEPPER_ENDSTOP_OUT, p->position == p->endstop);
75 }
76
77 static const char * irq_names[IRQ_STEPPER_COUNT] = {
78         [IRQ_STEPPER_DIR_IN] = "1<stepper.direction",
79         [IRQ_STEPPER_STEP_IN] = "1>stepper.step",
80         [IRQ_STEPPER_ENABLE_IN] = "1<stepper.enable",
81         [IRQ_STEPPER_POSITION_OUT] = "32<stepper.position",
82         [IRQ_STEPPER_ENDSTOP_OUT] = "1<stepper.endstop",
83 };
84
85 void
86 stepper_init(
87                 struct avr_t * avr,
88                 stepper_p p,
89                 char * name,
90                 float steps_per_mm,
91                 float start_position,
92                 float max_position,
93                 float endstop_position)
94 {
95         p->avr = avr;
96         strcpy(p->name, name);
97         p->irq = avr_alloc_irq(&avr->irq_pool, 0, IRQ_STEPPER_COUNT, irq_names);
98         avr_irq_register_notify(p->irq + IRQ_STEPPER_DIR_IN, stepper_dir_hook, p);
99         avr_irq_register_notify(p->irq + IRQ_STEPPER_STEP_IN, stepper_step_hook, p);
100         avr_irq_register_notify(p->irq + IRQ_STEPPER_ENABLE_IN, stepper_enable_hook, p);
101
102         p->steps_per_mm = steps_per_mm;
103         p->position = start_position;
104         p->max_position = max_position;
105         p->endstop = endstop_position;
106 }
107
108 void
109 stepper_connect(
110                 stepper_p p,
111                 avr_irq_t *     step,
112                 avr_irq_t *     dir,
113                 avr_irq_t *     enable,
114                 avr_irq_t *     endstop,
115                 uint16_t flags)
116 {
117         avr_connect_irq(step, p->irq + IRQ_STEPPER_STEP_IN);
118         avr_connect_irq(dir, p->irq + IRQ_STEPPER_DIR_IN);
119         avr_connect_irq(enable, p->irq + IRQ_STEPPER_ENABLE_IN);
120         p->irq[IRQ_STEPPER_ENDSTOP_OUT].flags |= IRQ_FLAG_FILTERED;
121         if (endstop) {
122                 avr_connect_irq(p->irq + IRQ_STEPPER_ENDSTOP_OUT, endstop);
123                 if (flags & stepper_endstop_inverted)
124                         p->irq[IRQ_STEPPER_ENDSTOP_OUT].flags |= IRQ_FLAG_NOT;
125         }
126 }