#include <pic.h>
__CONFIG(UNPROTECT & PWRTDIS & MCLRDIS & BORDIS & LVPDIS & HS);	// &'s important, not |'s!!!!!!
/* 
UNPROTECT	0xFFFF	Code and Data unprotected
WDTDIS		0xFFFB	Watchdog timer disabled
PWRTDIS		0xFFFF	Power-up timer disabled
MCLRDIS		0xFFDF	/MCLR internally tied high, pin is RA5 IO
BORDIS		0xFFBF	Brown-out reset detect disabled
LVPDIS		0xFF7F	Low-voltage programming disabled
HS		0xFFEE	Use high speed external oscillator (>8MHz)
*/

// Software version 1.00


#define TRUE 0x01
#define FALSE 0x00


/*  These PINOUTs as per Doug's pcb version 1.21


	General pinout layout
	Port A: RA0		weapon select input (active high) 
		RA1		touch scored output (active high)
		RA2		green pin c (20mm pin) weapon ground  (input to comparator)
		RA3		red   pin c (20mm pin) weapon ground  (input to comparator)
		RA4		pause/inhibit input (active high)
		RA5		piste

	Port B: RB0		red pin b (middle pin)
		RB1		output load clock to serial -> parallel chip (74HCT595)
		RB2		serial IO Tx (reserved)
		RB3		red pin a (15mm pin)
		RB4		green pin a (15mm pin)
		RB5		green pin b (middle pin)
		RB6		data to serial -> parallel chip (74HCT595)
		RB7		data clock to serial -> parallel chip (74HCT595)

	74HCT595 pinout layout
		Q0		(green) White LED (off target)
		Q1		(green) Yellow LED 
		Q2		(green) Green LED (on target)
		Q3		(red)	Red LED (on target)
		Q4		(red)	White LED (off target)
		Q5		(red)	Yellow LED
		Q6		buzzer
		Q7		Weapon LED


*/


/* some notes:

updating the status of the serial to parallel chip only occurs during the
Update_Lights routine.  Thus a data_for_port_b variable isn't needed, since
no data is being stored for later output while the 'fencing' functions are
running.

*/





// define weapons
#define FOIL 0x00
#define EPEE 0x01

#define TIMING_INCREMENT	0x04	// timing resolution, in tenths of milliseconds
					// this is equal to the number of "parts" in the main loop
					// DO NOT ADJUST!

// define colours - used in referencing arrays
#define RED 0
#define GREEN 1

// define timing constants

#define TOUCH_TIME_FOIL 	30	// 3 ms for foil
#define TOUCH_TIME_EPEE		50	// 5 ms for epee
#define LOCKOUT_TIME_FOIL	7500	// 750 ms for foil
#define LOCKOUT_TIME_EPEE	450	// 45 ms for epee
#define TOUCH_LIGHT_RESET_TIME	20000	// 2 s
#define BUZZER_RESET_TIME	20000	// 2 s


volatile bit		returned_from_int	= FALSE;
volatile unsigned char  data_for_74HC595	= 0x00;
volatile bit		lights_frozen		= FALSE;


// define some macros

#define FENCER_IO_PORT_A_MASK		0b00101100	// RA2:RA3:RA5
#define FENCER_IO_PORT_B_MASK		0b00111001	// RB0:RB3:RB4:RB5



#define SET_GREEN_OFF_TARGET_LED_ON	{ data_for_74HC595 |= 0x01; }
#define SET_GREEN_OFF_TARGET_LED_OFF	{ data_for_74HC595 &= 0xFF - 0x01; }

#define SET_GREEN_YELLOW_LED_ON		{ data_for_74HC595 |= 0x02; }
#define SET_GREEN_YELLOW_LED_OFF	{ data_for_74HC595 &= 0xFF - 0x02; }

#define SET_GREEN_ON_TARGET_LED_ON	{ data_for_74HC595 |= 0x04; }
#define SET_GREEN_ON_TARGET_LED_OFF	{ data_for_74HC595 &= 0xFF - 0x04; }

#define SET_RED_ON_TARGET_LED_ON	{ data_for_74HC595 |= 0x08; }
#define SET_RED_ON_TARGET_LED_OFF	{ data_for_74HC595 &= 0xFF - 0x08; }

