Project

General

Profile

Revision 1493

wireless library branch

View differences:

branches/wireless/code/projects/libdragonfly/motor.c
1
/**
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 motor.c
29
 * @brief Motors
30
 *
31
 * Implementation of functions for controlling the motors.
32
 *
33
 * @author Colony Project, CMU Robotics Club
34
 * Much of this is taken from FWR's library, author: Tom Lauwers
35
 **/
36

  
37
#include "dragonfly_defs.h"
38
#include "motor.h"
39

  
40
/**
41
 * @defgroup motors Motors
42
 * @brief Functions for controlling the motors.
43
 * Functions for controlling the motors. Found in motor.h.
44
 * @{
45
 **/
46

  
47
unsigned char motors_initd=0;
48

  
49
/**
50
 * Initializes both motors so that they can be used with future
51
 * calls to motor1_set and motor2_set.
52
 *
53
 * @return 0 if init succesfull, an error code otherwise
54
 *
55
 * @see motors_off, motor1_set, motor2_set
56
 **/
57
int motors_init( void ) {
58

  
59
  if(motors_initd)
60
    return ERROR_INIT_ALREADY_INITD;
61

  
62

  
63
  // Configure counter such that we use phase correct
64
  // PWM with 8-bit resolution
65
  PORTA &= 0x0F;
66
  DDRA |= 0xF0;
67
  DDRB |= 0x60;
68

  
69
  //timer 1A and 1B
70
  TCCR1A = _BV(COM1A1) | _BV(COM1B1) | _BV(WGM10);
71
  TCCR1B = _BV(WGM12) | _BV(CS10);
72
  //	TCCR1A = 0xA1;
73
  //	TCCR1B = 0x04;
74
  OCR1AH=0;
75
  OCR1AL=0;
76
  OCR1BH=0;
77
  OCR1BL=0;
78

  
79
  motors_initd=1;
80
  return 0;
81
}
82

  
83
/**
84
 * Sets the speed and direction of the left motor.
85
 * motors_init must be called before this function can be used.
86
 *
87
 * @param direction Either FORWARD or BACKWARD to set the direction of rotation.
88
 * @param speed The speed the motor will run at, in the range 0-255.
89
 * 
90
 * @return 0 if init succesfull, an error code otherwise
91
 *
92
 * @see motor_r_set, motors_init
93
 **/
94
int motor_l_set(int direction, int speed) {
95
  if(!motors_initd)
96
    return ERROR_LIBRARY_NOT_INITD;
97

  
98
  if(direction == 0) {
99
    // turn off PWM first if switching directions
100
    if((PORTA & 0x30) != 0x10) {
101
      OCR1A = 0;
102
    }	
103
    PORTA = (PORTA & 0xCF) | 0x10;
104
    //		PORTD |= 0x10;
105
    //		PORTD &= 0xBF;
106
  } else {
107
    // turn off PWM first if switching directions
108
    if((PORTA & 0x30) != 0x20) {
109
      OCR1A = 0;
110
    }
111
    PORTA = (PORTA & 0xCF) | 0x20;
112
    //		PORTD |= 0x40;
113
    //		PORTD &= 0xEF;
114
  }
115
	
116
  // Set the timer to count up to speed, an 8-bit value
117
  OCR1AL = speed;
118

  
119
  return 0;
120
}
121

  
122
/**
123
 * Sets the speed and direction of the right motor.
124
 * motors_init must be called before this function can be used.
125
 *
126
 * @param direction Either FORWARD or BACKWARD to set the direction of rotation.
127
 * @param speed The speed the motor will run at, in the range 0-255.
128
 *
129
 * @return 0 if init succesfull, an error code otherwise
130
 *
131
 * @see motor_l_set, motors_init
132
 **/
133
int motor_r_set(int direction, int speed) {
134
  if(!motors_initd)
135
    return ERROR_LIBRARY_NOT_INITD;
136

  
137
  if(direction == 0) {
138
    //		PORTD |= 0x20;
139
    //		PORTD &= 0x7F;
140
    // turn off PWM first if switching directions
141
    if((PORTA & 0xC0) != 0x80) {
142
      OCR1B = 0;
143
    }		
144
		
145
    PORTA = (PORTA & 0x3F) | 0x80;
146
  } else {
147
    //		PORTD |= 0x80;
148
    //		PORTD &= 0xDF;
149

  
150
    // turn off PWM first if switching directions
151
    if((PORTA & 0xC0) != 0x40) {
152
      OCR1B = 0;
153
    }		
154
		
155
    PORTA = (PORTA & 0x3F) | 0x40;
156
  }
157
  OCR1BL = speed;
158

  
159
  return 0;
160
}
161

  
162
/**
163
 * Sets the speed and direction of motor1.
164
 * motors_init must be called before this function can be used.
165
 *
166
 * @param direction Either FORWARD or BACKWARD to set the direction of rotation.
167
 * @param speed The speed the motor will run at, in the range 0-255.
168
 *
169
 * @return 0 if init succesfull, an error code otherwise
170
 *
171
 * @see motor2_set, motors_init
172
 **/
173
int motor1_set(int direction, int speed) {
174
  return motor_l_set(direction, speed);
175
}
176

  
177
/**
178
 * Sets the speed and direction of motor2.
179
 * motors_init must be called before this function can be used.
180
 *
181
 * @param direction Either FORWARD or BACKWARD to set the direction of rotation.
182
 * @param speed The speed the motor will run at, in the range 0-255.
183
 *
184
 * @return 0 if init succesfull, an error code otherwise
185
 *
186
 * @see motor2_set, motors_init
187
 **/
