Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /*
- * SpaceInvaders.c
- *
- * Created: 22.05.2014 16:26:08
- * Author: Ehlers
- */
- #define F_CPU 1000000UL
- /* ---------------------------------------------- */
- // Includes
- #include <avr/io.h>
- #include <util/delay.h>
- #include <stdint.h>
- #include <stdlib.h>
- #include "avrx.h"
- #include "avrxfifo.h"
- #include "avrx-io.h"
- #include "avrx-signal.h"
- #include "hardware.h"
- #include "lcd.h"
- /* ---------------------------------------------- */
- // Definitionen
- #define NUMBER_ALIEN_SPECIES 4
- #define SYMBOL_SPACESHIP 1
- #define SYMBOL_SPACESHIP_FIRE 2
- #define SYMBOL_EXPLOSION 3
- #define SYMBOL_MISS 4
- /* ---------------------------------------------- */
- // Globale Variablen
- // Position des Aliens in der erste Reihe
- uint8_t alienPosition;
- // Spezies des Aliens
- uint8_t alienSpecies = 5;
- // Position des Raumschiffes in der zweiten Reihe
- uint8_t spaceshipPosition = 0;
- // Fehlschuesse
- uint8_t spaceshipRemainingEnergie;
- // Punkte des Raumschiffes
- uint8_t spaceshipPoints = 0;
- // Spielzeit
- uint8_t playTime = 60;
- // Variablen zur Spielsteuerung
- uint8_t gameEnd = 1;
- uint8_t fire = 0;
- uint8_t alienBlocked = 0;
- /* ---------------------------------------------- */
- // semaphoreData: Mutual exclusion der globalen Variablen
- AVRX_MUTEX(semaphoreData);
- // semaphoreStart: Start des Spiels
- AVRX_MUTEX(semaphoreStart);
- /* ---------------------------------------------- */
- // Deklaration der Timer (Ein Timer kann nicht in mehreren Prozessen/Tasks genutzt werden)
- TimerControlBlock TickTimerClock;
- TimerControlBlock TickTimerAlien;
- TimerControlBlock TickTimerSpaceship;
- TimerControlBlock TickTimerButton;
- TimerControlBlock TickTimerLCD;
- /* ---------------------------------------------- */
- // Deklaration der Nachrichten und der MessageQueue
- MessageControlBlock UpdateDisplay;
- MessageQueue LcdQueue;
- /* ---------------------------------------------- */
- // AD-Wandlung
- uint16_t adc_read()
- {
- // AD-Wandlung starten
- ADCSRA |= (1<<ADSC);
- // auf Abschluss der Konvertierung warten
- while (ADCSRA & (1<<ADSC));
- // Ergebnis auslesen, umrechnen in Bereich 0-14 und zurückgeben
- return ADCW;
- }
- /* ---------------------------------------------- */
- // Initialisierung des AD Wandlers
- void adc_init()
- {
- // PINA0 als Eingang festlegen
- DDRA &= ~1;
- // Vcc als Referenzspannung
- ADMUX = (1<<REFS0);
- // Aktivieren und Pre-Scaler auf 128
- ADCSRA = (1<<ADEN) | (1<<ADPS0) | (1<<ADPS1) | (1<<ADPS2);
- // Dummy-Wandlung
- adc_read(0);
- }
- /* ---------------------------------------------- */
- // Interrupt Handler für die Timer
- AVRX_SIGINT(TIMER0_OVF_vect)
- {
- IntProlog();
- TCNT0 = TCNT0_INIT;
- AvrXTimerHandler();
- Epilog();
- }
- /* ---------------------------------------------- */
- // Initialisierungen
- void init_function()
- {
- MCUCR = _BV(SE);
- TCNT0 = TCNT0_INIT;
- TCCR0 = TMC8_CK256;
- TIMSK = _BV(TOIE0);
- DDRA = DDRA & ~(1 << PINA1);
- PORTA = PORTA | (1 << PINA1);
- }
- /* ---------------------------------------------- */
- // Zeitmessung
- AVRX_GCC_TASKDEF(taskClock, 30, 0)
- {
- while (1)
- {
- // warte eine Sekunde
- AvrXDelay(&TickTimerClock, 1000);
- // warte auf die Semaphore
- AvrXWaitSemaphore(&semaphoreData);
- // zaehle die Zeit um eine Sekunde runter
- playTime--;
- // falls die Zeit abgelaufen ist...
- if (playTime == 0)
- {
- // setze das Spiel auf beendet
- gameEnd = 1;
- }
- // das LCD aktualisieren
- AvrXSendMessage(&LcdQueue, &UpdateDisplay);
- // Semaphore freigeben
- AvrXSetSemaphore(&semaphoreData);
- }
- }
- /* ---------------------------------------------- */
- // Steuerung des Aliens
- AVRX_GCC_TASKDEF(taskAlien, 60, 0)
- {
- while (1)
- {
- // warte 1 Sekunde
- AvrXDelay(&TickTimerAlien, 1000);
- // warte auf die Semaphore
- AvrXWaitSemaphore(&semaphoreData);
- // die Alienposition zufaellig setzen
- alienPosition = rand() % 14;
- alienBlocked = 0;
- // das LCD aktualisieren
- AvrXSendMessage(&LcdQueue, &UpdateDisplay);
- // Semaphore freigeben
- AvrXSetSemaphore(&semaphoreData);
- }
- }
- /* ---------------------------------------------- */
- // Steuerung des Raumschiffes
- AVRX_GCC_TASKDEF(taskSpaceship, 60, 0)
- {
- uint8_t oldPosition;
- while (1)
- {
- // warte 20 Millisekunden
- AvrXDelay(&TickTimerSpaceship, 20);
- // warte auf die Semaphore
- AvrXWaitSemaphore(&semaphoreData);
- // die alte Position speichern
- oldPosition = spaceshipPosition;
- // die neue Position des Raumschiffes aus dem Wert des AD Wandlers errechnen:
- // 1023 / 74 als Ganzzahl ist 13
- spaceshipPosition = adc_read() / 74;
- // das LCD nur aktualisieren, wenn sich die Position geaendert hat
- if (oldPosition != spaceshipPosition)
- {
- // das LCD aktualisieren
- AvrXSendMessage(&LcdQueue, &UpdateDisplay);
- }
- // Semaphore freigeben
- AvrXSetSemaphore(&semaphoreData);
- }
- }
- /* ---------------------------------------------- */
- // Taster
- AVRX_GCC_TASKDEF(taskButton, 60, 0)
- {
- uint8_t isPressed = 0;
- while (1)
- {
- // warte 10 Millisekunden
- AvrXDelay(&TickTimerButton, 10);
- // falls der Taster gedrueckt ist...
- if (!(PINA & (1 << PINA1)))
- {
- // ... und vorher noch nicht gedrueckt war
- if (!isPressed)
- {
- // warte auf die Semaphore
- AvrXWaitSemaphore(&semaphoreData);
- // falls das Spiel beendet ist
- if (gameEnd)
- {
- // starte das Spiel neu
- gameEnd = 0;
- playTime = 60;
- spaceshipPoints = 0;
- fire = 0;
- spaceshipRemainingEnergie = 10;
- // setze die Start-Semaphore
- AvrXSetSemaphore(&semaphoreStart);
- }
- else
- {
- // wurde das Alien getroffen?
- if (alienPosition == spaceshipPosition)
- {
- // der Schuss war ein Treffer
- fire = 1;
- // erhoehe die Punktzahl
- spaceshipPoints++;
- // es gibt 2 Energiepunkte - 1 verbrauchten Energiepunkt
- spaceshipRemainingEnergie++;
- // setze die neue Alienspezies auf einen zufaelligen Wert
- alienSpecies = 5 + rand() % NUMBER_ALIEN_SPECIES;
- }
- else
- {
- // der Schuss ging daneben
- fire = 2;
- // ziehe einen Energiepunkt ab
- spaceshipRemainingEnergie--;
- // falls keine Energie mehr ueber ist
- if (!spaceshipRemainingEnergie)
- {
- // das Spiel ist vorbei
- gameEnd = 2;
- }
- }
- }
- // das LCD aktualisieren
- AvrXSendMessage(&LcdQueue, &UpdateDisplay);
- // Semaphore freigeben
- AvrXSetSemaphore(&semaphoreData);
- // speichern, dass der Button gedrueckt wird
- isPressed = 1;
- }
- }
- else
- {
- // der Taster ist nicht gedrueckt
- isPressed = 0;
- }
- }
- }
- /* ---------------------------------------------- */
- // LCD Ansteuerung
- AVRX_GCC_TASKDEF(taskLcd, 100, 4)
- {
- MessageControlBlock *p;
- while (1)
- {
- // Wait for messages in the message queue
- p = AvrXWaitMessage(&LcdQueue);
- // Is the message the one we are waiting for?
- if (p == &UpdateDisplay)
- {
- if (gameEnd)
- {
- AvrXWaitSemaphore(&semaphoreData);
- lcd_clear();
- char buf[16];
- switch (gameEnd)
- {
- case 1:
- lcd_setcursor(3, 1);
- snprintf(buf, 16, "Time Over!");
- lcd_string(buf);
- break;
- case 2:
- lcd_setcursor(2, 1);
- snprintf(buf, 16, "No Ammo Left!");
- lcd_string(buf);
- break;
- }
- lcd_setcursor(3, 2);
- snprintf(buf, 16, "Points: %u", spaceshipPoints);
- lcd_string(buf);
- AvrXDelay(&TickTimerLCD, 2000);
- AvrXSetSemaphore(&semaphoreData);
- AvrXWaitSemaphore(&semaphoreStart);
- }
- else
- {
- AvrXWaitSemaphore(&semaphoreData);
- lcd_clear();
- lcd_setcursor(14, 1);
- char buf[3];
- if (playTime < 10)
- {
- snprintf(buf, 3, "0%u", playTime);
- }
- else
- {
- snprintf(buf, 3, "%u", playTime);
- }
- lcd_string(buf);
- lcd_setcursor(14, 2);
- if (spaceshipRemainingEnergie < 10)
- {
- snprintf(buf, 3, "0%u", spaceshipRemainingEnergie);
- }
- else
- {
- snprintf(buf, 3, "%u", spaceshipRemainingEnergie);
- }
- lcd_string(buf);
- if (fire)
- {
- lcd_setcursor(spaceshipPosition, 2);
- lcd_data(SYMBOL_SPACESHIP_FIRE);
- if (fire == 1)
- {
- lcd_setcursor(alienPosition, 1);
- lcd_data(SYMBOL_EXPLOSION);
- alienBlocked = 1;
- }
- else
- {
- lcd_setcursor(alienPosition, 1);
- lcd_data(alienSpecies);
- lcd_setcursor(spaceshipPosition, 1);
- lcd_data(SYMBOL_MISS);
- }
- AvrXDelay(&TickTimerLCD, 250);
- fire = 0;
- }
- else
- {
- if (!alienBlocked)
- {
- lcd_setcursor(alienPosition, 1);
- lcd_data(alienSpecies);
- }
- lcd_setcursor(spaceshipPosition, 2);
- lcd_data(SYMBOL_SPACESHIP);
- }
- AvrXSetSemaphore(&semaphoreData);
- }
- }
- }
- }
- /* ---------------------------------------------- */
- int main(void)
- {
- // Initialisierungen
- // Definition des Stack Pointers der main
- AvrXSetKernelStack(0);
- // Initialisierung von AvrX
- init_function();
- // Initialisierung der LEDs
- lcd_init();
- // Initialisierung des ADW
- adc_init();
- // Definition und Initialisierung des Raumschiffes und der Aliens
- uint8_t symbols[] = {0x00, 0x00, 0x00, 0x04, 0x0A, 0x0A, 0x1B, 0x15,
- 0x04, 0x04, 0x0A, 0x04, 0x0A, 0x0A, 0x1B, 0x15,
- 0x0A, 0x00, 0x11, 0x0A, 0x0A, 0x11, 0x00, 0x0A,
- 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00,
- 0x00, 0x00, 0x00, 0x0E, 0x15, 0x1B, 0x0E, 0x1B,
- 0x00, 0x11, 0x1F, 0x15, 0x1F, 0x0A, 0x0E, 0x0A,
- 0x00, 0x00, 0x0E, 0x15, 0x0E, 0x04, 0x0A, 0x11,
- // Die folgende Zeile ersetzen, um den eigenen Alien zu erstellen
- 0x04, 0x0A, 0x0E, 0x11, 0x0A, 0x04, 0x0A, 0x11};
- for(int i = 0; i < 8; i++)
- {
- lcd_generatechar(i+1, symbols+(i*8));
- }
- // Starten des Tasks
- AvrXRunTask(TCB(taskClock));
- AvrXRunTask(TCB(taskAlien));
- AvrXRunTask(TCB(taskSpaceship));
- AvrXRunTask(TCB(taskButton));
- AvrXRunTask(TCB(taskLcd));
- // Setzen der Semaphore
- AvrXSetSemaphore(&semaphoreData);
- // Aufrufen des Schedulers
- Epilog();
- while(1);
- }
Advertisement
Add Comment
Please, Sign In to add comment