/hardware/

Ximon78-simon

2020-12-19 15:30:00

Simon.ino

#include <LedControl.h> // LED
#define PLAYER_WAIT_TIME 2000 // The time allowed between button presses - 2s 

byte sequence[100];           // Storage for the light sequence
byte curLen = 0;              // Current length of the sequence
byte inputCount = 0;          // The number of times that the player has pressed a (correct) button in a given turn 
byte lastInput = 0;           // Last input from the player
byte expRd = 0;               // The LED that's suppose to be lit by the player
bool btnDwn = false;          // Used to check if a button is pressed
bool wait = false;            // Is the program waiting for the user to press a button
bool resetFlag = false;       // Used to indicate to the program that once the player lost
byte noPins = 4;              // Number of buttons/LEDs (While working on this, I was using only 2 LEDs)
byte soundPin = 5;            // Speaker output
byte pins[] = {A1, A2, A3, A4}; // Button input pins and LED ouput pins - change these vaules if you wwant to connect yourbuttons to other pins
long inputTime = 0;           // Timer variable for the delay between user inputs

const int DIN_PIN = 4; // LED
const int CS_PIN = 3; // LED
const int CLK_PIN = 2; // LED
LedControl display = LedControl(DIN_PIN, CLK_PIN, CS_PIN); // LED

const uint64_t NUMBERS[] = {
  0x6699999966000000,
  0x4649496946000000,  0xe629e989e6000000,  0xe689e989e6000000,  0x8689e9a9a6000000,  0xe689e929e6000000,  0xe6a9e929e6000000,  0x86898989e6000000,  0xe6a9e9a9e6000000,  0xe689e9a9e6000000,  0x6494949664000000,
  0x2424243624000000,  0xe424e486e4000000,  0xe484e486e4000000,  0x8484e4a6a4000000,  0xe484e426e4000000,  0xe4a4e426e4000000,  0x84848486e4000000,  0xe4a4e4a6e4000000,  0xe484e4a6e4000000,  0x6791979467000000,
  0x4741476447000000,  0xe721e784e7000000,  0xe781e784e7000000,  0x8781e7a4a7000000,  0xe781e724e7000000,  0xe7a1e724e7000000,  0x87818784e7000000,  0xe7a1e7a4e7000000,  0xe781e7a4e7000000,  0x6794979467000000,
  0x4744476447000000,  0xe724e784e7000000,  0xe784e784e7000000,  0x8784e7a4a7000000,  0xe784e724e7000000,  0xe7a4e724e7000000,  0x87848784e7000000,  0xe7a4e7a4e7000000,  0x8784e7a4e7000000,  0x6494979565000000,
  0x4444476545000000,  0xe424e785e5000000,  0xe484e785e5000000,  0x8484e7a5a5000000,  0xe484e725e5000000,  0xe4a4e725e5000000,  0x84848785e5000000,  0xe4a4e7a5e5000000,  0x8484e7a5e5000000,  0x6794979167000000,
  0x4744476147000000,  0xe724e781e7000000,  0xe784e781e7000000,  0x8784e7a1a7000000,  0xe784e721e7000000,  0xe7a4e721e7000000,  0x87848781e7000000,  0xe7a4e7a1e7000000,  0x8784e7a1e7000000,  0x6795979167000000,
  0x4745476147000000,  0xe725e781e7000000,  0xe785e781e7000000,  0x8785e7a1a7000000,  0xe785e721e7000000,  0xe7a5e721e7000000,  0x87858781e7000000,  0xe7a5e7a1e7000000,  0x8785e7a1e7000000,  0x6494949467000000,
  0x2424243427000000,  0xe424e484e7000000,  0xe484e484e7000000,  0x8484e4a4a7000000,  0xe484e424e7000000,  0xe4a4e424e7000000,  0x84848484e7000000,  0xe4a4e4a4e7000000,  0x8484e4a4e7000000,  0x6795979567000000,
  0x4745476547000000,  0xe725e785e7000000,  0xe785e785e7000000,  0x8785e7a5a7000000,  0xe785e725e7000000,  0xe7a5e725e7000000,  0x87858785e7000000,  0xe7a5e7a5e7000000,  0x8785e7a5e7000000,  0x6494979567000000,
  0x2424273527000000,  0xe424e785e7000000,  0xe484e785e7000000,  0x8484e7a5a7000000,  0xe484e725e7000000,  0xe4a4e725e7000000,  0x84848785e7000000,  0xe4a4e7a5e7000000,  0x8484e7a5e7000000,  0xa5a542a5a5000000
};