188
int motor2_set(int direction, int speed) {
189
  return motor_r_set(direction, speed);
190
}
191

  
192

  
193
/**
194
 * Turns off both motors.
195
 *
196
 * @return 0 if init succesfull, an error code otherwise
197
 *
198
 * @see motors_init
199
 **/
200
int motors_off( void ) {
201
  if(!motors_initd)
202
    return ERROR_LIBRARY_NOT_INITD;
203

  
204
  OCR1AL = 0x0;
205
  OCR1BL = 0x0;
206

  
207
  return 0;
208
}
209

  
210
/**@}**///end defgroup
211

  
branches/wireless/code/projects/libdragonfly/motor.h
1
/**
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 motor.h
29
 * @brief Contains definitions for controlling the motors
30
 *
31
 * Contains definitions and functions for controlling
32
 * the motors.
33
 *
34
 * @author Colony Project, CMU Robotics Club
35
 * Based on Tom Lauwer's Firefly Library
36
 **/
37

  
38
#ifndef _MOTOR_H
39
#define _MOTOR_H
40

  
41
#include <avr/io.h>
42

  
43
/**
44
 * @addtogroup motors
45
 * @{
46
 **/
47

  
48
/** @brief make the motors go forwards **/
49
#define FORWARD 1
50
/** @brief make the motors go backwards **/
51
#define BACKWARD 0
52

  
53
/** @brief Initialize the motors **/
54
int motors_init(void);
55
/** @brief Set speed and direction of motor1 
56
 *  @deprecated use the left motor function instead. it's more intuitive and easier to read.**/
57
int motor1_set(int direction, int speed);
58
/** @brief Set speed and direction of motor2 
59
 *  @deprecated use the right motor function instead. it's more intuitive and easier to read.**/
60
int motor2_set(int direction, int speed);
61
/** @brief Set speed and direction of left motor **/
62
int motor_l_set(int direction, int speed);
63
/** @brief Set speed and direction of right motor **/
64
int motor_r_set(int direction, int speed);
65
/** @brief Turn the motors off **/
66
int motors_off(void);
67

  
68
/**@}**/ // end addtogroup
69

  
70
#endif
71

  
branches/wireless/code/projects/libdragonfly/serial.c
1
/**
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 serial.c
29
 * @brief Serial Input and Output
30
 *
31
 * Implementation of functions for serial input and output.
32
 *
33
 * @author Colony Project, CMU Robotics Club
34
 **/
35

  
36
#include <avr/io.h>
37

  
38
#include "dragonfly_defs.h"
39
#include "serial.h"
40

  
41
unsigned char usb_initd=0;
42
unsigned char xbee_initd=0;
43

  
44
#ifdef USE_STDIO
45

  
46
#include <stdio.h>
47

  
48
/**
49
 * For use with fprintf() and related stdio functions
50
 **/
51
FILE *usb_fd;
52

  
53
/**
54
 * For use with fprintf() and related stdio functions
55
 **/
56
FILE *xbee_fd;
57

  
58
#endif
59

  
60
/**
61
 * Initializes communication over the USB serial port.
62
 * This must be called before any other usb function
63
 * may be used.
64
 **/
65
int usb_init() {
66
  //Set baud rate
67
  // - 115200 (both wired and wireless) is UBRR=8, U2X=1
68
  // - 9600 is U2X =1, UBRR = 107.
69

  
70
  if(usb_initd) {
71
    return ERROR_INIT_ALREADY_INITD;
72
  }
73

  
74
#if (USB_BAUD == 115200)
75
  UBRR0H = 0x00;
76
  UBRR0L = 8;
77
  UCSR0A |= _BV(U2X0);
78
#elif (USB_BAUD == 9600)
79
  UBRR0H = 0x00;
80
  UBRR0L = 103;
81
  UCSR0A |= _BV(U2X0);
82
#else //Baud rate is defined in the header file, we should not get here
83
  return 0;
84
#endif
85

  
86
  /*Enable receiver and transmitter */
87
  UCSR0B |= (1<<RXEN0)|(1<<TXEN0);
88
	
89
  /* Set frame format: 8data, 1stop bit, asynchronous normal mode */
90
  UCSR0C |= (1<<UCSZ00) | (1<<UCSZ01);
91
  
92
  // if we have enabled the stdio stuff, then we init it here
93
#ifdef USE_STDIO
94
  /* Open the stdio stream corresponding to this port */
95
  usb_fd = fdevopen(usb_putc, usb_getc);
96
#endif
97

  
98
  usb_initd = 1;
99
  return 0;
100

  
101
}
102

  
103
/**
104
 * Initializes communication over the XBee.
105
 * This must be called before any other xbee function
106
 * may be used.
107
 **/
