Snake Game Console


Developed the game "Snake" using embedded C programming and several hardware components. The microcontroller used was the ARM Cortex-M4 on Texas Instrument's MSP432P401R Launchpad. The project consisted of using UART in order for the microcontroller to communicate with an external LCD (liquid crystal display) and using I2C in order to communicate with an external LRA (haptic feedback motor). In addition, we used peripherals on the Launchpad such as the ADC, pwm pins, and gpio pins to perform various other functions.

Quick Demo

     The above demo shows gameplay of our snake game with fully functioning matrix LED, LCD, joystick, and haptic motor driver. As shown, the LCD displays the score of the game, the joystick is used to control movement of the snake, and the haptic motor driver vibrates whenever the snake hits an apple.

Hardware Components
  • SparkFun Serial Enabled 16x2 LCD - White on Black 3.3V
  • Texas Instruments MSP-EXP432P401R SimpleLink MSP432 Launchpad
  • Sparkfun Haptic Motor Drive - DRV2605L
  • Adafruit 32x32 Matrix LED
  • Adafruit 2-Axis Thumb Joystick
  • AA Batteries
  • Adafruit Battery Case
  • Sparkfun LRA Motor
  • OSH Park Custom Fabricated PCB

Project Scope

     The project was to build the classical game Snake, using the 32x32 RGB LED matrix as a display, and an analog 2-axis thumb joystick as a controller. A 4xAA battery holder with a switch powers the matrix LED, and a USB connection to the MSP432 powers the rest of the project. A SparkFun 16x2 SerLCD displays the score of the game and uses UART to communicate with the MSP432. The game starts by moving any direction on the joystick and ends when the snake touches itself or the edge of the display. The LRA vibrates once the game is over and each time the snake eats an apple. The matrix LED display also presents a start screen and game over screen at the beginning and end of each playthrough.

     For this project we wrote our own UART, ADC, matrix LED, and LCD drivers, as well as the code for the snake game. We used a prewritten I2C driver, instead of writing our own in order to operate the DRV2605L and LRA. Our custom PCB is used to connect the MSP432 to all of the other components in order to reduce the amount of wires and provide a more compact design.

Functional Block Diagram

     This is a diagram of all the components of the project and how they connect to each other on a high level. 

Figure 1: Functional Block Diagram

Figure 1: Functional Block Diagram

Wiring Diagram

     Below is a wiring diagram, showing all of the pin connections between the MSP432, the PCB, and other components. We went very detailed with this diagram, including how many pins needed to be on the PCB and the locations of pins on the MSP432, so that we could have a better idea of the wiring before the parts arrived.

Figure 2: Wiring Diagram

Figure 2: Wiring Diagram


     This is the schematic for our PCB made using Autodesk Eagle. We used net labels for all of the pins instead of drawing the wire connections between them. We added an extra set of pins for each component to isolate the component and debug if needed (These pins came in handy when using the logic analyzer to debug UART communication between the LCD and the MSP432).

Figure 3: PCB Schematic

Figure 3: PCB Schematic

Figure 4: PCB Layout

Figure 4: PCB Layout

Figure 6: Fabricated PCB

Figure 6: Fabricated PCB (top view)

Figure 7: Fabricated PCB (bottom)

Figure 7: Fabricated PCB (bottom view)

Firmware Calculations

ADC14: For the ADC, we used the sample and hold pulse mode with one sample per every 192 ADC14CLK cycles. The source clock for the ADC14CLK was MODCLK, and the selection of 192 for the sample and hold time was completely arbitrary. We did not need to sample at a certain amount of time because the samples were already occurring fast enough so that there was no delay in the movement of the joystick and the snake.

     One part of the ADC that did require calculation was the memory conversion values. If the conversion was greater than 4000 or less than 100, the ADC14_ISR would either set the joystick direction to up/down or left/right. The range of conversion values was 0 to 4092 because of the 12-bit resolution setting. The reason for the choice of >= 4000 or <=100 was so that the joystick would not be sensitive to diagonal movements, which would make the game easier to play since the snake does not move diagonally.

UART: For the UART we decided to use the 9600 baud rate because that is the default for the LCD we bought. The clock source we used was SMCLK which was at 3MHz. To calculate the N value we divided 3MHz by 9600 to get 312.5, then we knew os16 had to be one because N was greater than 16. Then we took the integer of N/16 to get that UCBRx value to be 19. Then to find UCBRFx we took the INT(N/16-INT(N/16)*16) which gave us 0x08. Finally, we looked at a table in the technical reference manual to find UCBRSx to find that it equals 0xAA. Once we had all those values we set them in the A2 register which set up the correct baud rate.

