Revision 1461
updated all the library code to have sensible _init behavior.
Almost all of the library components have a global variable which gets set after init and the functions inside will fail with an error code if init has not been called. Also, the init functions themselves check this variable and will bail out without doing any damage if that init has already been called
trunk/code/lib/include/libdragonfly/spi.h | ||
---|---|---|
12 | 12 |
#ifndef __SPI_H__ |
13 | 13 |
#define __SPI_H__ |
14 | 14 |
|
15 |
#include<dragonfly_lib.h> |
|
16 |
|
|
15 | 17 |
#define DOUBLE_SCK 1 |
16 | 18 |
#define SPR0_BIT 1 |
17 | 19 |
|
... | ... | |
32 | 34 |
* @param spi_fun_recv_t The function that handles SPI data, byte for byte. |
33 | 35 |
* @param spi_fun_recv_complete_t Called on a completed transmission - typically for cleaning up. |
34 | 36 |
*/ |
35 |
void spi_init (spi_fun_recv_t, spi_fun_recv_complete_t);
|
|
37 |
int spi_init (spi_fun_recv_t, spi_fun_recv_complete_t);
|
|
36 | 38 |
|
37 | 39 |
/** |
38 | 40 |
* @brief Initialize SPI transfer. |
39 | 41 |
* |
40 | 42 |
* @param char The number of bytes to transfer. |
41 | 43 |
*/ |
42 |
void spi_transfer (char);
|
|
44 |
int spi_transfer (char);
|
|
43 | 45 |
|
44 | 46 |
/**@}**/ //end group |
45 | 47 |
|
trunk/code/lib/include/libdragonfly/time.h | ||
---|---|---|
37 | 37 |
#ifndef _TIME_H_ |
38 | 38 |
#define _TIME_H_ |
39 | 39 |
|
40 |
#include <dragonfly_lib.h> |
|
41 |
|
|
40 | 42 |
/* Predefined times for prescale_opt in time.c. |
41 | 43 |
To make you own, know that a pulse is 1/16th of a second. You cannot get less than this. To get more, you need |
42 | 44 |
to know how many 16ths of a second are in the time you want. (Time_desired * 16 = prescaler_opt) |
... | ... | |
63 | 65 |
/** @brief Delay execution for the specified time **/ |
64 | 66 |
void delay_ms(int ms) ; |
65 | 67 |
/** @brief Enable the realtime clock **/ |
66 |
void rtc_init(int prescale_opt, void (*rtc_func)(void));
|
|
68 |
int rtc_init(int prescale_opt, void (*rtc_func)(void));
|
|
67 | 69 |
/** @brief Reset the counter of the realtime clock **/ |
68 | 70 |
void rtc_reset(void); |
69 | 71 |
/** @brief Get the value of the realtime clock. **/ |
trunk/code/lib/include/libdragonfly/motor.h | ||
---|---|---|
38 | 38 |
#ifndef _MOTOR_H |
39 | 39 |
#define _MOTOR_H |
40 | 40 |
|
41 |
#include <dragonfly_lib.h> |
|
41 | 42 |
#include <avr/io.h> |
42 | 43 |
/** |
43 | 44 |
* @addtogroup motors |
... | ... | |
50 | 51 |
#define BACKWARD 0 |
51 | 52 |
|
52 | 53 |
/** @brief Initialize the motors **/ |
53 |
void motors_init(void);
|
|
54 |
int motors_init(void);
|
|
54 | 55 |
/** @brief Set speed and direction of motor1 |
55 | 56 |
* @deprecated use the left motor function instead. it's more intuitive and easier to read.**/ |
56 |
void motor1_set(int direction, int speed);
|
|
57 |
int motor1_set(int direction, int speed);
|
|
57 | 58 |
/** @brief Set speed and direction of motor2 |
58 | 59 |
* @deprecated use the right motor function instead. it's more intuitive and easier to read.**/ |
59 |
void motor2_set(int direction, int speed);
|
|
60 |
int motor2_set(int direction, int speed);
|
|
60 | 61 |
/** @brief Set speed and direction of left motor **/ |
61 |
void motor_l_set(int direction, int speed);
|
|
62 |
int motor_l_set(int direction, int speed);
|
|
62 | 63 |
/** @brief Set speed and direction of right motor **/ |
63 |
void motor_r_set(int direction, int speed);
|
|
64 |
int motor_r_set(int direction, int speed);
|
|
64 | 65 |
/** @brief Turn the motors off **/ |
65 |
void motors_off(void);
|
|
66 |
int motors_off(void);
|
|
66 | 67 |
|
67 | 68 |
/**@}**/ // end addtogroup |
68 | 69 |
|
trunk/code/lib/include/libdragonfly/analog.h | ||
---|---|---|
113 | 113 |
|
114 | 114 |
/** @brief Initialize analog ports. Will start running a loop |
115 | 115 |
if start_conversion is ADC_START.**/ |
116 |
void analog_init(int start_conversion);
|
|
116 |
int analog_init(int start_conversion);
|
|
117 | 117 |
/** @brief starts the analog loop. Doesn't do anything if the loop is already running. **/ |
118 |
void analog_start_loop(void);
|
|
118 |
int analog_start_loop(void);
|
|
119 | 119 |
/** @brief Stops the analog loop. Doesn't do anything if the loop is already stopped. **/ |
120 |
void analog_stop_loop(void);
|
|
120 |
int analog_stop_loop(void);
|
|
121 | 121 |
/** @brief Returns the status of the analog loop. **/ |
122 | 122 |
int analog_loop_status(void); |
123 | 123 |
/** @brief Returns an 8-bit analog value from the look up table. Use this instead of analog_get8. **/ |
trunk/code/lib/include/libdragonfly/encoders.h | ||
---|---|---|
51 | 51 |
#define MagINCn _BV(1) |
52 | 52 |
#define MagDECn _BV(0) |
53 | 53 |
|
54 |
#ifdef BUFFER_SIZE |
|
55 |
#error BUFFER_SIZE already defined! |
|
56 |
#endif |
|
57 |
|
|
54 | 58 |
/** @brief Buffer size **/ |
55 | 59 |
#define BUFFER_SIZE 46 |
56 | 60 |
|
57 | 61 |
#define ERR_VEL 1024 |
58 | 62 |
|
59 | 63 |
/** @brief Initialize encoders. **/ |
60 |
void encoders_init(void);
|
|
64 |
int encoders_init(void);
|
|
61 | 65 |
/** @brief Read instantaneous encoder value. **/ |
62 | 66 |
int encoder_read(char encoder); |
63 | 67 |
|
... | ... | |
72 | 76 |
/** @brief Get total distance traveled. **/ |
73 | 77 |
int encoder_get_dx(char encoder); |
74 | 78 |
/** @brief Reset distance counter. **/ |
75 |
void encoder_rst_dx(char encoder);
|
|
79 |
int encoder_rst_dx(char encoder);
|
|
76 | 80 |
/** @brief Get time count: The number of encoder reads that have occurred. **/ |
77 | 81 |
int encoder_get_tc(void); |
78 | 82 |
/** @brief Reset the time count. **/ |
79 |
void encoder_rst_tc(void);
|
|
83 |
int encoder_rst_tc(void);
|
|
80 | 84 |
|
81 | 85 |
/** @brief Waits for the next n encoder reading, then returns. **/ |
82 |
void encoder_wait( int nReadings );
|
|
86 |
int encoder_wait( int nReadings );
|
|
83 | 87 |
|
84 | 88 |
/**@}**/ //end group |
85 | 89 |
|
trunk/code/lib/include/libdragonfly/dragonfly_lib.h | ||
---|---|---|
41 | 41 |
* @{ |
42 | 42 |
**/ |
43 | 43 |
|
44 |
//return value definitions |
|
45 |
#define ERROR_INIT_FAILED 1 |
|
46 |
#define ERROR_INIT_ALREADY_INITD 2 |
|
47 |
|
|
48 |
#define ERROR_LIBRARY_NOT_INITD 3 |
|
49 |
|
|
44 | 50 |
// Configuration definitions |
45 | 51 |
/** @brief Initialize analog **/ |
46 | 52 |
#define ANALOG 0x01 |
trunk/code/lib/include/libdragonfly/bom.h | ||
---|---|---|
57 | 57 |
|
58 | 58 |
|
59 | 59 |
/** @brief Initialize the bom according to bom type **/ |
60 |
void bom_init(char type);
|
|
60 |
int bom_init(char type);
|
|
61 | 61 |
|
62 | 62 |
/** @brief Refresh bom_val[] with new values from analog8. analog_init and bom_init must be called for this to work. **/ |
63 |
void bom_refresh(int bit_field);
|
|
63 |
int bom_refresh(int bit_field);
|
|
64 | 64 |
|
65 | 65 |
/** @brief Gets the bom reading from bom_val[which]. Call bom_refresh beforehand to read new bom values. **/ |
66 | 66 |
int bom_get(int which); |
... | ... | |
72 | 72 |
int bom_get_max10(int *dist); |
73 | 73 |
|
74 | 74 |
/** @brief Enables the selected bom leds on a BOM1.5 **/ |
75 |
void bom_set_leds(int bit_field);
|
|
75 |
int bom_set_leds(int bit_field);
|
|
76 | 76 |
|
77 | 77 |
/** @brief (DEPRECATED) Gets and compares all bom values. Returns the index to the highest value element since last refresh. **/ |
78 | 78 |
int get_max_bom(void); |
79 | 79 |
|
80 | 80 |
/** @brief Turns on all BOM leds, or turns on enabled leds on a BOM1.5. **/ |
81 |
void bom_on(void);
|
|
81 |
int bom_on(void);
|
|
82 | 82 |
|
83 | 83 |
/** @brief Turns off all bom leds. **/ |
84 |
void bom_off(void);
|
|
84 |
int bom_off(void);
|
|
85 | 85 |
|
86 | 86 |
/** @} **/ |
87 | 87 |
|
trunk/code/lib/include/libdragonfly/serial.h | ||
---|---|---|
68 | 68 |
#ifndef _SERIAL_H |
69 | 69 |
#define _SERIAL_H |
70 | 70 |
|
71 |
#include <dragonfly_lib.h> |
|
71 | 72 |
#include <inttypes.h> |
72 | 73 |
#include <avr/pgmspace.h> |
73 | 74 |
|
... | ... | |
87 | 88 |
#endif |
88 | 89 |
|
89 | 90 |
/** @brief Initialize the USB **/ |
90 |
void usb_init(void);
|
|
91 |
int usb_init(void);
|
|
91 | 92 |
/** @brief Print a character to USB **/ |
92 | 93 |
int usb_putc(char c); |
93 | 94 |
/** @brief Read a character from USB **/ |
... | ... | |
97 | 98 |
/** @brief Print a string to USB **/ |
98 | 99 |
int usb_puts(char *s); |
99 | 100 |
/** @brief Print a string from program space to USB **/ |
100 |
void usb_puts_P (PGM_P s);
|
|
101 |
int usb_puts_P (PGM_P s);
|
|
101 | 102 |
/** @brief Print an integer to USB **/ |
102 | 103 |
int usb_puti(int value); |
103 | 104 |
/** @brief Determine a hexadecimal digit **/ |
104 | 105 |
uint8_t hex_digit (uint8_t value); |
105 | 106 |
/** @brief Print a fixed width hexadecimal representation to USB **/ |
106 |
void usb_puth16 (uint16_t value);
|
|
107 |
int usb_puth16 (uint16_t value);
|
|
107 | 108 |
/** @brief Print a fixed width hexadecimal representation to USB **/ |
108 |
void usb_puth8(uint8_t value);
|
|
109 |
int usb_puth8(uint8_t value);
|
|
109 | 110 |
/** @brief Alias for usb_puth16 **/ |
110 | 111 |
static inline void usb_puth (uint16_t value) { usb_puth16 (value); }; |
111 | 112 |
|
... | ... | |
130 | 131 |
#endif |
131 | 132 |
|
132 | 133 |
/** @brief Initialize the XBee **/ |
133 |
void xbee_init(void);
|
|
134 |
int xbee_init(void);
|
|
134 | 135 |
/** @brief Print a character to the XBee **/ |
135 | 136 |
int xbee_putc(char c); |
136 | 137 |
/** @brief Read a character from the XBee **/ |
trunk/code/lib/include/libdragonfly/rangefinder.h | ||
---|---|---|
37 | 37 |
#ifndef _RANGEFINDER_H_ |
38 | 38 |
#define _RANGEFINDER_H_ |
39 | 39 |
|
40 |
#include <dragonfly_lib.h> |
|
41 |
|
|
40 | 42 |
/** |
41 | 43 |
* @addtogroup rangefinder |
42 | 44 |
* @{ |
... | ... | |
58 | 60 |
#define MAX_IR_ADC8 133 |
59 | 61 |
|
60 | 62 |
/** @brief Initialize the rangefinders **/ |
61 |
void range_init(void);
|
|
63 |
int range_init(void);
|
|
62 | 64 |
/** @brief Read the distance from a rangefinder **/ |
63 | 65 |
int range_read_distance(int range_id); |
64 | 66 |
/** @brief Convert logarithmic-scale distance readings to a linear scale **/ |
trunk/code/lib/include/libdragonfly/eeprom.h | ||
---|---|---|
1 |
/** |
|
2 |
* @file eeprom.h |
|
3 |
* @brief handles eeprom storage for persistent data |
|
4 |
* |
|
5 |
* Contains functions and definitions for reading and writing to eeprom |
|
6 |
* |
|
7 |
* @author Colony Project, Brad Neuman |
|
8 |
*/ |
|
9 |
|
|
10 | 1 |
#ifndef _EEPROM_H_ |
11 | 2 |
#define _EEPROM_H_ |
12 | 3 |
|
13 | 4 |
#define EEPROM_ROBOT_ID_ADDR 0x10 |
14 | 5 |
#define EEPROM_BOM_TYPE_ADDR 0x14 |
15 | 6 |
|
16 |
/** @brief store a byte to eeproem |
|
17 |
* @return 0 if success, nonzero on failure |
|
18 |
*/ |
|
19 | 7 |
int eeprom_put_byte(unsigned int addr, unsigned char byte); |
20 | 8 |
|
21 |
/** @brief reads a byte from eeprom |
|
22 |
* |
|
23 |
* Pass it thge address and a pointer to a byte where the byte at the |
|
24 |
* address will be stored |
|
25 |
* |
|
26 |
* @return 0 if successful (byte is set to the eeprom value at addr), |
|
27 |
* nonzero if there was a problem |
|
28 |
*/ |
|
29 | 9 |
int eeprom_get_byte(unsigned int addr, unsigned char *byte); |
30 | 10 |
|
31 |
/** @brief get stored robot ID |
|
32 |
* |
|
33 |
* checks that EEPROM has been programed with an ID and returns it |
|
34 |
* |
|
35 |
* @return the robot id, if it is stored. If it returns 0xFF it is probably invalid |
|
36 |
*/ |
|
37 | 11 |
unsigned char get_robotid(void); |
38 | 12 |
|
39 |
/** @brief get stored robot ID |
|
40 |
* |
|
41 |
* checks that EEPROM has been programed with an BOM type and returns it |
|
42 |
* |
|
43 |
* @return the robot bom type as defined in bom.h, if it is stored. If it returns 0xFF it is probably invalid |
|
44 |
*/ |
|
45 | 13 |
unsigned char get_bom_type(void); |
46 | 14 |
|
47 | 15 |
#endif |
trunk/code/projects/test/test_motors.c | ||
---|---|---|
61 | 61 |
delay_ms(3000); |
62 | 62 |
//while(1){;} |
63 | 63 |
|
64 |
|
|
65 |
motors_off(); |
|
66 |
|
|
64 | 67 |
return 0; |
65 | 68 |
} |
66 | 69 |
|
... | ... | |
69 | 72 |
left >154 forward |
70 | 73 |
right >150 forward |
71 | 74 |
both >152 backward |
72 |
*/ |
|
75 |
*/ |
trunk/code/projects/test/test_rangefinder.c | ||
---|---|---|
30 | 30 |
int i; // index |
31 | 31 |
int sensor[5] = {IR4, IR3, IR2, IR1, IR5}; |
32 | 32 |
int color[5] = {RED, ORANGE, YELLOW, GREEN, BLUE}; |
33 |
int ret; |
|
33 | 34 |
|
34 | 35 |
// flash orbs BLUE 3 times |
35 | 36 |
for (i = 0; i < 3; i++) { |
... | ... | |
44 | 45 |
orb2_set_color(color[i]); |
45 | 46 |
|
46 | 47 |
// wait for sensor interaction |
47 |
while (range_read_distance(sensor[i]) == -1)
|
|
48 |
while ((ret = range_read_distance(sensor[i])) == -1) {
|
|
48 | 49 |
// stay RED until IR4 sees something |
49 | 50 |
orb1_set_color(RED); |
51 |
if(ret == -3) { //library not init'd |
|
52 |
while(1) { |
|
53 |
orb2_set_color(GREEN); |
|
54 |
orb1_set_color(RED); |
|
55 |
delay_ms(250); |
|
56 |
orb1_set_color(GREEN); |
|
57 |
orb2_set_color(RED); |
|
58 |
delay_ms(250); |
|
59 |
} |
|
60 |
} |
|
61 |
} |
|
50 | 62 |
|
51 | 63 |
orb1_set_color(GREEN); |
52 | 64 |
delay_ms(TEST_TIME); |
trunk/code/projects/test/main.c | ||
---|---|---|
3 | 3 |
#define RUN_TEST(f) extern int f(void); f(); |
4 | 4 |
|
5 | 5 |
int main(void) { |
6 |
RUN_TEST(testinits); |
|
7 |
|
|
6 | 8 |
dragonfly_init(ALL_ON); |
7 | 9 |
|
8 | 10 |
while (1) { |
9 |
// RUN_TEST(testusb);
|
|
11 |
//RUN_TEST(testusb); |
|
10 | 12 |
// RUN_TEST(testanalog); |
11 |
// RUN_TEST(testeeprom);
|
|
13 |
//RUN_TEST(testeeprom); |
|
12 | 14 |
// RUN_TEST(testencoders); |
13 | 15 |
// RUN_TEST(testlcd); |
14 |
// RUN_TEST(testlights);
|
|
15 |
// RUN_TEST(testmotors);
|
|
16 |
// RUN_TEST(testrangefinder);
|
|
16 |
//RUN_TEST(testlights); |
|
17 |
//RUN_TEST(testmotors); |
|
18 |
RUN_TEST(testrangefinder); |
|
17 | 19 |
// RUN_TEST(testtokenring); |
18 | 20 |
// RUN_TEST(testwireless); |
19 |
RUN_TEST(testxbee); |
|
21 |
//RUN_TEST(testxbee);
|
|
20 | 22 |
delay_ms(1000); |
21 | 23 |
} |
22 | 24 |
|
trunk/code/projects/hunter_prey/testbench/main.c | ||
---|---|---|
62 | 62 |
delay8.tv_sec = 2; |
63 | 63 |
delay8.tv_nsec = 800000000; |
64 | 64 |
|
65 |
wl_set_com_port("/dev/ttyUSB0");
|
|
65 |
wl_set_com_port("/dev/ttyUSB1");
|
|
66 | 66 |
// set up wireless |
67 | 67 |
wl_basic_init_default(); |
68 | 68 |
wl_set_channel(channel); |
trunk/code/projects/libdragonfly/motor.c | ||
---|---|---|
43 | 43 |
* @{ |
44 | 44 |
**/ |
45 | 45 |
|
46 |
unsigned char motors_initd=0; |
|
47 |
|
|
46 | 48 |
/** |
47 | 49 |
* Initializes both motors so that they can be used with future |
48 | 50 |
* calls to motor1_set and motor2_set. |
49 | 51 |
* |
52 |
* @return 0 if init succesfull, an error code otherwise |
|
53 |
* |
|
50 | 54 |
* @see motors_off, motor1_set, motor2_set |
51 | 55 |
**/ |
52 |
void motors_init( void ) { |
|
56 |
int motors_init( void ) { |
|
57 |
|
|
58 |
if(motors_initd) |
|
59 |
return ERROR_INIT_ALREADY_INITD; |
|
60 |
|
|
61 |
|
|
53 | 62 |
// Configure counter such that we use phase correct |
54 | 63 |
// PWM with 8-bit resolution |
55 | 64 |
PORTA &= 0x0F; |
... | ... | |
65 | 74 |
OCR1AL=0; |
66 | 75 |
OCR1BH=0; |
67 | 76 |
OCR1BL=0; |
77 |
|
|
78 |
motors_initd=1; |
|
79 |
return 0; |
|
68 | 80 |
} |
69 | 81 |
|
70 | 82 |
/** |
... | ... | |
74 | 86 |
* @param direction Either FORWARD or BACKWARD to set the direction of rotation. |
75 | 87 |
* @param speed The speed the motor will run at, in the range 0-255. |
76 | 88 |
* |
89 |
* @return 0 if init succesfull, an error code otherwise |
|
90 |
* |
|
77 | 91 |
* @see motor_r_set, motors_init |
78 | 92 |
**/ |
79 |
void motor_l_set(int direction, int speed) { |
|
93 |
int motor_l_set(int direction, int speed) { |
|
94 |
if(!motors_initd) |
|
95 |
return ERROR_LIBRARY_NOT_INITD; |
|
80 | 96 |
|
81 | 97 |
if(direction == 0) { |
82 | 98 |
// turn off PWM first if switching directions |
... | ... | |
98 | 114 |
|
99 | 115 |
// Set the timer to count up to speed, an 8-bit value |
100 | 116 |
OCR1AL = speed; |
117 |
|
|
118 |
return 0; |
|
101 | 119 |
} |
102 | 120 |
|
103 | 121 |
/** |
... | ... | |
107 | 125 |
* @param direction Either FORWARD or BACKWARD to set the direction of rotation. |
108 | 126 |
* @param speed The speed the motor will run at, in the range 0-255. |
109 | 127 |
* |
128 |
* @return 0 if init succesfull, an error code otherwise |
|
129 |
* |
|
110 | 130 |
* @see motor_l_set, motors_init |
111 | 131 |
**/ |
112 |
void motor_r_set(int direction, int speed) { |
|
132 |
int motor_r_set(int direction, int speed) { |
|
133 |
if(!motors_initd) |
|
134 |
return ERROR_LIBRARY_NOT_INITD; |
|
135 |
|
|
113 | 136 |
if(direction == 0) { |
114 | 137 |
// PORTD |= 0x20; |
115 | 138 |
// PORTD &= 0x7F; |
... | ... | |
131 | 154 |
PORTA = (PORTA & 0x3F) | 0x40; |
132 | 155 |
} |
133 | 156 |
OCR1BL = speed; |
157 |
|
|
158 |
return 0; |
|
134 | 159 |
} |
135 | 160 |
|
136 | 161 |
/** |
... | ... | |
140 | 165 |
* @param direction Either FORWARD or BACKWARD to set the direction of rotation. |
141 | 166 |
* @param speed The speed the motor will run at, in the range 0-255. |
142 | 167 |
* |
168 |
* @return 0 if init succesfull, an error code otherwise |
|
169 |
* |
|
143 | 170 |
* @see motor2_set, motors_init |
144 | 171 |
**/ |
145 |
void motor1_set(int direction, int speed) {
|
|
146 |
motor_l_set(direction, speed);
|
|
172 |
int motor1_set(int direction, int speed) {
|
|
173 |
return motor_l_set(direction, speed);
|
|
147 | 174 |
} |
148 | 175 |
|
149 | 176 |
/** |
... | ... | |
153 | 180 |
* @param direction Either FORWARD or BACKWARD to set the direction of rotation. |
154 | 181 |
* @param speed The speed the motor will run at, in the range 0-255. |
155 | 182 |
* |
183 |
* @return 0 if init succesfull, an error code otherwise |
|
184 |
* |
|
156 | 185 |
* @see motor2_set, motors_init |
157 | 186 |
**/ |
158 |
void motor2_set(int direction, int speed) {
|
|
159 |
motor_r_set(direction, speed);
|
|
187 |
int motor2_set(int direction, int speed) {
|
|
188 |
return motor_r_set(direction, speed);
|
|
160 | 189 |
} |
161 | 190 |
|
162 | 191 |
|
163 | 192 |
/** |
164 | 193 |
* Turns off both motors. |
165 | 194 |
* |
195 |
* @return 0 if init succesfull, an error code otherwise |
|
196 |
* |
|
166 | 197 |
* @see motors_init |
167 | 198 |
**/ |
168 |
void motors_off( void ) { |
|
199 |
int motors_off( void ) { |
|
200 |
if(!motors_initd) |
|
201 |
return ERROR_LIBRARY_NOT_INITD; |
|
202 |
|
|
169 | 203 |
OCR1AL = 0x0; |
170 | 204 |
OCR1BL = 0x0; |
205 |
|
|
206 |
return 0; |
|
171 | 207 |
} |
172 | 208 |
|
173 | 209 |
/**@}**///end defgroup |
trunk/code/projects/libdragonfly/motor.h | ||
---|---|---|
38 | 38 |
#ifndef _MOTOR_H |
39 | 39 |
#define _MOTOR_H |
40 | 40 |
|
41 |
#include <dragonfly_lib.h> |
|
41 | 42 |
#include <avr/io.h> |
42 | 43 |
/** |
43 | 44 |
* @addtogroup motors |
... | ... | |
50 | 51 |
#define BACKWARD 0 |
51 | 52 |
|
52 | 53 |
/** @brief Initialize the motors **/ |
53 |
void motors_init(void);
|
|
54 |
int motors_init(void);
|
|
54 | 55 |
/** @brief Set speed and direction of motor1 |
55 | 56 |
* @deprecated use the left motor function instead. it's more intuitive and easier to read.**/ |
56 |
void motor1_set(int direction, int speed);
|
|
57 |
int motor1_set(int direction, int speed);
|
|
57 | 58 |
/** @brief Set speed and direction of motor2 |
58 | 59 |
* @deprecated use the right motor function instead. it's more intuitive and easier to read.**/ |
59 |
void motor2_set(int direction, int speed);
|
|
60 |
int motor2_set(int direction, int speed);
|
|
60 | 61 |
/** @brief Set speed and direction of left motor **/ |
61 |
void motor_l_set(int direction, int speed);
|
|
62 |
int motor_l_set(int direction, int speed);
|
|
62 | 63 |
/** @brief Set speed and direction of right motor **/ |
63 |
void motor_r_set(int direction, int speed);
|
|
64 |
int motor_r_set(int direction, int speed);
|
|
64 | 65 |
/** @brief Turn the motors off **/ |
65 |
void motors_off(void);
|
|
66 |
int motors_off(void);
|
|
66 | 67 |
|
67 | 68 |
/**@}**/ // end addtogroup |
68 | 69 |
|
trunk/code/projects/libdragonfly/i2c.c | ||
---|---|---|
43 | 43 |
#include "i2c.h" |
44 | 44 |
#include "ring_buffer.h" |
45 | 45 |
|
46 |
//NOTE: this is here just to provide colony error codes, it can be safely removed |
|
47 |
// for use in another project |
|
48 |
#include <dragonfly_lib.h> |
|
49 |
|
|
46 | 50 |
/** |
47 | 51 |
* @defgroup i2c I2C |
48 | 52 |
* |
... | ... | |
78 | 82 |
*/ |
79 | 83 |
#define I2C_BIT_RATE_DIVIDER 0x0C |
80 | 84 |
|
85 |
unsigned char i2c_initd=0; |
|
86 |
|
|
81 | 87 |
static int start_flag; |
82 | 88 |
|
83 | 89 |
static fun_mrecv_t master_recv_function; |
... | ... | |
105 | 111 |
* @return 0 for success, nonzero for failure |
106 | 112 |
**/ |
107 | 113 |
int i2c_init(char addr, fun_mrecv_t master_recv, fun_srecv_t slave_recv, fun_send_t slave_send) { |
114 |
|
|
115 |
if(i2c_initd) |
|
116 |
return ERROR_INIT_ALREADY_INITD; |
|
117 |
|
|
118 |
|
|
108 | 119 |
master_recv_function = master_recv; |
109 | 120 |
slave_recv_function = slave_recv; |
110 | 121 |
slave_send_function = slave_send; |
... | ... | |
122 | 133 |
* global messages to be accepted */ |
123 | 134 |
TWAR = (addr << 1) | 1; |
124 | 135 |
|
136 |
i2c_initd = 1; |
|
125 | 137 |
return 0; |
126 | 138 |
} |
127 | 139 |
|
... | ... | |
141 | 153 |
int i2c_send(char dest, char *data, unsigned int bytes) { |
142 | 154 |
int i; |
143 | 155 |
|
156 |
if(!i2c_initd) |
|
157 |
return ERROR_LIBRARY_NOT_INITD; |
|
158 |
|
|
159 |
|
|
144 | 160 |
/* adding data to be sent to ring buffers is not atomic, |
145 | 161 |
* so disable interrupts */ |
146 | 162 |
cli(); |
... | ... | |
180 | 196 |
* @return 0 for success, nonzero for failure |
181 | 197 |
**/ |
182 | 198 |
int i2c_request(char dest) { |
199 |
if(!i2c_initd) |
|
200 |
return ERROR_LIBRARY_NOT_INITD; |
|
201 |
|
|
183 | 202 |
if(RING_BUFFER_FULL(i2c_write_buff)) |
184 | 203 |
return -1; |
185 | 204 |
|
trunk/code/projects/libdragonfly/serial.c | ||
---|---|---|
36 | 36 |
#include <avr/io.h> |
37 | 37 |
#include "serial.h" |
38 | 38 |
|
39 |
unsigned char usb_initd=0; |
|
40 |
unsigned char xbee_initd=0; |
|
41 |
|
|
39 | 42 |
#ifdef USE_STDIO |
40 | 43 |
|
41 | 44 |
#include <stdio.h> |
... | ... | |
57 | 60 |
* This must be called before any other usb function |
58 | 61 |
* may be used. |
59 | 62 |
**/ |
60 |
void usb_init() {
|
|
63 |
int usb_init() {
|
|
61 | 64 |
//Set baud rate |
62 | 65 |
// - 115200 (both wired and wireless) is UBRR=8, U2X=1 |
63 | 66 |
// - 9600 is U2X =1, UBRR = 107. |
67 |
|
|
68 |
if(usb_initd) { |
|
69 |
return ERROR_INIT_ALREADY_INITD; |
|
70 |
} |
|
71 |
|
|
64 | 72 |
#if (USB_BAUD == 115200) |
65 | 73 |
UBRR0H = 0x00; |
66 | 74 |
UBRR0L = 8; |
... | ... | |
70 | 78 |
UBRR0L = 103; |
71 | 79 |
UCSR0A |= _BV(U2X0); |
72 | 80 |
#else //Baud rate is defined in the header file, we should not get here |
73 |
return; |
|
81 |
return 0;
|
|
74 | 82 |
#endif |
75 | 83 |
|
76 | 84 |
/*Enable receiver and transmitter */ |
... | ... | |
84 | 92 |
/* Open the stdio stream corresponding to this port */ |
85 | 93 |
usb_fd = fdevopen(usb_putc, usb_getc); |
86 | 94 |
#endif |
95 |
|
|
96 |
usb_initd = 1; |
|
97 |
return 0; |
|
98 |
|
|
87 | 99 |
} |
88 | 100 |
|
89 | 101 |
/** |
... | ... | |
91 | 103 |
* This must be called before any other xbee function |
92 | 104 |
* may be used. |
93 | 105 |
**/ |
94 |
void xbee_init() { |
|
106 |
int xbee_init() { |
|
107 |
|
|
108 |
if(xbee_initd) { |
|
109 |
return ERROR_INIT_ALREADY_INITD; |
|
110 |
} |
|
111 |
|
|
95 | 112 |
//Set baud rate |
96 | 113 |
// - 115200 (both wired and wireless) is UBRR=8, U2X=1 |
97 | 114 |
// - 9600 is U2X =1, UBRR = 107. |
... | ... | |
104 | 121 |
UBRR1L = 103; |
105 | 122 |
UCSR1A |= _BV(U2X1); |
106 | 123 |
#else //Baud rate is defined in the header file, we should not get here |
107 |
return; |
|
124 |
return 0;
|
|
108 | 125 |
#endif |
109 | 126 |
|
110 | 127 |
//Enable receiver and transmitter |
... | ... | |
118 | 135 |
/* Open the stdio stream corresponding to this port */ |
119 | 136 |
xbee_fd = fdevopen(xbee_putc, xbee_getc); |
120 | 137 |
#endif |
138 |
|
|
139 |
xbee_initd = 1; |
|
140 |
return 0; |
|
141 |
|
|
121 | 142 |
} |
122 | 143 |
|
123 | 144 |
/** |
... | ... | |
127 | 148 |
* @return 0 for success, nonzero for failure |
128 | 149 |
**/ |
129 | 150 |
int usb_putc(char c) { |
151 |
|
|
152 |
if(!usb_initd) |
|
153 |
return ERROR_LIBRARY_NOT_INITD; |
|
154 |
|
|
130 | 155 |
// Wait until buffer is clear for sending |
131 | 156 |
loop_until_bit_is_set(UCSR0A, UDRE0); |
132 | 157 |
|
... | ... | |
142 | 167 |
* @return 0 for success, nonzero for failure |
143 | 168 |
**/ |
144 | 169 |
int xbee_putc(char c) { |
170 |
|
|
171 |
if(!xbee_initd) |
|
172 |
return ERROR_LIBRARY_NOT_INITD; |
|
173 |
|
|
145 | 174 |
// Wait until buffer is clear for sending |
146 | 175 |
loop_until_bit_is_set(UCSR1A, UDRE1); |
147 | 176 |
|
... | ... | |
158 | 187 |
**/ |
159 | 188 |
int usb_puts(char *s) { |
160 | 189 |
char *t = s; |
190 |
|
|
191 |
if(!usb_initd) |
|
192 |
return ERROR_LIBRARY_NOT_INITD; |
|
193 |
|
|
161 | 194 |
while (*t != 0) { |
162 | 195 |
usb_putc(*t); |
163 | 196 |
t++; |
... | ... | |
169 | 202 |
* Sends a sequence of characters from program space over USB. |
170 | 203 |
* |
171 | 204 |
* @param s the string to send |
205 |
* |
|
206 |
* @return 0 if init succesfull, an error code otherwise |
|
172 | 207 |
**/ |
173 |
void usb_puts_P (PGM_P s) {
|
|
208 |
int usb_puts_P (PGM_P s) {
|
|
174 | 209 |
char buf; |
210 |
|
|
211 |
if(!usb_initd) |
|
212 |
return ERROR_LIBRARY_NOT_INITD; |
|
175 | 213 |
|
176 | 214 |
while (memcpy_P (&buf, s, sizeof (char)), buf!=0) { |
177 | 215 |
usb_putc (buf); |
178 | 216 |
s++; |
179 | 217 |
} |
218 |
|
|
219 |
return 0; |
|
180 | 220 |
} |
181 | 221 |
|
182 | 222 |
|
... | ... | |
186 | 226 |
* This function blocks execution until a character has been received. |
187 | 227 |
* xbee_init must be called before this function may be used. |
188 | 228 |
* |
189 |
* @return the first character in the usb buffer |
|
229 |
* @return the first character in the usb buffer, -1 on error
|
|
190 | 230 |
* |
191 | 231 |
* @see usb_init, usb_getc_nb |
192 | 232 |
**/ |
193 | 233 |
int usb_getc(void) { |
234 |
|
|
235 |
if(!usb_initd) |
|
236 |
return -1; |
|
237 |
|
|
194 | 238 |
// Wait for the receive buffer to be filled |
195 | 239 |
loop_until_bit_is_set(UCSR0A, RXC0); |
196 | 240 |
|
... | ... | |
204 | 248 |
* received. xbee_init must be called before this function |
205 | 249 |
* may be used. |
206 | 250 |
* |
207 |
* @return the first character in the xbee buffer |
|
251 |
* @return the first character in the xbee buffer, -1 on error
|
|
208 | 252 |
* |
209 | 253 |
* @see xbee_init, xbee_getc_nb |
210 | 254 |
**/ |
211 | 255 |
int xbee_getc(void) { |
256 |
|
|
257 |
if(!usb_initd) |
|
258 |
return -1; |
|
259 |
|
|
212 | 260 |
// Wait for the receive buffer to be filled |
213 | 261 |
loop_until_bit_is_set(UCSR1A, RXC1); |
214 | 262 |
|
... | ... | |
224 | 272 |
* @param c the received character. This will be set if a character has |
225 | 273 |
* been received. |
226 | 274 |
* |
227 |
* @return -1 if no character is available, 0 otherwise |
|
275 |
* @return -1 if no character is available, 0 otherwise, positive for error
|
|
228 | 276 |
* |
229 | 277 |
* @see usb_init, usb_getc |
230 | 278 |
**/ |
231 | 279 |
int usb_getc_nb(char *c) { |
280 |
|
|
281 |
if(!usb_initd) |
|
282 |
return ERROR_LIBRARY_NOT_INITD; |
|
283 |
|
|
232 | 284 |
// check if the receive buffer is filled |
233 | 285 |
if (UCSR0A & _BV(RXC0)) { |
234 | 286 |
// Read the receive buffer |
... | ... | |
248 | 300 |
* @param c the received character. This will be set if a character has |
249 | 301 |
* been received. |
250 | 302 |
* |
251 |
* @return -1 if no character is available, 0 otherwise |
|
303 |
* @return -1 if no character is available, 0 otherwise, positive for error
|
|
252 | 304 |
* |
253 | 305 |
* @see xbee_init, xbee_getc |
254 | 306 |
**/ |
255 | 307 |
int xbee_getc_nb(char *c) { |
308 |
if(!xbee_initd) |
|
309 |
return ERROR_LIBRARY_NOT_INITD; |
|
310 |
|
|
256 | 311 |
// check if the receive buffer is filled |
257 | 312 |
if (UCSR1A & _BV(RXC1)) { |
258 | 313 |
// Read the receive buffer |
... | ... | |
284 | 339 |
int usb_puti(int value ) { |
285 | 340 |
unsigned char usb_data[6]={'0','0','0','0','0','0' }, position=sizeof(usb_data), radix=10; |
286 | 341 |
|
342 |
if(!usb_initd) |
|
343 |
return ERROR_LIBRARY_NOT_INITD; |
|
344 |
|
|
345 |
|
|
287 | 346 |
/* convert int to ascii */ |
288 | 347 |
if(value<0) { |
289 | 348 |
usb_putc('-'); |
... | ... | |
329 | 388 |
* @param value the value to print |
330 | 389 |
* |
331 | 390 |
* @see usb_init, usb_puti, usb_puts, usb_puth8, hex_digit |
391 |
* |
|
392 |
* @return 0 if init succesfull, an error code otherwise |
|
332 | 393 |
**/ |
333 |
void usb_puth16 (uint16_t value)
|
|
394 |
int usb_puth16 (uint16_t value)
|
|
334 | 395 |
{ |
396 |
if(!usb_initd) |
|
397 |
return ERROR_LIBRARY_NOT_INITD; |
|
398 |
|
|
335 | 399 |
usb_putc (hex_digit((value >>12)&0xF)); |
336 | 400 |
usb_putc (hex_digit((value >>8 )&0xF)); |
337 | 401 |
usb_putc (hex_digit((value >>4 )&0xF)); |
338 | 402 |
usb_putc (hex_digit( value &0xF)); |
403 |
|
|
404 |
return 0; |
|
339 | 405 |
} |
340 | 406 |
|
341 | 407 |
/** |
... | ... | |
346 | 412 |
* @param value the value to print |
347 | 413 |
* |
348 | 414 |
* @see usb_init, usb_puti, usb_puts, usb_puth16, hex_digit |
415 |
* |
|
416 |
* @return 0 if init succesfull, an error code otherwise |
|
349 | 417 |
**/ |
350 |
void usb_puth8(uint8_t value)
|
|
418 |
int usb_puth8(uint8_t value)
|
|
351 | 419 |
{ |
420 |
if(!usb_initd) |
|
421 |
return ERROR_LIBRARY_NOT_INITD; |
|
422 |
|
|
352 | 423 |
usb_putc (hex_digit ((value)>>4 &0xF)); |
353 | 424 |
usb_putc (hex_digit ( value &0xF)); |
425 |
|
|
426 |
return 0; |
|
354 | 427 |
} |
355 | 428 |
|
trunk/code/projects/libdragonfly/dragonfly_lib.h | ||
---|---|---|
41 | 41 |
* @{ |
42 | 42 |
**/ |
43 | 43 |
|
44 |
//return value definitions |
|
45 |
#define ERROR_INIT_FAILED 1 |
|
46 |
#define ERROR_INIT_ALREADY_INITD 2 |
|
47 |
|
|
48 |
#define ERROR_LIBRARY_NOT_INITD 3 |
|
49 |
|
|
44 | 50 |
// Configuration definitions |
45 | 51 |
/** @brief Initialize analog **/ |
46 | 52 |
#define ANALOG 0x01 |
trunk/code/projects/libdragonfly/serial.h | ||
---|---|---|
68 | 68 |
#ifndef _SERIAL_H |
69 | 69 |
#define _SERIAL_H |
70 | 70 |
|
71 |
#include <dragonfly_lib.h> |
|
71 | 72 |
#include <inttypes.h> |
72 | 73 |
#include <avr/pgmspace.h> |
73 | 74 |
|
... | ... | |
87 | 88 |
#endif |
88 | 89 |
|
89 | 90 |
/** @brief Initialize the USB **/ |
90 |
void usb_init(void);
|
|
91 |
int usb_init(void);
|
|
91 | 92 |
/** @brief Print a character to USB **/ |
92 | 93 |
int usb_putc(char c); |
93 | 94 |
/** @brief Read a character from USB **/ |
... | ... | |
97 | 98 |
/** @brief Print a string to USB **/ |
98 | 99 |
int usb_puts(char *s); |
99 | 100 |
/** @brief Print a string from program space to USB **/ |
100 |
void usb_puts_P (PGM_P s);
|
|
101 |
int usb_puts_P (PGM_P s);
|
|
101 | 102 |
/** @brief Print an integer to USB **/ |
102 | 103 |
int usb_puti(int value); |
103 | 104 |
/** @brief Determine a hexadecimal digit **/ |
104 | 105 |
uint8_t hex_digit (uint8_t value); |
105 | 106 |
/** @brief Print a fixed width hexadecimal representation to USB **/ |
106 |
void usb_puth16 (uint16_t value);
|
|
107 |
int usb_puth16 (uint16_t value);
|
|
107 | 108 |
/** @brief Print a fixed width hexadecimal representation to USB **/ |
108 |
void usb_puth8(uint8_t value);
|
|
109 |
int usb_puth8(uint8_t value);
|
|
109 | 110 |
/** @brief Alias for usb_puth16 **/ |
110 | 111 |
static inline void usb_puth (uint16_t value) { usb_puth16 (value); }; |
111 | 112 |
|
... | ... | |
130 | 131 |
#endif |
131 | 132 |
|
132 | 133 |
/** @brief Initialize the XBee **/ |
133 |
void xbee_init(void);
|
|
134 |
int xbee_init(void);
|
|
134 | 135 |
/** @brief Print a character to the XBee **/ |
135 | 136 |
int xbee_putc(char c); |
136 | 137 |
/** @brief Read a character from the XBee **/ |
trunk/code/projects/libdragonfly/eeprom.c | ||
---|---|---|
1 |
/** |
|
2 |
* @file eeprom.c |
|
3 |
* @brief handles eeprom storage for persistent data |
|
4 |
* |
|
5 |
* Contains functions and definitions for reading and writing to eeprom |
|
6 |
* |
|
7 |
* @author Colony Project, Brad Neuman |
|
8 |
*/ |
|
9 |
|
|
1 | 10 |
#include <avr/io.h> |
2 | 11 |
#include "eeprom.h" |
3 | 12 |
|
13 |
/** @brief store a byte to eeproem |
|
14 |
* @return 0 if success, nonzero on failure |
|
15 |
*/ |
|
4 | 16 |
int eeprom_put_byte(unsigned int uiAddress, unsigned char ucData) { |
5 | 17 |
/* Wait for completion of previous write */ |
6 | 18 |
while(EECR & (1<<EEWE)); |
... | ... | |
15 | 27 |
return 0; |
16 | 28 |
} |
17 | 29 |
|
30 |
/** @brief reads a byte from eeprom |
|
31 |
* |
|
32 |
* Pass it thge address and a pointer to a byte where the byte at the |
|
33 |
* address will be stored |
|
34 |
* |
|
35 |
* @return 0 if successful (byte is set to the eeprom value at addr), |
|
36 |
* nonzero if there was a problem |
|
37 |
*/ |
|
18 | 38 |
int eeprom_get_byte(unsigned int uiAddress, unsigned char *byte) { |
19 | 39 |
/* Wait for completion of previous write */ |
20 | 40 |
while(EECR & (1<<EEWE)); |
... | ... | |
28 | 48 |
return 0; |
29 | 49 |
} |
30 | 50 |
|
31 |
|
|
51 |
/** @brief get stored robot ID |
|
52 |
* |
|
53 |
* checks that EEPROM has been programed with an ID and returns it |
|
54 |
* |
|
55 |
* @return the robot id, if it is stored. If it returns 0xFF it is probably invalid |
|
56 |
*/ |
|
32 | 57 |
unsigned char get_robotid(void) { |
33 | 58 |
unsigned char c0, c1, c2; |
34 | 59 |
|
... | ... | |
41 | 66 |
return 0xFF; |
42 | 67 |
} |
43 | 68 |
|
69 |
/** @brief get stored robot ID |
|
70 |
* |
|
71 |
* checks that EEPROM has been programed with an BOM type and returns it |
|
72 |
* |
|
73 |
* @return the robot bom type as defined in bom.h, if it is stored. If it returns 0xFF it is probably invalid |
|
74 |
*/ |
|
44 | 75 |
unsigned char get_bom_type(void) { |
45 | 76 |
unsigned char c0, c1, c2, c3; |
46 | 77 |
|
trunk/code/projects/libdragonfly/spi.c | ||
---|---|---|
8 | 8 |
#include <avr/interrupt.h> |
9 | 9 |
#include "spi.h" |
10 | 10 |
|
11 |
unsigned char spi_initd=0; |
|
11 | 12 |
|
12 | 13 |
static volatile char spi_bytes; /* number of bytes to read */ |
13 | 14 |
static spi_fun_recv_t spi_recv_func; /* byte handler */ |
... | ... | |
18 | 19 |
* |
19 | 20 |
* @param recv_func The function to be called for each byte of data received. |
20 | 21 |
* @param recv_complete_func The function to be called at the end of a complete transmission. |
22 |
* |
|
23 |
* @return 0 if init succesfull, an error code otherwise |
|
21 | 24 |
*/ |
22 |
void spi_init (spi_fun_recv_t recv_func, spi_fun_recv_complete_t recv_complete_func)
|
|
25 |
int spi_init (spi_fun_recv_t recv_func, spi_fun_recv_complete_t recv_complete_func)
|
|
23 | 26 |
{ |
27 |
if(spi_initd) { |
|
28 |
return ERROR_INIT_ALREADY_INITD; |
|
29 |
} |
|
30 |
|
|
24 | 31 |
/* Enable Interrupt, Enable SPI Module, MSB First, Master Mode, Clock div = 64 */ |
25 | 32 |
SPCR = _BV(SPE) | _BV(SPIE) /*| _BV(DORD)*/ | _BV(MSTR) | _BV(SPR1) | _BV(SPR0); |
26 | 33 |
SPSR = _BV(SPI2X); |
... | ... | |
37 | 44 |
spi_recv_complete_func = recv_complete_func; |
38 | 45 |
spi_bytes = 0; |
39 | 46 |
//usb_puts("\tspi.c Debug: SPI INITIALIZED\n"); |
47 |
|
|
48 |
spi_initd=1; |
|
49 |
return 0; |
|
40 | 50 |
} |
41 | 51 |
|
42 | 52 |
/** |
... | ... | |
44 | 54 |
* |
45 | 55 |
* @param bytes The number of bytes to be transferred. |
46 | 56 |
**/ |
47 |
void spi_transfer(char bytes)
|
|
57 |
int spi_transfer(char bytes)
|
|
48 | 58 |
{ |
59 |
if(!spi_initd) |
|
60 |
return ERROR_LIBRARY_NOT_INITD; |
|
61 |
|
|
49 | 62 |
spi_bytes = bytes; |
50 | 63 |
PORTB &= ~SS; /* Set SS low to initiate transmission */ |
51 | 64 |
SPDR = 0xff; /* Initiate data transmision */ |
65 |
|
|
66 |
return 0; |
|
52 | 67 |
} |
53 | 68 |
|
54 | 69 |
ISR(SIG_SPI) |
trunk/code/projects/libdragonfly/eeprom.h | ||
---|---|---|
1 |
/** |
|
2 |
* @file eeprom.h |
|
3 |
* @brief handles eeprom storage for persistent data |
|
4 |
* |
|
5 |
* Contains functions and definitions for reading and writing to eeprom |
|
6 |
* |
|
7 |
* @author Colony Project, Brad Neuman |
|
8 |
*/ |
|
9 |
|
|
10 | 1 |
#ifndef _EEPROM_H_ |
11 | 2 |
#define _EEPROM_H_ |
12 | 3 |
|
13 | 4 |
#define EEPROM_ROBOT_ID_ADDR 0x10 |
14 | 5 |
#define EEPROM_BOM_TYPE_ADDR 0x14 |
15 | 6 |
|
16 |
/** @brief store a byte to eeproem |
|
17 |
* @return 0 if success, nonzero on failure |
|
18 |
*/ |
|
19 | 7 |
int eeprom_put_byte(unsigned int addr, unsigned char byte); |
20 | 8 |
|
21 |
/** @brief reads a byte from eeprom |
|
22 |
* |
|
23 |
* Pass it thge address and a pointer to a byte where the byte at the |
|
24 |
* address will be stored |
|
25 |
* |
|
26 |
* @return 0 if successful (byte is set to the eeprom value at addr), |
|
27 |
* nonzero if there was a problem |
|
28 |
*/ |
|
29 | 9 |
int eeprom_get_byte(unsigned int addr, unsigned char *byte); |
30 | 10 |
|
31 |
/** @brief get stored robot ID |
|
32 |
* |
|
33 |
* checks that EEPROM has been programed with an ID and returns it |
|
34 |
* |
|
35 |
* @return the robot id, if it is stored. If it returns 0xFF it is probably invalid |
|
36 |
*/ |
|
37 | 11 |
unsigned char get_robotid(void); |
38 | 12 |
|
39 |
/** @brief get stored robot ID |
|
40 |
* |
|
41 |
* checks that EEPROM has been programed with an BOM type and returns it |
|
42 |
* |
|
43 |
* @return the robot bom type as defined in bom.h, if it is stored. If it returns 0xFF it is probably invalid |
|
44 |
*/ |
|
45 | 13 |
unsigned char get_bom_type(void); |
46 | 14 |
|
47 | 15 |
#endif |
trunk/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 |
#include "time.h" |
|
62 |
|
|
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 |
**/ |
|
63 | 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 |
#include "time.h" |
|
62 |
|
|
63 |
|
|
64 | 64 |
/* Calculate how many cycles to delay for to get 1 ms. Based on F_CPU which should be defined by the makefile */ |
65 | 65 |
#ifdef F_CPU |
66 | 66 |
#define WAIT_CYCLES ((F_CPU / 1000) / 10) |
67 | 67 |
#else |
68 | 68 |
#define WAIT_CYCLES (8000 / 10) |
69 | 69 |
#endif |
70 |
|
|
71 |
static volatile int _rtc_val = 0; |
|
72 |
static volatile int _rtc_pulse = 0; |
|
73 |
static volatile int _rtc_scale = 32; //Defaults to 1 Second per pulse |
|
74 |
static void (*_rtc_f)(void) = 0; |
|
75 | 70 |
|
76 | 71 |
|
77 |
|
|
78 |
/** |
|
79 |
* @defgroup time Time |
|
80 |
* @brief Time functions |
|
81 |
* |
|
82 |
* Functions dealing with time. |
|
83 |
* |
|
84 |
* @{ |
|
85 |
**/ |
|
86 |
|
|
87 |
/** |
|
88 |
* Delays for the specified number of milliseconds. |
|
72 |
unsigned char time_initd = 0; |
|
73 |
|
|
74 |
static volatile int _rtc_val = 0; |
|
75 |
static volatile int _rtc_pulse = 0; |
|
76 |
static volatile int _rtc_scale = 32; //Defaults to 1 Second per pulse |
|
77 |
static void (*_rtc_f)(void) = 0; |
|
78 |
|
|
79 |
|
|
80 |
|
|
81 |
/** |
|
82 |
* @defgroup time Time |
|
83 |
* @brief Time functions |
|
84 |
* |
|
85 |
* Functions dealing with time. |
|
86 |
* |
|
87 |
* @{ |
|
88 |
**/ |
|
89 |
|
|
90 |
/** |
|
91 |
* Delays for the specified number of milliseconds. |
|
89 | 92 |
* It depends on F_CPU to be defined in order to calculate how many cycles |
90 | 93 |
* it should delay. If it is not defined, a default clock of 8MHz is assumed. |
91 | 94 |
* |
92 | 95 |
* We use _delay_loop_2 which will run assembly instructions that should be |
93 | 96 |
* 4 cycles long. Optimizations must be enabled for this to be true. |
94 | 97 |
* That function is called to ensure around 1ms per execution. To generate |
95 |
* multiple ms we run a for loop of how many milliseconds are desired.
|
|
98 |
* multiple ms we run a for loop of how many milliseconds are desired. |
|
96 | 99 |
* |
97 | 100 |
* The error should be just the skew on the oscillator as the formula to |
98 | 101 |
* calculate delay cycles should always be a whole number. The is some skew |
99 | 102 |
* in practice though it is unavoidable. Delaying for less than 1s should make |
100 | 103 |
* the error negligable. |
101 |
*
|
|
102 |
* @param ms the number of milliseconds to delay for
|
|
103 |
**/
|
|
104 |
* |
|
105 |
* @param ms the number of milliseconds to delay for |
|
106 |
**/ |
|
104 | 107 |
void delay_ms(int ms) { |
105 | 108 |
for (; ms > 0; ms--) { |
106 | 109 |
_delay_loop_2(WAIT_CYCLES); |
107 | 110 |
} |
108 | 111 |
} |
109 | 112 |
|
110 |
|
|
111 |
/* Prescales defined in time.h. SECOND will give you 1 second. |
|
112 |
More scales are defined in the time.h file. |
|
113 |
rtc_func is the address to a function that you want called every clock tick. */ |
|
114 |
/** |
|
115 |
* Initializes the real time clock. Prescales are defined in time.h. |
|
116 |
* For example, SECOND will give 1 second. The specified function is |
|
117 |
* called every clock tick. For the real time clock to activate, |
|
118 |
* interrupts must be enabled. (through sei() ) |
|
119 |
* |
|
120 |
* @param prescale_opt the period with which the timer is triggered |
|
121 |
* @param rtc_func the function called when the timer is triggered |
|
122 |
* |
|
123 |
* @see rtc_get, rtc_reset |
|
124 |
* |
|
125 |
**/ |
|
126 |
void rtc_init(int prescale_opt, void (*rtc_func)(void)) { |
|
127 |
|
|
128 |
//Clear timer register for Timer 3 |
|
129 |
TCNT3 = 0; |
|
130 |
|
|
131 |
/* This sets the Waveform Generation Module to CTC (Clear Timer on Compare) Mode (100) |
|
132 |
See page135 in Atmega128 Docs for more modes and explanations */ |
|
133 |
TCCR3B |= _BV(WGM32); |
|
134 |
|
|
135 |
/* This sets the prescaler for the system clock (8MHz) ie: divides the clock by some number. |
|
136 |
Currently set to a prescaler of 8 because that is what the orb and servos use (they are on this timer as well) |
|
137 |
See page137 in Atemga128 Docs for all the available prescalers */ |
|
138 |
TCCR3B |= _BV(CS31); |
|
139 |
|
|
140 |
/* Sets the two regsiters that we compare against. So the timer counts up to this number and |
|
141 |
then resets back to 0 and calls the compare match interrupt. |
|
142 |
8x10^6 / 8 = 1/16 Second. All values are based off of this number. Do not change it unless you |
|
143 |
are l337*/ |
|
144 |
|
|
145 |
OCR3A = 0xF424; |
|
146 |
|
|
147 |
/* Enable Output Compare A Interrupt. When OCR3A is met by the timer TCNT3 this interrupt will be |
|
148 |
triggerd. (See page140 in Atmega128 Docs for more information */ |
|
149 |
ETIMSK |= _BV(OCIE3A); |
|
150 |
|
|
151 |
/* Store the pointer to the function to be used in the interrupt */ |
|
152 |
_rtc_f = rtc_func; |
|
153 |
|
|
154 |
/* Store how many 1/16ths of a second you want to let by before triggering an interrupt */ |
|
155 |
_rtc_scale = prescale_opt; |
|
156 |
} |
|
157 |
|
|
158 |
/** |
|
159 |
* Returns the time elapsed in seconds since the last call to |
|
160 |
* rtc_init or rtc_reset. |
|
161 |
* |
|
162 |
* @return the number of seconds since the last call to rtc_init or rtc_reset |
|
163 |
* |
|
164 |
* @see rtc_init, rtc_reset |
|
165 |
**/ |
|
166 |
int rtc_get(void) { |
|
167 |
return _rtc_val; |
|
168 |
} |
|
169 |
|
|
170 |
/** |
|
171 |
* Resets the real time clock counter to 0. |
|
172 |
* |
|
173 |
* @see rtc_init, rtc_get |
|
174 |
**/ |
|
175 |
void rtc_reset(void) { |
|
176 |
_rtc_val = 0; |
|
177 |
} |
|
178 |
|
|
179 |
/** @} **/ //end defgroup |
|
180 |
|
|
181 |
/* Called every pulse. Function in _rtc_f is called every _rtc_scale and also the counter is updated. |
|
182 |
Bascially, since the pulse is hard set at 1/16s you want to count how many 16ths of a second have passed |
|
183 |
and when it reaches the amount of time you want, execute the code. */ |
|
184 |
SIGNAL(TIMER3_COMPA_vect) { |
|
185 |
|
|
186 |
if (_rtc_pulse == _rtc_scale) { |
|
187 |
//Increment the real time clock counter |
|
188 |
_rtc_val++; |
|
189 |
|
|
190 |
//Calls the function tied to the real time clock if defined |
|
191 |
if(_rtc_f != 0) |
|
192 |
_rtc_f(); |
|
193 |
|
|
194 |
//Resets the pulse until the next scale is matched |
|
195 |
_rtc_pulse = 0; |
|
196 |
} |
|
197 |
|
|
198 |
//Updates the amount of pulses seen since the last scale match |
|
199 |
_rtc_pulse++; |
|
200 |
|
|
201 |
} |
|
113 |
|
|
114 |
/* Prescales defined in time.h. SECOND will give you 1 second. |
|
115 |
More scales are defined in the time.h file. |
|
116 |
rtc_func is the address to a function that you want called every clock tick. */ |
|
117 |
/** |
|
118 |
* Initializes the real time clock. Prescales are defined in time.h. |
|
119 |
* For example, SECOND will give 1 second. The specified function is |
|
120 |
* called every clock tick. For the real time clock to activate, |
|
121 |
* interrupts must be enabled. (through sei() ) |
|
122 |
* |
|
123 |
* @param prescale_opt the period with which the timer is triggered |
|
124 |
* @param rtc_func the function called when the timer is triggered |
|
125 |
* |
|
126 |
* @return 0 if init succesfull, an error code otherwise |
|
127 |
* |
|
128 |
* @see rtc_get, rtc_reset |
|
129 |
* |
|
130 |
**/ |
|
131 |
int rtc_init(int prescale_opt, void (*rtc_func)(void)) { |
|
132 |
|
|
133 |
if(time_initd) { |
|
134 |
return ERROR_INIT_ALREADY_INITD; |
|
135 |
} |
|
136 |
|
|
137 |
//Clear timer register for Timer 3 |
|
138 |
TCNT3 = 0; |
Also available in: Unified diff