108
int xbee_init() {
109

  
110
  if(xbee_initd) {
111
    return ERROR_INIT_ALREADY_INITD;
112
  }
113

  
114
  //Set baud rate
115
  // - 115200 (both wired and wireless) is UBRR=8, U2X=1
116
  // - 9600 is U2X =1, UBRR = 107.
117
#if (XBEE_BAUD == 115200)
118
  UBRR1H = 0x00;
119
  UBRR1L = 8;
120
  UCSR1A |= _BV(U2X1);
121
#elif (XBEE_BAUD == 9600)
122
  UBRR1H = 0x00;
123
  UBRR1L = 103;
124
  UCSR1A |= _BV(U2X1);
125
#else //Baud rate is defined in the header file, we should not get here
126
  return 0;
127
#endif
128

  
129
  //Enable receiver and transmitter
130
  UCSR1B |= (1<<RXEN1)|(1<<TXEN1);
131
	
132
  // Set frame format: 8data, 1stop bit, asynchronous normal mode
133
  UCSR1C |= (1<<UCSZ10) | (1<<UCSZ11);
134
  
135
  // if we have enabled the stdio stuff, then we init it here
136
#ifdef USE_STDIO
137
  /* Open the stdio stream corresponding to this port */
138
  xbee_fd = fdevopen(xbee_putc, xbee_getc);
139
#endif
140

  
141
  xbee_initd = 1;
142
  return 0;
143

  
144
}
145

  
146
/**
147
 * Sends a character over USB.
148
 *
149
 * @param c the character to send
150
 * @return 0 for success, nonzero for failure
151
 **/
152
int usb_putc(char c) {
153

  
154
  if(!usb_initd)
155
    return ERROR_LIBRARY_NOT_INITD;
156

  
157
  // Wait until buffer is clear for sending
158
  loop_until_bit_is_set(UCSR0A, UDRE0);
159
	
160
  // Load buffer with your character
161
  UDR0 = c;
162
  return 0;
163
}
164

  
165
/**
166
 * Sends a character to the XBee.
167
 *
168
 * @param c the character to send
169
 * @return 0 for success, nonzero for failure
170
 **/
171
int xbee_putc(char c) {
172

  
173
  if(!xbee_initd)
174
    return ERROR_LIBRARY_NOT_INITD;
175

  
176
  // Wait until buffer is clear for sending
177
  loop_until_bit_is_set(UCSR1A, UDRE1);
178
	
179
  // Load buffer with your character
180
  UDR1 = c;
181
  return 0;
182
}
183

  
184
/**
185
 * Sends a sequence of characters over USB.
186
 *
187
 * @param s the string to send
188
 * @return 0 for success, nonzero for failure
189
 **/
190
int usb_puts(char *s) {
191
  char *t = s;
192

  
193
  if(!usb_initd)
194
    return ERROR_LIBRARY_NOT_INITD;
195

  
196
  while (*t != 0) {
197
    usb_putc(*t);
198
    t++;
199
  }
200
  return 0;
201
}
202

  
203
/**
204
 * Sends a sequence of characters from program space over USB.
205
 *
206
 * @param s the string to send
207
 *
208
 * @return 0 if init succesfull, an error code otherwise
209
 **/
210
int usb_puts_P (PGM_P s) {
211
    char buf;
212

  
213
    if(!usb_initd)
214
      return ERROR_LIBRARY_NOT_INITD;
215
	
216
    while (memcpy_P (&buf, s, sizeof (char)), buf!=0) {
217
        usb_putc (buf);
218
        s++;
219
    }
220

  
221
    return 0;
222
}
223

  
224

  
225

  
226
/**
227
 * Returns the first character in the buffer received from USB.
228
 * This function blocks execution until a character has been received.
229
 * xbee_init must be called before this function may be used.
230
 * 
231
 * @return the first character in the usb buffer, -1 on error
232
 *
233
 * @see usb_init, usb_getc_nb
234
 **/
235
int usb_getc(void) {
236

  
237
  if(!usb_initd)
238
    return -1;
239

  
240
  // Wait for the receive buffer to be filled
241
  loop_until_bit_is_set(UCSR0A, RXC0);
242
	
243
  // Read the receive buffer
244
  return UDR0;
245
}
246

  
247
/**
248
 * Returns the first character in the buffer received from USB.
249
 * This function blocks execution until a character has been
250
 * received. xbee_init must be called before this function
251
 * may be used.
252
 * 
253
 * @return the first character in the xbee buffer, -1 on error
254
 * 
255
 * @see xbee_init, xbee_getc_nb
256
 **/
257
int xbee_getc(void) {
258

  
259
  if(!usb_initd)
260
    return -1;
261

  
262
  // Wait for the receive buffer to be filled
263
  loop_until_bit_is_set(UCSR1A, RXC1);
264
	
265
  // Read the receive buffer
266
  return UDR1;
267
}
268

  
269
/**
270
 * Non blocking version of usb_getc. If a character is present in the buffer,
271
 * it is returned, otherwise -1 is returned immediately. usb_init must be
272
 * called before this function can be used.
273
 *
274
 * @param c the received character. This will be set if a character has
275
 * been received.
276
 * 
277
 * @return -1 if no character is available, 0 otherwise, positive for error
278
 * 
279
 * @see usb_init, usb_getc
280
 **/
281
int usb_getc_nb(char *c) {
282

  
283
  if(!usb_initd)
284
    return ERROR_LIBRARY_NOT_INITD;
285

  
286
  // check if the receive buffer is filled
287
  if (UCSR0A & _BV(RXC0)) {
288
    // Read the receive buffer
289
    (*c) = UDR0;
290
    return 0;
291
  } else {
292
    // Return empty
293
    return -1;
294
  }
295
}
296

  
297
/**
298
 * Non blocking version of xbee_getc. If a character is present in the buffer,
299
 * it is returned, otherwise -1 is returned immediately. xbee_init
300
 * must be called before this function can be used.
301
 *
302
 * @param c the received character. This will be set if a character has
303
 * been received.
304
 * 
305
 * @return -1 if no character is available, 0 otherwise, positive for error
306
 *
307
 * @see xbee_init, xbee_getc
308
 **/
