Pong Game Explained Finally

Understanding Timer2 Interrupt in Arduino-Part 1 #arduSerie 25

J3
Jungletronics
9 min readMar 8, 2017

--

Hello, hobbyist!!! Welcome!!!

Tutorial goals:

After completing this AVR Atmel Studio 7 Simulation tutorial readers should be able to:

. Play ping-pong with Arduino;

. Configure Timer2 interrupt in 1 kHz (any, actually…) in Arduino;

. Understand how Pong code works inside, with the help of Atmel Studio 7 Simulator;

. Analyze the code step by step, module by module, until the final code. We divide to conquer !!! There will be 3 tutorials, 3 codes…

. Calculate the overflow time on an interrupt, and make your next code
following a secure coding standard;

. Work with any Matrix 8 x 8 LED, our is like this: HS-2088B / 23088A:

….Let’s just jump into that pool !!! Here my breadboard:

Schema of the Implementation of this game with 74HC138 and Arduino Uno

Based on: LEDMatrix from Electronic Thingies for Doing al kinds of Fun Stuff

Here is a matrix 8 x 8 that we implement the game
Collections of images to generate a video simulation; each image is renewed in 8 millisseconds (125 Hz)

This is the original code:

hardware reset or hard reset of a computer system

We start by introducing you to how this code (it’s a fragment of this code that plays pong) works inside.

int n;void setup() {
for (int z = 2; z < 14; z++) {
pinMode(z, OUTPUT); }
TCCR2A = 0;
TCCR2B = 4;
TIMSK2 = 1 << TOIE2;
TCNT2 = 0x06;
}
void loop() { digitalWrite(12, HIGH);
// delay(100);
}
ISR(TIMER2_OVF_vect) {
TCNT2 = 0x06;
PORTD &= 0xE3;
PORTD |= (n << 2) & 0x1C;
n++;

if (n > 7) {
n = 0;
}
}

Let me explain the motivation: did you already see one of those codes that only geniuses are capable of creating?
One that looks simple but has interruptions, assembler, ports, and those complicated things? Probably, right!?
I’ve always been intrigued by the beauty of such a code that operates a simple game of ping-pong in the end.
We have already published on the subject, but now let’s go the extra mile…!!!
My methodology: I look, observe, understand what I see and then publish it.
This is a brief tutorial to put you in the game too…Let’s break this code apart … and understand it, of course!

Nothing is so complicated that we can not understand. Let’s get started!!!!

Arduino uses ATmega328P — Of course one may always refer to the Microcontroller’s datasheet. Grab yours and… without further ado here is the explanation of that code.

The first highlighted parts of the code are carefully examined below:

TCCRnA:

Where CR stands for Control Register, therein TCCRnA, Timer / Counter CR.
default: Normal operation; OC2A disconnected

TCCRnB:
Clock divisor 1:64 (prescale); set to 4h.

TIMSKn:

Where TIMSK stands for Timer Interrupt MaSK Controls register, which interrupts the Timer can trigger. Overflow interrupt flag enabled

TCNTn:
Timer/Counter initialized by 0x06 (256–6 = 250); see calculations below ;-)

Every time you need to set up an interrupt in Arduino follow this sequence again (TCCRnA, TCCRnB, TIMSKn, and TCNTn).

Remember Arduino runs on 16 000 000Hz (16MHz) and Timer2 is 8-bit.

Lets calculate the overflow and frequency rate:

OVF (Overflow)

C (Max count for this register 8-bit discounted)

P (Prescale —clock divisor)

F (Clock Frequency)

OVF = C * P * F

OVF = CountMax * Prescale * FrequencyClock

OVF = (256–6) * 64 * (1/16000000)

OVF = 250 * 64 * 0,0000000625

OVF = 0,001 seconds = 1 millisecond

T (Period) F (Frequency)

T = 1 / F

F = 1 / TF = 1 / 0,001F = 1000 Hz = 1 KHz

