PIC32 Racing Game

Brandon Guo (bhg39), Dustin Hwang (djh326), Haley Lee (hal64)



Our project is a racing game with human input control that emulates the act of driving a car. We decided on this project, as all three of us greatly enjoy playing games. The goal of the game is to cross the finish line in the shortest amount of time while avoiding obstacle collisions, which result in an added time penalty. The player uses an acceleration pedal, a brake pedal, and a steering wheel to control the movement of the car across the CRT display.

High level design

The majority of our game design is loosely based around general racing games such as Mario Kart but with controls more similar to games such as Subway Surfer. However, since we created our own sound effects and images, the chance of copyright infringement is nonexistent. Our project therefore complies with all standards, as this game is solely our creation.

The goal of our project was to make the controls of our game as similar to the experience of driving a real car. Thus, the functionality of the hardware parts should mimic the functionality of a vehicle. This was achieved by constructing two pedals from wood and 3D printing a steering wheel. Whereas the sensitivity of the pedals was adjusted based on ADC readings of the slide-potentiometers, the wheel’s steering was determined by an accelerometer, which required an Arduino driver.

We opted to not use the TFT on the Big Board to augment the playability of the game. Instead, we connected the display to a CRT (and later, an old-style, black-and-white, analog television), using an NTSC video generation driver our professor had provided us with. The limitations of using the larger display, however, were considerable: we could not properly thread our game, nor use other DMA channels. Additionally, since we used the Small Board and also did not have access to other DMA channels, we had to connect our own DAC using the SPI protocol in order to produce sound effects via direct digital synthesis. Although we originally intended to have more complex sound effects, we decided to use pure sine waves of varying frequencies to save memory space and CPU time.

Program/Hardware Design



To create the pedals, we obtained four pieces of wood of equal size about ¾ inch thick. We chose the material of the pedals to be wood since it was cheap, durable, and we could drill into it. Then, we attached a hinge at the end to connect two pieces of wood together, as well as holes to insert a compression spring between them at the end. We then filled the holes with hot glue to secure the spring. Lastly, we hot glued both pedals to a larger wooden board, so that when the player presses the pedal the pedals do not slide out of place.

Figure 1: Acceleration and brake pedals

Figure 2: Pedal circuit schematic

In order to determine the compression of the pedal, we attached slide potentiometers at the ends where the springs are. We originally hot glued the potentiometer to the end of the pedal, but this would frequently break; to resolve this, we adhered the potentiometer to both the pedal and the board. We used a string to attach the slide to a ring of the spring, so that whenever the spring is compressed, the slide potentiometer indicates by how much. The acceleration and brake pedals were then respectively connected to the PIC32 at pins RB3 and RB2, with a 330 ohm resistor in between.

Steering Wheel

We chose to 3D print our steering wheel so that it was smooth to touch and of the desired design. We hot glued an accelerometer to the back, and connected it to an Arduino mini which acted as the device driver. We used the specific accelerometer library for Arduino we found on the adafruit tutorial page. The accelerometer connects to the mini via I2C. This library allowed us to read the exact orientation of the accelerometer on all three axes. We used the x-axis readings which allowed us to specify rotation regardless of which way the wheel was pointed. We attached very long wires from the wheel to the Arduino to allow for more movement freedom of the wheel. To connect the Arduino to the PIC32, we used a simple parallel interface. We had two wires, the first bit was high/low depending on if the wheel was rotated beyond a certain point left or right and the second bit indicated the direction it was rotated in. One of the things we tried to do but were unsuccessful in completing was creating a bluetooth communication device between the wheel and PIC32. We tried to use XBees S2 to do this, but we found that there were limitations on the small board, specifically due to serial interfaces being used by both the CRT and DAC.

Figure 3: Steering wheel

Figure 4: Arduino accelerator circuit schematic

CRT Circuit

An RCA connector was used to wire the video output of the CRT to the PIC32. We used our professor’s adaptation of Di Jasio’s method of generating sync pulses using one output-compare unit. The CRT sync (SYNC pin 14) and the CRT input (VIDEO pin 3) were respectively connected to ports RB5 and RA1 on the microcontroller. The DAC which combines the SYNC and video signal and adjusts to levels to standard video is shown in the figure below.