Matrix LED: For the matrix LED, we figured out that we would have to set MCLK to 48MHz because otherwise it would not update fast enough. When we had MCLK set to its default value of 12MHz, the matrix would only update at a frequency of 28Hz, which caused the display to blink. In order to combat this problem, we set MCLK to 48MHz so that the MSP432 would be able to update the pins connected to the matrix LED fast enough. Once we completed this task, the Matrix LED was able to update at about 130Hz.

In-Depth Explanation of Code

Joystick: adc.c

     In the adc.c file, we incorporated five functions. The ADC14_GPIO_CONFIG() function is used to put pin 5.0 and 5.2 into analog input mode by using the SELx registers. The ADC14_INIT function is used to enable interrupts globally, in the NVIC module, and in ADC14’s IER register. This function also sets up two memory control registers and puts ADC14 into repeated autoscan mode so that the MSP432 can read two different analog inputs. This was needed because the joystick has two analog outputs for the X and Y directions. The ADC14_ISR_Xout and ADC14_ISR_Yout functions basically read the conversion result and print right and/or up if the conversion result is greater than or equal to 4000. It prints left and/or up if the conversion result is less than or equal to 100. The ADC14_IRQHandler function triggered whenever the joystick is moved. When the function is triggered it calls either ADC14_ISR_Xout or ADC14_ISR_Yout based on the highest priority interrupt in the ADC14IV register. The register view within Code Composer Studio was very helpful for debugging this C file. It allowed me to see that the MEM[1] register was not being loaded with conversions. After further reading in the MSP432 datasheet, I found out that I would have to use the repeat autoscan mode or manually alter the CSTARTADDx bits in order for this register to be loaded with conversion results.

Figure 3: adc.c Functionality Test

Figure 8: adc.c functionality test

UART.c for LCD

     Used UART to communicate with the LCD. Used the UART interrupts and created a circular buffer in order to put bytes in and out of the TXBUF and RXBUF in the UART. Has received and send string, but the only one used is send string because the LCD doesn’t send anything back. We created a structure called bufr_t to make the circular buffer, and manipulated this circular buffer using the remove and insert byte functions. The IRQ handler is what used those functions to actually make the UART work and have it send the information. In the config function we set up the UART and the baud rate to 9600 which we chose because it is the default baud rate of the LCD.

Figure 9: Working LCD

Figure 5: Logic Analyzer on LCD

Figure 10: Testing LCD with logic analyzer

Matrix LED code:

     The snake game now plays on the matrix LED. We have several several files that make this happen one for the snake game play and one for the updating of the matrix. We also change the master clock to run at 48MHz so that the game would be smooth and without glitches.

     Due to very limited documentation on the Matrix LED, this component was very difficult to get running. Through the process of writing a driver for the Matrix LED, we learned that the MCLK would have to run at 48MHz. This is because when we ran our snake game code on the Matrix LED, the display would update at only 28Hz. This caused blinking on the display while we were playing the game because human eyes can detect the change in light up until about 60Hz. The 48MHz MCLK brought the update frequency to about 130Hz, which got rid of the blinking.

     We also ended up figuring out that the panel is only able to light up two rows of LEDs at a time. If the address sent to the display is 4’b0000, then the 1st and 17th row of LEDs light up. It takes 32 clock cycles before all LEDs light up, and the RGB pins on the matrix LED panel select which colors to send to the LED. After all 32 clock cycles, we latched the RGB values through the LAT pin, and then enabled outputs through the OE_n pin. After a short delay, we toggled the LAT pin again and then disabled outputs, and incremented the address to 4’b0001. We kept repeating this process in our code until it reached address 15. Upon reaching address 15, we reset the address to 4’b0000. The function that contains this code is called void read(uint8_t matrix[32][32]) and can be found in the matrixLED.c file through the Github link.

Snake Code:

     The code for the actual snake game can be found in the snake.c file through the Github link, and consists of a variety of functions that manipulate matrices, that are then sent to the void read(uint8_t matrix[32][32]) function in order to actually be displayed as LED colors.




  1. Excellent blog, I read your post, and I get knowledge about the Joystick. You have done excellent work. Buy PC Joystick for Gaming Online in Australia.Please keep sharing.

  2. You have a genuine capacity to compose a substance that is useful for us. You have shared an amazing post about Buy from japan online .Much obliged to you for your endeavors in sharing such information with us.

  3. You have done good work by publishing this article here.How to buy from japan online I found this article too much informative, and also it is beneficial to enhance our knowledge. Grateful to you for sharing an article like this.

  4. It is what I was searching for is really informative.Mens Vintage Clothing Stores Online It is a significant and useful article for us. Thankful to you for sharing an article like this.

  5. Great project! Your Snake Game Console looks amazing, and it's impressive how you were able to fit all the components in such a compact design. I'm particularly interested in the PCB layout services you used, as it seems like a crucial aspect of the project's success. It's inspiring to see how technology can be used to create fun and engaging games. Keep up the good work!


Post a Comment