#include #include #define LCD_I2C_ADDRESS 0x27 #define LCD_COLUMNS 20 #define LCD_ROWS 4 #define RED PB2 #define GREEN PB3 #define BLUE PB4 #define YELLOW PB5 #define FOTOR1 PC0 #define FOTOR2 PC1 #define FOTOR3 PC2 #define FOTOR4 PC3 #define PIEZO_PIN PB1 #define MAX_SEQUENCE_LENGTH 15 #define BUTTON_THRESHOLD 50 LiquidCrystal_I2C lcd(LCD_I2C_ADDRESS, LCD_COLUMNS, LCD_ROWS); int sensorValue1 = 0; int sensorValue2 = 0; int sensorValue3 = 0; int sensorValue4 = 0; int gameRunning = 1; int sequenceLength = 0; int sequence[MAX_SEQUENCE_LENGTH]; int playerSequence[MAX_SEQUENCE_LENGTH]; int levelDiff; int songLength = 17; char notes[] = "cdaf gf adfgc gc "; int beats[] = {1,1,1,1,1,4,4,2,1,1,1,1,1,1,4,4,3}; int tempo = 130; volatile uint32_t elapsedSeconds = 0; ISR(TIMER1_OVF_vect) { elapsedSeconds++; } void setAdcChannel(int PIN) { switch (PIN) { case PC1: ADMUX |= (1 << MUX0); break; case PC2: ADMUX |= (1 << MUX1); break; case PC3: ADMUX |= (1 << MUX1) | (1 << MUX0); break; case PC4: ADMUX |= (1 << MUX2); break; default: break; } } void readInputFromPhotoR(int PIN, int *sensorValue) { ADMUX = (1 << REFS0); setAdcChannel(PIN); ADCSRA = (1 << ADPS2) | (1 << ADPS1) | (1 << ADPS0); ADCSRA |= (1 << ADEN); ADCSRA |= (1 << ADSC); while (ADCSRA & (1 << ADSC)) { } *sensorValue = ADC; ADCSRA &= ~(1 << ADEN); } void readUserInput() { readInputFromPhotoR(FOTOR1, &sensorValue1); readInputFromPhotoR(FOTOR2, &sensorValue2); readInputFromPhotoR(FOTOR3, &sensorValue3); readInputFromPhotoR(FOTOR4, &sensorValue4); } void testLED() { PORTB |= (1 << RED) | (1 << GREEN) | (1 << BLUE) | (1 << YELLOW); delay(500); PORTB &= ~(1 << RED) & ~(1 << GREEN) & ~(1 << BLUE) & ~(1 << YELLOW); delay(500); } void generateSequence() { for (int i = 0; i < MAX_SEQUENCE_LENGTH; i++) { sequence[i] = rand() % 4; } } void showLEDSequence() { for (int i = 0; i < MAX_SEQUENCE_LENGTH - levelDiff; i++) { int led = sequence[i]; PORTB |= (1 << (led + RED)); delay(500); PORTB &= ~(1 << (led + RED)); delay(500); } } void showLEDSequencePlayer() { for (int i = 0; i < MAX_SEQUENCE_LENGTH - levelDiff; i++) { int led = playerSequence[i]; PORTB |= (1 << (led + RED)); delay(500); PORTB &= ~(1 << (led + RED)); delay(500); } delay(2000); } void wait(unsigned int us) { for(unsigned int i=0; i < us; i++) { _delay_us(1); } } void playTone(uint16_t frequency, uint16_t duration) { uint16_t period = (uint16_t)(1000000 / frequency); for (uint16_t i = 0; i < duration * 1000 / period; i++) { // Toggle the PIEZO_PIN to generate the tone PORTB ^= (1 << PIEZO_PIN); wait(period / 2); } // Turn off the piezo after the tone duration PORTB &= ~(1 << PIEZO_PIN); } void playSadSong() { // Define the notes of the sad song (frequency and duration) uint16_t sadSong[] = { 262, 500, // C4 196, 500, // G3 196, 500, // G3 220, 1000, // A3 262, 1000, // C4 220, 1000, // A3 196, 1000, // G3 196, 500 // G3 }; // Play each note of the sad song for (uint16_t i = 0; i < sizeof(sadSong) / sizeof(sadSong[0]); i += 2) { uint16_t frequency = sadSong[i]; uint16_t duration = sadSong[i + 1]; playTone(frequency, duration); } } int frequency(char note) { int i; const int numNotes = 8; char names[] = { 'c', 'd', 'e', 'f', 'g', 'a', 'b', 'C' }; int frequencies[] = {262, 294, 330, 349, 392, 440, 494, 523}; for (i = 0; i < numNotes; i++) { if (names[i] == note) { return(frequencies[i]); } } return(0); } void youLostSong() { int i, duration; for (i = 0; i < songLength; i++) { duration = beats[i]*tempo; if (notes[i] == ' ') { delay(duration); } else { playTone(frequency(notes[i]), duration); } delay(tempo/10); // brief pause between notes } } void getPlayerInput() { lcd.clear(); lcd.setCursor(2, 0); lcd.print("Let's see if you"); lcd.setCursor(3, 1); lcd.print("memorised it."); int index = 0; elapsedSeconds = 0; sei(); while (index < MAX_SEQUENCE_LENGTH - levelDiff) { readUserInput(); if (sensorValue1 < 100) { playerSequence[index] = 0; PORTB |= (1 << (0 + RED)); delay(1000); PORTB &= ~(1 << (0 + RED)); index++; } else if(sensorValue2 < 100) { playerSequence[index] = 1; PORTB |= (1 << (1 + RED)); delay(1000); PORTB &= ~(1 << (1 + RED)); index++; } else if(sensorValue3 < 100) { playerSequence[index] = 2; PORTB |= (1 << (2 + RED)); delay(1000); PORTB &= ~(1 << (2 + RED)); index++; } else if(sensorValue4 < 100) { playerSequence[index] = 3; PORTB |= (1 << (3 + RED)); delay(1000); PORTB &= ~(1 << (3 + RED)); index++; } if (index > 0) { if (sequence[index - 1] != playerSequence[index - 1]) { gameRunning = 0; lcd.clear(); lcd.print("Wrong!"); youLostSong(); delay(2000); break; } else { lcd.clear(); lcd.print("Correct!"); delay(2000); } } if (elapsedSeconds > 10) { cli(); lcd.clear(); lcd.print("Time is up!"); delay(2000); break; } } cli(); } void setup() { DDRB |= (1 << RED) | (1 << GREEN) | (1 << BLUE) | (1 << YELLOW); DDRB |= (1 << PIEZO_PIN); levelDiff = 14; lcd.begin(LCD_COLUMNS, LCD_ROWS); lcd.backlight(); TCCR1B |= (1 << CS12) | (1 << CS10); TIMSK1 |= (1 << TOIE1); } void loop() { if(levelDiff == 14) { lcd.setCursor(3, 0); lcd.print("Welcome to this"); lcd.setCursor(5, 1); lcd.print("this game!"); lcd.setCursor(8, 2); lcd.print("Wait..."); delay(5000); lcd.setCursor(8, 2); lcd.print("Ready!"); delay(1000); lcd.clear(); } if (!gameRunning) { lcd.clear(); lcd.setCursor(0, 0); lcd.print("Game ended, sorry!"); delay(5000); lcd.clear(); levelDiff = 14; gameRunning = 1; } else { lcd.setCursor(0,0); lcd.print("I will generate the"); lcd.setCursor(5, 1); lcd.print("sequence!"); lcd.setCursor(3, 2); lcd.print("Pay attention!"); delay(2000); lcd.clear(); generateSequence(); showLEDSequence(); getPlayerInput(); if(levelDiff > 0) { levelDiff--; } } }