ini
[aversive.git] / modules / devices / encoders / encoders_microb / encoders_microb.c
1 /*  
2  *  Copyright Droids Corporation, Microb Technology, Eirbot (2005)
3  * 
4  *  This program is free software; you can redistribute it and/or modify
5  *  it under the terms of the GNU General Public License as published by
6  *  the Free Software Foundation; either version 2 of the License, or
7  *  (at your option) any later version.
8  *
9  *  This program is distributed in the hope that it will be useful,
10  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
11  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  *  GNU General Public License for more details.
13  *
14  *  You should have received a copy of the GNU General Public License
15  *  along with this program; if not, write to the Free Software
16  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
17  *
18  *  Revision : $Id: encoders_microb.c,v 1.6.4.3 2008-01-09 22:27:19 zer0 Exp $
19  *
20  */
21
22 /** \file encoders_microb.c
23  *  \brief Implementation for getting motor position
24  *
25  *  \todo test the module
26  *
27  *  \test nothing done
28  *
29  * This module provides functions for getting position from
30  * coders. Its implementation depends on hardware, so that's why there
31  * is (or will be) multiple implementation of this module.
32  * 
33  * The harware is quite simple here :
34  * 
35  * \verbatim         
36  * ----------
37  * |        |  8
38  * |    PINx|<-/---  value
39  * |        |   
40  * |        |  8
41  * |    PINy|<-/---  value
42  * |        |
43  * |        |  8
44  * |    PINz|<-/---  value
45  * |        |
46  * |    ....|
47  * |        |
48  * |    SEL |---->  (1 bit)
49  * |        |  
50  * |        |
51  * |        |
52  * ----------
53  * \endverbatim         
54  */
55
56 #include <stdlib.h>
57
58 #include <aversive.h>
59 #include <aversive/wait.h>
60
61 #include <encoders_microb.h>
62 #include <encoders_microb_config.h>
63
64
65 /******************************************/
66 int32_t g_encoders_microb_values[ENCODERS_MICROB_NUMBER];
67 int8_t g_encoders_microb_previous[ENCODERS_MICROB_NUMBER];
68
69 /******************************************/
70
71 #define SEL_A() cbi(ENCODERS_MICROB_SEL_PORT,ENCODERS_MICROB_SEL_BIT)
72 #define SEL_B() sbi(ENCODERS_MICROB_SEL_PORT,ENCODERS_MICROB_SEL_BIT)
73
74 /******************************************/
75
76 #define READ(n)                                     \
77 do {                                                \
78 val = ENCODERS_MICROB##n##_PIN;                     \
79 nop();                                              \
80 if (val != ENCODERS_MICROB##n##_PIN)                \
81      val = ENCODERS_MICROB##n##_PIN;                \
82                                                     \
83 res = (val - g_encoders_microb_previous[n]);        \
84 g_encoders_microb_previous[n] = val;                \
85                                                     \
86 g_encoders_microb_values[n] += (int32_t)res ;           \
87 } while(0)
88
89 /******************************************/
90
91 #define INIT(n)   do {                              \
92 g_encoders_microb_values[n] = 0;                    \
93 } while(0)
94
95 /******************************************/
96
97
98
99
100
101 /** 
102  * Initialisation of encoders, variables
103  */
104 void encoders_microb_init(void)
105 {
106   uint8_t flags;
107
108   sbi(DDR(ENCODERS_MICROB_SEL_PORT),ENCODERS_MICROB_SEL_BIT);
109   SEL_A();
110   // wait at least 10us
111   wait_4cyc(50);
112   encoders_microb_manage(NULL);
113   wait_4cyc(50);
114   encoders_microb_manage(NULL);
115
116   IRQ_LOCK(flags);
117 #ifdef ENCODERS_MICROB0_ENABLED
118   INIT(0);
119 #endif
120
121 #ifdef ENCODERS_MICROB2_ENABLED
122   INIT(2);
123 #endif
124
125 #ifdef ENCODERS_MICROB4_ENABLED
126   INIT(4);
127 #endif
128
129 #ifdef ENCODERS_MICROB6_ENABLED
130   INIT(6);
131 #endif
132
133   
134   SEL_B();
135   // wait at least 10us
136   wait_4cyc(50);
137
138 #ifdef ENCODERS_MICROB1_ENABLED
139   INIT(1);
140 #endif
141
142 #ifdef ENCODERS_MICROB3_ENABLED
143   INIT(3);
144 #endif
145
146 #ifdef ENCODERS_MICROB5_ENABLED
147   INIT(5);
148 #endif
149
150 #ifdef ENCODERS_MICROB7_ENABLED
151   INIT(7);
152 #endif
153   IRQ_UNLOCK(flags);
154
155 }
156
157
158 /** 
159  * Update encoders values, need to be done quite often
160  * (Fmax_encoders/64). First, encoders 0 2 4 6 are read, and at next call
161  * encoders 1 3 5 7. 
162  * 
163  * \param dummy : a (void *) pointer that is not used. It is here according
164  *                to the encoders interface.
165  */
166 void encoders_microb_manage(void * dummy)
167 {
168   static uint8_t sel=0;
169   uint8_t flags;
170
171
172   int8_t val, res;
173
174   IRQ_LOCK(flags);
175
176   if ( ! sel) /* here SEL_A() is set since last call */
177     {
178 #ifdef ENCODERS_MICROB0_ENABLED
179       READ(0);
180 #endif
181       
182 #ifdef ENCODERS_MICROB2_ENABLED
183       READ(2);
184 #endif
185       
186 #ifdef ENCODERS_MICROB4_ENABLED
187       READ(4);
188 #endif
189       
190 #ifdef ENCODERS_MICROB6_ENABLED
191       READ(6);
192 #endif
193
194       SEL_B();
195     }
196   else /* here SEL_B() is set since last call */
197     {
198 #ifdef ENCODERS_MICROB1_ENABLED
199       READ(1);
200 #endif
201       
202 #ifdef ENCODERS_MICROB3_ENABLED
203       READ(3);
204 #endif
205       
206 #ifdef ENCODERS_MICROB5_ENABLED
207       READ(5);
208 #endif
209       
210 #ifdef ENCODERS_MICROB7_ENABLED
211       READ(7);
212 #endif
213
214       SEL_A();
215     }
216   
217   sel = !sel;
218
219   IRQ_UNLOCK(flags);
220
221 }
222
223
224
225 /** Extract encoder value.
226  *
227  * \param number : a (void *) that is casted in (int) containing the number
228  *                 of the encoder to be read.
229  */
230 int32_t encoders_microb_get_value(void * number)
231 {
232   int32_t value;
233   uint8_t flags;
234
235   IRQ_LOCK(flags);
236   value = g_encoders_microb_values[(int)number];
237   IRQ_UNLOCK(flags);
238
239   return value;
240 }
241
242 /** Set an encoder value
243  *
244  * \param number : a (void *) that is casted in (int) containing the number
245  *                 of the encoder to be read.
246  * \param v      : the value
247  */
248 void encoders_microb_set_value(void * number, int32_t v)
249 {
250   uint8_t flags;
251
252   IRQ_LOCK(flags);
253   g_encoders_microb_values[(int)number] = v;
254   IRQ_UNLOCK(flags);
255 }