/* PISTOLE */ #include "hardware.h" #include #define SYSFREQ 16000000l /* Systemtakt in Hz */ #define SMCLKDIVISOR 8 #define PERIODEFREQ 3000l /* Taktfrequenz fuer PWM und TA1 interrupt */ #define PERIODECOUNT (SYSFREQ / (PERIODEFREQ * SMCLKDIVISOR)) /* Wert fuer Timer um FREQPWM zu erreichen */ #define IRPULSFREQ 38000l /* gewuenschte IR Pulsefrequenz */ #define IRPULSCOUNT (SYSFREQ / (IRPULSFREQ * SMCLKDIVISOR) / 2) /* Wert fuer Timer um IR Pulsefrequenz zu erreichen */ /* Timer laeuft mit SMCLK und kann auch mal angehalten werden */ #define TIMER_STOP TACTL = TASSEL_SMCLK | ID_DIV8 #define TIMER_RUN TACTL = TASSEL_SMCLK | ID_DIV8 | MC_CONT #define TIMER1_INTERRUPT TACCTL1 = OUTMOD_OUT | CCIE /* Interrupts erzeugen, Output bleibt 0 */ #define TIMER1_NOINTERRUPT TACCTL1 = OUTMOD_OUT /* Keine Interrupts, Output bleibt 0 */ #define TIMER1_TOGGLE_INTERRUPT TACCTL1 = OUTMOD_TOGGLE | CCIE /* Interrupts erzeugen, Output wechselt */ #define TIMER1_RESET_INTERRUPT TACCTL1 = OUTMOD_RESET | CCIE /* Interrupts erzeugen, Output wechselt auf 0 */ #define TIMER1_RESET_NOINTERRUPT TACCTL1 = OUTMOD_RESET /* Keine Interrupts erzeugen, Output wechselt auf 0 */ #define TIMER1_DET_RELOAD TACCR1 += PERIODECOUNT /* Reloadwert fuer IR-Empfang (Bitzeit) */ #define TIMER1_IR_RELOAD TACCR1 += IRPULSCOUNT /* Reloadwert fuer IR-Sendepulse (Pulszeit fuer Burst) */ #define TIMER1_INT_RESET TACCTL1 = TACCTL1 & ~CCIFG /* Interruptanforderung loeschen */ #define TIMER0_OUTLOW_INTERRUPT TACCTL0 = OUTMOD_OUT | CCIE | OUT_LOW #define TIMER0_CCR_RELOAD TACCR0 += PERIODECOUNT /* Nachladen fuer periodischen Interrupt */ #define IR_INT_ENABLE P1IE = P1IE | IR_PORT /* IR-Interrupt ermoeglichen */ #define IR_INT_DISABLE P1IE = P1IE & ~IR_PORT /* IR-Interrupt abschalten */ #define IR_INT_RESET P1IFG = P1IFG & ~IR_PORT /* IR-Interruptanforderung loeschen */ #define NUR_EINSTELLUNG_INT_ENABLE P1IE = EINSTELLUNG /* Nur noch Interrupt durch Programmierstecker zulassen */ #define ALLE_TASTEN_INT_ENABLE P1IE = ALLE_TASTEN /* Interrupts durch alle Tasten zulassen */ #define IRBITS 5 /* Eine IR-Nachricht besteht aus 5 Bits */ #define PAUSE (3*2) /* Nach einer IR-Nachricht wird eine Sendepause eingelegt */ #define TXPAUSE 10 /* Nach dem Senden einer IR-Nachricht wird eine Zwangspause eingelegt */ #define INAKTIVDAUER 30*60 /* Zeit in Sekunden, bis zum Abschalten der Pistole */ #define TREFFERDAUER 20 /* Zeit in Sekunden, die die Pistole nach einem Treffer nicht schiesst */ #define FLASH_SEG_ERASE 0xA502 #define FLASH_UNLOCK 0xA500 #define FLASH_WRITE 0xA540 #define FLASH_PROG_OFF 0xA500 /* Hier kommen jetzt ein paar waffenabhaengige Einstellungen */ #if ! (defined (UZI) || defined (PISTOLE) || defined (M16)) #error Es muss eine Waffe angegeben werden #endif #ifdef UZI /* Die Uzi hat keine Magazintasten. Daher kann sie nicht nachgeladen werden */ #define PATRONEN_PRO_MAGAZIN 250 #define SCHUSSPAUSE MS(80) /* Nach einem Schuss muss 80ms gewartet werden bis wieder geschossen werden kann */ #endif #ifdef PISTOLE #define PATRONEN_PRO_MAGAZIN 10 #define SCHUSSPAUSE MS(400) #endif #ifdef M16 #define PATRONEN_PRO_MAGAZIN 30 #define SCHUSSPAUSE MS(40) #endif #define MAGAZINE 4 /* Zustaende fuer die Statemachine die die Pistole steuert */ #define ST_SCHUSSBEREIT 0 #define ST_MAGAZIN_LEER 1 #define ST_MAGAZIN_RAUS 2 #define ST_GANZ_LEER 3 /* MS(x) liefert eine Zahl, die x Millisekunden warten laesst */ #define MS(x) (((x) * PERIODEFREQ) / 1000) #define BLINK_AN_LANGSAM ((PERIODEFREQ) / 2) #define BLINK_AUS_LANGSAM ((PERIODEFREQ) / 2) #define BLINK_AN_ZAEHLEND MS(100) #define BLINK_AUS_ZAEHLEND MS(300) #define BLINK_AN_FEHLER MS(50) #define BLINK_AUS_FEHLER MS(50) #define BLINK_AN_TREFFER MS(25) #define BLINK_AUS_TREFFER MS(25) #define BLINK_AN_LOWBAT MS(10) #define BLINK_AUS_LOWBAT MS(30) #define FLASHDIVIDER (SYSFREQ / 366000) /* Das Flash-EPROM braucht eine Frequenz von ca. 366kHz */ #define MUETZENNUMMER_ADDR 0x1000 /* Im Flash-EPROM wird diese Adresse fuer die Speicherung der ID benutzt */ sfrw(MUETZENNUMMER, MUETZENNUMMER_ADDR); /* Assembler funktion um auf die Adresse MUETZENNUMMER_ADDR wortbreit zugreifen zu koennen */ volatile int irrxbitcount; volatile int irrxpausecount; volatile int irrxdaten; volatile char irempfang; volatile unsigned int irtxdaten; volatile unsigned char irtxbitcount; volatile unsigned char irtxpausecount; volatile unsigned int timer; volatile unsigned int delaytimer; volatile unsigned int sekundenzaehler; volatile unsigned char empfangsmode; volatile unsigned int aktivzeit; volatile unsigned int trefferzeit; volatile unsigned char muetzennummer; int patronen; int magazine; int anzahl_magazine; int zustand; int i; /** Verzoegerungsfunktion durch Abwarten bis Interrupt den delaytimer auf 0 heruntergezaehlt hat */ void delay(unsigned int d) { delaytimer = d; while (delaytimer) { } } /* Die LED blinkt 'anzahl' mal. Die Leuchtdauer und Pausendauer ist durch 'zeitAn' und 'zeitAus' bestimmt. Bei jedem Blinken wird aber noch der externe Spannungsteiler abgepr[ft und mit der internen Referenz verglichen. Falls die Batteriespannung zu niedrig ist, wird im Anschluss an das normale Blinken noch 20 mal ganz schnell geblinkt. */ void blink(unsigned int anzahl, unsigned int zeitAn, unsigned int zeitAus) { int i; char lowbat; lowbat = 0; for (i = 0; i < anzahl; i++) { LED_AN; /* Diodenreferenz an -In, Comparator einschalten */ CACTL1 = CAEX | CAREF_3 | CAON; delay(zeitAn); if(CACTL2 & CAOUT) { lowbat = 1; } CACTL1 = CAEX | CAREF_3; LED_AUS; delay(zeitAus); } if (lowbat) { for (i = 0; i < 20; i++) { LED_AN; delay(BLINK_AN_LOWBAT); LED_AUS; delay(BLINK_AUS_LOWBAT); } } } /* Mit dieser Routine wird an 'adresse' das 'datum' ins Flash-EPROM geschrieben. Da hier nur ein einziges Datum, naemlich die Muetzennummer, zu speichern ist, wird einfach immer der gesamter Flash/ */ void flashWrite(unsigned int adresse, unsigned int datum) { /* Watchdog disable nicht noetig, da sowieso aus */ dint(); /* Interrupts sperren */ /* Erst mal loeschen */ FCTL1 = FLASH_SEG_ERASE; FCTL3 = FLASH_UNLOCK; *((unsigned int *)(adresse)) = 0xFFFF; while(BUSY & FCTL3); /* Nur wenn nicht Busy weitermachen */ FCTL3 = FLASH_UNLOCK; FCTL1 = FLASH_WRITE; *((unsigned int *)(adresse)) = (datum); FCTL1 = FLASH_PROG_OFF; eint(); /* Interrupts wieder zulassen */ } interrupt (TIMERA0_VECTOR) Timer_A(void) { eint(); /* Interrupts wieder zulassen, damit TIMERA1 weiterhin drankommen kann. */ TIMER0_CCR_RELOAD; /* Neuen Zaehlervergleichswert speichern */ /* Ab hier kommt die Behandlung des Sendeimpulses */ /* Wenn irtxbitcount != 0 ist, muss das Senden von Bits bearbeitet werden */ /* Pro Bit gibt es eine Puls- und eine Pausenhaelfte. Bei Bit=1 wird zunaechst ein */ /* Puls und dann eine Pause gesendet. Beides wird durch Setzen der MODE-Bits fuer */ /* Timer 0 gesteuert. Bei Bit=0 ist die Pause zuerst. */ /* 'irtxbitcount' zaehlt 2 mal Bits da ein Bits jeweils aus Pause und Puls besteht */ if (irtxbitcount != 0) { /* Wenn noch Bits zu senden sind */ if ((irtxbitcount & 0x0001) == 0) { /* Erste Pulshaelfte (Gerade Anzahl von Bithaelften) */ if (irtxdaten & 0x0001) { TIMER1_TOGGLE_INTERRUPT; /* Timer 1 laesst den Ausgang wechseln. 38kHz Puls. */ } else { TIMER1_RESET_INTERRUPT; /* Puls abschalten, Pause */ } } else { /* Zweite Pulshaelfte */ if (irtxdaten & 0x0001) { TIMER1_RESET_INTERRUPT; /* Pause einschalten */ } else { TIMER1_TOGGLE_INTERRUPT; /* Timer 1 laesst den Ausgang wechseln. 38kHz Puls. */ } /* Nach zweiter Bithaelfte wird das nachste Bit vorbereitet */ irtxdaten = irtxdaten >> 1; } /* Jede Bithaelfte mitzaehlen */ irtxbitcount--; } else { /* Nach den IR-Bits wird eine Pause eingelegt in der nichts gesendet wird. (Stoppbits) */ TIMER1_RESET_INTERRUPT; if (irtxpausecount) { irtxpausecount--; } } /* Nebenbei wird noch ein Sekundenzaehler realisiert, der auch den Background immer mal wieder aufweckt. */ timer++; if (timer >= PERIODEFREQ) { timer = 0; sekundenzaehler++; _BIC_SR_IRQ(LPM1_bits); /* Aufwachen und Background einmal durchlaufen lassen */ } /* Fuers kurzzeitge Warten gibt es noch den delaytimer, der in diesem Interrupt runtergezaehlt wird */ if (delaytimer) { delaytimer--; } } /* Die TIMER1 Interruptroutine wird mit zwei verschiedenen Betriebsarten verwendet. */ /* Wenn der IR-Empfaenger einen Interrupt ausgeloest hat, wird durch das Flag 'empfangsmode' */ /* bestimmt, dass nun im halben Bitraster das IR-Signal abzutasten ist und das Signal zu decodieren ist. */ /* Der IR-Interrupt hat dafuer gesorgt, dass die Abtastungen jeweils in den Mitten der Bithaelften stattfinden. */ /* Erwartet wird als Ergebnis eine Zahl von 0 bis 7. Wird aber ein Fehler im IR-Datenstrom gefunden, so wird */ /* eine Zahl der Form 0xFFFn ausgegeben, die als ungueltig erkannt werden kann. */ /* Wird nichts empfangen, so wird der TIMER1 mit 2*38kHz ausgeloest, so dass er, gesteuert durch den Timer0- */ /* Interrupt Lichtpulse mit 38kHz ausloesen kann. */ interrupt (TIMERA1_VECTOR) timera1_interrupt(void) { if (TAIV & 0x02) { if (empfangsmode) { /* Es wird ein IR-Bitstrom empfangen und er muss mit doppelter Bitrate abgetastet werden */ TIMER1_DET_RELOAD; if (irrxbitcount > 0) { /* Es ist noch was zu empfangen */ if ((irrxbitcount & 0x0001) == 0) { /* Erste Bithaelfte */ if (IR_ERKANNT) { /* Wenn Puls erkannt, eine 1 empfangen */ irrxdaten = (irrxdaten >> 1) | (1 << (IRBITS - 1)); } else { /* Sonst ist es eine 0 */ irrxdaten = (irrxdaten >> 1); } } else { /* Zweite Bithaelfte */ if (IR_ERKANNT) { if ((irrxdaten & (1 << (IRBITS - 1))) != 0) { /* Wenn ein Puls kommt, obwohl in der ersten Haelfte schon */ /* einer da war, wird das Ergebnis auf 0xffff gesetzt und */ /* durch irbitcount der Empfang beendet */ irrxbitcount = 1; irrxdaten = 0xffff; /* Fehler melden */ } } else { if ((irrxdaten & (1 << (IRBITS - 1))) == 0) { /* Beenden bei zweiter Pause in Folge */ irrxbitcount = 1; irrxdaten = 0xffff; /* Fehler melden */ } } /* Nichts machen */ } irrxbitcount--; } else { if (irrxpausecount) { if (IR_ERKANNT) { irrxdaten = 0xfff8; /* Fehler melden, keine Pause erkannt */ } irrxpausecount--; } else { /* Wenn keine Bits mehr zu empfangen sind, Timer Interrupt abschalten */ TIMER1_NOINTERRUPT; /* Die Startbits rausschieben */ irrxdaten = irrxdaten >> 2; /* Melden, dass Empfangsdaten anliegen */ irempfang = 1; _BIC_SR_IRQ(LPM1_bits); /* Aufwachen und Background einmal durchlaufen lassen */ empfangsmode = 0; /* Flasg fuer Empfangsmode zuruecksetzen */ } } } else { /* Es wird ein 38*2kHz Interrupt erzeugt */ /* Je nach Programmierung durch Timer0 wird der Ausgang gepulst oder auf 0 gehalten */ TIMER1_IR_RELOAD; } } } /* Diese Routine reagiert auf Interrupts durch Tasten oder den IR-Empfaenger. */ /* Nicht alle Interrupts sind zu jedem Zeitpunkt freigegeben. So ist z.B. im */ /* ausgeschalteten Zustand nur der Interrupt fuer den externen Stecker aktiv. */ /* Es ist darauf zu achten, dass, je nach Quelle, mehrere Interrupts hintereinander */ /* ausgeloest werden koennen (Prellen der Tasten). Das muss im Background abgefangen werden. */ interrupt (PORT1_VECTOR) port1_interrupt(void) { if (P1IFG & IR_PORT) { /* Wenn IR-Empfaenger den Interupt ausgeloest hat */ /* Timer stoppen und Timer-Interrupt auf halbe Bithaelfte einstellen */ TIMER_STOP; TACCR1 = TAR + PERIODECOUNT / 2; /* Naechster Interrupt in der Mitte der Bithaelfte */ TIMER_RUN; /* Merken, dass der Empfang laeuft */ empfangsmode = 1; /* Jetzt keine Interrupts mehr durch den IR-Empfaenger zulassen */ IR_INT_DISABLE; /* Es werden 2*IRBITS ausgewertet */ /* Solange irbitcount != 0 ist, wird im Timerinterrupt geprueft */ irrxbitcount = IRBITS*2; irrxpausecount = PAUSE; /* Das Datenwort wird erst mal auf 0 gesetzt */ irrxdaten = 0; /* Den Timer auf Interruptausloesung einstellen */ TIMER1_INT_RESET; TIMER1_RESET_INTERRUPT; } if (P1IFG & DREI_TASTEN) { /* Wenn eine der Tasten den Interrupt ausgeloest hat, wird das automatische Abschalten verhindert */ aktivzeit = sekundenzaehler; _BIC_SR_IRQ(LPM4_bits); /* Background durchlaufen lassen */ } /* Alle anstehenden Interrupts zuruecknehmen */ P1IFG = 0; } /* ir_out() sendet das datenbyte als RC5-aehnlicher Code aus */ /* Es werden drei Bits Daten aus 'datenbyte' gesendet, also Codes von 0 bis 7 */ /* Eine Pistole sendet als Schuss immer eine 0. */ /* Es werden zwei Startbits hinzugefuegt und mit der TIMER0 Interruptroutine */ /* ausgesendet. Im Anschluss an das Senden wird eine Pause eingefuegt. Die Dauer */ /* wird in 'irtxpausecount' bestimmt. */ /* ir_out() wartet bis die Interruptroutine das Datum vollstaendig gesendet hat. */ /* Dies wird durch das Nullen des Bitzaehlers erkannt. */ void ir_out(int datenbyte) { IR_INT_DISABLE; while (empfangsmode) { /* Einen eventuell stattfindenden Empfang abwarten (das geht auch ohne IR_INT */ } irtxdaten = (datenbyte << 2) | 0x03; /* zwei Startbits hinzufuegen */ TIMER_STOP; TACCR1 = TAR + 10; /* Timer auf baldigen Interrupt programmieren */ TIMER_RUN; irtxpausecount = TXPAUSE; irtxbitcount = IRBITS*2; /* Es werden insgesamt 3 + 2 Startbits gesendet, */ /* das sind 5 * zwei Bithaelften */ while ((irtxbitcount > 0) || (irtxpausecount > 0)); /* Warten bis alles abgearbeitet ist */ IR_INT_RESET; /* Eventuell aufgelaufene IR_Interrupts loeschen */ IR_INT_ENABLE; /* Jetzt wieder IR-Empfangsbereit sein */ } /********************************************************************/ int main(void) { /* Nach dem Einlegen der Batterien wird hier gestartet */ WDTCTL = WDTCTL_INIT; /*Init watchdog timer */ P1OUT = P1OUT_INIT; /* Init output data of port1*/ P2OUT = P2OUT_INIT; /* Init output data of port2*/ P1SEL = P1SEL_INIT; /*Select port or module -function on port1 */ P2SEL = P2SEL_INIT; /*Select port or module -function on port2 */ P1DIR = P1DIR_INIT; /* Init port direction register of port1*/ P2DIR = P2DIR_INIT; /*Init port direction register of port2*/ P1REN = P1REN_INIT; P1IES = P1IES_INIT; /*init port interrupts*/ P2IES = P2IES_INIT; P1IE = P1IE_INIT; P2IE = P2IE_INIT; FCTL2 = FWKEY | FSSEL_MCLK | FLASHDIVIDER; /* Clock fuer Flash-EPROM auswaehlen */ sekundenzaehler = 1000; /* Eine Zeit waehlen, die mit der Initialisierung der diversen anderen Zaehler nicht kollidiert */ timer = 0; /* Schneller Zaehler fuer Interrupts initialisieren */ eint(); /* Interrupts sind jetzt grundsaetzlich zugelassen */ /* Systemfrequenz ist 16MHz */ DCOCTL = CALDCO_16MHZ; BCSCTL1 = XT2OFF | CALBC1_16MHZ; /* Timer 1 soll Periodisch aufgerufen werden */ TACCR0 = PERIODECOUNT; TACCR1 = IRPULSCOUNT; /* Timer 1 setzt den Pin auf 0 und erzeugt periodisch Interrupts */ TIMER1_RESET_INTERRUPT; /* Timer 0 haelt den Pin auf 0, erzeugt aber periodisch Interrupts */ TIMER0_OUTLOW_INTERRUPT; /* Volle Taktfrequenz fuer Timer, einfach immer durchlaufen */ TIMER_RUN; CACTL2 = P2CA2 | P2CA3 | CAF; /* Pin P1.6 als Komparatoreingang waehlen */ CAPD = CAPD6; /* P1.6 als Analogeingang schalten */ /* Einige Initialisierungen machen */ patronen = PATRONEN_PRO_MAGAZIN; magazine = anzahl_magazine = MAGAZINE; LED_AN; blink(2, BLINK_AN_FEHLER, BLINK_AUS_FEHLER); LED_AUS; zustand = ST_SCHUSSBEREIT; /* Der Zustand der Pistole wird hierueber gesteuert */ delaytimer = 0; trefferzeit = 0; aktivzeit = sekundenzaehler; /* letzte Zeit mit Aktivitaet merken */ muetzennummer = MUETZENNUMMER; /* Aktuelle Muetzennummer aus Flash-EPROM holen */ if ((muetzennummer < 1) || (muetzennummer > 7)) { muetzennummer = 1; /* Falls nicht zwischen 1 und 7, wird sie auf 1 gesetzt */ flashWrite(MUETZENNUMMER_ADDR, muetzennummer); /* und im EPROM abgespeichert */ } IR_INT_ENABLE; /* Bevor es in die endlose Backgroundschleife geht, wird der Interrupt des IR-Empfaengers eingeschaltet */ /* Endlosschleife, in der zyklisch alle Eingaben abgearbeitet werden */ while (1) { /* Wenn kein Abzug gedrueckt ist, wird sich schlafen gelegt. Die Zaehler und Interrupts laufen weiter */ if (!ABZUG_GEDRUECKT) { LPM1; /* Aufgeweckt wird durch Tastendruck oder Sekundenzaehler */ } if ((aktivzeit + INAKTIVDAUER) < sekundenzaehler) { /* Wenn die Inaktive Zeit zu lange angedauert hat wird die Pistole ausgeschaltet */ LED_AUS; /* Die LED wird abgeschaltet */ IR_POWER_OFF; /* Der IR-Empfaenger wird abgeschaltet */ NUR_EINSTELLUNG_INT_ENABLE; /* Nur noch der externe Stecker kann einen Interrupt ausloesen */ P1OUT = P1OUT & ~(DREI_TASTEN); /* Tasteneingaenge auf 0 damit Tastendruck keinen Strom verbraucht */ LPM4; /* Alles abschalten und nur noch auf den einen Interrupt durch externen Stecker warten */ /* Hier geht es nur weiter, wenn man den externen Stecker eingesteckt hat. */ P1OUT = P1OUT | DREI_TASTEN; /* Pullups der Tasteneingaenge wieder einschalten */ ALLE_TASTEN_INT_ENABLE; /* Interrupts der Tasten wieder einschalten */ IR_POWER_ON; /* IR-Empfaenger wieder einschalten */ } if (irempfang) { /* Wenn ein Signal empfangen wurde */ irempfang = 0; /* Quittieren, dass man es gelesen hat */ P1IFG = 0; /* Eventuelle Interruptanforderungen vom IR-Empfaenger loeschen */ IR_INT_ENABLE; /* Interrupt durch IR-Empfaenger wieder zulassen */ /* Nun empfangenes Zeichen interpretieren */ if (irrxdaten == muetzennummer) { /* Wenn es die eigene Muetze war */ trefferzeit = sekundenzaehler; /* wird die Trefferzeit festgehalten */ blink(40, BLINK_AN_TREFFER, BLINK_AUS_TREFFER); /* und die Pistole gibt Blinkzeichen von sich. */ } } else { /* Kein Signal empfangen */ if (!(EINSTELLUNG_GESTECKT)) { /* Wenn kein externer Stecker gesteckt ist, wird je nach Zustand der Pistole gehandelt */ switch (zustand) { case ST_SCHUSSBEREIT: if (ABZUG_GEDRUECKT) { if ((trefferzeit + TREFFERDAUER) < sekundenzaehler) { /* Nur wenn ein eventueller Treffer weit genug zurueckliegt */ ir_out(0); /* wird mit einer '0' geschossen */ blink(1, MS(50), SCHUSSPAUSE); /* Der Schuss wird mit der LED angezeigt. Die Blinkpause bestimmt die maximale Schussrate. */ patronen--; /* Eine Patrone weniger */ if (patronen == 0) { /* Wenn keine Patrone mehr uebrig ist, wird in den Zustand ST_MAGAZIN_LEER gewechselt */ zustand = ST_MAGAZIN_LEER; if (magazine == 0) { /* Wenn das aber auch das letzte Magazin war, wird das angezeigt und nach ST_GANZ_LEER gewechselt */ blink(50, BLINK_AN_FEHLER, BLINK_AUS_FEHLER); zustand = ST_GANZ_LEER; } else { LED_AN; /* Wenn noch ein Magazin uebrig ist, geht die LED an und bleibt bis zum Magazinwechsel an */ } } } else { /* Wenn man vor kurzem getroffen wurde, wird nicht geschossen, sondern nur geblinkt */ blink(10, BLINK_AN_TREFFER, BLINK_AUS_TREFFER); } } if (AUSWURF_GEDRUECKT) { patronen = 0; zustand = ST_MAGAZIN_RAUS; LED_AN; while (AUSWURF_GEDRUECKT) { } delay(MS(50)); } break; case ST_MAGAZIN_LEER: if (AUSWURF_GEDRUECKT) { patronen = 0; zustand = ST_MAGAZIN_RAUS; LED_AN; while (AUSWURF_GEDRUECKT) { } delay(MS(50)); } break; case ST_MAGAZIN_RAUS: if (EINSCHUB_GEDRUECKT) { LED_AUS; if (magazine > 0) { magazine--; patronen = PATRONEN_PRO_MAGAZIN; zustand = ST_SCHUSSBEREIT; } } while (EINSCHUB_GEDRUECKT) { } delay(MS(50)); break; case ST_GANZ_LEER: P1IES = ABZUG; break; default: break; } } else { /* Einstellung ist gesteckt */ P1IES = P1IES_INIT; blink(2,BLINK_AN_FEHLER, BLINK_AUS_FEHLER); delay(MS(500)); blink(muetzennummer, BLINK_AN_ZAEHLEND, BLINK_AUS_ZAEHLEND); while (EINSTELLUNG_GESTECKT) { if (ABZUG_GEDRUECKT) { blink(50, BLINK_AN_LOWBAT, BLINK_AUS_LOWBAT); while (EINSTELLUNG_GESTECKT) { } blink(50, BLINK_AN_LOWBAT, BLINK_AUS_LOWBAT); LED_AUS; IR_POWER_OFF; NUR_EINSTELLUNG_INT_ENABLE; P1OUT = P1OUT & ~(DREI_TASTEN); /*Tasteneingaenge auf 0 damit Tastendruck keinen Strom verbraucht */ LPM4; P1OUT = P1OUT | DREI_TASTEN; ALLE_TASTEN_INT_ENABLE; IR_POWER_ON; /* Hier kann noch was hin */ } else if (AUSWURF_GEDRUECKT) { if (anzahl_magazine < 10) { anzahl_magazine += 3; } else { anzahl_magazine = 1; } blink(anzahl_magazine, BLINK_AN_ZAEHLEND, BLINK_AUS_ZAEHLEND); } else if (EINSCHUB_GEDRUECKT) { if (muetzennummer < 7) { muetzennummer++; } else { muetzennummer = 1; } blink(muetzennummer, BLINK_AN_ZAEHLEND, BLINK_AUS_ZAEHLEND); } } flashWrite(MUETZENNUMMER_ADDR, muetzennummer); magazine = anzahl_magazine; patronen = PATRONEN_PRO_MAGAZIN; zustand = ST_SCHUSSBEREIT; } } } }