309
int xbee_getc_nb(char *c) {
310
  if(!xbee_initd)
311
    return ERROR_LIBRARY_NOT_INITD;
312

  
313
  // check if the receive buffer is filled
314
  if (UCSR1A & _BV(RXC1)) {
315
    // Read the receive buffer
316
    (*c) = UDR1;
317
    return 0;
318
  } else {
319
    // Return empty
320
    return -1;
321
  }
322
}
323

  
324

  
325
/*
326
  prints an int to serial
327

  
328
  code adapted from Chris Efstathiou's code (hendrix@otenet.gr)
329
  uses usb_putc
330
*/
331
/**
332
 * Prints an integer, converted to ASCII, to usb. usb_init must be called
333
 * before this function can be used.
334
 *
335
 * @param value the integer to print
336
 * 
337
 * @return 0 if successful, nonzero otherwise
338
 *
339
 * @see usb_init, usb_putc
340
 **/
341
int usb_puti(int value ) {
342
  unsigned char usb_data[6]={'0','0','0','0','0','0' }, position=sizeof(usb_data), radix=10; 
343

  
344
  if(!usb_initd)
345
    return ERROR_LIBRARY_NOT_INITD;
346

  
347

  
348
  /* convert int to ascii  */ 
349
  if(value<0) { 
350
    usb_putc('-'); 
351
    value=-value; 
352
  }    
353
  do { 
354
    position--; 
355
    *(usb_data+position)=(value%radix)+'0'; 
356
    value/=radix;  
357
  } while(value); 
358

  
359
    
360
  /* start displaying the number */
361
  for(;position<=(sizeof(usb_data)-1);position++) {
362
            
363
    usb_putc(usb_data[position]);
364
  }
365

  
366
  return 0;
367
}
368

  
369
/**
370
 * Determines a hexadecimal digit in ASCII code.
371
 *
372
 * @param value the value of the digit (0<=value<=15)
373
 * 
374
 * @return the hexadecimal digit in ASCII code, or '?'
375
 * if the input is invalid.
376
 **/
377
uint8_t hex_digit (uint8_t value)
378
{
379
    if (value>15) return '?';
380
    // Postcondition: 0<=x<=15
381

  
382
    return "0123456789ABCDEF"[value];
383
}
384

  
385
/**
386
 * Prints a fixed width hexadecimal representation of an unsigned
387
 * 16 bit integer in ASCII code to USB.
388
 * usb_init must be called before this function can be used.
389
 *
390
 * @param value the value to print
391
 * 
392
 * @see usb_init, usb_puti, usb_puts, usb_puth8, hex_digit
393
 *
394
 * @return 0 if init succesfull, an error code otherwise
395
 **/
396
int usb_puth16 (uint16_t value)
397
{
398
    if(!usb_initd)
399
      return ERROR_LIBRARY_NOT_INITD;
400

  
401
    usb_putc (hex_digit((value >>12)&0xF));
402
    usb_putc (hex_digit((value >>8 )&0xF));
403
    usb_putc (hex_digit((value >>4 )&0xF));
404
    usb_putc (hex_digit( value      &0xF));
405

  
406
    return 0;
407
}
408

  
409
/**
410
 * Prints a fixed width hexadecimal representation of an unsigned
411
 * 8 bit integer in ASCII code to USB.
412
 * usb_init must be called before this function can be used.
413
 *
414
 * @param value the value to print
415
 * 
416
 * @see usb_init, usb_puti, usb_puts, usb_puth16, hex_digit
417
 *
418
 * @return 0 if init succesfull, an error code otherwise
419
 **/
420
int usb_puth8(uint8_t value)
421
{
422
    if(!usb_initd)
423
      return ERROR_LIBRARY_NOT_INITD;
424

  
425
    usb_putc (hex_digit ((value)>>4 &0xF));
426
    usb_putc (hex_digit ( value     &0xF));
427

  
428
    return 0;
429
}
430

  
branches/wireless/code/projects/libdragonfly/dragonfly_lib.h
1
/**
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 dragonfly_lib.h
29
 * @brief Contains other include files
30
 * 
31
 * Include this file for all the functionality of libdragonfly.
32
 *
33
 * @author Colony Project, CMU Robotics Club
34
 **/
35

  
36
#ifndef _DRAGONFLY_LIB_H_
37
#define _DRAGONFLY_LIB_H_
38

  
39
/**
40
 * @addtogroup dragonfly
41
 * @{
42
 **/
43

  
44
/** @brief Initialize the board **/
45
void dragonfly_init(int config);
46

  
47
/** @} **/ //end addtogroup
48

  
49
#include <inttypes.h>
50
#include <avr/io.h>
51
#include <avr/interrupt.h>
52
#include <util/delay.h>
53
#include <util/twi.h>
54

  
55
// This file is included from the libdragonfly directory because it seems to be
56
// missing from the AVR libc distribution.
57
#include "atomic.h"
58

  
59
#include "dragonfly_defs.h"
60
#include "analog.h"
61
#include "dio.h"
62
#include "time.h"
63
#include "lcd.h"
64
#include "lights.h"
65
#include "motor.h"
66
#include "serial.h"
67
#include "buzzer.h"
68
#include "rangefinder.h"
69
#include "bom.h"
70
#include "encoders.h"
71
#include "move.h"
72
#include "reset.h"
73
#include "math.h"
74
#include "eeprom.h"
75

  
76
#include <stddef.h>
77
#include <stdbool.h>
78

  
79
#endif
80

  
branches/wireless/code/projects/libdragonfly/serial.h
1
/**
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 serial.h
29
 * @brief Contains declarations for serial input and output
30
 *
31
 * Contains definitions for serial input and output.
32
 *
33
 * @author Colony Project, CMU Robotics Club
34
 * Based on Tom Lauwer's Firefly Library
35
 *
36
 **/