#define SET_RED_OFF_TARGET_LED_ON	{ data_for_74HC595 |= 0x10; }
#define SET_RED_OFF_TARGET_LED_OFF	{ data_for_74HC595 &= 0xFF - 0x10; }

#define SET_RED_YELLOW_LED_ON		{ data_for_74HC595 |= 0x20; }
#define SET_RED_YELLOW_LED_OFF		{ data_for_74HC595 &= 0xFF - 0x20; }

#define SET_BUZZER_ON			{ data_for_74HC595 |= 0x40; }
#define SET_BUZZER_OFF			{ data_for_74HC595 &= 0xFF - 0x40; }
#define GET_BUZZER_STATUS		(data_for_74HC595 & 0x40)

#define SET_WEAPON_LED_TO_EPEE		{ data_for_74HC595 |= 0x80; }
#define SET_WEAPON_LED_TO_FOIL		{ data_for_74HC595 &= 0xFF - 0x80; }


#define CLEAR_LIGHTS			{ data_for_74HC595 = 0x00; }


// define return values from read_wires function
/*
	return: 0x01	RB0		red pin b (middle pin)
		0x02	(RA2>>1)	green pin c (20mm pin) weapon ground  (input to comparator)
		0x04	(RA3>>1)	red   pin c (20mm pin) weapon ground  (input to comparator)
		0x08	RB3		red pin a (15mm pin)
		0x10	RB4		green pin a (15mm pin)
		0x20	RB5		green pin b (middle pin)
		0x40	(RA5<<1)	piste
*/
#define PISTE			0x40
#define RED_WPN_GND		0x04	// 20mm pin C
#define RED_FOIL_LAME		0x08	// 15mm pin A
#define RED_FOIL_TIP		0x01	// centre pin B
#define RED_EPEE_TIP		0x08	// 15mm pin A
#define RED_EPEE_TIP_RETURN	0x01	// centre pin B 
#define GREEN_WPN_GND		0x02	// 20mm pin C
#define GREEN_FOIL_LAME		0x10	// 15mm pin A
#define GREEN_FOIL_TIP		0x20	// centre pin B
#define GREEN_EPEE_TIP		0x10	// 15mm pin A
#define GREEN_EPEE_TIP_RETURN	0x20	// centre pin B 




void Update_Lights() {
	unsigned char mask, data, i;

	if( data_for_74HC595 & 0b00101101 ) 		// one of the red/green/white lights is active
		PORTA = 0x02;				// set the touch scored signal high
	else
		PORTA = 0x00;				// otherwise set it low

	mask = 0x80;
	for(i=0;i<8;i++) {
		data = 0x00;
		if( data_for_74HC595 & mask ) data = 0x40;
		PORTB = data;				// set the data line
		PORTB = data | 0x80;			// set the clock line high
		PORTB = data;				// set the clock line low
		mask = mask >> 1;
	}
	PORTB = 0x02;					// load the new data onto the output
	PORTB = 0x00;
}


// Sends the active wire high and returns the read value from the other wires
// ONLY PINS A & B CAN BE SET HIGH, NOT PIN C OR THE PISTE!

unsigned char read_wires(unsigned char active_wire) {
	unsigned char i, return_value, pa_read1, pb_read1, pa_read2, pb_read2;

	TRISB = FENCER_IO_PORT_B_MASK ^ active_wire;		// assign data lines and active wire(s) to output, all others input
	PORTB = active_wire;

	do {
		for(i=15; --i>0;);
		pa_read1 = PORTA & FENCER_IO_PORT_A_MASK;
		pb_read1 = PORTB & FENCER_IO_PORT_B_MASK;
		for(i=15; --i>0;);		
		pa_read2 = PORTA & FENCER_IO_PORT_A_MASK;
		pb_read2 = PORTB & FENCER_IO_PORT_B_MASK;
	} while	((pa_read1 != pa_read2) || (pb_read1 != pb_read2));		// wait for inputs to settle

	TRISB = FENCER_IO_PORT_B_MASK;				// assign data lines to output, all others input
	PORTB = 0x00;			// set all pins low

	return_value = pb_read1 | ((pa_read1 << 1) & 0x40) | ((pa_read1 >> 1) & 0x06);

	return return_value;
}



