Simon Game With TM4C123GH6PM

by moalharsani in Circuits > Microcontrollers

26 Views, 0 Favorites, 0 Comments

Simon Game With TM4C123GH6PM

original_1ead2b68-3158-4ecb-a337-d79a585ff7e3_PXL_20241215_213959726.jpg

I implemented the Simon Memory Game, a classic game where players repeat sequences of lights and sounds generated by the system, using the TM4C123GH6PM microcontroller from Texas Instruments.

I wrote the code using Direct Register Access (DRA) to have full control over the microcontroller's hardware. Most of my work involved referring to the microcontroller's datasheet to configure registers for GPIO, timers, and interrupts. The rest of my effort went into developing the game logic, handling interrupts, and generating random sequences.

I’ve uploaded the complete code for reference, along with a video showcasing the game in action.

Downloads

Game Design Overview


The game is designed to present a sequence of elements to the player using LEDs and a buzzer. Each LED color is paired with a distinct buzzer tone to make it easier for the player to identify.

Sequence Generation

  1. Sequence Logic:
  2. A sequence of 32 elements is generated using the rand() function.
  3. The output of rand() is divided by 4, and the remainder (0, 1, 2, or 3) corresponds to one of the LED colors:
  4. 0 → Yellow (Y)
  5. 1 → White (W)
  6. 2 → Blue (B)
  7. 3 → Red (R)
  8. Randomization:
  9. Without a seed, the random sequence would remain the same on every game restart.
  10. To ensure randomness, the srand() function is seeded with the ADC value of a potentiometer connected to the MCU. Rotating the potentiometer generates a different sequence every time the game is restarted.

Gameplay Flow

  1. Starting the Game:
  2. The game begins by playing the first element of the sequence (LED lights up and the corresponding buzzer tone plays).
  3. The system waits for the player to press the correct pushbutton that matches the sequence.
  4. Progression:
  5. If the player presses the correct button, the game progresses to the next level.
  6. The system then plays the sequence from the beginning, adding one more element each time (e.g., 2 elements in level 2, 3 elements in level 3, etc.).
  7. Game Over:
  8. If the player presses the wrong button, all four LEDs blink, and a "game over" tone is played through the buzzer.
  9. The game ends, signaling the player to restart.

System Connection Diagram

Screenshot 2024-12-18 230409.png

Using GPIO A, C, and D to interact with the input and output devices.

GPIOA is used to interact with the LEDs, GPIOC with pushbuttons, GPIOD to interact with the potentiometer and buzzer.


The selection for LEDs and pushbuttons GPIO ports is not restricted, but for the timers and Analog-to-digital converted (ADC) the GPIO port and pin is restricted and can be found in the datasheet for the TM4C123GH6PM

How I Used Pusle-width-modulation to Generate Different Tones?

The MCU is running at a clock speed of 50 MHz, which can be adjusted. This means it takes one second for the CPU to count up to 50 million. How does this help?

In the uploaded video, a "Game Over" tone is played. This tone is essentially a sequence of square waves with different frequencies generated on the PD2 pin, which is connected to a timer.


Example Code:

// Array of tones for the "Game Over" sound sequence
const float tones[] = {349.23, 392.00, 440.00, 493.88, 523.25};

To generate the first tone (349 Hz), we need to create a square wave with a frequency of 349 Hz. How can we do this?

The frequency (f) of a wave is given by: f = 1 / T

We know the frequency we want is 349 Hz, so: 349 = 1 / T

Which gives: T = 0.00286 seconds

This is straightforward to achieve using timers and counters.

Since the CPU is running at 50 MHz, it will take x counts until T = 0.00286 seconds has passed. The count can be calculated as: Count = Desired Delay (T) × CPU Frequency

Substituting the values: Count = 0.00286 × 50,000,000

Count = 143,000

This means the CPU needs to count up to 143,000. After each count to this number, we toggle the PD2 pin (set it to HIGH or LOW). Note that the time it takes for the CPU to toggle the pin is extremely small: 1 / 50,000,000 seconds = 0.00000002 seconds

Thus, the toggling happens almost instantaneously relative to the timer delay.