The old pong game, a game that was released as an arcade game by Atari over 40 years ago had many interpretation throughout the years.
The electronic ping pong got very popular in many countries during the years.
We thought it would be nice to take this simple old game and use our embedded software writing skills to create our own version on an LCD screen and using some kind of game controller to play it. The main board we used is the Stellaris LMF4120 launchapd former known as "tiva". The LCD is a simple chinese screen with resolution of 128X64. The game controller we used was a Wii nunchuck, so the jog on it can move the players boards.
The electrical board has three major components, the LCD, and the two nunchuck controllers.
The LCD is a cheap 128x64 pixels graphical LCD using the ST7921 controller. This controller can support 3 modes of operation, specifically: 8 bit mode, 4 bit mode and a serial interface. For our uses we chose to use 8 bit modes to communicate with the board. It follow a custom protocol in which 8 bits are written to the data bits and the enable control is toggled on and off. The wiring of the LCD to the Tiva C board is presented in the following schematic:
The nunchucks communicate using the I2C protocol, after an initial handshake message they can polled to retrieve the current status of each input. For our game we only used the analog joystick values and the keys. The nunchucks are connected to two different I2C interfaces of the microcontroller as the I2C address of the nunchuck is hard coded into each nunchuck making it impossible to connect both on the same bus.
The LCD controller datasheet maps the LCD screen memory to a 256x64 array in memory (it supports 256x64 pixel screens). Where we have 64 lines and the first 128 bits are mapped to the screens column. However it seems that some ST7921 based screens are mapped differently. Specifically the two halves of the screen use 256x32 bit array where each half of the screen uses half of the array This meant that the first version of the LCD driver only wrote to the upper half of the screen. After updating the driver to the new mapping everything displayed correctly.
To reduce costs we used cheap Chinese knockoff nunchucks instead of ones made by Nintendo. However it appears they differ from the originals in 3 points:
After updating the code to reflect the different hardware we could use the nunchuck data in the game.
The symptom of this issue was that when both the LCD and the nunchucks were initialized one of the nunchucks stopped working and caused a hang when attempting to request data. The reason for this odd behavior is due to the wiring of the Launchpad board. In order to support older launchpads the pins PB6,PB7 and PD0,PD1 (I2C3) are connected together using a 0 ohm resistors. This meant that writing to the LCD caused the I2C communications to fail and the I2C driver hanged on a mster busy signal.
The solution was a to change the I2C pins to different ones available, specifically I2C1 which is on PA6,PA7
The LCD is limited in its response time. While it is relativy fast to change pixel status (on\off) it takes a considerable amount of time for the pixel to fully lit and have it at maximum brightness. When quickly updating the ball position it is required to quickly turn pixels on and off thus making the fall appear ‘faded’.
There only solution we found to fix this problem that didn’t impact gameply was using a different screen which we didn’t have available. Increasing the ball update time allowed the pixels some more time to get fully lighted up, but slowed the ball too much for the game to continue to be fun.
We faced it when we updated too much pixels at once. Too many writes to the screen at different positions causes it to ignore some commands and update the wrong position (16 pixels since the LCD controller is a 16 bit part)
The solution was to use less updates. The actual pixels that should be updated on every refresh are the ball pixels and the players' boards. Instead of using immediate updating for each pixel, we updated an internal buffer of the screen state and then called the LCD hardware sync and update the whole screen.