37

  
38
/*
39
  serial.h - Contains definitions and function prototypes for the RS232 serial port
40
  author(s): pkv
41
  
42
  Directions:
43
  Call the initialization function for the serial port you wish to use.  Then, use
44
  either the provided functions or the stdio functions (fprintf, etc) to read and
45
  write characters to the serial ports.
46
  
47
  UART Mapping:
48
  usb_*() -> UART0
49
  xbee_*() -> UART1
50
  
51
  Options: (Add the following defines to your code to configure this library)
52
  #define USB_BAUD { 115200 | 9600 } <= pick ONE value from in here
53
  #define XBEE_BAUD { 115200 | 9600 } <= pick ONE value from in here
54
  #define USE_STDIO
55
  
56
  Note: If you enable USE_STDIO, the first init function that is called will 
57
  automatically be linked to stdin, stdout, and stderr.  To use the baud rate 
58
  commands, add something like the following to your code:
59
  
60
  #define FOO_BAUD 9600
61
  
62
  **UNLESS YOU KNOW WHAT YOU ARE DOING, PLEASE DO NOT CHANGE THIS FILE**
63
  Many, many other people use this file in their code.  If you change it, you will
64
  probably break all of their nice code.  You should not need to change anything in
65
  here, except to accomodate new hardware.
66
*/
67

  
68
#ifndef _SERIAL_H
69
#define _SERIAL_H
70

  
71
#include <inttypes.h>
72
#include <avr/pgmspace.h>
73

  
74
/**
75
 * @defgroup usb USB Input / Output
76
 * @brief Functions for USB input / output
77
 *
78
 * Low level functions for USB input and output.
79
 *
80
 * @{
81
 **/
82

  
83
// if no baud rate is defined for usb, default is set here
84
#ifndef USB_BAUD
85
/** @brief the USB baud rate **/
86
#define USB_BAUD 115200
87
#endif
88

  
89
/** @brief Initialize the USB **/
90
int usb_init(void);
91
/** @brief Print a character to USB **/
92
int usb_putc(char c);
93
/** @brief Read a character from USB **/
94
int usb_getc(void);
95
/** @brief Read a character from USB without blocking **/
96
int usb_getc_nb(char *c);
97
/** @brief Print a string to USB **/
98
int usb_puts(char *s);
99
/** @brief Print a string from program space to USB **/
100
int usb_puts_P (PGM_P s);
101
/** @brief Print an integer to USB **/
102
int usb_puti(int value);
103
/** @brief Determine a hexadecimal digit **/
104
uint8_t hex_digit (uint8_t value);
105
/** @brief Print a fixed width hexadecimal representation to USB **/
106
int usb_puth16 (uint16_t value);
107
/** @brief Print a fixed width hexadecimal representation to USB **/
108
int usb_puth8(uint8_t value);
109
/** @brief Alias for usb_puth16 **/
110
static inline void usb_puth (uint16_t value) { usb_puth16 (value); };
111

  
112

  
113
/** @} **/ //end addtogroup
114

  
115
/**
116
 * @defgroup xbee XBee Input / Output
117
 * @brief Functions for XBee input / output
118
 *
119
 * Low level functions for XBee input and output.
120
 *
121
 * @{
122
 **/
123

  
124
// if no baud rate is defined for usb, default is set here
125

  
126
// if no baud rate is defined for xbee, default is set here
127
#ifndef XBEE_BAUD
128
/** @brief the XBee baud rate **/
129
#define XBEE_BAUD 9600
130
#endif
131

  
132
/** @brief Initialize the XBee **/
133
int xbee_init(void);
134
/** @brief Print a character to the XBee **/
135
int xbee_putc(char c);
136
/** @brief Read a character from the XBee **/
137
int xbee_getc(void);
138
/** @brief Read a character from the XBee without blocking **/
139
int xbee_getc_nb(char *c);
140

  
141

  
142

  
143
/** @} **/ //end addtogroup
144

  
145
#endif
146

  
branches/wireless/code/projects/libdragonfly/spi.c
1
/**
2
 * @file spi.c
3
 * @brief Basic SPI module to handle encoders
4
 * @author Colony Project, CMU Robotics Club
5
 *	Need to move spi.h include into dragonfly_lib.h when stable
6
 **/
