#include // inputs #define PSWITCH BIT1 #define TRIGGER BIT3 // outputs #define SVALVE BIT6 #define PUMP BIT0 #define FEED BIT7 // globals enum weaponstate { NOCHARGE, CHARGED, CHARGING, FIRING }; int wstate; void fire (void) { /* weapon firing subroutine */ /* set the state */ wstate = FIRING; /* NB: The pswitch should not trigger ther P1 INT routine while fire() is running since fire() is only ever called from p1int. */ /* activate FEED magnet (prevents non-chambered ammo from falling into chamber during firing) */ P1OUT |= FEED; /* enabler timera */ TACTL = TASSEL_2 + MC_3 + ID_2; // ACLK, up/down mode, factor 4 divider /* open solenoid valve / dump air */ P1OUT |= SVALVE; /* done. the timer will close valve and then run the pump ( CHARGING state ) */ } void __attribute__((interrupt (PORT1_VECTOR))) p1int (void) { if (P1IFG & TRIGGER) { switch (wstate) { case FIRING: case CHARGING: case NOCHARGE: /* for now, do nothing. Maybe later I'll add a sound effect or something */ break; case CHARGED: /* the gun is charged and the trigger was pulled. FIRE ZE WEAPON! */ fire(); break; } P1IFG &= ~ TRIGGER; } if (P1IFG & PSWITCH) { if (wstate == CHARGING) { /* pressure switch tripped while charging, that means we're charged! */ wstate = CHARGED; P1OUT &= ~PUMP; /* turn off pump */ } P1IFG &= ~ PSWITCH; } } void __attribute__((interrupt (TIMERA0_VECTOR))) timera (void) { static unsigned int i = 0; if ( i++ > 1 ) { i = 0; TACTL = MC_0; // stop timer P1OUT &= ~( FEED + SVALVE); // close svalve, turn off FEED magnet wstate = CHARGING; // change state to charging P1OUT |= PUMP; // and activate pump } } int main() { WDTCTL = WDTPW + WDTHOLD; // disable watchdog P1DIR |= SVALVE + PUMP + FEED; // set SVALVE PUMP FEED to output P1DIR &= ~( TRIGGER + PSWITCH ); // set TRIGGER and PSWITCH to input P1OUT &= ~( SVALVE + PUMP + FEED); // make sure SVALVE and PUMP and FEED are off // setup IRQ for GPIO P1IE = PSWITCH + TRIGGER; P1IES |= PSWITCH + TRIGGER; // set high-to-low transition interrupt trigger P1IFG = 0; // clear all interrupt flags P1REN &= ~ ( PSWITCH + TRIGGER ); // enable internal pull up/down internal resistor P1OUT |= (PSWITCH + TRIGGER); // set to pull up resistor // set up timera configuration ( but do not start timer) CCTL0 = CCIE; // enable timera's interrupt CCR0 = 0xffff; // count up to this then down to zero // check if the pswitch is active / figure out our state if ( (P1IN & PSWITCH) == 0) { wstate = CHARGING; P1OUT |= PUMP; } else { wstate = CHARGED; } __eint(); // enable interrupts LPM0; // low power mode 0 }