// 100 - 200 Ohm test.  Returns true if resistance is <100 Ohms.
// fencer variable selects whether the RED or the GREEN weapon ground line is tested.
unsigned char ohm_check_100_200(unsigned char active_wire, unsigned char fencer) {
  unsigned char i, return_value;

  CMCON = 0b00001010;				// assign pin RA3 (red) to comparator 1 Vin-
						// assign pin RA2 (green) to comparator 2 Vin-

  VRCON = 0b10001110;				// Vref ~ 3.4v for 100 - 200R test

  TRISB = FENCER_IO_PORT_B_MASK ^ active_wire;	// assign active wire to output, all others input
  PORTB = active_wire;

  for(i=15;i>0;i--);
  if(CMCON & (0x40<<fencer)) {	// comparator value = 1 -> input voltage < Vref  =>  R > 200R
		return_value = FALSE;		
	} else {		// comparator value = 0 -> input voltage > Vref  =>  R < 200R
		return_value = TRUE;
	}

  CMCON = 0b00001111;				// disconnect RA2 & RA3 from comparator
  TRISB = FENCER_IO_PORT_B_MASK;		// assign LEDs to output, all others input
  PORTB = 0x00;

  return return_value;
}



// 450 - 475 Ohm test.  Returns true if resistance is <450 Ohms.
// fencer variable selects whether the RED or the GREEN weapon ground line is tested.
unsigned char ohm_check_450_475(unsigned char active_wire, unsigned char fencer) {
  unsigned char i, return_value;

  CMCON = 0b00001010;				// assign pin RA3 to comparator 1 Vin-
						// assign pin RA2 to comparator 2 Vin-

  VRCON = 0b10000111;				// Vref ~ 2.3v for 450 - 475R test

  TRISB = FENCER_IO_PORT_B_MASK - active_wire;	// assign active wire to output, all others input
  PORTB = active_wire;

  for(i=15;i>0;i--);
  if(CMCON & (0x40<<fencer)) {	// comparator value = 1 -> input voltage < Vref  =>  R > 475R
		return_value = FALSE;		
	} else {		// comparator value = 0 -> input voltage > Vref  =>  R < 475R
		return_value = TRUE;
	}

  CMCON = 0b00001111;				// disconnect RA2 & RA3 from comparator
  TRISB = FENCER_IO_PORT_B_MASK;		// assign LEDs to output, all others input
  PORTB = 0x00;					// set all pins ABC low


  return return_value;
}




// This is the interrupt handler, called by the timer interrupt every 0.1ms.
void interrupt tc_int(void) {
	TMR0 = 256 - 250 + 11;			// Set the Timer0 count back to 250 ticks short of overflow.
	CLRWDT();				// clear the watchdog timer
	returned_from_int = TRUE;		// set value to true so main loop starts again
	T0IF = 0;				// Clear the timer interrupt flag.
}




