#include #include #include "PinChangeInterrupt.h" //HP music #define NOTE_B0 31 #define NOTE_C1 33 #define NOTE_CS1 35 #define NOTE_D1 37 #define NOTE_DS1 39 #define NOTE_E1 41 #define NOTE_F1 44 #define NOTE_FS1 46 #define NOTE_G1 49 #define NOTE_GS1 52 #define NOTE_A1 55 #define NOTE_AS1 58 #define NOTE_B1 62 #define NOTE_C2 65 #define NOTE_CS2 69 #define NOTE_D2 73 #define NOTE_DS2 78 #define NOTE_E2 82 #define NOTE_F2 87 #define NOTE_FS2 93 #define NOTE_G2 98 #define NOTE_GS2 104 #define NOTE_A2 110 #define NOTE_AS2 117 #define NOTE_B2 123 #define NOTE_C3 131 #define NOTE_CS3 139 #define NOTE_D3 147 #define NOTE_DS3 156 #define NOTE_E3 165 #define NOTE_F3 175 #define NOTE_FS3 185 #define NOTE_G3 196 #define NOTE_GS3 208 #define NOTE_A3 220 #define NOTE_AS3 233 #define NOTE_B3 247 #define NOTE_C4 262 #define NOTE_CS4 277 #define NOTE_D4 294 #define NOTE_DS4 311 #define NOTE_E4 330 #define NOTE_F4 349 #define NOTE_FS4 370 #define NOTE_G4 392 #define NOTE_GS4 415 #define NOTE_A4 440 #define NOTE_AS4 466 #define NOTE_B4 494 #define NOTE_C5 523 #define NOTE_CS5 554 #define NOTE_D5 587 #define NOTE_DS5 622 #define NOTE_E5 659 #define NOTE_F5 698 #define NOTE_FS5 740 #define NOTE_G5 784 #define NOTE_GS5 831 #define NOTE_A5 880 #define NOTE_AS5 932 #define NOTE_B5 988 #define NOTE_C6 1047 #define NOTE_CS6 1109 #define NOTE_D6 1175 #define NOTE_DS6 1245 #define NOTE_E6 1319 #define NOTE_F6 1397 #define NOTE_FS6 1480 #define NOTE_G6 1568 #define NOTE_GS6 1661 #define NOTE_A6 1760 #define NOTE_AS6 1865 #define NOTE_B6 1976 #define NOTE_C7 2093 #define NOTE_CS7 2217 #define NOTE_D7 2349 #define NOTE_DS7 2489 #define NOTE_E7 2637 #define NOTE_F7 2794 #define NOTE_FS7 2960 #define NOTE_G7 3136 #define NOTE_GS7 3322 #define NOTE_A7 3520 #define NOTE_AS7 3729 #define NOTE_B7 3951 #define NOTE_C8 4186 #define NOTE_CS8 4435 #define NOTE_D8 4699 #define NOTE_DS8 4978 #define REST 0 // change this to make the song slower or faster int tempo = 120; // change this to whichever pin you want to use int buzzer = 5; // melody for wrong answer int wrong_melody[] = { NOTE_C4, 4, NOTE_A3, 4, NOTE_G3, 4, NOTE_E3, 4, NOTE_D3, 4 }; int wrong_notes = sizeof(wrong_melody) / sizeof(wrong_melody[0]) / 2; // melody for correct answer int correct_melody[] = { NOTE_C5, 4, NOTE_D5, 4, NOTE_E5, 4, NOTE_G5, 4, NOTE_F5, 4 }; int correct_notes = sizeof(correct_melody) / sizeof(correct_melody[0]) / 2; // melody game over int gameover_melody[] = { NOTE_C3, 4, NOTE_E3, 4, NOTE_G3, 4, NOTE_AS3, 2, NOTE_C4, 2, NOTE_AS3, 2, NOTE_G3, 2, NOTE_E3, 2 }; int gameover_notes = sizeof(gameover_melody) / sizeof(correct_melody[0]) / 2; // this calculates the duration of a whole note in ms (60s/tempo)*4 beats int wholenote = (60000 * 4) / tempo; int divider = 0, noteDuration = 0; LiquidCrystal_I2C lcd(0x27, 16, 2); const int SW_pin = 11; const int X_pin = 0; const int Y_pin = 1; const int IR1_pin = 2; const int IR2_pin = 3; const int ledRed_pin = 8; const int ledGreen_pin = 7; const int button_pin = 4; volatile int score1; volatile int score2; volatile int contor; volatile int gamePhase; volatile int currentPlayer; volatile int updatePlayerMessage; volatile int currentAnswer; volatile bool joystickPressed; int lastButtonState; // Previous state of the button int buttonPressCount; int question_id; int used_questions[11]; void setup() { // put your setup code here, to run once: //initialize variables score1 = 0; score2 = 0; contor = 1; gamePhase = 0; currentPlayer = 0; updatePlayerMessage = 0; currentAnswer = 0; joystickPressed = false; buttonPressCount = 0; lastButtonState = HIGH; for (int i = 1; i <= 10; i++) { // 0 - unused qustion ; 1 - used question used_questions[i] = 0; } // initialize the LCD, lcd.begin(); // // Turn on the blacklight and print a message. lcd.backlight(); lcd.clear(); lcd.print("Are you ready? "); lcd.setCursor (0,1); // go to start of 2nd line lcd.print("Press the button!!"); //ir senzor Serial.begin(9600); pinMode(IR1_pin, INPUT);// set pin as input attachInterrupt(digitalPinToInterrupt(IR1_pin), sensor1Interrupt, RISING); pinMode(IR2_pin, INPUT);// set pin as input attachInterrupt(digitalPinToInterrupt(IR2_pin), sensor2Interrupt, RISING); //joystick pinMode(SW_pin, INPUT_PULLUP); attachPCINT(digitalPinToPCINT(SW_pin), joystickInterrupt, CHANGE); digitalWrite(SW_pin, HIGH); //led red pinMode(ledRed_pin, OUTPUT); pinMode(ledGreen_pin, OUTPUT); //button pinMode(button_pin, INPUT_PULLUP); } void loop() { int reading = digitalRead(button_pin); // Check if the button state has changed if (reading != lastButtonState) { // Reset the button press count if button state changes from HIGH to LOW if (reading == LOW) { buttonPressCount++; if (buttonPressCount >= 2) { // Restart the game setup(); return; // Exit the loop to prevent further execution of game code } if (gamePhase == 0) { gamePhase = 1; //show question delay(1000); } } } // Update the last button state lastButtonState = reading; if (gamePhase == 1) { //show question question_id = random(1,10); while(used_questions[question_id] != 0) { question_id = random(1,10); } show_question(question_id); gamePhase = 2; // wait for player selection used_questions[question_id] = 1; } if(gamePhase == 3) { lcd.clear(); lcd.print("It's your turn,"); lcd.setCursor (0,1); lcd.print("player "); lcd.print(currentPlayer); gamePhase = 4; // show answer options delay(3000); } if (gamePhase == 4) { show_answers(question_id); gamePhase = 5; // wait for player to pick an answer } if (gamePhase == 6) { //show result check_answer(question_id); contor++; currentPlayer = 0; if (contor > 5) { gamePhase = 7; } else { gamePhase = 1; } } if (gamePhase == 7) { game_over(); } } void sensor1Interrupt() { if (gamePhase == 2 && currentPlayer == 0) { currentPlayer = 1; gamePhase = 3; //show message for selected player } } void sensor2Interrupt() { if (gamePhase == 2 && currentPlayer == 0) { currentPlayer = 2; gamePhase = 3; //show message for selected player } } void joystickInterrupt() { if (gamePhase == 5 && joystickPressed == false) { get_answer(); joystickPressed = true; } if (gamePhase == 5 && joystickPressed == true) { joystickPressed = false; gamePhase = 6; } } void show_question(int contor) { if (contor == 1) { lcd.clear(); lcd.print("La ce port este"); lcd.setCursor (0,1); // go to start of 2nd line lcd.print("conectat pinul 3"); delay(1000); } else if (contor == 2) { lcd.clear(); lcd.print("Cati pini are "); lcd.setCursor (0,1); // go to start of 2nd line lcd.print("uC ATmega328P ?"); delay(1000); } else if(contor == 3) { lcd.clear(); lcd.print("Cate timere are "); lcd.setCursor (0,1); // go to start of 2nd line lcd.print(" ATmega328P ?"); delay(1000); } else if (contor == 4) { lcd.clear(); lcd.print("Care este dim. "); lcd.setCursor (0,1); // go to start of 2nd line lcd.print("memoriei EEPROM?"); delay(1000); } else if (contor == 5) { lcd.clear(); lcd.print("Pe cati biti"); lcd.setCursor (0,1); // go to start of 2nd line lcd.print("este uC ATmega328P ?"); delay(1000); } else if (contor == 6) { lcd.clear(); lcd.print("De ce tip este"); lcd.setCursor (0,1); // go to start of 2nd line lcd.print("ADC-ul uC-ului"); delay(1000); } else if (contor == 7) { lcd.clear(); lcd.print("Pe ce pin este"); lcd.setCursor (0,1); // go to start of 2nd line lcd.print("semnalul SDA ?"); delay(1000); } else if (contor == 8) { lcd.clear(); lcd.print("Pe ce pin este"); lcd.setCursor (0,1); // go to start of 2nd line lcd.print("semnalul MISO ?"); delay(1000); } else if (contor == 9) { lcd.clear(); lcd.print("Ce tip de comuni"); lcd.setCursor (0,1); // go to start of 2nd line lcd.print("care este I2C?"); delay(1000); } else if (contor == 10) { lcd.clear(); lcd.print("Ce este PWM?"); delay(1000); } } void show_answers(int contor) { if (contor == 1) { lcd.clear(); lcd.print("A. A"); lcd.setCursor (0,1); // go to start of 2nd line lcd.print("B. D"); } else if (contor == 2) { lcd.clear(); lcd.print("A. 28"); lcd.setCursor (0,1); // go to start of 2nd line lcd.print("B. 32"); } else if(contor == 3) { lcd.clear(); lcd.print("A. 3"); lcd.setCursor (0,1); // go to start of 2nd line lcd.print("B. 4"); } else if (contor == 4) { lcd.clear(); lcd.print("A. 1KB"); lcd.setCursor (0,1); // go to start of 2nd line lcd.print("B. 2KB"); } else if (contor == 5) { lcd.clear(); lcd.print("A. 8"); lcd.setCursor (0,1); // go to start of 2nd line lcd.print("B. 16"); } else if (contor == 6) { lcd.clear(); lcd.print("A.cu aprox succ"); lcd.setCursor (0,1); // go to start of 2nd line lcd.print("B.cu integrare"); delay(1000); } else if (contor == 7) { lcd.clear(); lcd.print("A. A3"); lcd.setCursor (0,1); // go to start of 2nd line lcd.print("B. A4"); delay(1000); } else if (contor == 8) { lcd.clear(); lcd.print("A. 10"); lcd.setCursor (0,1); // go to start of 2nd line lcd.print("B. 12"); delay(1000); } else if (contor == 9) { lcd.clear(); lcd.print("A. asincrona"); lcd.setCursor (0,1); // go to start of 2nd line lcd.print("B. sincrona"); delay(1000); } else if (contor == 10) { lcd.clear(); lcd.print("A.Modulare impuls "); lcd.setCursor (0,1); // go to start of 2nd line lcd.print("B.Pulsator wireless"); delay(1000); } delay(1000); } void get_answer() { int x = analogRead(X_pin); int y = analogRead(Y_pin); if( x <= 490) { currentAnswer = 1; return; } if (x >= 520) { currentAnswer = 2; return; } } void check_answer(int contor) { if(contor == 1) { if(currentAnswer == 2) { //corect print_answer(1); update_score(1); } else { //wrong print_answer(0); update_score(0); } } else if(contor == 2) { if(currentAnswer == 2) { //corect print_answer(1); update_score(1); } else { //wrong print_answer(0); update_score(0); } } else if(contor == 3) { if(currentAnswer == 1) { //corect print_answer(1); update_score(1); } else { //wrong print_answer(0); update_score(0); } } else if(contor == 4) { if(currentAnswer == 1) { //corect print_answer(1); update_score(1); } else { //wrong print_answer(0); update_score(0); } } else if(contor == 5) { if(currentAnswer == 1) { //corect print_answer(1); update_score(1); } else { //wrong print_answer(0); update_score(0); } } else if(contor == 6) { if(currentAnswer == 1) { //corect print_answer(1); update_score(1); } else { //wrong print_answer(0); update_score(0); } } else if(contor == 7) { if(currentAnswer == 1) { //corect print_answer(1); update_score(1); } else { //wrong print_answer(0); update_score(0); } } else if(contor == 8) { if(currentAnswer == 2) { //corect print_answer(1); update_score(1); } else { //wrong print_answer(0); update_score(0); } } else if(contor == 9) { if(currentAnswer == 2) { //corect print_answer(1); update_score(1); } else { //wrong print_answer(0); update_score(0); } } else if(contor == 10) { if(currentAnswer == 1) { //corect print_answer(1); update_score(1); } else { //wrong print_answer(0); update_score(0); } } } void print_answer(int corect) { if (corect == 1) { lcd.clear(); lcd.print("You are right!"); lcd.setCursor (0,1); // go to start of 2nd line lcd.print(" + 10 points"); light_and_sound_effects(1); delay(1000); } else { lcd.clear(); lcd.print("You are wrong!"); lcd.setCursor (0,1); // go to start of 2nd line lcd.print(" - 5 points"); light_and_sound_effects(0); delay(1000); } } void light_and_sound_effects(int corect) { if (corect == 1) { //correct answer effects digitalWrite(ledGreen_pin, HIGH); playMelody(correct_melody, correct_notes); digitalWrite(ledGreen_pin, LOW); } else { //wrong answer effects digitalWrite(ledRed_pin, HIGH); playMelody(wrong_melody, wrong_notes); digitalWrite(ledRed_pin, LOW); } } void playFinalMelody(const int *melody, int notes){ // iterate over the notes of the melody. // Remember, the array is twice the number of notes (notes + durations) int state = HIGH; for (int thisNote = 0; thisNote < notes; thisNote++) { //light effects digitalWrite(ledGreen_pin, state); digitalWrite(ledRed_pin, state); // calculates the duration of each note divider = melody[thisNote + 1]; if (divider > 0) { // regular note, just proceed noteDuration = (wholenote) / divider; } else if (divider < 0) { // dotted notes are represented with negative durations!! noteDuration = (wholenote) / abs(divider); noteDuration *= 1.5; // increases the duration in half for dotted notes } // we only play the note for 90% of the duration, leaving 10% as a pause tone(buzzer, melody[thisNote], noteDuration * 0.9); // Wait for the specief duration before playing the next note. delay(noteDuration); // stop the waveform generation before the next note. noTone(buzzer); if (state == 1) { state = 0; } else { state = 1; } } } void playMelody(const int *melody, int notes){ // iterate over the notes of the melody. // Remember, the array is twice the number of notes (notes + durations) for (int thisNote = 0; thisNote < notes; thisNote++) { // calculates the duration of each note divider = melody[thisNote + 1]; if (divider > 0) { // regular note, just proceed noteDuration = (wholenote) / divider; } else if (divider < 0) { // dotted notes are represented with negative durations!! noteDuration = (wholenote) / abs(divider); noteDuration *= 1.5; // increases the duration in half for dotted notes } // we only play the note for 90% of the duration, leaving 10% as a pause tone(buzzer, melody[thisNote], noteDuration * 0.9); // Wait for the specief duration before playing the next note. delay(noteDuration); // stop the waveform generation before the next note. noTone(buzzer); } } void update_score(int correct) { if (currentPlayer == 1) { if (correct == 1) { score1 += 10; } else { score1 -= 5; } } if (currentPlayer == 2) { if (correct == 2) { score2 += 10; } else { score2 -= 5; } } } void game_over() { if (score1 < score2) { lcd.clear(); lcd.print("Congrats!Player2"); lcd.setCursor (0,1); // go to start of 2nd line lcd.print("is the winner."); } else if (score1 > score2) { lcd.clear(); lcd.print("Congrats!Player1"); lcd.setCursor (0,1); // go to start of 2nd line lcd.print("is the winner."); } else { lcd.clear(); lcd.print("It's a tie."); lcd.setCursor (0,1); // go to start of 2nd line lcd.print("Try again."); } playFinalMelody(gameover_melody, gameover_notes); gamePhase = 8; } void restart() { score1 = 0; score2 = 0; contor = 1; gamePhase = 0; currentPlayer = 0; updatePlayerMessage = 0; currentAnswer = 0; joystickPressed = false; lcd.clear(); lcd.print("Are you ready? "); lcd.setCursor (0,1); // go to start of 2nd line lcd.print("Press the button!!"); delay(1000); }