Index: branches/wireless/code/projects/libdragonfly/motor.c
===================================================================
--- branches/wireless/code/projects/libdragonfly/motor.c	(nonexistent)
+++ branches/wireless/code/projects/libdragonfly/motor.c	(revision 1493)
@@ -0,0 +1,211 @@
+/**
+ * Copyright (c) 2007 Colony Project
+ * 
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ * 
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ **/
+
+
+/**
+ * @file motor.c
+ * @brief Motors
+ *
+ * Implementation of functions for controlling the motors.
+ *
+ * @author Colony Project, CMU Robotics Club
+ * Much of this is taken from FWR's library, author: Tom Lauwers
+ **/
+
+#include "dragonfly_defs.h"
+#include "motor.h"
+
+/**
+ * @defgroup motors Motors
+ * @brief Functions for controlling the motors.
+ * Functions for controlling the motors. Found in motor.h.
+ * @{
+ **/
+
+unsigned char motors_initd=0;
+
+/**
+ * Initializes both motors so that they can be used with future
+ * calls to motor1_set and motor2_set.
+ *
+ * @return 0 if init succesfull, an error code otherwise
+ *
+ * @see motors_off, motor1_set, motor2_set
+ **/
+int motors_init( void ) {
+
+  if(motors_initd)
+    return ERROR_INIT_ALREADY_INITD;
+
+
+  // Configure counter such that we use phase correct
+  // PWM with 8-bit resolution
+  PORTA &= 0x0F;
+  DDRA |= 0xF0;
+  DDRB |= 0x60;
+
+  //timer 1A and 1B
+  TCCR1A = _BV(COM1A1) | _BV(COM1B1) | _BV(WGM10);
+  TCCR1B = _BV(WGM12) | _BV(CS10);
+  //	TCCR1A = 0xA1;
+  //	TCCR1B = 0x04;
+  OCR1AH=0;
+  OCR1AL=0;
+  OCR1BH=0;
+  OCR1BL=0;
+
+  motors_initd=1;
+  return 0;
+}
+
+/**
+ * Sets the speed and direction of the left motor.
+ * motors_init must be called before this function can be used.
+ *
+ * @param direction Either FORWARD or BACKWARD to set the direction of rotation.
+ * @param speed The speed the motor will run at, in the range 0-255.
+ * 
+ * @return 0 if init succesfull, an error code otherwise
+ *
+ * @see motor_r_set, motors_init
+ **/
+int motor_l_set(int direction, int speed) {
+  if(!motors_initd)
+    return ERROR_LIBRARY_NOT_INITD;
+
+  if(direction == 0) {
+    // turn off PWM first if switching directions
+    if((PORTA & 0x30) != 0x10) {
+      OCR1A = 0;
+    }	
+    PORTA = (PORTA & 0xCF) | 0x10;
+    //		PORTD |= 0x10;
+    //		PORTD &= 0xBF;
+  } else {
+    // turn off PWM first if switching directions
+    if((PORTA & 0x30) != 0x20) {
+      OCR1A = 0;
+    }
+    PORTA = (PORTA & 0xCF) | 0x20;
+    //		PORTD |= 0x40;
+    //		PORTD &= 0xEF;
+  }
+	
+  // Set the timer to count up to speed, an 8-bit value
+  OCR1AL = speed;
+
+  return 0;
+}
+
+/**
+ * Sets the speed and direction of the right motor.
+ * motors_init must be called before this function can be used.
+ *
+ * @param direction Either FORWARD or BACKWARD to set the direction of rotation.
+ * @param speed The speed the motor will run at, in the range 0-255.
+ *
+ * @return 0 if init succesfull, an error code otherwise
+ *
+ * @see motor_l_set, motors_init
+ **/
+int motor_r_set(int direction, int speed) {
+  if(!motors_initd)
+    return ERROR_LIBRARY_NOT_INITD;
+
+  if(direction == 0) {
+    //		PORTD |= 0x20;
+    //		PORTD &= 0x7F;
+    // turn off PWM first if switching directions
+    if((PORTA & 0xC0) != 0x80) {
+      OCR1B = 0;
+    }		
+		
+    PORTA = (PORTA & 0x3F) | 0x80;
+  } else {
+    //		PORTD |= 0x80;
+    //		PORTD &= 0xDF;
+
+    // turn off PWM first if switching directions
+    if((PORTA & 0xC0) != 0x40) {
+      OCR1B = 0;
+    }		
+		
+    PORTA = (PORTA & 0x3F) | 0x40;
+  }
+  OCR1BL = speed;
+
+  return 0;
+}
+
+/**
+ * Sets the speed and direction of motor1.
+ * motors_init must be called before this function can be used.
+ *
+ * @param direction Either FORWARD or BACKWARD to set the direction of rotation.
+ * @param speed The speed the motor will run at, in the range 0-255.
+ *
+ * @return 0 if init succesfull, an error code otherwise
+ *
+ * @see motor2_set, motors_init
+ **/
+int motor1_set(int direction, int speed) {
+  return motor_l_set(direction, speed);
+}
+
+/**
+ * Sets the speed and direction of motor2.
+ * motors_init must be called before this function can be used.
+ *
+ * @param direction Either FORWARD or BACKWARD to set the direction of rotation.
+ * @param speed The speed the motor will run at, in the range 0-255.
+ *
+ * @return 0 if init succesfull, an error code otherwise
+ *
+ * @see motor2_set, motors_init
+ **/
+int motor2_set(int direction, int speed) {
+  return motor_r_set(direction, speed);
+}
+
+
+/**
+ * Turns off both motors.
+ *
+ * @return 0 if init succesfull, an error code otherwise
+ *
+ * @see motors_init
+ **/
+int motors_off( void ) {
+  if(!motors_initd)
+    return ERROR_LIBRARY_NOT_INITD;
+
+  OCR1AL = 0x0;
+  OCR1BL = 0x0;
+
+  return 0;
+}
+
+/**@}**///end defgroup
+
Index: branches/wireless/code/projects/libdragonfly/motor.h
===================================================================
--- branches/wireless/code/projects/libdragonfly/motor.h	(nonexistent)
+++ branches/wireless/code/projects/libdragonfly/motor.h	(revision 1493)
@@ -0,0 +1,71 @@
+/**
+ * Copyright (c) 2007 Colony Project
+ * 
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ * 
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ **/
+
+
+/**
+ * @file motor.h
+ * @brief Contains definitions for controlling the motors
+ *
+ * Contains definitions and functions for controlling
+ * the motors.
+ *
+ * @author Colony Project, CMU Robotics Club
+ * Based on Tom Lauwer's Firefly Library
+ **/
+
+#ifndef _MOTOR_H
+#define _MOTOR_H
+
+#include <avr/io.h>
+
+/**
+ * @addtogroup motors
+ * @{
+ **/
+
+/** @brief make the motors go forwards **/
+#define FORWARD 1
+/** @brief make the motors go backwards **/
+#define BACKWARD 0
+
+/** @brief Initialize the motors **/
+int motors_init(void);
+/** @brief Set speed and direction of motor1 
+ *  @deprecated use the left motor function instead. it's more intuitive and easier to read.**/
+int motor1_set(int direction, int speed);
+/** @brief Set speed and direction of motor2 
+ *  @deprecated use the right motor function instead. it's more intuitive and easier to read.**/
+int motor2_set(int direction, int speed);
+/** @brief Set speed and direction of left motor **/
+int motor_l_set(int direction, int speed);
+/** @brief Set speed and direction of right motor **/
+int motor_r_set(int direction, int speed);
+/** @brief Turn the motors off **/
+int motors_off(void);
+
+/**@}**/ // end addtogroup
+
+#endif
+
Index: branches/wireless/code/projects/libdragonfly/serial.c
===================================================================
--- branches/wireless/code/projects/libdragonfly/serial.c	(nonexistent)
+++ branches/wireless/code/projects/libdragonfly/serial.c	(revision 1493)
@@ -0,0 +1,430 @@
+/**
+ * Copyright (c) 2007 Colony Project
+ * 
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ * 
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ **/
+
+
+/**
+ * @file serial.c
+ * @brief Serial Input and Output
+ *
+ * Implementation of functions for serial input and output.
+ *
+ * @author Colony Project, CMU Robotics Club
+ **/
+
+#include <avr/io.h>
+
+#include "dragonfly_defs.h"
+#include "serial.h"
+
+unsigned char usb_initd=0;
+unsigned char xbee_initd=0;
+
+#ifdef USE_STDIO
+
+#include <stdio.h>
+
+/**
+ * For use with fprintf() and related stdio functions
+ **/
+FILE *usb_fd;
+
+/**
+ * For use with fprintf() and related stdio functions
+ **/
+FILE *xbee_fd;
+
+#endif
+
+/**
+ * Initializes communication over the USB serial port.
+ * This must be called before any other usb function
+ * may be used.
+ **/
+int usb_init() {
+  //Set baud rate
+  // - 115200 (both wired and wireless) is UBRR=8, U2X=1
+  // - 9600 is U2X =1, UBRR = 107.
+
+  if(usb_initd) {
+    return ERROR_INIT_ALREADY_INITD;
+  }
+
+#if (USB_BAUD == 115200)
+  UBRR0H = 0x00;
+  UBRR0L = 8;
+  UCSR0A |= _BV(U2X0);
+#elif (USB_BAUD == 9600)
+  UBRR0H = 0x00;
+  UBRR0L = 103;
+  UCSR0A |= _BV(U2X0);
+#else //Baud rate is defined in the header file, we should not get here
+  return 0;
+#endif
+
+  /*Enable receiver and transmitter */
+  UCSR0B |= (1<<RXEN0)|(1<<TXEN0);
+	
+  /* Set frame format: 8data, 1stop bit, asynchronous normal mode */
+  UCSR0C |= (1<<UCSZ00) | (1<<UCSZ01);
+  
+  // if we have enabled the stdio stuff, then we init it here
+#ifdef USE_STDIO
+  /* Open the stdio stream corresponding to this port */
+  usb_fd = fdevopen(usb_putc, usb_getc);
+#endif
+
+  usb_initd = 1;
+  return 0;
+
+}
+
+/**
+ * Initializes communication over the XBee.
+ * This must be called before any other xbee function
+ * may be used.
+ **/
+int xbee_init() {
+
+  if(xbee_initd) {
+    return ERROR_INIT_ALREADY_INITD;
+  }
+
+  //Set baud rate
+  // - 115200 (both wired and wireless) is UBRR=8, U2X=1
+  // - 9600 is U2X =1, UBRR = 107.
+#if (XBEE_BAUD == 115200)
+  UBRR1H = 0x00;
+  UBRR1L = 8;
+  UCSR1A |= _BV(U2X1);
+#elif (XBEE_BAUD == 9600)
+  UBRR1H = 0x00;
+  UBRR1L = 103;
+  UCSR1A |= _BV(U2X1);
+#else //Baud rate is defined in the header file, we should not get here
+  return 0;
+#endif
+
+  //Enable receiver and transmitter
+  UCSR1B |= (1<<RXEN1)|(1<<TXEN1);
+	
+  // Set frame format: 8data, 1stop bit, asynchronous normal mode
+  UCSR1C |= (1<<UCSZ10) | (1<<UCSZ11);
+  
+  // if we have enabled the stdio stuff, then we init it here
+#ifdef USE_STDIO
+  /* Open the stdio stream corresponding to this port */
+  xbee_fd = fdevopen(xbee_putc, xbee_getc);
+#endif
+
+  xbee_initd = 1;
+  return 0;
+
+}
+
+/**
+ * Sends a character over USB.
+ *
+ * @param c the character to send
+ * @return 0 for success, nonzero for failure
+ **/
+int usb_putc(char c) {
+
+  if(!usb_initd)
+    return ERROR_LIBRARY_NOT_INITD;
+
+  // Wait until buffer is clear for sending
+  loop_until_bit_is_set(UCSR0A, UDRE0);
+	
+  // Load buffer with your character
+  UDR0 = c;
+  return 0;
+}
+
+/**
+ * Sends a character to the XBee.
+ *
+ * @param c the character to send
+ * @return 0 for success, nonzero for failure
+ **/
+int xbee_putc(char c) {
+
+  if(!xbee_initd)
+    return ERROR_LIBRARY_NOT_INITD;
+
+  // Wait until buffer is clear for sending
+  loop_until_bit_is_set(UCSR1A, UDRE1);
+	
+  // Load buffer with your character
+  UDR1 = c;
+  return 0;
+}
+
+/**
+ * Sends a sequence of characters over USB.
+ *
+ * @param s the string to send
+ * @return 0 for success, nonzero for failure
+ **/
+int usb_puts(char *s) {
+  char *t = s;
+
+  if(!usb_initd)
+    return ERROR_LIBRARY_NOT_INITD;
+
+  while (*t != 0) {
+    usb_putc(*t);
+    t++;
+  }
+  return 0;
+}
+
+/**
+ * Sends a sequence of characters from program space over USB.
+ *
+ * @param s the string to send
+ *
+ * @return 0 if init succesfull, an error code otherwise
+ **/
+int usb_puts_P (PGM_P s) {
+    char buf;
+
+    if(!usb_initd)
+      return ERROR_LIBRARY_NOT_INITD;
+	
+    while (memcpy_P (&buf, s, sizeof (char)), buf!=0) {
+        usb_putc (buf);
+        s++;
+    }
+
+    return 0;
+}
+
+
+
+/**
+ * Returns the first character in the buffer received from USB.
+ * This function blocks execution until a character has been received.
+ * xbee_init must be called before this function may be used.
+ * 
+ * @return the first character in the usb buffer, -1 on error
+ *
+ * @see usb_init, usb_getc_nb
+ **/
+int usb_getc(void) {
+
+  if(!usb_initd)
+    return -1;
+
+  // Wait for the receive buffer to be filled
+  loop_until_bit_is_set(UCSR0A, RXC0);
+	
+  // Read the receive buffer
+  return UDR0;
+}
+
+/**
+ * Returns the first character in the buffer received from USB.
+ * This function blocks execution until a character has been
+ * received. xbee_init must be called before this function
+ * may be used.
+ * 
+ * @return the first character in the xbee buffer, -1 on error
+ * 
+ * @see xbee_init, xbee_getc_nb
+ **/
+int xbee_getc(void) {
+
+  if(!usb_initd)
+    return -1;
+
+  // Wait for the receive buffer to be filled
+  loop_until_bit_is_set(UCSR1A, RXC1);
+	
+  // Read the receive buffer
+  return UDR1;
+}
+
+/**
+ * Non blocking version of usb_getc. If a character is present in the buffer,
+ * it is returned, otherwise -1 is returned immediately. usb_init must be
+ * called before this function can be used.
+ *
+ * @param c the received character. This will be set if a character has
+ * been received.
+ * 
+ * @return -1 if no character is available, 0 otherwise, positive for error
+ * 
+ * @see usb_init, usb_getc
+ **/
+int usb_getc_nb(char *c) {
+
+  if(!usb_initd)
+    return ERROR_LIBRARY_NOT_INITD;
+
+  // check if the receive buffer is filled
+  if (UCSR0A & _BV(RXC0)) {
+    // Read the receive buffer
+    (*c) = UDR0;
+    return 0;
+  } else {
+    // Return empty
+    return -1;
+  }
+}
+
+/**
+ * Non blocking version of xbee_getc. If a character is present in the buffer,
+ * it is returned, otherwise -1 is returned immediately. xbee_init
+ * must be called before this function can be used.
+ *
+ * @param c the received character. This will be set if a character has
+ * been received.
+ * 
+ * @return -1 if no character is available, 0 otherwise, positive for error
+ *
+ * @see xbee_init, xbee_getc
+ **/
+int xbee_getc_nb(char *c) {
+  if(!xbee_initd)
+    return ERROR_LIBRARY_NOT_INITD;
+
+  // check if the receive buffer is filled
+  if (UCSR1A & _BV(RXC1)) {
+    // Read the receive buffer
+    (*c) = UDR1;
+    return 0;
+  } else {
+    // Return empty
+    return -1;
+  }
+}
+
+
+/*
+  prints an int to serial
+
+  code adapted from Chris Efstathiou's code (hendrix@otenet.gr)
+  uses usb_putc
+*/
+/**
+ * Prints an integer, converted to ASCII, to usb. usb_init must be called
+ * before this function can be used.
+ *
+ * @param value the integer to print
+ * 
+ * @return 0 if successful, nonzero otherwise
+ *
+ * @see usb_init, usb_putc
+ **/
+int usb_puti(int value ) {
+  unsigned char usb_data[6]={'0','0','0','0','0','0' }, position=sizeof(usb_data), radix=10; 
+
+  if(!usb_initd)
+    return ERROR_LIBRARY_NOT_INITD;
+
+
+  /* convert int to ascii  */ 
+  if(value<0) { 
+    usb_putc('-'); 
+    value=-value; 
+  }    
+  do { 
+    position--; 
+    *(usb_data+position)=(value%radix)+'0'; 
+    value/=radix;  
+  } while(value); 
+
+    
+  /* start displaying the number */
+  for(;position<=(sizeof(usb_data)-1);position++) {
+            
+    usb_putc(usb_data[position]);
+  }
+
+  return 0;
+}
+
+/**
+ * Determines a hexadecimal digit in ASCII code.
+ *
+ * @param value the value of the digit (0<=value<=15)
+ * 
+ * @return the hexadecimal digit in ASCII code, or '?'
+ * if the input is invalid.
+ **/
+uint8_t hex_digit (uint8_t value)
+{
+    if (value>15) return '?';
+    // Postcondition: 0<=x<=15
+
+    return "0123456789ABCDEF"[value];
+}
+
+/**
+ * Prints a fixed width hexadecimal representation of an unsigned
+ * 16 bit integer in ASCII code to USB.
+ * usb_init must be called before this function can be used.
+ *
+ * @param value the value to print
+ * 
+ * @see usb_init, usb_puti, usb_puts, usb_puth8, hex_digit
+ *
+ * @return 0 if init succesfull, an error code otherwise
+ **/
+int usb_puth16 (uint16_t value)
+{
+    if(!usb_initd)
+      return ERROR_LIBRARY_NOT_INITD;
+
+    usb_putc (hex_digit((value >>12)&0xF));
+    usb_putc (hex_digit((value >>8 )&0xF));
+    usb_putc (hex_digit((value >>4 )&0xF));
+    usb_putc (hex_digit( value      &0xF));
+
+    return 0;
+}
+
+/**
+ * Prints a fixed width hexadecimal representation of an unsigned
+ * 8 bit integer in ASCII code to USB.
+ * usb_init must be called before this function can be used.
+ *
+ * @param value the value to print
+ * 
+ * @see usb_init, usb_puti, usb_puts, usb_puth16, hex_digit
+ *
+ * @return 0 if init succesfull, an error code otherwise
+ **/
+int usb_puth8(uint8_t value)
+{
+    if(!usb_initd)
+      return ERROR_LIBRARY_NOT_INITD;
+
+    usb_putc (hex_digit ((value)>>4 &0xF));
+    usb_putc (hex_digit ( value     &0xF));
+
+    return 0;
+}
+
Index: branches/wireless/code/projects/libdragonfly/dragonfly_lib.h
===================================================================
--- branches/wireless/code/projects/libdragonfly/dragonfly_lib.h	(nonexistent)
+++ branches/wireless/code/projects/libdragonfly/dragonfly_lib.h	(revision 1493)
@@ -0,0 +1,80 @@
+/**
+ * Copyright (c) 2007 Colony Project
+ * 
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ * 
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ **/
+
+
+/**
+ * @file dragonfly_lib.h
+ * @brief Contains other include files
+ * 
+ * Include this file for all the functionality of libdragonfly.
+ *
+ * @author Colony Project, CMU Robotics Club
+ **/
+
+#ifndef _DRAGONFLY_LIB_H_
+#define _DRAGONFLY_LIB_H_
+
+/**
+ * @addtogroup dragonfly
+ * @{
+ **/
+
+/** @brief Initialize the board **/
+void dragonfly_init(int config);
+
+/** @} **/ //end addtogroup
+
+#include <inttypes.h>
+#include <avr/io.h>
+#include <avr/interrupt.h>
+#include <util/delay.h>
+#include <util/twi.h>
+
+// This file is included from the libdragonfly directory because it seems to be
+// missing from the AVR libc distribution.
+#include "atomic.h"
+
+#include "dragonfly_defs.h"
+#include "analog.h"
+#include "dio.h"
+#include "time.h"
+#include "lcd.h"
+#include "lights.h"
+#include "motor.h"
+#include "serial.h"
+#include "buzzer.h"
+#include "rangefinder.h"
+#include "bom.h"
+#include "encoders.h"
+#include "move.h"
+#include "reset.h"
+#include "math.h"
+#include "eeprom.h"
+
+#include <stddef.h>
+#include <stdbool.h>
+
+#endif
+
Index: branches/wireless/code/projects/libdragonfly/serial.h
===================================================================
--- branches/wireless/code/projects/libdragonfly/serial.h	(nonexistent)
+++ branches/wireless/code/projects/libdragonfly/serial.h	(revision 1493)
@@ -0,0 +1,146 @@
+/**
+ * Copyright (c) 2007 Colony Project
+ * 
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ * 
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ **/
+
+
+/**
+ * @file serial.h
+ * @brief Contains declarations for serial input and output
+ *
+ * Contains definitions for serial input and output.
+ *
+ * @author Colony Project, CMU Robotics Club
+ * Based on Tom Lauwer's Firefly Library
+ *
+ **/
+
+/*
+  serial.h - Contains definitions and function prototypes for the RS232 serial port
+  author(s): pkv
+  
+  Directions:
+  Call the initialization function for the serial port you wish to use.  Then, use
+  either the provided functions or the stdio functions (fprintf, etc) to read and
+  write characters to the serial ports.
+  
+  UART Mapping:
+  usb_*() -> UART0
+  xbee_*() -> UART1
+  
+  Options: (Add the following defines to your code to configure this library)
+  #define USB_BAUD { 115200 | 9600 } <= pick ONE value from in here
+  #define XBEE_BAUD { 115200 | 9600 } <= pick ONE value from in here
+  #define USE_STDIO
+  
+  Note: If you enable USE_STDIO, the first init function that is called will 
+  automatically be linked to stdin, stdout, and stderr.  To use the baud rate 
+  commands, add something like the following to your code:
+  
+  #define FOO_BAUD 9600
+  
+  **UNLESS YOU KNOW WHAT YOU ARE DOING, PLEASE DO NOT CHANGE THIS FILE**
+  Many, many other people use this file in their code.  If you change it, you will
+  probably break all of their nice code.  You should not need to change anything in
+  here, except to accomodate new hardware.
+*/
+
+#ifndef _SERIAL_H
+#define _SERIAL_H
+
+#include <inttypes.h>
+#include <avr/pgmspace.h>
+
+/**
+ * @defgroup usb USB Input / Output
+ * @brief Functions for USB input / output
+ *
+ * Low level functions for USB input and output.
+ *
+ * @{
+ **/
+
+// if no baud rate is defined for usb, default is set here
+#ifndef USB_BAUD
+/** @brief the USB baud rate **/
+#define USB_BAUD 115200
+#endif
+
+/** @brief Initialize the USB **/
+int usb_init(void);
+/** @brief Print a character to USB **/
+int usb_putc(char c);
+/** @brief Read a character from USB **/
+int usb_getc(void);
+/** @brief Read a character from USB without blocking **/
+int usb_getc_nb(char *c);
+/** @brief Print a string to USB **/
+int usb_puts(char *s);
+/** @brief Print a string from program space to USB **/
+int usb_puts_P (PGM_P s);
+/** @brief Print an integer to USB **/
+int usb_puti(int value);
+/** @brief Determine a hexadecimal digit **/
+uint8_t hex_digit (uint8_t value);
+/** @brief Print a fixed width hexadecimal representation to USB **/
+int usb_puth16 (uint16_t value);
+/** @brief Print a fixed width hexadecimal representation to USB **/
+int usb_puth8(uint8_t value);
+/** @brief Alias for usb_puth16 **/
+static inline void usb_puth (uint16_t value) { usb_puth16 (value); };
+
+
+/** @} **/ //end addtogroup
+
+/**
+ * @defgroup xbee XBee Input / Output
+ * @brief Functions for XBee input / output
+ *
+ * Low level functions for XBee input and output.
+ *
+ * @{
+ **/
+
+// if no baud rate is defined for usb, default is set here
+
+// if no baud rate is defined for xbee, default is set here
+#ifndef XBEE_BAUD
+/** @brief the XBee baud rate **/
+#define XBEE_BAUD 9600
+#endif
+
+/** @brief Initialize the XBee **/
+int xbee_init(void);
+/** @brief Print a character to the XBee **/
+int xbee_putc(char c);
+/** @brief Read a character from the XBee **/
+int xbee_getc(void);
+/** @brief Read a character from the XBee without blocking **/
+int xbee_getc_nb(char *c);
+
+
+
+/** @} **/ //end addtogroup
+
+#endif
+
Index: branches/wireless/code/projects/libdragonfly/spi.c
===================================================================
--- branches/wireless/code/projects/libdragonfly/spi.c	(nonexistent)
+++ branches/wireless/code/projects/libdragonfly/spi.c	(revision 1493)
@@ -0,0 +1,90 @@
+/**
+ * @file spi.c
+ * @brief Basic SPI module to handle encoders
+ * @author Colony Project, CMU Robotics Club
+ *	Need to move spi.h include into dragonfly_lib.h when stable
+ **/
+
+#include <avr/interrupt.h>
+
+#include "dragonfly_defs.h"
+#include "spi.h"
+
+unsigned char spi_initd=0;
+
+static volatile char spi_bytes; /* number of bytes to read */
+static spi_fun_recv_t spi_recv_func; /* byte handler */
+static spi_fun_recv_complete_t spi_recv_complete_func; /*transmission completion handler */
+
+/** 
+* @brief Initialize SPI hardware for communication.
+* 
+* @param recv_func The function to be called for each byte of data received.
+* @param recv_complete_func  The function to be called at the end of a complete transmission.
+*
+* @return 0 if init succesfull, an error code otherwise
+*/
+int spi_init (spi_fun_recv_t recv_func, spi_fun_recv_complete_t recv_complete_func)
+{
+    if(spi_initd) {
+      return ERROR_INIT_ALREADY_INITD;
+    }
+
+    /*  Enable Interrupt, Enable SPI Module, MSB First, Master Mode, Clock div = 64 */
+    SPCR = _BV(SPE) | _BV(SPIE) /*| _BV(DORD)*/ | _BV(MSTR) | _BV(SPR1) | _BV(SPR0);
+    SPSR = _BV(SPI2X); 
+
+    /* Set SCLK, SS, MOSI as outputs. MISO as input */
+    DDRB |= MOSI | SCLK | SS;
+    DDRB &= ~MISO;
+    
+    /* Keep SS high until transmit */
+    PORTB |= SS;
+
+    /* set function to be executed when we receive a byte */
+    spi_recv_func = recv_func;
+    spi_recv_complete_func = recv_complete_func;
+    spi_bytes = 0;
+    //usb_puts("\tspi.c Debug: SPI INITIALIZED\n");
+
+    spi_initd=1;
+    return 0;
+}
+
+/** 
+* @brief Transfer a given byte to slave and receive a byte 
+* 
+* @param bytes The number of bytes to be transferred.
+**/
+int spi_transfer(char bytes)
+{
+    if(!spi_initd)
+      return ERROR_LIBRARY_NOT_INITD;
+
+    spi_bytes = bytes;
+    PORTB &= ~SS; /* Set SS low to initiate transmission */
+    SPDR = 0xff; /* Initiate data transmision */
+
+    return 0;
+}
+
+ISR(SIG_SPI) 
+{
+	//usb_puts("Interrupt");
+    /* only handle intterupt when we are expecting data */
+    if(spi_bytes > 0){
+	/* process byte */
+	spi_recv_func(SPDR);
+	/* if we've read all the bytes, set SS high to end transmission,
+	 * otherwise get the next byte  */
+	if(--spi_bytes == 0){
+		//usb_puts("Read all bytes\r\n");
+		PORTB |= SS;
+		if(spi_recv_complete_func)
+			spi_recv_complete_func();
+	}else {
+		//usb_puts("There are this many bytes left: "); usb_puti(spi_bytes);usb_puts("\r\n");
+		SPDR = 0xff;
+	}
+    }
+}		
Index: branches/wireless/code/projects/libdragonfly/time.c
===================================================================
--- branches/wireless/code/projects/libdragonfly/time.c	(nonexistent)
+++ branches/wireless/code/projects/libdragonfly/time.c	(revision 1493)
@@ -0,0 +1,216 @@
+/**
+ * Copyright (c) 2007 Colony Project
+ * 
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ * 
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ **/
+
+
+/**
+ * @file time.c
+ * @brief Timer code
+ *
+ * Implementation of functions for timers.
+ *
+ * @author Colony Project, CMU Robotics Club
+ **/
+
+/*
+  time.c
+  anything that requires a delay
+  mostly delay_ms
+
+  author: Robotics Club, Colony Project
+
+  Change Log:
+  2.5.07 - Kevin
+  Aaron fixed the orb/servo code and made them use timer3 but compare registers B and C. He hard set the prescaler
+  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.
+  You now count how many 16ths of a second you want until you trigger your actual interrupt. Works. Changed defines
+  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
+  etc. Read that section in the time.h file for more information. Tested and works, though the clock drifts more than
+  it used to
+  1.30.07 - Kevin
+  Modified the clock to run on timer3 on the Dragonfly. Works with decent accuracy. Using a prescaler of 256
+  the timer counts up to a precomputer value which will trigger an interrupt and reset the timer. Multiples of
+  256 change it by that multiple. Refer to the time.h file for all possible prescalers.
+  The interrupt will call a specified function _rtc_func every pulse.
+  All of it has been tested and it works.
+
+*/
+#include <avr/interrupt.h>
+#include <util/delay.h>
+
+#include "dragonfly_defs.h"
+#include "time.h"
+
+
+/* Calculate how many cycles to delay for to get 1 ms. Based on F_CPU which should be defined by the makefile */
+#ifdef F_CPU
+#define WAIT_CYCLES ((F_CPU / 1000) / 10)
+#else
+#define WAIT_CYCLES (8000 / 10)
+#endif
+
+
+unsigned char time_initd = 0;
+
+static volatile int _rtc_val = 0;
+static volatile int _rtc_pulse = 0;
+static volatile int _rtc_scale = 32;	//Defaults to 1 Second per pulse
+static void (*_rtc_f)(void) = 0;
+
+
+
+/**
+ * @defgroup time Time
+ * @brief Time functions
+ * 
+ * Functions dealing with time.
+ * 
+ * @{
+ **/
+
+/**
+ * Delays for the specified number of milliseconds.
+ * It depends on F_CPU to be defined in order to calculate how many cycles
+ * it should delay. If it is not defined, a default clock of 8MHz is assumed.
+ * 
+ * We use _delay_loop_2 which will run assembly instructions that should be
+ * 4 cycles long. Optimizations must be enabled for this to be true.
+ * That function is called to ensure around 1ms per execution. To generate
+ * multiple ms we run a for loop of how many milliseconds are desired.
+ *
+ * The error should be just the skew on the oscillator as the formula to 
+ * calculate delay cycles should always be a whole number. The is some skew
+ * in practice though it is unavoidable. Delaying for less than 1s should make
+ * the error negligable.
+ *
+ * @param ms the number of milliseconds to delay for
+ **/
+void delay_ms(int ms) {
+    for (; ms > 0; ms--) {
+        _delay_loop_2(WAIT_CYCLES);
+    }
+}
+
+
+/* 	Prescales defined in time.h. SECOND will give you 1 second.
+	More scales are defined in the time.h file.
+	rtc_func is the address to a function that you want called every clock tick. */
+/**
+ * Initializes the real time clock. Prescales are defined in time.h.
+ * For example, SECOND will give 1 second. The specified function is
+ * called every clock tick. For the real time clock to activate,
+ * interrupts must be enabled. (through sei() )
+ *
+ * @param prescale_opt the period with which the timer is triggered
+ * @param rtc_func the function called when the timer is triggered
+ *
+ * @return 0 if init succesfull, an error code otherwise
+ *
+ * @see rtc_get, rtc_reset
+ *
+ **/
+int rtc_init(int prescale_opt, void (*rtc_func)(void)) {
+
+  if(time_initd) {
+    return ERROR_INIT_ALREADY_INITD;
+  }
+	
+  //Clear timer register for Timer 3
+  TCNT3 = 0;
+	
+  /* 	This sets the Waveform Generation Module to CTC (Clear Timer on Compare) Mode (100)
+	See page135 in Atmega128 Docs for more modes and explanations */
+  TCCR3B |= _BV(WGM32);
+	
+  /* 	This sets the prescaler for the system clock (8MHz) ie: divides the clock by some number.
+	Currently set to a prescaler of 8 because that is what the orb and servos use (they are on this timer as well)
+	See page137 in Atemga128 Docs for all the available prescalers */
+  TCCR3B |= _BV(CS31);
+	
+  /* 	Sets the two regsiters that we compare against. So the timer counts up to this number and
+	then resets back to 0 and calls the compare match interrupt.
+	8x10^6 / 8 = 1/16 Second. All values are based off of this number. Do not change it unless you
+	are l337*/
+		
+  OCR3A = 0xF424;	
+
+  /* 	Enable Output Compare A Interrupt. When OCR3A is met by the timer TCNT3 this interrupt will be
+	triggerd. (See page140 in Atmega128 Docs for more information */
+  ETIMSK |= _BV(OCIE3A);
+	
+  /*	Store the pointer to the function to be used in the interrupt */
+  _rtc_f = rtc_func;
+	
+  /*	Store how many 1/16ths of a second you want to let by before triggering an interrupt */
+  _rtc_scale = prescale_opt;
+
+  time_initd = 1;
+
+  return 0;
+}
+
+/**
+ * Returns the time elapsed in seconds since the last call to
+ * rtc_init or rtc_reset.
+ *
+ * @return the number of seconds since the last call to rtc_init or rtc_reset
+ *
+ * @see rtc_init, rtc_reset
+ **/
+int rtc_get(void) {
+  return _rtc_val;
+}
+
+/**
+ * Resets the real time clock counter to 0.
+ *
+ * @see rtc_init, rtc_get
+ **/
+void rtc_reset(void) {
+  _rtc_val = 0;
+}
+
+/** @} **/ //end defgroup
+
+/*	Called every pulse. Function in _rtc_f is called every _rtc_scale and also the counter is updated.
+	Bascially, since the pulse is hard set at 1/16s  you want to count how many 16ths of a second have passed
+	and when it reaches the amount of time you want, execute the code. */
+SIGNAL(TIMER3_COMPA_vect) {
+
+  if (_rtc_pulse ==  _rtc_scale) {
+    //Increment the real time clock counter
+    _rtc_val++;
+		
+    //Calls the function tied to the real time clock if defined
+    if(_rtc_f != 0)
+      _rtc_f();
+		
+    //Resets the pulse until the next scale is matched
+    _rtc_pulse = 0;
+  }	
+	
+  //Updates the amount of pulses seen since the last scale match
+  _rtc_pulse++;
+	
+}
Index: branches/wireless/code/projects/libdragonfly/spi.h
===================================================================
--- branches/wireless/code/projects/libdragonfly/spi.h	(nonexistent)
+++ branches/wireless/code/projects/libdragonfly/spi.h	(revision 1493)
@@ -0,0 +1,46 @@
+/**
+ * @file spi.h
+ * @brief Definitions for SPI
+ * @author Colony Project, CMU Robotics Club
+ **/
+
+/**
+ * @addtogroup spi
+ * @{
+ **/
+
+#ifndef __SPI_H__
+#define __SPI_H__
+
+#define DOUBLE_SCK 1
+#define SPR0_BIT 1
+
+#define MASTER 1
+#define SLAVE 0
+
+#define MOSI _BV(PB2)
+#define MISO _BV(PB3)
+#define SS   _BV(PB0)
+#define SCLK _BV(PB1)
+
+typedef int (*spi_fun_recv_t)(char);
+typedef void (*spi_fun_recv_complete_t)(void);
+
+/** 
+* @brief Initialize SPI
+* 
+* @param spi_fun_recv_t The function that handles SPI data, byte for byte.
+* @param spi_fun_recv_complete_t  Called on a completed transmission - typically for cleaning up.
+*/
+int spi_init (spi_fun_recv_t, spi_fun_recv_complete_t);
+
+/** 
+* @brief Initialize SPI transfer.
+* 
+* @param char The number of bytes to transfer.
+*/
+int spi_transfer (char);
+
+/**@}**/ //end group
+
+#endif
Index: branches/wireless/code/projects/libdragonfly/analog.c
===================================================================
--- branches/wireless/code/projects/libdragonfly/analog.c	(nonexistent)
+++ branches/wireless/code/projects/libdragonfly/analog.c	(revision 1493)
@@ -0,0 +1,398 @@
+/**
+ * Copyright (c) 2007 Colony Project
+ * 
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ * 
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ **/
+
+/**
+ * @file analog.c
+ * @brief Analog input and output
+ *
+ * Contains functions for manipulating the ADC on the Dragonfly board.
+ * 
+ * @author Colony Project, CMU Robotics Club
+ * originally taken from fwr analog file (author: Tom Lauwers)
+ * loop code written by Kevin Woo and James Kong
+ **/
+
+#include <util/delay.h>
+#include <avr/interrupt.h>
+
+
+#include "dragonfly_defs.h"
+#include "serial.h"
+#include "analog.h"
+// Internal Function Prototypes
+void set_adc_mux(int which);
+
+/**
+ * @defgroup analog Analog
+ * Functions for manipulation the ADC on the dragonfly board.
+ * All definitions may be found in analog.h.
+ *
+ * @{
+ **/
+
+unsigned char analog_initd=0;
+
+volatile int adc_loop_status = ADC_LOOP_STOPPED;
+volatile int adc_sig_stop_loop = 0;
+volatile int adc_current_port = 0;
+volatile adc_t an_val[11];
+
+/**
+ * Initializes the ADC.
+ * Call analog_init before reading from the analog ports.
+ *
+ * @return returns 0 on success, nonzero on error
+ *
+ * @see analog8, analog10, analog_get8, analog_get10
+ *
+ * @bug First conversion takes a performance penalty of
+ * 25 vs. 13 ADC clock cycles of successive conversions.
+ * Analog_init should run a dummy conversion to pre-empt
+ * this.
+ *
+ * For good 10-bit precision, ACD clock must be between
+ * 50kHz and 200kHz. Currently, ADC clock is fixed at
+ * 125kHz using 1/64prescalar. However, most code uses
+ * 8-bit precision which can work at ADC clock speeds
+ * higher than 200kHz. Experimental tests needed to
+ * determine highest clock speed for accurate 8-bit ADC.
+ *
+ **/
+int analog_init(int start_conversion) {
+  if(analog_initd)
+    return ERROR_INIT_ALREADY_INITD;
+
+  for (int i = 0; i < 11; i++) {
+    an_val[i].adc10 = 0;
+    an_val[i].adc8 = 0;
+  }
+
+  // ADMUX register
+  // Bit 7,6 - Set voltage reference to AVcc (0b01)
+  // Bit 5 - ADLAR set to simplify moving from register
+  // Bit 4 - X
+  // Bit 3:0 - Sets the current channel
+  // Initializes to read from AN1 first (AN0 is reservered for the BOM)
+  ADMUX = 0;
+  ADMUX |= ADMUX_OPT | _BV(MUX0);
+
+  // ADC Status Register A
+  // Bit 7 - ADEN is set (enables analog)
+  // Bit 6 - Start conversion bit is set (must be done once for free-running mode)
+  // Bit 5 - Enable Auto Trigger (for free running mode) NOT DOING THIS RIGHT NOW
+  // Bit 4 - ADC interrupt flag, 0
+  // Bit 3 - Enable ADC Interrupt (required to run free-running mode)
+  // Bits 2-0 - Set to create a clock divisor of 128, to make ADC clock = 8,000,000/64 = 125kHz
+  ADCSRA = 0;
+  ADCSRA |= _BV(ADEN) | _BV(ADPS2) | _BV(ADPS1) | _BV(ADPS0);
+	
+  // Set external mux lines to outputs
+  DDRG |= 0x1C;
+	
+  // Set up first port for conversions
+  set_adc_mux(0x00);
+  adc_current_port = AN1;
+
+  //Start the conversion loop if requested
+  if (start_conversion)
+    analog_start_loop();
+		
+  //Conversion loop disabled by default
+
+  analog_initd=1;
+  return 0;
+}	
+
+/**
+ * Returns the 8-bit analog conversion of which from
+ * the lookup table. If the requested port is the BOM_PORT
+ * you will get an automatic 0 since the BOM_PORT is not
+ * read in the loop and not stored. If you need that port
+ * you should use the functions in bom.c. There is an analog_get8
+ * function which for instant lookups but should be avoided unless
+ * you know what you're doing.
+ *
+ * @param which the port that you want to read
+ *
+ * @bug may cause a seg fault if which is a larger value
+ * than exists in an_val table. Not sure if we should fix
+ * this or not since it would add overhead.
+ *
+ * @return 8-bit analog value for the which port requested
+ *
+ * @see analog10, analog_get8, analog_get10
+ **/
+unsigned int analog8(int which) {
+	if (which == BOM_PORT) {
+		return 0;
+	} else {
+		return an_val[which - 1].adc8;
+	}
+}
+
+/**
+ * Returns the 10-bit analog conversion of which from
+ * the lookup table. If the requested port is the BOM_PORT
+ * you will get an automatic 0 since the BOM_PORT is not
+ * read in the loop and not stored. If you need that port
+ * you should use the functions in bom.c. There is an analog_get10
+ * function which for instant lookups but should be avoided unless
+ * you know what you are doing.
+ *
+ * @param which the port that you want to read
+ *
+ * @bug may cause a seg fault if which is a larger value
+ * than exists in an_val table. Not sure if we should fix
+ * this or not since it would add overhead.
+ *
+ * @return 10-bit analog value for the which port requested
+ *
+ * @see analog8, analog_get8, analog_get10
+ **/
+unsigned int analog10(int which) {
+	if (which == BOM_PORT) {
+		return 0;
+	} else {
+		return an_val[which - 1].adc10;
+	}
+}
+
+/**
+ * Starts the analog update loop. Will continue to run
+ * until analog_stop_loop is called.
+ *
+ * @return returns 0 on success, nonzero on error
+ *
+ * @see analog_stop_loop, analog_loop_status
+ **/
+int analog_start_loop(void) {
+  if(!analog_initd)
+    return ERROR_LIBRARY_NOT_INITD;
+
+  if(adc_loop_status != ADC_LOOP_RUNNING){
+    //Start the conversion, enable ADC interrupt
+    ADCSRA |= _BV(ADIE);
+    ADCSRA |= _BV(ADSC);
+    adc_loop_status = ADC_LOOP_RUNNING;
+  }
+
+  return 0;
+}
+
+/**
+ * Stops the analog update loop. If there is a current
+ * read, it will finish up and be stored before the loop
+ * is interrupted. No further updates will be made until
+ * the loop is started again.
+ *
+ * @return returns 0 on success, nonzero on error
+ *
+ * @see analog_start_loop, analog_loop_status
+ **/
+int analog_stop_loop() {
+  if(!analog_initd)
+    return ERROR_LIBRARY_NOT_INITD;
+
+  //Signal to stop after the next conversion
+  adc_sig_stop_loop = 1;
+
+  return 0;
+}
+
+/**
+ * Returns the status of loop. 0 for stopped.
+ * 1 for running. 2 for paused.
+ *
+ * @see analog_start_loop, analog_stop_loop
+ **/
+int analog_loop_status(void) {
+	return adc_loop_status;
+}
+
+/**
+ * Reads an 8-bit number from an analog port.
+ * analog_init must be called before using this function.
+ * The analog loop must also be stopped before using this
+ * function or you will mess up the lookup table. You
+ * must also reenabled the loop when you are done unless
+ * you are doing more instant reads. See analog_stop_loop
+ * and analog_start_loop for more information about the loop.
+ * 
+ * @param which the analog port to read from. One of
+ * the constants AN0 - AN7.
+ *
+ * @return the 8-bit input to the specified port
+ *
+ * @see analog_init, analog_get10, analog8, analog_stop_loop,
+ * analog_start_loop
+ **/
+unsigned int analog_get8(int which) {	
+	// Let any previous conversion finish
+	while (ADCSRA & _BV(ADSC));
+	
+	if(which < EXT_MUX) {
+		ADMUX = ADMUX_OPT + which;
+	} else {
+		ADMUX = ADMUX_OPT + EXT_MUX;
+		set_adc_mux(which - 8);
+	}
+	
+	// Start the conversion
+	ADCSRA |= _BV(ADSC);
+
+	// Wait for the conversion to finish
+	while (ADCSRA & _BV(ADSC));
+
+	return ADCH; //since we left aligned the data, ADCH is the 8 MSB.
+}
+
+/**
+ * Reads an 10-bit number from an analog port.
+ * analog_init must be called before using this function.
+ * The analog loop must also be stopped before using this
+ * function or you will mess up the lookup table. You
+ * must also reenabled the loop when you are done unless
+ * you are doing more instant reads. See analog_stop_loop
+ * and analog_start_loop for more information about the loop.
+ * 
+ *
+ * @param which the analog port to read from. Typically
+ * a constant, one of AN0 - AN7.
+ *
+ * @return the 10-bit number input to the specified port
+ * 
+ * @see analog_init, analog_get8, analog10, analog_stop_loop,
+ * analog_start_loop
+ **/
+unsigned int analog_get10(int which) {
+	int adc_h;
+	int adc_l;
+	
+	// Let any previous conversion finish
+	while (ADCSRA & _BV(ADSC));
+
+	if(which < EXT_MUX) {
+		ADMUX = ADMUX_OPT + which;
+	} else {
+		ADMUX = ADMUX_OPT + EXT_MUX;
+		set_adc_mux(which - 8);
+	}
+	
+	// Start the conversion
+	ADCSRA |= _BV(ADSC);
+
+	// Wait for the conversion to finish
+	while (ADCSRA & _BV(ADSC));
+	
+	adc_l = ADCL;
+	adc_h = ADCH;
+
+	return ((adc_h << 2) | (adc_l >> 6));
+}
+
+/**
+ * Returns the current position of the wheel, as an integer
+ * in the range 0 - 255.
+ * analog_init must be called before using this function.
+ *
+ * @return the orientation of the wheel, as an integer in
+ * the range 0 - 255.
+ *
+ * @see analog_init
+ **/
+int wheel(void) {
+	return analog8(WHEEL_PORT);
+}
+
+
+/**
+ * Sets the value of the external analog mux. Values are read
+ * 	on AN7 physical port. (AN8 - AN15 are "virtual" ports).
+ *
+ * @param which which analog mux port (0-7) which corresponds
+ * 		  to AN8-AN15.
+ *
+ * @bug FIX THIS IN THE NEXT BOARD REVISION:
+ *		ADDR2 ADDR1 ADDR0
+ *		G2.G4.G3 set mux to port 0-7 via vinary selection
+ *		math would be much cleaner if it was G4.G3.G2
+ *
+ * @see analog_init
+ **/
+void set_adc_mux(int which) {  
+  // mask so only proper bits are possible.  
+  PORTG = (PORTG & 0xE3) | ((which & 0x03) << 3) | (which & 0x04);
+}
+
+/**@}**/ //end defgroup
+
+
+ISR(ADC_vect) {
+	int adc_h = 0;
+	int adc_l = 0;
+	
+	if(adc_loop_status != ADC_LOOP_RUNNING) return;
+
+	//Store the value only if this read isn't for the BOM
+	if (ADMUX != BOM_PORT) {
+		adc_l = ADCL;
+		adc_h = ADCH;
+	
+		an_val[adc_current_port - 1].adc10 = (adc_h << 2) | (adc_l >> 6);
+		an_val[adc_current_port - 1].adc8 = adc_h;
+	}
+	
+	//Skip AN7 because it is not a real port
+	if (adc_current_port == AN6) {
+		ADMUX = ADMUX_OPT | EXT_MUX;
+		set_adc_mux(AN8 - 8);
+		adc_current_port = AN8;
+	//Wrap around
+	} else if (adc_current_port == AN11) {
+		adc_current_port = AN1;
+		ADMUX = ADMUX_OPT | adc_current_port;
+	//Normal increment
+	} else {
+		adc_current_port++;
+	
+		if(adc_current_port < EXT_MUX) {
+			ADMUX = ADMUX_OPT | adc_current_port;
+		} else {
+			ADMUX = ADMUX_OPT | EXT_MUX;
+			set_adc_mux(adc_current_port - 8);
+		}
+	}
+
+	//Stop loop if signal is set
+	if(adc_sig_stop_loop) {
+		adc_sig_stop_loop = 0;
+		adc_loop_status = ADC_LOOP_STOPPED;
+		return;
+	}
+	
+	//Start next conversion
+	ADCSRA |= _BV(ADSC);
+}
+
Index: branches/wireless/code/projects/libdragonfly/encoders.c
===================================================================
--- branches/wireless/code/projects/libdragonfly/encoders.c	(nonexistent)
+++ branches/wireless/code/projects/libdragonfly/encoders.c	(revision 1493)
@@ -0,0 +1,446 @@
+/**
+ * Copyright (c) 2007 Colony Project
+ * 
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ * 
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ **/
+
+
+/**
+ * @file encoders.c
+ * @brief Encoders
+ *
+ * Implementation of functions for encoders.
+ *
+ * @author Colony Project, CMU Robotics Club
+ **/
+
+#include <avr/io.h>
+
+#include "dragonfly_defs.h"
+#include "spi.h"
+#include "ring_buffer.h"
+#include "encoders.h"
+
+unsigned char encoders_initd=0;
+
+unsigned int left_data_buf;
+unsigned int right_data_buf;
+char encoder_buf_index;
+
+unsigned int left_data;
+unsigned int right_data;
+
+unsigned int left_data_array[BUFFER_SIZE];
+unsigned int right_data_array[BUFFER_SIZE];
+int left_data_idx;
+int right_data_idx;
+
+int left_dx;
+int right_dx;
+long int timecount;
+
+volatile short int data_ready;
+
+int encoder_recv(char data);
+
+//Helper Function Prototypes
+inline void left_data_array_put(unsigned short int value);
+inline unsigned int left_data_array_top(void);
+inline unsigned int left_data_array_prev(void);
+inline unsigned int left_data_array_bottom(void);
+
+inline void right_data_array_put(unsigned short int value);
+inline unsigned int right_data_array_top(void);
+inline unsigned int right_data_array_prev(void);
+inline unsigned int right_data_array_bottom(void);
+
+//encoder_get_v helper function prototypes
+int left_data_at(int index);
+int right_data_at(int index);
+int get_dx(char encoder, int index);
+
+void encoder_recv_complete(void){
+  	encoder_buf_index = 0;
+	data_ready++;
+  
+   	spi_transfer(5);
+}
+
+/** 
+* @brief Initializes encoder variables and the hardware interface.
+*/
+int encoders_init(void){
+  int i;
+	
+  if(encoders_initd)
+    return ERROR_INIT_ALREADY_INITD;
+
+  data_ready=0;
+
+  if(spi_init(encoder_recv, encoder_recv_complete))
+    return -1; //if spi was inited for something else, bail out
+  encoder_buf_index = 0;
+  left_data_buf = 0;
+  right_data_buf= 0;
+  left_data = -1;
+  right_data = -1;
+
+  //RING_BUFFER_INIT(enc_buffer,BUFFER_SIZE);
+  left_data_idx = 0;
+  right_data_idx = 0;
+
+  for(i = 0; i < BUFFER_SIZE; i++) {
+    left_data_array[i] = 0;
+  }
+  for(i = 0; i < BUFFER_SIZE; i++) {
+    right_data_array[i] = 0;
+  }
+
+  spi_transfer(5);
+
+  encoders_initd=1;
+  return 0;
+}
+
+/**
+ * @brief Returns the specified encoders value
+ *
+ * @param encoder this is the encoder that you want to read. Valid arguments
+ *          are LEFT and RIGHT
+ *
+ * @return the value of the specified encoder.
+ *         -1 usually means low battery.
+ *         -2 means the library was not properly initialized
+ *         values above ENCODER_MAX usually means phyiscal problems with
+ *         the encoder.
+ **/
+int encoder_read(char encoder){
+  if(!encoders_initd)
+    return -2;
+
+  if(encoder==LEFT) {
+    return left_data;
+  }
+  else if(encoder==RIGHT){
+    return right_data;
+  }
+  else{
+    return -1;
+  }
+}
+
+/**
+ * @brief Get total distance travelled by the specified encoder (in encoder ticks)
+ *
+ * @param encoder the encoder that you want to read, either LEFT or RIGHT
+ *
+ * @return The distance covered by the specified encoder.
+ *
+ * @note Simply calls encoder_get_dx.
+ **/
+int encoder_get_x(char encoder) {
+	return encoder_get_dx(encoder);
+}
+
+/**
+ * Gets the total distance covered by the specified encoder (in encoder clicks)
+ *
+ * @param encoder the encoder that you want to read, use LEFT or RIGHT
+ *
+ * @return The distance covered by the specified encoder, -2 if the library is not initialized
+ **/
+int encoder_get_dx(char encoder) {
+  if(!encoders_initd)
+    return -2;
+
+  if(encoder==LEFT)
+    return left_dx;
+  else if(encoder==RIGHT)
+    return right_dx;
+  else
+    return -1;
+}
+
+/** 
+ * @brief Returns the approximated instantaneous velocity of the robot
+ * in terms of encoder clicks.
+ * 
+ * @param encoder RIGHT or LEFT - the wheel you want the velocity for.
+ * 
+ * @return The instantaneous velocity for the given wheel or twice the ERR_VEL
+ *         if an error occurs (1024 * 2 = 2048)
+ *
+ * @bug This uses hard coded values and results are inconsistent.
+ *      Use at your own risk.
+ */
+int encoder_get_v(char encoder){
+    int vel1, vel2;
+
+    vel1 = get_dx(encoder, 0);
+    vel2 = get_dx(encoder, 1);
+
+    if (vel1 == ERR_VEL && vel2 == ERR_VEL)
+        return ERR_VEL << 1;
+    else if (vel2 == ERR_VEL)
+        return vel1 << 1;
+    else if (vel1 == ERR_VEL)
+        return vel2 << 1;
+    else
+        return vel1 + vel2;
+}
+
+/**
+ * Resets the distance accumulator for the specified
+ *  encoder.
+ *
+ * @param encoder the encoder that you want to reset distance for
+ **/
+int encoder_rst_dx(char encoder) {
+
+  if(!encoders_initd)
+    return ERROR_LIBRARY_NOT_INITD;
+
+  if(encoder==LEFT)
+    left_dx = 0;
+  else if(encoder==RIGHT)
+    right_dx = 0;
+
+  return 0;
+}
+
+/** 
+* @brief Returns the number of encoder reads that have occurred.
+* 
+* @return The time count.
+*/
+int encoder_get_tc(void) {
+	return timecount;
+}
+
+/** 
+* @brief Resets the encoder read counter.
+* @return 0 if init succesfull, an error code otherwise
+*/
+int encoder_rst_tc(void) {
+  if(!encoders_initd)
+    return ERROR_LIBRARY_NOT_INITD;
+
+  timecount = 0;
+
+  return 0;
+}
+
+/** 
+* @brief Waits until n encoder reads have occurred.
+* Counter is reset on functions exit.
+* 
+* @param n 
+*
+* @return 0 if init succesfull, an error code otherwise
+*/
+int encoder_wait(int n){
+  if(!encoders_initd)
+    return ERROR_LIBRARY_NOT_INITD;
+
+  while(data_ready<n);
+  data_ready=0;
+
+  return 0;
+}
+
+/**
+ * @brief This functions recieves data from the encoders directly
+ *
+ * @note Full reads occur every 40 microseconds. This function should be called every 8 microseconds.
+ *
+ * @return 0 if init succesfull, an error code otherwise
+ */
+int encoder_recv(char data){
+  short int dx;
+
+  if(!encoders_initd)
+    return ERROR_LIBRARY_NOT_INITD;
+
+  //Parse the encoder data, comes in over 5 bytes 16 bits per encoder,
+  // second is offset by 1 bit.
+  switch(encoder_buf_index){	
+  case 0: 
+    right_data_buf |= ((short)data)<<8 & 0xff00;
+    break;
+  case 1:
+    right_data_buf |= ((short)data) & 0xff;
+    break;
+  case 2:
+    left_data_buf |= (((short)data) << 9) & (0x7F << 9);
+    break;
+  case 3:
+    left_data_buf |= (((short)data) << 1) & (0xFF<<1);
+    break;
+  case 4: left_data_buf |= (((short)data)>>7) & 0x1;
+  }	
+		
+  encoder_buf_index = (encoder_buf_index + 1) % 5;
+
+  if(encoder_buf_index==0) {
+		
+    /*Error handling for the left encoder*/ 
+    if(!(left_data_buf & OCF)) 
+      left_data = ENCODER_DATA_NOT_READY; 
+    if(left_data_buf & (COF | LIN))  
+      left_data = ENCODER_MISALIGNED;
+    else if((left_data_buf & MagINCn) && (left_data_buf & MagDECn)) 
+      left_data = ENCODER_MAGNET_FAILURE;
+    else left_data = (left_data_buf>>5) & 1023;
+			
+    /*Error handling for the right encoder*/ 
+    if(!(right_data_buf & OCF))
+      right_data = ENCODER_DATA_NOT_READY;	
+    if(right_data_buf & (COF | LIN)) 
+      right_data = ENCODER_MISALIGNED;
+    else if ((right_data_buf & MagINCn)  && (right_data_buf & MagDECn)) 
+      right_data = ENCODER_MAGNET_FAILURE;
+    else right_data = (right_data_buf>>5) & 1023;
+			
+    left_data_buf = 0;
+    right_data_buf = 0;
+
+    /*Note: Above 1023 is invalid data*/	
+    if(!(left_data > 1023)) {
+      //Reverse the left wheel since encoders are necessarily mounted backwards.
+      left_data = 1023 - left_data;
+      left_data_array_put(left_data);
+
+      //Adjust left accumulator
+      dx = left_data - left_data_array_prev();
+			
+      if(left_data_array_prev()==0)  dx=0;
+
+      if(dx > 512) left_dx += dx - 1023; //Underflow
+      else if(dx < -512) left_dx += dx + 1023; //Overflow
+      else left_dx += dx;
+    }
+
+    /*Above 1023 is invalid data*/	
+    if(!(right_data > 1023)) {
+      right_data_array_put(right_data);
+
+      //Adjust right accumulator
+      dx = right_data - right_data_array_prev();
+
+      if(right_data_array_prev()==0) dx=0;
+			  
+      if(dx > 512) right_dx += dx - 1023; //underflow
+      else if(dx < -512) right_dx += dx + 1023; //overflow 
+      else right_dx += dx;
+    }
+  }
+
+  //Increment timecount accumulator
+  timecount++;
+
+  return 0;
+}
+
+
+//Helper Functions
+inline void left_data_array_put(unsigned short int value) {
+	if(left_data_idx == BUFFER_SIZE-1)
+		left_data_idx = 0;
+	else
+		left_data_idx++;
+	left_data_array[left_data_idx] = value;
+}
+
+inline unsigned int left_data_array_top(void) {
+	return left_data_array[left_data_idx];
+}
+
+inline unsigned int left_data_array_prev(void) {
+	if(left_data_idx == 0)
+		return left_data_array[BUFFER_SIZE-1];
+	else
+		return left_data_array[left_data_idx - 1];
+}
+
+inline unsigned int left_data_array_bottom(void) {
+	if(left_data_idx == BUFFER_SIZE-1)
+		return left_data_array[0];
+	else
+		return left_data_array[left_data_idx + 1];
+}
+
+inline void right_data_array_put(unsigned short int value) {
+	if(right_data_idx == BUFFER_SIZE-1)
+		right_data_idx = 0;
+	else
+		right_data_idx++;
+	right_data_array[right_data_idx] = value;
+}
+
+inline unsigned int right_data_array_top(void) {
+	return right_data_array[right_data_idx];
+}
+
+inline unsigned int right_data_array_prev(void) {
+	if(right_data_idx == 0)
+		return right_data_array[BUFFER_SIZE-1];
+	else
+		return right_data_array[right_data_idx - 1];
+}
+
+inline unsigned int right_data_array_bottom(void) {
+	if(right_data_idx == BUFFER_SIZE-1)
+		return right_data_array[0];
+	else
+		return right_data_array[right_data_idx + 1];
+}
+
+/* Helper functions for encoder_get_v */
+int left_data_at(int index) {
+    int tmp_idx = left_data_idx - index;
+    if (tmp_idx < 0)
+        tmp_idx += BUFFER_SIZE;
+    return left_data_array[tmp_idx];
+}
+
+int right_data_at(int index) {
+    int tmp_idx = right_data_idx - index;
+    if (tmp_idx < 0)
+        tmp_idx += BUFFER_SIZE;
+    return right_data_array[tmp_idx];
+}
+
+int get_dx(char encoder, int index) {
+    int dx, ctr;
+    ctr = 0;
+    dx = 1024;
+    do {
+        if (encoder == LEFT)
+            dx = left_data_at(index+ctr) - left_data_at(index+ctr+38);
+        else
+            dx = right_data_at(index+ctr) - right_data_at(index+ctr+38);
+        ctr++;
+    } while ((dx > 30 || dx < -30) && ctr < 3); 
+    if (dx > 30 || dx < -30)
+        return ERR_VEL;
+    return dx; 
+}
Index: branches/wireless/code/projects/libdragonfly/time.h
===================================================================
--- branches/wireless/code/projects/libdragonfly/time.h	(nonexistent)
+++ branches/wireless/code/projects/libdragonfly/time.h	(revision 1493)
@@ -0,0 +1,76 @@
+/**
+ * Copyright (c) 2007 Colony Project
+ * 
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ * 
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ **/
+
+
+/**
+ * @file time.h
+ * @brief Contains time-related functions and definitions
+ *
+ * Contains functions and definitions for dealing with time,
+ * namely delay_ms and the realtime clock.
+ *
+ * @author Colony Project, CMU Robotics Club
+ **/
+
+#ifndef _TIME_H_
+#define _TIME_H_
+
+
+/*	Predefined times for prescale_opt in time.c.
+	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
+	to know how many 16ths of a second are in the time you want. (Time_desired * 16 = prescaler_opt)
+*/
+/**
+ * @addtogroup time
+ * @{
+ **/
+/** @brief A sixteenth of a second **/
+#define SIXTEENTH_SECOND 1
+/** @brief An eighth of a second **/
+#define EIGTH_SECOND 2
+/** @brief A quarter of a second **/
+#define QUARTER_SECOND 4
+/** @brief Half of a second **/
+#define HALF_SECOND	8
+/** @brief One second **/
+#define SECOND 16
+/** @brief Two seconds **/
+#define TWO_SECOND 32
+/** @brief Four seconds **/
+#define FOUR_SECOND 64
+
+/** @brief Delay execution for the specified time **/
+void delay_ms(int ms) ;
+/** @brief Enable the realtime clock **/
+int rtc_init(int prescale_opt, void (*rtc_func)(void));
+/** @brief Reset the counter of the realtime clock **/
+void rtc_reset(void);
+/** @brief Get the value of the realtime clock. **/
+int rtc_get(void);
+
+/** @} **/
+
+#endif
+
Index: branches/wireless/code/projects/libdragonfly/encoders.h
===================================================================
--- branches/wireless/code/projects/libdragonfly/encoders.h	(nonexistent)
+++ branches/wireless/code/projects/libdragonfly/encoders.h	(revision 1493)
@@ -0,0 +1,115 @@
+/**
+ * Copyright (c) 2007 Colony Project
+ * 
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ * 
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ **/
+
+
+/**
+ * @file encoders.h
+ * @brief Contains functions for reading encoder values.
+ *
+ * Contains high and low level functions for reading encoders
+ * including reading out total distance covered, and 
+ * eventually velocity.
+ *	
+ * @author Colony Project, CMU Robotics Club
+*/
+
+/**
+ * @addtogroup encoders
+ * @{
+ **/
+
+#ifndef __ENCODERS_H__
+#define __ENCODERS_H__
+
+
+#ifndef LEFT
+	/** @brief Left wheel **/
+	#define LEFT 0
+#endif
+#ifndef RIGHT
+	/** @brief Right wheel **/
+	#define RIGHT 1
+#endif
+
+/** @brief Max value of valid encoder reading. **/
+#define ENCODER_MAX 1024
+
+/** @brief Magnet misaligned - likely distance from encoder problem. **/
+#define ENCODER_MAGNET_FAILURE 1025
+/** @brief Encoder misaligned - likely on XY plane. **/
+#define ENCODER_MISALIGNED 1027
+/** @brief Not enough time has passed - encoders not initialized in hardware. **/
+#define ENCODER_DATA_NOT_READY 1026
+
+/** @brief delay_ms argument after a full read is complete **/
+#define ENCODER_DELAY 20
+
+//Data invalid flags (hardware failure):
+#define OCF _BV(4)
+#define COF _BV(3)
+
+//Data invalid alarm (May be invalid):
+#define LIN _BV(2)
+
+#define MagINCn _BV(1)
+#define MagDECn _BV(0)
+
+#ifdef BUFFER_SIZE
+#error BUFFER_SIZE already defined!
+#endif
+
+/** @brief Buffer size **/
+#define BUFFER_SIZE 46
+
+#define ERR_VEL 1024
+
+/** @brief Initialize encoders. **/
+int encoders_init(void);
+/** @brief Read instantaneous encoder value. **/
+int encoder_read(char encoder);
+
+/** @brief Get total distance traveled.
+ *  @note  Simply calls encoder_get_dx.
+ **/
+int encoder_get_x(char encoder);
+
+/** @brief Get instantaneous velocity. **/
+int encoder_get_v(char encoder);
+
+/** @brief Get total distance traveled. **/
+int encoder_get_dx(char encoder);
+/** @brief Reset distance counter. **/
+int encoder_rst_dx(char encoder);
+/** @brief Get time count: The number of encoder reads that have occurred. **/
+int encoder_get_tc(void);
+/** @brief Reset the time count. **/
+int encoder_rst_tc(void);
+
+/** @brief Waits for the next n encoder reading, then returns. **/
+int encoder_wait( int nReadings );
+
+/**@}**/ //end group
+
+#endif
Index: branches/wireless/code/projects/libdragonfly/bom.c
===================================================================
--- branches/wireless/code/projects/libdragonfly/bom.c	(nonexistent)
+++ branches/wireless/code/projects/libdragonfly/bom.c	(revision 1493)
@@ -0,0 +1,443 @@
+/**
+ * Copyright (c) 2007 Colony Project
+ * 
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ * 
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ **/
+
+
+/**
+ * @file bom.c
+ * @brief Implementation for using the BOM
+ *
+ * Contains functions for using the Bearing and Orientation Module (BOM)
+ *
+ * @author Colony Project, CMU Robotics Club
+ **/
+
+#include "dragonfly_defs.h"
+#include "dio.h"
+#include "serial.h"
+#include "analog.h"
+#include "bom.h"
+
+//On the original BOM1.0, the emmitter angular order does not match the analog mux order
+//so you need to iterate through the mux index in the following order if you want to get
+//the detector readings in order:
+static const char lookup[16] = {7,6,5,0xe,1,4,3,2,0xf,0,0xd,8,0xc,0xb,9,0xa};
+
+// internal function prototypes
+static void bom_select(char which);
+
+/*
+ Bk R Y (Analog)
+---------
+ Green
+ Blue
+ White
+---------
+ Blue
+ White
+*/
+
+
+/*
+the analog pin definitions from dio.h DO NOT work here,
+so we must use PF0 from avrgcc (as opposed to _PIN_F0).
+BUT the dio pin definitions from dio.h must be used (no PE...).
+
+also, _PIN_E2 is initialized to high for some reason,
+which turns the BOM on when the robot is turned on.
+WORK-AROUND: call digital_output(_PIN_E2,0) at some point.
+
+*/
+
+#define MONKI PF0         //analog (yellow)
+//------------------------//
+#define MONKL _PIN_E2     //green
+#define MONK1 _PIN_E3     //blue
+#define MONK0 _PIN_E4     //white
+//------------------------//
+#define MONK3 _PIN_E6     //blue
+#define MONK2 _PIN_E7     //white
+
+#define BOM_VALUE_THRESHOLD 150 //200
+#define NUM_BOM_LEDS 16
+
+/*
+  *The following pin definitions are for the BOM v1.5
+  */
+
+#define BOM_MODE	_PIN_E2	//dio0
+#define BOM_STROBE	_PIN_E3	//dio1
+
+#define BOM_DATA	_PIN_A0 //servo0
+#define BOM_CLOCK	_PIN_A1	//servo1
+
+#define BOM_S0		_PIN_E5	//dio3
+#define BOM_S1		_PIN_E4	//dio2
+#define BOM_S2		_PIN_E7	//dio4
+#define BOM_S3		_PIN_E6	//dio5
+#define BOM_OUT		PF0		//analog(yellow)
+
+/**
+ * @defgroup bom BOM (Bearing and Orientation Module)
+ * @brief Functions for dealing with the BOM.
+ *
+ * The Bearing and Orientation Module / Barrel of Monkeys / BOM
+ * is a custom sensor designed and built by the Colony Project.
+ * It consists of a ring of 16 IR emitters and 16 IR detectors.
+ * The BOM is most often use to determine the direction of other
+ * robots. This module contains functions for controlling the BOM.
+ *
+ * Include bom.h to access these functions.
+ *
+ * @{
+ **/
+
+unsigned char bom_initd=0;
+
+static unsigned int bom_val[NUM_BOM_LEDS];
+static volatile char bom_type = BOM10;
+static int select_pins[4];
+static int analog_pin;
+
+/**
+ * Initializes the BOM.
+ * Call bom_init before reading bom values or turning bom leds.
+ *
+ * @bugs INCOMPLETE - No utilization of BOM1.5 RSSI capability. Probably leave this out
+ * until Cornell and Pras return
+ *
+ * @return 0 if init succesfull, an error code otherwise 
+ *
+ * @see bom_refresh, bom_leds_on, bom_leds_off
+ **/
+int bom_init(char type) {
+
+    if(bom_initd)
+      return ERROR_INIT_ALREADY_INITD;
+
+
+    bom_type = type;
+    
+    switch(bom_type) {
+    case BOM10:
+		select_pins[0] = MONK0; 
+		select_pins[1] = MONK1;
+		select_pins[2] = MONK2;
+		select_pins[3] = MONK3;
+		analog_pin = MONKI;
+        break;
+    case BOM15:
+        //Sets BOM1.5 to normal [BOM] mode
+        digital_output(BOM_MODE, 0);
+		select_pins[0] = BOM_S0; 
+		select_pins[1] = BOM_S1;
+		select_pins[2] = BOM_S2;
+		select_pins[3] = BOM_S3;
+		bom_set_leds(BOM_ALL);
+		analog_pin = BOM_OUT;
+        break;
+    case RBOM:
+        break;
+    //default:
+    }
+
+    bom_initd=1;
+    return 0;
+}
+
+/**
+ * Iterates through each bit in the bit_field. For each set bit, sets the corresponding bom select bits
+ *    and updates the corresponding bom value with an analog_get8 reading.  analog_init and bom_init
+ *    must be called for this to work. Must call this before reading BOM values!
+ *
+ *
+ * @param bit_field specifies which elements in bom_val[] should be updated. Use BOM_ALL to refresh all values.
+ *    Ex. if 0x0003 is passed, bom_val[0] and bom_val[1] will be updated.
+ *
+ * @return 0 if init succesfull, an error code otherwise
+ *
+ * @see bom_get
+ **/
+int bom_refresh(int bit_field) {
+    int i;
+    int loop_was_running = 0;
+
+    if(!bom_initd)
+      return ERROR_LIBRARY_NOT_INITD;
+
+    
+    //Check analog loop status
+    if(analog_loop_status() == ADC_LOOP_RUNNING) {
+      loop_was_running = 1;
+      analog_stop_loop();
+    }
+    
+    //Read BOM values
+    for(i = 0; i < NUM_BOM_LEDS; i++) {
+      if(bit_field & 0x1) {
+	bom_select(i);
+	bom_val[i] = analog_get8(analog_pin);
+      }
+      bit_field = bit_field >> 1;
+    }
+    
+    //Restore analog loop status
+    if(loop_was_running)
+      analog_start_loop();
+
+    return 0;
+}
+
+/**
+ * Gets the bom reading from bom_val[which].  Call bom_refresh beforehand to read new bom values.
+ *
+ * @pre must call bom refresh first
+ *
+ * @param which which bom value to return
+ *
+ * @return the bom value, -1 on error
+ *
+ * see bom_refresh
+ **/
+int bom_get(int which) {
+    if(!bom_initd)
+      return -1;
+
+    return bom_val[which];
+}
+
+/** 
+ * Compares all the values in bom_val[] and returns the index to the lowest (max) value element.
+ *
+ * @pre must call bom refresh
+ * @return index to the lowest (max) bom value element.  -1 if no value is lower than
+ *    BOM_VALUE_THRESHOLD, -2 if the bom is not initialized
+ **/
+int bom_get_max(void) {
+    int i, lowest_val, lowest_i;
+
+    if(!bom_initd)
+      return -2;
+
+    lowest_i = -1;
+    lowest_val = 255;
+    for(i = 0; i < NUM_BOM_LEDS; i++) {
+        if(bom_val[i] < lowest_val) {
+            lowest_val = bom_val[i];
+            lowest_i = i;
+        }
+    }
+    
+    if(lowest_val < BOM_VALUE_THRESHOLD)
+        return lowest_i;
+    else
+        return -1;
+}
+
+/** 
+ * Computes the weighted average of all the bom readings to estimate the position (and distance) of another robot.
+ *
+ * @pre must call bom refresh
+ * @param dist  pointer to int in which to return the estimated distance to the other robot
+ * @return estimated position of the max bom value element as a fixed point value analogous to 10 times the
+ *        index of the max bom value.  -1 if no value is lower than BOM_VALUE_THRESHOLD, -2 if the bom is not initialized
+ **/
+int bom_get_max10(int *dist) {
+    int i, max;
+    long long mean = 0, sum = 0;
+
+    if(!bom_initd)
+      return ERROR_LIBRARY_NOT_INITD;
+
+
+    max = bom_get_max();
+    if (max < 0)
+    {
+        if (dist)
+        {
+            *dist = -1;
+        }
+        return -1;
+    }
+    /* Record values into an array */
+    for (i = 0; i < NUM_BOM_LEDS; i++) {
+        int idx = ((i + (NUM_BOM_LEDS/2 - max) + NUM_BOM_LEDS) % NUM_BOM_LEDS) - (NUM_BOM_LEDS/2 - max);
+        int val = 255 - bom_val[i];
+        mean += idx * val;
+        sum += val;
+    }
+    mean = (mean * 10) / sum;
+    mean = (mean + NUM_BOM_LEDS*10) % (NUM_BOM_LEDS*10);
+
+    if (dist)
+    {
+        *dist = 50 - sum/48;
+    }
+
+    return mean;
+}
+
+/**
+ * Iterates through each bit in the bit_field. If the bit is set, the corresponding emitter will
+ *    be enabled to turn on when bom_on() is called.
+ *    bom_init must be called for this to work. Does nothing if a BOM1.0 is installed
+ *
+ * @param bit_field specifies which leds should be turned on when bom_on is called.  Use BOM_ALL to turn on all bom leds.
+ *    Ex. if 0x0005 is passed, leds 0 and 2 will be turned on.
+ *
+ * @return 0 if init succesfull, an error code otherwise
+ *
+ **/
+int bom_set_leds(int bit_field) {
+    int i;
+    unsigned int mask = 1<<(NUM_BOM_LEDS-1);
+
+    if(!bom_initd)
+      return ERROR_LIBRARY_NOT_INITD;
+
+    switch(bom_type) {
+    case BOM10:
+        //TODO: put an assert here to alert the user that this should not be called
+        break;
+		
+    case BOM15:
+	    for(i=NUM_BOM_LEDS; i>0; i--)
+	    {
+		    //set the current bit, sending MSB first
+		    digital_output(BOM_DATA, bit_field&mask);
+		    //then pulse the clock
+		    digital_output(BOM_CLOCK, 1);
+		    digital_output(BOM_CLOCK, 0);
+			mask = mask>>1;
+	    }
+        break;
+		
+    case RBOM:
+        //add rbom code here
+        break;
+    }
+
+    return 0;
+}
+
+
+/**
+ * (DEPRECATED) Returns the direction of the maximum BOM reading,
+ * as an integer in the range 0-15. 0 indicates to the
+ * robot's right, while the rest of the sensors are
+ * numbered counterclockwise. This is useful for determining
+ * the direction of a robot flashing its BOM, of only one
+ * robot is currently doing so. analog_init must be called
+ * before this function can be used.
+ *
+ * @return the direction of the maximum BOM reading
+ *
+ * @see analog_init
+ **/
+int get_max_bom(void) {
+    bom_refresh(BOM_ALL);
+    return bom_get_max();
+}
+
+/**
+ * Flashes the BOM.  If using a BOM1.5, only the emitters that have been enabled using
+ * bom_set_leds will turn on.
+ * 
+ * @return 0 if init succesfull, an error code otherwise
+ *
+ * @see bom_off, bom_set_leds
+ **/
+int bom_on(void)
+{
+  if(!bom_initd)
+    return ERROR_LIBRARY_NOT_INITD;
+
+  switch(bom_type) {
+  case BOM10:
+	digital_output(MONKL, 1);
+	break;
+  case BOM15:
+	digital_output(BOM_STROBE, 1);
+	break;
+  case RBOM:
+	break;
+  }
+
+  return 0;
+}
+
+/**
+ * Turns off all bom leds.
+ * 
+ * @return 0 if init succesfull, an error code otherwise
+ *
+ * @see bom_on
+ **/
+int bom_off(void)
+{
+  if(!bom_initd)
+    return ERROR_LIBRARY_NOT_INITD;
+
+  switch(bom_type) {
+  case BOM10:
+	digital_output(MONKL, 0);
+	break;
+  case BOM15:
+	digital_output(BOM_STROBE, 0);
+	break;
+  case RBOM:
+	break;
+  }
+
+  return 0;
+}
+
+/** @} **/ //end group
+
+//select a detector to read
+static void bom_select(char which) {
+	if(bom_type == BOM10)
+	  which = lookup[(int)which];
+	
+    if (which&8)
+      digital_output(select_pins[3], 1);
+    else
+      digital_output(select_pins[3], 0);
+
+    if (which&4)
+      digital_output(select_pins[2], 1);
+    else
+      digital_output(select_pins[2], 0);
+
+    if (which&2)
+      digital_output(select_pins[1], 1);
+    else
+      digital_output(select_pins[1], 0);
+
+    if (which&1)
+      digital_output(select_pins[0], 1);
+    else
+      digital_output(select_pins[0], 0);
+	
+}
Index: branches/wireless/code/projects/libdragonfly/rangefinder.c
===================================================================
--- branches/wireless/code/projects/libdragonfly/rangefinder.c	(nonexistent)
+++ branches/wireless/code/projects/libdragonfly/rangefinder.c	(revision 1493)
@@ -0,0 +1,172 @@
+/**
+ * Copyright (c) 2007 Colony Project
+ * 
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ * 
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ **/
+
+
+/**
+ * @file rangefinder.c
+ * @brief Rangefinders
+ *
+ * Implementation of functions for rangefinder use.
+ *
+ * @author Colony Project, CMU Robotics Club
+ **/
+
+/*
+  Authors: James Kong and Greg Tress
+
+  Last Modified: 4/30/06 by James
+  -Started log_distance conversion function !!!NOT COMPLETE!!!
+  -Cleaning up comments
+
+  -----------------
+  rangefinder.c
+  Using Sharp GP2D02 IR Rangefinder
+
+  Vin is the input to the rangefinder, designated RANGE_CTRL.
+  Vout is the output from the rangefinder, designated RANGE_IN# where # is the rangefinder you are reading from
+
+  Expected Initial Conditions:
+  Vin is high and Vout should read high.
+
+  Usage:
+  1.) Set Vin low. Vout should read low.
+  2.) Wait for high on Vout.
+  3.) Begin clocking Vin and reading 8 bits from Vout (MSB first).
+  4.) Set Vin high for 2ms or more to turn off rangefinder
+
+*/
+#include <avr/pgmspace.h>
+
+#include "dragonfly_defs.h"
+#include "analog.h"
+#include "dio.h"
+#include "rangefinder.h"
+
+unsigned char range_initd=0;
+
+
+/*
+  read_distance returns the 8-bit reading from the rangefinder
+  parameters:
+  range_id - dio pin set as the rangefinder Vout [i.e. RANGE_IN0]
+
+  NOTE:
+  The Sharp GD2D02 returns values on a decreasing logrithmic scale.
+  So higher values correspond to closer distances.  Use linearize_distance to convert to normal centimeter scale.
+  Also, when reading distances closer than 8cm, the Sharp GD2D02 will return lower values than the values at 8cm.
+  At this point, we are only reading from one rangefinder [RANGE_IN0].
+*/
+
+// constants
+/* Nasty IR approximation table
+   I'm using this for the heck of it.  We can do whatever.
+
+   Note the minimum value is .4V (20), and the maximum is 2.6V (133).
+   Gives distance in mm.
+
+   excel formula(valid for inputs 20-133):  ROUND(2353.6*(E2^(-1.1146))*10,0)
+
+   This is only valid for the GP2D12, with objects directly ahead and more than
+   10cm from the detector.  See the datasheet for more information.
+*/
+
+static int IR_dist_conversion[114] PROGMEM = {
+  800,791,751,714,681,651,623,597,574,552,531,512,494,478,462,447
+  ,434,421,408,397,386,375,365,356,347,338,330,322,315,307,301,294
+  ,288,282,276,270,265,260,255,250,245,241,237,232,228,224,221,217
+  ,213,210,207,203,200,197,194,191,189,186,183,181,178,176,173,171
+  ,169,166,164,162,160,158,156,154,152,151,149,147,145,144,142,140
+  ,139,137,136,134,133,131,130,129,127,126,125,124,122,121,120,119
+  ,118,117,115,114,113,112,111,110,109,108,107,106,105,105,104,103
+  ,102,101
+};
+
+/**
+ * @defgroup rangefinder Rangefinder
+ * @brief Functions for using the IR rangefinders
+ * 
+ * Functions for using the IR rangefinders.
+ *
+ * @{
+ **/
+
+/**
+ * Initializes the rangefinders. This must be called before
+ * range_read_distance.
+ *
+ * @return 0 if init succesfull, an error code otherwise
+ *
+ * @see range_read_distance
+ **/
+int range_init(void)
+{
+  if(range_initd)
+    return ERROR_INIT_ALREADY_INITD;
+
+  digital_output(_PIN_B4,0);
+
+  range_initd=1;
+  return 0;
+}
+
+/**
+ * Reads the distance measured by one of the rangefinders.
+ * This distance is in arbitrary units.
+ *
+ * @param range_id the rangefinder to use. This should be one
+ * of the constants IR1 - IR5.
+ *
+ * @return the distance measured by the rangefinder, or an error code
+ *
+ * @see range_init
+ **/
+int range_read_distance(int range_id) {
+  if(!range_initd)
+    return -3;
+
+  return linearize_distance(analog8(range_id));
+}
+
+/**
+ * Transforms distance readings from logarithmic to linear scale.
+ * This probably isn't the function you are looking for.
+ *
+ * Note: pgm_read_word() needs additional testing
+ *
+ * @param value the 8-bit analog value from rangefinder
+ *
+ * @return linearized distance reading from rangefinder (integer in [101,800])
+ **/
+int linearize_distance(int value) {
+  if(value < MIN_IR_ADC8) {
+    return -1;
+  } else if(value > MAX_IR_ADC8) {
+    return -1;
+  } else {
+    return pgm_read_word(&(IR_dist_conversion[value - MIN_IR_ADC8]));
+  }
+}
+
+/** @} **/ //end defgroup
Index: branches/wireless/code/projects/libdragonfly/rangefinder.h
===================================================================
--- branches/wireless/code/projects/libdragonfly/rangefinder.h	(nonexistent)
+++ branches/wireless/code/projects/libdragonfly/rangefinder.h	(revision 1493)
@@ -0,0 +1,70 @@
+/**
+ * Copyright (c) 2007 Colony Project
+ * 
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ * 
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ **/
+
+
+/**
+ * @file rangefinder.h
+ * @brief Contains rangefinder declarations and functions
+ * 
+ * Contains functions and definitions for the use of
+ * IR rangefinders.
+ *
+ * @author Colony Project, CMU Robotics Club
+ **/
+
+#ifndef _RANGEFINDER_H_
+#define _RANGEFINDER_H_
+
+/**
+ * @addtogroup rangefinder
+ * @{
+ **/
+
+/** @brief IR Rangefinder 1 **/
+#define IR1 6
+/** @brief IR Rangefinder 2 **/
+#define IR2 5
+/** @brief IR Rangefinder 3 **/
+#define IR3 4
+/** @brief IR Rangefinder 4 **/
+#define IR4 3
+/** @brief IR Rangefinder 5 **/
+#define IR5 2
+/** @brief smallest meaningful rangefinder reading (logarithmic scale) **/
+#define MIN_IR_ADC8 20
+/** @brief largest meaningful rangefinder reading (logarithmic scale) **/
+#define MAX_IR_ADC8 133
+
+/** @brief Initialize the rangefinders **/
+int range_init(void);
+/** @brief Read the distance from a rangefinder **/
+int range_read_distance(int range_id);
+/** @brief Convert logarithmic-scale distance readings to a linear scale **/
+int linearize_distance(int value);
+
+/** @} **/ //end addtogroup
+
+#endif
+
Index: branches/wireless/code/projects/libdragonfly/dragonfly_defs.h
===================================================================
--- branches/wireless/code/projects/libdragonfly/dragonfly_defs.h	(nonexistent)
+++ branches/wireless/code/projects/libdragonfly/dragonfly_defs.h	(revision 1493)
@@ -0,0 +1,93 @@
+/**
+ * Copyright (c) 2007 Colony Project
+ * 
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ * 
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ **/
+
+
+/**
+ * @file dragonfly_def.h
+ * @brief Contains definitions for dragonfly library
+ * 
+ * Should be included in all dragonfly library source files.
+ * Does not need to be included by user programs.
+ *
+ * @author Colony Project, CMU Robotics Club
+ **/
+
+#ifndef _DRAGONFLY_DEFS_H_
+#define _DRAGONFLY_DEFS_H_
+
+/**
+ * @addtogroup dragonfly
+ * @{
+ **/
+ 
+//return value definitions
+/** @brief Error code for init failure **/
+#define ERROR_INIT_FAILED 1
+/** @brief Error code for duplicate init calls **/
+#define ERROR_INIT_ALREADY_INITD 2
+/** @brief Error code for not calling init **/
+#define ERROR_LIBRARY_NOT_INITD 3
+
+// Configuration definitions
+/** @brief Initialize analog **/
+#define ANALOG 0x01
+/** @brief Initialize serial communications **/
+#define SERIAL 0x02
+/** @brief Initialize USB communications **/
+#define USB    0x02
+/** @brief Initialize communications **/
+#define COMM   0x02
+/** @brief Initialize the orb **/
+#define ORB    0x04
+/** @brief Initialize the motors **/
+#define MOTORS 0x08
+/** @brief Initialize I2C **/
+#define I2C    0x20
+/** @brief Initialize the buzzer **/
+#define BUZZER 0x40
+/** @brief Initialize the LCD screen **/
+#define LCD    0x80
+/** @brief Initialize the rangefinders **/
+#define RANGE  0x0100
+/** @brief Initialize the BOM **/
+#define BOM  0x0200
+/** @brief Initilize encoders **/
+#define ENCODERS 0x400
+/** @brief Initialize everything  **/
+#define ALL_ON 0x07FF 
+ 
+ /** @} **/ //end addtogroup
+ 
+ /** @brief shortcut for ATOMIC_BLOCK(ATOMIC_RESTORESTATE) **/
+#define SYNC ATOMIC_BLOCK(ATOMIC_RESTORESTATE)
+
+/** @brief atomically grab a lock if it is free, return otherwise **/
+#define REQUIRE_LOCK_OR_RETURN(LOCK) do { SYNC { if (LOCK) return; LOCK=1; } } while (0)
+
+/** @brief atomically release a lock **/
+#define RELEASE_LOCK(LOCK) do { LOCK=0; } while (0)
+
+
+#endif
\ No newline at end of file
Index: branches/wireless/code/projects/libdragonfly/i2c.c
===================================================================
--- branches/wireless/code/projects/libdragonfly/i2c.c	(nonexistent)
+++ branches/wireless/code/projects/libdragonfly/i2c.c	(revision 1493)
@@ -0,0 +1,364 @@
+/**
+ * Copyright (c) 2007 Colony Project
+ * 
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ * 
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ **/
+
+
+/**
+ * @file i2c.c
+ * @brief Implemenation of I2C communications protocol
+ * 
+ * In the case where you have master sends and then a master request to the same
+ * address, you will not give up control of the line because the send and
+ * request addresses are seen as different addresses. In between it will send a
+ * restart but will not give up the line.
+ *
+ * @author CMU Robotics Club, Kevin Woo, Sursh Nidhiry
+ * @bug Not tested.
+ */
+
+#include <avr/interrupt.h>
+#include <util/twi.h>
+
+#include "i2c.h"
+#include "ring_buffer.h"
+
+//NOTE: this is here just to provide colony error codes, it can be safely removed
+// for use in another project
+#include <dragonfly_lib.h>
+
+/**
+ * @defgroup i2c I2C 
+ *
+ * @brief Provides Inter-Interconnected-Communications (I2C)
+ * 
+ * Initiates I2C functions on an ATMega128 which has a fully hardware Two Wire 
+ * Interface (TWI) module. Any Atmel chip with this hardware should be able to
+ * use the software.
+ *
+ * This code will operate in a multi-master enviornment and can be either a
+ * slave or a master at any time (as long as they are not one or the other at
+ * the moment. You can queue up multiple transmission modes in the buffer up to 
+ * the buffer size. The buffer is implemented as a ring buffer.
+ *
+ * It is implemented using callback functions. Whenever you want to send a packet
+ * you can call the built in send function (as a master) and it will send an array
+ * of bytes. Master recieve and slave send/receive are all handled by the call back
+ * functions. It is up to the end user to create functions that will handle the
+ * receiving of packets. Their functions will be called with every byte recieved
+ * so you must either buffer the inputs or handle each one separately.
+ *
+ * On errors we will simply flush the entire buffer.
+ * 
+ * For information on how I2C operates, read the wikipedia article
+ * http://en.wikipedia.org/wiki/I2c
+ * for a good explanation of how it works.
+ * @{
+ */
+
+/** 
+ * @brief Set bit rate 12 = 100kbit/s (max speed setting is 10 for an
+ *  8 MHz clock). It is a divider, so the lower the number the faster the speed.
+ */
+#define I2C_BIT_RATE_DIVIDER 0x0C
+
+unsigned char i2c_initd=0;
+
+static int start_flag;
+
+static fun_mrecv_t master_recv_function;
+static fun_srecv_t slave_recv_function;
+static fun_send_t slave_send_function;
+
+RING_BUFFER_NEW(i2c_buffer, 128, char, i2c_write_buff, i2c_addr_buff);
+
+
+/**
+ * @brief Initializes the i2c module.
+ *
+ * Initializes the I2C module to start listening on the i2c lines. If the callback functions
+ * are not set to null they will be called when that transmission mode is called. The address
+ * is your address that you will listen to when you are not the master.
+ *
+ * @param addr 			Your address on the I2C bus.
+ * @param master_recv 	The address of the function to call when you receive a byte when you are a
+ *                    	master.
+ * @param slave_recv 	The address of the function to call when you are a slave you receive data
+ *								from the master
+ * @param slave_send		The address of the function to call when you are a slave and the master
+ *								requests data from you.
+ *
+ * @return 0 for success, nonzero for failure
+ **/
+int i2c_init(char addr, fun_mrecv_t master_recv, fun_srecv_t slave_recv, fun_send_t slave_send) {
+
+    if(i2c_initd)
+      return ERROR_INIT_ALREADY_INITD;
+
+
+    master_recv_function = master_recv;
+    slave_recv_function = slave_recv;
+    slave_send_function = slave_send;
+
+    RING_BUFFER_CLEAR(i2c_write_buff);
+    RING_BUFFER_CLEAR(i2c_addr_buff);
+  
+    /* enables twi interrupt, automatic ack sending, and all twi hardware */
+    TWCR =  (_BV(TWEA) | _BV(TWEN) | _BV(TWIE));
+
+    /* sets the bit rate of data transmission */
+    TWBR = I2C_BIT_RATE_DIVIDER;
+
+    /* sets the address (it is stored in the 7 most significant bits) and allows
+     * global messages to be accepted */
+    TWAR = (addr << 1) | 1;
+  
+    i2c_initd = 1;
+    return 0;
+}
+
+/**
+ * @brief Sends a byte array over I2C as a master
+ *
+ * Will perform a send over I2C to the destination from data for the ammount of
+ * bytes that bytes is.
+ *
+ * @param dest		Destination address of the data on the I2C bus.
+ * @param data 	The pointer to the byte array of data
+ * @param bytes	The amount of bytes long that the byte array is. This is how
+ *						many bytes from the array that the function will send.
+ *
+ * @return zero for success, nonzero for failure
+ **/
+int i2c_send(char dest, char *data, unsigned int bytes) {
+    int i;
+
+    if(!i2c_initd)
+      return ERROR_LIBRARY_NOT_INITD;
+
+
+    /* adding data to be sent to ring buffers is not atomic,
+     * so disable interrupts */
+    cli();
+    for(i = 0; i < bytes; i++) {
+        if(RING_BUFFER_FULL(i2c_write_buff)) {
+            sei();
+            return -1;
+        }
+
+        RING_BUFFER_ADD(i2c_write_buff, data[i]);
+        RING_BUFFER_ADD(i2c_addr_buff, dest << 1);
+    }
+    
+    /* re-enable the interrupts */
+    sei();
+    
+    /* send the start bit, only if this device is not currently master */
+    if(!start_flag) {
+        start_flag = 1;
+        TWCR |= _BV(TWSTA);
+        TWCR |= _BV(TWINT);
+    }
+  
+    return 0;
+}
+ 
+/**
+ * @brief Send a master request to the destination
+ *
+ * Sends a request of data from the target address and calls
+ * the callback function to handle data as it comes in. This function will
+ * not work if the slave has not informationt to send or has nothing implemented
+ * to send it.
+ *
+ * @param dest		The destination that we want to receive information from.
+ *
+ * @return 0 for success, nonzero for failure
+ **/ 
+int i2c_request(char dest) {
+    if(!i2c_initd)
+      return ERROR_LIBRARY_NOT_INITD;
+
+    if(RING_BUFFER_FULL(i2c_write_buff))
+        return -1;
+  
+    RING_BUFFER_ADD(i2c_write_buff, 0);
+    RING_BUFFER_ADD(i2c_addr_buff, (dest << 1) | 1);
+  
+    if(!start_flag) {
+        start_flag = 1;
+        TWCR |= _BV(TWSTA);
+        TWCR |= _BV(TWINT);
+    }
+  
+    return 0;
+}
+
+/** @} **/
+ 
+/**
+ * @brief Interrupt to handle I2C interrupts from the I2C hardware.
+ * 
+ * Uses the status codes from the I2C register to handle the events
+ * needed to advance in I2C stages. For instance, you will get a bit for
+ * receiving a start ack, then a address ack, then a data ack, etc.
+ * The events are handled in each switch case. The status codes are defined
+ * by avr-gcc in /util/twi.h but are the same codes as the Atmel documentation.
+ *
+ * Bytes are sent by popping off the ring buffer. It also will keep track
+ * of what modes the send is in.
+ *
+ * Errors are handled here as well.
+ **/ 
+ISR(TWI_vect) {
+	static char data_to_send;
+	static char addr_to_send = -1;
+	char addr, statusCode;
+  
+	//Get status code (only upper 5 bits)
+	statusCode = (TWSR & 0xF8);
+
+    switch (statusCode) {
+        //Start sent successfully
+        case TW_START:
+        case TW_REP_START:
+            /* Send address and write
+             * ring_buffer will not be empty */
+            RING_BUFFER_REMOVE(i2c_addr_buff, addr_to_send);
+            RING_BUFFER_REMOVE(i2c_write_buff, data_to_send);
+            
+            /* first send the address */
+            TWDR = addr_to_send; 
+            
+            //Turn off start bits
+            TWCR &= ~_BV(TWSTA);
+            break;
+
+        //Master Transmit - Address sent succesfully
+        case TW_MT_SLA_ACK:
+        //Send byte
+            TWDR = data_to_send;
+            PORTG &= ~_BV(PG2);
+            break;
+	 
+        //Master Transmit - Data sent succesfully
+        case TW_MT_DATA_ACK:    
+            //If there is still data to send
+            if(!RING_BUFFER_EMPTY(i2c_write_buff)) {
+                RING_BUFFER_PEEK(i2c_addr_buff, addr);
+        
+                //Still data for this address
+                if (addr == addr_to_send) {
+                    RING_BUFFER_REMOVE(i2c_addr_buff, addr);
+                    RING_BUFFER_REMOVE(i2c_write_buff, TWDR);
+                    break;
+                //No more data for this address, data for another address -> resend start
+                } else {
+                    TWCR |= _BV(TWSTA);
+                    break;
+                }
+            }
+            /* there are no bytes to send */
+            TWCR |= _BV(TWSTO);
+            start_flag = 0;
+            break; 
+            
+        //Master Transmit - Slave sends a nack, transmit is done
+        case TW_MT_DATA_NACK:
+            PORTG |= _BV(PG2);
+            TWCR |= _BV(TWSTO);
+            start_flag = 0;
+            break;
+    
+        //Master Receive - Address sent succesfully
+        case TW_MR_SLA_ACK:
+            PORTG |= _BV(PG2);
+            break;
+            
+        //Master Receive - Data received succesfully
+        case TW_MR_DATA_ACK:
+            if(master_recv_function) {
+                if(!master_recv_function(TWDR)) {
+                    TWCR &= ~_BV(TWEA);
+                }
+            }
+            break;
+            
+        //Master Receive - Slave sends a nack, transmission is done    
+        case TW_MR_DATA_NACK:
+            TWCR |= _BV(TWEA);
+      
+            //If there is still data to send
+            if(!RING_BUFFER_EMPTY(i2c_write_buff)) {
+                TWCR |= _BV(TWSTA);
+                break;
+            }
+      
+            /* there are no bytes to send */
+            TWCR |= _BV(TWSTO);
+            start_flag = 0;  
+            break;
+    
+        //Slave Transmit - Address received
+        case TW_ST_SLA_ACK:
+            break;
+    
+        //Slave Transmit - Nack received, no data requsted
+        case TW_ST_DATA_NACK:
+            break;
+        
+        //Slave Transmit - Data requested, ack received
+        case TW_ST_DATA_ACK:
+            if (slave_send_function) {
+                TWDR = slave_send_function();
+            }
+            break;
+    
+        //Slave Receive - Address received  
+        case TW_SR_SLA_ACK:
+            break;
+    
+        //Slave Receive - Data received, ack returned
+        case TW_SR_DATA_ACK:
+            if(slave_recv_function) {
+                slave_recv_function(TWDR);
+            }
+            
+            break;
+      
+        //Stop sent  
+        case TW_SR_STOP:
+            break;
+	
+        //Problem on the bus, reset everything
+        default:
+            TWCR |= _BV(TWSTO);
+            start_flag = 0;
+            RING_BUFFER_CLEAR(i2c_write_buff);
+            RING_BUFFER_CLEAR(i2c_addr_buff);  	
+    }
+  
+  /* Toggle TWINT so that it resets and executes the commands */
+  TWCR |= _BV(TWINT);
+}
+
Index: branches/wireless/code/projects/libdragonfly/eeprom.c
===================================================================
--- branches/wireless/code/projects/libdragonfly/eeprom.c	(nonexistent)
+++ branches/wireless/code/projects/libdragonfly/eeprom.c	(revision 1493)
@@ -0,0 +1,86 @@
+/**
+ * @file eeprom.c
+ * @brief handles eeprom storage for persistent data
+ *
+ * Contains functions and definitions for reading and writing to eeprom
+ *
+ * @author Colony Project, Brad Neuman
+ */
+ 
+#include <avr/io.h>
+#include "eeprom.h"
+
+/** @brief store a byte to eeproem
+ *  @return 0 if success, nonzero on failure
+ */
+int eeprom_put_byte(unsigned int uiAddress, unsigned char ucData) {
+    /* Wait for completion of previous write */
+    while(EECR & (1<<EEWE));
+    /* Set up address and data registers */
+    EEAR = uiAddress;
+    EEDR = ucData;
+    /* Write logical one to EEMWE */
+    EECR |= (1<<EEMWE);
+    /* Start eeprom write by setting EEWE */
+    EECR |= (1<<EEWE);
+    
+    return 0;
+}
+
+/** @brief reads a byte from eeprom
+ *
+ *  Pass it thge address and a pointer to a byte where the byte at the
+ *  address will be stored
+ *
+ *  @return 0 if successful (byte is set to the eeprom value at addr), 
+ *  nonzero if there was a problem
+ */
+int eeprom_get_byte(unsigned int uiAddress, unsigned char *byte) {
+    /* Wait for completion of previous write */
+    while(EECR & (1<<EEWE));
+    /* Set up address register */
+    EEAR = uiAddress;
+    /* Start eeprom read by writing EERE */
+    EECR |= (1<<EERE);
+    /* get data from data register */
+    *byte=EEDR;
+    
+    return 0;
+}
+
+/** @brief get stored robot ID
+ *
+ *  checks that EEPROM has been programed with an ID and returns it
+ *
+ *  @return the robot id, if it is stored. If it returns 0xFF it is probably invalid
+ */
+unsigned char get_robotid(void) {
+    unsigned char c0, c1, c2;
+    
+    eeprom_get_byte(EEPROM_ROBOT_ID_ADDR, &c0);
+    eeprom_get_byte(EEPROM_ROBOT_ID_ADDR+1, &c1);
+    eeprom_get_byte(EEPROM_ROBOT_ID_ADDR+2, &c2);
+    if(c0 == 'I' && c1 == 'D')
+        return c2;
+    else
+        return 0xFF;
+}
+
+/** @brief get stored robot ID
+ *
+ * checks that EEPROM has been programed with an BOM type and returns it
+ *
+ *  @return the robot bom type as defined in bom.h, if it is stored. If it returns 0xFF it is probably invalid
+ */
+unsigned char get_bom_type(void) {
+    unsigned char c0, c1, c2, c3;
+    
+    eeprom_get_byte(EEPROM_BOM_TYPE_ADDR, &c0);
+    eeprom_get_byte(EEPROM_BOM_TYPE_ADDR+1, &c1);
+    eeprom_get_byte(EEPROM_BOM_TYPE_ADDR+2, &c2);
+    eeprom_get_byte(EEPROM_BOM_TYPE_ADDR+3, &c3);
+    if(c0 == 'B' && c1 == 'O' && c2 == 'M')
+        return c3;
+    else
+        return 0xFF;
+}
Index: branches/wireless/code/projects/libdragonfly/eeprom.h
===================================================================
--- branches/wireless/code/projects/libdragonfly/eeprom.h	(nonexistent)
+++ branches/wireless/code/projects/libdragonfly/eeprom.h	(revision 1493)
@@ -0,0 +1,15 @@
+ #ifndef _EEPROM_H_
+ #define _EEPROM_H_
+ 
+ #define EEPROM_ROBOT_ID_ADDR 0x10
+ #define EEPROM_BOM_TYPE_ADDR 0x14
+ 
+ int eeprom_put_byte(unsigned int addr, unsigned char byte);
+ 
+ int eeprom_get_byte(unsigned int addr, unsigned char *byte);
+ 
+ unsigned char get_robotid(void);
+  
+ unsigned char get_bom_type(void);
+ 
+ #endif
Index: branches/wireless/code/projects/libdragonfly/analog.h
===================================================================
--- branches/wireless/code/projects/libdragonfly/analog.h	(nonexistent)
+++ branches/wireless/code/projects/libdragonfly/analog.h	(revision 1493)
@@ -0,0 +1,138 @@
+/**
+ * Copyright (c) 2007 Colony Project
+ * 
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ * 
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ **/
+
+/**
+ * 
+ * @file analog.h
+ * @brief Contains functions and definitions for using the ADC
+ * 
+ * Contains definitions and function prototypes for using the
+ * ADC to detect analog signals on pins AN0 - AN7.
+ * AN6 and AN7 are used for the wheel and battery.
+	
+ * The pins labeled E6 and E7 are external interrupt pins and are not related 
+ * to analog.
+	
+ * @author Colony Project, CMU Robotics Club, based on firefly
+ * originally taken from fwr analog file (author: Tom Lauwers)
+ * loop code written by Kevin Woo and James Kong
+ */
+
+#ifndef _ANALOG_H
+#define _ANALOG_H
+
+#include <inttypes.h>
+
+/**
+ * @addtogroup analog
+ * @{
+ **/
+
+/** @brief Analog port 0 **/
+#define AN0 0x00
+/** @brief Analog port 1 **/
+#define AN1 0x01
+/** @brief Analog port 2 **/
+#define AN2 0x02
+/** @brief Analog port 3 **/
+#define AN3 0x03
+/** @brief Analog port 4 **/
+#define AN4 0x04
+/** @brief Analog port 5 **/
+#define AN5 0x05
+/** @brief Analog port 6 **/
+#define AN6 0x06
+/** @brief Analog port 7 **/
+#define AN7 0x07
+/** @brief Analog port 8 **/
+#define AN8 0x08
+/** @brief Analog port 9 **/
+#define AN9 0x09
+/** @brief Analog port 10 **/
+#define AN10 0x0A
+/** @brief Analog port 11 **/
+#define AN11 0x0B
+/** @brief Analog port 12 **/
+#define AN12 0x0C
+/** @brief Analog port 13 **/
+#define AN13 0x0D
+/** @brief Analog port 14 **/
+#define AN14 0x0E
+/** @brief Analog port 15 **/
+#define AN15 0x0F
+
+/** @brief BOM_PORT analog port for BOM **/
+#define BOM_PORT AN0
+/** @brief EXT_MUX analog port **/
+#define EXT_MUX AN7
+/** @brief Analog port for the wheel **/
+#define WHEEL_PORT AN10
+/** @brief Analog port for the battery voltage detector **/
+#define BATT_PORT  AN11
+
+/** @brief Analog loop status. ADC conversion running. **/
+#define ADC_LOOP_RUNNING 1
+/** @brief Analog loop status.  No ADC conversion running.**/
+#define ADC_LOOP_STOPPED 0
+
+/** @brief Analog init parameter. Start the analog loop. **/
+#define ADC_START 1
+/** @brief Analog init parameter. Don't start the analog loop. **/
+#define ADC_STOP  0
+
+#define ADMUX_OPT 0x60
+
+/** @brief Struct to hold the value of a particular analog port **/
+typedef struct {
+  uint8_t adc8;
+  uint16_t adc10;
+} adc_t;
+
+
+/** @brief Initialize analog ports. Will start running a loop
+    if start_conversion is ADC_START.**/
+int analog_init(int start_conversion);
+/** @brief starts the analog loop. Doesn't do anything if the loop is already running. **/
+int analog_start_loop(void);
+/** @brief Stops the analog loop. Doesn't do anything if the loop is already stopped. **/
+int analog_stop_loop(void);
+/** @brief Returns the status of the analog loop. **/
+int analog_loop_status(void);
+/** @brief Returns an 8-bit analog value from the look up table. Use this instead of analog_get8. **/
+unsigned int analog8(int which);
+/** @brief Returns an 10-bit analog value from the look up table. Use this instead of analog_get10. **/
+unsigned int analog10(int which);
+/** @brief Read the position of the wheel. **/
+int wheel(void);
+/** @brief Read an 8-bit number from an analog port. Loop must be stopped for this to work. **/
+unsigned int analog_get8(int which);
+/** @brief Read a 10-bit number from an analog port. Loop must be stopped for this to work. **/
+unsigned int analog_get10(int which);
+
+
+/**@}**/ //end group
+
+#endif
+
Index: branches/wireless/code/projects/libdragonfly/bom.h
===================================================================
--- branches/wireless/code/projects/libdragonfly/bom.h	(nonexistent)
+++ branches/wireless/code/projects/libdragonfly/bom.h	(revision 1493)
@@ -0,0 +1,89 @@
+/**
+ * Copyright (c) 2007 Colony Project
+ * 
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ * 
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ **/
+
+
+/**
+ * @file bom.h
+ * @brief Definitions for using the BOM
+ * 
+ * This file contains definitions for using the Bearing and 
+ * Orientation Module (BOM).
+ *
+ * @author Colony Project, CMU Robotics Club
+ *
+ **/
+
+#ifndef _BOM_H
+#define _BOM_H
+
+/**
+ * @addtogroup bom
+ * @{
+ **/
+ 
+/** @brief Include all elements in the 16-bit bitfield **/
+#define BOM_ALL 0xFFFF
+
+/** @brief Original BOM - No Range, No Individual LED control **/
+#define BOM10     0
+
+/** @brief BOM 1.5 - No Range, Individual LED control **/
+#define BOM15   1
+
+/** @brief RBOM - Range, Individual LED control **/
+#define RBOM    2
+
+
+/** @brief Initialize the bom according to bom type **/
+int bom_init(char type);
+
+/** @brief Refresh bom_val[] with new values from analog8.  analog_init and bom_init must be called for this to work. **/
+int bom_refresh(int bit_field);
+
+/** @brief Gets the bom reading from bom_val[which].  Call bom_refresh beforehand to read new bom values. **/
+int bom_get(int which);
+
+/** @brief Compares all the values in bom_val[] and returns the index to the highest value element. **/
+int bom_get_max(void);
+
+/** @brief Computes the weighted average of all the bom readings to estimate the position and distance of another robot. **/
+int bom_get_max10(int *dist);
+
+/** @brief Enables the selected bom leds on a BOM1.5 **/
+int bom_set_leds(int bit_field);
+
+/** @brief (DEPRECATED) Gets and compares all bom values.  Returns the index to the highest value element since last refresh. **/
+int get_max_bom(void);
+
+/** @brief Turns on all BOM leds, or turns on enabled leds on a BOM1.5. **/
+int bom_on(void);
+
+/** @brief Turns off all bom leds. **/
+int bom_off(void);
+
+/** @} **/
+
+#endif
+
Index: branches/wireless/code/projects/libdragonfly/lcd.c
===================================================================
--- branches/wireless/code/projects/libdragonfly/lcd.c	(nonexistent)
+++ branches/wireless/code/projects/libdragonfly/lcd.c	(revision 1493)
@@ -0,0 +1,312 @@
+/**
+ * Copyright (c) 2007 Colony Project
+ * 
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ * 
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ **/
+
+
+/**
+ * @file lcd.c
+ * @brief LCD
+ *
+ * Implementation of functions for using the LCD.
+ *
+ * @author Colony Project, CMU Robotics Club
+ **/
+#include <avr/io.h>
+#include <avr/pgmspace.h>
+
+#include "lcd.h"
+#include "time.h"
+
+//LCD defines
+#define RST _BV(4)  // pd4 (GPIO)
+#define SCE _BV(0)  // pb0 (~SS)
+#define D_C _BV(5)  // pd5 (GPIO?)
+#define SDI _BV(2)  // pb2 (MOSI)
+#define SCK _BV(1) // pb1 (SCK)
+
+#define LCDPORT PORTB
+#define LCDDDR DDRB
+
+#define LCDRESETPORT PORTD
+#define LCDRESETDDR DDRD
+
+void lcd_putbyte(unsigned char b);
+
+
+//**************************************Old shit below!*****************
+/*
+  FontLookup - a lookup table for all characters
+*/
+static const unsigned char FontLookup [][5] PROGMEM =
+  {
+    { 0x00, 0x00, 0x00, 0x00, 0x00 },  // sp
+    { 0x00, 0x00, 0x5f, 0x00, 0x00 },   // !
+    { 0x00, 0x07, 0x00, 0x07, 0x00 },   // "
+    { 0x14, 0x7f, 0x14, 0x7f, 0x14 },   // #
+    { 0x24, 0x2a, 0x7f, 0x2a, 0x12 },   // $
+    { 0x23, 0x13, 0x08, 0x64, 0x62 },   // %
+    { 0x36, 0x49, 0x55, 0x22, 0x50 },   // &
+    { 0x00, 0x05, 0x03, 0x00, 0x00 },   // '
+    { 0x00, 0x1c, 0x22, 0x41, 0x00 },   // (
+    { 0x00, 0x41, 0x22, 0x1c, 0x00 },   // )
+    { 0x14, 0x08, 0x3E, 0x08, 0x14 },   // *
+    { 0x08, 0x08, 0x3E, 0x08, 0x08 },   // +
+    { 0x00, 0x00, 0x50, 0x30, 0x00 },   // ,
+    { 0x10, 0x10, 0x10, 0x10, 0x10 },   // -
+    { 0x00, 0x60, 0x60, 0x00, 0x00 },   // .
+    { 0x20, 0x10, 0x08, 0x04, 0x02 },   // /
+    { 0x3E, 0x51, 0x49, 0x45, 0x3E },   // 0
+    { 0x00, 0x42, 0x7F, 0x40, 0x00 },   // 1
+    { 0x42, 0x61, 0x51, 0x49, 0x46 },   // 2
+    { 0x21, 0x41, 0x45, 0x4B, 0x31 },   // 3
+    { 0x18, 0x14, 0x12, 0x7F, 0x10 },   // 4
+    { 0x27, 0x45, 0x45, 0x45, 0x39 },   // 5
+    { 0x3C, 0x4A, 0x49, 0x49, 0x30 },   // 6
+    { 0x01, 0x71, 0x09, 0x05, 0x03 },   // 7
+    { 0x36, 0x49, 0x49, 0x49, 0x36 },   // 8
+    { 0x06, 0x49, 0x49, 0x29, 0x1E },   // 9
+    { 0x00, 0x36, 0x36, 0x00, 0x00 },   // :
+    { 0x00, 0x56, 0x36, 0x00, 0x00 },   // ;
+    { 0x08, 0x14, 0x22, 0x41, 0x00 },   // <
+    { 0x14, 0x14, 0x14, 0x14, 0x14 },   // =
+    { 0x00, 0x41, 0x22, 0x14, 0x08 },   // >
+    { 0x02, 0x01, 0x51, 0x09, 0x06 },   // ?
+    { 0x32, 0x49, 0x59, 0x51, 0x3E },   // @
+    { 0x7E, 0x11, 0x11, 0x11, 0x7E },   // A
+    { 0x7F, 0x49, 0x49, 0x49, 0x36 },   // B
+    { 0x3E, 0x41, 0x41, 0x41, 0x22 },   // C
+    { 0x7F, 0x41, 0x41, 0x22, 0x1C },   // D
+    { 0x7F, 0x49, 0x49, 0x49, 0x41 },   // E
+    { 0x7F, 0x09, 0x09, 0x09, 0x01 },   // F
+    { 0x3E, 0x41, 0x49, 0x49, 0x7A },   // G
+    { 0x7F, 0x08, 0x08, 0x08, 0x7F },   // H
+    { 0x00, 0x41, 0x7F, 0x41, 0x00 },   // I
+    { 0x20, 0x40, 0x41, 0x3F, 0x01 },   // J
+    { 0x7F, 0x08, 0x14, 0x22, 0x41 },   // K
+    { 0x7F, 0x40, 0x40, 0x40, 0x40 },   // L
+    { 0x7F, 0x02, 0x0C, 0x02, 0x7F },   // M
+    { 0x7F, 0x04, 0x08, 0x10, 0x7F },   // N
+    { 0x3E, 0x41, 0x41, 0x41, 0x3E },   // O
+    { 0x7F, 0x09, 0x09, 0x09, 0x06 },   // P
+    { 0x3E, 0x41, 0x51, 0x21, 0x5E },   // Q
+    { 0x7F, 0x09, 0x19, 0x29, 0x46 },   // R
+    { 0x46, 0x49, 0x49, 0x49, 0x31 },   // S
+    { 0x01, 0x01, 0x7F, 0x01, 0x01 },   // T
+    { 0x3F, 0x40, 0x40, 0x40, 0x3F },   // U
+    { 0x1F, 0x20, 0x40, 0x20, 0x1F },   // V
+    { 0x3F, 0x40, 0x38, 0x40, 0x3F },   // W
+    { 0x63, 0x14, 0x08, 0x14, 0x63 },   // X
+    { 0x07, 0x08, 0x70, 0x08, 0x07 },   // Y
+    { 0x61, 0x51, 0x49, 0x45, 0x43 },   // Z
+    { 0x00, 0x7F, 0x41, 0x41, 0x00 },   // [
+    { 0x02, 0x04, 0x08, 0x10, 0x20 },   // backslash
+    { 0x00, 0x41, 0x41, 0x7F, 0x00 },   // ]
+    { 0x04, 0x02, 0x01, 0x02, 0x04 },   // ^
+    { 0x40, 0x40, 0x40, 0x40, 0x40 },   // _
+    { 0x00, 0x01, 0x02, 0x04, 0x00 },   // '
+    { 0x20, 0x54, 0x54, 0x54, 0x78 },   // a
+    { 0x7F, 0x48, 0x44, 0x44, 0x38 },   // b
+    { 0x38, 0x44, 0x44, 0x44, 0x20 },   // c
+    { 0x38, 0x44, 0x44, 0x48, 0x7F },   // d
+    { 0x38, 0x54, 0x54, 0x54, 0x18 },   // e
+    { 0x08, 0x7E, 0x09, 0x01, 0x02 },   // f
+    { 0x0C, 0x52, 0x52, 0x52, 0x3E },   // g
+    { 0x7F, 0x08, 0x04, 0x04, 0x78 },   // h
+    { 0x00, 0x44, 0x7D, 0x40, 0x00 },   // i
+    { 0x20, 0x40, 0x44, 0x3D, 0x00 },   // j
+    { 0x7F, 0x10, 0x28, 0x44, 0x00 },   // k
+    { 0x00, 0x41, 0x7F, 0x40, 0x00 },   // l
+    { 0x7C, 0x04, 0x18, 0x04, 0x78 },   // m
+    { 0x7C, 0x08, 0x04, 0x04, 0x78 },   // n
+    { 0x38, 0x44, 0x44, 0x44, 0x38 },   // o
+    { 0x7C, 0x14, 0x14, 0x14, 0x08 },   // p
+    { 0x08, 0x14, 0x14, 0x18, 0x7C },   // q
+    { 0x7C, 0x08, 0x04, 0x04, 0x08 },   // r
+    { 0x48, 0x54, 0x54, 0x54, 0x20 },   // s
+    { 0x04, 0x3F, 0x44, 0x40, 0x20 },   // t
+    { 0x3C, 0x40, 0x40, 0x20, 0x7C },   // u
+    { 0x1C, 0x20, 0x40, 0x20, 0x1C },   // v
+    { 0x3C, 0x40, 0x30, 0x40, 0x3C },   // w
+    { 0x44, 0x28, 0x10, 0x28, 0x44 },   // x
+    { 0x0C, 0x50, 0x50, 0x50, 0x3C },   // y
+    { 0x44, 0x64, 0x54, 0x4C, 0x44 },    // z
+    { 0x00, 0x08, 0x36, 0x41, 0x41 },   // {
+    { 0x00, 0x00, 0x7F, 0x00, 0x00 },   // |
+    { 0x41, 0x41, 0x36, 0x08, 0x00 },   // }
+    { 0x02, 0x01, 0x01, 0x02, 0x01 },   // ~
+    { 0x55, 0x2A, 0x55, 0x2A, 0x55 },   // del
+  };
+
+
+/**
+ * @defgroup lcd LCD
+ * @brief Functions for the LCD
+ * Functions for writing to the LCD.
+ * All functions may be found in lcd.h.
+ *
+ * @{
+ **/
+
+/**
+ * Initializes the LCD. Must be called before any other
+ * LCD functions.
+ **/
+void lcd_init(void) {
+  LCDDDR |= (SCE | SDI | SCK);
+  LCDRESETDDR |= (RST|D_C);
+
+  LCDPORT &= ~( SCE | SDI | SCK);
+  LCDRESETPORT &=~(D_C);
+  
+  SPCR |= 0x50;//0b01010000; // no SPI int, SPI en, Master, sample on rising edge, fosc/2
+  SPSR |= 0x01;       // a continuation of the above
+
+  LCDRESETPORT |= RST;
+  delay_ms(10);
+  LCDRESETPORT &= (~RST);
+  delay_ms(100);
+  LCDRESETPORT |= RST;
+	
+  lcd_putbyte( 0x21 );  // LCD Extended Commands.
+  lcd_putbyte( 0xC8 );  // Set LCD Vop (Contrast).
+  lcd_putbyte( 0x06 );  // Set Temp coefficent.
+  lcd_putbyte( 0x13 );  // LCD bias mode 1:48.
+  lcd_putbyte( 0x20 );  // LCD Standard Commands, Horizontal addressing mode.
+  lcd_putbyte( 0x0C );  // LCD in normal mode.
+	
+  LCDRESETPORT |= D_C;		//put it in init instead of main
+	
+  lcd_clear_screen();
+}
+
+/**
+ * Clears the LCD screen. lcd_init must be called first.
+ * 
+ * @see lcd_init
+ **/
+void lcd_clear_screen( void ) {
+  int i;
+  for (i = 0; i < 504; i++)
+    lcd_putbyte(0x0);
+	
+  lcd_gotoxy(0,0);
+}
+
+/**
+ * Prints a character on the LCD screen. lcd_init
+ * must be called before this function may be used.
+ *
+ * Note: pgm_read_byte() is untested
+ *
+ * @param c the character to print
+ *
+ * @see lcd_init
+ **/
+void lcd_putc(char c) {
+  int i;
+	
+  for (i = 0; i < 5; i++)
+    lcd_putbyte(pgm_read_byte(&(FontLookup[c-32][i])));
+  lcd_putbyte(0);
+}
+
+/*
+  print an entire string to the lcd
+*/
+void lcd_puts(char *s) {
+  char *t = s;
+  while (*t != 0) {
+    lcd_putc(*t);
+    t++;
+  }
+}
+
+/*
+  go to coordinate x, y
+  y: vertically - 1 char
+  x: horizontally - 1 pixel
+
+  multiply x by 6 if want to move 1 entire character
+
+  origin (0,0) is at top left corner of lcd screen
+*/
+
+/**
+ * Move the current cursor position to the one specified.
+ * lcd_init must be called before this function may be used.
+ * 
+ * @param x The x coordinate of the new position
+ * @param y The y coordinate of the new position
+ *
+ * @see lcd_init
+ **/
+void lcd_gotoxy(int x, int y) {
+  LCDRESETPORT &= ~(D_C);
+  lcd_putbyte(0x40 | (y & 0x07));
+  lcd_putbyte(0x80 | (x & 0x7f));
+  LCDRESETPORT |= D_C;
+}
+
+/*
+  prints an int to the lcd
+
+  code adapted from Chris Efstathiou's code (hendrix@otenet.gr)
+*/
+
+/**
+ * Print an integer to the LCD screen.
+ * lcd_init must be called before this function may be used.
+ * 
+ * @param value the integer to print
+ *
+ * @see lcd_init
+ **/
+void lcd_puti(int value ) {
+  unsigned char lcd_data[6]={'0','0','0','0','0','0' }, position=sizeof(lcd_data), radix=10; 
+
+  /* convert int to ascii  */ 
+  if(value<0) { 
+    lcd_putc('-'); 
+    value=-value; 
+  }    
+  do { 
+    position--; 
+    *(lcd_data+position)=(value%radix)+'0'; 
+    value/=radix;  
+  } while(value); 
+
+    
+  /* start displaying the number */
+  for(;position<=(sizeof(lcd_data)-1);position++)
+    lcd_putc(lcd_data[position]);
+
+  return;
+}
+
+/** @} **/ //end defgroup
+
+void lcd_putbyte(unsigned char b) {
+  SPDR = b;
+  while (!(SPSR & 0x80)); /* Wait until SPI transaction is complete */
+}
Index: branches/wireless/code/projects/libdragonfly/dragonfly_lib.c
===================================================================
--- branches/wireless/code/projects/libdragonfly/dragonfly_lib.c	(nonexistent)
+++ branches/wireless/code/projects/libdragonfly/dragonfly_lib.c	(revision 1493)
@@ -0,0 +1,146 @@
+/**
+ * Copyright (c) 2007 Colony Project
+ * 
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ * 
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ **/
+
+
+/**
+ * @file dragonfly_lib.c
+ * @brief Dragonfly initialization
+ *
+ * Contains implementation of dragonfly_init.
+ *
+ * @author Colony Project, CMU Robotics Club
+ **/
+
+#include "dragonfly_lib.h"
+
+/* init_dragonfly - Initializes functions based on configuration parameters
+   examples:
+
+   init_dragonfly (0, 0, 0); - just initialize the digital IO (buttons, potentiometer)
+
+   init_dragonfly (ANALOG | SERIAL | BUZZER, C0_C1_ANALOG, BAUD115200); 
+   Initialize ADC and set C0 and C1 as analog inputs.  Initialize serial and set baud rate
+   to 115200 bps.  Initialize the buzzer.
+   
+   init_dragonfly (MOTORS | ORB, 0, 0);
+   Initialize motor driving and the color fading abilities of the ORB. */
+
+/**
+ * @defgroup dragonfly Dragonfly
+ * @brief General Dragonfly Functions
+ * General functions for the dragonfly. Include
+ * dragonfly_lib.h to access these functions.
+ *
+ * @{
+ **/
+
+/**
+ * Initializes the components specified by config.
+ * 
+ * @see analog_init, usb_init, xbee_init, buzzer_init,
+ * bom_init, orb_init, motors_init, lcd_init, encoders_init
+ **/
+ 
+void flash_red(void);
+
+void dragonfly_init(int config) 
+{
+    sei();
+    // Set directionality of various IO pins
+    DDRG &= ~(_BV(PING0)|_BV(PING1));
+    PORTG |= _BV(PING0)|_BV(PING1);
+    
+    if(config & ANALOG)
+        analog_init(ADC_START);
+    
+    if(config & COMM)
+    {
+        //Defaults to 115200. Check serial.h for more information.
+        usb_init();
+        xbee_init();
+    }
+    
+    if(config & BUZZER)
+    {
+        sei();
+        buzzer_init();
+    }
+    
+    if(config & ORB)
+    {
+        sei();
+        orb_init();
+    }
+    
+    if(config & MOTORS)
+        motors_init();
+
+    if(config & LCD)
+        lcd_init();
+    
+    if(config & RANGE)
+        range_init();
+        
+    if(config & BOM)
+    {
+        unsigned char bom_read = get_bom_type();
+        if(bom_read == 0xFF)
+            //warn that bom initialization failed
+            flash_red();
+        else
+            bom_init(bom_read);
+    }
+
+	if (config & ENCODERS)
+	{
+		encoders_init();
+	}
+
+    // delay a bit for stability
+    _delay_ms(1);
+}
+
+//flash lights red three times and restore ports
+void flash_red(void)
+{
+    cli();
+    char dd = DDRC;
+    char po = PORTC;
+    char i;
+    DDRC = 0x77;
+    for(i = 0; i<3; i++)
+    {
+        PORTC = 0x77;
+        delay_ms(300);
+        PORTC = 0x66;
+        delay_ms(300);
+    }
+    
+    DDRC = dd;
+    PORTC = po;
+    sei();
+}
+/** @} **/ //end defgroup
+
Index: branches/wireless/code/projects/libdragonfly/buzzer.c
===================================================================
--- branches/wireless/code/projects/libdragonfly/buzzer.c	(nonexistent)
+++ branches/wireless/code/projects/libdragonfly/buzzer.c	(revision 1493)
@@ -0,0 +1,137 @@
+/**
+ * Copyright (c) 2007 Colony Project
+ * 
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ * 
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ **/
+
+
+/**
+ * @file buzzer
+ * @brief Functions for using the buzzer
+ *
+ * Contains functions for using the buzzer.
+ *
+ * @author Colony Project, CMU Robotics Club
+ *
+ * much taken from FWR's firefly library (author: Tom Lauwers)
+ **/
+
+#include <avr/io.h>
+#include "buzzer.h"
+#include "time.h"
+
+/**
+ * @defgroup buzzer Buzzer
+ * @brief Functions for controlling the buzzer.
+ * Functions for controlling the buzzer. Include
+ * buzzer.h to access these functions.
+ * @{
+ **/
+
+/**
+ * Initializes the buzzer. Must be called before any other buzzer
+ * function may be used.
+ **/
+void buzzer_init( void )
+{
+	//NOTE: This is mostly handled by buzzer_Set_val for now
+	// Set pin B7 to output - B7 is buzzer pin
+	//DDRB |= _BV(DDB7);
+	//Fast PWM Mode, Clear OCR0 on compare match and set at bottom, clock/64
+	//TCCR2 = _BV(COM20) | _BV(WGM21)  | _BV(CS22);
+}
+
+/**
+ * Sets the value of the buzzer's pitch.
+ * Higher values are lower frequencies.
+ *
+ * @param buzz_value the value to set the buzzer's frequency too,
+ * in the range 0-255
+ *
+ * @see buzzer_init, buzzer_set_freq, buzzer_off
+ **/
+void buzzer_set_val(unsigned int buzz_value)
+{ 
+	TCCR2 = _BV(COM20) | _BV(WGM21)  | _BV(CS22);
+	DDRB |= _BV(DDB7);
+	OCR2 = buzz_value;
+}
+
+/**
+ * Sets the buzzer frequency. Usage of constants such as C4
+ * is highly recommended as input to this function.
+ * buzzer_init must be called before this function may
+ * be used.
+ *
+ * @param buzz_freq the frequency to set the buzzer to
+ *
+ * @see buzzer_init, buzzer_set_val, buzzer_off
+ **/
+void buzzer_set_freq(unsigned int buzz_freq)
+{
+  int buzz_value;
+  
+  buzz_value = 62500/buzz_freq - 1;
+
+  if(buzz_value > 255){
+    buzz_value = 255;
+  }else if(buzz_value < 0){
+    buzz_value = 0;
+  }
+  
+  buzzer_set_val(buzz_value);
+}
+
+/**
+ * Plays the specified frequency for the specified
+ * amount of time. This function blocks execution
+ * until the time is completed. buzzer_init must be
+ * called before this function can be used.
+ *
+ * @param ms the time in milliseconds to play the frequency
+ * @param buzz_freq the frequency to play
+ *
+ * @see buzzer_init, buzzer_set_freq
+ **/
+void buzzer_chirp(unsigned int ms, unsigned int buzz_freq) 
+{ 
+  buzzer_set_freq(buzz_freq);
+  delay_ms(ms);
+  buzzer_off();
+}
+
+/**
+ * Turns off the buzzer by disabling the timer0 clock.
+ *
+ * @see buzzer_init
+ **/
+void buzzer_off()
+{
+  // Disable clock, to halt counter
+  TCCR2 &= 0xF8;//0b11111000;
+  
+  // Set buzzer pin low in case it's high
+  PORTB &= 0xBF;//0b10111111;
+}
+
+/** @} **/ // end buzzer group
+
Index: branches/wireless/code/projects/libdragonfly/i2c.h
===================================================================
--- branches/wireless/code/projects/libdragonfly/i2c.h	(nonexistent)
+++ branches/wireless/code/projects/libdragonfly/i2c.h	(revision 1493)
@@ -0,0 +1,55 @@
+/**
+ * Copyright (c) 2007 Colony Project
+ * 
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ * 
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ **/
+
+
+/** @file i2c.h
+ *  @brief Header file for I2C
+ *
+ *  Contains functions for I2C.
+ *
+ *  @author Kevin Woo and Suresh Nidhiry, Colony Project, CMU Robotics Club
+ **/
+
+
+#ifndef _I2C_H_
+#define _I2C_H_
+
+/** @brief Address of slave receive handler function **/
+typedef void (*fun_srecv_t)(char);
+
+/** @brief Address of master receive handler function**/
+typedef int (*fun_mrecv_t)(char);
+
+/** @brief Address of slave send handler function**/
+typedef char (*fun_send_t)(void);
+
+int i2c_init(char addr, fun_mrecv_t master_recv, fun_srecv_t slave_recv, fun_send_t slave_send);
+int i2c_send(char dest, char* data, unsigned int bytes);
+int i2c_request(char dest);
+
+void i2c_packet_rec (char i2c_byte);
+void i2c_packet_sniff(char data);
+#endif
+
Index: branches/wireless/code/projects/libdragonfly/odometry.c
===================================================================
--- branches/wireless/code/projects/libdragonfly/odometry.c	(nonexistent)
+++ branches/wireless/code/projects/libdragonfly/odometry.c	(revision 1493)
@@ -0,0 +1,152 @@
+#include "odometry.h"
+#include "encoders.h"
+#include <math.h>
+#include <avr/interrupt.h>
+#include "time.h"
+#include "serial.h"
+
+long lround(double d);
+
+
+int encoder_ltm1, encoder_rtm1;
+
+//Measure mm displacement in x and y from starting position. (+x:theta=0 +y:theta=M_PI/2)
+long diff_x,diff_y, velocity;
+
+//Measures radian angle displacement from starting position. (initially 0)
+double angle;
+
+/**
+ * Retrieve the estimated x position. [millimeters]
+ */
+long odometry_dx(void){
+	return diff_x;
+}
+
+/**
+ * Retrieve the estimated y position. [millimeters]
+ */
+long odometry_dy(void){
+	return diff_y;
+}
+
+/**
+ * Retrieve the estimated angle [radians]
+ */
+double odometry_angle(void){
+	return angle;
+}
+
+long odometry_velocity(void){
+	return velocity;
+}
+
+/**
+ * Initializes odometry to run on timer 2.
+ * Also resets all values so that the center of the robot is 
+ * considered to be at the origin facing the x direction.
+ */
+void odometry_init(void){
+	
+	encoders_init();
+	
+	delay_ms(100);
+
+	odometry_reset();
+
+	
+	//CTC Mode. CLK / 1024
+	TCCR2 = 0; // (Fully disconnected)
+	TCCR2 = _BV(WGM21) | _BV(CS22) | _BV(CS20); //CLK/1024 , CTC Mode.
+
+	TIMSK |= _BV(OCIE2);
+
+	OCR2 = ODOMETRY_CLK;
+}
+/**
+ * Resets all values so that the center of the robot is 
+ * considered to be at the origin facing the x direction.
+ */
+void odometry_reset(void){
+	diff_x = 0;
+	diff_y = 0;
+	encoder_ltm1 = encoder_read(LEFT);
+	encoder_rtm1 = encoder_read(RIGHT);
+	angle = 0.0;
+}
+
+
+void odometry_run(void){
+	//Angle swept through in a time step CCW-
+	double theta, rl, dc;
+	long dr,dl;
+	
+	//Get the change in wheel positions
+	{	
+		int encoder_right = encoder_read(RIGHT);	
+		int encoder_left = encoder_read(LEFT);	
+	
+		dl = encoder_left - encoder_ltm1;
+		dr = encoder_right - encoder_rtm1;
+		
+		//No motion.
+		if(dl == 0 && dr == 0) return;
+
+		encoder_ltm1 = encoder_left;
+		encoder_rtm1 = encoder_right;
+	
+		// Try to avoid over/underflow.
+		dl = dl > 512 ? dl - 1024 :dl;
+		dl = dl < -512 ? dl + 1024 :dl;
+		dr = dr > 512 ? dr - 1024 :dr;
+		dr = dr < -512 ? dr + 1024 :dr;
+	
+		//Convert "clicks" to um
+		dl *= CLICK_DISTANCE_UM; //um
+		dr *= CLICK_DISTANCE_UM;
+	}
+	
+
+	if(dl == dr){
+		diff_x += lround(dl*cos(angle)/1000.0); //mm
+		diff_y += lround(dl*sin(angle)/1000.0); //mm
+		velocity = lround((dl * 1000.0)/(ODOMETRY_CLK*TIME_SCALE)); //um / ms = mm/s
+    usb_puts("dc: ");
+    usb_puti(dl);
+    usb_puts("um, velocity: ");
+    usb_puti(velocity);
+		usb_puts("\r\n mm/s");
+		return;
+	}
+	
+	//Call the left wheel 0, clockwise positive.
+	rl = ((double)(ROBOT_WIDTH_UM*dl))/((double)(dl - dr)); //um
+	theta = ((double)(dl - dr))/((double)ROBOT_WIDTH_UM);   //rad
+	
+	//Distance the center has traveled.
+	dc = (theta * (rl - ROBOT_WIDTH_UM)) / 2.0; //um
+	velocity = lround( dc * 1000 /(ODOMETRY_CLK*TIME_SCALE));
+	usb_puts("dc: ");
+  usb_puti(dl);
+  usb_puts("um, velocity: ");
+  usb_puti(velocity);
+  usb_puts("\r\n mm/s");
+	
+	//angle is necessarily CCW+, so subtract.
+	angle -= ANGLE_SCALE * theta; 
+	
+	//Change state variables. Probably lose all measurements less then a mm.
+	diff_x += lround((DISTANCE_SCALE * dc * cos(angle))/1000.0); //mm
+	diff_y += lround((DISTANCE_SCALE * dc * sin(angle))/1000.0); //mm
+}
+
+ISR(TIMER2_COMP_vect){
+	odometry_run(); 
+}
+
+long lround(double d){
+	double f = floor(d);
+	return (long)(d - f > 0.5 ? f + 1 : f);
+}
+
+
Index: branches/wireless/code/projects/libdragonfly/move.c
===================================================================
--- branches/wireless/code/projects/libdragonfly/move.c	(nonexistent)
+++ branches/wireless/code/projects/libdragonfly/move.c	(revision 1493)
@@ -0,0 +1,189 @@
+/**
+ * Copyright (c) 2007 Colony Project
+ * 
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ * 
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ **/
+
+
+/**
+ * @file move.c
+ * @brief Functions for moving
+ *
+ * Implementation of functions for moving the robot.
+ *
+ * @author Colony Project, CMU Robotics Club
+ **/
+
+#include "move.h"
+#include "motor.h"
+#include "rangefinder.h"
+
+
+// Internal prototypes
+void translateAngulartoLinear (int velocity, int omega, int* vl, int* vr);
+
+// global varaibles for move_avoid
+int d1, d2, d3, d4, d5; 
+/**
+ * @defgroup move Movement
+ * @brief Functions fo controlling robot motion
+ * Higher level functions to control the movement of robots.
+ * 
+ * @{
+ **/
+
+
+/**
+ * Causes the robot to move with the given translation and rotational velocities.
+ * motors_init must be called before this function can be used.
+ *
+ * @param velocity the translational velocity of the robot, in the range -255 to 255.
+ * A positive value indicates forward motion, while a negative value indicates
+ * backwards motion.
+ * 
+ * @param omega the rotational velocity of the robot, in the range -255 to 255.
+ * A positive value indicates a counterclockwise velocity, while a negative
+ * value indicates a clockwise velocity.
+ *
+ * @see motors_init, motor1_set, motor2_set
+ **/
+void move (int velocity, int omega) {
+  int vl = 0;
+  int vr = 0;
+  translateAngulartoLinear(velocity, omega, &vl , &vr );
+  //
+  
+  if (vl < 0) {
+    motor1_set(BACKWARD, -vl);
+  } else {
+    motor1_set(FORWARD, vl);
+  }
+  if (vr < 0) {
+    motor2_set(BACKWARD, -vr);
+  } else {
+    motor2_set(FORWARD, vr);
+  }
+}
+
+
+/**
+ * Moves the robot with the given translational and angular velocities
+ * while avoiding obstacles. To be effective, this function must be
+ * called repeatedly throughout the motion. It relies on the IR
+ * rangefinders to detect obstacles. Before calling this function,
+ * motors_init and range_init must be called.
+ *
+ * @param velocity the translational velocity of the robot, in the
+ * range -255 to 255. A positive value indicates forward motion.
+ *
+ * @param omega the rotational velocity of the robot, in the range
+ * -255 to 255. A positive value indicates a counterclockwise velocity.
+ *
+ * @param strength the strength of the avoid behavior, in the range
+ * 0 to 100.
+ *
+ * @see motors_init, range_init, move
+ **/
+void move_avoid(int velocity, int omega, int strength) {
+  int pControl;
+  int vl = 0;
+  int vr = 0;
+  int temp;
+  
+  temp=range_read_distance(IR1);
+  d1 = (temp == -1) ? d1 : temp;
+  
+  temp=range_read_distance(IR2);
+  d2=(temp == -1) ? d2 : temp;
+  
+  temp=range_read_distance(IR3);
+  d3=(temp == -1) ? d3 : temp;
+  
+  temp=range_read_distance(IR4);
+  d4=(temp == -1) ? d4 : temp;
+  
+  temp=range_read_distance(IR5);
+  d5=(temp == -1) ? d5 : temp;
+  
+  /* Avoid obstacles ahead
+     if(d2>170)
+     v*=-1;
+    
+     Naturally slow down if there is something in the way.
+     if(d2>150 || d1>180 || d3>180){
+     v>>=1;
+  */
+  
+  //pControl= (((d3-d1) + (d4-d5))*strength)/100;
+  pControl= (((d5-d4))*strength)/100;
+  omega = (omega*(100-strength))/100 + pControl;
+  translateAngulartoLinear(velocity, omega, &vl , &vr );
+  
+  if (vl < 0) {
+    motor1_set(BACKWARD, -vl);
+  } else {
+    motor1_set(FORWARD, vl);
+  }
+  if (vr < 0) {
+    motor2_set(BACKWARD, -vr);
+  } else {
+    motor2_set(FORWARD, vr);
+  }
+}
+
+/**@}**///end the motion group
+
+void translateAngulartoLinear (int velocity, int omega, int* vl, int* vr) {
+  //omega: angle measure, positive couter-clockwise from front.
+  // -180 <= omega <= 180
+  //velocity: -255 <= velocity <= 255
+  
+  long int vltemp, vrtemp;
+  
+  //make sure values are in bounds
+  if (velocity < -255 || velocity >255 || omega < -255 || omega > 255) return;
+	
+  //compute
+  vrtemp = velocity + omega * 3;
+  vltemp = velocity - omega * 3;
+	
+  //check to see if max linear velocities have been exceeded.
+  if (vrtemp > 255) {
+    vltemp = 255 * vltemp / vrtemp;
+    vrtemp = 255;
+  }
+  if (vltemp > 255) {	   
+    vrtemp = 255 * vrtemp / vltemp;    
+    vltemp = 255;  
+  }
+  if (vrtemp < -255) {
+    vltemp = -255 * vltemp / vrtemp;
+    vrtemp = -255;
+  }
+  if (vltemp < -255) {
+    vrtemp = -255 * vrtemp / vltemp;
+    vltemp = -255;
+  }
+  
+  *vr = (int)vrtemp;
+  *vl = (int)vltemp;
+}
Index: branches/wireless/code/projects/libdragonfly/dio.c
===================================================================
--- branches/wireless/code/projects/libdragonfly/dio.c	(nonexistent)
+++ branches/wireless/code/projects/libdragonfly/dio.c	(revision 1493)
@@ -0,0 +1,318 @@
+/**
+ * Copyright (c) 2007 Colony Project
+ * 
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ * 
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ **/
+
+
+/**
+ * @file dio.c
+ * @brief Digital Input and Output
+ *
+ * Implementation of functions for digital input and output.
+ *
+ * @author Colony Project, CMU Robotics Club
+ **/
+
+#include <avr/interrupt.h>
+#include "dio.h"
+#include "time.h"
+#include "lights.h"
+
+/**
+ * @defgroup dio Digital Input / Output
+ * @brief Controls digital input and output
+ * 
+ * A general note on how port / pin numbers work:<br>
+ * The portpin is used to select both the bank and which pin is selected.
+ * 6 bits are used (lower 6, ex: 0b00abcdef).
+ * The first 3 (abc in this example) are used to select the bank.<br>
+ * A = 001<br>
+ * B = 010<br>
+ * C = 011<br>
+ * D = 100<br>
+ * E = 101<br>
+ * F = 110<br>
+ * G = 111<br><br>
+ * 		
+ * The bank can be found by doing portpin >> 3. <br>
+ * 		
+ * The next three (def in this example) are used to select the pin number.
+ * These three bits are just the binary representation of the pin number.<br>
+ * <br>
+ * The pin number can be found by doing portpin & 0b111.<br><br>
+ *
+ * Include dio.h to access these functions.
+ **/
+
+/**
+ * Reads the selected portpin.
+ * 
+ * @param portpin The portpin to be read. See the general description
+ * for a description of portpins.
+ *
+ * @return 1 or 0, depending on the value of the portpin.
+ **/
+int digital_input(int portpin) {
+  int pin = portpin & 0x7;
+  int pin_val = 0;
+  
+  switch(portpin >> 3) {
+  case _PORT_A:
+    DDRA &= ~_BV(pin);
+    pin_val = PINA;
+    return (pin_val >> pin) & 1;
+  case _PORT_B:
+    DDRB &= ~_BV(pin);
+    pin_val = PINB;
+    return (pin_val >> pin) & 1;
+  case _PORT_C:
+    DDRC &= ~_BV(pin);
+    pin_val = PINC;
+    return (pin_val >> pin) & 1;
+  case _PORT_D:
+    DDRD &= ~_BV(pin);
+    pin_val = PIND;
+    return (pin_val >> pin) & 1;
+  case _PORT_E:
+    DDRE &= ~_BV(pin);
+    pin_val = PINE;
+    return (pin_val >> pin) & 1;
+  case _PORT_F:
+    if(pin>=4) {
+      MCUSR|=1<<7;
+      MCUSR|=1<<7;
+    }
+    DDRF &= ~_BV(pin);
+    pin_val = PINF;
+    return (pin_val >> pin) & 1;
+  case _PORT_G:
+    DDRG &= ~_BV(pin);
+    pin_val = PING;
+    return (pin_val >> pin) & 1;
+  default: break;
+  }
+  
+  return -1;
+}
+
+/**
+ * Enables pullup on a pin. If it is an output pin, the pin will output
+ * 1.
+ *
+ * @param portpin the pin to enable pullup on. See the general description
+ * for a discussion of portpins.
+ **/
+void digital_pull_up(int portpin) {
+  int pins = portpin & 0x07;
+
+  switch(portpin >> 3) {
+  case _PORT_A:
+    PORTA |= _BV(pins);
+    break;
+  case _PORT_B:
+    PORTB |= _BV(pins);
+    break;    
+  case _PORT_C:
+    PORTC |= _BV(pins);
+    break;    
+  case _PORT_D:
+    PORTD |= _BV(pins);
+    break;    
+  case _PORT_E:
+    PORTE |= _BV(pins);
+    break;    
+  case _PORT_F:
+    PORTF |= _BV(pins);
+    break;    
+  case _PORT_G:
+    PORTG |= _BV(pins);
+    break;
+  }
+}
+
+/**
+ * Sets portpin to the given value.
+ * 
+ * @param portpin the portpin to output to. See the general
+ * description for a discussion of portpins.
+ *
+ * @param val the value to set the portpin to. 0 for off,
+ * nonzero for on.
+ **/
+void digital_output(int portpin, int val) {
+  int pins = portpin & 0x07;
+  
+  /* if you want to set to 0... */
+  if(val == 0) {
+    switch(portpin >> 3) {
+    case _PORT_A:
+      DDRA |= _BV(pins);
+      PORTA &= (0XFF - _BV(pins));
+      break;
+    case _PORT_B:
+      DDRB |= _BV(pins);
+      PORTB &= (0XFF - _BV(pins));
+      break;    
+    case _PORT_C:
+      DDRC |= _BV(pins);
+      PORTC &= (0XFF - _BV(pins));
+      break;    
+    case _PORT_D:
+      DDRD |= _BV(pins);
+      PORTD &= (0XFF - _BV(pins));
+      break;    
+    case _PORT_E:
+      DDRE |= _BV(pins);
+      PORTE &= (0XFF - _BV(pins));
+      break;    
+    case _PORT_F:
+      DDRF |= _BV(pins);
+      PORTF &= (0XFF - _BV(pins));
+      break;    
+    case _PORT_G:
+      DDRG |= _BV(pins);
+      PORTG &= (0XFF - _BV(pins));
+      break;
+    }
+  } else { /* ( val == 1) */ 
+    switch(portpin >> 3) {
+    case _PORT_A:
+      DDRA |= _BV(pins);
+      PORTA |= _BV(pins);
+      break;
+    case _PORT_B:
+      DDRB |= _BV(pins);
+      PORTB |= _BV(pins);
+      break;    
+    case _PORT_C:
+      DDRC |= _BV(pins);
+      PORTC |= _BV(pins);
+      break;    
+    case _PORT_D:
+      DDRD |= _BV(pins);
+      PORTD |= _BV(pins);
+      break;    
+    case _PORT_E:
+      DDRE |= _BV(pins);
+      PORTE |= _BV(pins);
+      break;    
+    case _PORT_F:
+      DDRF |= _BV(pins);
+      PORTF |= _BV(pins);
+      break;    
+    case _PORT_G:
+      DDRG |= _BV(pins);
+      PORTG |= _BV(pins);
+      break;
+    }
+  }
+}
+
+/**
+ * Checks if button1 is currently pressed.
+ * 
+ * @return 1 if button1 is pressed, 0 otherwise
+ *
+ * @see button1_wait, button1_click
+ **/
+int button1_read( void ) {
+  int pin_val;
+  DDRG &= ~_BV(PING0);
+  PORTG|= _BV(PING0);
+  pin_val = PING;
+  return !((pin_val & _BV(PING0)));
+}
+
+/**
+ * Delays execution until button1 is pressed.
+ *
+ * @see button1_read, button1_click
+ **/
+void button1_wait( void ) {
+  while(!button1_read() ) {
+    delay_ms(15);
+  }
+}
+
+/**
+ * If button1 is pressed, waits until it is released before returning.
+ * Otherwise, the function returns immediately.
+ *
+ * @return 1 if button1 has been pressed, 0 otherwise
+ *
+ * @see button1_read, button1_wait
+ **/
+int button1_click() {
+  if(button1_read()) {
+    while(button1_read());
+    return 1;
+  } else {
+    return 0;
+  }
+}
+
+/**
+ * Checks if button2 is currently pressed.
+ * 
+ * @return 1 if button2 is pressed, 0 otherwise
+ *
+ * @see button2_wait, button2_click
+ **/
+int button2_read( void ) {
+  int pin_val;
+  DDRG &= ~_BV(PING1);
+  PORTG|= _BV(PING1);
+  pin_val = PING;
+  return !((pin_val & _BV(PING1)));
+}
+
+/**
+ * Delays execution until button2 is pressed.
+ *
+ * @see button2_read, button2_click
+ **/
+void button2_wait( void ) {
+  while(!button2_read()){
+    delay_ms(15);
+  }
+}
+
+/**
+ * If button2 is pressed, waits until it is released before returning.
+ * Otherwise, the function returns immediately.
+ *
+ * @return 1 if button2 has been pressed, 0 otherwise
+ *
+ * @see button2_read, button2_wait
+ **/
+int button2_click() {
+  if(button2_read()) {
+    while(button2_read());
+    return 1;
+  } else {
+    return 0;
+  }
+}
+
+/** @} **/ //end defgroup
+
Index: branches/wireless/code/projects/libdragonfly/reset.c
===================================================================
--- branches/wireless/code/projects/libdragonfly/reset.c	(nonexistent)
+++ branches/wireless/code/projects/libdragonfly/reset.c	(revision 1493)
@@ -0,0 +1,60 @@
+/**
+ * Copyright (c) 2007 Colony Project
+ * 
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ * 
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ **/
+
+
+/**
+ * @file reset
+ * @brief Reset the Robot
+ *
+ * Implementation of a function to reset the robot.
+ *
+ * @author Colony Project, CMU Robotics Club
+ **/
+#include <avr/interrupt.h>
+#include <util/delay.h>
+#include "reset.h"
+
+/**
+ * @defgroup reset Reset
+ * Functions for manipulation the ADC on the dragonfly board.
+ * All definitions may be found in analog.h.
+ *
+ * @{
+ **/
+
+/**
+ * Resets the AVR when called.  Sets the watchdog timer and lets it overflow
+ * to reset the AVR.  The reset clears all memory and resets all registers
+ * with the exception of the Watchdog Reset Flag (WDRF) in the MCU Control
+ * and Status Register (MCUCSR).
+ **/
+void reset(void) {
+  WDTCR &= 0xF8;
+  WDTCR |= 0x08;
+  _delay_ms(15);
+}
+
+/**@}**/ //end defgroup
+
Index: branches/wireless/code/projects/libdragonfly/lights.c
===================================================================
--- branches/wireless/code/projects/libdragonfly/lights.c	(nonexistent)
+++ branches/wireless/code/projects/libdragonfly/lights.c	(revision 1493)
@@ -0,0 +1,752 @@
+/**
+ * Copyright (c) 2007 Colony Project
+ * 
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ * 
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ **/
+
+/**
+ * @file ligths.c
+ * @brief Orbs
+ *
+ * Implemenation for the orbs (tri-colored LEDs)
+ *
+ * @author Colony Project, CMU Robotics Club
+ * @bug Unfinished
+ **/
+
+/*
+lights.c
+Controls orb1 and orb2. Can be extended for a software PWM that may be used for servos in the future (although maybe
+using a different timer might be preferable).
+
+author: CMU Robotics Club, Colony Project
+
+Change Log:
+3/31/2009 - Martin
+    Rewritten from scratch. Fixes code duplication, long ISRs, bugs, unnecessary synchronized code, memory waste
+*/
+
+
+
+/*
+ * Test cases:
+ *   - The following code has to work without flickering:
+ *     orb_init_pwm(); while(1) { orbs_set(1,1,1,254,254,254); }
+ */
+
+/*
+ * Possible optimizations:
+ *   - Use pointers instead of indicies for current_pwm_channel
+ *   - Optimize output_compare()
+ *   - Use a different sorting algorithm (see sort_orbs_buffer for further comments on this issue)
+ *   - Use pointers in fill_orbs_buffer
+ *   - Optimized orb_set (use the knowledge that there are only 3 distinct values, don't use a loop but unroll the
+ *     sorting, which is no problem for 3 values)
+ *   - Use a lower update frequency. The next higher prescaler value leads to a frequency of 30Hz which is too low (the
+ *     orbs are flickering). So the timer would have to be reloaded manually after 127 to generate 60Hz. This would
+ *     decrease the resolution from 8 to 7 bit, but 128 steps should still be enough.
+ *   - On setting the orbs, combine channels with the same time. This would reduce the all-values-equal OC interrupt
+ *     (30us) to the time of one regular OC interrupt (6us/10us). Also, it would reduce the total cpu usage whenever
+ *     some of the values are equal.
+ *
+ * When code is changed, the performance measurements above should be redone.
+ */
+
+#include "dragonfly_lib.h"
+#include "lights.h"
+
+// ***************
+// ** Constants **
+// ***************
+
+#define NUM_ORBS 2   // Number or orbs
+#define NUM_COLORS 3 // Number of colors per orb
+#define num_pwm_channels NUM_ORBS*NUM_COLORS
+
+
+// *********
+// ** I/O **
+// *********
+
+// Orb port
+#define ORBPORT PORTC
+#define ORBDDR  DDRC
+
+// Orb pins
+#define ORB1_RED   0
+#define ORB1_GREEN 1
+#define ORB1_BLUE  2
+#define ORB2_RED   4
+#define ORB2_GREEN 5
+#define ORB2_BLUE  6
+
+
+// ***************
+// ** Debugging **
+// ***************
+
+//#define LIGHTS_DEBUG
+#undef LIGHTS_DEBUG
+
+#define LIGHTS_DEBUG_INIT                             DDRF=6;
+#define LIGHTS_DEBUG_OVERFLOW_INTERRUPT_START         PORTF|=4;
+#define LIGHTS_DEBUG_OVERFLOW_INTERRUPT_END           PORTF&=~4;
+#define LIGHTS_DEBUG_OUTPUT_COMPARE_INTERRUPT_START   PORTF|=2;
+#define LIGHTS_DEBUG_OUTPUT_COMPARE_INTERRUPT_END     PORTF&=~2;
+#define LIGHTS_DEBUG_APPLY_START                      //PORTF|=2;
+#define LIGHTS_DEBUG_APPLY_END                        //PORTF&=~2;
+
+
+// ***********
+// ** Masks **
+// ***********
+
+// Some useful bit masks. All of them are are calculated from the I/O definitions above. The calculations should be done
+// at compile time (even if they are not, they are only executed once at startup).
+
+// Masks for the individual LEDs
+#define orb1_red_mask    _BV (ORB1_RED  )
+#define orb1_green_mask  _BV (ORB1_GREEN)
+#define orb1_blue_mask   _BV (ORB1_BLUE )
+#define orb2_red_mask    _BV (ORB2_RED  )
+#define orb2_green_mask  _BV (ORB2_GREEN)
+#define orb2_blue_mask   _BV (ORB2_BLUE )
+
+// Mask for all LEDs
+#define all_orbs_mask \
+    orb1_red_mask | orb1_green_mask | orb1_blue_mask | \
+    orb2_red_mask | orb2_green_mask | orb2_blue_mask;
+
+// Mask for the individual LEDs, organized as an array for programmatic access. The layout of this array is
+// orb_mask[orb_num, color_num]
+const uint8_t orb_mask[NUM_ORBS][NUM_COLORS]={
+    { orb1_red_mask, orb1_green_mask, orb1_blue_mask },
+    { orb2_red_mask, orb2_green_mask, orb2_blue_mask }
+};
+
+// ***********
+// ** Types **
+// ***********
+
+struct pwm_channel_t { // 2 bytes
+    uint8_t time;
+    uint8_t mask;
+};
+
+struct pwm_t { // 13 bytes
+    uint8_t init_mask;
+    struct pwm_channel_t channel[num_pwm_channels];
+};
+
+
+// ***************
+// ** Variables **
+// ***************
+
+// Whether to use PWM (true) or binary (false) orb mode. Not volatile because it's only read once per function.
+bool enable_orb_pwm=true;
+
+// The PWM channels and the buffer pointers. This data structure is triple buffered, see above for the reasons. Not
+// volatile because they are not modified asynchronously (the read buffer is never written to asynchronously).
+struct pwm_t pwm_buffer[3];
+
+// The front buffer the ISR reads from. Other threads may not touch this pointer or the buffer it points to. Not
+// volatile because it may only be modified by the ISR.
+struct pwm_t *pwm_read_buffer =&pwm_buffer[0];
+
+// The back buffer we can write to. The ISR may not touch this pointer or the buffer it points to. Not volatile because
+// it may only be modified by the caller.
+struct pwm_t *pwm_write_buffer=&pwm_buffer[1]; 
+
+// The middle buffer to flip the write or read buffer with. Not volatile because it is only read once per function.
+struct pwm_t *pwm_free_buffer =&pwm_buffer[2]; 
+
+// Whether to perform a page flip on the beginning of the next PWM cycle. Not volatile because it is only read once
+// per function.
+bool pwm_page_flip=false; // Whether to do a page flip on the next overflow
+
+// The orb value array. Orb values are written here to be sorted into pwm_channels. Not volatile because all accesses
+// are from guarded (thread safe) functions.
+uint8_t orb_values[NUM_ORBS][NUM_COLORS];
+
+
+// ****************
+// ** Timer ISRs **
+// ****************
+
+// Not volatile because it is only accessed in the interrupt handler.
+uint8_t current_pwm_channel=0;
+
+
+static void output_compare (void) {
+	// This function is called when an output compare condition may have occured.
+	
+    // If the OC interrupt is executed without delay, TCNT0==time+1 (where time==OCR0), because the interrupt flag is
+	// queued at the next timer clock cycle after an output compare.
+
+    // What may happen here is that the interrupt is delayed for more than one timer clock cycle (33 us). In that case,
+	// the timer has already counted on and TCNT0 is bigger than current_channel_timer. Also, while during the ISR no
+	// other interrupts will occur, the timer may still count on. Thus, we have to check the following channel as well.
+
+	// Some optimization is possible in this function.
+
+    while (1) {
+		// The timer value at which the output compare interrupt should occur (one timer clock cycle after the output
+		// compare condition is detected).
+		uint8_t current_channel_time=pwm_read_buffer->channel[current_pwm_channel].time+1;
+		
+		// If the counter is not at this time yet, we don't have to do anything right now.
+		if (current_channel_time>TCNT0) return;
+		
+		// We have an output compare condition for the current channel.
+		
+        // Turn the current channel off
+        ORBPORT|=pwm_read_buffer->channel[current_pwm_channel].mask;
+
+		// If this was the last channel, exit
+		if (current_pwm_channel==num_pwm_channels-1) return;
+
+        // Increment the channel index
+        current_pwm_channel++;
+
+        // There is a next channel, load its OCR value
+        if (pwm_read_buffer->channel[current_pwm_channel].time<255)
+            OCR0=pwm_read_buffer->channel[current_pwm_channel].time;
+    }
+}
+
+SIGNAL (SIG_OVERFLOW0) {
+#ifdef LIGHTS_DEBUG
+    LIGHTS_DEBUG_OVERFLOW_INTERRUPT_START
+#endif
+
+    if (pwm_page_flip) {
+        // Flip the read buffer with the free buffer. We are in an ISR (and we didn't re-enable interrupts), so we don't
+        // have to synchronize explicitly.
+        struct pwm_t *temp = pwm_read_buffer;
+        pwm_read_buffer    = pwm_free_buffer;
+        pwm_free_buffer    = temp;
+        pwm_page_flip=false;
+    }
+
+    // Turn only the appropriate PWM channels on. Do this directly on the orb port because at this point all orbs should
+    // be off anyway.
+    ORBPORT|=all_orbs_mask;
+    ORBPORT&=pwm_read_buffer->init_mask;
+    
+    // Start at the first channel
+    current_pwm_channel=0;
+    
+    // Load the first OCR
+    OCR0=pwm_read_buffer->channel[current_pwm_channel].time;
+
+	// If this interrupt was delayed, we might already have an output compare condition.
+	output_compare ();
+
+#ifdef LIGHTS_DEBUG
+    LIGHTS_DEBUG_OVERFLOW_INTERRUPT_END
+#endif
+}
+
+SIGNAL(SIG_OUTPUT_COMPARE0) {
+#ifdef LIGHTS_DEBUG
+    LIGHTS_DEBUG_OUTPUT_COMPARE_INTERRUPT_START
+#endif
+
+	// We have an output compare condition.
+	output_compare ();
+    
+#ifdef LIGHTS_DEBUG
+    LIGHTS_DEBUG_OUTPUT_COMPARE_INTERRUPT_END
+#endif
+}
+
+
+
+// ************************************
+// ** Internal orb setting functions **
+// ************************************
+
+static void sort_orbs_buffer (void) {
+    // This function applies a bubble sort to sort the elements of the pwm_write_buffer->channel array by the time
+    // field.
+    // This implementation is heavily optimized. Note that due to the low (and constant) number of elements to be
+    // sorted, the runtime complexity (O(n^2) for bubble sort) is not relevant here. In fact, a more advanced algorithm
+    // like quick sort or merge sort might even be slower due to higher overhead.
+    // That said, it is possible that selection sort (which is also in O(n^2)) would be faster that bubble sort because
+    // it only has to do a maximum of (n-1) swapping steps (as opposed to n*(n-1)/2 for bubble sort). However, the check
+    // if the elements are already in the correct order would either have to be left out (doing the full search every
+    // time, even if the array is already sorted) or done explicitly, so selection sort might actually be slower than
+    // bubble sort, especially if the array is already sorted or almost sorted.
+    
+    // This implementation uses macros to make the algorithm more clear because the loop is rolled out and the function
+    // would become quite long without macros.
+    
+    // Macro to swap two values of any type. Requires a variable of the appropriate type called swap_temp.
+    #define swap(a,b) { swap_temp=a; a=b; b=swap_temp; }
+
+    // Macro to do one bubble sorting step (compare & swap)
+    #define bubble \
+        if(a->time > b->time) \
+        { \
+            swap (a->time, b->time); \
+            swap (a->mask, b->mask); \
+            done=false; \
+        }
+    
+    // Macro to move to the next bubble sort pair
+    #define next { a++; b++; }
+
+    // Whether no change was made during the last run, which means that all values are already in correct order.
+    bool done;
+    
+    // A temporary variable for swapping.
+    uint8_t swap_temp;
+    
+    // Precompute the first PWM channel (tested faster).
+    struct pwm_channel_t *first=&(pwm_write_buffer->channel[0]);
+
+    // Pointers to the two PWM channels under inspection
+    struct pwm_channel_t *a, *b;
+
+    // The actual sorting
+    a=first; b=a+1; done=true;
+    bubble next bubble next bubble next bubble next bubble
+    if (done) return;
+
+    a=first; b=a+1; done=true;
+    bubble next bubble next bubble next bubble
+    if (done) return;
+
+    a=first; b=a+1; done=true;
+    bubble next bubble next bubble
+    if (done) return;
+
+    a=first; b=a+1; done=true;
+    bubble next bubble
+    if (done) return;
+
+    a=first; b=a+1; done=true;
+    bubble
+    if (done) return;
+
+    // Undefine the macros so they do not disturb some other function.
+    #undef next
+    #undef bubble
+    #undef swap
+}
+
+static void fill_orbs_buffer (void) {
+    // We do not use a loop here because it introduces 27us overhead, which is quite much, given the total time for
+    // optimized copying and sorting of 34us (elements already in correct order) to 71 us (elements in reverse order).
+    
+    #define copy_value(orb, color) \
+        index=NUM_COLORS*orb+color; \
+        time=orb_values[orb][color]; \
+        mask=orb_mask[orb][color]; \
+        \
+        pwm_write_buffer->channel[index].time=time-1; \
+        pwm_write_buffer->channel[index].mask=mask; \
+        \
+        if (time!=0) \
+            pwm_write_buffer->init_mask &= ~mask; \
+
+    uint8_t index, time, mask;
+    copy_value(0,0); copy_value(0,1); copy_value(0,2);
+    copy_value(1,0); copy_value(1,1); copy_value(1,2);
+    
+    #undef copy_value
+}
+
+static void apply_orbs (void) {
+	/*
+	 * Some timing tests: Time for apply_orbs with interrupts disabled, in microseconds:
+     *             Values in:     Correct order      Reverse order
+     * Naive bubble sort:         148                217
+     * Aborting bubble sort:       71                232
+     * Only count to top:          73                189
+     *
+     * Loops rolled out:           61                120
+     * Using pointers:             62                 98
+     * Copy loop also rolled out:  35                 72
+	 *
+	 * Note that rolling out both loops and using pointers saves 52%/62% of time! 27us were spent on loop overhead,
+	 * which is quite much, considering an optimized total time for copying and sorting or 35us.
+	 */
+
+#ifdef LIGHTS_DEBUG
+    LIGHTS_DEBUG_APPLY_START
+#endif
+
+    if (enable_orb_pwm) {
+        // PWM mode
+        
+        pwm_write_buffer->init_mask=~0;
+    
+        // 1. Write the orb values and corresponding masks to the pwm channels
+        // array unsorted.
+        fill_orbs_buffer ();
+
+        // 2. sort the buffer.
+        sort_orbs_buffer ();
+
+        // Flip the write buffer with the free buffer.
+        SYNC {
+            struct pwm_t *temp = pwm_write_buffer;
+            pwm_write_buffer   = pwm_free_buffer;
+            pwm_free_buffer    = temp;
+        }
+        
+        // On the next overflow, flip the read buffer with the free buffer.
+        pwm_page_flip=true;
+    }
+    else {
+        // Binary mode.
+        // The outputs are inverted.
+        uint8_t on=0;
+        
+        if (orb_values[0][0]) on |= orb_mask[0][0];
+        if (orb_values[0][1]) on |= orb_mask[0][1];
+        if (orb_values[0][2]) on |= orb_mask[0][2];
+        if (orb_values[1][0]) on |= orb_mask[1][0];
+        if (orb_values[1][1]) on |= orb_mask[1][1];
+        if (orb_values[1][2]) on |= orb_mask[1][2];
+    
+        // Write the new orb states to the output port. Synchronized because it is a RMW operation.
+        SYNC {
+            uint8_t value=ORBPORT;
+            value |= all_orbs_mask; // All orbs off
+            value &= ~on; // Selected orbs on
+            ORBPORT=value;
+        }
+    }
+            
+#ifdef LIGHTS_DEBUG
+    LIGHTS_DEBUG_APPLY_END
+#endif
+}
+
+static void set_orb_values (uint8_t num, uint8_t red, uint8_t green, uint8_t blue) {
+    // Write the values to the array, but do not sort them yet, as we might want to write the other orb values first so
+    // we don't have to sort twice.
+    // Any function calling this function will probably want to call apply_orbs() afterwards.
+    orb_values[num][0]=red;
+    orb_values[num][1]=green;
+    orb_values[num][2]=blue;
+}
+
+
+// ***********************
+// ** RGB color setting **
+// ***********************
+
+// All of these functions use set_orb_values to set the actual values, and then call apply_orbs() to apply the changes.
+// set_orb_values should be used (even though it would be faster to set the array directly) because the binary/pwm mode
+// has to be handled.
+// All of these functions must be 
+
+uint8_t orb_lock=0;
+
+/**
+ * Sets the specified orb to the specified color. The orbs must be initialized before this function may be used.
+ * Note that, when setting both orbs, using orbs_set is faster then setting the orbs individually because the values are
+ * only sorted once.
+ *
+ * @param num the number of the orb to set (0 or 1)
+ * @param red the red value for the specified orb
+ * @param green the green value for the specified orb
+ * @param blue the blue value for the specified orb
+ * @see 
+ */
+void orb_n_set (uint8_t num, uint8_t red, uint8_t green, uint8_t blue) {
+	REQUIRE_LOCK_OR_RETURN(orb_lock);
+	
+    set_orb_values (num, red, green, blue);
+    apply_orbs ();
+	
+	RELEASE_LOCK(orb_lock);
+}
+
+/**
+ * Set orb1 to the color specified. The orbs must be initialized before this function may be used. Note that, when
+ * setting both orbs, using orbs_set is faster then setting the orbs individually because the values are only sorted
+ * once.
+ *
+ * @param red the red component of the color
+ * @param green the green component of the color
+ * @param blue the blue component of the color
+ *
+ * @see orb_init
+ **/
+void orb1_set (uint8_t red, uint8_t green, uint8_t blue) {
+	REQUIRE_LOCK_OR_RETURN(orb_lock);
+	
+    set_orb_values (0, red, green, blue);
+    apply_orbs ();
+
+	RELEASE_LOCK(orb_lock);
+}
+
+/**
+ * Set orb2 to the color specified. The orbs must be initialized before this function may be used. Note that, when
+ * setting both orbs, using orbs_set is faster then setting the orbs individually because the values are only sorted
+ * once.
+ *
+ * @param red_led the red component of the color
+ * @param green_led the green component of the color
+ * @param blue_led the blue component of the color
+ *
+ * @see orb_init
+ **/
+void orb2_set (uint8_t red, uint8_t green, uint8_t blue) {
+	REQUIRE_LOCK_OR_RETURN(orb_lock);
+	
+    set_orb_values (1, red, green, blue);
+    apply_orbs ();
+
+	RELEASE_LOCK(orb_lock);
+}
+
+/**
+ * Set both orbs to the color specified. The orbs must be initialized before this function may be used.
+ *
+ * @param red_led the red component of the color
+ * @param green_led the green component of the color
+ * @param blue_led the blue component of the color
+ *
+ * @see orb_init, orb1_set, orb2_set
+ **/
+void orb_set (uint8_t red, uint8_t green, uint8_t blue) {
+	REQUIRE_LOCK_OR_RETURN(orb_lock);
+	
+    set_orb_values (0, red, green, blue);
+    set_orb_values (1, red, green, blue);
+    apply_orbs ();
+
+	RELEASE_LOCK(orb_lock);
+}
+
+/**
+ * Set the orbs to the respective values. The orbs must be initialized before this function may be used. Note that, when
+ * setting both orbs, this function is faster than calling orb1_set and orb2_set (or orb_n_set) because the values are
+ * only sorted once.
+ *
+ * @param red1
+ * @param green1
+ * @param blue1
+ * @param red2
+ * @param green2
+ * @param blue2
+ * @see orb1_set
+ * @see orb2_set
+ * @see orb_n_set
+ **/
+void orbs_set (
+    uint8_t red1, uint8_t green1, uint8_t blue1,
+    uint8_t red2, uint8_t green2, uint8_t blue2) {
+
+	REQUIRE_LOCK_OR_RETURN(orb_lock);
+
+    set_orb_values (0, red1, green1, blue1);
+    set_orb_values (1, red2, green2, blue2);
+    apply_orbs ();
+
+	RELEASE_LOCK(orb_lock);
+}
+
+
+// ******************************
+// ** Predefined color setting **
+// ******************************
+
+// This functions just call the corresponding orb*_set functions. If the orbs array is accessed in any other way, it
+// must be synchronized on orb_lock (REQUIRE_LOCK_OR_RETURN and RELEASE_LOCK)! Note that one synchronized function
+// cannot call another one with this lock implementation.
+
+// Macros for extracting a color.
+#define C_RED(col)   (((col & 0xE0) >> 5) * 36)
+#define C_GREEN(col) (((col & 0x1C) >> 2) * 36)
+#define C_BLUE(col)  (((col & 0x03)     ) * 85)
+
+/**
+ * Set the specified orb to the specified color. This function is intended to be used with the predefined colors.
+ *
+ * @param num the number of the orb to set (0 or 1)
+ * @param col the color to set the orbs to
+ **/
+void orb_n_set_color(uint8_t num, uint8_t col) {
+    orb_n_set(num, C_RED(col), C_GREEN(col), C_BLUE(col));
+}
+
+/**
+ * Set orb1 to the specified color. This function is intended to be used with the predefined colors.
+ *
+ * @param col the color to set the orbs to
+ **/
+void orb1_set_color(uint8_t col) {
+    orb1_set (C_RED(col), C_GREEN(col), C_BLUE(col));
+}
+
+/**
+ * Set orb2 to the specified color. This function is intended to be used with the predefined colors.
+ *
+ * @param col the color to set the orbs to
+ **/
+void orb2_set_color(uint8_t col) {
+    orb2_set(C_RED(col), C_GREEN(col), C_BLUE(col));
+}
+
+/**
+ * Set both orbs to the specified color. This function is intended to be used with the predefined colors.
+ *
+ * @param col the color to set the orbs to
+ **/
+void orb_set_color(uint8_t col) {
+    orb_set (C_RED(col), C_GREEN(col), C_BLUE(col));
+}
+
+/**
+ * Set the orbs to the respective color. This function is intended to be used with the predefined colors.
+ *
+ * @param col1 the color to set orb 1 to
+ * @param col2 the color to set orb 2 to
+ **/
+void orbs_set_color(uint8_t col1, uint8_t col2) {
+    orbs_set (C_RED(col1), C_GREEN(col1), C_BLUE(col1), C_RED(col2), C_GREEN(col2), C_BLUE(col2));
+}
+
+#undef C_BLUE
+#undef C_GREEN
+#undef C_RED2
+
+
+// ******************
+// ** Mode setting **
+// ******************
+
+/**
+ * Enables the orb timer. Note that you usually don't want to use this function directly. Instead, use orb_set_mode.
+ * @see orb_set_mode
+ **/
+void orb_enable_timer (void) {
+    // Use 8 bit TC0.
+    //
+    // Timer mode: We cannot use CTC mode because it can only clear on OCR0 (in contrast to the 16 bit timers which can
+    // also use the ICR for that) and OCR0 is already used for generating output compare interrupts. We also need
+    // immediate (non double buffered) update of OCR0, so the only mode left is "Normal".
+    //
+    // Note that for a timer counting from 0 to 255, there are 256 states and thus 257 output possibilities
+    // (0/256...256/256)! However, there are only 256 values in the byte used to specify the PWM value. Possible ways
+    // to deal with that:
+    //   1. use a 16 bit variable for the PWM value (memory waste, overhead)
+    //   2. use an additional flag for the 257th value (inconvenient)
+    //   3. use 1/256...256/256 (skip 0, never complete off)
+    //   4. use 0/256...256/256 (skip 256, never complete on)
+    //   5. skip a value somewhere in the middle
+    //   6. reload the timer after 254
+    // For this implementation, variant 4 was chosen.
+    //
+    // Using an 8 bit timer has the added advantage that all the comparisons are faster.
+    
+    // Normal mode, Compare match output off, Prescaler
+    TCCR0=_BV(CS02) | _BV(CS01); // 256, 120 Hz
+	// The next higher prescaler would be 1024 (30 Hz) which makes the orbs flicker visibly.
+
+    // Enable the interrupts
+    TIMSK|= _BV(OCIE0) | _BV(TOIE0);
+}
+
+/**
+ * Disables the orb timer. Note that you usually don't want to use this function directly. Instead, use orb_set_mode.
+ * @see orb_set_mode
+ **/
+void orb_disable_timer (void) {
+    // Disable the interrupts
+    TIMSK&=~( _BV(OCIE0) | _BV(TOIE0));
+}
+
+
+void orb_set_mode (orb_mode_t mode) {
+    // Set enable_orb_pwm to the appropriate value and disable or enable the timer.
+    if (mode==orb_mode_binary) {
+        orb_disable_timer ();
+
+        enable_orb_pwm=false;
+        apply_orbs ();
+    }
+    else { // orb_mode_pwm
+        enable_orb_pwm=true;
+        apply_orbs ();
+
+        orb_enable_timer ();
+    }
+}
+
+
+// ********************
+// ** Initialization **
+// ********************
+
+// Orb initialization code common to all modes.
+static void orb_init_common (void) {
+    // Enable the output ports and turn off the LEDs
+    ORBPORT |=  all_orbs_mask;
+    ORBDDR  |=  all_orbs_mask;
+
+    // Set all orbs to "off"
+    orb_set (0, 0, 0);
+    
+#ifdef LIGHTS_DEBUG
+    LIGHTS_DEBUG_INIT
+#endif
+}
+
+/**
+ * Initializes the orbs in PWM mode. One of the orb_init* functions must be called before the orbs can be used.
+ * 
+ * @see orb_init_pwm
+ **/
+void orb_init_binary (void) {
+    orb_init_common ();
+    orb_set_mode (orb_mode_binary);
+}
+
+/**
+ * Initializes the orbs in PWM mode. One of the orb_init* functions must be called before the orbs can be used.
+ * 
+ * @see orb_init_binary
+ **/
+void orb_init_pwm (void) {
+    orb_init_common ();
+    orb_set_mode (orb_mode_pwm);
+}
+
+/**
+ * Initializes the orbs in default mode. One of the orb_init* functions must be called before the orbs can be used. Use
+ * the orb_init_binary or orb_init_pwm function if you want one specific mode.
+ *
+ * @see orb_init_pwm
+ * @see orb_init_binary
+ **/
+void orb_init () {
+    orb_init_pwm ();
+}
Index: branches/wireless/code/projects/libdragonfly/lights.h
===================================================================
--- branches/wireless/code/projects/libdragonfly/lights.h	(nonexistent)
+++ branches/wireless/code/projects/libdragonfly/lights.h	(revision 1493)
@@ -0,0 +1,224 @@
+// FIXME remove
+typedef unsigned char uint8_t;
+
+
+/**
+ * Copyright (c) 2007 Colony Project
+ * 
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ * 
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ **/
+
+
+/**
+ * @file lights.h
+ * @brief Contains declarations for managing the orbs.
+ *
+ * Contains declarations for using the orbs and PWM.
+ *
+ * @author Colony Project, CMU Robotics Club
+ * Based on Firefly Library, by Tom Lauwers and Steven Shamlian
+ **/
+
+#ifndef _LIGHTS_H_
+#define _LIGHTS_H_
+
+/**
+ * @addtogroup orbs
+ * @{
+ **/
+
+/**
+ * Quick start: call orb_init_pwm or orb_init_binary, depending on which mode you want to use. Call orb*set or
+ * orb*set_color to set the orbs.
+ * 
+ * The orbs have two modes of operation: PWM mode and binary mode. In PWM mode, a pwm signal is generated by a hardware
+ * timer and the orbs can be set to a value of 0 through 255. In binary mode, the orbs can only be turned on or off and
+ * a value of 0 means "off" and any other value means "on". The mode can be chosen on initialization and can be changed
+ * at runtime using the orb_set_mode function.
+ *
+ * Operation (PWM mode): On timer overflow, all LEDs with a value>0 are turned on and the output compare value for the
+ * first LED is loaded. On compare match, the corresponding LED is turned off and the next output compare value is
+ * loaded. All masks are precomputed and sorted by time when setting the values.
+ *
+ * The data structure (pwm_t) containing the PWM times and masks is triple buffered. This is because the buffer the ISR
+ * is reading from may only be modified on timer overflow before the next PWM sequence is started, because otherwise the
+ * next OCR value might be sed to a value smaller than the current timer value, resulting in the remaining channels not
+ * being turned off in that PWM period (flash to on). When using two buffers, the page flip can only occur on a timer
+ * overflow for the same reason. So after writing a buffer and marking it for page flip, neither of the buffers could be
+ * modified because the front buffer is read by the ISR and the back buffer could be switched at any time. So the
+ * calling thread would have to be delayed by up to one full PWM period (8ms in the current implementation, but
+ * 20ms-50ms would be a reasonable value to expect here). To avoid this, triple buffering is used.
+ *
+ * The code for applying the orbs is fairly optimized. See the apply_orbs function for some time measurements and
+ * further nodes.
+ *
+ * The PWM frequency is 120Hz (8ms period time). The next lower frequency (determined by the prescaler) is 30 Hz which
+ * is too slow (orbs flicker).
+ *
+ * The orbs code is thread safe, which means that the functions may be called from another interrupt handler. If there
+ * are multiple concurrent calls to the orb*set* functions, one of them is ignored and the orbs are never left in an
+ * inconsistent state. For example, if the orbs are set to green by the main thread and to red by an interrupt handler,
+ * the resulting color will be either red or green, but never yellow.
+ * Thread safety is achieved by grabbing a lock at the beginning of all functions that modify the orb code and releasing
+ * the lock at the end. If the lock is already taken, the function just returns doing nothing.
+ *
+ * Some performance measurements:
+ *   - Time for setting new orb values (PWM mode):       35us-72us (depending on the degree to which the array is
+ *                                                                  already in the correct order)
+ *   - Time for setting new orb values (binary mode):        5.5us
+ *
+ *   - Interrupt time (PWM mode only):                         8us (overflow)
+ *                                                            10us (output compare)
+ *                                                             6us (last output compare)
+ *                                                            30us (output compare, all value equal)
+ *
+ *   - Maximum total interrupt time per period:               64us
+ *   - Maximum CPU usage for interrupts (PWM mode only):     <0.8%
+ *
+ *   - Maximum contiguous synchronized block:                 30us (output compare interrupt, all values equal)
+ *
+ * There are some potential optimizations left. See the source code for more information.
+ *
+ * A note on robustness: if the output compare interrupt is disabled for too long, either due to a long ISR or a long
+ * synchronized code block, the orbs will flicker to brighter values for being turned off too late. With software PWM,
+ * there's nothing at all to be done about that. The problem can be alleviated by using a lower PWM frequency, but then
+ * the orbs will start flickering all the time due to the low update frequency.
+ * Some measurements: with 100us synchronized blocks, the flickering is accepptably low. Longer synchronized blocks
+ * mean more flickering. At 1ms synchronized blocks, the flickering is quite bad, especially for low orb values. Note
+ * that orb value 0 never flickers at all because the corresponding channels are not turned on at all.
+ * Test code (note the _delay_us restrictions!)
+ *   orb_set (1,1,1); while (1) { SYNC { for (uint8_t m=0; m<10; ++m) { _delay_us(10); } } }
+ **/
+
+/** @} **/ //end addtogroup
+
+/**
+ * @addtogroup orbs
+ * @{
+ **/
+
+// ***** Predefined colors *****
+/** @brief Red **/
+#define RED       0xE0
+/** @brief Orange **/
+#define ORANGE    0xE4
+/** @brief Yellow **/
+#define YELLOW    0xE8
+/** @brief Lime **/
+#define LIME      0x68
+/** @brief Green **/
+#define GREEN     0x1C
+/** @brief Cyan **/
+#define CYAN      0x1F
+/** @brief Blue **/
+#define BLUE      0x03
+/** @brief Pink **/
+#define PINK      0xA6 
+/** @brief Purple **/
+#define PURPLE    0x41
+/** @brief Magenta **/
+#define MAGENTA   0xE3
+/** @brief White **/
+#define WHITE     0xFE
+/** @brief Turn the orb off **/
+#define ORB_OFF   0x00
+
+
+
+// ***** Initialization *****
+
+/** @brief Enables the orbs in default mode **/
+void orb_init(void);
+
+/** @brief Enables the orbs in binary mode **/
+void orb_init_binary (void);
+
+/** @brief Enables the orbs in PWM mode **/
+void orb_init_pwm (void);
+
+
+
+// ***** Mode setting *****
+
+/** Specification of the orb mode **/
+typedef uint8_t orb_mode_t;
+
+/** @brief PWM mode **/
+#define orb_mode_pwm 0
+
+/** @brief Binary mode **/
+#define orb_mode_binary 1
+
+
+/** @brief Switches the orbs to the specified mode **/
+void orb_set_mode (orb_mode_t mode);
+
+/** @brief Disables the orb timer, but does not change the mode **/
+void orb_disable_timer (void);
+
+/** @brief Enables the orb timer, but does not change the mode **/
+void orb_enable_timer (void);
+
+
+
+// ***** Setting RGB colors *****
+
+/** @brief set the specified orb to a specified color
+* 	@deprecated This function indexes from 0 instead of 1 **/
+void orb_n_set (uint8_t num, uint8_t red, uint8_t green, uint8_t blue);
+
+/** @brief Set both orbs to a specified color **/
+void orb_set(uint8_t red, uint8_t green, uint8_t blue);
+
+/** @brief Set orb1 to a specified color **/
+void orb1_set(uint8_t red_led, uint8_t green_led, uint8_t blue_led); 
+
+/** @brief Set orb2 to a specified color **/
+void orb2_set(uint8_t red_led, uint8_t green_led, uint8_t blue_led);
+
+void orbs_set (uint8_t red1, uint8_t green1, uint8_t blue1, uint8_t red2, uint8_t green2, uint8_t blue2);
+
+
+
+// ***** Settings predefined colors *****
+
+/** @brief set the specified orb to the specified color
+* 	@deprecated This function indexes from 0 instead of 1 **/
+void orb_n_set_color(uint8_t num, uint8_t col);
+
+/** @brief Set orb1 to a specified color **/
+void orb1_set_color(uint8_t col);
+
+/** @brief Set orb2 to a specified color **/
+void orb2_set_color(uint8_t col);
+
+/** @brief set the orbs to specified colors **/
+void orbs_set_color(uint8_t col1, uint8_t col2);
+
+/** @brief Set both orbs to a specified color **/
+void orb_set_color(uint8_t col);
+
+
+
+/** @} **/ //end addtogroup
+
+#endif
Index: branches/wireless/code/projects/libdragonfly/Doxyfile
===================================================================
--- branches/wireless/code/projects/libdragonfly/Doxyfile	(nonexistent)
+++ branches/wireless/code/projects/libdragonfly/Doxyfile	(revision 1493)
@@ -0,0 +1,1514 @@
+# Doxyfile 1.5.9
+
+# This file describes the settings to be used by the documentation system
+# doxygen (www.doxygen.org) for a project
+#
+# All text after a hash (#) is considered a comment and will be ignored
+# The format is:
+#       TAG = value [value, ...]
+# For lists items can also be appended using:
+#       TAG += value [value, ...]
+# Values that contain spaces should be placed between quotes (" ")
+
+#---------------------------------------------------------------------------
+# Project related configuration options
+#---------------------------------------------------------------------------
+
+# This tag specifies the encoding used for all characters in the config file 
+# that follow. The default is UTF-8 which is also the encoding used for all 
+# text before the first occurrence of this tag. Doxygen uses libiconv (or the 
+# iconv built into libc) for the transcoding. See 
+# http://www.gnu.org/software/libiconv for the list of possible encodings.
+
+DOXYFILE_ENCODING      = UTF-8
+
+# The PROJECT_NAME tag is a single word (or a sequence of words surrounded 
+# by quotes) that should identify the project.
+
+PROJECT_NAME           = libdragonfly
+
+# The PROJECT_NUMBER tag can be used to enter a project or revision number. 
+# This could be handy for archiving the generated documentation or 
+# if some version control system is used.
+
+PROJECT_NUMBER         = 1.0
+
+# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) 
+# base path where the generated documentation will be put. 
+# If a relative path is entered, it will be relative to the location 
+# where doxygen was started. If left blank the current directory will be used.
+
+OUTPUT_DIRECTORY       = docs
+
+# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create 
+# 4096 sub-directories (in 2 levels) under the output directory of each output 
+# format and will distribute the generated files over these directories. 
+# Enabling this option can be useful when feeding doxygen a huge amount of 
+# source files, where putting all generated files in the same directory would 
+# otherwise cause performance problems for the file system.
+
+CREATE_SUBDIRS         = NO
+
+# The OUTPUT_LANGUAGE tag is used to specify the language in which all 
+# documentation generated by doxygen is written. Doxygen will use this 
+# information to generate all constant output in the proper language. 
+# The default language is English, other supported languages are: 
+# Afrikaans, Arabic, Brazilian, Catalan, Chinese, Chinese-Traditional, 
+# Croatian, Czech, Danish, Dutch, Esperanto, Farsi, Finnish, French, German, 
+# Greek, Hungarian, Italian, Japanese, Japanese-en (Japanese with English 
+# messages), Korean, Korean-en, Lithuanian, Norwegian, Macedonian, Persian, 
+# Polish, Portuguese, Romanian, Russian, Serbian, Serbian-Cyrilic, Slovak, 
+# Slovene, Spanish, Swedish, Ukrainian, and Vietnamese.
+
+OUTPUT_LANGUAGE        = English
+
+# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will 
+# include brief member descriptions after the members that are listed in 
+# the file and class documentation (similar to JavaDoc). 
+# Set to NO to disable this.
+
+BRIEF_MEMBER_DESC      = YES
+
+# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend 
+# the brief description of a member or function before the detailed description. 
+# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the 
+# brief descriptions will be completely suppressed.
+
+REPEAT_BRIEF           = YES
+
+# This tag implements a quasi-intelligent brief description abbreviator 
+# that is used to form the text in various listings. Each string 
+# in this list, if found as the leading text of the brief description, will be 
+# stripped from the text and the result after processing the whole list, is 
+# used as the annotated text. Otherwise, the brief description is used as-is. 
+# If left blank, the following values are used ("$name" is automatically 
+# replaced with the name of the entity): "The $name class" "The $name widget" 
+# "The $name file" "is" "provides" "specifies" "contains" 
+# "represents" "a" "an" "the"
+
+ABBREVIATE_BRIEF       = 
+
+# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then 
+# Doxygen will generate a detailed section even if there is only a brief 
+# description.
+
+ALWAYS_DETAILED_SEC    = NO
+
+# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all 
+# inherited members of a class in the documentation of that class as if those 
+# members were ordinary class members. Constructors, destructors and assignment 
+# operators of the base classes will not be shown.
+
+INLINE_INHERITED_MEMB  = NO
+
+# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full 
+# path before files name in the file list and in the header files. If set 
+# to NO the shortest path that makes the file name unique will be used.
+
+FULL_PATH_NAMES        = YES
+
+# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag 
+# can be used to strip a user-defined part of the path. Stripping is 
+# only done if one of the specified strings matches the left-hand part of 
+# the path. The tag can be used to show relative paths in the file list. 
+# If left blank the directory from which doxygen is run is used as the 
+# path to strip.
+
+STRIP_FROM_PATH        = 
+
+# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of 
+# the path mentioned in the documentation of a class, which tells 
+# the reader which header file to include in order to use a class. 
+# If left blank only the name of the header file containing the class 
+# definition is used. Otherwise one should specify the include paths that 
+# are normally passed to the compiler using the -I flag.
+
+STRIP_FROM_INC_PATH    = 
+
+# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter 
+# (but less readable) file names. This can be useful is your file systems 
+# doesn't support long names like on DOS, Mac, or CD-ROM.
+
+SHORT_NAMES            = NO
+
+# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen 
+# will interpret the first line (until the first dot) of a JavaDoc-style 
+# comment as the brief description. If set to NO, the JavaDoc 
+# comments will behave just like regular Qt-style comments 
+# (thus requiring an explicit @brief command for a brief description.)
+
+JAVADOC_AUTOBRIEF      = NO
+
+# If the QT_AUTOBRIEF tag is set to YES then Doxygen will 
+# interpret the first line (until the first dot) of a Qt-style 
+# comment as the brief description. If set to NO, the comments 
+# will behave just like regular Qt-style comments (thus requiring 
+# an explicit \brief command for a brief description.)
+
+QT_AUTOBRIEF           = NO
+
+# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen 
+# treat a multi-line C++ special comment block (i.e. a block of //! or /// 
+# comments) as a brief description. This used to be the default behaviour. 
+# The new default is to treat a multi-line C++ comment block as a detailed 
+# description. Set this tag to YES if you prefer the old behaviour instead.
+
+MULTILINE_CPP_IS_BRIEF = NO
+
+# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented 
+# member inherits the documentation from any documented member that it 
+# re-implements.
+
+INHERIT_DOCS           = YES
+
+# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce 
+# a new page for each member. If set to NO, the documentation of a member will 
+# be part of the file/class/namespace that contains it.
+
+SEPARATE_MEMBER_PAGES  = NO
+
+# The TAB_SIZE tag can be used to set the number of spaces in a tab. 
+# Doxygen uses this value to replace tabs by spaces in code fragments.
+
+TAB_SIZE               = 8
+
+# This tag can be used to specify a number of aliases that acts 
+# as commands in the documentation. An alias has the form "name=value". 
+# For example adding "sideeffect=\par Side Effects:\n" will allow you to 
+# put the command \sideeffect (or @sideeffect) in the documentation, which 
+# will result in a user-defined paragraph with heading "Side Effects:". 
+# You can put \n's in the value part of an alias to insert newlines.
+
+ALIASES                = 
+
+# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C 
+# sources only. Doxygen will then generate output that is more tailored for C. 
+# For instance, some of the names that are used will be different. The list 
+# of all members will be omitted, etc.
+
+OPTIMIZE_OUTPUT_FOR_C  = YES
+
+# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java 
+# sources only. Doxygen will then generate output that is more tailored for 
+# Java. For instance, namespaces will be presented as packages, qualified 
+# scopes will look different, etc.
+
+OPTIMIZE_OUTPUT_JAVA   = NO
+
+# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran 
+# sources only. Doxygen will then generate output that is more tailored for 
+# Fortran.
+
+OPTIMIZE_FOR_FORTRAN   = NO
+
+# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL 
+# sources. Doxygen will then generate output that is tailored for 
+# VHDL.
+
+OPTIMIZE_OUTPUT_VHDL   = NO
+
+# Doxygen selects the parser to use depending on the extension of the files it parses. 
+# With this tag you can assign which parser to use for a given extension. 
+# Doxygen has a built-in mapping, but you can override or extend it using this tag. 
+# The format is ext=language, where ext is a file extension, and language is one of 
+# the parsers supported by doxygen: IDL, Java, Javascript, C#, C, C++, D, PHP, 
+# Objective-C, Python, Fortran, VHDL, C, C++. For instance to make doxygen treat 
+# .inc files as Fortran files (default is PHP), and .f files as C (default is Fortran), 
+# use: inc=Fortran f=C. Note that for custom extensions you also need to set FILE_PATTERNS otherwise the files are not read by doxygen.
+
+EXTENSION_MAPPING      = 
+
+# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want 
+# to include (a tag file for) the STL sources as input, then you should 
+# set this tag to YES in order to let doxygen match functions declarations and 
+# definitions whose arguments contain STL classes (e.g. func(std::string); v.s. 
+# func(std::string) {}). This also make the inheritance and collaboration 
+# diagrams that involve STL classes more complete and accurate.
+
+BUILTIN_STL_SUPPORT    = NO
+
+# If you use Microsoft's C++/CLI language, you should set this option to YES to 
+# enable parsing support.
+
+CPP_CLI_SUPPORT        = NO
+
+# Set the SIP_SUPPORT tag to YES if your project consists of sip sources only. 
+# Doxygen will parse them like normal C++ but will assume all classes use public 
+# instead of private inheritance when no explicit protection keyword is present.
+
+SIP_SUPPORT            = NO
+
+# For Microsoft's IDL there are propget and propput attributes to indicate getter 
+# and setter methods for a property. Setting this option to YES (the default) 
+# will make doxygen to replace the get and set methods by a property in the 
+# documentation. This will only work if the methods are indeed getting or 
+# setting a simple type. If this is not the case, or you want to show the 
+# methods anyway, you should set this option to NO.
+
+IDL_PROPERTY_SUPPORT   = YES
+
+# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC 
+# tag is set to YES, then doxygen will reuse the documentation of the first 
+# member in the group (if any) for the other members of the group. By default 
+# all members of a group must be documented explicitly.
+
+DISTRIBUTE_GROUP_DOC   = NO
+
+# Set the SUBGROUPING tag to YES (the default) to allow class member groups of 
+# the same type (for instance a group of public functions) to be put as a 
+# subgroup of that type (e.g. under the Public Functions section). Set it to 
+# NO to prevent subgrouping. Alternatively, this can be done per class using 
+# the \nosubgrouping command.
+
+SUBGROUPING            = YES
+
+# When TYPEDEF_HIDES_STRUCT is enabled, a typedef of a struct, union, or enum 
+# is documented as struct, union, or enum with the name of the typedef. So 
+# typedef struct TypeS {} TypeT, will appear in the documentation as a struct 
+# with name TypeT. When disabled the typedef will appear as a member of a file, 
+# namespace, or class. And the struct will be named TypeS. This can typically 
+# be useful for C code in case the coding convention dictates that all compound 
+# types are typedef'ed and only the typedef is referenced, never the tag name.
+
+TYPEDEF_HIDES_STRUCT   = NO
+
+# The SYMBOL_CACHE_SIZE determines the size of the internal cache use to 
+# determine which symbols to keep in memory and which to flush to disk. 
+# When the cache is full, less often used symbols will be written to disk. 
+# For small to medium size projects (<1000 input files) the default value is 
+# probably good enough. For larger projects a too small cache size can cause 
+# doxygen to be busy swapping symbols to and from disk most of the time 
+# causing a significant performance penality. 
+# If the system has enough physical memory increasing the cache will improve the 
+# performance by keeping more symbols in memory. Note that the value works on 
+# a logarithmic scale so increasing the size by one will rougly double the 
+# memory usage. The cache size is given by this formula: 
+# 2^(16+SYMBOL_CACHE_SIZE). The valid range is 0..9, the default is 0, 
+# corresponding to a cache size of 2^16 = 65536 symbols
+
+SYMBOL_CACHE_SIZE      = 0
+
+#---------------------------------------------------------------------------
+# Build related configuration options
+#---------------------------------------------------------------------------
+
+# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in 
+# documentation are documented, even if no documentation was available. 
+# Private class members and static file members will be hidden unless 
+# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES
+
+EXTRACT_ALL            = NO
+
+# If the EXTRACT_PRIVATE tag is set to YES all private members of a class 
+# will be included in the documentation.
+
+EXTRACT_PRIVATE        = NO
+
+# If the EXTRACT_STATIC tag is set to YES all static members of a file 
+# will be included in the documentation.
+
+EXTRACT_STATIC         = NO
+
+# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) 
+# defined locally in source files will be included in the documentation. 
+# If set to NO only classes defined in header files are included.
+
+EXTRACT_LOCAL_CLASSES  = YES
+
+# This flag is only useful for Objective-C code. When set to YES local 
+# methods, which are defined in the implementation section but not in 
+# the interface are included in the documentation. 
+# If set to NO (the default) only methods in the interface are included.
+
+EXTRACT_LOCAL_METHODS  = NO
+
+# If this flag is set to YES, the members of anonymous namespaces will be 
+# extracted and appear in the documentation as a namespace called 
+# 'anonymous_namespace{file}', where file will be replaced with the base 
+# name of the file that contains the anonymous namespace. By default 
+# anonymous namespace are hidden.
+
+EXTRACT_ANON_NSPACES   = NO
+
+# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all 
+# undocumented members of documented classes, files or namespaces. 
+# If set to NO (the default) these members will be included in the 
+# various overviews, but no documentation section is generated. 
+# This option has no effect if EXTRACT_ALL is enabled.
+
+HIDE_UNDOC_MEMBERS     = NO
+
+# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all 
+# undocumented classes that are normally visible in the class hierarchy. 
+# If set to NO (the default) these classes will be included in the various 
+# overviews. This option has no effect if EXTRACT_ALL is enabled.
+
+HIDE_UNDOC_CLASSES     = NO
+
+# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all 
+# friend (class|struct|union) declarations. 
+# If set to NO (the default) these declarations will be included in the 
+# documentation.
+
+HIDE_FRIEND_COMPOUNDS  = NO
+
+# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any 
+# documentation blocks found inside the body of a function. 
+# If set to NO (the default) these blocks will be appended to the 
+# function's detailed documentation block.
+
+HIDE_IN_BODY_DOCS      = NO
+
+# The INTERNAL_DOCS tag determines if documentation 
+# that is typed after a \internal command is included. If the tag is set 
+# to NO (the default) then the documentation will be excluded. 
+# Set it to YES to include the internal documentation.
+
+INTERNAL_DOCS          = NO
+
+# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate 
+# file names in lower-case letters. If set to YES upper-case letters are also 
+# allowed. This is useful if you have classes or files whose names only differ 
+# in case and if your file system supports case sensitive file names. Windows 
+# and Mac users are advised to set this option to NO.
+
+CASE_SENSE_NAMES       = YES
+
+# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen 
+# will show members with their full class and namespace scopes in the 
+# documentation. If set to YES the scope will be hidden.
+
+HIDE_SCOPE_NAMES       = NO
+
+# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen 
+# will put a list of the files that are included by a file in the documentation 
+# of that file.
+
+SHOW_INCLUDE_FILES     = YES
+
+# If the INLINE_INFO tag is set to YES (the default) then a tag [inline] 
+# is inserted in the documentation for inline members.
+
+INLINE_INFO            = YES
+
+# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen 
+# will sort the (detailed) documentation of file and class members 
+# alphabetically by member name. If set to NO the members will appear in 
+# declaration order.
+
+SORT_MEMBER_DOCS       = YES
+
+# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the 
+# brief documentation of file, namespace and class members alphabetically 
+# by member name. If set to NO (the default) the members will appear in 
+# declaration order.
+
+SORT_BRIEF_DOCS        = NO
+
+# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the 
+# hierarchy of group names into alphabetical order. If set to NO (the default) 
+# the group names will appear in their defined order.
+
+SORT_GROUP_NAMES       = NO
+
+# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be 
+# sorted by fully-qualified names, including namespaces. If set to 
+# NO (the default), the class list will be sorted only by class name, 
+# not including the namespace part. 
+# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. 
+# Note: This option applies only to the class list, not to the 
+# alphabetical list.
+
+SORT_BY_SCOPE_NAME     = NO
+
+# The GENERATE_TODOLIST tag can be used to enable (YES) or 
+# disable (NO) the todo list. This list is created by putting \todo 
+# commands in the documentation.
+
+GENERATE_TODOLIST      = YES
+
+# The GENERATE_TESTLIST tag can be used to enable (YES) or 
+# disable (NO) the test list. This list is created by putting \test 
+# commands in the documentation.
+
+GENERATE_TESTLIST      = YES
+
+# The GENERATE_BUGLIST tag can be used to enable (YES) or 
+# disable (NO) the bug list. This list is created by putting \bug 
+# commands in the documentation.
+
+GENERATE_BUGLIST       = YES
+
+# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or 
+# disable (NO) the deprecated list. This list is created by putting 
+# \deprecated commands in the documentation.
+
+GENERATE_DEPRECATEDLIST= YES
+
+# The ENABLED_SECTIONS tag can be used to enable conditional 
+# documentation sections, marked by \if sectionname ... \endif.
+
+ENABLED_SECTIONS       = 
+
+# The MAX_INITIALIZER_LINES tag determines the maximum number of lines 
+# the initial value of a variable or define consists of for it to appear in 
+# the documentation. If the initializer consists of more lines than specified 
+# here it will be hidden. Use a value of 0 to hide initializers completely. 
+# The appearance of the initializer of individual variables and defines in the 
+# documentation can be controlled using \showinitializer or \hideinitializer 
+# command in the documentation regardless of this setting.
+
+MAX_INITIALIZER_LINES  = 30
+
+# Set the SHOW_USED_FILES tag to NO to disable the list of files generated 
+# at the bottom of the documentation of classes and structs. If set to YES the 
+# list will mention the files that were used to generate the documentation.
+
+SHOW_USED_FILES        = YES
+
+# If the sources in your project are distributed over multiple directories 
+# then setting the SHOW_DIRECTORIES tag to YES will show the directory hierarchy 
+# in the documentation. The default is NO.
+
+SHOW_DIRECTORIES       = NO
+
+# Set the SHOW_FILES tag to NO to disable the generation of the Files page. 
+# This will remove the Files entry from the Quick Index and from the 
+# Folder Tree View (if specified). The default is YES.
+
+SHOW_FILES             = YES
+
+# Set the SHOW_NAMESPACES tag to NO to disable the generation of the 
+# Namespaces page. 
+# This will remove the Namespaces entry from the Quick Index 
+# and from the Folder Tree View (if specified). The default is YES.
+
+SHOW_NAMESPACES        = YES
+
+# The FILE_VERSION_FILTER tag can be used to specify a program or script that 
+# doxygen should invoke to get the current version for each file (typically from 
+# the version control system). Doxygen will invoke the program by executing (via 
+# popen()) the command <command> <input-file>, where <command> is the value of 
+# the FILE_VERSION_FILTER tag, and <input-file> is the name of an input file 
+# provided by doxygen. Whatever the program writes to standard output 
+# is used as the file version. See the manual for examples.
+
+FILE_VERSION_FILTER    = 
+
+# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed by 
+# doxygen. The layout file controls the global structure of the generated output files 
+# in an output format independent way. The create the layout file that represents 
+# doxygen's defaults, run doxygen with the -l option. You can optionally specify a 
+# file name after the option, if omitted DoxygenLayout.xml will be used as the name 
+# of the layout file.
+
+LAYOUT_FILE            = 
+
+#---------------------------------------------------------------------------
+# configuration options related to warning and progress messages
+#---------------------------------------------------------------------------
+
+# The QUIET tag can be used to turn on/off the messages that are generated 
+# by doxygen. Possible values are YES and NO. If left blank NO is used.
+
+QUIET                  = NO
+
+# The WARNINGS tag can be used to turn on/off the warning messages that are 
+# generated by doxygen. Possible values are YES and NO. If left blank 
+# NO is used.
+
+WARNINGS               = YES
+
+# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings 
+# for undocumented members. If EXTRACT_ALL is set to YES then this flag will 
+# automatically be disabled.
+
+WARN_IF_UNDOCUMENTED   = YES
+
+# If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for 
+# potential errors in the documentation, such as not documenting some 
+# parameters in a documented function, or documenting parameters that 
+# don't exist or using markup commands wrongly.
+
+WARN_IF_DOC_ERROR      = YES
+
+# This WARN_NO_PARAMDOC option can be abled to get warnings for 
+# functions that are documented, but have no documentation for their parameters 
+# or return value. If set to NO (the default) doxygen will only warn about 
+# wrong or incomplete parameter documentation, but not about the absence of 
+# documentation.
+
+WARN_NO_PARAMDOC       = NO
+
+# The WARN_FORMAT tag determines the format of the warning messages that 
+# doxygen can produce. The string should contain the $file, $line, and $text 
+# tags, which will be replaced by the file and line number from which the 
+# warning originated and the warning text. Optionally the format may contain 
+# $version, which will be replaced by the version of the file (if it could 
+# be obtained via FILE_VERSION_FILTER)
+
+WARN_FORMAT            = "$file:$line: $text"
+
+# The WARN_LOGFILE tag can be used to specify a file to which warning 
+# and error messages should be written. If left blank the output is written 
+# to stderr.
+
+WARN_LOGFILE           = 
+
+#---------------------------------------------------------------------------
+# configuration options related to the input files
+#---------------------------------------------------------------------------
+
+# The INPUT tag can be used to specify the files and/or directories that contain 
+# documented source files. You may enter file names like "myfile.cpp" or 
+# directories like "/usr/src/myproject". Separate the files or directories 
+# with spaces.
+
+INPUT                  = 
+
+# This tag can be used to specify the character encoding of the source files 
+# that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is 
+# also the default input encoding. Doxygen uses libiconv (or the iconv built 
+# into libc) for the transcoding. See http://www.gnu.org/software/libiconv for 
+# the list of possible encodings.
+
+INPUT_ENCODING         = UTF-8
+
+# If the value of the INPUT tag contains directories, you can use the 
+# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp 
+# and *.h) to filter out the source-files in the directories. If left 
+# blank the following patterns are tested: 
+# *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx 
+# *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.py *.f90
+
+FILE_PATTERNS          = 
+
+# The RECURSIVE tag can be used to turn specify whether or not subdirectories 
+# should be searched for input files as well. Possible values are YES and NO. 
+# If left blank NO is used.
+
+RECURSIVE              = NO
+
+# The EXCLUDE tag can be used to specify files and/or directories that should 
+# excluded from the INPUT source files. This way you can easily exclude a 
+# subdirectory from a directory tree whose root is specified with the INPUT tag.
+
+EXCLUDE                = 
+
+# The EXCLUDE_SYMLINKS tag can be used select whether or not files or 
+# directories that are symbolic links (a Unix filesystem feature) are excluded 
+# from the input.
+
+EXCLUDE_SYMLINKS       = NO
+
+# If the value of the INPUT tag contains directories, you can use the 
+# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude 
+# certain files from those directories. Note that the wildcards are matched 
+# against the file with absolute path, so to exclude all test directories 
+# for example use the pattern */test/*
+
+EXCLUDE_PATTERNS       = 
+
+# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names 
+# (namespaces, classes, functions, etc.) that should be excluded from the 
+# output. The symbol name can be a fully qualified name, a word, or if the 
+# wildcard * is used, a substring. Examples: ANamespace, AClass, 
+# AClass::ANamespace, ANamespace::*Test
+
+EXCLUDE_SYMBOLS        = 
+
+# The EXAMPLE_PATH tag can be used to specify one or more files or 
+# directories that contain example code fragments that are included (see 
+# the \include command).
+
+EXAMPLE_PATH           = 
+
+# If the value of the EXAMPLE_PATH tag contains directories, you can use the 
+# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp 
+# and *.h) to filter out the source-files in the directories. If left 
+# blank all files are included.
+
+EXAMPLE_PATTERNS       = 
+
+# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be 
+# searched for input files to be used with the \include or \dontinclude 
+# commands irrespective of the value of the RECURSIVE tag. 
+# Possible values are YES and NO. If left blank NO is used.
+
+EXAMPLE_RECURSIVE      = NO
+
+# The IMAGE_PATH tag can be used to specify one or more files or 
+# directories that contain image that are included in the documentation (see 
+# the \image command).
+
+IMAGE_PATH             = 
+
+# The INPUT_FILTER tag can be used to specify a program that doxygen should 
+# invoke to filter for each input file. Doxygen will invoke the filter program 
+# by executing (via popen()) the command <filter> <input-file>, where <filter> 
+# is the value of the INPUT_FILTER tag, and <input-file> is the name of an 
+# input file. Doxygen will then use the output that the filter program writes 
+# to standard output. 
+# If FILTER_PATTERNS is specified, this tag will be 
+# ignored.
+
+INPUT_FILTER           = 
+
+# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern 
+# basis. 
+# Doxygen will compare the file name with each pattern and apply the 
+# filter if there is a match. 
+# The filters are a list of the form: 
+# pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further 
+# info on how filters are used. If FILTER_PATTERNS is empty, INPUT_FILTER 
+# is applied to all files.
+
+FILTER_PATTERNS        = 
+
+# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using 
+# INPUT_FILTER) will be used to filter the input files when producing source 
+# files to browse (i.e. when SOURCE_BROWSER is set to YES).
+
+FILTER_SOURCE_FILES    = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to source browsing
+#---------------------------------------------------------------------------
+
+# If the SOURCE_BROWSER tag is set to YES then a list of source files will 
+# be generated. Documented entities will be cross-referenced with these sources. 
+# Note: To get rid of all source code in the generated output, make sure also 
+# VERBATIM_HEADERS is set to NO.
+
+SOURCE_BROWSER         = YES
+
+# Setting the INLINE_SOURCES tag to YES will include the body 
+# of functions and classes directly in the documentation.
+
+INLINE_SOURCES         = NO
+
+# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct 
+# doxygen to hide any special comment blocks from generated source code 
+# fragments. Normal C and C++ comments will always remain visible.
+
+STRIP_CODE_COMMENTS    = YES
+
+# If the REFERENCED_BY_RELATION tag is set to YES 
+# then for each documented function all documented 
+# functions referencing it will be listed.
+
+REFERENCED_BY_RELATION = YES
+
+# If the REFERENCES_RELATION tag is set to YES 
+# then for each documented function all documented entities 
+# called/used by that function will be listed.
+
+REFERENCES_RELATION    = YES
+
+# If the REFERENCES_LINK_SOURCE tag is set to YES (the default) 
+# and SOURCE_BROWSER tag is set to YES, then the hyperlinks from 
+# functions in REFERENCES_RELATION and REFERENCED_BY_RELATION lists will 
+# link to the source code. 
+# Otherwise they will link to the documentation.
+
+REFERENCES_LINK_SOURCE = YES
+
+# If the USE_HTAGS tag is set to YES then the references to source code 
+# will point to the HTML generated by the htags(1) tool instead of doxygen 
+# built-in source browser. The htags tool is part of GNU's global source 
+# tagging system (see http://www.gnu.org/software/global/global.html). You 
+# will need version 4.8.6 or higher.
+
+USE_HTAGS              = NO
+
+# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen 
+# will generate a verbatim copy of the header file for each class for 
+# which an include is specified. Set to NO to disable this.
+
+VERBATIM_HEADERS       = YES
+
+#---------------------------------------------------------------------------
+# configuration options related to the alphabetical class index
+#---------------------------------------------------------------------------
+
+# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index 
+# of all compounds will be generated. Enable this if the project 
+# contains a lot of classes, structs, unions or interfaces.
+
+ALPHABETICAL_INDEX     = NO
+
+# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then 
+# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns 
+# in which this list will be split (can be a number in the range [1..20])
+
+COLS_IN_ALPHA_INDEX    = 5
+
+# In case all classes in a project start with a common prefix, all 
+# classes will be put under the same header in the alphabetical index. 
+# The IGNORE_PREFIX tag can be used to specify one or more prefixes that 
+# should be ignored while generating the index headers.
+
+IGNORE_PREFIX          = 
+
+#---------------------------------------------------------------------------
+# configuration options related to the HTML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_HTML tag is set to YES (the default) Doxygen will 
+# generate HTML output.
+
+GENERATE_HTML          = YES
+
+# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. 
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be 
+# put in front of it. If left blank `html' will be used as the default path.
+
+HTML_OUTPUT            = html
+
+# The HTML_FILE_EXTENSION tag can be used to specify the file extension for 
+# each generated HTML page (for example: .htm,.php,.asp). If it is left blank 
+# doxygen will generate files with .html extension.
+
+HTML_FILE_EXTENSION    = .html
+
+# The HTML_HEADER tag can be used to specify a personal HTML header for 
+# each generated HTML page. If it is left blank doxygen will generate a 
+# standard header.
+
+HTML_HEADER            = 
+
+# The HTML_FOOTER tag can be used to specify a personal HTML footer for 
+# each generated HTML page. If it is left blank doxygen will generate a 
+# standard footer.
+
+HTML_FOOTER            = 
+
+# The HTML_STYLESHEET tag can be used to specify a user-defined cascading 
+# style sheet that is used by each HTML page. It can be used to 
+# fine-tune the look of the HTML output. If the tag is left blank doxygen 
+# will generate a default style sheet. Note that doxygen will try to copy 
+# the style sheet file to the HTML output directory, so don't put your own 
+# stylesheet in the HTML output directory as well, or it will be erased!
+
+HTML_STYLESHEET        = 
+
+# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes, 
+# files or namespaces will be aligned in HTML using tables. If set to 
+# NO a bullet list will be used.
+
+HTML_ALIGN_MEMBERS     = YES
+
+# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML 
+# documentation will contain sections that can be hidden and shown after the 
+# page has loaded. For this to work a browser that supports 
+# JavaScript and DHTML is required (for instance Mozilla 1.0+, Firefox 
+# Netscape 6.0+, Internet explorer 5.0+, Konqueror, or Safari).
+
+HTML_DYNAMIC_SECTIONS  = NO
+
+# If the GENERATE_DOCSET tag is set to YES, additional index files 
+# will be generated that can be used as input for Apple's Xcode 3 
+# integrated development environment, introduced with OSX 10.5 (Leopard). 
+# To create a documentation set, doxygen will generate a Makefile in the 
+# HTML output directory. Running make will produce the docset in that 
+# directory and running "make install" will install the docset in 
+# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find 
+# it at startup. 
+# See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html for more information.
+
+GENERATE_DOCSET        = NO
+
+# When GENERATE_DOCSET tag is set to YES, this tag determines the name of the 
+# feed. A documentation feed provides an umbrella under which multiple 
+# documentation sets from a single provider (such as a company or product suite) 
+# can be grouped.
+
+DOCSET_FEEDNAME        = "Doxygen generated docs"
+
+# When GENERATE_DOCSET tag is set to YES, this tag specifies a string that 
+# should uniquely identify the documentation set bundle. This should be a 
+# reverse domain-name style string, e.g. com.mycompany.MyDocSet. Doxygen 
+# will append .docset to the name.
+
+DOCSET_BUNDLE_ID       = org.doxygen.Project
+
+# If the GENERATE_HTMLHELP tag is set to YES, additional index files 
+# will be generated that can be used as input for tools like the 
+# Microsoft HTML help workshop to generate a compiled HTML help file (.chm) 
+# of the generated HTML documentation.
+
+GENERATE_HTMLHELP      = NO
+
+# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can 
+# be used to specify the file name of the resulting .chm file. You 
+# can add a path in front of the file if the result should not be 
+# written to the html output directory.
+
+CHM_FILE               = 
+
+# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can 
+# be used to specify the location (absolute path including file name) of 
+# the HTML help compiler (hhc.exe). If non-empty doxygen will try to run 
+# the HTML help compiler on the generated index.hhp.
+
+HHC_LOCATION           = 
+
+# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag 
+# controls if a separate .chi index file is generated (YES) or that 
+# it should be included in the master .chm file (NO).
+
+GENERATE_CHI           = NO
+
+# If the GENERATE_HTMLHELP tag is set to YES, the CHM_INDEX_ENCODING 
+# is used to encode HtmlHelp index (hhk), content (hhc) and project file 
+# content.
+
+CHM_INDEX_ENCODING     = 
+
+# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag 
+# controls whether a binary table of contents is generated (YES) or a 
+# normal table of contents (NO) in the .chm file.
+
+BINARY_TOC             = NO
+
+# The TOC_EXPAND flag can be set to YES to add extra items for group members 
+# to the contents of the HTML help documentation and to the tree view.
+
+TOC_EXPAND             = NO
+
+# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and QHP_VIRTUAL_FOLDER 
+# are set, an additional index file will be generated that can be used as input for 
+# Qt's qhelpgenerator to generate a Qt Compressed Help (.qch) of the generated 
+# HTML documentation.
+
+GENERATE_QHP           = NO
+
+# If the QHG_LOCATION tag is specified, the QCH_FILE tag can 
+# be used to specify the file name of the resulting .qch file. 
+# The path specified is relative to the HTML output folder.
+
+QCH_FILE               = 
+
+# The QHP_NAMESPACE tag specifies the namespace to use when generating 
+# Qt Help Project output. For more information please see 
+# http://doc.trolltech.com/qthelpproject.html#namespace
+
+QHP_NAMESPACE          = 
+
+# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating 
+# Qt Help Project output. For more information please see 
+# http://doc.trolltech.com/qthelpproject.html#virtual-folders
+
+QHP_VIRTUAL_FOLDER     = doc
+
+# If QHP_CUST_FILTER_NAME is set, it specifies the name of a custom filter to add. 
+# For more information please see 
+# http://doc.trolltech.com/qthelpproject.html#custom-filters
+
+QHP_CUST_FILTER_NAME   = 
+
+# The QHP_CUST_FILT_ATTRS tag specifies the list of the attributes of the custom filter to add.For more information please see 
+# <a href="http://doc.trolltech.com/qthelpproject.html#custom-filters">Qt Help Project / Custom Filters</a>.
+
+QHP_CUST_FILTER_ATTRS  = 
+
+# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this project's 
+# filter section matches. 
+# <a href="http://doc.trolltech.com/qthelpproject.html#filter-attributes">Qt Help Project / Filter Attributes</a>.
+
+QHP_SECT_FILTER_ATTRS  = 
+
+# If the GENERATE_QHP tag is set to YES, the QHG_LOCATION tag can 
+# be used to specify the location of Qt's qhelpgenerator. 
+# If non-empty doxygen will try to run qhelpgenerator on the generated 
+# .qhp file.
+
+QHG_LOCATION           = 
+
+# The DISABLE_INDEX tag can be used to turn on/off the condensed index at 
+# top of each HTML page. The value NO (the default) enables the index and 
+# the value YES disables it.
+
+DISABLE_INDEX          = NO
+
+# This tag can be used to set the number of enum values (range [1..20]) 
+# that doxygen will group on one line in the generated HTML documentation.
+
+ENUM_VALUES_PER_LINE   = 4
+
+# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index 
+# structure should be generated to display hierarchical information. 
+# If the tag value is set to FRAME, a side panel will be generated 
+# containing a tree-like index structure (just like the one that 
+# is generated for HTML Help). For this to work a browser that supports 
+# JavaScript, DHTML, CSS and frames is required (for instance Mozilla 1.0+, 
+# Netscape 6.0+, Internet explorer 5.0+, or Konqueror). Windows users are 
+# probably better off using the HTML help feature. Other possible values 
+# for this tag are: HIERARCHIES, which will generate the Groups, Directories, 
+# and Class Hierarchy pages using a tree view instead of an ordered list; 
+# ALL, which combines the behavior of FRAME and HIERARCHIES; and NONE, which 
+# disables this behavior completely. For backwards compatibility with previous 
+# releases of Doxygen, the values YES and NO are equivalent to FRAME and NONE 
+# respectively.
+
+GENERATE_TREEVIEW      = NO
+
+# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be 
+# used to set the initial width (in pixels) of the frame in which the tree 
+# is shown.
+
+TREEVIEW_WIDTH         = 250
+
+# Use this tag to change the font size of Latex formulas included 
+# as images in the HTML documentation. The default is 10. Note that 
+# when you change the font size after a successful doxygen run you need 
+# to manually remove any form_*.png images from the HTML output directory 
+# to force them to be regenerated.
+
+FORMULA_FONTSIZE       = 10
+
+#---------------------------------------------------------------------------
+# configuration options related to the LaTeX output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will 
+# generate Latex output.
+
+GENERATE_LATEX         = NO
+
+# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. 
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be 
+# put in front of it. If left blank `latex' will be used as the default path.
+
+LATEX_OUTPUT           = latex
+
+# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be 
+# invoked. If left blank `latex' will be used as the default command name.
+
+LATEX_CMD_NAME         = latex
+
+# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to 
+# generate index for LaTeX. If left blank `makeindex' will be used as the 
+# default command name.
+
+MAKEINDEX_CMD_NAME     = makeindex
+
+# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact 
+# LaTeX documents. This may be useful for small projects and may help to 
+# save some trees in general.
+
+COMPACT_LATEX          = NO
+
+# The PAPER_TYPE tag can be used to set the paper type that is used 
+# by the printer. Possible values are: a4, a4wide, letter, legal and 
+# executive. If left blank a4wide will be used.
+
+PAPER_TYPE             = a4wide
+
+# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX 
+# packages that should be included in the LaTeX output.
+
+EXTRA_PACKAGES         = 
+
+# The LATEX_HEADER tag can be used to specify a personal LaTeX header for 
+# the generated latex document. The header should contain everything until 
+# the first chapter. If it is left blank doxygen will generate a 
+# standard header. Notice: only use this tag if you know what you are doing!
+
+LATEX_HEADER           = 
+
+# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated 
+# is prepared for conversion to pdf (using ps2pdf). The pdf file will 
+# contain links (just like the HTML output) instead of page references 
+# This makes the output suitable for online browsing using a pdf viewer.
+
+PDF_HYPERLINKS         = NO
+
+# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of 
+# plain latex in the generated Makefile. Set this option to YES to get a 
+# higher quality PDF documentation.
+
+USE_PDFLATEX           = NO
+
+# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode. 
+# command to the generated LaTeX files. This will instruct LaTeX to keep 
+# running if errors occur, instead of asking the user for help. 
+# This option is also used when generating formulas in HTML.
+
+LATEX_BATCHMODE        = NO
+
+# If LATEX_HIDE_INDICES is set to YES then doxygen will not 
+# include the index chapters (such as File Index, Compound Index, etc.) 
+# in the output.
+
+LATEX_HIDE_INDICES     = NO
+
+# If LATEX_SOURCE_CODE is set to YES then doxygen will include source code with syntax highlighting in the LaTeX output. Note that which sources are shown also depends on other settings such as SOURCE_BROWSER.
+
+LATEX_SOURCE_CODE      = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the RTF output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output 
+# The RTF output is optimized for Word 97 and may not look very pretty with 
+# other RTF readers or editors.
+
+GENERATE_RTF           = NO
+
+# The RTF_OUTPUT tag is used to specify where the RTF docs will be put. 
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be 
+# put in front of it. If left blank `rtf' will be used as the default path.
+
+RTF_OUTPUT             = rtf
+
+# If the COMPACT_RTF tag is set to YES Doxygen generates more compact 
+# RTF documents. This may be useful for small projects and may help to 
+# save some trees in general.
+
+COMPACT_RTF            = NO
+
+# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated 
+# will contain hyperlink fields. The RTF file will 
+# contain links (just like the HTML output) instead of page references. 
+# This makes the output suitable for online browsing using WORD or other 
+# programs which support those fields. 
+# Note: wordpad (write) and others do not support links.
+
+RTF_HYPERLINKS         = NO
+
+# Load stylesheet definitions from file. Syntax is similar to doxygen's 
+# config file, i.e. a series of assignments. You only have to provide 
+# replacements, missing definitions are set to their default value.
+
+RTF_STYLESHEET_FILE    = 
+
+# Set optional variables used in the generation of an rtf document. 
+# Syntax is similar to doxygen's config file.
+
+RTF_EXTENSIONS_FILE    = 
+
+#---------------------------------------------------------------------------
+# configuration options related to the man page output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_MAN tag is set to YES (the default) Doxygen will 
+# generate man pages
+
+GENERATE_MAN           = NO
+
+# The MAN_OUTPUT tag is used to specify where the man pages will be put. 
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be 
+# put in front of it. If left blank `man' will be used as the default path.
+
+MAN_OUTPUT             = man
+
+# The MAN_EXTENSION tag determines the extension that is added to 
+# the generated man pages (default is the subroutine's section .3)
+
+MAN_EXTENSION          = .3
+
+# If the MAN_LINKS tag is set to YES and Doxygen generates man output, 
+# then it will generate one additional man file for each entity 
+# documented in the real man page(s). These additional files 
+# only source the real man page, but without them the man command 
+# would be unable to find the correct page. The default is NO.
+
+MAN_LINKS              = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the XML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_XML tag is set to YES Doxygen will 
+# generate an XML file that captures the structure of 
+# the code including all documentation.
+
+GENERATE_XML           = NO
+
+# The XML_OUTPUT tag is used to specify where the XML pages will be put. 
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be 
+# put in front of it. If left blank `xml' will be used as the default path.
+
+XML_OUTPUT             = xml
+
+# The XML_SCHEMA tag can be used to specify an XML schema, 
+# which can be used by a validating XML parser to check the 
+# syntax of the XML files.
+
+XML_SCHEMA             = 
+
+# The XML_DTD tag can be used to specify an XML DTD, 
+# which can be used by a validating XML parser to check the 
+# syntax of the XML files.
+
+XML_DTD                = 
+
+# If the XML_PROGRAMLISTING tag is set to YES Doxygen will 
+# dump the program listings (including syntax highlighting 
+# and cross-referencing information) to the XML output. Note that 
+# enabling this will significantly increase the size of the XML output.
+
+XML_PROGRAMLISTING     = YES
+
+#---------------------------------------------------------------------------
+# configuration options for the AutoGen Definitions output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will 
+# generate an AutoGen Definitions (see autogen.sf.net) file 
+# that captures the structure of the code including all 
+# documentation. Note that this feature is still experimental 
+# and incomplete at the moment.
+
+GENERATE_AUTOGEN_DEF   = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the Perl module output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_PERLMOD tag is set to YES Doxygen will 
+# generate a Perl module file that captures the structure of 
+# the code including all documentation. Note that this 
+# feature is still experimental and incomplete at the 
+# moment.
+
+GENERATE_PERLMOD       = NO
+
+# If the PERLMOD_LATEX tag is set to YES Doxygen will generate 
+# the necessary Makefile rules, Perl scripts and LaTeX code to be able 
+# to generate PDF and DVI output from the Perl module output.
+
+PERLMOD_LATEX          = NO
+
+# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be 
+# nicely formatted so it can be parsed by a human reader. 
+# This is useful 
+# if you want to understand what is going on. 
+# On the other hand, if this 
+# tag is set to NO the size of the Perl module output will be much smaller 
+# and Perl will parse it just the same.
+
+PERLMOD_PRETTY         = YES
+
+# The names of the make variables in the generated doxyrules.make file 
+# are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. 
+# This is useful so different doxyrules.make files included by the same 
+# Makefile don't overwrite each other's variables.
+
+PERLMOD_MAKEVAR_PREFIX = 
+
+#---------------------------------------------------------------------------
+# Configuration options related to the preprocessor   
+#---------------------------------------------------------------------------
+
+# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will 
+# evaluate all C-preprocessor directives found in the sources and include 
+# files.
+
+ENABLE_PREPROCESSING   = YES
+
+# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro 
+# names in the source code. If set to NO (the default) only conditional 
+# compilation will be performed. Macro expansion can be done in a controlled 
+# way by setting EXPAND_ONLY_PREDEF to YES.
+
+MACRO_EXPANSION        = NO
+
+# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES 
+# then the macro expansion is limited to the macros specified with the 
+# PREDEFINED and EXPAND_AS_DEFINED tags.
+
+EXPAND_ONLY_PREDEF     = NO
+
+# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files 
+# in the INCLUDE_PATH (see below) will be search if a #include is found.
+
+SEARCH_INCLUDES        = YES
+
+# The INCLUDE_PATH tag can be used to specify one or more directories that 
+# contain include files that are not input files but should be processed by 
+# the preprocessor.
+
+INCLUDE_PATH           = 
+
+# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard 
+# patterns (like *.h and *.hpp) to filter out the header-files in the 
+# directories. If left blank, the patterns specified with FILE_PATTERNS will 
+# be used.
+
+INCLUDE_FILE_PATTERNS  = 
+
+# The PREDEFINED tag can be used to specify one or more macro names that 
+# are defined before the preprocessor is started (similar to the -D option of 
+# gcc). The argument of the tag is a list of macros of the form: name 
+# or name=definition (no spaces). If the definition and the = are 
+# omitted =1 is assumed. To prevent a macro definition from being 
+# undefined via #undef or recursively expanded use the := operator 
+# instead of the = operator.
+
+PREDEFINED             = 
+
+# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then 
+# this tag can be used to specify a list of macro names that should be expanded. 
+# The macro definition that is found in the sources will be used. 
+# Use the PREDEFINED tag if you want to use a different macro definition.
+
+EXPAND_AS_DEFINED      = 
+
+# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then 
+# doxygen's preprocessor will remove all function-like macros that are alone 
+# on a line, have an all uppercase name, and do not end with a semicolon. Such 
+# function macros are typically used for boiler-plate code, and will confuse 
+# the parser if not removed.
+
+SKIP_FUNCTION_MACROS   = YES
+
+#---------------------------------------------------------------------------
+# Configuration::additions related to external references   
+#---------------------------------------------------------------------------
+
+# The TAGFILES option can be used to specify one or more tagfiles. 
+# Optionally an initial location of the external documentation 
+# can be added for each tagfile. The format of a tag file without 
+# this location is as follows: 
+#  
+# TAGFILES = file1 file2 ... 
+# Adding location for the tag files is done as follows: 
+#  
+# TAGFILES = file1=loc1 "file2 = loc2" ... 
+# where "loc1" and "loc2" can be relative or absolute paths or 
+# URLs. If a location is present for each tag, the installdox tool 
+# does not have to be run to correct the links. 
+# Note that each tag file must have a unique name 
+# (where the name does NOT include the path) 
+# If a tag file is not located in the directory in which doxygen 
+# is run, you must also specify the path to the tagfile here.
+
+TAGFILES               = 
+
+# When a file name is specified after GENERATE_TAGFILE, doxygen will create 
+# a tag file that is based on the input files it reads.
+
+GENERATE_TAGFILE       = 
+
+# If the ALLEXTERNALS tag is set to YES all external classes will be listed 
+# in the class index. If set to NO only the inherited external classes 
+# will be listed.
+
+ALLEXTERNALS           = NO
+
+# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed 
+# in the modules index. If set to NO, only the current project's groups will 
+# be listed.
+
+EXTERNAL_GROUPS        = YES
+
+# The PERL_PATH should be the absolute path and name of the perl script 
+# interpreter (i.e. the result of `which perl').
+
+PERL_PATH              = /usr/bin/perl
+
+#---------------------------------------------------------------------------
+# Configuration options related to the dot tool   
+#---------------------------------------------------------------------------
+
+# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will 
+# generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base 
+# or super classes. Setting the tag to NO turns the diagrams off. Note that 
+# this option is superseded by the HAVE_DOT option below. This is only a 
+# fallback. It is recommended to install and use dot, since it yields more 
+# powerful graphs.
+
+CLASS_DIAGRAMS         = YES
+
+# You can define message sequence charts within doxygen comments using the \msc 
+# command. Doxygen will then run the mscgen tool (see 
+# http://www.mcternan.me.uk/mscgen/) to produce the chart and insert it in the 
+# documentation. The MSCGEN_PATH tag allows you to specify the directory where 
+# the mscgen tool resides. If left empty the tool is assumed to be found in the 
+# default search path.
+
+MSCGEN_PATH            = 
+
+# If set to YES, the inheritance and collaboration graphs will hide 
+# inheritance and usage relations if the target is undocumented 
+# or is not a class.
+
+HIDE_UNDOC_RELATIONS   = YES
+
+# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is 
+# available from the path. This tool is part of Graphviz, a graph visualization 
+# toolkit from AT&T and Lucent Bell Labs. The other options in this section 
+# have no effect if this option is set to NO (the default)
+
+HAVE_DOT               = NO
+
+# By default doxygen will write a font called FreeSans.ttf to the output 
+# directory and reference it in all dot files that doxygen generates. This 
+# font does not include all possible unicode characters however, so when you need 
+# these (or just want a differently looking font) you can specify the font name 
+# using DOT_FONTNAME. You need need to make sure dot is able to find the font, 
+# which can be done by putting it in a standard location or by setting the 
+# DOTFONTPATH environment variable or by setting DOT_FONTPATH to the directory 
+# containing the font.
+
+DOT_FONTNAME           = FreeSans
+
+# The DOT_FONTSIZE tag can be used to set the size of the font of dot graphs. 
+# The default size is 10pt.
+
+DOT_FONTSIZE           = 10
+
+# By default doxygen will tell dot to use the output directory to look for the 
+# FreeSans.ttf font (which doxygen will put there itself). If you specify a 
+# different font using DOT_FONTNAME you can set the path where dot 
+# can find it using this tag.
+
+DOT_FONTPATH           = 
+
+# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen 
+# will generate a graph for each documented class showing the direct and 
+# indirect inheritance relations. Setting this tag to YES will force the 
+# the CLASS_DIAGRAMS tag to NO.
+
+CLASS_GRAPH            = YES
+
+# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen 
+# will generate a graph for each documented class showing the direct and 
+# indirect implementation dependencies (inheritance, containment, and 
+# class references variables) of the class with other documented classes.
+
+COLLABORATION_GRAPH    = YES
+
+# If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen 
+# will generate a graph for groups, showing the direct groups dependencies
+
+GROUP_GRAPHS           = YES
+
+# If the UML_LOOK tag is set to YES doxygen will generate inheritance and 
+# collaboration diagrams in a style similar to the OMG's Unified Modeling 
+# Language.
+
+UML_LOOK               = NO
+
+# If set to YES, the inheritance and collaboration graphs will show the 
+# relations between templates and their instances.
+
+TEMPLATE_RELATIONS     = NO
+
+# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT 
+# tags are set to YES then doxygen will generate a graph for each documented 
+# file showing the direct and indirect include dependencies of the file with 
+# other documented files.
+
+INCLUDE_GRAPH          = YES
+
+# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and 
+# HAVE_DOT tags are set to YES then doxygen will generate a graph for each 
+# documented header file showing the documented files that directly or 
+# indirectly include this file.
+
+INCLUDED_BY_GRAPH      = YES
+
+# If the CALL_GRAPH and HAVE_DOT options are set to YES then 
+# doxygen will generate a call dependency graph for every global function 
+# or class method. Note that enabling this option will significantly increase 
+# the time of a run. So in most cases it will be better to enable call graphs 
+# for selected functions only using the \callgraph command.
+
+CALL_GRAPH             = NO
+
+# If the CALLER_GRAPH and HAVE_DOT tags are set to YES then 
+# doxygen will generate a caller dependency graph for every global function 
+# or class method. Note that enabling this option will significantly increase 
+# the time of a run. So in most cases it will be better to enable caller 
+# graphs for selected functions only using the \callergraph command.
+
+CALLER_GRAPH           = NO
+
+# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen 
+# will graphical hierarchy of all classes instead of a textual one.
+
+GRAPHICAL_HIERARCHY    = YES
+
+# If the DIRECTORY_GRAPH, SHOW_DIRECTORIES and HAVE_DOT tags are set to YES 
+# then doxygen will show the dependencies a directory has on other directories 
+# in a graphical way. The dependency relations are determined by the #include 
+# relations between the files in the directories.
+
+DIRECTORY_GRAPH        = YES
+
+# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images 
+# generated by dot. Possible values are png, jpg, or gif 
+# If left blank png will be used.
+
+DOT_IMAGE_FORMAT       = png
+
+# The tag DOT_PATH can be used to specify the path where the dot tool can be 
+# found. If left blank, it is assumed the dot tool can be found in the path.
+
+DOT_PATH               = 
+
+# The DOTFILE_DIRS tag can be used to specify one or more directories that 
+# contain dot files that are included in the documentation (see the 
+# \dotfile command).
+
+DOTFILE_DIRS           = 
+
+# The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of 
+# nodes that will be shown in the graph. If the number of nodes in a graph 
+# becomes larger than this value, doxygen will truncate the graph, which is 
+# visualized by representing a node as a red box. Note that doxygen if the 
+# number of direct children of the root node in a graph is already larger than 
+# DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note 
+# that the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH.
+
+DOT_GRAPH_MAX_NODES    = 50
+
+# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the 
+# graphs generated by dot. A depth value of 3 means that only nodes reachable 
+# from the root by following a path via at most 3 edges will be shown. Nodes 
+# that lay further from the root node will be omitted. Note that setting this 
+# option to 1 or 2 may greatly reduce the computation time needed for large 
+# code bases. Also note that the size of a graph can be further restricted by 
+# DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction.
+
+MAX_DOT_GRAPH_DEPTH    = 0
+
+# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent 
+# background. This is disabled by default, because dot on Windows does not 
+# seem to support this out of the box. Warning: Depending on the platform used, 
+# enabling this option may lead to badly anti-aliased labels on the edges of 
+# a graph (i.e. they become hard to read).
+
+DOT_TRANSPARENT        = NO
+
+# Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output 
+# files in one run (i.e. multiple -o and -T options on the command line). This 
+# makes dot run faster, but since only newer versions of dot (>1.8.10) 
+# support this, this feature is disabled by default.
+
+DOT_MULTI_TARGETS      = NO
+
+# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will 
+# generate a legend page explaining the meaning of the various boxes and 
+# arrows in the dot generated graphs.
+
+GENERATE_LEGEND        = YES
+
+# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will 
+# remove the intermediate dot files that are used to generate 
+# the various graphs.
+
+DOT_CLEANUP            = YES
+
+#---------------------------------------------------------------------------
+# Options related to the search engine
+#---------------------------------------------------------------------------
+
+# The SEARCHENGINE tag specifies whether or not a search engine should be 
+# used. If set to NO the values of all tags below this one will be ignored.
+
+SEARCHENGINE           = NO
Index: branches/wireless/code/projects/libdragonfly/Makefile
===================================================================
--- branches/wireless/code/projects/libdragonfly/Makefile	(nonexistent)
+++ branches/wireless/code/projects/libdragonfly/Makefile	(revision 1493)
@@ -0,0 +1,210 @@
+############################
+### Update this Section ####
+############################
+
+COLONYROOT = ../../..
+
+# Target file name (without extension).
+TARGET = libdragonfly
+
+############################
+
+CDEFS = 
+
+# MCU name
+MCU = atmega128
+
+
+# Processor frequency.
+#     This will define a symbol, F_CPU, in all source code files equal to the 
+#     processor frequency. You can then use this symbol in your source code to 
+#     calculate timings. Do NOT tack on a 'UL' at the end, this will be done
+#     automatically to create a 32-bit value in your source code.
+F_CPU = 16000000
+
+
+# Output format. (can be srec, ihex, binary)
+FORMAT = ihex
+
+
+# List C source files here. (C dependencies are automatically generated.)
+SRC = $(wildcard *.c)
+
+# List Assembler source files here.
+#     Make them always end in a capital .S.  Files ending in a lowercase .s
+#     will not be considered source files but generated files (assembler
+#     output from the compiler), and will be deleted upon "make clean"!
+#     Even though the DOS/Win* filesystem matches both .s and .S the same,
+#     it will preserve the spelling of the filenames, and gcc itself does
+#     care about how the name is spelled on its command-line.
+ASRC = 
+
+# Optimization level, can be [0, 1, 2, 3, s]. 
+#     0 = turn off optimization. s = optimize for size.
+#     (Note: 3 is not always the best optimization level. See avr-libc FAQ.)
+OPT = s
+
+# Debugging format.
+#     Native formats for AVR-GCC's -g are dwarf-2 [default] or stabs.
+#     AVR Studio 4.10 requires dwarf-2.
+#     AVR [Extended] COFF format requires stabs, plus an avr-objcopy run.
+DEBUG = 
+# dwarf-2
+
+# List any extra directories to look for include files here.
+#     Each directory must be seperated by a space.
+#     Use forward slashes for directory separators.
+#     For a directory that has spaces, enclose it in quotes.
+EXTRAINCDIRS = 
+
+# Compiler flag to set the C Standard level.
+#     c89   = "ANSI" C
+#     gnu89 = c89 plus GCC extensions
+#     c99   = ISO C99 standard (not yet fully implemented)
+#     gnu99 = c99 plus GCC extensions
+CSTANDARD = -std=gnu99
+
+
+# Place -D or -U options here
+CDEFS += -DF_CPU=$(F_CPU)UL 
+
+# Place -I options here
+
+
+#---------------- Compiler Options ----------------
+#  -g*:          generate debugging information
+#  -O*:          optimization level
+#  -f...:        tuning, see GCC manual and avr-libc documentation
+#  -Wall...:     warning level
+#  -Wa,...:      tell GCC to pass this to the assembler.
+#    -adhlns...: create assembler listing
+CFLAGS = -g$(DEBUG)
+CFLAGS += $(CDEFS) $(CINCS)
+CFLAGS += -O$(OPT)
+CFLAGS += -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums
+CFLAGS += -Wall -Wstrict-prototypes
+CFLAGS += -Wa,-adhlns=$(<:.c=.lst)
+CFLAGS += $(patsubst %,-I%,$(EXTRAINCDIRS))
+CFLAGS += $(CSTANDARD)
+
+
+#---------------- Library Options ----------------
+# Minimalistic printf version
+PRINTF_LIB_MIN = -Wl,-u,vfprintf -lprintf_min
+
+# Floating point printf version (requires MATH_LIB = -lm below)
+PRINTF_LIB_FLOAT = -Wl,-u,vfprintf -lprintf_flt
+
+# If this is left blank, then it will use the Standard printf version.
+PRINTF_LIB = 
+#PRINTF_LIB = $(PRINTF_LIB_MIN)
+#PRINTF_LIB = $(PRINTF_LIB_FLOAT)
+
+# Minimalistic scanf version
+SCANF_LIB_MIN = -Wl,-u,vfscanf -lscanf_min
+
+# Floating point + %[ scanf version (requires MATH_LIB = -lm below)
+SCANF_LIB_FLOAT = -Wl,-u,vfscanf -lscanf_flt
+
+# If this is left blank, then it will use the Standard scanf version.
+SCANF_LIB = 
+#SCANF_LIB = $(SCANF_LIB_MIN)
+#SCANF_LIB = $(SCANF_LIB_FLOAT)
+
+MATH_LIB = -lm
+
+#============================================================================
+
+
+# Define programs and commands.
+SHELL = sh
+CC = avr-gcc
+AR = avr-ar
+OBJCOPY = avr-objcopy
+OBJDUMP = avr-objdump
+SIZE = avr-size
+NM = avr-nm
+AVRDUDE = avrdude
+REMOVE = rm -f
+REMOVEDIR = rm -rf
+COPY = cp
+DOXYGEN = doxygen
+WINSHELL = cmd
+
+
+# Define Messages
+# English
+MSG_ERRORS_NONE = Errors: none
+MSG_BEGIN = -------- begin --------
+MSG_END = --------  end  --------
+MSG_COMPILING = Compiling:
+MSG_CLEANING = Cleaning project:
+
+# Define all object files.
+OBJ = $(SRC:.c=.o) $(ASRC:.S=.o) 
+
+# Define all listing files.
+LST = $(SRC:.c=.lst) $(ASRC:.S=.lst) 
+
+# Compiler flags to generate dependency files.
+GENDEPFLAGS = -MD -MP -MF .dep/$(@F).d
+
+# Combine all necessary flags and optional flags.
+# Add target processor to flags.
+ALL_CFLAGS = -mmcu=$(MCU) -I. $(CFLAGS) $(GENDEPFLAGS)
+ALL_ASFLAGS = rcs
+
+# Default target.
+all: begin build end
+
+dist: all publish
+
+publish:
+	$(COPY) $(TARGET).a $(COLONYROOT)/code/lib/bin
+	$(COPY) *.h $(COLONYROOT)/code/lib/include/$(TARGET)
+
+.PHONY: docs
+docs:
+	$(DOXYGEN)
+	$(COPY) docs/html/* $(COLONYROOT)/docs/$(TARGET)
+
+
+build: $(OBJ)
+	$(AR) $(ALL_ASFLAGS) $(TARGET).a $(OBJ)
+
+# Eye candy.
+# AVR Studio 3.x does not check make's exit code but relies on
+# the following magic strings to be generated by the compile job.
+begin:
+	@echo
+	@echo $(MSG_BEGIN)
+
+end:
+	@echo $(MSG_END)
+	@echo
+
+# Compile: create object files from C source files.
+%.o : %.c
+	@echo
+	@echo $(MSG_COMPILING) $<
+	$(CC) -c $(ALL_CFLAGS) $< -o $@ 
+
+
+# Target: clean project.
+clean: begin clean_list end
+
+clean_list :
+	@echo
+	@echo $(MSG_CLEANING)
+	$(REMOVE) $(TARGET).a
+	$(REMOVE) $(OBJ)
+	$(REMOVE) $(LST)
+	$(REMOVE) $(SRC:.c=.s)
+	$(REMOVE) $(SRC:.c=.d)
+	$(REMOVEDIR) .dep
+
+
+
+# Include the dependency files.
+-include $(shell mkdir .dep 2>/dev/null) $(wildcard .dep/*)
+
Index: branches/wireless/code/projects/libdragonfly/atomic.h
===================================================================
--- branches/wireless/code/projects/libdragonfly/atomic.h	(nonexistent)
+++ branches/wireless/code/projects/libdragonfly/atomic.h	(revision 1493)
@@ -0,0 +1,309 @@
+/* This file is in the dragonfly library directory because it seems to be
+   missing from the AVR libc distribution */
+   
+/* Copyright (c) 2007 Dean Camera
+   All rights reserved.
+
+   Redistribution and use in source and binary forms, with or without
+   modification, are permitted provided that the following conditions are met:
+
+   * Redistributions of source code must retain the above copyright
+     notice, this list of conditions and the following disclaimer.
+
+   * Redistributions in binary form must reproduce the above copyright
+     notice, this list of conditions and the following disclaimer in
+     the documentation and/or other materials provided with the
+     distribution.
+
+   * Neither the name of the copyright holders nor the names of
+     contributors may be used to endorse or promote products derived
+     from this software without specific prior written permission.
+
+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+  POSSIBILITY OF SUCH DAMAGE.
+*/
+
+/* $Id: atomic.h,v 1.3 2007/12/20 14:17:56 joerg_wunsch Exp $ */
+
+#ifndef _UTIL_ATOMIC_H_
+#define _UTIL_ATOMIC_H_ 1
+
+#include <avr/io.h>
+#include <avr/interrupt.h>
+
+#if !defined(__DOXYGEN__)
+/* Internal helper functions. */
+static __inline__ uint8_t __iSeiRetVal(void)
+{
+    sei();
+    return 1;
+}
+
+static __inline__ uint8_t __iCliRetVal(void)
+{
+    cli();
+    return 1;
+}
+
+static __inline__ void __iSeiParam(const uint8_t *__s)
+{
+    sei();
+    __asm__ volatile ("" ::: "memory");
+    (void)__s;
+}
+
+static __inline__ void __iCliParam(const uint8_t *__s)
+{
+    cli();
+    __asm__ volatile ("" ::: "memory");
+    (void)__s;
+}
+
+static __inline__ void __iRestore(const  uint8_t *__s)
+{
+    SREG = *__s;
+    __asm__ volatile ("" ::: "memory");
+}
+#endif	/* !__DOXYGEN__ */
+
+/** \file */
+/** \defgroup util_atomic <util/atomic.h> Atomically and Non-Atomically Executed Code Blocks
+
+    \code
+    #include <util/atomic.h>
+    \endcode
+
+    \note The macros in this header file require the ISO/IEC 9899:1999
+    ("ISO C99") feature of for loop variables that are declared inside
+    the for loop itself.  For that reason, this header file can only
+    be used if the standard level of the compiler (option --std=) is
+    set to either \c c99 or \c gnu99.
+
+    The macros in this header file deal with code blocks that are
+    guaranteed to be excuted Atomically or Non-Atmomically.  The term
+    "Atomic" in this context refers to the unability of the respective
+    code to be interrupted.
+
+    These macros operate via automatic manipulation of the Global
+    Interrupt Status (I) bit of the SREG register. Exit paths from
+    both block types are all managed automatically without the need
+    for special considerations, i. e. the interrupt status will be
+    restored to the same value it has been when entering the
+    respective block.
+
+    A typical example that requires atomic access is a 16 (or more)
+    bit variable that is shared between the main execution path and an
+    ISR.  While declaring such a variable as volatile ensures that the
+    compiler will not optimize accesses to it away, it does not
+    guarantee atomic access to it.  Assuming the following example:
+
+    \code
+#include <inttypes.h>
+#include <avr/interrupt.h>
+#include <avr/io.h>
+
+volatile uint16_t ctr;
+
+ISR(TIMER1_OVF_vect)
+{
+  ctr--;
+}
+
+...
+int
+main(void)
+{
+   ...
+   ctr = 0x200;
+   start_timer();
+   while (ctr != 0)
+     // wait
+       ;
+   ...
+}
+    \endcode
+
+    There is a chance where the main context will exit its wait loop
+    when the variable \c ctr just reached the value 0xFF.  This happens
+    because the compiler cannot natively access a 16-bit variable
+    atomically in an 8-bit CPU.  So the variable is for example at
+    0x100, the compiler then tests the low byte for 0, which succeeds.
+    It then proceeds to test the high byte, but that moment the ISR
+    triggers, and the main context is interrupted.  The ISR will
+    decrement the variable from 0x100 to 0xFF, and the main context
+    proceeds.  It now tests the high byte of the variable which is
+    (now) also 0, so it concludes the variable has reached 0, and
+    terminates the loop.
+
+    Using the macros from this header file, the above code can be
+    rewritten like:
+
+    \code
+#include <inttypes.h>
+#include <avr/interrupt.h>
+#include <avr/io.h>
+#include <util/atomic.h>
+
+volatile uint16_t ctr;
+
+ISR(TIMER1_OVF_vect)
+{
+  ctr--;
+}
+
+...
+int
+main(void)
+{
+   ...
+   ctr = 0x200;
+   start_timer();
+   sei();
+   uint16_t ctr_copy;
+   do
+   {
+     ATOMIC_BLOCK(ATOMIC_FORCEON)
+     {
+       ctr_copy = ctr;
+     }
+   }
+   while (ctr_copy != 0);
+   ...
+}
+    \endcode
+
+    This will install the appropriate interrupt protection before
+    accessing variable \c ctr, so it is guaranteed to be consistently
+    tested.  If the global interrupt state were uncertain before
+    entering the ATOMIC_BLOCK, it should be executed with the
+    parameter ATOMIC_RESTORESTATE rather than ATOMIC_FORCEON.
+
+*/
+
+/** \def ATOMIC_BLOCK(type)
+    \ingroup util_atomic
+
+    Creates a block of code that is guaranteed to be executed
+    atomically. Upon entering the block the Global Interrupt Status
+    flag in SREG is disabled, and re-enabled upon exiting the block
+    from any exit path.
+
+    Two possible macro parameters are permitted, ATOMIC_RESTORESTATE
+    and ATOMIC_FORCEON.
+*/
+#if defined(__DOXYGEN__)
+#define ATOMIC_BLOCK(type)
+#else
+#define ATOMIC_BLOCK(type) for ( type, __ToDo = __iCliRetVal(); \
+	                       __ToDo ; __ToDo = 0 )
+#endif	/* __DOXYGEN__ */
+
+/** \def NONATOMIC_BLOCK(type)
+    \ingroup util_atomic
+
+    Creates a block of code that is executed non-atomically. Upon
+    entering the block the Global Interrupt Status flag in SREG is
+    enabled, and disabled upon exiting the block from any exit
+    path. This is useful when nested inside ATOMIC_BLOCK sections,
+    allowing for non-atomic execution of small blocks of code while
+    maintaining the atomic access of the other sections of the parent
+    ATOMIC_BLOCK.
+
+    Two possible macro parameters are permitted,
+    NONATOMIC_RESTORESTATE and NONATOMIC_FORCEOFF.
+*/
+#if defined(__DOXYGEN__)
+#define NONATOMIC_BLOCK(type)
+#else
+#define NONATOMIC_BLOCK(type) for ( type, __ToDo = __iSeiRetVal(); \
+	                          __ToDo ;  __ToDo = 0 )
+#endif	/* __DOXYGEN__ */
+
+/** \def ATOMIC_RESTORESTATE
+    \ingroup util_atomic
+
+    This is a possible parameter for ATOMIC_BLOCK. When used, it will
+    cause the ATOMIC_BLOCK to restore the previous state of the SREG
+    register, saved before the Global Interrupt Status flag bit was
+    disabled. The net effect of this is to make the ATOMIC_BLOCK's
+    contents guaranteed atomic, without changing the state of the
+    Global Interrupt Status flag when execution of the block
+    completes.
+*/
+#if defined(__DOXYGEN__)
+#define ATOMIC_RESTORESTATE
+#else
+#define ATOMIC_RESTORESTATE uint8_t sreg_save \
+	__attribute__((__cleanup__(__iRestore))) = SREG
+#endif	/* __DOXYGEN__ */
+
+/** \def ATOMIC_FORCEON
+    \ingroup util_atomic
+
+    This is a possible parameter for ATOMIC_BLOCK. When used, it will
+    cause the ATOMIC_BLOCK to force the state of the SREG register on
+    exit, enabling the Global Interrupt Status flag bit. This saves on
+    flash space as the previous value of the SREG register does not
+    need to be saved at the start of the block.
+
+    Care should be taken that ATOMIC_FORCEON is only used when it is
+    known that interrupts are enabled before the block's execution or
+    when the side effects of enabling global interrupts at the block's
+    completion are known and understood.
+*/
+#if defined(__DOXYGEN__)
+#define ATOMIC_FORCEON
+#else
+#define ATOMIC_FORCEON uint8_t sreg_save \
+	__attribute__((__cleanup__(__iSeiParam))) = 0
+#endif	/* __DOXYGEN__ */
+
+/** \def NONATOMIC_RESTORESTATE
+    \ingroup util_atomic
+
+    This is a possible parameter for NONATOMIC_BLOCK. When used, it
+    will cause the NONATOMIC_BLOCK to restore the previous state of
+    the SREG register, saved before the Global Interrupt Status flag
+    bit was enabled. The net effect of this is to make the
+    NONATOMIC_BLOCK's contents guaranteed non-atomic, without changing
+    the state of the Global Interrupt Status flag when execution of
+    the block completes.
+*/
+#if defined(__DOXYGEN__)
+#define NONATOMIC_RESTORESTATE
+#else
+#define NONATOMIC_RESTORESTATE uint8_t sreg_save \
+	__attribute__((__cleanup__(__iRestore))) = SREG
+#endif	/* __DOXYGEN__ */
+
+/** \def NONATOMIC_FORCEOFF
+    \ingroup util_atomic
+
+    This is a possible parameter for NONATOMIC_BLOCK. When used, it
+    will cause the NONATOMIC_BLOCK to force the state of the SREG
+    register on exit, disabling the Global Interrupt Status flag
+    bit. This saves on flash space as the previous value of the SREG
+    register does not need to be saved at the start of the block.
+
+    Care should be taken that NONATOMIC_FORCEOFF is only used when it
+    is known that interrupts are disabled before the block's execution
+    or when the side effects of disabling global interrupts at the
+    block's completion are known and understood.
+*/
+#if defined(__DOXYGEN__)
+#define NONATOMIC_FORCEOFF
+#else
+#define NONATOMIC_FORCEOFF uint8_t sreg_save \
+	__attribute__((__cleanup__(__iCliParam))) = 0
+#endif	/* __DOXYGEN__ */
+
+#endif
Index: branches/wireless/code/projects/libdragonfly/odometry.h
===================================================================
--- branches/wireless/code/projects/libdragonfly/odometry.h	(nonexistent)
+++ branches/wireless/code/projects/libdragonfly/odometry.h	(revision 1493)
@@ -0,0 +1,56 @@
+
+/**
+ * @file odometry.h
+ * @brief Code for estimating the robots pose.
+ * 
+ * Offers simple position and orientation information.
+ *
+ * @author Colony Project, CMU Robotics Club
+ **/
+
+#ifndef __ODOMETRY_C__
+#define __ODOMETRY_C__
+
+/**
+ * @addtogroup odometry 
+ * @{
+ **/
+
+//Odometry resolution, *64 microseconds.
+#define ODOMETRY_CLK 255u 
+#define TIME_SCALE 64
+
+//Wheel = 2.613 in.  
+//Circumference = 208.508133 mm
+//Distance per encoder click (circumference / 1024)  = 203.621224 um.
+//Robot width = 5.3745 in. = 136.5123 mm
+
+#define ROBOT_WIDTH_UM 137000  //um
+#define CLICK_DISTANCE_UM 204 //um
+
+#define DISTANCE_SCALE 2.10526316 //Magic constant.
+#define ANGLE_SCALE 1.12823207 //Magic constant.
+
+/** @brief Retrieve the robots estimated x position*/
+long odometry_dx(void);
+
+/** @brief Retrieve the robots estimated y position*/
+long odometry_dy(void);
+
+/** @brief Retrieve the robots estimated orientation*/
+double odometry_angle(void);
+
+/** @brief Initialize odometry. MUST be called before 
+ * the other functions work.**/
+void odometry_init(void);
+
+/** @brief Reset position and orientation to the origin facing
+ * the x axis.*/
+void odometry_reset(void);
+
+/** @brief Report estimated velocity [mm/s].*/
+long odometry_velocity(void);
+
+/**@}**/ //end group
+
+#endif
Index: branches/wireless/code/projects/libdragonfly/reset.h
===================================================================
--- branches/wireless/code/projects/libdragonfly/reset.h	(nonexistent)
+++ branches/wireless/code/projects/libdragonfly/reset.h	(revision 1493)
@@ -0,0 +1,49 @@
+/**
+ * Copyright (c) 2007 Colony Project
+ * 
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ * 
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ **/
+
+
+/**
+ * 
+ * @file reset.h
+ * @brief Contains function(s) for resetting the robots
+ * 
+ * @author Colony Project, CMU Robotics Club, James Kong
+ */
+
+#ifndef _RESET_H_
+#define _RESET_H_
+
+/**
+ * @addtogroup reset
+ * @{
+ **/
+ 
+/** @brief Reset the robot **/
+void reset(void);
+
+/**@}**/ //end group
+
+#endif
+
Index: branches/wireless/code/projects/libdragonfly/dio.h
===================================================================
--- branches/wireless/code/projects/libdragonfly/dio.h	(nonexistent)
+++ branches/wireless/code/projects/libdragonfly/dio.h	(revision 1493)
@@ -0,0 +1,348 @@
+/**
+ * Copyright (c) 2007 Colony Project
+ * 
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ * 
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ **/
+
+
+/**
+ * @file dio.h
+ * @brief Definitions for digital input / output
+ *
+ * This file contains definitions and functions for dealing
+ * with digital input and output.
+ *
+ * @author Colony Project, CMU Robotics Club
+ * Based on Tom Lauwer's Firefly Library
+ **/
+
+#ifndef _DIO_H
+#define _DIO_H
+
+/*
+  these are ALL the pins
+  don't use unless you know what you're doing
+*/
+
+/*
+  DIO pins on new dragonfly boards are shown below:
+  -----------------------------------------------
+  | _PIN_E6 | _PIN_E7 | _PIN_D2 | _PIN_D3 | VCC |
+  -----------------------------------------------
+  | _PIN_E2 | _PIN_E3 | _PIN_E4 | _PIN_E5 | GND |
+  -----------------------------------------------
+*/
+
+/** @brief Port A **/
+#define _PORT_A 1
+/** @brief Port B **/
+#define _PORT_B 2
+/** @brief Port C **/
+#define _PORT_C 3
+/** @brief Port D **/
+#define _PORT_D 4
+/** @brief Port E **/
+#define _PORT_E 5
+/** @brief Port F **/
+#define _PORT_F 6
+/** @brief Port G **/
+#define _PORT_G 7
+
+/** @brief Pin A0 **/
+#define _PIN_A0 8
+/** @brief Pin A1 **/
+#define _PIN_A1 9
+/** @brief Pin A2 **/
+#define _PIN_A2 10
+/** @brief Pin A3 **/
+#define _PIN_A3 11
+/** @brief Pin A4 **/
+#define _PIN_A4 12
+/** @brief Pin A5 **/
+#define _PIN_A5 13
+/** @brief Pin A6 **/
+#define _PIN_A6 14 
+/** @brief Pin A7 **/
+#define _PIN_A7 15
+
+/** @brief Pin B0 **/
+#define _PIN_B0 16
+/** @brief Pin B1 **/
+#define _PIN_B1 17
+/** @brief Pin B2 **/
+#define _PIN_B2 18
+/** @brief Pin B3 **/
+#define _PIN_B3 19
+/** @brief Pin B4 **/
+#define _PIN_B4 20
+/** @brief Pin B5 **/
+#define _PIN_B5 21
+/** @brief Pin B6 **/
+#define _PIN_B6 22
+/** @brief Pin B7 **/
+#define _PIN_B7 23
+
+/** @brief Pin C0 **/
+#define _PIN_C0 24
+/** @brief Pin C1 **/
+#define _PIN_C1 25
+/** @brief Pin C2 **/
+#define _PIN_C2 26
+/** @brief Pin C3 **/
+#define _PIN_C3 27
+/** @brief Pin C4 **/
+#define _PIN_C4 28
+/** @brief Pin C5 **/
+#define _PIN_C5 29
+/** @brief Pin C6 **/
+#define _PIN_C6 30
+/** @brief Pin C7 **/
+#define _PIN_C7 31
+
+/** @brief Pin D0 **/
+#define _PIN_D0 32  // pin DIO6 on new dragonfly boards
+/** @brief Pin D1 **/
+#define _PIN_D1 33  // pin DIO7
+/** @brief Pin D2 **/
+#define _PIN_D2 34
+/** @brief Pin D3 **/
+#define _PIN_D3 35
+/** @brief Pin D4 **/
+#define _PIN_D4 36
+/** @brief Pin D5 **/
+#define _PIN_D5 37
+/** @brief Pin D6 **/
+#define _PIN_D6 38
+/** @brief Pin D7 **/
+#define _PIN_D7 39
+
+/** @brief Pin E0 **/
+#define _PIN_E0 40
+/** @brief Pin E1 **/
+#define _PIN_E1 41
+/** @brief Pin E2 **/
+#define _PIN_E2 42  // pin DIO0
+/** @brief Pin E3 **/
+#define _PIN_E3 43  // pin DIO1
+/** @brief Pin E4 **/
+#define _PIN_E4 44  // pin DIO2
+/** @brief Pin E5 **/
+#define _PIN_E5 45  // pin DIO3
+/** @brief Pin E6 **/
+#define _PIN_E6 46  // pin DIO4
+/** @brief Pin E7 **/
+#define _PIN_E7 47  // pin DIO5
+
+/** @brief Pin F0 **/
+#define _PIN_F0 48
+/** @brief Pin F1 **/
+#define _PIN_F1 49
+/** @brief Pin F2 **/
+#define _PIN_F2 50
+/** @brief Pin F3 **/
+#define _PIN_F3 51
+/** @brief Pin F4 **/
+#define _PIN_F4 52
+/** @brief Pin F5 **/
+#define _PIN_F5 53
+/** @brief Pin F6 **/
+#define _PIN_F6 54
+/** @brief Pin F7 **/
+#define _PIN_F7 55
+
+/** @brief Pin G0 **/
+#define _PIN_G0 56
+/** @brief Pin WR **/
+#define _PIN_WR 56
+/** @brief Pin G1 **/
+#define _PIN_G1 57
+/** @brief Pin RD **/
+#define _PIN_RD 57
+/** @brief Pin G2 **/
+#define _PIN_G2 58
+/** @brief Pin ALE **/
+#define _PIN_ALE 58
+/** @brief Pin G3 **/
+#define _PIN_G3 59
+/** @brief Pin TOSC2 **/
+#define _PIN_TOSC2 59
+/** @brief Pin G4 **/
+#define _PIN_G4 60
+/** @brief Pin TOSC1 **/
+#define _PIN_TOSC1 60
+//#define _PIN_G5 61
+//#define _PIN_G6 62
+//#define _PIN_G7 63
+
+/*
+  These are the header pins (the ones you can connect things to)
+  Feel free to use these
+*/
+
+/**
+ * @addtogroup dio
+ * @{
+ **/
+/** @brief Pin A0 **/
+#define PIN_A0 8
+/** @brief Pin A1 **/
+#define PIN_A1 9
+/** @brief Pin A2 **/
+#define PIN_A2 10
+/** @brief Pin A3 **/
+#define PIN_A3 11
+/** @brief Pin A4 **/
+#define PIN_A4 12
+/** @brief Pin A5 **/
+#define PIN_A5 13
+/** @brief Pin A6 **/
+#define PIN_A6 14 
+/** @brief Pin A7 **/
+#define PIN_A7 15
+
+/** @brief Pin SS **/
+#define PIN_SS 16
+/** @brief Pin SCK **/
+#define PIN_SCK 17
+/** @brief Pin MOSI **/
+#define PIN_MOSI 18
+/** @brief Pin MISO **/
+#define PIN_MISO 19
+/** @brief LCD Command Pin **/
+#define PIN_LCD_COMMAND 20
+
+/** @brief Pin C0 **/
+#define PIN_C0 24
+/** @brief Pin C1 **/
+#define PIN_C1 25
+/** @brief Pin C2 **/
+#define PIN_C2 26
+/** @brief Pin C3 **/
+#define PIN_C3 27
+/** @brief Pin C4 **/
+#define PIN_C4 28
+/** @brief Pin C5 **/
+#define PIN_C5 29
+/** @brief Pin C6 **/
+#define PIN_C6 30
+/** @brief Pin C7 **/
+#define PIN_C7 31
+
+/** @brief Pin SCL **/
+#define PIN_SCL 32
+/** @brief Pin SDA **/
+#define PIN_SDA 33
+
+/** @brief Pin RX0 **/
+#define PIN_RX0 40
+/** @brief Pin TX0 **/
+#define PIN_TX0 41
+/** @brief LCD Reset Pin **/
+#define PIN_LCD_RESET 42
+/** @brief Pin E6 **/
+#define PIN_E6 46
+/** @brief Pin EXT_DIO1 **/
+#define PIN_EXT_DIO1 46
+/** @brief Pin E7 **/
+#define PIN_E7 47
+/** @brief Pin EXT_DIO2 **/
+#define PIN_EXT_DIO2 48
+
+/** @brief Pin AN0 **/
+#define PIN_AN0 48
+/** @brief Pin ADC0 **/
+#define PIN_ADC0 48
+/** @brief Pin AN1 **/
+#define PIN_AN1 49
+/** @brief Pin ADC1 **/
+#define PIN_ADC1 49
+/** @brief Pin AN2 **/
+#define PIN_AN2 50
+/** @brief Pin ADC2 **/
+#define PIN_ADC2 50
+/** @brief Pin AN3 **/
+#define PIN_AN3 51
+/** @brief Pin ADC3 **/
+#define PIN_ADC3 51
+/** @brief Pin AN4 **/
+#define PIN_AN4 52
+/** @brief Pin ADC4 **/
+#define PIN_ADC4 52
+/** @brief Pin AN5 **/
+#define PIN_AN5 53
+/** @brief Pin ADC5 **/
+#define PIN_ADC5 53
+/** @brief Pin AN6 **/
+#define PIN_AN6 54
+/** @brief Pin ADC6 **/
+#define PIN_ADC6 54
+/** @brief Pin AN7 **/
+#define PIN_AN7 55
+/** @brief Pin ADC7 **/
+#define PIN_ADC7 55
+
+/** @brief Wheel Pin **/
+#define PIN_WHEEL 54
+/** @brief Battery Voltage Monitor Pin **/
+#define PIN_BATT 55
+
+/** @brief button1 Pin **/
+#define PIN_BTN1 56
+/** @brief button2 Pin **/
+#define PIN_BTN2 57
+
+/** @brief LED1 Pin **/
+#define PIN_LED1 58
+
+/* Buttons */
+/** @brief Button Pin **/
+#define PIN_BTN PING
+/** @brief button2 Pin **/
+#define BTN2 PING1
+/** @brief button1 Pin **/
+#define BTN1 PING0
+
+/** @brief Read a portpin. **/
+int digital_input(int);
+/** @brief Output to a portpin. **/
+void digital_output(int bit, int val);
+/** @brief Pullup a portpin. **/
+void digital_pull_up(int);
+
+/** @brief Check if button1 is pressed. **/
+int button1_read( void );
+/** @brief Check if button1 is clicked. **/
+int button1_click( void );
+/** @brief Wait until button1 is pressed. **/
+void button1_wait( void );
+
+/** @brief Check if button2 is pressed. **/
+int button2_read( void );
+/** @brief Check if button2 is clicked. **/
+int button2_click( void );
+/** @brief Wait until button2 is pressed. **/
+void button2_wait( void );
+
+/** @} **/ // end addtogroup
+
+#endif
+
Index: branches/wireless/code/projects/libdragonfly/battery.c
===================================================================
--- branches/wireless/code/projects/libdragonfly/battery.c	(nonexistent)
+++ branches/wireless/code/projects/libdragonfly/battery.c	(revision 1493)
@@ -0,0 +1,156 @@
+/**
+ * Copyright (c) 2007 Colony Project
+ * 
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ * 
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ **/
+
+
+/**
+ * @file battery.c
+ * @brief Implementation for reading battery level
+ *
+ * Contains functions for reading the battery level.
+ *
+ * @author Colony Project, CMU Robotics Club
+ **/
+
+#include "battery.h"
+#include "analog.h"
+
+//Constants for Battery
+//Constants determined experimentally 2/9/2007 - James Kong
+//See Battery8_data.xls for experiment data
+#define BATTERY_NEXT_READ_PRESCALAR 5
+#define MAX_LOW_COUNT 5
+
+//global variables
+int battery_low_count;
+
+/**
+ * @defgroup battery Battery
+ * @brief Functions for reading battery voltage.
+ * 
+ * Contains functions for checking the current
+ * voltage of the battery. Include battery.h to
+ * access these functions.
+ *
+ * @{
+ **/
+
+/**
+ * Returns the voltage of the battery as an analog8
+ * reading. 128 is approximately 5 volts. analog_init
+ * must be called before using this function.
+ *
+ * @return the voltage of the battery as an analog8
+ * reading
+ *
+ * @see analog_init, battery, analog8
+ **/
+int battery8(void)
+{
+  return analog8(BATT_PORT);
+}
+
+/**
+ * Returns the voltage of the battery in deciVolts.
+ * analog_init must be called before using this function.
+ *
+ * @return the voltage of the battery in deciVolts.
+ *
+ * @see analog_init, battery8
+ **/
+int battery(void)
+{
+  /* 5 volts is the max, 255 is the max 8bit number , *2 for the divider */
+        return analog8(BATT_PORT) * 500 >>7;
+}
+
+
+/**
+ * Checks if the battery is low. analog_init must be called before
+ * this function can be used. This function waits for several low
+ * battery readings in a row to avoid false positives.
+ *
+ * @return 1 if the battery is low, 0 otherwise
+ *
+ * @see analog_init
+ **/
+char battery_low(void)
+{
+  static char next_read = 0;
+  static char ret = 0;
+  
+  int batt_reading = battery8();
+
+  if(next_read == 0) 
+  {
+    if(batt_reading > BATTERY_LOWV)
+    {
+        ret = 0;
+        battery_low_count = 0;
+    }
+    else
+    {
+        battery_low_count++;
+        if( battery_low_count >= MAX_LOW_COUNT )
+        {
+            ret = 1;
+            battery_low_count = 0;
+        }
+    }
+    
+    next_read = BATTERY_NEXT_READ_PRESCALAR;
+  }
+  else next_read--;
+  
+  return ret;
+}
+
+/**
+ * Averages n_samples battery8 readings. This function may
+ * take a while to complete, and is only made available
+ * for convenience. analog_init must be called before this
+ * function may be used.
+ *
+ * @param n_samples the number of times to sample the battery voltage
+ *
+ * @return the average reading for the battery voltage, where 128
+ * is approximately 5 Volts.
+ *
+ * @see analog_init, battery
+ **/
+int battery8_avg(int n_samples)
+{
+  int i;
+  long int sum = 0;
+  
+  for(i = 0; i < n_samples; i++) 
+  {
+    sum += battery8();
+  }
+  
+  return (int)(sum / n_samples);
+}
+
+/** @} **/ //end defgroup
+
Index: branches/wireless/code/projects/libdragonfly/move.h
===================================================================
--- branches/wireless/code/projects/libdragonfly/move.h	(nonexistent)
+++ branches/wireless/code/projects/libdragonfly/move.h	(revision 1493)
@@ -0,0 +1,75 @@
+/**
+ * Copyright (c) 2007 Colony Project
+ * 
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ * 
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ **/
+
+
+/**
+ * @file move.h
+ * @brief Contains definitions for controlling robot motion
+ * 
+ * This file offers higher-level functions for robot motion.
+ *
+ * @author Colony Project, CMU Robotics Club
+ **/
+
+#ifndef _MOVE_H_
+#define _MOVE_H_
+
+/**
+ * @addtogroup move
+ * @{
+ **/
+
+/** @brief Move forwards **/
+#define FWD 0
+/** @brief Move backwards **/
+#define BCK 1
+
+/** @brief A slow speed **/
+#define SLOW_SPD 96
+/** @brief Half of the full speed **/
+#define HALF_SPD 128
+/** @brief A normal speed **/
+#define NRML_SPD 160
+/** @brief A fast speed **/
+#define FAST_SPD 192
+/** @brief The maximum speed **/
+#define FULL_SPD 255
+
+/** @brief A slow turning speed **/
+#define SLOW_TURN 64
+/** @brief A medium turning speed **/
+#define NRML_TURN 96
+/** @brief A high turning speed **/
+#define FAST_TURN 128
+
+/** @brief Move the robot at the specified velocity **/
+void move(int velocity, int omega);
+/** @brief Move the robot while avoiding obstacles **/
+void move_avoid(int velocity, int omega, int strength);
+
+/** @} **/
+
+#endif
+
Index: branches/wireless/code/projects/libdragonfly/buzzer.h
===================================================================
--- branches/wireless/code/projects/libdragonfly/buzzer.h	(nonexistent)
+++ branches/wireless/code/projects/libdragonfly/buzzer.h	(revision 1493)
@@ -0,0 +1,88 @@
+/**
+ * Copyright (c) 2007 Colony Project
+ * 
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ * 
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ **/
+
+
+/**
+ * @file buzzer.h
+ * @brief Contains definitions for using the buzzer.
+ *
+ * Contains definitions for using the buzzer built into
+ * the colony robots.
+ *
+ * @author Colony Project, CMU Robotics Club
+ **/
+
+#ifndef _BUZZER_H_
+#define _BUZZER_H_
+
+/**
+ * @addtogroup buzzer
+ * @{
+ **/
+
+//Musical note definitions
+//Source: http://www.answers.com/topic/piano-key-frequencies
+/** @brief Middle C **/
+#define	C4	260 //Middle C
+/** @brief C# **/
+#define	C4s	277 //C sharp
+/** @brief D **/
+#define	D4	294
+/** @brief D# **/
+#define	D4s	311
+/** @brief E **/
+#define	E4	330
+/** @brief F **/
+#define	F4	349
+/** @brief F# **/
+#define	F4s	370
+/** @brief G **/
+#define	G4	392
+/** @brief G# **/
+#define	G4s	415
+/** @brief A **/
+#define	A4	440
+/** @brief A# **/
+#define	A4s	466
+/** @brief B **/
+#define	B4	494
+/** @brief C **/
+#define	C5	523
+
+/** @brief Initialize the buzzer. **/
+void buzzer_init(void);
+/** @brief Set the value the buzzer plays. **/
+void buzzer_set_val(unsigned int buzz_value);
+/** @brief Set the frequency the buzzer plays. **/
+void buzzer_set_freq(unsigned int buzz_freq);
+/** @brief Play a frequency for a specified time. **/
+void buzzer_chirp(unsigned int ms, unsigned int buzz_freq);
+/** @brief Turn the buzzer off. **/
+void buzzer_off(void); 
+
+/** @} **/ //end addtogroup
+
+#endif
+
Index: branches/wireless/code/projects/libdragonfly/lcd.h
===================================================================
--- branches/wireless/code/projects/libdragonfly/lcd.h	(nonexistent)
+++ branches/wireless/code/projects/libdragonfly/lcd.h	(revision 1493)
@@ -0,0 +1,61 @@
+/**
+ * Copyright (c) 2007 Colony Project
+ * 
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ * 
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ **/
+
+
+/**
+ * @file lcd.h
+ * @brief Contains definitions for dealing with the LCD screen.
+ * 
+ * Contains definitions and functions for dealing with the 
+ * LCD screen.
+ *
+ * @author Colony Project, CMU Robotics Club
+ **/
+
+#ifndef _LCD_H_
+#define _LCD_H_
+
+/**
+ * @addtogroup lcd
+ * @{
+ **/
+
+/** @brief Initialize the LCD screen **/
+void lcd_init(void);
+/** @brief Clear the LCD screen **/
+void lcd_clear_screen( void );
+/** @brief Print a char to the LCD screen **/
+void lcd_putc(char c);
+/** @brief Print a string to the LCD screen **/
+void lcd_puts(char *s);
+/** @brief Print an int to the LCD screen **/
+void lcd_puti(int value);
+/** @brief Set the current cursor position **/
+void lcd_gotoxy(int x, int y);
+
+/** @} **/
+
+#endif
+
Index: branches/wireless/code/projects/libdragonfly/battery.h
===================================================================
--- branches/wireless/code/projects/libdragonfly/battery.h	(nonexistent)
+++ branches/wireless/code/projects/libdragonfly/battery.h	(revision 1493)
@@ -0,0 +1,64 @@
+/**
+ * Copyright (c) 2007 Colony Project
+ * 
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ * 
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ **/
+
+
+/**
+ * @file battery.h
+ * @brief Definitions for checking battery voltage.
+ * 
+ * Contains definitions for checking the voltage of the 
+ * battery.
+ *
+ * @author Colony Project, CMU Robotics Club
+ **/
+
+#ifndef _BATTERY_H_
+#define _BATTERY_H_
+
+/**
+ * @addtogroup battery
+ * @{
+ **/
+
+/** @brief Normal battery voltage. (6 V) **/
+#define BATTERY_NORMALV 154
+/** @brief Charging battery voltage. (7 V) **/
+#define BATTERY_CHARINGV 179
+/** @brief Low battery voltage. ( < 6 V) **/
+#define BATTERY_LOWV 152
+
+/** @brief Read the battery voltage. **/
+int battery8(void);
+/** @brief Read the battery voltage in deciVolts. **/
+int battery(void);
+/** @brief Check if the battery is low. **/
+char battery_low(void);
+/** @brief Get an average battery voltage reading. **/
+int battery8_avg(int n_samples);
+
+/** @} **/ //end addtogroup
+
+#endif
+
Index: branches/wireless/code/projects/libdragonfly/ring_buffer.h
===================================================================
--- branches/wireless/code/projects/libdragonfly/ring_buffer.h	(nonexistent)
+++ branches/wireless/code/projects/libdragonfly/ring_buffer.h	(revision 1493)
@@ -0,0 +1,142 @@
+/**
+ * Copyright (c) 2007 Colony Project
+ * 
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ * 
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ **/
+
+
+/** @file ring_buffer.h
+ * @brief Ring Buffer
+ *
+ * Include macros to create a ring buffer. Originally written for 15-410.
+ * Modified for use in ATMega128 serial driver
+ *
+ * @author Cornell Wright (cgwright)
+ * @author Jason P. Winters (jpwinter)
+ *
+ **/
+
+#ifndef _RING_BUFFER_H
+#define _RING_BUFFER_H
+
+/** @brief Creates the struct for a new ring buffer. This just expands to a
+ *	structure definition and thus should be invoked in the global context.
+ *
+ *	@param struct_name Name of the ring buffer struct.
+ *
+ *	@param size The size of the buffer to create.
+ *
+ *	@param type The type of object that the queue is to hold.
+ *
+ *	@param ... Name or names of the instance or instances of the ring buffer(s)
+ *	to be created.
+ */
+#define RING_BUFFER_NEW(struct_name, size, type, ...)	\
+	struct struct_name {	\
+		type queue[size];	\
+		uint8_t start;			\
+		uint8_t end;			\
+		uint8_t buffer_size;			\
+	} __VA_ARGS__
+
+
+/** @brief Initializes the ring buffer, setting its size to the correct value
+ *
+ *	@param buf The ring buffer to initialize.
+ *
+ *  @param size The size of the ring buffer (in array elements)
+ */
+#define RING_BUFFER_INIT(buf, size) 			\
+	do {										\
+		(buf).buffer_size = size;				\
+	} while(0)
+
+
+/** @brief Sets the specified ring buffer to be empty.
+ *
+ *	@param buf The ring buffer to make empty.
+ */
+#define RING_BUFFER_CLEAR(buf)	\
+	do {						\
+		(buf).start = 0;		\
+		(buf).end = 0;			\
+	} while (0)
+
+/** @brief Returns true if the ring buffer specified is empty.
+ *
+ *	@param buf The buffer to check emptiness of.
+ */
+#define RING_BUFFER_EMPTY(buf) ((buf).start == (buf).end)
+
+
+/** @brief Returns true if the ring buffer specified is full.
+ *
+ *	@param buf The buffer to check fullness of.
+ */
+#define RING_BUFFER_FULL(buf)	\
+		(((buf).end + 1) % (buf).buffer_size == (buf).start)
+
+
+/** @brief Adds val to ring buffer buf. Note that val must be of the type
+ *	used in creating the ring buffer to prevent the compiler from spewing
+ *	confusing errors. Also, this assumes that the ring buffer is not full.
+ *
+ *	@param buf The ring buffer to add to.
+ *	@param val The value to add.
+ */
+#define RING_BUFFER_ADD(buf, val)		\
+	do {								\
+		(buf).queue[(buf).end] = val;	\
+		(buf).end = ((buf).end + 1) % (buf).buffer_size;	\
+	} while (0)
+
+
+/** @brief Removes the value at the head of the ring buffer and puts it in
+ *	val_ret. Note that val_ret must be the same type used in creating the ring
+ *	buffer to prevent the compiler from spewing confusing errors. Also, this
+ *	assumes that the ring buffer is not empty.
+ *
+ *	@param buf The ring buffer to remove from.
+ *	@param val_ret Where to put the value removed from the head of the ring
+ *	buffer.
+ */
+#define RING_BUFFER_REMOVE(buf, val_ret)	\
+	do {	\
+		(val_ret) = (buf).queue[(buf).start];	\
+		(buf).start = ((buf).start + 1) % (buf).buffer_size;	\
+	} while (0)
+
+/** @brief Checks the value at the head of the ring buffer without removing it
+ *  and puts it into val_ret. Note that val_ret must be the same type used in
+ *  creating the ring buffer to prevent the compiler from spewing confusing
+ *  errors. Also, this assumes that the ring buffer is not empty.
+ *
+ *  @param buf The ring buffer to check from
+ *  @param val_ret where to put the value checked from the head of the ring
+ */
+ #define RING_BUFFER_PEEK(buf, val_ret)  \
+  do { \
+    (val_ret) = (buf).queue[(buf).start]; \
+  } while(0)
+
+#endif /* _RING_BUFFER_H */
+