Figure 5: CRT circuit schematic

Start/Reset Button

We decided that in order to increase the replayability of the game, we wanted to have a button that will let the user reset the game at his or her discretion. We hot glued this button to the steering wheel in order to make access for the user easier. This was connected to RB4 on the PIC32.

Figure 6: Button circuit schematic


One of our final implementations in hardware was adding a DAC for sound effects. The SPI DAC we used was the MCP4822. We wired the DAC SPI Sclock to pin RB15, the DAC SPI chip select to RB13, and the PPS output to RB11. Using the SPI interface, we were able to connect the analog output of the DAC to an audio socket and speakers.

Figure 7: DAC circuit schematic


NTSC Video Generation on PIC32

To display our game, we used a CRT display which was outputted using DMA. We used DMA channel 1 to output video generation to the CRT. It is drawn by triggering the ISR which operates at 30 MHz. The ISR works by going through each line up to line 262 and using the DMA to transfer information from the pic32 to the screen. It resets at this point and then repeats this process. The timing of the ISR is necessary to maintain the framerate of the game. Besides this, we also have to configure the SPI channel and SYNC channel to get the video generation to work properly. Most of this was already done in the driver code provided on the main course website, so the main issue was wiring it properly and using the functions provided to draw to the screen.


The graphics of our game were done in a pixel art form. To facilitate manually drawing the graphics, we wrote two video functions, video_clear() and video_fill(). As their names imply, these functions respectively fill large rectangular sections with white and clear the screen to completely black.

We started by drawing the car from a top-down view. After we got the car model, we created the background, which was a four-lane road with grass on either side. Finally, we drew obstacles as rectangles in the lanes of the road. To show movement of the car and obstacles, we simply erased the car at the beginning of every frame. Then, we calculated and updated the positions of the car and obstacles. Next, we drew the background and finally we redrew the car. This ensured that the car appeared on top of any obstacles and background (the grass and road).

Figure 8: CRT/Analog TV displays

We also designed a start screen that appears every time the game is reset. On this screen the rules of the game are explained, so that the player does not start the game blindly. Upon pressing the start button from the start screen, the program countdowns from three before the game actually begins. We drew these numbers (3, 2, 1) pixel by pixel, since the provided video text functions made the numbers too small.

Figure 9: Pixellated numbers


We connected the DAC to the pic32 through the SPI channel. We used the first SPI channel for the CRT, and we used the second SPI channel for the DAC. We connected RB13 to this channel and were able to set the sine wave from the ISR.

Sound Output ISR

To output the data to the speakers, we had to use an ISR to output the data. Using the DDS increment, we could set the sine wave table value to the DAC output. Changing the DDS increment value affects the phase which lets us play different notes depending on the different events, specifically finishing the game, hitting an obstacle, or losing all your lives.

Figure 10: DDS algorithm within the ISR

Direct Digital Synthesis

To make our sound effects, we used the same method introduced in lab 1. Our sound effects were pure sine waves at different frequencies to indicate collisions, game over and reaching the finish line. We used an ISR to write values to the DAC at 44kHz from looking up values from a sine table. We declared this sine table in the beginning because if we did it in the ISR it would take too much time. We modified DDS_increment to different frequencies. This worked because we used a sine table lookup to generate the sine wave output and thus increasing and decreasing DSS_increment would dictate how “fast” or “slow” our sine wave was generated, thus changing the frequency.

One side effect that occurred was slight artifacts appeared on the screen after we added the ISR. This was because a separate ISR controlled writing to the CRT display. Having two ISRs messed up the timing slightly, but an easy fix would be to combine the two ISRs into one and change DDS_increment to control sound frequency.

Game Logic

TThe majority of our project was figuring out how to configure the logic in the game to provide a fun and interactive game for the player. There were multiple parts of the ingame logic that we had to discuss, such as obstacle detection, car movement, and finishing conditions. These are the thought process and implementation behind each of them.