That’s it, in each millisecond the interrupt occurs and ISR(TIMER2_OVF_vect) is called.

And what happens on this Interrupt Service Routine?

Alright, let’s see this part of the code: we first restart the counter, which start with zero, because of the hardware reset or hard reset of a computer system (see calculation above why we init as hex 6):

TCNT2 = 0x06

Then we reset the pins 2, 3, and 4 so that the next operation counts up zero to seven on these three bits in binary nicely. Since these pins will be connected to the 74hc138 input, we will now have the de-multiplexed count for the eight bits of the array. This code will work as a film projector (let the game appear on screen).

PORTD &= 0xE3 

E3 = 11100011 —> which reset PIN 2,3,4

Let’s break it down:

PORTD contains:     XXXXXXXX
bit-wise AND with: 11100011
--------
PORTD now equals: XXX000XX ( resets pins 2,3 and 4 )

Remember:

Operator And is Accurate; needs two equals, if not, nothing done … 
1 plus 1 is 1, and 0 plus 0 is 0. Closed.

So if it appears the zero it will always be zero independent of the other operand. So where it has zero with AND it resets the bits!

Next:

PORTD |= (n << 2) & 0x1C

Here it is a bit more complex: there are two operations; One with AND (&), another with OR (|) together with attribution, see the rule:

Operator Precedence table:op    desc       order      sequence
!= equality 1 left to right
& bit-wise AND 2 left to right
^ bit-wise XOR 3 left to right
| bit-wise OR 4 left to right

Precedence is the order in which a computer language evaluates expressions. Operators with higher precedence are evaluated first even though they do not appear first in the left to right ordering.

Let’s break it down:

First part: (n << 2) & 0x1C

Range of n: 0 to 7

nº   Binary
0 = 00000000
1 = 00000001
2 = 00000010
3 = 00000011
4 = 00000100
5 = 00000101
6 = 00000110
7 = 00000111

Let’s suppose n = 7; then n = 00000111 << 2 (seven bit-wise left by 2) result 00011100. Make this (n << 2) & 0x1C operation resulting in:

n contains:         00011100
bit-wise AND with: 00011100 (1C = 00011100 — Mask it out)
--------
Result1 now equals: 00011100
Second part: PORTD |= 00011100

Continuing breaking it down (now OR operator):

PORTD contains:    XXXXXXXX
bit-wise OR with: 00011100 (Result1 from the first part)
--------
PORTD now equals: XXX111XX (Do not affect others, but bits 2,3,4)

Remember:

Operator Or is Oaf. Accept any truth. 
1 and 0 equals 1, and 0 and 1 is 1.
It all can be accepted as true. It is an idiot operator…

All operations will result in a count of 0 to 7 of bits 2, 3, and 4, inside a loop. The other bits will not be affected. This portion of the code generates the image refresh rate. It works like a movie projector, letting the scene appear on the screen. This is the work of the 74HC138 chip (columns) while the Arduino takes care of drawing the paddle bats and the ball (rows)…

That’s it!!!

The end part:

 n++; 
if (n > 7) {
n = 0; …}

Makes the loop from 0 to 7, refreshing byte to byte in the rows, drawing the game, nothing more than this… See note in the code in GitHub:)

Now let’s run this code in the Atmel Studio 7 simulator and see inside:

Go to your Atmel Studio 7 app…

File > New > Project and hit Create Project from Arduino Sketch (for details see this video).

Name: as you wish, mine is Pong_explained_00
Location: set your project folder

Choose ATmega328p as chip and there you go!

The Atmel Studio 7 will create a main.cpp and Sketch.cpp (your program).

Now go in the extreme left of Sketch.cpp and double click in void setup() function to mark the first breakpoint. Set another immediately
where TNCT2 = 0x006 line are.

Click Start Debugging and Break (Alt + F5) and debug session starts.

The Cycle Counter = 86. It means that the Arduino did serial port initializations and other pertinent routines.