const uint64_t LOADER[] = {
  0x0000000008000000,  0x0000000018000000,  0x0000001018000000,  0x0000001818000000,  0x0000001c18000000,  0x0000001c1c000000,
  0x0000001c1c040000,  0x0000001c1c0c0000,  0x0000001c1c1c0000,  0x0000001c1c3c0000,  0x0000001c3c3c0000,  0x0000003c3c3c0000,
  0x0000203c3c3c0000,  0x0000303c3c3c0000,  0x0000383c3c3c0000,  0x00003c3c3c3c0000,  0x00003e3c3c3c0000,  0x00003e3e3c3c0000,
  0x00003e3e3e3c0000,  0x00003e3e3e3e0000,  0x00003e3e3e3e0200,  0x00003e3e3e3e0600,  0x00003e3e3e3e0e00,  0x00003e3e3e3e1e00,
  0x00003e3e3e3e3e00,  0x00003e3e3e3e7e00,  0x00003e3e3e7e7e00,  0x00003e3e7e7e7e00,  0x00003e7e7e7e7e00,  0x00007e7e7e7e7e00,
  0x00407e7e7e7e7e00,  0x00607e7e7e7e7e00,  0x00707e7e7e7e7e00,  0x00787e7e7e7e7e00,  0x007c7e7e7e7e7e00,  0x007e7e7e7e7e7e00,
  0x007f7e7e7e7e7e00,  0x007f7f7e7e7e7e00,  0x007f7f7f7e7e7e00,  0x007f7f7f7f7e7e00,  0x007f7f7f7f7f7e00,  0x007f7f7f7f7f7f00,
  0x007f7f7f7f7f7f01,  0x007f7f7f7f7f7f03,  0x007f7f7f7f7f7f07,  0x007f7f7f7f7f7f0f,  0x007f7f7f7f7f7f1f,  0x007f7f7f7f7f7f3f,
  0x007f7f7f7f7f7f7f,  0x007f7f7f7f7f7fff,  0x007f7f7f7f7fffff,  0x007f7f7f7fffffff,  0x007f7f7fffffffff,  0x007f7fffffffffff,
  0x007fffffffffffff,  0x00ffffffffffffff,  0x80ffffffffffffff,  0xc0ffffffffffffff,  0xe0ffffffffffffff,  0xf0ffffffffffffff,
  0xf8ffffffffffffff,  0xfcffffffffffffff,  0xfeffffffffffffff,  0xffffffffffffffff
};

void setup() {
    Serial.begin(9600);         // Start Serial monitor. This can be removed too as long as you remove all references to Serial below
  reset();

  display.clearDisplay(0); // LED
  display.shutdown(0, false); // LED
  display.setIntensity(0, 10); // LED

    showLoader();
}

void showLoader() {
    for (int i = 0; i <= 63; i++) {
    displayImage(LOADER[i]);
        delay(100);
    }
}


// Sets all the pins as either INPUT or OUTPUT based on the value of 'dir'
void setPinDirection(byte dir) {
  for(byte i = 0; i < noPins; i++) {
    pinMode(pins[i], dir); 
  }
}

// send the same value to all the LED pins
void writeAllPins(byte val) {
  for(byte i = 0; i < noPins; i++) {
    digitalWrite(pins[i], val); 
  }
}

// makes beep sound
void beep(byte freq) {
  analogWrite(soundPin, 2);
  delay(freq);
  analogWrite(soundPin, 0);
  delay(freq);
}

// flashes all the LEDs together (freq is the blink speed - small number -> fast | big number -> slow)
void flash(short freq) {
  setPinDirection(OUTPUT); /// We're activating the LEDS now
  for(int i = 0; i < 5; i++) {
    writeAllPins(HIGH);
    beep(50);
    delay(freq);
    writeAllPins(LOW);
    delay(freq);
  }
}

// this function resets all the game variables to their default values
void reset() {
    //flash(500);
  curLen = 0;
  inputCount = 0;
  lastInput = 0;
  expRd = 0;
  btnDwn = false;
  wait = false;
  resetFlag = false;
}

