Subversion Repositories Projects

Compare Revisions

Ignore whitespace Rev 270 → Rev 271

/bots/Wedgy/Delay.c
0,0 → 1,159
/****************************************************************************
*
* Delay.c
*
* Routines for waiting various amounts of time.
*
****************************************************************************/
 
#include "Config.h"
#include "Delay.h"
 
#include <avr/interrupt.h>
#include <avr/signal.h>
 
#define LOOPS_PER_US (CFG_CPU_CLOCK/4)
#define LOOPS_PER_MS (CFG_CPU_CLOCK/1000/4)
 
volatile uns16 gTickCount = 0;
 
/* spin for us microseconds */
void us_spin(unsigned short us)
{
if (!us)
return;
 
/* the inner loop takes 4 cycles per iteration */
__asm__ __volatile__ (
"1: \n"
" ldi r26, %3 \n"
" ldi r27, %2 \n"
"2: sbiw r26, 1 \n"
" brne 2b \n"
" sbiw %0, 1 \n"
" brne 1b \n"
: "=w" (us)
: "w" (us), "i" (LOOPS_PER_MS >> 8), "i" (0xff & LOOPS_PER_MS)
);
}
 
/* spin for ms milliseconds */
void ms_spin(unsigned short ms)
{
if (!ms)
return;
 
/* the inner loop takes 4 cycles per iteration */
__asm__ __volatile__ (
"1: \n"
" ldi r26, %3 \n"
" ldi r27, %2 \n"
"2: sbiw r26, 1 \n"
" brne 2b \n"
" sbiw %0, 1 \n"
" brne 1b \n"
: "=w" (ms)
: "w" (ms), "i" (LOOPS_PER_MS >> 8), "i" (0xff & LOOPS_PER_MS)
);
}
 
/***************************************************************************/
/**
* Delays for a multiple of 100 microseconds.
*
* @note This routine assumes a 20 MHz clock.
*/
 
void Delay100uSec
(
uns8 num100uSec /**< Number of 100 microsecond units to delay */
)
{
while ( num100uSec > 0 )
{
us_spin( 100 );
num100uSec--;
}
 
} // Delay100uSec
 
/***************************************************************************/
/**
* Delays for a multiple of 10 microseconds.
*
* @note This routine assumes a 20 MHz clock.
*/
 
void Delay10uSec
(
uns8 num10uSec /**< Number of 10 microsecond units to delay */
)
{
while ( num10uSec > 0 )
{
us_spin( 10 );
}
 
} // Delay10uSec
 
/***************************************************************************/
/**
* Timer 0 interrupt handler
*/
 
SIGNAL(SIG_OVERFLOW0) /* signal handler for tcnt0 overflow interrupt */
{
static int microTick = 0;
 
if ( ++microTick >= 10 )
{
microTick = 0;
 
gTickCount++;
}
 
// We want our timer tick to interrupt once a millisecond.
// If we use 8 MHz/64 then we get 125000 counts/second. So setting
// things up to overflow after 125 will give us 1000 overflows/second
//
// 256 - 125 = 131
 
TCNT0 = 131;
 
} // Timer 0 Overflow
 
/***************************************************************************/
/**
* InitTimer
*/
 
void InitTimer( void )
{
TCCR0 = ( 0 << CS02 ) | ( 1 << CS01 ) | ( 1 << CS00 ); // Divide by 64
TCNT0 = 0;
 
// Enable Timer 0 interrupt
 
timer_enable_int( BV( TOIE0 ));
 
sei();
 
} // InitTimer
 
/***************************************************************************/
/**
* Wait for Timer 0 to rollover
*/
 
void WaitForTimer0Rollover( void )
{
uns16 prevCount = gTickCount;
 
while ( gTickCount == prevCount )
{
;
}
 
} // WaitForTimer0Rollover
 
 
/bots/Wedgy/DebugKey.c
0,0 → 1,201
/****************************************************************************
*
* DebugKey.c
*
* Debug Processing of a character
*
****************************************************************************/
 
#define DEBUG 1
 
#include "DebugKey.h"
#include "Delay.h"
#include "Motor.h"
#include "Puts.h"
#include "Sensor.h"
#include "Uart.h"
 
#if DEBUG
 
uns8 gRunMotors;
uns8 gDoneDebugKey;
 
#define DEBUG_LEFT_MOTOR 1
#define DEBUG_RIGHT_MOTOR 2
#define DEBUG_BOTH_MOTORS 3
 
uns8 gDebugMotor;
uns8 gDebugCounter;
 
speed_t gSpeedMap[10] = { 0, -255, -192, -128, -64, 0, 64, 128, 192, 255 };
 