7

  
8
#include <avr/interrupt.h>
9

  
10
#include "dragonfly_defs.h"
11
#include "spi.h"
12

  
13
unsigned char spi_initd=0;
14

  
15
static volatile char spi_bytes; /* number of bytes to read */
16
static spi_fun_recv_t spi_recv_func; /* byte handler */
17
static spi_fun_recv_complete_t spi_recv_complete_func; /*transmission completion handler */
18

  
19
/** 
20
* @brief Initialize SPI hardware for communication.
21
* 
22
* @param recv_func The function to be called for each byte of data received.
23
* @param recv_complete_func  The function to be called at the end of a complete transmission.
24
*
25
* @return 0 if init succesfull, an error code otherwise
26
*/
27
int spi_init (spi_fun_recv_t recv_func, spi_fun_recv_complete_t recv_complete_func)
28
{
29
    if(spi_initd) {
30
      return ERROR_INIT_ALREADY_INITD;
31
    }
32

  
33
    /*  Enable Interrupt, Enable SPI Module, MSB First, Master Mode, Clock div = 64 */
34
    SPCR = _BV(SPE) | _BV(SPIE) /*| _BV(DORD)*/ | _BV(MSTR) | _BV(SPR1) | _BV(SPR0);
35
    SPSR = _BV(SPI2X); 
36

  
37
    /* Set SCLK, SS, MOSI as outputs. MISO as input */
38
    DDRB |= MOSI | SCLK | SS;
39
    DDRB &= ~MISO;
40
    
41
    /* Keep SS high until transmit */
42
    PORTB |= SS;
43

  
44
    /* set function to be executed when we receive a byte */
45
    spi_recv_func = recv_func;
46
    spi_recv_complete_func = recv_complete_func;
47
    spi_bytes = 0;
48
    //usb_puts("\tspi.c Debug: SPI INITIALIZED\n");
49

  
50
    spi_initd=1;
51
    return 0;
52
}
53

  
54
/** 
55
* @brief Transfer a given byte to slave and receive a byte 
56
* 
57
* @param bytes The number of bytes to be transferred.
58
**/
59
int spi_transfer(char bytes)
60
{
61
    if(!spi_initd)
62
      return ERROR_LIBRARY_NOT_INITD;
63

  
64
    spi_bytes = bytes;
65
    PORTB &= ~SS; /* Set SS low to initiate transmission */
66
    SPDR = 0xff; /* Initiate data transmision */
67

  
68
    return 0;
69
}
70

  
71
ISR(SIG_SPI) 
72
{
73
	//usb_puts("Interrupt");
74
    /* only handle intterupt when we are expecting data */
75
    if(spi_bytes > 0){
76
	/* process byte */
77
	spi_recv_func(SPDR);
78
	/* if we've read all the bytes, set SS high to end transmission,
79
	 * otherwise get the next byte  */
80
	if(--spi_bytes == 0){
81
		//usb_puts("Read all bytes\r\n");
82
		PORTB |= SS;
83
		if(spi_recv_complete_func)
84
			spi_recv_complete_func();
85
	}else {
86
		//usb_puts("There are this many bytes left: "); usb_puti(spi_bytes);usb_puts("\r\n");
87
		SPDR = 0xff;
88
	}
89
    }
90
}		
branches/wireless/code/projects/libdragonfly/time.c
1
/**
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 time.c
29
 * @brief Timer code
30
 *
31
 * Implementation of functions for timers.
32
 *
33
 * @author Colony Project, CMU Robotics Club
34
 **/
35

  
36
/*
37
  time.c
38
  anything that requires a delay
39
  mostly delay_ms
40

  
41
  author: Robotics Club, Colony Project
42

  
43
  Change Log:
44
  2.5.07 - Kevin
45
  Aaron fixed the orb/servo code and made them use timer3 but compare registers B and C. He hard set the prescaler
46
  to 8 so the RTC broke. Changed it so that we use a 8 prescaler which sets the compare match at 1/16th of a second.
47
  You now count how many 16ths of a second you want until you trigger your actual interrupt. Works. Changed defines
48
  for time so you can still call rtc_init with a scale but now it is defined in terms of actual time like second, quarter_second
49
  etc. Read that section in the time.h file for more information. Tested and works, though the clock drifts more than
50
  it used to
51
  1.30.07 - Kevin
52
  Modified the clock to run on timer3 on the Dragonfly. Works with decent accuracy. Using a prescaler of 256
53
  the timer counts up to a precomputer value which will trigger an interrupt and reset the timer. Multiples of
54
  256 change it by that multiple. Refer to the time.h file for all possible prescalers.
55
  The interrupt will call a specified function _rtc_func every pulse.
56
  All of it has been tested and it works.
57

  
58
*/
59
#include <avr/interrupt.h>
60
#include <util/delay.h>
61

  
62
#include "dragonfly_defs.h"
63
#include "time.h"
64

  
65

  
66
/* Calculate how many cycles to delay for to get 1 ms. Based on F_CPU which should be defined by the makefile */
67
#ifdef F_CPU
68
#define WAIT_CYCLES ((F_CPU / 1000) / 10)
69
#else
70
#define WAIT_CYCLES (8000 / 10)
71
#endif
72

  
73

  
74
unsigned char time_initd = 0;
75

  
76
static volatile int _rtc_val = 0;
77
static volatile int _rtc_pulse = 0;
78
static volatile int _rtc_scale = 32;	//Defaults to 1 Second per pulse
79
static void (*_rtc_f)(void) = 0;
80

  
81

  
82

  
83
/**
84
 * @defgroup time Time
85
 * @brief Time functions
86
 * 
87
 * Functions dealing with time.
88
 * 
89
 * @{
90
 **/
91

  
92
/**
93
 * Delays for the specified number of milliseconds.
94
 * It depends on F_CPU to be defined in order to calculate how many cycles
95
 * it should delay. If it is not defined, a default clock of 8MHz is assumed.
96
 * 
97
 * We use _delay_loop_2 which will run assembly instructions that should be
98
 * 4 cycles long. Optimizations must be enabled for this to be true.
99
 * That function is called to ensure around 1ms per execution. To generate
100
 * multiple ms we run a for loop of how many milliseconds are desired.
101
 *
102
 * The error should be just the skew on the oscillator as the formula to 
103
 * calculate delay cycles should always be a whole number. The is some skew
104
 * in practice though it is unavoidable. Delaying for less than 1s should make
105
 * the error negligable.
106
 *
107
 * @param ms the number of milliseconds to delay for
108
 **/
