Simon's Game
Zo stránky SensorWiki
Záverečný projekt predmetu MIPS / LS2024 - Ondrej Tarcal
Zadanie
Cieľom zadania bolo naprogramovať minihru Simon's game. V skratke minihra by mala fungovať tak, že doska generuje náhodnú sekvenciu a my ju musíme následne zopakovať.
Literatúra:
Analýza a opis riešenia
Tento program som vytvoril na ovládanie štyroch LEDiek pomocou joysticku. Najprv sa navrhlo samotné ovládanie LEDiek joystickom. Následne som dokódoval aby sa najprv LEDky rozsvietili v náhodnej sekvencii. Nakoniec som dokódoval aby po doznení danej sekvencie uživateľ danú sekvenciu zopakoval a program vyhodnotí, či sa sekvencia rovná alebo nerovná roszvietením LEDiek. Joystick sa taktiež využil na zresetovanie a opakované spustenie novej sekvencie aby sa nemusel využívať reset button na doske Arduino.
Program
1. Definície a Inicializácie
Naprv sa preddefinovali makrá pre LEDky a ich polohy a mŕtve zóny joysticka. Inicializácia ADC prevodníka, čítanie z ADC, inicializacia LEDiek, tlačidla na joysticku a kontrola stlačenia tlačidla
2. Funkcie pre samotnú hru
Zobrazenie LEDiek, generovanie náhodných sekvencií a následne zobrazenie sekvencií cez LEDky. Získanie sekvencie od uživateľa cez joystick, kontrola sekvencie a indikácia úspechu alebo neúspechu
3. Main funkcie
V časti main sa program neustále opakuje, generuje náhodne sekvencie, zobrazuje ich pomocou LEDiek, získava od užívateľa sekvencie a porovnáva ich zhodnosť. Program čaká na stlačenie tlačidla na joysticku pre začatie novej sekvencie.
#include <avr/io.h>
#include <avr/io.h>
#include <util/delay.h>
#include <stdlib.h>
#include <stdbool.h>
#define F_CPU 16000000UL
#define LED_LEFT PD2
#define LED_RIGHT PD3
#define LED_DOWN PD4
#define LED_UP PD5
#define BUTTON_PIN PD6
#define THRESHOLD_X_MIN 300
#define THRESHOLD_X_MAX 700
#define THRESHOLD_Y_MIN 300
#define THRESHOLD_Y_MAX 700
void ADC_Init() {
ADMUX = (1 << REFS0); // Set ADC reference to AVCC
ADCSRA = (1 << ADEN) | (1 << ADPS2) | (1 << ADPS1) | (1 << ADPS0); // Zapne ADC a nastavi predelicku na 128
}
uint16_t ADC_Read(uint8_t channel) {
ADMUX = (ADMUX & 0xF0) | (channel & 0x0F); // Select ADC channel
ADCSRA |= (1 << ADSC); // zacne jednotkovu konverziu
while (ADCSRA & (1 << ADSC)); // caka na dokoncenie konverzie
return ADC; // vrati ADC hodnotu
}
void LED_Init() {
DDRD |= (1 << LED_LEFT) | (1 << LED_RIGHT) | (1 << LED_DOWN) | (1 << LED_UP);
PORTD &= ~((1 << LED_LEFT) | (1 << LED_RIGHT) | (1 << LED_DOWN) | (1 << LED_UP));
}
void Button_Init() {
DDRD &= ~(1 << BUTTON_PIN); // tlacitko na joysticku input bude
PORTD |= (1 << BUTTON_PIN); // pull-up resistor
}
bool isButtonPressed() {
return !(PIND & (1 << BUTTON_PIN)); // Return true if button is pressed
}
void displayLED(int ledIndex) {
PORTD &= ~((1 << LED_LEFT) | (1 << LED_RIGHT) | (1 << LED_DOWN) | (1 << LED_UP));
switch (ledIndex) {
case 1:
PORTD |= (1 << LED_LEFT);
break;
case 2:
PORTD |= (1 << LED_RIGHT);
break;
case 3:
PORTD |= (1 << LED_DOWN);
break;
case 4:
PORTD |= (1 << LED_UP);
break;
default:
break;
}
}
void generateRandomSequence(int sequence[], int length) {
for (int i = 0; i < length; i++) {
sequence[i] = (rand() % 4) + 1; // Random cislo medzi 1 az 4
}
}
void displayLEDSequence(int sequence[], int length) {
for (int i = 0; i < length; i++) {
displayLED(sequence[i]);
_delay_ms(5000); // kazdu led vysvieti na dany cas
displayLED(0); // vypne vsetky ledky
_delay_ms(2000); // medzera pred dalsou ledkou vysvietenou
}
}
void getUserInputSequence(int userSequence[], int length) {
for (int i = 0; i < length; i++) {
bool inputReceived = false;
// Wait for a valid input from the joystick
while (!inputReceived) {
if (isButtonPressed()) return; // zresetuje sekvenciu ak sa zatlaci joystick
uint16_t xAxisValue = ADC_Read(0);
uint16_t yAxisValue = ADC_Read(1);
if (xAxisValue < THRESHOLD_X_MIN) {
userSequence[i] = 1; // Left
inputReceived = true;
} else if (xAxisValue > THRESHOLD_X_MAX) {
userSequence[i] = 2; // Right
inputReceived = true;
} else if (yAxisValue < THRESHOLD_Y_MIN) {
userSequence[i] = 3; // Down
inputReceived = true;
} else if (yAxisValue > THRESHOLD_Y_MAX) {
userSequence[i] = 4; // Up
inputReceived = true;
}
// rozsvieti tu LEDku ktoru ma podla inputu
if (inputReceived) {
displayLED(userSequence[i]);
_delay_ms(2000); // Small delay to show the LED
displayLED(0); // Turn off the LED
}
}
}
}
bool checkUserInput(int sequence[], int userSequence[], int length) {
for (int i = 0; i < length; i++) {
if (sequence[i] != userSequence[i]) {
return false; // nespravny input
}
}
return true; // sekvencie sa zhoduju
}
void indicateSuccess() {
// ak sedi sekvencia rozsvieti ledky
PORTD |= ((1 << LED_LEFT) | (1 << LED_RIGHT) | (1 << LED_DOWN) | (1 << LED_UP));
_delay_ms(1000);
PORTD &= ~((1 << LED_LEFT) | (1 << LED_RIGHT) | (1 << LED_DOWN) | (1 << LED_UP));
}
void indicateFailure() {
// ak nesedi sekvencia rozsvieti inak rozsvieti ledky
for (int i = 0; i < 3; i++) {
PORTD |= ((1 << LED_LEFT) | (1 << LED_DOWN));
_delay_ms(200);
PORTD &= ~((1 << LED_LEFT) | (1 << LED_DOWN));
_delay_ms(200);
}
}
int main(void) {
ADC_Init();
LED_Init();
Button_Init();
srand(42); // Initialize random number generator
int sequenceLength = 4;
int sequence[sequenceLength];
int userSequence[sequenceLength];
while (1) {
generateRandomSequence(sequence, sequenceLength);
displayLEDSequence(sequence, sequenceLength);
getUserInputSequence(userSequence, sequenceLength);
if (isButtonPressed()) {
// zresetuje sekvenciu ak je stlaceny joystick
continue;
}
bool sequenceMatched = checkUserInput(sequence, userSequence, sequenceLength);
if (sequenceMatched) {
indicateSuccess();
} else {
indicateFailure();
}
// caka na resetu tlacitko pred zacatim novej sekvencie
while (!isButtonPressed()) {
_delay_ms(100);
}
// Small delay to debounce the button press
_delay_ms(200);
}
return 0;
}
#include <avr/io.h>
void adc_init(void); // A/D converter initialization
unsigned int adc_read(char a_pin);
Zdrojový kód: OndrejTarcal_Simons_game
Overenie
Na používanie nášho programu sa využíva joystick, postup používania tejto minihry je popísany v sekcii popis riešenia
Video:
Kľúčové slová 'Category', ktoré sú na konci stránky nemeňte.