// user lost
void lose() {
  flash(50);  
}

// the arduino shows the user what must be memorized (also called after losing to show you what you last sequence was)
void playSequence() {
  // loop through the stored sequence and light the appropriate LEDs in turn
  for(int i = 0; i < curLen; i++) {
      Serial.print("Seq: ");
      Serial.print(i);
      Serial.print("Pin: ");
      Serial.println(sequence[i]);
      digitalWrite(sequence[i], HIGH);
      delay(500);
      digitalWrite(sequence[i], LOW);
      delay(250);
    } 
}

/// the events that occur upon a loss
void doLoseProcess() {
  lose();             // flash all the LEDS quickly (see Lose function)
  delay(1000);
  //playSequence();     // shows the user the last sequence - So you can count remember your best score - Mine's 22 by the way :)
  //delay(1000);
  reset();            // reset everything for a new game
  displayImage(NUMBERS[0]); // LED
}

/// where the magic happens
void loop() {
  if(!wait) {
        // arduino's turn
    setPinDirection(OUTPUT);                      // We're using the LEDs
    randomSeed(analogRead(A0));                   // https://www.arduino.cc/en/Reference/RandomSeed
    sequence[curLen] = pins[random(0,noPins)];    // Put a new random value in the next position in the sequence -  https://www.arduino.cc/en/Reference/random
    curLen++;                                     // Set the new Current length of the sequence
    playSequence();                               // Show the sequence to the player
    beep(50);                                     // Make a beep for the player to be aware
    wait = true;                                  // Set Wait to true as it's now going to be the turn of the player
    inputTime = millis();                         // Store the time to measure the player's response time
  } else {
    // player's turn
        displayImage(NUMBERS[curLen]); // LED
    setPinDirection(INPUT); // we're using the buttons

    if(millis() - inputTime > PLAYER_WAIT_TIME){  // If the player takes more than the allowed time,
      doLoseProcess();                            // All is lost :(
      return;
    }

    if(!btnDwn) {
      expRd = sequence[inputCount];               // Find the value we expect from the player
      Serial.print("Expected: ");                 // Serial Monitor Output - Should be removed if you removed the Serial.begin above
      Serial.println(expRd);                      // Serial Monitor Output - Should be removed if you removed the Serial.begin above

      for(int i = 0; i < noPins; i++) {           // Loop through the all the pins
        if(pins[i]==expRd)                        
          continue;                               // Ignore the correct pin
        if(digitalRead(pins[i]) == HIGH) {        // Is the buttong pressed
          lastInput = pins[i];
          resetFlag = true;                       // Set the resetFlag - this means you lost
          btnDwn = true;                          // This will prevent the program from doing the same thing over and over again
          Serial.print("Read: ");                 // Serial Monitor Output - Should be removed if you removed the Serial.begin above
          Serial.println(lastInput);              // Serial Monitor Output - Should be removed if you removed the Serial.begin above
        }
      }      
    }

    if(digitalRead(expRd) == 1 && !btnDwn) {        // The player pressed the right button
      inputTime = millis();
      lastInput = expRd;
      inputCount++;                               // The user pressed a (correct) button again
      btnDwn = true;                              // This will prevent the program from doing the same thing over and over again
      Serial.print("Read: ");                     // Serial Monitor Output - Should be removed if you removed the Serial.begin above
      Serial.println(lastInput);                  // Serial Monitor Output - Should be removed if you removed the Serial.begin above
    } else {
      if(btnDwn && digitalRead(lastInput) == LOW) {  // Check if the player released the button
        btnDwn = false;
        delay(20);
        if(resetFlag) {                              // If this was set to true up above, you lost
          doLoseProcess();                          // So we do the losing sequence of events
        } else {
          if(inputCount == curLen) {                 // Has the player finished repeating the sequence
            wait = false;                           // If so, this will make the next turn the program's turn
            inputCount = 0;                         // Reset the number of times that the player has pressed a button
            delay(1500);
          }

        }
      }
    }    
  }
}

void displayImage(uint64_t image) { // LED
    for (int i = 0; i < 8; i++) { // LED
        byte row = (image >> i * 8) & 0xFF; // LED    
        for (int j = 0; j < 8; j++) { // LED
            display.setLed(0, i, j, bitRead(row, j)); // LED
        } // LED
    } // LED
} // LED