109
void delay_ms(int ms) {
110
    for (; ms > 0; ms--) {
111
        _delay_loop_2(WAIT_CYCLES);
112
    }
113
}
114

  
115

  
116
/* 	Prescales defined in time.h. SECOND will give you 1 second.
117
	More scales are defined in the time.h file.
118
	rtc_func is the address to a function that you want called every clock tick. */
119
/**
120
 * Initializes the real time clock. Prescales are defined in time.h.
121
 * For example, SECOND will give 1 second. The specified function is
122
 * called every clock tick. For the real time clock to activate,
123
 * interrupts must be enabled. (through sei() )
124
 *
125
 * @param prescale_opt the period with which the timer is triggered
126
 * @param rtc_func the function called when the timer is triggered
127
 *
128
 * @return 0 if init succesfull, an error code otherwise
129
 *
130
 * @see rtc_get, rtc_reset
131
 *
132
 **/
133
int rtc_init(int prescale_opt, void (*rtc_func)(void)) {
134

  
135
  if(time_initd) {
136
    return ERROR_INIT_ALREADY_INITD;
137
  }
138
	
139
  //Clear timer register for Timer 3
140
  TCNT3 = 0;
141
	
142
  /* 	This sets the Waveform Generation Module to CTC (Clear Timer on Compare) Mode (100)
143
	See page135 in Atmega128 Docs for more modes and explanations */
144
  TCCR3B |= _BV(WGM32);
145
	
146
  /* 	This sets the prescaler for the system clock (8MHz) ie: divides the clock by some number.
147
	Currently set to a prescaler of 8 because that is what the orb and servos use (they are on this timer as well)
148
	See page137 in Atemga128 Docs for all the available prescalers */
149
  TCCR3B |= _BV(CS31);
150
	
151
  /* 	Sets the two regsiters that we compare against. So the timer counts up to this number and
152
	then resets back to 0 and calls the compare match interrupt.
153
	8x10^6 / 8 = 1/16 Second. All values are based off of this number. Do not change it unless you
154
	are l337*/
155
		
156
  OCR3A = 0xF424;	
157

  
158
  /* 	Enable Output Compare A Interrupt. When OCR3A is met by the timer TCNT3 this interrupt will be
159
	triggerd. (See page140 in Atmega128 Docs for more information */
160
  ETIMSK |= _BV(OCIE3A);
161
	
162
  /*	Store the pointer to the function to be used in the interrupt */
163
  _rtc_f = rtc_func;
164
	
165
  /*	Store how many 1/16ths of a second you want to let by before triggering an interrupt */
166
  _rtc_scale = prescale_opt;
167

  
168
  time_initd = 1;
169

  
170
  return 0;
171
}
172

  
173
/**
174
 * Returns the time elapsed in seconds since the last call to
175
 * rtc_init or rtc_reset.
176
 *
177
 * @return the number of seconds since the last call to rtc_init or rtc_reset
178
 *
179
 * @see rtc_init, rtc_reset
180
 **/
181
int rtc_get(void) {
182
  return _rtc_val;
183
}
184

  
185
/**
186
 * Resets the real time clock counter to 0.
187
 *
188
 * @see rtc_init, rtc_get
189
 **/
190
void rtc_reset(void) {
191
  _rtc_val = 0;
192
}
193

  
194
/** @} **/ //end defgroup
195

  
196
/*	Called every pulse. Function in _rtc_f is called every _rtc_scale and also the counter is updated.
197
	Bascially, since the pulse is hard set at 1/16s  you want to count how many 16ths of a second have passed
198
	and when it reaches the amount of time you want, execute the code. */
199
SIGNAL(TIMER3_COMPA_vect) {
200

  
201
  if (_rtc_pulse ==  _rtc_scale) {
202
    //Increment the real time clock counter
203
    _rtc_val++;
204
		
205
    //Calls the function tied to the real time clock if defined
206
    if(_rtc_f != 0)
207
      _rtc_f();
208
		
209
    //Resets the pulse until the next scale is matched
210
    _rtc_pulse = 0;
211
  }	
212
	
213
  //Updates the amount of pulses seen since the last scale match
214
  _rtc_pulse++;
215
	
216
}
branches/wireless/code/projects/libdragonfly/spi.h
1
/**
2
 * @file spi.h
3
 * @brief Definitions for SPI
4
 * @author Colony Project, CMU Robotics Club
5
 **/
6

  
7
/**
8
 * @addtogroup spi
9
 * @{
10
 **/
11

  
12
#ifndef __SPI_H__
13
#define __SPI_H__
14

  
15
#define DOUBLE_SCK 1
16
#define SPR0_BIT 1
17

  
18
#define MASTER 1
19
#define SLAVE 0
20

  
21
#define MOSI _BV(PB2)
22
#define MISO _BV(PB3)
23
#define SS   _BV(PB0)
24
#define SCLK _BV(PB1)
25

  
26
typedef int (*spi_fun_recv_t)(char);
27
typedef void (*spi_fun_recv_complete_t)(void);
28

  
29
/** 
30
* @brief Initialize SPI
31
* 
32
* @param spi_fun_recv_t The function that handles SPI data, byte for byte.
33
* @param spi_fun_recv_complete_t  Called on a completed transmission - typically for cleaning up.
34
*/
35
int spi_init (spi_fun_recv_t, spi_fun_recv_complete_t);
36

  
37
/** 
38
* @brief Initialize SPI transfer.
39
* 
40
* @param char The number of bytes to transfer.
41
*/
42
int spi_transfer (char);
43

  
44
/**@}**/ //end group
45

  
46
#endif
branches/wireless/code/projects/libdragonfly/analog.c
1
/**
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
 * @file analog.c
28
 * @brief Analog input and output
29
 *
30
 * Contains functions for manipulating the ADC on the Dragonfly board.
31
 * 
32
 * @author Colony Project, CMU Robotics Club
33
 * originally taken from fwr analog file (author: Tom Lauwers)
34
 * loop code written by Kevin Woo and James Kong
35
 **/
