Revision 1560
added speed test behavior to wireless branch (this is where I'm testing the baud rate, which still doesn't work)
branches/wireless/code/behaviors/Wireless_Speed_test/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 = 1; //Defaults to 1/32 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/behaviors/Wireless_Speed_test/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 |
|
|
67 |
if(usb_initd) { |
|
68 |
return ERROR_INIT_ALREADY_INITD; |
|
69 |
} |
|
70 |
|
|
71 |
//Set baud rate |
|
72 |
#if (USB_BAUD == 250000) |
|
73 |
UBRR0H = 0x00; |
|
74 |
UBRR0L = 3; |
|
75 |
UCSR0A |= _BV(U2X0); |
|
76 |
#elif (USB_BAUD == 115200) |
|
77 |
UBRR0H = 0x00; |
|
78 |
UBRR0L = 8; |
|
79 |
UCSR0A |= _BV(U2X0); |
|
80 |
#elif (USB_BAUD == 57600) |
|
81 |
UBRR0H = 0x00; |
|
82 |
UBRR0L = 16; |
|
83 |
UCSR0A |= _BV(U2X0); |
|
84 |
#elif (USB_BAUD == 28800) |
|
85 |
UBRR0H = 0x00; |
|
86 |
UBRR0L = 34; |
|
87 |
UCSR0A |= _BV(U2X0); |
|
88 |
#elif (USB_BAUD == 14400) |
|
89 |
UBRR0H = 0x00; |
|
90 |
UBRR0L = 68; |
|
91 |
UCSR0A |= _BV(U2X0); |
|
92 |
#elif (USB_BAUD == 9600) |
|
93 |
UBRR0H = 0x00; |
|
94 |
UBRR0L = 103; |
|
95 |
UCSR0A |= _BV(U2X0); |
|
96 |
#else //Baud rate is defined in the header file, we should not get here |
|
97 |
return 0; |
|
98 |
#endif |
|
99 |
|
|
100 |
/*Enable receiver and transmitter */ |
|
101 |
UCSR0B |= (1<<RXEN0)|(1<<TXEN0); |
|
102 |
|
|
103 |
/* Set frame format: 8data, 1stop bit, asynchronous normal mode */ |
|
104 |
UCSR0C |= (1<<UCSZ00) | (1<<UCSZ01); |
|
105 |
|
|
106 |
// if we have enabled the stdio stuff, then we init it here |
|
107 |
#ifdef USE_STDIO |
|
108 |
/* Open the stdio stream corresponding to this port */ |
|
109 |
usb_fd = fdevopen(usb_putc, usb_getc); |
|
110 |
#endif |
|
111 |
|
|
112 |
usb_initd = 1; |
|
113 |
return 0; |
|
114 |
|
|
115 |
} |
|
116 |
|
|
117 |
/** |
|
118 |
* Initializes communication over the XBee. |
|
119 |
* This must be called before any other xbee function |
|
120 |
* may be used. |
|
121 |
**/ |
|
122 |
int xbee_init() { |
|
123 |
|
|
124 |
if(xbee_initd) { |
|
125 |
return ERROR_INIT_ALREADY_INITD; |
|
126 |
} |
|
127 |
|
|
128 |
//Set default baud rate to 9600 |
|
129 |
UBRR1H = 0x00; |
|
130 |
UBRR1L = 103; |
|
131 |
UCSR1A |= _BV(U2X1); |
|
132 |
|
|
133 |
//Enable receiver and transmitter |
|
134 |
UCSR1B |= (1<<RXEN1)|(1<<TXEN1); |
|
135 |
|
|
136 |
// Set frame format: 8data, 1stop bit, asynchronous normal mode |
|
137 |
UCSR1C |= (1<<UCSZ10) | (1<<UCSZ11); |
|
138 |
|
|
139 |
// if we have enabled the stdio stuff, then we init it here |
|
140 |
#ifdef USE_STDIO |
|
141 |
/* Open the stdio stream corresponding to this port */ |
|
142 |
xbee_fd = fdevopen(xbee_putc, xbee_getc); |
|
143 |
#endif |
|
144 |
|
|
145 |
xbee_initd = 1; |
|
146 |
return 0; |
|
147 |
|
|
148 |
} |
|
149 |
|
|
150 |
/** |
|
151 |
* Sends a character over USB. |
|
152 |
* |
|
153 |
* @param c the character to send |
|
154 |
* @return 0 for success, nonzero for failure |
|
155 |
**/ |
|
156 |
int usb_putc(char c) { |
|
157 |
|
|
158 |
if(!usb_initd) |
|
159 |
return ERROR_LIBRARY_NOT_INITD; |
|
160 |
|
|
161 |
// Wait until buffer is clear for sending |
|
162 |
loop_until_bit_is_set(UCSR0A, UDRE0); |
|
163 |
|
|
164 |
// Load buffer with your character |
|
165 |
UDR0 = c; |
|
166 |
return 0; |
|
167 |
} |
|
168 |
|
|
169 |
/** |
|
170 |
* Sends a character to the XBee. |
|
171 |
* |
|
172 |
* @param c the character to send |
|
173 |
* @return 0 for success, nonzero for failure |
|
174 |
**/ |
|
175 |
int xbee_putc(char c) { |
|
176 |
|
|
177 |
if(!xbee_initd) |
|
178 |
return ERROR_LIBRARY_NOT_INITD; |
|
179 |
|
|
180 |
// Wait until buffer is clear for sending |
|
181 |
loop_until_bit_is_set(UCSR1A, UDRE1); |
|
182 |
|
|
183 |
// Load buffer with your character |
|
184 |
UDR1 = c; |
|
185 |
return 0; |
|
186 |
} |
|
187 |
|
|
188 |
/** |
|
189 |
* Sends a sequence of characters over USB. |
|
190 |
* |
|
191 |
* @param s the string to send |
|
192 |
* @return 0 for success, nonzero for failure |
|
193 |
**/ |
|
194 |
int usb_puts(char *s) { |
|
195 |
char *t = s; |
|
196 |
|
|
197 |
if(!usb_initd) |
|
198 |
return ERROR_LIBRARY_NOT_INITD; |
|
199 |
|
|
200 |
while (*t != 0) { |
|
201 |
usb_putc(*t); |
|
202 |
t++; |
|
203 |
} |
|
204 |
return 0; |
|
205 |
} |
|
206 |
|
|
207 |
/** |
|
208 |
* Sends a sequence of characters from program space over USB. |
|
209 |
* |
|
210 |
* @param s the string to send |
|
211 |
* |
|
212 |
* @return 0 if init succesfull, an error code otherwise |
|
213 |
**/ |
|
214 |
int usb_puts_P (PGM_P s) { |
|
215 |
char buf; |
|
216 |
|
|
217 |
if(!usb_initd) |
|
218 |
return ERROR_LIBRARY_NOT_INITD; |
|
219 |
|
|
220 |
while (memcpy_P (&buf, s, sizeof (char)), buf!=0) { |
|
221 |
usb_putc (buf); |
|
222 |
s++; |
|
223 |
} |
|
224 |
|
|
225 |
return 0; |
|
226 |
} |
|
227 |
|
|
228 |
|
|
229 |
|
|
230 |
/** |
|
231 |
* Returns the first character in the buffer received from USB. |
|
232 |
* This function blocks execution until a character has been received. |
|
233 |
* xbee_init must be called before this function may be used. |
|
234 |
* |
|
235 |
* @return the first character in the usb buffer, -1 on error |
|
236 |
* |
|
237 |
* @see usb_init, usb_getc_nb |
|
238 |
**/ |
|
239 |
int usb_getc(void) { |
|
240 |
|
|
241 |
if(!usb_initd) |
|
242 |
return -1; |
|
243 |
|
|
244 |
// Wait for the receive buffer to be filled |
|
245 |
loop_until_bit_is_set(UCSR0A, RXC0); |
|
246 |
|
|
247 |
// Read the receive buffer |
|
248 |
return UDR0; |
|
249 |
} |
|
250 |
|
|
251 |
/** |
|
252 |
* Returns the first character in the buffer received from USB. |
|
253 |
* This function blocks execution until a character has been |
|
254 |
* received. xbee_init must be called before this function |
|
255 |
* may be used. |
|
256 |
* |
|
257 |
* @return the first character in the xbee buffer, -1 on error |
|
258 |
* |
|
259 |
* @see xbee_init, xbee_getc_nb |
|
260 |
**/ |
|
261 |
int xbee_getc(void) { |
|
262 |
|
|
263 |
if(!usb_initd) |
|
264 |
return -1; |
|
265 |
|
|
266 |
// Wait for the receive buffer to be filled |
|
267 |
loop_until_bit_is_set(UCSR1A, RXC1); |
|
268 |
|
|
269 |
// Read the receive buffer |
|
270 |
return UDR1; |
|
271 |
} |
|
272 |
|
|
273 |
/** |
|
274 |
* Non blocking version of usb_getc. If a character is present in the buffer, |
|
275 |
* it is returned, otherwise -1 is returned immediately. usb_init must be |
|
276 |
* called before this function can be used. |
|
277 |
* |
|
278 |
* @param c the received character. This will be set if a character has |
|
279 |
* been received. |
|
280 |
* |
|
281 |
* @return -1 if no character is available, 0 otherwise, positive for error |
|
282 |
* |
|
283 |
* @see usb_init, usb_getc |
|
284 |
**/ |
|
285 |
int usb_getc_nb(char *c) { |
|
286 |
|
|
287 |
if(!usb_initd) |
|
288 |
return ERROR_LIBRARY_NOT_INITD; |
|
289 |
|
|
290 |
// check if the receive buffer is filled |
|
291 |
if (UCSR0A & _BV(RXC0)) { |
|
292 |
// Read the receive buffer |
|
293 |
(*c) = UDR0; |
|
294 |
return 0; |
|
295 |
} else { |
|
296 |
// Return empty |
|
297 |
return -1; |
|
298 |
} |
|
299 |
} |
|
300 |
|
|
301 |
/** |
|
302 |
* Non blocking version of xbee_getc. If a character is present in the buffer, |
|
303 |
* it is returned, otherwise -1 is returned immediately. xbee_init |
|
304 |
* must be called before this function can be used. |
|
305 |
* |
|
306 |
* @param c the received character. This will be set if a character has |
|
307 |
* been received. |
|
308 |
* |
|
309 |
* @return -1 if no character is available, 0 otherwise, positive for error |
|
310 |
* |
|
311 |
* @see xbee_init, xbee_getc |
|
312 |
**/ |
|
313 |
int xbee_getc_nb(char *c) { |
|
314 |
if(!xbee_initd) |
|
315 |
return ERROR_LIBRARY_NOT_INITD; |
|
316 |
|
|
317 |
// check if the receive buffer is filled |
|
318 |
if (UCSR1A & _BV(RXC1)) { |
|
319 |
// Read the receive buffer |
|
320 |
(*c) = UDR1; |
|
321 |
return 0; |
|
322 |
} else { |
|
323 |
// Return empty |
|
324 |
return -1; |
|
325 |
} |
|
326 |
} |
|
327 |
|
|
328 |
|
|
329 |
/* |
|
330 |
prints an int to serial |
|
331 |
|
|
332 |
code adapted from Chris Efstathiou's code (hendrix@otenet.gr) |
|
333 |
uses usb_putc |
|
334 |
*/ |
|
335 |
/** |
|
336 |
* Prints an integer, converted to ASCII, to usb. usb_init must be called |
|
337 |
* before this function can be used. |
|
338 |
* |
|
339 |
* @param value the integer to print |
|
340 |
* |
|
341 |
* @return 0 if successful, nonzero otherwise |
|
342 |
* |
|
343 |
* @see usb_init, usb_putc |
|
344 |
**/ |
|
345 |
int usb_puti(int value ) { |
|
346 |
unsigned char usb_data[6]={'0','0','0','0','0','0' }, position=sizeof(usb_data), radix=10; |
|
347 |
|
|
348 |
if(!usb_initd) |
|
349 |
return ERROR_LIBRARY_NOT_INITD; |
|
350 |
|
|
351 |
|
|
352 |
/* convert int to ascii */ |
|
353 |
if(value<0) { |
|
354 |
usb_putc('-'); |
|
355 |
value=-value; |
|
356 |
} |
|
357 |
do { |
|
358 |
position--; |
|
359 |
*(usb_data+position)=(value%radix)+'0'; |
|
360 |
value/=radix; |
|
361 |
} while(value); |
|
362 |
|
|
363 |
|
|
364 |
/* start displaying the number */ |
|
365 |
for(;position<=(sizeof(usb_data)-1);position++) { |
|
366 |
|
|
367 |
usb_putc(usb_data[position]); |
|
368 |
} |
|
369 |
|
|
370 |
return 0; |
|
371 |
} |
|
372 |
|
|
373 |
/** |
|
374 |
* Determines a hexadecimal digit in ASCII code. |
|
375 |
* |
|
376 |
* @param value the value of the digit (0<=value<=15) |
|
377 |
* |
|
378 |
* @return the hexadecimal digit in ASCII code, or '?' |
|
379 |
* if the input is invalid. |
|
380 |
**/ |
|
381 |
uint8_t hex_digit (uint8_t value) |
|
382 |
{ |
|
383 |
if (value>15) return '?'; |
|
384 |
// Postcondition: 0<=x<=15 |
|
385 |
|
|
386 |
return "0123456789ABCDEF"[value]; |
|
387 |
} |
|
388 |
|
|
389 |
/** |
|
390 |
* Prints a fixed width hexadecimal representation of an unsigned |
|
391 |
* 16 bit integer in ASCII code to USB. |
|
392 |
* usb_init must be called before this function can be used. |
|
393 |
* |
|
394 |
* @param value the value to print |
|
395 |
* |
|
396 |
* @see usb_init, usb_puti, usb_puts, usb_puth8, hex_digit |
|
397 |
* |
|
398 |
* @return 0 if init succesfull, an error code otherwise |
|
399 |
**/ |
|
400 |
int usb_puth16 (uint16_t value) |
|
401 |
{ |
|
402 |
if(!usb_initd) |
|
403 |
return ERROR_LIBRARY_NOT_INITD; |
|
404 |
|
|
405 |
usb_putc (hex_digit((value >>12)&0xF)); |
|
406 |
usb_putc (hex_digit((value >>8 )&0xF)); |
|
407 |
usb_putc (hex_digit((value >>4 )&0xF)); |
|
408 |
usb_putc (hex_digit( value &0xF)); |
|
409 |
|
|
410 |
return 0; |
|
411 |
} |
|
412 |
|
|
413 |
/** |
|
414 |
* Prints a fixed width hexadecimal representation of an unsigned |
|
415 |
* 8 bit integer in ASCII code to USB. |
|
416 |
* usb_init must be called before this function can be used. |
|
417 |
* |
|
418 |
* @param value the value to print |
|
419 |
* |
|
420 |
* @see usb_init, usb_puti, usb_puts, usb_puth16, hex_digit |
|
421 |
* |
|
422 |
* @return 0 if init succesfull, an error code otherwise |
|
423 |
**/ |
|
424 |
int usb_puth8(uint8_t value) |
|
425 |
{ |
|
426 |
if(!usb_initd) |
|
427 |
return ERROR_LIBRARY_NOT_INITD; |
|
428 |
|
|
429 |
usb_putc (hex_digit ((value)>>4 &0xF)); |
|
430 |
usb_putc (hex_digit ( value &0xF)); |
|
431 |
|
|
432 |
return 0; |
|
433 |
} |
|
434 |
|
branches/wireless/code/behaviors/Wireless_Speed_test/dio.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 dio.h |
|
29 |
* @brief Definitions for digital input / output |
|
30 |
* |
|
31 |
* This file contains definitions and functions for dealing |
|
32 |
* with digital input and output. |
|
33 |
* |
|
34 |
* @author Colony Project, CMU Robotics Club |
|
35 |
* Based on Tom Lauwer's Firefly Library |
|
36 |
**/ |
|
37 |
|
|
38 |
#ifndef _DIO_H |
|
39 |
#define _DIO_H |
|
40 |
|
|
41 |
/* |
|
42 |
these are ALL the pins |
|
43 |
don't use unless you know what you're doing |
|
44 |
*/ |
|
45 |
|
|
46 |
/* |
|
47 |
DIO pins on new dragonfly boards are shown below: |
|
48 |
----------------------------------------------- |
|
49 |
| _PIN_E6 | _PIN_E7 | _PIN_D2 | _PIN_D3 | VCC | |
|
50 |
----------------------------------------------- |
|
51 |
| _PIN_E2 | _PIN_E3 | _PIN_E4 | _PIN_E5 | GND | |
|
52 |
----------------------------------------------- |
|
53 |
*/ |
|
54 |
|
|
55 |
/** @brief Port A **/ |
|
56 |
#define _PORT_A 1 |
|
57 |
/** @brief Port B **/ |
|
58 |
#define _PORT_B 2 |
|
59 |
/** @brief Port C **/ |
|
60 |
#define _PORT_C 3 |
|
61 |
/** @brief Port D **/ |
|
62 |
#define _PORT_D 4 |
|
63 |
/** @brief Port E **/ |
|
64 |
#define _PORT_E 5 |
|
65 |
/** @brief Port F **/ |
|
66 |
#define _PORT_F 6 |
|
67 |
/** @brief Port G **/ |
|
68 |
#define _PORT_G 7 |
|
69 |
|
|
70 |
/** @brief Pin A0 **/ |
|
71 |
#define _PIN_A0 8 |
|
72 |
/** @brief Pin A1 **/ |
|
73 |
#define _PIN_A1 9 |
|
74 |
/** @brief Pin A2 **/ |
|
75 |
#define _PIN_A2 10 |
|
76 |
/** @brief Pin A3 **/ |
|
77 |
#define _PIN_A3 11 |
|
78 |
/** @brief Pin A4 **/ |
|
79 |
#define _PIN_A4 12 |
|
80 |
/** @brief Pin A5 **/ |
|
81 |
#define _PIN_A5 13 |
|
82 |
/** @brief Pin A6 **/ |
|
83 |
#define _PIN_A6 14 |
|
84 |
/** @brief Pin A7 **/ |
|
85 |
#define _PIN_A7 15 |
|
86 |
|
|
87 |
/** @brief Pin B0 **/ |
|
88 |
#define _PIN_B0 16 |
|
89 |
/** @brief Pin B1 **/ |
|
90 |
#define _PIN_B1 17 |
|
91 |
/** @brief Pin B2 **/ |
|
92 |
#define _PIN_B2 18 |
|
93 |
/** @brief Pin B3 **/ |
|
94 |
#define _PIN_B3 19 |
|
95 |
/** @brief Pin B4 **/ |
|
96 |
#define _PIN_B4 20 |
|
97 |
/** @brief Pin B5 **/ |
|
98 |
#define _PIN_B5 21 |
|
99 |
/** @brief Pin B6 **/ |
|
100 |
#define _PIN_B6 22 |
|
101 |
/** @brief Pin B7 **/ |
|
102 |
#define _PIN_B7 23 |
|
103 |
|
|
104 |
/** @brief Pin C0 **/ |
|
105 |
#define _PIN_C0 24 |
|
106 |
/** @brief Pin C1 **/ |
|
107 |
#define _PIN_C1 25 |
|
108 |
/** @brief Pin C2 **/ |
|
109 |
#define _PIN_C2 26 |
|
110 |
/** @brief Pin C3 **/ |
|
111 |
#define _PIN_C3 27 |
|
112 |
/** @brief Pin C4 **/ |
|
113 |
#define _PIN_C4 28 |
|
114 |
/** @brief Pin C5 **/ |
|
115 |
#define _PIN_C5 29 |
|
116 |
/** @brief Pin C6 **/ |
|
117 |
#define _PIN_C6 30 |
|
118 |
/** @brief Pin C7 **/ |
|
119 |
#define _PIN_C7 31 |
|
120 |
|
|
121 |
/** @brief Pin D0 **/ |
|
122 |
#define _PIN_D0 32 // pin DIO6 on new dragonfly boards |
|
123 |
/** @brief Pin D1 **/ |
|
124 |
#define _PIN_D1 33 // pin DIO7 |
|
125 |
/** @brief Pin D2 **/ |
|
126 |
#define _PIN_D2 34 |
|
127 |
/** @brief Pin D3 **/ |
|
128 |
#define _PIN_D3 35 |
|
129 |
/** @brief Pin D4 **/ |
|
130 |
#define _PIN_D4 36 |
|
131 |
/** @brief Pin D5 **/ |
|
132 |
#define _PIN_D5 37 |
|
133 |
/** @brief Pin D6 **/ |
|
134 |
#define _PIN_D6 38 |
|
135 |
/** @brief Pin D7 **/ |
|
136 |
#define _PIN_D7 39 |
|
137 |
|
|
138 |
/** @brief Pin E0 **/ |
|
139 |
#define _PIN_E0 40 |
|
140 |
/** @brief Pin E1 **/ |
|
141 |
#define _PIN_E1 41 |
|
142 |
/** @brief Pin E2 **/ |
|
143 |
#define _PIN_E2 42 // pin DIO0 |
|
144 |
/** @brief Pin E3 **/ |
|
145 |
#define _PIN_E3 43 // pin DIO1 |
|
146 |
/** @brief Pin E4 **/ |
|
147 |
#define _PIN_E4 44 // pin DIO2 |
|
148 |
/** @brief Pin E5 **/ |
|
149 |
#define _PIN_E5 45 // pin DIO3 |
|
150 |
/** @brief Pin E6 **/ |
|
151 |
#define _PIN_E6 46 // pin DIO4 |
|
152 |
/** @brief Pin E7 **/ |
|
153 |
#define _PIN_E7 47 // pin DIO5 |
|
154 |
|
|
155 |
/** @brief Pin F0 **/ |
|
156 |
#define _PIN_F0 48 |
|
157 |
/** @brief Pin F1 **/ |
|
158 |
#define _PIN_F1 49 |
|
159 |
/** @brief Pin F2 **/ |
|
160 |
#define _PIN_F2 50 |
|
161 |
/** @brief Pin F3 **/ |
|
162 |
#define _PIN_F3 51 |
|
163 |
/** @brief Pin F4 **/ |
|
164 |
#define _PIN_F4 52 |
|
165 |
/** @brief Pin F5 **/ |
|
166 |
#define _PIN_F5 53 |
|
167 |
/** @brief Pin F6 **/ |
|
168 |
#define _PIN_F6 54 |
|
169 |
/** @brief Pin F7 **/ |
|
170 |
#define _PIN_F7 55 |
|
171 |
|
|
172 |
/** @brief Pin G0 **/ |
|
173 |
#define _PIN_G0 56 |
|
174 |
/** @brief Pin WR **/ |
|
175 |
#define _PIN_WR 56 |
|
176 |
/** @brief Pin G1 **/ |
|
177 |
#define _PIN_G1 57 |
|
178 |
/** @brief Pin RD **/ |
|
179 |
#define _PIN_RD 57 |
|
180 |
/** @brief Pin G2 **/ |
|
181 |
#define _PIN_G2 58 |
|
182 |
/** @brief Pin ALE **/ |
|
183 |
#define _PIN_ALE 58 |
|
184 |
/** @brief Pin G3 **/ |
|
185 |
#define _PIN_G3 59 |
|
186 |
/** @brief Pin TOSC2 **/ |
|
187 |
#define _PIN_TOSC2 59 |
|
188 |
/** @brief Pin G4 **/ |
|
189 |
#define _PIN_G4 60 |
|
190 |
/** @brief Pin TOSC1 **/ |
|
191 |
#define _PIN_TOSC1 60 |
|
192 |
//#define _PIN_G5 61 |
|
193 |
//#define _PIN_G6 62 |
|
194 |
//#define _PIN_G7 63 |
|
195 |
|
|
196 |
/* |
|
197 |
These are the header pins (the ones you can connect things to) |
|
198 |
Feel free to use these |
|
199 |
*/ |
|
200 |
|
|
201 |
/** |
|
202 |
* @addtogroup dio |
|
203 |
* @{ |
|
204 |
**/ |
|
205 |
/** @brief Pin A0 **/ |
|
206 |
#define PIN_A0 8 |
|
207 |
/** @brief Pin A1 **/ |
|
208 |
#define PIN_A1 9 |
|
209 |
/** @brief Pin A2 **/ |
|
210 |
#define PIN_A2 10 |
|
211 |
/** @brief Pin A3 **/ |
|
212 |
#define PIN_A3 11 |
|
213 |
/** @brief Pin A4 **/ |
|
214 |
#define PIN_A4 12 |
|
215 |
/** @brief Pin A5 **/ |
|
216 |
#define PIN_A5 13 |
|
217 |
/** @brief Pin A6 **/ |
|
218 |
#define PIN_A6 14 |
|
219 |
/** @brief Pin A7 **/ |
|
220 |
#define PIN_A7 15 |
|
221 |
|
|
222 |
/** @brief Pin SS **/ |
|
223 |
#define PIN_SS 16 |
|
224 |
/** @brief Pin SCK **/ |
|
225 |
#define PIN_SCK 17 |
|
226 |
/** @brief Pin MOSI **/ |
|
227 |
#define PIN_MOSI 18 |
|
228 |
/** @brief Pin MISO **/ |
|
229 |
#define PIN_MISO 19 |
|
230 |
/** @brief LCD Command Pin **/ |
|
231 |
#define PIN_LCD_COMMAND 20 |
|
232 |
|
|
233 |
/** @brief Pin C0 **/ |
|
234 |
#define PIN_C0 24 |
|
235 |
/** @brief Pin C1 **/ |
|
236 |
#define PIN_C1 25 |
|
237 |
/** @brief Pin C2 **/ |
|
238 |
#define PIN_C2 26 |
|
239 |
/** @brief Pin C3 **/ |
|
240 |
#define PIN_C3 27 |
|
241 |
/** @brief Pin C4 **/ |
|
242 |
#define PIN_C4 28 |
|
243 |
/** @brief Pin C5 **/ |
|
244 |
#define PIN_C5 29 |
|
245 |
/** @brief Pin C6 **/ |
|
246 |
#define PIN_C6 30 |
|
247 |
/** @brief Pin C7 **/ |
|
248 |
#define PIN_C7 31 |
|
249 |
|
|
250 |
/** @brief Pin SCL **/ |
|
251 |
#define PIN_SCL 32 |
|
252 |
/** @brief Pin SDA **/ |
|
253 |
#define PIN_SDA 33 |
|
254 |
|
|
255 |
/** @brief Pin RX0 **/ |
|
256 |
#define PIN_RX0 40 |
|
257 |
/** @brief Pin TX0 **/ |
|
258 |
#define PIN_TX0 41 |
|
259 |
/** @brief LCD Reset Pin **/ |
|
260 |
#define PIN_LCD_RESET 42 |
|
261 |
/** @brief Pin E6 **/ |
|
262 |
#define PIN_E6 46 |
|
263 |
/** @brief Pin EXT_DIO1 **/ |
|
264 |
#define PIN_EXT_DIO1 46 |
|
265 |
/** @brief Pin E7 **/ |
|
266 |
#define PIN_E7 47 |
|
267 |
/** @brief Pin EXT_DIO2 **/ |
|
268 |
#define PIN_EXT_DIO2 48 |
|
269 |
|
|
270 |
/** @brief Pin AN0 **/ |
|
271 |
#define PIN_AN0 48 |
|
272 |
/** @brief Pin ADC0 **/ |
|
273 |
#define PIN_ADC0 48 |
|
274 |
/** @brief Pin AN1 **/ |
|
275 |
#define PIN_AN1 49 |
|
276 |
/** @brief Pin ADC1 **/ |
|
277 |
#define PIN_ADC1 49 |
|
278 |
/** @brief Pin AN2 **/ |
|
279 |
#define PIN_AN2 50 |
|
280 |
/** @brief Pin ADC2 **/ |
|
281 |
#define PIN_ADC2 50 |
|
282 |
/** @brief Pin AN3 **/ |
|
283 |
#define PIN_AN3 51 |
|
284 |
/** @brief Pin ADC3 **/ |
|
285 |
#define PIN_ADC3 51 |
|
286 |
/** @brief Pin AN4 **/ |
|
287 |
#define PIN_AN4 52 |
|
288 |
/** @brief Pin ADC4 **/ |
|
289 |
#define PIN_ADC4 52 |
|
290 |
/** @brief Pin AN5 **/ |
|
291 |
#define PIN_AN5 53 |
|
292 |
/** @brief Pin ADC5 **/ |
|
293 |
#define PIN_ADC5 53 |
|
294 |
/** @brief Pin AN6 **/ |
|
295 |
#define PIN_AN6 54 |
|
296 |
/** @brief Pin ADC6 **/ |
|
297 |
#define PIN_ADC6 54 |
|
298 |
/** @brief Pin AN7 **/ |
|
299 |
#define PIN_AN7 55 |
|
300 |
/** @brief Pin ADC7 **/ |
|
301 |
#define PIN_ADC7 55 |
|
302 |
|
|
303 |
/** @brief Wheel Pin **/ |
|
304 |
#define PIN_WHEEL 54 |
|
305 |
/** @brief Battery Voltage Monitor Pin **/ |
|
306 |
#define PIN_BATT 55 |
|
307 |
|
|
308 |
/** @brief button1 Pin **/ |
|
309 |
#define PIN_BTN1 56 |
|
310 |
/** @brief button2 Pin **/ |
|
311 |
#define PIN_BTN2 57 |
|
312 |
|
|
313 |
/** @brief LED1 Pin **/ |
|
314 |
#define PIN_LED1 58 |
|
315 |
|
|
316 |
/* Buttons */ |
|
317 |
/** @brief Button Pin **/ |
|
318 |
#define PIN_BTN PING |
|
319 |
/** @brief button2 Pin **/ |
|
320 |
#define BTN2 PING1 |
|
321 |
/** @brief button1 Pin **/ |
|
322 |
#define BTN1 PING0 |
|
323 |
|
|
324 |
/** @brief Read a portpin. **/ |
|
325 |
int digital_input(int); |
|
326 |
/** @brief Output to a portpin. **/ |
|
327 |
void digital_output(int bit, int val); |
|
328 |
/** @brief Pullup a portpin. **/ |
|
329 |
void digital_pull_up(int); |
|
330 |
|
|
331 |
/** @brief Check if button1 is pressed. **/ |
|
332 |
int button1_read( void ); |
|
333 |
/** @brief Check if button1 is clicked. **/ |
|
334 |
int button1_click( void ); |
|
335 |
/** @brief Wait until button1 is pressed. **/ |
|
336 |
void button1_wait( void ); |
|
337 |
|
|
338 |
/** @brief Check if button2 is pressed. **/ |
|
339 |
int button2_read( void ); |
|
340 |
/** @brief Check if button2 is clicked. **/ |
|
341 |
int button2_click( void ); |
|
342 |
/** @brief Wait until button2 is pressed. **/ |
|
343 |
void button2_wait( void ); |
|
344 |
|
|
345 |
/** @} **/ // end addtogroup |
|
346 |
|
|
347 |
#endif |
|
348 |
|
branches/wireless/code/behaviors/Wireless_Speed_test/time.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 time.h |
|
29 |
* @brief Contains time-related functions and definitions |
|
30 |
* |
|
31 |
* Contains functions and definitions for dealing with time, |
|
32 |
* namely delay_ms and the realtime clock. |
|
33 |
* |
|
34 |
* @author Colony Project, CMU Robotics Club |
|
35 |
**/ |
|
36 |
|
|
37 |
#ifndef _TIME_H_ |
|
38 |
#define _TIME_H_ |
|
39 |
|
|
40 |
|
|
41 |
/* Predefined times for prescale_opt in time.c. |
|
42 |
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 |
|
43 |
to know how many 16ths of a second are in the time you want. (Time_desired * 16 = prescaler_opt) |
|
44 |
*/ |
|
45 |
/** |
|
46 |
* @addtogroup time |
|
47 |
* @{ |
|
48 |
**/ |
|
49 |
/** @brief A sixteenth of a second **/ |
|
50 |
#define SIXTEENTH_SECOND 1 |
|
51 |
/** @brief An eighth of a second **/ |
|
52 |
#define EIGTH_SECOND 2 |
|
53 |
/** @brief A quarter of a second **/ |
|
54 |
#define QUARTER_SECOND 4 |
|
55 |
/** @brief Half of a second **/ |
|
56 |
#define HALF_SECOND 8 |
|
57 |
/** @brief One second **/ |
|
58 |
#define SECOND 16 |
|
59 |
/** @brief Two seconds **/ |
|
60 |
#define TWO_SECOND 32 |
|
61 |
/** @brief Four seconds **/ |
|
62 |
#define FOUR_SECOND 64 |
|
63 |
|
|
64 |
/** @brief Delay execution for the specified time **/ |
|
65 |
void delay_ms(int ms) ; |
|
66 |
/** @brief Enable the realtime clock **/ |
|
67 |
int rtc_init(int prescale_opt, void (*rtc_func)(void)); |
|
68 |
/** @brief Reset the counter of the realtime clock **/ |
|
69 |
void rtc_reset(void); |
|
70 |
/** @brief Get the value of the realtime clock. **/ |
|
71 |
int rtc_get(void); |
|
72 |
|
|
73 |
/** @} **/ |
|
74 |
|
|
75 |
#endif |
|
76 |
|
branches/wireless/code/behaviors/Wireless_Speed_test/xbee.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 xbee.c |
|
28 |
* @brief XBee Interface |
|
29 |
* |
|
30 |
* Implementation of low level communication with the XBee in API mode. |
|
31 |
* |
|
32 |
* @author Brian Coltin, Colony Project, CMU Robotics Club |
|
33 |
**/ |
|
34 |
|
|
35 |
#include "xbee.h" |
|
36 |
#include "wl_defs.h" |
|
37 |
#include "time.h" |
|
38 |
|
|
39 |
//#define ROBOT |
|
40 |
//#define WL_DEBUG |
|
41 |
//#define WL_DEBUG_PRINT( s ) usb_puts( s ) |
|
42 |
//#define WL_DEBUG_PRINT_INT( i ) usb_puti(i) |
|
43 |
|
|
44 |
#ifndef ROBOT |
|
45 |
|
|
46 |
#include <fcntl.h> |
|
47 |
#include <unistd.h> |
|
48 |
#include <pthread.h> |
|
49 |
#include <errno.h> |
|
50 |
#include <termios.h> |
|
51 |
|
|
52 |
#else |
|
53 |
|
|
54 |
#include "serial.h" //////////////////////// |
|
55 |
#include <avr/interrupt.h> |
|
56 |
|
|
57 |
#endif |
|
58 |
|
|
59 |
#include <stdio.h> |
|
60 |
#include <stdlib.h> |
|
61 |
#include <string.h> |
|
62 |
|
|
63 |
#define XBEE_FRAME_START 0x7E |
|
64 |
#define XBEE_GET_PACKET_TIMEOUT 1000 |
|
65 |
|
|
66 |
/*Frame Types*/ |
|
67 |
#define XBEE_FRAME_STATUS 0x8A |
|
68 |
#define XBEE_FRAME_AT_COMMAND 0x08 |
|
69 |
#define XBEE_FRAME_AT_COMMAND_RESPONSE 0x88 |
|
70 |
#define XBEE_FRAME_TX_REQUEST_64 0x00 |
|
71 |
#define XBEE_FRAME_TX_REQUEST_16 0x01 |
|
72 |
#define XBEE_FRAME_TX_STATUS XBEE_TX_STATUS |
|
73 |
#define XBEE_FRAME_RX_64 0x80 |
|
74 |
#define XBEE_FRAME_RX_16 XBEE_RX |
|
75 |
|
|
76 |
/*Internal Function Prototypes*/ |
|
77 |
|
|
78 |
/*I/O Functions*/ |
|
79 |
static int xbee_send(char* buf, int size); |
|
80 |
static int xbee_send_string(char* c); |
|
81 |
|
|
82 |
#ifndef ROBOT |
|
83 |
static int xbee_read(char* buf, int size); |
|
84 |
#endif |
|
85 |
|
|
86 |
/*Command Mode Functions |
|
87 |
* Called during initialization. |
|
88 |
*/ |
|
89 |
static int xbee_enter_command_mode(void); |
|
90 |
static int xbee_exit_command_mode(void); |
|
91 |
static int xbee_enter_api_mode(void); |
|
92 |
static int xbee_exit_api_mode(void); |
|
93 |
static int xbee_wait_for_string(char* s, int len); |
|
94 |
static int xbee_wait_for_ok(void); |
|
95 |
|
|
96 |
/*API Mode Functions*/ |
|
97 |
|
|
98 |
static int xbee_handle_packet(char* packet, int len); |
|
99 |
static int xbee_handle_at_command_response(char* command, char result, char* extra, int extraLen); |
|
100 |
static void xbee_handle_status(char status); |
|
101 |
static int xbee_verify_checksum(char* packet, int len); |
|
102 |
static char xbee_compute_checksum(char* packet, int len); |
|
103 |
static int xbee_send_frame(char* buf, int len); |
|
104 |
int xbee_send_read_at_command(char* command); |
|
105 |
static int xbee_send_modify_at_command(char* command, char* value); |
|
106 |
|
|
107 |
/*Global Variables*/ |
|
108 |
|
|
109 |
#ifndef ROBOT |
|
110 |
static char* xbee_com_port = XBEE_PORT_DEFAULT; |
|
111 |
static int xbee_stream; |
|
112 |
static pthread_t* xbee_listen_thread; |
|
113 |
#endif |
|
114 |
|
|
115 |
// TODO: is this a good size? |
|
116 |
#define XBEE_BUFFER_SIZE 128 |
|
117 |
#define PACKET_BUFFER_SIZE 108 |
|
118 |
// a buffer for data received from the XBee |
|
119 |
char arrival_buf[XBEE_BUFFER_SIZE]; |
|
120 |
// location of last unread byte in buffer |
|
121 |
volatile int buffer_last = 0; |
|
122 |
// first unread byte in buffer |
|
123 |
volatile int buffer_first = 0; |
|
124 |
|
|
125 |
|
|
126 |
//used to store packets as they are read |
|
127 |
static char xbee_buf[PACKET_BUFFER_SIZE]; |
|
128 |
static int currentBufPos = 0; |
|
129 |
|
|
130 |
//XBee status |
|
131 |
static unsigned int xbee_panID = XBEE_PAN_DEFAULT; |
|
132 |
static unsigned int xbee_pending_panID = XBEE_PAN_DEFAULT; |
|
133 |
static int xbee_channel = XBEE_CHANNEL_DEFAULT; |
|
134 |
static int xbee_pending_channel = XBEE_CHANNEL_DEFAULT; |
|
135 |
static volatile unsigned int xbee_address = 0; |
|
136 |
|
|
137 |
/*Function Implementations*/ |
|
138 |
|
|
139 |
#ifdef ROBOT |
|
140 |
|
|
141 |
/** |
|
142 |
* Interrupt for the robot. Adds bytes received from the xbee |
|
143 |
* to the buffer. |
|
144 |
**/ |
|
145 |
#ifndef FIREFLY |
|
146 |
ISR(USART1_RX_vect) |
|
147 |
{ |
|
148 |
char c = UDR1; |
|
149 |
arrival_buf[buffer_last] = c; |
|
150 |
int t = buffer_last + 1; |
|
151 |
if (t == XBEE_BUFFER_SIZE) |
|
152 |
t = 0; |
|
153 |
if (t == buffer_first) |
|
154 |
{ |
|
155 |
WL_DEBUG_PRINT("\nOut of space in buffer.\n"); |
|
156 |
} |
|
157 |
buffer_last = t; |
|
158 |
} |
|
159 |
#else |
|
160 |
SIGNAL(SIG_USART0_RECV) |
|
161 |
{ |
|
162 |
char c = UDR0; |
|
163 |
arrival_buf[buffer_last] = c; |
|
164 |
int t = buffer_last + 1; |
|
165 |
if (t == XBEE_BUFFER_SIZE) |
|
166 |
t = 0; |
|
167 |
if (t == buffer_first) |
|
168 |
{ |
|
169 |
WL_DEBUG_PRINT("Out of space in buffer.\n"); |
|
170 |
} |
|
171 |
buffer_last = t; |
|
172 |
} |
|
173 |
#endif |
|
174 |
|
|
175 |
#else |
|
176 |
|
|
177 |
// Computer code |
|
178 |
|
|
179 |
/** |
|
180 |
* Thread that listens to the xbee. |
|
181 |
**/ |
|
182 |
static void* listen_to_xbee(void* x) |
|
183 |
{ |
|
184 |
char c; |
|
185 |
while (1) |
|
186 |
{ |
|
187 |
if (xbee_read(&c, 1) != 0) { |
|
188 |
WL_DEBUG_PRINT("xbee_read failed.\n"); |
|
189 |
return NULL; |
|
190 |
} |
|
191 |
|
|
192 |
arrival_buf[buffer_last] = c; |
|
193 |
int t = buffer_last + 1; |
|
194 |
if (t == XBEE_BUFFER_SIZE) |
|
195 |
t = 0; |
|
196 |
if (t == buffer_first) |
|
197 |
{ |
|
198 |
WL_DEBUG_PRINT("Out of space in buffer.\n"); |
|
199 |
} |
|
200 |
buffer_last = t; |
|
201 |
|
|
202 |
usleep(1000); |
|
203 |
} |
|
204 |
|
|
205 |
return NULL; |
|
206 |
} |
|
207 |
|
|
208 |
#endif |
|
209 |
|
|
210 |
/** |
|
211 |
* Initializes the XBee library so that other functions may be used. |
|
212 |
**/ |
|
213 |
int xbee_lib_init() |
|
214 |
{ |
|
215 |
if (xbee_init() != 0) { |
|
216 |
usb_puts("xbee_init error"); |
|
217 |
return -1; |
|
218 |
} |
|
219 |
|
|
220 |
WL_DEBUG_PRINT("in xbee_init\n"); |
|
221 |
#ifdef ROBOT |
|
222 |
|
|
223 |
//enable the receiving interrupt |
|
224 |
#ifdef FIREFLY |
|
225 |
UCSR0B |= _BV(RXCIE) | _BV(RXEN); |
|
226 |
#else |
|
227 |
#ifdef BAYBOARD |
|
228 |
UCSR1B |= _BV(RXCIE1); |
|
229 |
#else |
|
230 |
UCSR1B |= _BV(RXCIE); |
|
231 |
#endif |
|
232 |
#endif |
|
233 |
sei(); |
|
234 |
#else |
|
235 |
xbee_stream = open(xbee_com_port, O_RDWR); |
|
236 |
if (xbee_stream == -1/* || lockf(xbee_stream, F_TEST, 0) != 0*/) |
|
237 |
{ |
|
238 |
WL_DEBUG_PRINT("Failed to open connection to XBee on port "); |
|
239 |
WL_DEBUG_PRINT_INT(xbee_com_port); |
|
240 |
WL_DEBUG_PRINT(".\n"); |
|
241 |
return -1; |
|
242 |
} else { |
|
243 |
WL_DEBUG_PRINT("Successfully opened connection to XBee on port "); |
|
244 |
WL_DEBUG_PRINT_INT(xbee_com_port); |
|
245 |
WL_DEBUG_PRINT(".\n"); |
|
246 |
} |
|
247 |
|
|
248 |
// set baud rate, etc. correctly |
|
249 |
struct termios options; |
|
250 |
|
|
251 |
tcgetattr(xbee_stream, &options); |
|
252 |
cfsetispeed(&options, B9600); |
|
253 |
cfsetospeed(&options, B9600); |
|
254 |
options.c_iflag &= ~ICRNL; |
|
255 |
options.c_oflag &= ~OCRNL; |
|
256 |
options.c_cflag |= (CLOCAL | CREAD); |
|
257 |
options.c_cflag &= ~PARENB; |
|
258 |
options.c_cflag &= ~CSTOPB; |
|
259 |
options.c_cflag &= ~CSIZE; |
|
260 |
options.c_cflag |= CS8; |
|
261 |
options.c_lflag &= ~ICANON; |
|
262 |
options.c_cc[VMIN] = 1; |
|
263 |
options.c_cc[VTIME] = 50; |
|
264 |
|
|
265 |
if (tcsetattr(xbee_stream, TCSANOW, &options)) |
|
266 |
{ |
|
267 |
WL_DEBUG_PRINT("Error setting attributes.\n"); |
|
268 |
return -1; |
|
269 |
} |
|
270 |
|
|
271 |
xbee_listen_thread = (pthread_t*)malloc(sizeof(pthread_t)); |
|
272 |
if (xbee_listen_thread == NULL) |
|
273 |
{ |
|
274 |
WL_DEBUG_PRINT("Malloc failed.\n"); |
|
275 |
return -1; |
|
276 |
} |
|
277 |
|
|
278 |
int ret = pthread_create(xbee_listen_thread, NULL, listen_to_xbee, NULL); |
|
279 |
if (ret) |
|
280 |
{ |
|
281 |
WL_DEBUG_PRINT("Failed to create listener thread.\n"); |
|
282 |
return -1; |
|
283 |
} |
|
284 |
#endif |
|
285 |
|
|
286 |
WL_DEBUG_PRINT("Entering command mode.\r\n"); |
|
287 |
|
|
288 |
if (xbee_enter_command_mode() != 0) { |
|
289 |
usb_puts("error entering command mode\r\n"); |
|
290 |
return -1; |
|
291 |
} |
|
292 |
|
|
293 |
WL_DEBUG_PRINT("Entered command mode.\r\n"); |
|
294 |
|
|
295 |
// reset baud rate |
|
296 |
usb_puts("Resetting Baud to "); |
|
297 |
usb_puts(XBEE_BAUD_STR); |
|
298 |
usb_puts("\r\n"); |
|
299 |
|
|
300 |
// set baud on xbee |
|
301 |
#if (XBEE_BAUD == 115200) |
|
302 |
xbee_send_string("ATBD7\r"); |
|
303 |
#end if |
|
304 |
// exit command mode |
|
305 |
xbee_wait_for_ok(); |
|
306 |
xbee_send_string("ATCN\r"); |
|
307 |
xbee_wait_for_ok(); |
|
308 |
|
|
309 |
// set UART baud |
|
310 |
#if (XBEE_BAUD == 250000) |
|
311 |
UBRR1H = 0x00; |
|
312 |
UBRR1L = 3; |
|
313 |
UCSR1A |= _BV(U2X1); |
|
314 |
#elif (XBEE_BAUD == 115200) |
|
315 |
UBRR1H = 0x00; |
|
316 |
UBRR1L = 8; |
|
317 |
UCSR1A |= _BV(U2X1); |
|
318 |
#elif (XBEE_BAUD == 57600) |
|
319 |
if (xbee_send_modify_at_command("BD","6")) { |
|
320 |
return -1; |
|
321 |
} |
|
322 |
UBRR1H = 0x00; |
|
323 |
UBRR1L = 16; |
|
324 |
UCSR1A |= _BV(U2X1); |
|
325 |
#elif (XBEE_BAUD == 38400) |
|
326 |
if (xbee_send_modify_at_command("BD","5")) { |
|
327 |
return -1; |
|
328 |
} |
|
329 |
UBRR1H = 0x00; |
|
330 |
UBRR1L = 25; |
|
331 |
UCSR1A |= _BV(U2X1); |
|
332 |
#elif (XBEE_BAUD == 19200) |
|
333 |
if (xbee_send_modify_at_command("BD","4")) { |
|
334 |
return -1; |
|
335 |
} |
|
336 |
UBRR1H = 0x00; |
|
337 |
UBRR1L = 51; |
|
338 |
UCSR1A |= _BV(U2X1); |
|
339 |
#elif (XBEE_BAUD == 9600) |
|
340 |
/* this is the default baud rate, so do nothing |
|
341 |
if (xbee_send_modify_at_command("BD","3")) { |
|
342 |
return -1; |
|
343 |
} |
|
344 |
UBRR1H = 0x00; |
|
345 |
UBRR1L = 103; |
|
346 |
UCSR1A |= _BV(U2X1);*/ |
|
347 |
#else //Baud rate is defined in the header file, we should not get here |
|
348 |
return 0; |
|
349 |
#endif |
|
350 |
|
|
351 |
// enter command mode |
|
352 |
if (xbee_enter_command_mode() != 0) { |
|
353 |
usb_puts("error entering command mode after baud set\r\n"); |
|
354 |
return -1; |
|
355 |
} |
|
356 |
|
|
357 |
if (xbee_enter_api_mode() != 0) { |
|
358 |
usb_puts("can't enter api mode\r\n"); |
|
359 |
return -1; |
|
360 |
} |
|
361 |
|
|
362 |
WL_DEBUG_PRINT("Entered api mode.\r\n"); |
|
363 |
|
|
364 |
if (xbee_exit_command_mode() != 0) { |
|
365 |
usb_puts("can't exit command mode\r\n"); |
|
366 |
return -1; |
|
367 |
} |
|
368 |
|
|
369 |
WL_DEBUG_PRINT("Left command mode.\r\n"); |
|
370 |
|
|
371 |
// get MY address |
|
372 |
if (xbee_send_read_at_command("BD")) { |
|
373 |
usb_puts("can't send BD command\r\n"); |
|
374 |
return -1; |
|
375 |
} |
|
376 |
WL_DEBUG_PRINT("Getting ATBD rate.\n"); |
|
377 |
|
|
378 |
// get MY address |
|
379 |
if (xbee_send_read_at_command("MY")) { |
|
380 |
usb_puts("can't send my command\r\n"); |
|
381 |
return -1; |
|
382 |
} |
|
383 |
WL_DEBUG_PRINT("Getting ATMY address.\n"); |
|
384 |
|
|
385 |
#ifndef ROBOT |
|
386 |
int i; |
|
387 |
for (i = 0; xbee_address == 0 && i < XBEE_GET_PACKET_TIMEOUT; i++) { |
|
388 |
ret = xbee_get_packet(NULL); |
|
389 |
|
|
390 |
usleep(1000); |
|
391 |
|
|
392 |
/* if (ret == -1) { */ |
|
393 |
/* WL_DEBUG_PRINT("xbee_get_packet(NULL) failed.\n"); */ |
|
394 |
/* return -1; */ |
|
395 |
/* } */ |
|
396 |
} |
|
397 |
#else |
|
398 |
//wait to return until the address is set |
|
399 |
//TODO: this shouldn't wait indefinitely. There should be some sort of reasonable timeout |
|
400 |
// so if the address is never set right, an error can be returned instead of having the |
|
401 |
// robot hang forever |
|
402 |
while (xbee_address == 0) { |
Also available in: Unified diff