void DebugKey( void )
{
uns8 ch;
 
gRunMotors = 0;
gDoneDebugKey = 0;
gDebugCounter = 0;
puts( "\nDebugKey\n" );
while ( !gDoneDebugKey )
{
if ( UART_IsCharAvailable() )
{
ch = UART_GetChar();
switch ( ch )
{
case ' ':
{
puts( "Go\n" );
gDoneDebugKey = 1;
break;
}
case '.':
{
uns8 maxRamp = 1 << RAMP_SHIFT;
if ( gRampDelta < maxRamp )
{
gRampDelta <<= 1;
}
puts( "RampDelta = " );
putu8( gRampDelta );
puts( "\n" );
break;
}
case ',':
{
if ( gRampDelta > 1 )
{
gRampDelta >>= 1;
}
puts( "RampDelta = " );
putu8( gRampDelta );
puts( "\n" );
break;
}
case 'b':
{
putc( 'B' );
gDebugMotor = DEBUG_BOTH_MOTORS;
break;
}
case 'c': // Calibrate Servos
{
puts( "Calibrate Servos\n" );
gRunMotors = 1;
gSpeedL = SPEED_OFF;
gSpeedR = SPEED_OFF;
break;
}
case 'l':
{
putc( 'L' );
gDebugMotor = DEBUG_LEFT_MOTOR;
break;
}
case 'r':
{
putc( 'R' );
gDebugMotor = DEBUG_RIGHT_MOTOR;
break;
}
case '0':
{
putc( ch );
gRunMotors = 0;
gSpeedL = SPEED_OFF;
gSpeedR = SPEED_OFF;
break;
}
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
{
putc( ch );
gRunMotors = 1;
if ( gDebugMotor & DEBUG_LEFT_MOTOR )
{
gSpeedL = gSpeedMap[( ch - '0' )];
}
if ( gDebugMotor & DEBUG_RIGHT_MOTOR )
{
gSpeedR = gSpeedMap[( ch - '0' )];
}
break;
}
}
}
 
ReadSensors();
if (( gDebugCounter & 0x0F ) == 0 )
{
gDeferredNewline = 0;
puts( "\rL[ " );
putu8( gLineL );
puts( " " );
putu8( gLineR );
puts( " ]R " );
puts( " EL: " );
putu8( gEyeL );
puts( " ER: " );
putu8( gEyeR );
 
#if 0
puts( " IR: " );
putu8( gIrDetected );
puts( " (" );
putu8( gDetectCount );
puts( ")"
#endif
puts( " SL: " );
putu8( gSpeedL );
puts( " SR: " );
putu8( gSpeedR );
gDeferredNewline = 1;
}
if ( gRunMotors )
{
PulseMotors();
}
WaitForTimer0Rollover();
gDebugCounter++;
}
 
} // DebugKey
 
#else
 
void DebugKeyDummy( void )
{
;
}
 
#endif // DEBUG
/bots/Wedgy/MiniSumo.c
0,0 → 1,516
/****************************************************************************
*
* MiniSumo.c
*
* Mini Sumo code for Wedgy
*
****************************************************************************/
 
#include <avr/io.h>
 
#include "a2d.h"
#include "Avoid.h"
#include "Debug.h"
#include "DebugKey.h"
#include "Delay.h"
#include "Motor.h"
#include "Puts.h"
#include "Sensor.h"
#include "Uart.h"
 
#define EYE_MIN_SIGNAL 35 // Normal use
#define EYE_MIN_SIGNAL2 65 // Used for shortly after we hit the line
#define EYE_MIN_DIFF 10
 
#define COUNTER_TURN_COUNT 400
#define COUNTER_SPIN_COUNT 0 // 0 - 50 = arc, > 50 = SPIN
 
// It takes about 6/10 of second to spin, so we'll ignore about 1/3 of a circle.
 
#define COUNTER_EYE_RESET_COUNT ( COUNTER_SPIN_COUNT + 25 )
 
#define COUNTER_STRAIGHT_COUNT 400 // Start going straight
 
uns16 gLineAvg;
uns8 gLineThresh;
 
uns8 gEyeMinSignal;
uns8 gEyeState;
uns8 gPrevEyeState;
 
uns8 gHuntDir;
uns16 gHuntCounter;
 
/***************************************************************************/
/**
* Main program for the Mini Sumo
*/
 
int main( void )
{
uns8 lineSide;
int16 eyeDiff;
uns8 i;
uns8 sec;
 
DBG( uns8 huntState; )
DBG( uns8 prevHuntState; )
 
// Initialization
 
InitializeA2D();
UART_Init();
 
#if DEBUG
UART_PutStr( "****************************\r\n" );
UART_PutStr( "** **\r\n" );
UART_PutStr( "** Wedgy MiniSumo Program **\r\n" );
UART_PutStr( "** **\r\n" );
UART_PutStr( "****************************\r\n\r\n" );
#endif
 
InitTimer();
InitMotors();
 
//puts( "Testing\n" );
 
gDeferredNewline = 0;
 
// Take average reading to determine threashold for line detection.
 
gLineR = a2d( LINE_R );
// gLineC = a2d( LINE_C );
gLineL = a2d( LINE_L );
 
#if 0
gLineAvg = gLineR;
gLineAvg += gLineC;
gLineAvg += gLineL;
gLineAvg *= 1; // Take 1/3 of average
gLineAvg /= 9;
gLineAvg /= 2;
gLineThresh = (uns8)gLineAvg;
#else
// With the 680 ohm on the IR and 18K pullup, I get 255 for black and
// around 128 for white (lower if it's really bright).
 
gLineThresh = ( 255 + 128 ) / 2;
 
#endif
 
//gLineThresh = 12; // Special hack for Robothon
 
DBG( puts( "LineThresh: " ); )
DBG( putu8( gLineThresh ); )
DBG( puts( "\n" ); )
 
gHuntCounter = 0;
 
gEyeState = 0;
gPrevEyeState = 0;
gEyeMinSignal = EYE_MIN_SIGNAL;
 
DBG( huntState = 0; )
DBG( prevHuntState = 0; )
 
gHuntDir = HUNT_RIGHT;
 
// Delay for 5 seconds
 
DDRB |= BV( 4 ) | BV( 6 );
 
for ( sec = 0; sec < 5; sec++ )
{
// Turn LED on
 
PORTB &= ~( BV( 4 ) | BV( 6 ));
 
for ( i = 0; i < 25; i++ )
{
WaitForTimer0Rollover();
}
 
// Turn LED off
 
PORTB |= ( BV( 4 ) | BV( 6 ));
 
for ( i = 0; i < 75; i++ )
{
WaitForTimer0Rollover();
}
}
// Turn LED on
PORTB &= ~( BV( 4 ) | BV( 6 ));
 
while ( 1 )
{
// Wait for 100 Hz timer
 
WaitForTimer0Rollover();
gHuntCounter++;
 
#if DEBUG || 1
if ( UART_IsCharAvailable() )
{
UART_GetChar();
#if 1
DebugKey();
#else
/*
* A key was pressed. pause and wait for another
*/
 
puts( "Paused\n" );
 
while ( !UART_IsCharAvailable() ) ;
 
puts( "Go\n" );
UART_GetChar();
#endif
}
#endif
 
ReadSensors();
 
#if USE_TILT
if ( gTiltState != 0 )
{
AvoidTilt();
}
#endif
 
#if 1
// Clamp distances which are more than across the ring
//if ( !gIrDetected )
{
if ( gEyeL < gEyeMinSignal )
{
gEyeL = 0;
}
if ( gEyeR < gEyeMinSignal )
{
gEyeR = 0;
}
}
#endif
 
#if DEBUG
if (( gHuntCounter & 0x0F ) == 0 )
{
gDeferredNewline = 0;
 
puts( "\rLL: " );
putu8( gLineL );
puts( " LR: " );
putu8( gLineR );
 
puts( " EL: " );
putu8( gEyeL );
puts( " ER: " );
putu8( gEyeR );
 
#if 0
puts( " IR: " );
putu8( gIrDetected );
puts( " (" );
putu8( gDetectCount );
puts( ")" );
#endif
puts( " SL: " );
putu8( gSpeedL );
puts( " SR: " );
putu8( gSpeedR );
#if USE_TILT
puts( " TX: " );
putu8( gTiltX );
puts( " TY: " );
putu8( gTiltY );
#endif
puts( " C: " );
putu16( gHuntCounter );
 
gDeferredNewline = 1;
}
#endif
 
gSpeedL = SPEED_FWD;
gSpeedR = SPEED_FWD;
 
//if ( !gIrDetected )
{
// Check line sensors
 
lineSide = 0;
 
if ( gLineR < gLineThresh )
{
DBG( puts( "LineR detected (" ); )
DBG( putu8( gLineR ); )
DBG( puts( ") C:" ); )
DBG( putu16( gHuntCounter ); )
DBG( puts( "\n" ); )
lineSide |= LINE_DETECTED_RIGHT;
//if ( !gIrDetected )
{
// Set the hunt direction to be left so that we hunt "away" from the line.
 
gHuntDir = HUNT_LEFT;
}
}
if ( gLineL < gLineThresh )
{
DBG( puts( "LineL detected (" ); )
DBG( putu8( gLineL ); )
DBG( puts( ") C:" ); )
DBG( putu16( gHuntCounter ); )
DBG( puts( "\n" ); )
 
lineSide |= LINE_DETECTED_LEFT;
//if ( !gIrDetected )
{
// Set the hunt direction to be right so that we hunt "away" from the line.
 
gHuntDir = HUNT_RIGHT;
}
}
 
if ( lineSide != 0 )
{
AvoidEdge( lineSide );
 
// We set the Hunt Counter to 50 so that it will spin as opposed
// to arc.
 
gHuntCounter = COUNTER_SPIN_COUNT;
 
// Raise the eye threshold since we hit the line. Otherwise, if
// we've locked on to something outside the ring we'll just
// keep running towards it.
 
gEyeMinSignal = EYE_MIN_SIGNAL2;
}
}
 
// Bigger number = closer distance
 
gEyeState = 0;
 
#if 1
if ( gEyeL >= gEyeMinSignal )
{
// We have some object in the left
 
gEyeState |= EYE_DETECTED_LEFT;
}
if ( gEyeR >= gEyeMinSignal )
{
// We have some object in the right
 
gEyeState |= EYE_DETECTED_RIGHT;
}
#endif
 
eyeDiff = gEyeL - gEyeR;
if ( eyeDiff > EYE_MIN_DIFF )
{
// Object closer in left than in right. This has preference
// over mere "object" detected, so we blank out the right signal.
 
gEyeState = EYE_DETECTED_LEFT;
}
else
{
eyeDiff = gEyeR - gEyeL;
if ( eyeDiff > EYE_MIN_DIFF )
{
// Object closer in right than in left. This has preference
// over mere "object" detected, so we blank out the left signal.
 
gEyeState = EYE_DETECTED_RIGHT;
}
}
 
if ( gEyeState == EYE_DETECTED_LEFT )
{
// Object detected on the left side only. Turn towards it
 
//gSpeedL = SPEED_BWD_MED;
//if ( gHuntDir != HUNT_LEFT )
{
//DBG( puts( "Resetting gHuntCounter L\n" ); )
gHuntCounter = 0;
}
gHuntDir = HUNT_LEFT;
}
else
if ( gEyeState == EYE_DETECTED_RIGHT )
{
// Object detected on the right side only. Turn towards it
 
//gSpeedR = SPEED_BWD_MED;
//if ( gHuntDir != HUNT_RIGHT )
{
//DBG( puts( "Resetting gHuntCounter R\n" ); )
gHuntCounter = 0;
}
gHuntDir = HUNT_RIGHT;
}
else
//if (( gEyeState == 0 ) && !gIrDetected )
if ( gEyeState == 0 )
{
// No object detected and the other guy isn't close, so go into
// hunt mode.
 
if ( gHuntCounter < COUNTER_TURN_COUNT )
{
if ( gHuntDir == HUNT_LEFT )
{
DBG( huntState = HUNT_STATE_SPIN_LEFT; )
 
// Spin Left
 
if ( gHuntCounter < COUNTER_SPIN_COUNT )
{
// Arc forward turning left
 
gSpeedL = SPEED_FWD_MED;
}
else
{
// Spin to the left
 
gSpeedL = SPEED_BWD;
}
gSpeedR = SPEED_FWD;
}
else
{
DBG( huntState = HUNT_STATE_SPIN_RIGHT; )
 
// Spin Right
 
gSpeedL = SPEED_FWD;
if ( gHuntCounter < COUNTER_SPIN_COUNT )
{
// Arc forward turning right
 
gSpeedR = SPEED_FWD_MED;
}
else
{
// Spin right
 
gSpeedR = SPEED_BWD;
}
}
}
else
if ( gHuntCounter < COUNTER_STRAIGHT_COUNT )
{
DBG( huntState = HUNT_STATE_GO_STRAIGHT; )
 
// Go forward
 
gSpeedL = SPEED_FWD;
gSpeedR = SPEED_FWD;
}
else
{
// Counter wrapped and we still didn't find anybody.
// Swap hunt direction so we don't get "stuck in a corner"
 
gHuntCounter = 0;
gHuntDir = SWAP_HUNT_DIR( gHuntDir );
}
 
if ( gHuntCounter >= COUNTER_EYE_RESET_COUNT )
{
gEyeMinSignal = EYE_MIN_SIGNAL;
}
}
#if DEBUG
if ( gEyeState != gPrevEyeState )
{
puts( "EyeState changed: " );
if (( gEyeState & EYE_DETECTED_LEFT ) != 0 )
{
putc( 'L' );
}
else
{
putc( ' ' );
}
if (( gEyeState & EYE_DETECTED_RIGHT ) != 0 )
{
putc( 'R' );
}
else
{
putc( ' ' );
}
puts( " EyeL:" );
putu8( gEyeL );
puts( " EyeR:" );
putu8( gEyeR );
puts( " C: " );
putu16( gHuntCounter );
puts( "\n" );
gPrevEyeState = gEyeState;
}
if ( huntState != prevHuntState )
{
if ( huntState != 0 )
{
puts( "Hunt: " );
 
switch ( huntState )
{
case HUNT_STATE_SPIN_LEFT:
{
puts( "Spin Left" );
break;
}
 
case HUNT_STATE_SPIN_RIGHT:
{
puts( "Spin Right" );
break;
}
 
case HUNT_STATE_GO_STRAIGHT:
{
puts( "Go Forward" );
break;
}
 
default:
{
puts( "*** Unknown ***" );
break;
}
}
 
puts( " C: ");
putu16( gHuntCounter );
puts( "\n" );
}
prevHuntState = huntState;
}
#endif
PulseMotors();
}
 
return 0;
 
} // main
 
/** @} */
 
/bots/Wedgy/Motor.c
0,0 → 1,221
/****************************************************************************
*
* Motor.c
*
* Motor Control Code
*
****************************************************************************/
 
// ---- Include Files -------------------------------------------------------
 
#include <avr/io.h>
 
#include "Motor.h"
#include "Puts.h"
#include "Sensor.h"
 
// ---- Public Variables ----------------------------------------------------
 
speed_t gSpeedL = SPEED_OFF;
speed_t gSpeedR = SPEED_OFF;
speed_t gPrevSpeedL = SPEED_OFF + 1; // Anything different from initial gSpeedL
speed_t gPrevSpeedR = SPEED_OFF + 1;
 
#define DO_RAMP 0
 
speed_t gRampDelta;
 
#if DO_RAMP
 
#define RAMP_DELTA gRampDelta
 
speed_t gActualSpeedFixedL;
speed_t gActualSpeedFixedR;
 
#endif // DO_RAMP
 
// ---- Private Constants and Types -----------------------------------------
// ---- Private Variables ---------------------------------------------------
 
// ---- Private Function Prototypes -----------------------------------------
// ---- Functions -----------------------------------------------------------
 
#define SPEED_OFF_FIXED ( SPEED_OFF << RAMP_SHIFT )
 
#if DO_RAMP
uns8 AdjustSpeed( uns8 desiredSpeedFixed, uns8 actualSpeedFixed )
{
if (( desiredSpeedFixed < actualSpeedFixed ) && ( desiredSpeedFixed >= SPEED_OFF_FIXED ))
{
// The speed is being reduced
 
return desiredSpeedFixed;
}
 
if (( desiredSpeedFixed > actualSpeedFixed ) && ( desiredSpeedFixed <= SPEED_OFF_FIXED ))
{
// The speed is being reduced
 
return desiredSpeedFixed;
}
 
if ( desiredSpeedFixed > actualSpeedFixed )
{
actualSpeedFixed += RAMP_DELTA;
}
else
if ( desiredSpeedFixed < actualSpeedFixed )
{
actualSpeedFixed -= RAMP_DELTA;
}
 
return actualSpeedFixed;
}
#endif
 
extern void InitMotors( void )
{
gPrevSpeedL = 0;
gPrevSpeedR = 0;
gRampDelta = 2;
 
#if DO_RAMP
gActualSpeedFixedL = 15 << RAMP_SHIFT;
gActualSpeedFixedR = 15 << RAMP_SHIFT;
#endif
 
// 8 bit PWM yields divide by 255
 
#define CHAN_A_NON_INVERTING_PWM ( 1 << COM1A1 ) | ( 0 << COM1A0 )
#define CHAN_B_NON_INVERTING_PWM ( 1 << COM1B1 ) | ( 0 << COM1B0 )
#define PWM_8_BIT_MODE ( 0 << WGM11 ) | ( 1 << WGM10 )
 
TCCR1A = CHAN_A_NON_INVERTING_PWM | CHAN_B_NON_INVERTING_PWM | PWM_8_BIT_MODE;
 
#define T1_PRESCALAR_8 ( 0 << CS22 ) | ( 1 << CS21 ) | ( 0 << CS20 )
 
TCCR1B = T1_PRESCALAR_8; // Divide by 8 prescalar
 
OCR1A = 0;
OCR1B = 0;
 
// In order to use PortC pins 2, 3, 4, and 5 the JTAG needs to be disabled.
// So, we set the JTD bit in MCUCSR to disable the JTAG.
 
MCUCSR |= ( 1 << JTD );
 
// Set the 4 motor control pins as outputs
// Port C pin 4, is the Right Motor Direction
// Port C pin 3, is the Left Motor Direction
// Port D pin 5 (OC1A) is the Right Motor PWM
// Port D pin 4 (OC1B) is the Left Motor PWM
 
PORTC |= ( ( 1 << PC3 ) | ( 1 << PC4 ));
 
DDRC |= ( ( 1 << DDC3 ) | ( 1 << DDC4 ));
DDRD |= ( ( 1 << DDD4 ) | ( 1 << DDD5 ));
 
PORTC &= ( ( 1 << PC3 ) | ( 1 << PC4 ));
 
PulseMotors();
}
 
/****************************************************************************
*
* Sets the motor speed of both motors.
*/
 
extern void PulseMotors( void )
{
speed_t pulseL;
speed_t pulseR;
 
#if DO_RAMP
 
speed_t gActualSpeedL;
speed_t gActualSpeedR;
 
speed_t gDesiredSpeedFixedL = gSpeedL << RAMP_SHIFT;
speed_t gDesiredSpeedFixedR = gSpeedR << RAMP_SHIFT;
 
gActualSpeedFixedL = AdjustSpeed( gDesiredSpeedFixedL, gActualSpeedFixedL );
gActualSpeedFixedR = AdjustSpeed( gDesiredSpeedFixedR, gActualSpeedFixedR );
 
gActualSpeedL = ( gActualSpeedFixedL >> RAMP_SHIFT );
gActualSpeedR = ( gActualSpeedFixedR >> RAMP_SHIFT );
 
#else
 
#define gActualSpeedL gSpeedL
#define gActualSpeedR gSpeedR
 
#endif
 
// We need to run the right motor in reverse, so we
// do the adjustment here.
//
// The way I wired up the motors, +ve goes backwards and -ve goes
// forwards, so we just negate things here.
pulseL = -gActualSpeedL;
pulseR = -gActualSpeedR;
//puts( "PulseMotors called\n" );
#if DEBUG
if (( gSpeedL != gPrevSpeedL ) || ( gSpeedR != gPrevSpeedR ))
{
puts( "PulseMotors L:" );
putu8( gSpeedL );
puts( " R:" );
putu8( gSpeedR );
puts( " C: " );
putu16( gHuntCounter );
puts( "\n" );
gPrevSpeedL = gSpeedL;
gPrevSpeedR = gSpeedR;
}
#endif
 
{
static speed_t prevPulseL = SPEED_OFF + 1;
static speed_t prevPulseR = SPEED_OFF + 1;
 
if ( pulseL != prevPulseL )
{
if ( pulseL >= 0 )
{
PORTC &= ~( 1 << PC3 ); // Clear Port-C.3
TCCR1A &= ~( 1 << COM1B0 ); // Normal PWM
OCR1B = pulseL;
}
else
{
PORTC |= ( 1 << PC3 ); // Set Port-C.3
TCCR1A |= ( 1 << COM1B0 ); // Inverted PWM
OCR1B = -pulseL;
}
prevPulseL = pulseL;
}
 
if ( pulseR != prevPulseR )
{
if ( pulseR >= 0 )
{
PORTC &= ~( 1 << PC4 ); // Clear Port-C.4
TCCR1A &= ~( 1 << COM1A0 ); // Normal PWM
OCR1A = pulseR;
}
else
{
PORTC |= ( 1 << PC4 ); // Set Port-C.4
TCCR1A |= ( 1 << COM1A0 ); // Inverted PWM
OCR1A = -pulseR;
}
prevPulseR = pulseR;
}
}
 
} // PulseMotors
 
/bots/Wedgy/Puts.h
0,0 → 1,32
/****************************************************************************
*
* Puts.h
*
* Routines for outputting strings.
*
****************************************************************************/
 
#if !defined( PUTS_H )
#define PUTS_H
 
#if !defined( TYPES_H )
# include "Types.h"
#endif
 
#if !defined( DEBUG_H )
# include "Debug.h"
#endif
 
uns8 gDeferredNewline;
 
#define putc dh_putc
#define puts dh_puts
 
void dh_putc( char ch );
void dh_puts( const char *s );
void putdigit( uns8 num );
void putu8( uns8 num );
void putu16( uns16 num );
 
#endif // PUTS_H
 
/bots/Wedgy/Avoid.c
0,0 → 1,144
/****************************************************************************
*
* Avoid.c
*
* AvoidEdge and AvoidTilt
*
****************************************************************************/
 
// ---- Include Files -------------------------------------------------------
 
#include "Avoid.h"
#include "Debug.h"
#include "Delay.h"
#include "Motor.h"
#include "Sensor.h"
#include "Puts.h"
 
// ---- Private Constants and Types -----------------------------------------
// ---- Private Variables ---------------------------------------------------
// ---- Private Function Prototypes -----------------------------------------
// ---- Functions -----------------------------------------------------------
 
/***************************************************************************/
/**
* AvoidEdge
*
* Backs away from the edge
*/
 
extern void AvoidEdge( uns8 lineSide )
{
uns8 i;
 
// Back up a bit
 
DBG( puts( "Avoid Edge: Backing up\n" ); )
 
gSpeedL = SPEED_BWD;
gSpeedR = SPEED_BWD;
 
for ( i = 0; i < 60; i++ )
{
PulseMotors();
WaitForTimer0Rollover();
}
 
DBG( puts( "Avoid Edge: Turning\n" ); )
// Turn away from the line
 
if (( lineSide & LINE_DETECTED_LEFT ) != 0 )
{
gSpeedL = SPEED_FWD;
}
else
{
gSpeedR = SPEED_FWD;
}
 
for ( i = 0; i < 60; i++ )
{
PulseMotors();
WaitForTimer0Rollover();
}
 
} // AvoidEdge
 
#if 0
/****************************************************************************
*
* AvoidTilt
*
* Backs away from being tilted
*/
 
extern void AvoidTilt( void )
{
if (( gTiltState & TILTED_LEFT ) != 0 )
{
DBG( puts( "Tilted Left\n" ); )
 
gSpeedL = SPEED_BWD;
gSpeedR = SPEED_FWD;
}
else
if (( gTiltState & TILTED_RIGHT ) != 0 )
{
DBG( puts( "Tilted Right\n" ); )
gSpeedL = SPEED_FWD;
gSpeedR = SPEED_BWD;
}
else
if (( gTiltState & TILTED_BACK ) != 0 )
{
DBG( puts( "Tilted Back\n" ); )
 
if ( gHuntDir == HUNT_RIGHT )
{
// Target is probably to the right. Back away
// to the right.
 
gSpeedL = SPEED_BWD;
gSpeedR = SPEED_FWD;
}
else
{
// Target is probably to the left. Back away
// to the left.
 
gSpeedL = SPEED_FWD;
gSpeedR = SPEED_BWD;
}
}
else
{
DBG( puts( "Tilt Unknown\n" ); )
gSpeedL = SPEED_FWD;
gSpeedR = SPEED_BWD;
}
 
DBG( puts( "AvoidTilt: Turning away\n" ); )
 
for ( i = 0; i < 30; i++ )
{
PulseMotors();
WaitForTimer0Rollover();
}
 
DBG( puts( "AvoidTilt: Backing up\n" ); )
 
gSpeedL = SPEED_BWD;
gSpeedR = SPEED_BWD;
for ( i = 0; i < 30; i++ )
{
PulseMotors();
WaitForTimer0Rollover();
}
 
} // AvoidTilt
 
#endif
/bots/Wedgy/Delay.h
0,0 → 1,25
/****************************************************************************
*
* Delay.h
*
* Routines for waiting various amounts of time.
*
****************************************************************************/
 
#if !defined( DELAY_H )
#define DELAY_H
 
#if !defined( TYPES_H )
# include "Types.h"
#endif
 
extern volatile uns16 gTickCount;
 
void Delay100uSec( uns8 num100uSec );
void Delay10uSec( uns8 num10uSec );
 
void InitTimer( void );
void WaitForTimer0Rollover( void );
 
#endif // DELAY_H
 
/bots/Wedgy/DebugKey.h
0,0 → 1,21
/****************************************************************************
*
* DebugKey.h
*
* Debug Processing of a character
*
****************************************************************************/
 
#if !defined( DEBUGKEY_H )
#define DEBUGKEY_H
 
#if !defined( TYPES_H )
# include "Types.h"
#endif
 
extern uns8 gDebugCounter;
 
void DebugKey( void );
 
#endif /* DEBUGKEY_H */
 
/bots/Wedgy/Motor.h
0,0 → 1,42
/****************************************************************************
*
* Motor.h
*
* Motor Control Code
*
****************************************************************************/
 
#if !defined( MOTOR_H )
#define MOTOR_H
 
#if !defined( TYPES_H )
# include "Types.h"
#endif
 
// Motor Speeds are defined as a percentage
 
#define SPEED_BWD -255
#define SPEED_BWD_MED -150
#define SPEED_OFF 0
#define SPEED_FWD_MED 150
#define SPEED_FWD 255
 
#define SPEED_BWD_SPIN -150
#define SPEED_FWD_SPIN 150
 
typedef int16 speed_t;
 
extern speed_t gSpeedL;
extern speed_t gSpeedR;
extern speed_t gPrevSpeedL;
extern speed_t gPrevSpeedR;
extern speed_t gRampDelta;
 
#define RAMP_SHIFT 3
 
 
void InitMotors( void );
void PulseMotors( void );
 
#endif // MOTOR_H
 
/bots/Wedgy/a2d.c
0,0 → 1,46
/****************************************************************************
*
* a2d.c
*
****************************************************************************/
 
#include <avr/io.h>
#include "a2d.h"
 
/***************************************************************************/
/**
* Initializes the A2D
*/
 
void InitializeA2D( void )
{
ADCSR = BV(ADEN) | BV(ADSC) | BV(ADPS1) | BV(ADPS2);
while (ADCSR & BV(ADSC));
 
} // InitializeA2D
 
/***************************************************************************/
/**
* Reads an A/D pin
*/
 
uns8 a2d( uns8 Channel )
{
#define ADLAR 5 // Give Left Adjusted result
 
// Select the channel
ADMUX = Channel | BV( ADLAR );
 
// Start the conversion
ADCSR = ADCSR | BV(ADSC);
 
// Wait for it to complete
while (ADCSR & BV(ADSC));
 
// We only need the top 8 bits (left-adjusted)
return ADCH;
 
} // a2d
 
 
/bots/Wedgy/Avoid.h
0,0 → 1,27
/****************************************************************************
*
* Avoid.h
*
* AvoidEdge and AvoidTilt
*
****************************************************************************/
 
#if !defined( AVOID_H )
#define AVOID_H
 
#if !defined( TYPES_H )
# include "Types.h"
#endif
 
#define LINE_DETECTED_LEFT 0x01
#define LINE_DETECTED_RIGHT 0x02
 
#define HUNT_LEFT 1
#define HUNT_RIGHT 2
#define SWAP_HUNT_DIR(dir) (3 - (dir))
 
void AvoidEdge( uns8 lineSide );
void AvoidTilt( void );
 
#endif // AVOID_H
 
/bots/Wedgy/Sensor.c
0,0 → 1,61
/****************************************************************************
*
* Sensor.c
*
* ReadSensors routine.
*
****************************************************************************/
 
// ---- Include Files -------------------------------------------------------
 
#include "a2d.h"
#include "Puts.h"
#include "Sensor.h"
 
// ---- Private Constants and Types -----------------------------------------
 
// ---- Private Variables ---------------------------------------------------
 
uns8 gLineL;
uns8 gLineR;
 
uns16 gEyeL;
uns16 gEyeR;
 
// ---- Private Function Prototypes -----------------------------------------
// ---- Functions -----------------------------------------------------------
 
/***************************************************************************
*
* ReadSensors
*
* Reads the various sensors
*/
 
extern void ReadSensors( void )
{
// Read the line sensors
 
gLineR = a2d( LINE_R );
gLineL = a2d( LINE_L );
 
// Read the Eye sensors
 
gEyeR = a2d( EYE_R );
gEyeL = a2d( EYE_L );
 
#if 0
// puts( "ReadSensors called\n" );
puts( "LineL: " );
putu8( gLineL );
puts( " LineR: " );
putu8( gLineR );
puts( " EyeL: " );
putu8( gEyeL);
puts( " EyeR: " );
putu8( gEyeR );
puts( "\n" );
#endif
 
} // ReadSensors
 
/bots/Wedgy/Types.h
0,0 → 1,19
/****************************************************************************
*
* Types.h
*
****************************************************************************/
 
#if !defined( TYPES_H )
#define TYPES_H
 
#if !defined( __INTTYPES_H_ )
#include <inttypes.h>
#endif
 
typedef int8_t int8;
typedef int16_t int16;
typedef uint8_t uns8;
typedef uint16_t uns16;
 
#endif // TYPES_H
/bots/Wedgy/Config.h
0,0 → 1,16
/****************************************************************************
*
* Config.h
*
* Contains configuration information.
*
****************************************************************************/
 
#if !defined( CONFIG_H )
#define CONFIG_H
 
#define CFG_CPU_CLOCK 8000000
 
#endif // CONFIG_H
 
 
/bots/Wedgy/arc_10.h
0,0 → 1,54
#define ENABLE_BIT_DEFINITIONS
#include <avr/io.h>
#define CPUCLK = 8000000
#define BAUD = 19200
 
// ADC Channels are just numbers passed to GetADC()
 
enum {
left_sharp = 0,
left_floor = 1,
center_floor = 2,
right_floor = 3,
right_sharp = 7,
motor_forward = 0,
motor_reverse = 1
};
 
// Port B
 
#define prog_led 4 // Output
#define option_a 6 // Input
#define option_b 7 // Input
 
// Port C
 
#define right_motor_dir 4 // Output
#define right_motor_pwm Pwm1a
#define right_encoder_b 5 // Input
#define right_servo_out 5 // Output
#define left_motor_dir 3 // Input
#define left_motor_pwm Pwm1b
#define left_encoder_b 2 // Input
#define left_servo_out 2 // Output
#define SDA 1 // I2C
#define SCL 0 // I2C
 
// Port D
 
#define right_encoder_a 2 // Input INT0
#define left_encoder_a 3 // Input INT1
 
// Library routines
//
// These routines pass parameters by value since a typical situation is to
// pass constants (e.g. 1/2 speed forward, servo position X) otherwise a global
// would have to be declared to hold the value and then the routine called.
 
void right_servo(unsigned);
void left_servo(unsigned);
void set_left_motor_pwm(int);
void set_right_motor_pwm(int);
void initialize_pwm(void);
int getadc(char);
void waitms(int);
/bots/Wedgy/Uart.c
0,0 → 1,114
/****************************************************************************
*
* uart.c
*
* Code for abstracting the UART interface (uses polled I/O)
*
****************************************************************************/
 
#include "Config.h"
#include "Uart.h"
#include <avr/io.h>
 
#define BAUD_RATE 38400
//#define BAUD_UBRR (( CFG_CPU_CLOCK / ( 16 * BAUD_RATE )) - 1 )
 
#define BAUD_UBRR 12
 
/***************************************************************************/
/**
* Initializes the UART
*/
 
void UART_Init( void )
{
// Set the baud rate
// UBRR = ( Fosc / ( 16 * baud )) - 1
//UBRRH = BAUD_UBRR >> 8;
//UBRRL = BAUD_UBRR & 0x00FF;
 
UBRRH = 0;
UBRRL = 12;
 
// Enable the Transmitter and Receiver
 
UCSRB = ( 1 << RXEN ) | ( 1 << TXEN );
 
// Set to 8-N-1
 
#define DATA_BIT_8 ( 1 << UCSZ1 ) | ( 1 << UCSZ0 )
#define PARITY_NONE ( 0 << UPM1 ) | ( 0 << UPM0 )
#define STOP_BIT_1 ( 1 << USBS )
 
UCSRC = ( 1 << URSEL ) | DATA_BIT_8 | PARITY_NONE | STOP_BIT_1;
 
} // UART_Init
 
/***************************************************************************/
/**
* Reads a character from the UART (waits until a character is available)
*/
 
uns8 UART_GetChar( void )
{
// Wait until chcracter is available
 
while ( !UART_IsCharAvailable() )
{
;
}
 
// Read it and return it
 
return UDR;
 
} // UART_GetChar
 
/***************************************************************************/
/**
* Writes a character to the UART
*/
 
void UART_PutChar( uns8 ch )
{
// Wait for empty transmit buffer
 
while (( UCSRA & ( 1 << UDRE )) == 0 )
{
;
}
 
// Send the character
 
UDR = ch;
 
} // UART_PutChar
 
/***************************************************************************/
/**
* Writes a string to the uart.
*/
 
void UART_PutStr( const char *str )
{
while ( *str != '\0' )
{
UART_PutChar( *str );
 
str++;
}
 
} // UART_PutStr
 
/***************************************************************************/
/**
* Determines if a character is available in the receive buffer.
*/
 
int UART_IsCharAvailable( void )
{
return ( UCSRA & ( 1 << RXC )) != 0;
 
} // UART_IsCharAvailable
 
/bots/Wedgy/a2d.h
0,0 → 1,18
/****************************************************************************
*
* a2d.h
*
****************************************************************************/
 
#if !defined( A2D_H )
#define A2D_H
 
#if !defined( TYPES_H )
# include "Types.h"
#endif
 
void InitializeA2D( void );
uns8 a2d( uns8 pin );
 
#endif /* A2D_H */
 
/bots/Wedgy/Sensor.h
0,0 → 1,55
/****************************************************************************
*
* Sensor.h
*
* externs for senosr values
*
****************************************************************************/
 
#if !defined( SENSOR_H )
#define SENSOR_H
 
// ADC channel selection codes
 
#define EYE_R 0 // ADC0
#define LINE_R 1
#define LINE_C 2
#define LINE_L 3
#define ADC_4 4
#define ADC_5 5
#define ADC_6 6
#define EYE_L 7
 
#define HUNT_STATE_SPIN_LEFT 1
#define HUNT_STATE_SPIN_RIGHT 2
#define HUNT_STATE_GO_STRAIGHT 3
 
extern uns8 gLineL;
extern uns8 gLineR;
 
extern uns16 gLineAvg;
extern uns8 gLineThresh;
 
extern uns16 gEyeL;
extern uns16 gEyeR;
 
#define EYE_DETECTED_LEFT 0x01
#define EYE_DETECTED_RIGHT 0x02
 
extern uns8 gEyeState;
extern uns8 gPrevEyeState;
 
extern uns8 gHuntDir;
extern uns16 gHuntCounter;
 
#define HUNT_SELECT_LEFT 0
#define HUNT_SELECT_RIGHT 1
 
#define PGM_SELECT_LINE_FOLLOW 0
#define PGM_SELECT_SUMO 1
 
 
void ReadSensors( void );
 
#endif // SENSOR_H
 
/bots/Wedgy/Uart.h
0,0 → 1,22
/****************************************************************************
*
* uart.h
*
* Code for abstracting the UART interface (uses polled I/O)
*
****************************************************************************/
 
#if !defined( UART_H )
#define UART_H
 
#if !defined( TYPES_H )
# include "Types.h"
#endif
 
void UART_Init( void );
uns8 UART_GetChar( void );
void UART_PutChar( uns8 ch );
void UART_PutStr( const char *str );
int UART_IsCharAvailable( void );
 
#endif // UART_H
/bots/Wedgy/flash_led.c
0,0 → 1,16
#include "arc_10.h"
 
int main(void)
{
outp(BV(prog_led), DDRB); // Make LED port bit an output
while(1)
{
sbi(PORTB, 4); // Turn LED off
waitms(500);
cbi(PORTB, 4); // Turn LED on
waitms(500);
}
return 0;
}
/bots/Wedgy/FlashLed.c
0,0 → 1,61
#include "arc_10.h"
#include "a2d.h"
#include "DebugKey.h"
#include "Delay.h"
#include "Motor.h"
#include "Sensor.h"
#include "Uart.h"
 
int main(void)
{
int i, j;
 
InitializeA2D();
UART_Init();
UART_PutStr( "FlashLED Test Program\r\n" );
InitTimer();
InitMotors();
 
DDRB = BV( prog_led ) | BV( 6 );
while( 1 )
{
// Turn LED on
ReadSensors();
PORTB &= ~( BV( prog_led ) | BV( 6 ));
 
for ( i = 0; i < 10; i++ )
{
if ( UART_IsCharAvailable() )
{
UART_GetChar();
DebugKey();
}
for ( j = 0; j < 50; j++ )
{
WaitForTimer0Rollover();
}
}
 
// Turn LED off
 
ReadSensors();
PORTB |= ( BV( prog_led ) | BV( 6 ));
 
for ( i = 0; i < 10; i++ )
{
if ( UART_IsCharAvailable() )
{
UART_GetChar();
DebugKey();
}
for ( j = 0; j < 50; j++ )
{
WaitForTimer0Rollover();
}
}
 
}
return 0;
}
/bots/Wedgy/Debug.h
0,0 → 1,23
/****************************************************************************
*
* Debug.h
*
* Debug control
*
****************************************************************************/
 
#if !defined( DEBUG_H )
#define DEBUG_H
 
#if !defined( DEBUG )
#define DEBUG 1
#endif
 
#if DEBUG
# define DBG(x) x
#else
# define DBG(x)
#endif
 
#endif // DEBUG_H
 
/bots/Wedgy/Puts.c
0,0 → 1,168
/****************************************************************************
*
* Puts.c
*
* Routines for outputting strings.
*
****************************************************************************/
 
// ---- Include Files -------------------------------------------------------
 
#include "Types.h"
#include "Puts.h"
#include "Uart.h"
 
// ---- Public Variables ----------------------------------------------------
 
uns8 gDeferredNewline;
 
// ---- Private Constants and Types -----------------------------------------
 
static char buf[ 6 ];
 
// ---- Private Variables ---------------------------------------------------
// ---- Private Function Prototypes -----------------------------------------
// ---- Functions -----------------------------------------------------------
 
/****************************************************************************
*
* Writes a string the serial port.
*/
 
void dh_puts( const char *s )
{
if ( gDeferredNewline )
{
putc( '\r' );
putc( '\n' );
putc( '+' );
gDeferredNewline = 0;
}
 
while ( *s )
{
if ( *s == '\n' )
{
putc( '\r' );
}
 
putc( *s );
 
s++;
}
 
} // puts
 
/****************************************************************************
*
* Writes a number as a single digit.
*/
 
void putdigit( uns8 num )
{
if ( num > 9 )
{
putc( '*' );
}
else
{
putc( num + '0' );
}
} // putdigit
 
/****************************************************************************
*
* Writes a single character to the serial port.
*/
 
void dh_putc( char ch )
{
UART_PutChar( (char)ch );
 
} // putc
 
/****************************************************************************
*
* Writes an integer in ASCII form to the serial port
*/
 
void putu8( uns8 num )
{
int i = 0;
do
{
uns8 c;
c = num % 10;
c += '0';
buf[ i ] = c;
i++;
num /= 10;
} while ( num != 0 );
while ( i < 3 )
{
buf[ i ] = ' ';
i++;
}
while ( i > 0 )
{
i--;
putc( buf[ i ]);
}
 
} // putu8
 
/****************************************************************************
*
* Writes an integer in ASCII form to the serial port
*/
 
void putu16( uns16 num )
{
#if 0
uns16 num2;
 
num2 = num & 0xFF00;
num2 >>= 8;
putu8( (uns8)num2 );
putc( ':' );
num2 = num & 0x00FF;
putu8( (uns8)num2 );
 
#else
 
int i = 0;
 
do
{
uns16 c;
 
c = num % 10;
c += '0';
buf[ i ] = (uns8)c;
i++;
num /= 10;
} while ( num != 0 );
 
// puts( "i:" ); putu8( i ); putc( ' ' );
 
while ( i > 0 )
{
i--;
 
putc( buf[ i ]);
}
 
// puts (" done PutU16\n" );
#endif
 
} // putu16
/bots/Wedgy/arclib_10.c
0,0 → 1,36
#include <avr/io.h>
/*
ARC 1.0 Lib
*/
 
// Tuned for reasonably accurate delays w/o interrupts @ 8mhz (likely to change with compiler rev).
 
void waitms(int delay)
{
while (delay)
{
delay--;
int i;
for (i = 1597; i; i--) asm("nop");
}
}
 
// Simple polled ADC input
 
void initialize_adc(void)
{
ADCSR = BV(ADEN) | BV(ADSC) | BV(ADPS1) | BV(ADPS2);
while (ADCSR & BV(ADSC));
}
 
int getadc(char Channel)
{
ADMUX = Channel;
ADCSR = ADCSR | BV(ADSC);
while (ADCSR & BV(ADSC)); // Wait conversion done
return ADCW;
}
 
void initialize_pwm(void)
{
}
/bots/Wedgy/Makefile
0,0 → 1,114
MCU_TARGET = atmega16
MCU_PROG_TARGET = m16
OPTIMIZE = -O2
 
DEFS =
LIBS =
 
# You should not have to change anything below here.
 
CC = avr-gcc
 
# Override is only needed by avr-lib build system.
 
override CFLAGS = -g -Wall $(OPTIMIZE) -mmcu=$(MCU_TARGET) $(DEFS)
override LDFLAGS = -Wl,-Map,$(PRG).map
 
OBJCOPY = avr-objcopy
OBJDUMP = avr-objdump
PROGRAMMER = avrdude
 
PROGRAMMER_OPTS = -p $(MCU_PROG_TARGET) -c avrisp -P COM1
 
.PHONY: MiniSumo FlashLed
 
all: MiniSumo
 
MiniSumo: MiniSumo.hex
FlashLed: FlashLed.hex
 
MiniSumo.elf : MiniSumo.o a2d.o Avoid.o DebugKey.o Delay.o Motor.o Sensor.o Puts.o Uart.o
 
FlashLed.elf : FlashLed.o a2d.o DebugKey.o Delay.o Motor.o Sensor.o Puts.o Uart.o arclib_10.o
 
FORCE:
 
clean:
rm -rf *.o $(PRG).elf *.eps *.png *.pdf *.bak
rm -rf *.lst *.map $(EXTRA_CLEAN_FILES)
d download: MiniSumo.dld
%.elf :
$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $^ $(LIBS)
 
%.dld : %.hex
$(PROGRAMMER) $(PROGRAMMER_OPTS) -e -U flash:w:$<
 
%.cod: %.c FORCE
$(CC) $(CFLAGS) $(CPPFLAGS) $(TARGET_ARCH) -c -g -Wa,-ahdl=$@ -o $(@:.cod=.o) $<
%.pp: %.c
$(CC) $(CFLAGS) $(CPPFLAGS) $(TARGET_ARCH) -E -Wp,-dN,-C -o $@ $<
 
lst: $(PRG).lst
 
%.lst: %.elf
$(OBJDUMP) -h -S $< > $@
 
# Rules for building the .text rom images
 
text: hex bin srec
 
hex: $(PRG).hex
bin: $(PRG).bin
srec: $(PRG).srec
 
%.hex: %.elf
$(OBJCOPY) -j .text -j .data -O ihex $< $@
 
%.srec: %.elf
$(OBJCOPY) -j .text -j .data -O srec $< $@
 
%.bin: %.elf
$(OBJCOPY) -j .text -j .data -O binary $< $@
 
# Rules for building the .eeprom rom images
 
eeprom: ehex ebin esrec
 
ehex: $(PRG)_eeprom.hex
ebin: $(PRG)_eeprom.bin
esrec: $(PRG)_eeprom.srec
 
%_eeprom.hex: %.elf
$(OBJCOPY) -j .eeprom --change-section-lma .eeprom=0 -O ihex $< $@
 
%_eeprom.srec: %.elf
$(OBJCOPY) -j .eeprom --change-section-lma .eeprom=0 -O srec $< $@
 
%_eeprom.bin: %.elf
$(OBJCOPY) -j .eeprom --change-section-lma .eeprom=0 -O binary $< $@
 
# Every thing below here is used by avr-libc's build system and can be ignored
# by the casual user.
 
FIG2DEV = fig2dev
EXTRA_CLEAN_FILES = *.hex *.bin *.srec
 
dox: eps png pdf
 
eps: $(PRG).eps
png: $(PRG).png
pdf: $(PRG).pdf
 
%.eps: %.fig
$(FIG2DEV) -L eps $< $@
 
%.pdf: %.fig
$(FIG2DEV) -L pdf $< $@
 
%.png: %.fig
$(FIG2DEV) -L png $< $@