36

  
37
#include <util/delay.h>
38
#include <avr/interrupt.h>
39

  
40

  
41
#include "dragonfly_defs.h"
42
#include "serial.h"
43
#include "analog.h"
44
// Internal Function Prototypes
45
void set_adc_mux(int which);
46

  
47
/**
48
 * @defgroup analog Analog
49
 * Functions for manipulation the ADC on the dragonfly board.
50
 * All definitions may be found in analog.h.
51
 *
52
 * @{
53
 **/
54

  
55
unsigned char analog_initd=0;
56

  
57
volatile int adc_loop_status = ADC_LOOP_STOPPED;
58
volatile int adc_sig_stop_loop = 0;
59
volatile int adc_current_port = 0;
60
volatile adc_t an_val[11];
61

  
62
/**
63
 * Initializes the ADC.
64
 * Call analog_init before reading from the analog ports.
65
 *
66
 * @return returns 0 on success, nonzero on error
67
 *
68
 * @see analog8, analog10, analog_get8, analog_get10
69
 *
70
 * @bug First conversion takes a performance penalty of
71
 * 25 vs. 13 ADC clock cycles of successive conversions.
72
 * Analog_init should run a dummy conversion to pre-empt
73
 * this.
74
 *
75
 * For good 10-bit precision, ACD clock must be between
76
 * 50kHz and 200kHz. Currently, ADC clock is fixed at
77
 * 125kHz using 1/64prescalar. However, most code uses
78
 * 8-bit precision which can work at ADC clock speeds
79
 * higher than 200kHz. Experimental tests needed to
80
 * determine highest clock speed for accurate 8-bit ADC.
81
 *
82
 **/
83
int analog_init(int start_conversion) {
84
  if(analog_initd)
85
    return ERROR_INIT_ALREADY_INITD;
86

  
87
  for (int i = 0; i < 11; i++) {
88
    an_val[i].adc10 = 0;
89
    an_val[i].adc8 = 0;
90
  }
91

  
92
  // ADMUX register
93
  // Bit 7,6 - Set voltage reference to AVcc (0b01)
94
  // Bit 5 - ADLAR set to simplify moving from register
95
  // Bit 4 - X
96
  // Bit 3:0 - Sets the current channel
97
  // Initializes to read from AN1 first (AN0 is reservered for the BOM)
98
  ADMUX = 0;
99
  ADMUX |= ADMUX_OPT | _BV(MUX0);
100

  
101
  // ADC Status Register A
102
  // Bit 7 - ADEN is set (enables analog)
103
  // Bit 6 - Start conversion bit is set (must be done once for free-running mode)
104
  // Bit 5 - Enable Auto Trigger (for free running mode) NOT DOING THIS RIGHT NOW
105
  // Bit 4 - ADC interrupt flag, 0
106
  // Bit 3 - Enable ADC Interrupt (required to run free-running mode)
107
  // Bits 2-0 - Set to create a clock divisor of 128, to make ADC clock = 8,000,000/64 = 125kHz
108
  ADCSRA = 0;
109
  ADCSRA |= _BV(ADEN) | _BV(ADPS2) | _BV(ADPS1) | _BV(ADPS0);
110
	
111
  // Set external mux lines to outputs
112
  DDRG |= 0x1C;
113
	
114
  // Set up first port for conversions
115
  set_adc_mux(0x00);
116
  adc_current_port = AN1;
117

  
118
  //Start the conversion loop if requested
119
  if (start_conversion)
120
    analog_start_loop();
121
		
122
  //Conversion loop disabled by default
123

  
124
  analog_initd=1;
125
  return 0;
126
}	
127

  
128
/**
129
 * Returns the 8-bit analog conversion of which from
130
 * the lookup table. If the requested port is the BOM_PORT
131
 * you will get an automatic 0 since the BOM_PORT is not
132
 * read in the loop and not stored. If you need that port
133
 * you should use the functions in bom.c. There is an analog_get8
134
 * function which for instant lookups but should be avoided unless
135
 * you know what you're doing.
136
 *
137
 * @param which the port that you want to read
138
 *
139
 * @bug may cause a seg fault if which is a larger value
140
 * than exists in an_val table. Not sure if we should fix
141
 * this or not since it would add overhead.
142
 *
143
 * @return 8-bit analog value for the which port requested
144
 *
145
 * @see analog10, analog_get8, analog_get10
146
 **/
147
unsigned int analog8(int which) {
148
	if (which == BOM_PORT) {
149
		return 0;
150
	} else {
151
		return an_val[which - 1].adc8;
152
	}
153
}
154

  
155
/**
156
 * Returns the 10-bit analog conversion of which from
157
 * the lookup table. If the requested port is the BOM_PORT
158
 * you will get an automatic 0 since the BOM_PORT is not
159
 * read in the loop and not stored. If you need that port
160
 * you should use the functions in bom.c. There is an analog_get10
161
 * function which for instant lookups but should be avoided unless
162
 * you know what you are doing.
163
 *
164
 * @param which the port that you want to read
165
 *
166
 * @bug may cause a seg fault if which is a larger value
... This diff was truncated because it exceeds the maximum size that can be displayed.

Also available in: Unified diff