Our game turned out very smooth with realistic controls. The pedal configuration had a clean design and worked incredibly reliably; the response from pressing the pedal to controlling the movement of the car was immediate. The steering wheel also responded accurately to the user input, though it was a little too sensitive; since the Arduino Mini does not have a true analog output, we had to take digital readings.

Visually, we had little to no flickering. Though we had a lot of drawings, it did not affect the rate at which the ISR redrew the images. There was no flickering evident when we played the game on the CRT. However, upon switching to the old-style analog television, slight artifacts became apparent. This was likely due to the fact that we had two ISRs running at different speeds; one for the sound effects, and the other for the visual output. Even so, the flickering was so minimal that it did not interfere with the playability of the game at all.

The audio portion of our program also ran reasonably fast, as the sound effects seemed to have no delay between the trigger and output. There were three different and audibly distinct frequencies of sound, one for the obstacle collision, game over, and win game.

We thoroughly tested our game in order to detect and resolve any present bugs. During our play tests, we also made sure that we enforced safety in all our designs. Some choices we made to maintain safety was to 3D print the wheel and to add a block to rest your heels on so that your ankles are not strained due to the height of the pedals. We also tested our game during our lab sections to ensure that there was no interference with our peer’s designs. Ultimately, our game is extremely responsive with easy-to-understand controls.

Final Demo:


Overall, our project definitely met our expectations. We were very happy with the final result and we thought the game was actually very fun. At the beginning of the project, we had very differing ideas on how the project would work regarding the game mechanics. We had different opinions on the FOV and how turning and speed would work. In the end we agreed on the top view frogger style game.

One thing different we could have done was combine the two ISRs into a single one to get rid of artifacts during screen drawing.

One other thing that would be nice for a future update to this project is a partial redesign of the wheel. This time around we used the arduino as the device driver for the steering wheel. However, it might be better to get more precise readings from the wheel using a standard potentiometer. This would require the steering wheel to be mounted, which could also make the project more uniform and put together.

We could also consider the sound effects of the game. Although a flat noise is pretty fitting for the obstacle collision, we could implement FM synthesis to make the finish line and game over sounds more distinct and interesting.

Our project followed all the standards we used like SPI, I2C, RCA and NTSC. Additionally, we followed all safety guidelines as well. Finally, we followed the IEEE code of ethics by making a safe and ethical project that did not harm anybody.

For our base code, we started with code found on the ECE 4760 course website that would allow us to connect with CRT. From here, we independently designed our code to create the game without referencing other websites. We modelled aspects of our game after other traditional racing games, but completely implemented the logic on our own. We did not sign any non-disclosures and only used parts that are traditionally easy to obtain.

There are not many safety considerations for our project, other than the aforementioned concerns in the results section.

For ethical considerations, our project does not violate any of the clauses. Our project was created for the sole purpose of creating a project that some other individual may find fun to play. It does not have any element that could be considered offensive or morally incorrect.

There are no legal concerns for our projects.


Appendix A: Approvals

The group approves this report for inclusion on the course website.

The group approves the video for inclusion on the course youtube channel.

Appendix B: Program Listing

Link to public repository

Appendix C: Schematics

Appendix D: Cost Break Down

Part Vendor Quantity Cost
Accelerometer Adafruit 3 $23.84
CRT/Analog TV Lab rental 1 $0.00
Compression String Lowes 2 $4.50
Wood Lowes 1 $2.00
Screws Lowes 12 $4.00
Hinges Lowes 2 $6.00
Steering Wheel 3D printed 1 $0.00
MicroStickII Lab rental 1 $1.00
Small Board Lab rental 1 $4.00
PIC32MX250F128B Lab rental 1 $5.00
MCP4822, 12-bit DAC Lab rental 1 $3.15
Power Supply Lab rental 2 $10.00
Slide Potentiometers Lab rental 2 $2.00
Arduino Mini Self provided 1 $10.00
Star Button Lab rental 1 $0.00
Resistors and wire Lab rental Many $0.00
Speakers Lab rental 1 $20.00
Total Budget $96.00

Appendix E: Work Distribution

Appendix F: References