// Delay
void delay(unsigned short i) {
	for(;(i>>8)>0;i--) CLRWDT();
}



	
main(void) {
  unsigned char i, value1, value2, value3, last_value;
  unsigned char continuous_off_target[2] = { FALSE, FALSE };

  // are the timers ticking?
  unsigned char lockout_timer_active 		= FALSE; 
  unsigned char touch_light_reset_timer_active 	= FALSE;

  // are we listening to the weapons
  unsigned char listen[2] = {TRUE, TRUE};
  unsigned char weapon_type;			// active weapon type

  // these arrays store the elapsed time
  unsigned short on_touch_timer[2] = { 0, 0 };
  unsigned short off_touch_timer[2] = { 0, 0 };
  unsigned short lockout_timer = 0; 
  unsigned short touch_light_reset_timer = 0;


  // Do various stuff associated with setup and initialisation.
  // Set up the prescaler for the watchdog - based on code from section 26.3 of the PIC Mid-range Reference manual.
  OPTION = 0b11011111;				// Assign the postscaler to the watchdog.
  CLRWDT();					// Clear the watchdog timer
  INTCON = 0b00000000;				// Disable all interupts.
  TRISA =  0b11111101;				// pins RA1 output, all others input
  PORTA = 0;
  TRISB = 0b00111111;				// pins RB7 RB8 output, all others input				
  PORTB = 0;

  // define some variables
  last_value = 0;
  value1 = 0;
  value2 = 0;
  value3 = 0;


// Do power-on routine
   data_for_74HC595 = 0xFF;
   Update_Lights();
   delay(0xFFFF);
   data_for_74HC595 = 0x00;
   Update_Lights();
   delay(0xFFFF);
   data_for_74HC595 = 0xFF;
   Update_Lights();
   delay(0xFFFF);
   data_for_74HC595 = 0x00;


  // check for weapon type
  weapon_type = EPEE;
  SET_WEAPON_LED_TO_EPEE;
  if( ((read_wires(RED_FOIL_TIP) & RED_WPN_GND) != 0x00) || ((read_wires(GREEN_FOIL_TIP) & GREEN_WPN_GND) != 0x00))  { 
    weapon_type = FOIL;
    SET_WEAPON_LED_TO_FOIL;
  }
  Update_Lights();

  T0IF = 0;		// Clear the timer interrupt flag.
  TMR0 = 256 - 250 + 11;	// Set the Timer0 count to 250 ticks short of overflow.
				// This means that the timer interrupt occurs every
				// 250 * 0.4us = 0.1ms, for a 10MHz clock.
  INTCON = 0b10100000;	// Enable global interrupts and the timer interrupt.

  for(;;) {				// loop forever

//************** PART I: HANDLES THE RED FENCER **************
    if( lights_frozen == FALSE) {
	if( listen[RED] ) {								// if we're listening to red's weapon
		if( weapon_type == FOIL ) {						// if it's a foil
			i = read_wires(RED_FOIL_TIP);					// read what the tip is touching


			if( (i & PISTE) && (i & GREEN_FOIL_TIP) && (i & GREEN_FOIL_LAME) ) {
				// touching the opponent's lame, the piste AND the opponent's tip
				// assume both fencers are touching the piste 
				// while one is touching their guard to their lame, so register no touch
				i = RED_WPN_GND;					// set only WPN_GND bit in i
			} else 

			if((i & GREEN_WPN_GND) && (i & GREEN_FOIL_LAME)) {
				// touching both the opponent's lame and the wpn gnd/guard
				// need to test resistance as per anti-blocking specs
				if( ohm_check_100_200(GREEN_FOIL_LAME, GREEN) ) {
					// anti-blocking is active - register as if touching only lame
					i ^= GREEN_WPN_GND;					// clear WPN_GND bit in i
				} else {
					// resistance between green's weapon ground and lame is >100R.
					// need to resister touches normally, which meens we need to know
					// if red's tip is touching green's lame or guard.
					if( ohm_check_100_200(RED_FOIL_TIP, GREEN) ) {
						// resistance from red's foil tip to green's guard is < 100R
						// infer that red is touching green's guard and not their lame
						// so, set only WPN_GND bit in i
						i ^= GREEN_FOIL_LAME;
					} else {
						// resistance from red's foil tip to green's guard is > 100R
						// infer that red is touching green's lame and not their guard
						// so, clear WPN_GND bit in i
						i ^= GREEN_WPN_GND;
					}
				}
			}

			if( i & (PISTE | RED_WPN_GND | GREEN_WPN_GND)) { 		// if tip is not pressed
											// or is touching the PISTE or 
											// opponent's guard
				continuous_off_target[RED] = FALSE;
				on_touch_timer[RED] = 0;				// set touch timers to 0
				off_touch_timer[RED] = 0;

			} else if( i & GREEN_FOIL_LAME ) {				// if tip is pressed and
											// touching their lame?
				continuous_off_target[RED] = FALSE;
				on_touch_timer[RED]+=TIMING_INCREMENT;			// increment timer
										// if we've reached the time for this wpn
				if ( on_touch_timer[RED] >= TOUCH_TIME_FOIL ) {	
					on_touch_timer[RED] = 0;		// reset touch timers to 0
					off_touch_timer[RED] = 0;
					lockout_timer_active = TRUE;		// start lockout timer
					listen[RED] = FALSE;			// stop listening to weapon
					SET_RED_ON_TARGET_LED_ON;
					SET_BUZZER_ON;
				}
			} else {						// touching off target
				off_touch_timer[RED]+=TIMING_INCREMENT;		// increment timer
										// if we've reached the time for this wpn
				if ( off_touch_timer[RED] >= TOUCH_TIME_FOIL ) {	
					on_touch_timer[RED] = 0;		// reset touch timer to 0
					off_touch_timer[RED] = 0;
					lockout_timer_active = TRUE;		// start lockout timer
					listen[RED] = FALSE;			// stop listening to weapon
					SET_RED_OFF_TARGET_LED_ON;
					if( GET_BUZZER_STATUS == 0x00 ) 	// buzzer is off
						if (continuous_off_target[RED] == FALSE) SET_BUZZER_ON;
					continuous_off_target[RED] = TRUE;
				}
			}
		} else if ( weapon_type == EPEE ) {					// if it's an epee
			i = read_wires(RED_EPEE_TIP);					// read what the tip is touching
			if ( i & RED_EPEE_TIP_RETURN ) { 				// if tip is pressed
										// touching their guard/the piste?
				if ( i & (GREEN_WPN_GND | PISTE) ) {
					on_touch_timer[RED] = 0;			// set touch timer to 0
				} else {						// touching valid target
					on_touch_timer[RED]+=TIMING_INCREMENT;		// increment timer
										// if we've reached the time for this wpn
					if ( on_touch_timer[RED] >= TOUCH_TIME_EPEE ) {	
						on_touch_timer[RED] = 0;		// rest touch timer to 0
						lockout_timer_active = TRUE;		// start lockout timer
						listen[RED] = FALSE;			// stop listening to weapon
						SET_RED_ON_TARGET_LED_ON;
						SET_BUZZER_ON;
					}
				}
			} else {							// if tip is not pressed
				on_touch_timer[RED] = 0;				// set touch timer to 0
			}
		}
	}
    Update_Lights();
    }
	while(returned_from_int == FALSE) ;  	// loop forever waiting for next timer interrupt
	returned_from_int = FALSE;		// reset value to false

//************** PART II: HANDLES THE GREEN FENCER **************
    if( lights_frozen == FALSE) {
	if( listen[GREEN] ) {								// if we're listening to red's weapon
		if( weapon_type == FOIL ) {						// if it's a foil
			i = read_wires(GREEN_FOIL_TIP);					// read what the tip is touching



			if( (i & PISTE) && (i & RED_FOIL_TIP) && (i & RED_FOIL_LAME) ) {
				// touching the opponent's lame, the piste AND the opponent's tip
				// assume both fencers are touching the piste 
				// while one is touching their guard to their lame, so register no touch
				i = GREEN_WPN_GND;					// set only WPN_GND bit in i
			} 

			if( (i & RED_WPN_GND) && (i & RED_FOIL_LAME) ) {
				// touching both the opponent's lame and the wpn gnd/guard
				// need to test resistance as per anti-blocking specs
				if( ohm_check_100_200(RED_FOIL_LAME, RED) ) {
					// anti-blocking is active - register as if touching only lame
					i ^= RED_WPN_GND;					// clear WPN_GND bit in i
				} else {
					// resistance between red's weapon ground and lame is >100R.
					// need to resister touches normally, which meens we need to know
					// if green's tip is touching red's lame or guard.
					if( ohm_check_100_200(GREEN_FOIL_TIP, RED) ) {
						// resistance from green's foil tip to red's guard is < 100R
						// infer that green is touching red's guard and not their lame
						// so, set only WPN_GND bit in i
						i ^= RED_FOIL_LAME;
					} else {
						// resistance from green's foil tip to red's guard is > 100R
						// infer that green is touching red's lame and not their guard
						// so, clear WPN_GND bit in i
						i ^= RED_WPN_GND;
					}
				}
			}

			if( i & (PISTE | RED_WPN_GND | GREEN_WPN_GND) ) { 		// if tip is not pressed
											// or is touching the PISTE or 
											// opponent's guard
				continuous_off_target[GREEN] = FALSE;
				on_touch_timer[GREEN] = 0;				// set touch timers to 0
				off_touch_timer[GREEN] = 0;
			} else if( i & RED_FOIL_LAME ) { 				// if tip is pressed and
											// touching their lame?
				continuous_off_target[GREEN] = FALSE;
				on_touch_timer[GREEN]+=TIMING_INCREMENT;		// increment timer
										// if we've reached the time for this wpn
				if ( on_touch_timer[GREEN] >= TOUCH_TIME_FOIL ) {	
					on_touch_timer[GREEN] = 0;		// reset touch timers to 0
					off_touch_timer[GREEN] = 0;
					lockout_timer_active = TRUE;		// start lockout timer
					listen[GREEN] = FALSE;			// stop listening to weapon
					SET_GREEN_ON_TARGET_LED_ON;
					SET_BUZZER_ON;
				}
			} else {						// touching off target
				off_touch_timer[GREEN]+=TIMING_INCREMENT;	// increment timer
										// if we've reached the time for this wpn
				if ( off_touch_timer[GREEN] >= TOUCH_TIME_FOIL ) {	
					on_touch_timer[GREEN] = 0;		// reset touch timer to 0
					off_touch_timer[GREEN] = 0;
					lockout_timer_active = TRUE;		// start lockout timer
					listen[GREEN] = FALSE;			// stop listening to weapon
					SET_GREEN_OFF_TARGET_LED_ON;
					if( GET_BUZZER_STATUS == 0x00 )	// buzzer is off
						if (continuous_off_target[GREEN] == FALSE) SET_BUZZER_ON;
					continuous_off_target[GREEN] = TRUE;
				}
			}
		} else if ( weapon_type == EPEE ) {					// if it's an epee
			i = read_wires(GREEN_EPEE_TIP);					// read what the tip is touching
			if ( i & GREEN_EPEE_TIP_RETURN ) { 				// if tip is pressed
										// touching their guard/the piste?
				if ( i & (RED_WPN_GND | PISTE) ) {
					on_touch_timer[GREEN] = 0;			// set touch timer to 0
				} else {						// touching valid target
					on_touch_timer[GREEN]+=TIMING_INCREMENT;	// increment timer
										// if we've reached the time for this wpn
					if ( on_touch_timer[GREEN] >= TOUCH_TIME_EPEE ) {	
						on_touch_timer[GREEN] = 0;		// rest touch timer to 0
						lockout_timer_active = TRUE;		// start lockout timer
						listen[GREEN] = FALSE;			// stop listening to weapon
						SET_GREEN_ON_TARGET_LED_ON;
						SET_BUZZER_ON;
					}
				}
			} else {							// if tip is not pressed
				on_touch_timer[GREEN] = 0;				// set touch timer to 0
			}
		}
	}
    Update_Lights();
    }
	while(returned_from_int == FALSE) ;  	// loop forever waiting for next timer interrupt
	returned_from_int = FALSE;		// reset value to false

//************** PART III: HANDLES CONDUCTIVITY CHECKS **************


        if(PORTA & 0x10) {				// check if lights inhibit is active (active high!)
		// lights inhibit is active
		if(lights_frozen == FALSE) {
			// newly active, so update lights and turn buzzer off to stop it buzzing continually!
			lights_frozen = TRUE;
			SET_BUZZER_OFF;	
			Update_Lights();
		}		
	} else {
		// lights inhibit is inactive
		if (lights_frozen == TRUE) {
			// was active, so reset everything
			SET_RED_ON_TARGET_LED_OFF;				// turn all touch lights off
			SET_GREEN_ON_TARGET_LED_OFF;
			SET_RED_OFF_TARGET_LED_OFF;
			SET_GREEN_OFF_TARGET_LED_OFF;
			touch_light_reset_timer_active = FALSE;		// stop the timers
			lockout_timer_active = FALSE;			
			lockout_timer = 0;				// reset timers to 0
			touch_light_reset_timer = 0;			
			listen[RED] = TRUE;				// start listening to both weapons
			listen[GREEN] = TRUE;
			continuous_off_target[RED] = FALSE;
			continuous_off_target[GREEN] = FALSE;
			Update_Lights();
			lights_frozen = FALSE;
		}

	} 
	

    if( lights_frozen == FALSE) {
	SET_RED_YELLOW_LED_OFF;
	SET_GREEN_YELLOW_LED_OFF;
	if (weapon_type == FOIL) {
		if( ohm_check_450_475(RED_FOIL_LAME, RED) ) SET_RED_YELLOW_LED_ON;
		if( ohm_check_450_475(GREEN_FOIL_LAME, GREEN) ) SET_GREEN_YELLOW_LED_ON;
	} else if (weapon_type == EPEE) {
		if( ohm_check_450_475(RED_EPEE_TIP|RED_EPEE_TIP_RETURN, RED) ) SET_RED_YELLOW_LED_ON;
		if( ohm_check_450_475(GREEN_EPEE_TIP|GREEN_EPEE_TIP_RETURN, GREEN) ) SET_GREEN_YELLOW_LED_ON;
	} 
	Update_Lights();
    }

    while(returned_from_int == FALSE) ;  	// loop forever waiting for next timer interrupt
    returned_from_int = FALSE;		// reset value to false

//************** PART IV: HANDLES THE TIMERS, IF RUNNING, AND CHECKS FOR BUTTON PRESSES **************

    if( lights_frozen == FALSE) {
	if ( touch_light_reset_timer_active ) {					// if reset timer active
		touch_light_reset_timer+=TIMING_INCREMENT;			// increment reset timer
		if ( touch_light_reset_timer >= BUZZER_RESET_TIME) SET_BUZZER_OFF;
		if ( touch_light_reset_timer >= TOUCH_LIGHT_RESET_TIME ) {	// if we've reached the time
			SET_RED_ON_TARGET_LED_OFF;				// turn all touch lights off
			SET_GREEN_ON_TARGET_LED_OFF;
			SET_RED_OFF_TARGET_LED_OFF;
			SET_GREEN_OFF_TARGET_LED_OFF;
			SET_BUZZER_OFF;	
			touch_light_reset_timer_active = FALSE;			// stop the timer
			touch_light_reset_timer = 0;				// reset timer to 0
			listen[RED] = TRUE;					// start listening to both weapons
			listen[GREEN] = TRUE;
		}
	}
	if ( lockout_timer_active ) {						// if lockout timer active
		lockout_timer+=TIMING_INCREMENT;				// increment timer
		if ( weapon_type == FOIL) {
			if ( lockout_timer >= LOCKOUT_TIME_FOIL ) {			// reached the time for this wpn?
				lockout_timer = 0;					// reset lockout timer to 0
				lockout_timer_active = FALSE;				// stop lockout timer
				touch_light_reset_timer_active = TRUE;			// start the touch light reset timer
				listen[RED] = FALSE;					// stop listening to both weapons
				listen[GREEN] = FALSE;
			}
		} else {
			if ( lockout_timer >= LOCKOUT_TIME_EPEE ) {			// reached the time for this wpn?
				lockout_timer = 0;					// reset lockout timer to 0
				lockout_timer_active = FALSE;				// stop lockout timer
				touch_light_reset_timer_active = TRUE;			// start the touch light reset timer
				listen[RED] = FALSE;					// stop listening to both weapons
				listen[GREEN] = FALSE;
			}
		}
	}
    }

	// listen for button press
	value3 = value2;
	value2 = value1;
	value1 = PORTA & 0x01;						// RA0 is weapon select switch
	if ((value1 == value2) && (value1 == value3)) {
		if (value1 != last_value) {				// there is a change
			if (value1) {					// button was pressed
				CLEAR_LIGHTS;				// sets weapon light to foil by default
				if(weapon_type == EPEE) {
					weapon_type = FOIL; 
				} else { 
					weapon_type = EPEE;
					SET_WEAPON_LED_TO_EPEE;
				}
				touch_light_reset_timer_active = FALSE;		// stop the timers
				lockout_timer_active = FALSE;			
				lockout_timer = 0;				// reset timers to 0
				touch_light_reset_timer = 0;			
				listen[RED] = TRUE;				// start listening to both weapons
				listen[GREEN] = TRUE;
				continuous_off_target[RED] = FALSE;
				continuous_off_target[GREEN] = FALSE;
				lights_frozen = FALSE;
			}
			last_value = value1;
		}
	}
	Update_Lights();
 
    while(returned_from_int == FALSE) ;  	// loop forever waiting for a timer interrupt
    returned_from_int = FALSE;		// reset value to false
  }
}