What interests us is more ahead. Click Continue (F5) and the yellow arrow should stop in the setup of our code. great!!
In I/O Port select PORTD and click Step Over (F10) and bits 2, 3, 4, 5, 6 and 7 will be set (Corresponding to the pins 2–7 of PORTD).
Continue clicking Step Over (F10) and the rest of pins will be set up (pins 0–5 for PORTB). All are now OUTPUT.
In the 26th click, the yellow arrow is now in TCCR2B = 4.
That’s because TCCR2A is ‘as is’ and we are setting the interrupt right now.
Now detach I/O windows and enlarge it (see video as a guide).
Choose Timer/Counter, 8-bit Async (TC2) peripheral, by selecting it.
Pay attention to the bits of TCC2B (mainly CS2). This line will set 3rd bit, configuring it as prescale 1:64.
Go ahead and F10 again.
Now expand the bits of TIMSK2 (look for TOIE — Overflow Interrupt Enable will be set).
That enables the interrupt of Timer2.
F10 again.
The counter value (TCNT2) are initialized in 6 hexadecimal; see calculations above.
In the next F10, we will inside the ISR routine. Get the explanations above and
Turn your attention to the StopWatch in Processor Status window.
All operations will be completed in Approximately 3 millionths of a second (69,56–66,69 = 2,87 us).
See those bitwise operations are executed with absolute speed !!!
Now click three times on Continue(F5) and you will be positioned inside ISR again. The difference is that you are 1 000 us ahead. That represents a millisecond that we configured the overflow. Awesome!!!

You can keep playing, trying to understand the code even more. Here ends the first part.

On the next page we will continue the implementation of the code towards the final code. Do not miss it !!!

We’re always adding new stuff so make sure to come back as often as you can!

Thank you for your visit and see you soon in the continuation of this tutorial!

Curiosity:

How fast is an eye blink?

A real blink of an eye takes 300 to 400 milliseconds.
Since there are 1000 milliseconds in each second, a blink of an eye takes around 1/3 of a second. Compared to the time span of one full second, a blink of an eye is an eternity.

If we are interrupting at each 1 ms (as calculated above), we get 300 interruptions in the blink of an eye. 300 changes of every 8 columns, resulting in 37.5 times the entire screen is renewed. that’s awesome!!!

On the other hand, it is known that your eyes blinks about 150 times per minute. This means a frequency of 2.5 Hz. One second, two and a half blinks…awesome!

Think about it…

1 blink = 400ms

2.5 blinks = 1000ms (per second)

2.5 * 60 = 150 blinks (per minute)

6.400.000 Arduino Cycles * ( 1/16.000.000) = 0.4 sec => 400 ms

In other words: within each wink, the Arduino has already executed more than six million operations already! What a great speed!

How long does it take the brain to process an image?

U.S. researchers discovered that the human brain can interpret images that the eye sees in just 13 millisecondsthe first evidence of such rapid processing speed. That speed is almost eight times faster than the 100 milliseconds recorded by previous.

“The fact that you can do that at these high speeds indicates 
to us that what vision does is find concepts. That’s what the
brain is doing all day long — trying to understand what we’re
looking at,”

says Mary Potter, an MIT professor of brain and
cognitive sciences and senior author of the study.

Download all Archive for this Project

References:

Arduino Pong Game w/ IC 74HC138!!! 01 #arduSeriestudies

Proteus — Arduino & IC 74HC138 — Simple Ping Pong

Arduino Matrix Led Display Ping Pong

The Royal Society Article — High-speed camera characterization of voluntary eye blinking kinematics

In the blink of an eye — MIT neuroscientists find the brain can identify images seen for as little as 13 milliseconds by MIT News

reviewed text & links @ Nov, 2022

--

--

J3
Jungletronics

😎 Gilberto Oliveira Jr | 🖥️ Computer Engineer | 🐍 Python | 🧩 C | 💎 Rails | 🤖 AI & IoT | ✍️