#include <FastLED.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <Encoder.h>
#include "pitches.h"
// LED Configuration
#define NUM_LEDS 16
#define DATA_PIN 3
// Button Configuration
#define RED_BUTTON 7
#define GREEN_BUTTON 6
#define BLUE_BUTTON 10
#define YELLOW_BUTTON 20
// Notes for tones
#define RED_NOTE NOTE_C4
#define GREEN_NOTE NOTE_D4
#define BLUE_NOTE NOTE_E4
#define YELLOW_NOTE NOTE_F4
#define BUZZER_PIN 5
// OLED Configuration
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, -1);
// Rotary Encoder Configuration
#define ENCODER_PIN1 0
#define ENCODER_PIN2 1
Encoder rotaryEncoder(ENCODER_PIN1, ENCODER_PIN2);
// Define the array of LEDs
CRGB leds[NUM_LEDS];
// Game over sound sequence
#define GAME_OVER_TONE_COUNT 3
const int GAME_OVER_TONE[] = {440, 330, 262}; // A4, E4, C4
const int GAME_OVER_DURATION[] = {300, 300, 500}; // 300ms each
const int RED_TONE = 262; // C4
const int GREEN_TONE = 294; // D4
const int BLUE_TONE = 330; // E4
const int YELLOW_TONE = 349; // F4
// Sequence and game state variables
int sequence[100];
int sequenceIndex = 0;
int userIndex = 0;
int currentLevel = 1;
bool gameRunning = false;
void setup() {
Serial.begin(115200);
// Initialize FastLED
FastLED.addLeds<NEOPIXEL, DATA_PIN>(leds, NUM_LEDS);
// Initialize buttons
pinMode(RED_BUTTON, INPUT_PULLUP);
pinMode(GREEN_BUTTON, INPUT_PULLUP);
pinMode(BLUE_BUTTON, INPUT_PULLUP);
pinMode(YELLOW_BUTTON, INPUT_PULLUP);
// Initialize OLED
if(!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
Serial.println(F("SSD1306 allocation failed"));
for(;;);
}
display.clearDisplay();
display.setTextSize(1);
display.setTextColor(SSD1306_WHITE);
display.display();
// Seed the random number generator
randomSeed(analogRead(0));
// Start the game
startGame();
}
// Start a new game
void startGame() {
sequenceIndex = 0;
userIndex = 0;
currentLevel = 1;
gameRunning = true;
addToSequence();
playSequence();
updateDisplay("Level: 1", "Repeat the pattern!");
}
// Add a random color to the sequence
void addToSequence() {
sequence[sequenceIndex] = random(4); // Random number from 0 to 3
sequenceIndex++;
}
// Play the sequence
void playSequence() {
for (int i = 0; i < sequenceIndex; i++) {
lightUp(sequence[i]);
delay(500);
clearLEDs();
delay(200);
}
}
// Light up an LED and play a tone
void lightUp(int color) {
int note;
switch (color) {
case 0: leds[0] = CRGB::Red; note = RED_NOTE; break;
case 1: leds[4] = CRGB::Green; note = GREEN_NOTE; break;
case 2: leds[8] = CRGB::Blue; note = BLUE_NOTE; break;
case 3: leds[12] = CRGB::Yellow; note = YELLOW_NOTE; break;
}
FastLED.show();
tone(5, note, 300); // Play the note on pin 5
}
// Clear all LEDs
void clearLEDs() {
fill_solid(leds, NUM_LEDS, CRGB::Black);
FastLED.show();
}
// Update OLED display
void updateDisplay(const char* line1, const char* line2) {
display.clearDisplay();
display.setCursor(0, 0);
display.println(line1);
display.println(line2);
display.display();
}
void playLevelUpSound() {
tone(BUZZER_PIN, NOTE_E4);
delay(150);
tone(BUZZER_PIN, NOTE_G4);
delay(150);
tone(BUZZER_PIN, NOTE_E5);
delay(150);
tone(BUZZER_PIN, NOTE_C5);
delay(150);
tone(BUZZER_PIN, NOTE_D5);
delay(150);
tone(BUZZER_PIN, NOTE_G5);
delay(150);
noTone(BUZZER_PIN);
}
// Check user input
void checkInput() {
int buttonPressed = -1;
if (digitalRead(RED_BUTTON) == LOW) buttonPressed = 0;
if (digitalRead(GREEN_BUTTON) == LOW) buttonPressed = 1;
if (digitalRead(BLUE_BUTTON) == LOW) buttonPressed = 2;
if (digitalRead(YELLOW_BUTTON) == LOW) buttonPressed = 3;
if (buttonPressed != -1) {
lightUp(buttonPressed);
delay(300);
clearLEDs();
if (buttonPressed == sequence[userIndex]) {
userIndex++;
if (userIndex == sequenceIndex) {
currentLevel++;
playLevelUpSound();
delay(1000);
userIndex = 0;
addToSequence();
updateDisplay("Level:", String(currentLevel).c_str());
playSequence();
}
} else {
gameOver();
}
}
}
void playGameOverSound() {
// Play a Wah-Wah-Wah-Wah sound
tone(BUZZER_PIN, NOTE_DS5);
delay(300);
tone(BUZZER_PIN, NOTE_D5);
delay(300);
tone(BUZZER_PIN, NOTE_CS5);
delay(300);
for (byte i = 0; i < 10; i++) {
for (int pitch = -10; pitch <= 10; pitch++) {
tone(BUZZER_PIN, NOTE_C5 + pitch);
delay(5);
}
}
noTone(BUZZER_PIN);
delay(500);
}
// End the game
void gameOver() {
gameRunning = false;
for (int i = 0; i < 3; i++) {
fill_solid(leds, NUM_LEDS, CRGB::Red);
FastLED.show();
delay(300);
clearLEDs();
delay(300);
}
playGameOverSound();
updateDisplay("Game Over!", "Press to restart.");
delay(2000);
while (true) {
if (digitalRead(RED_BUTTON) == LOW || digitalRead(GREEN_BUTTON) == LOW ||
digitalRead(BLUE_BUTTON) == LOW || digitalRead(YELLOW_BUTTON) == LOW) {
delay(500); // Debounce delay to prevent immediate restart
startGame();
break;
}
}
}
// Main loop
void loop() {
if (gameRunning) {
checkInput();
}
// Rotary Encoder: Adjust brightness or volume
long position = rotaryEncoder.read() / 4; // Adjusting sensitivity
if (position > 0) {
FastLED.setBrightness(min(255, FastLED.getBrightness() + 5));
rotaryEncoder.write(0);
} else if (position < 0) {
FastLED.setBrightness(max(0, FastLED.getBrightness() - 5));
rotaryEncoder.write(0);
}
}
Loading
aitewinrobot-esp32c3-supermini
aitewinrobot-esp32c3-supermini