Project

General

Profile

Statistics
| Revision:

root / branches / simulator / projects / libdragonfly / encoders.c @ 1042

History | View | Annotate | Download (6.91 KB)

1 891 bcoltin
/**
2
 * Copyright (c) 2007 Colony Project
3
 *
4
 * Permission is hereby granted, free of charge, to any person
5
 * obtaining a copy of this software and associated documentation
6
 * files (the "Software"), to deal in the Software without
7
 * restriction, including without limitation the rights to use,
8
 * copy, modify, merge, publish, distribute, sublicense, and/or sell
9
 * copies of the Software, and to permit persons to whom the
10
 * Software is furnished to do so, subject to the following
11
 * conditions:
12
 *
13
 * The above copyright notice and this permission notice shall be
14
 * included in all copies or substantial portions of the Software.
15
 *
16
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
18
 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
20
 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
21
 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
23
 * OTHER DEALINGS IN THE SOFTWARE.
24
 **/
25
26
27
/**
28
 * @file encoders.c
29
 * @brief Implemenation of encoders.
30
 *
31
 * Contains implementation of functions controlling and
32
 * reading from the encoders.
33
 *
34
 * @author CMU Robotics Club
35
 * @bug Not tested.
36
 */
37
38 868 justin
#include "encoders.h"
39
#include "spi.h"
40
#include <dragonfly_lib.h>
41
#include "ring_buffer.h"
42
43
unsigned int left_data_buf;
44
unsigned int right_data_buf;
45
char encoder_buf_index;
46
47
unsigned int left_data;
48
unsigned int right_data;
49
50
unsigned int left_data_array[BUFFER_SIZE];
51
unsigned int right_data_array[BUFFER_SIZE];
52
int left_data_idx;
53
int right_data_idx;
54
55
int left_dx;
56
int right_dx;
57
long int timecount;
58
59
int left_v;
60
int right_v;
61
62
63
volatile short int data_ready;
64
65
void encoder_recv(char data);
66
67
//Helper Function Prototypes
68
inline void left_data_array_put(unsigned short int value);
69
inline unsigned int left_data_array_top(void);
70
inline unsigned int left_data_array_prev(void);
71
inline unsigned int left_data_array_bottom(void);
72
73
inline void right_data_array_put(unsigned short int value);
74
inline unsigned int right_data_array_top(void);
75
inline unsigned int right_data_array_prev(void);
76
inline unsigned int right_data_array_bottom(void);
77
78
79
void encoder_recv_complete(){
80
          encoder_buf_index = 0;
81
        data_ready++;
82
83
           spi_transfer(5);
84
}
85
86
void encoders_init(void){
87
        int i;
88
89
        data_ready=0;
90
91
        spi_init(encoder_recv, encoder_recv_complete);
92
        encoder_buf_index = 0;
93
        left_data_buf = 0;
94
        right_data_buf= 0;
95
        left_data = -1;
96
        right_data = -1;
97
98
99
        left_v=0;
100
        right_v=0;
101
102
        //RING_BUFFER_INIT(enc_buffer,BUFFER_SIZE);
103
        left_data_idx = 0;
104
        right_data_idx = 0;
105
        for(i = 0; i < BUFFER_SIZE; i++) {
106
                left_data_array[i] = 0;
107
        }
108
        for(i = 0; i < BUFFER_SIZE; i++) {
109
                right_data_array[i] = 0;
110
        }
111
        spi_transfer(5);
112
}
113
114
int encoder_read(char encoder){
115
116
        if(encoder==LEFT) return left_data;
117
        else if(encoder==RIGHT) return right_data;
118
        else return -1;
119
}
120
121
int encoder_get_dx(char encoder) {
122
123
        if(encoder==LEFT) return left_dx;
124
        else if(encoder==RIGHT) return right_dx;
125
        else return -1;
126
}
127
128
void encoder_rst_dx(char encoder) {
129
130
        if(encoder==LEFT) left_dx = 0;
131
        else if(encoder==RIGHT) right_dx = 0;
132
}
133
134
int encoder_get_tc(void) {
135
        return timecount;
136
}
137
138
void encoder_rst_tc(void) {
139
        timecount = 0;
140
}
141
142
void encoder_wait(int n){
143
        while(data_ready<n);
144
        data_ready=0;
145
}
146
147
148
//Full reads occur every 40 microseconds. This function should be called
149
//every 8 microseconds.
150
void encoder_recv(char data){
151
        short int dx;
152
153
        //Parse the encoder data, comes in over 5 bytes 16 bits per encoder,
154
        // second is offset by 1 bit.
155
        switch(encoder_buf_index){
156
        case 0:
157
                right_data_buf |= ((short)data)<<8 & 0xff00;
158
                break;
159
        case 1:
160
                right_data_buf |= ((short)data) & 0xff;
161
                break;
162
        case 2:
163
                left_data_buf |= (((short)data) << 9) & (0x7F << 9);
164
                break;
165
        case 3:
166
                left_data_buf |= (((short)data) << 1) & (0xFF<<1);
167
                break;
168
        case 4: left_data_buf |= (((short)data)>>7) & 0x1;
169
        }
170
171
        encoder_buf_index = (encoder_buf_index + 1) % 5;
172
173
        if(encoder_buf_index==0) {
174
175
                /*Error handling for the left encoder*/
176
                if(!(left_data_buf & OCF))
177
                        left_data = ENCODER_DATA_NOT_READY;
178
                if(left_data_buf & (COF | LIN))
179
                        left_data = ENCODER_MISALIGNED;
180
                else if((left_data_buf & MagINCn) && (left_data_buf & MagDECn))
181
                        left_data = ENCODER_MAGNET_FAILURE;
182
                else left_data = (left_data_buf>>5) & 1023;
183
184
                /*Error handling for the right encoder*/
185
                 if(!(right_data_buf & OCF))
186
                        right_data = ENCODER_DATA_NOT_READY;
187
                if(right_data_buf & (COF | LIN))
188
                        right_data = ENCODER_MISALIGNED;
189
                else if ((right_data_buf & MagINCn)  && (right_data_buf & MagDECn))
190
                        right_data = ENCODER_MAGNET_FAILURE;
191
                else right_data = (right_data_buf>>5) & 1023;
192
193
                  left_data_buf = 0;
194
                right_data_buf = 0;
195
196
                /*Note: Above 1023 is invalid data*/
197
                if(!(left_data > 1023)) {
198 870 justin
                        //Reverse the left wheel since encoders are necessarily mounted backwards.
199
                        left_data = 1023 - left_data;
200 868 justin
                        left_data_array_put(left_data);
201
202
                        //Adjust left accumulator
203
                        dx = left_data - left_data_array_prev();
204
205
                        //Adjust velocity: save last dx
206
                        left_v = left_dx;
207
208
                        if(left_data_array_prev()==0)  dx=0;
209
210
                        if(dx > 512) left_dx += dx - 1023; //Underflow
211
                        else if(dx < -512) left_dx += dx + 1023; //Overflow
212
                        else left_dx += dx;
213
214
                        //Adjust velocity: update
215
                        left_v = left_dx - left_v;
216
                }
217
218
                /*Above 1023 is invalid data*/
219
                if(!(right_data > 1023)) {
220
                        right_data_array_put(right_data);
221
222
                        //Adjust right accumulator
223
                        dx = right_data - right_data_array_prev();
224
225
                        if(right_data_array_prev()==0) dx=0;
226
227
                        if(dx > 512) right_dx += dx - 1023; //underflow
228
                        else if(dx < -512) right_dx += dx + 1023; //overflow
229
                        else right_dx += dx;
230
                }
231
        }
232
233
        //Increment timecount accumulator
234
        timecount++;
235
}
236
237
238
//Helper Functions
239
inline void left_data_array_put(unsigned short int value) {
240
        if(left_data_idx == BUFFER_SIZE-1)
241
                left_data_idx = 0;
242
        else
243
                left_data_idx++;
244
        left_data_array[left_data_idx] = value;
245
}
246
247
inline unsigned int left_data_array_top(void) {
248
        return left_data_array[left_data_idx];
249
}
250
251
inline unsigned int left_data_array_prev(void) {
252
        if(left_data_idx == 0)
253
                return left_data_array[BUFFER_SIZE-1];
254
        else
255
                return left_data_array[left_data_idx - 1];
256
}
257
258
inline unsigned int left_data_array_bottom(void) {
259
        if(left_data_idx == BUFFER_SIZE-1)
260
                return left_data_array[0];
261
        else
262
                return left_data_array[left_data_idx + 1];
263
}
264
265
inline void right_data_array_put(unsigned short int value) {
266
        if(right_data_idx == BUFFER_SIZE-1)
267
                right_data_idx = 0;
268
        else
269
                right_data_idx++;
270
        right_data_array[right_data_idx] = value;
271
}
272
273
inline unsigned int right_data_array_top(void) {
274
        return right_data_array[right_data_idx];
275
}
276
277
inline unsigned int right_data_array_prev(void) {
278
        if(right_data_idx == 0)
279
                return right_data_array[BUFFER_SIZE-1];
280
        else
281
                return right_data_array[right_data_idx - 1];
282
}
283
284
inline unsigned int right_data_array_bottom(void) {
285
        if(right_data_idx == BUFFER_SIZE-1)
286
                return right_data_array[0];
287
        else
288
                return right_data_array[right_data_idx + 1];
289
}