:GAME ZIP 64 for the BBC micro:bit - Review

Table of contents

RoadTest: :GAME ZIP 64 for the BBC micro:bit

Author: luislabmo

Creation date:

Evaluation Type: Development Boards & Tools

Did you receive all parts the manufacturer stated would be included in the package?: True

What other parts do you consider comparable to this product?: None that I know of.

What were the biggest problems encountered?: One of RGB LED failed to light blue (green and red ok). One pin of the edge connector was bent.

Detailed Review:

The Kitronik :GAME ZIP 64 is an all in one hand-held gaming solution for the BBC micro:bit or in other words, a gaming accessory focused on helping build simple projects -mostly retrogames and robotics- as it incorporates inputs/outputs similar to modern game controllers. The micro:bit acts like a game cartridge allowing to easily swap to another microbit if desired.

 

Features

Some of the included features:

  • Edge Connector for the BBC micro:bit
  • 4 x directional buttons
  • 2 x fire buttons
  • 2 x Expansion pads positioned accurately to add trigger-like buttons. These expansion pads also provide breakout for P19 and P20 (providing room to connect I2C devices).
  • 64 (8x8) individually addressable RGB LEDs
  • Vibration motor
  • Piezo buzzer
  • 3 x AA Battery Holders
  • 4 x M3 mounting holes

 

First impressions

The :GAME ZIP 64 comes packaged in a retail package (clear Thermoformed Packaging) with a 2-page brochure that includes pin mapping and general information. All components feel safely soldered without any visible bad-solder joints. The built-in 12mm tactile switches are very responsive, seem of good quality and each come with 12x12mm Snap Fit Caps.

 

{gallery:width=960,height=768,autoplay=false} Unboxing

GAME ZIP 64: Retail package

Brochure - front: Pin mapping

Brochure - back: Quick reference

Front: Kitronik GAME ZIP 64

Back: Kitronik GAME ZIP 64

microbit: Supplied for this review by Element14

Together: microbit and kitronik GAME ZIP 64

GAME ZIP 64: Zoomed in addressable RGB LED

Rainbow: Zoomed in addressable RGB LEDs

 

The :GAME ZIP 64 brings a very simple design which uses a two layer, 1.6 mm thick PCB as the main body, this build type feels rigid and doesn't seem to represent a durability risk as all the components soldered add extra rigidity. Every component is clearly labeled and as an added bonus, there is an online datasheet and plenty of documentation available.

 

The available expansion pads in my opinion have small holes, I was not able to use my mini-grabber test clips securely and found them getting disconnected some times when working on my tests; this may be by design, to keep components in place when soldering but, my take on small holes is that they won't allow solder to flow inside the holes properly by capillary action.

 

The 8x8 LED display is really bright!, so bright I found myself lowering its brightness at the first lines of code of most of my sketches. Brightness and colors seem consistent across all the LEDs, well except on one -more on this next-.

 

First issues found

I found two issues that did not stop me from reviewing and testing the device as intended.

 

Bent pin on the Edge Connector

One of the pins of the Edge Connector was very close to the next one, after using some magnification I verified visually that they were not shorted. I addressed this issue by straightening the pin with my finger.

 

Bad Addressable RGB LED

Seems the blue channel of one of the addressable RGB LED was not making proper contact; I believe bad solder is not the problem as we are talking about addressable RGB LEDs here. I think this issue may be due to bad contact of the conductors inside the epoxy encapsulation-, I realized this because it would work -at some times- when I put some pressure on it with my fingernail.

Powering the :GAME ZIP 64

Power to the :GAME ZIP 64 is provided via the built in 3 x AA battery holders, which are placed strategically to mimic hand-grips in the same way as modern gaming controllers have (or to mimic a DSLR hand-grip).

{gallery:width=960,height=768,autoplay=false} :GAME ZIP 64 batteries

GAME ZIP 64: 3 x AA Batteries

Hand-grips: GAME ZIP 64 batteries hand-grips

 

When powering the :GAME ZIP 64 with batteries, it provides regulated power to the BBC micro:bit and provides power also to the 3.3V and GND expansion pads. According to the datasheet only extra 100mA total is available to external components:

 

To work with the 8x8 RGB LED display, power must be provided using the AA batteries, the (8x8) display won't work just by providing power to the USB port in the microbit. On a side note, I was able to work all the time with rechargeable AA batteries without any issue.

Switch that turns ON/OFF power from batteries

 

Coding with Microsoft MakeCode

Since the microbit's main goal is to get you started with coding with focus on teaching and learning, it made sense to start some of my tests/examples using the Microsoft MakeCode Editor. I was not familiar with this platform so it was the perfect opportunity to start learning myself.

 

Simple Pacman animation with sound

To star working properly with the :GAME ZIP 64 in the Microsoft MakeCode, it is recommended to start by adding the Game Zip MakeCode Blocks. These add basic functionality like triggers when the buttons are pressed, functions to use the 8x8 display or an individual LED and so on:

 

Go to the Extensions menu

 

Search for "game zip" and add it

 

The :GAME ZIP64 extension should be available now.

 

I then started coding a simple Pacman animation with sound. I created the animation by alternating 4 basic frames. When tilting the microbit left or right (roll) this would change what part of the next frame needed to be displayed (remember the display is only 8x8) giving the impression the Pacman is chasing a ghost.

 

To simplify the process, I initialized the the matrix with a basic template, and as the animation goes to each different frame, it just updates the pixels that would change at any given point of time only. Simple eh?

 

{gallery:width=542,height=232,autoplay=false} Pacman animation matrix

Pixels that may change: Pixels that may change between each frame, marked with X

Pacman frame 0: Pacman animation, Frame number 0

Pacman frame 1: Pacman animation, Frame number 1

Pacman frame 2: Pacman animation, Frame number 2

Pacman frame 3: Pacman animation, Frame number 3

 

The above results in a fluid Pacman animation chasing a ghost. Sound was created with the pacman notes from here. In the video can be appreciated when pressing the fire buttons, actions are performed without interrupting the sound, which indicates that they may be programmed internally using interrupts .

 

 

This animation example is available in the file microbit-pacman-intro.hex attached.

 

NeoPixel

The neopixel extension allow us use addressable RGB LEDs with the microbit and also works with the :GAME ZIP's LEDs. To add this extension I used the same steps as before, except this time I typed "neopixel" in the search bar.

Once the extension was added, I made a simple sketch to show a rainbow demonstrating how practical is to light the LEDs with the neopixel extension.

 

This neopixel example is available in the file microbit-Neopixel-test.hex attached.

 

A bug found in MakeCode

It was brought to my attention that when using the display.show block, it will freeze the microbit when there were no changes applied to any of the 64 addressable RGB LEDs.

Practical examples with MicroPhyton

MicroPhyton is the version of Python that the BBC micro:bit uses. As part of this review, it made sense to me to provide a couple of practical examples in this programming language also.

 

Testing the I2C serial protocol

The :GAME ZIP 64 breaks out the micro:bit's SCL (Pin19) and SDA (Pin20) to interface with I²C devices.

The datasheet also brings important notes regarding the use of Pins 19 and 20 as GPIOs:

To test the I²C serial protocol communication capabilities of the micro:bit together with the :GAME ZIP 64, I created a simple sketch in Micro:bit - Python editor to connect a Nintendo Nunchuk Controller (other Phyton editors could be used like Mu).

To interface with the Nunchuk controller I took inspiration from here and removed all the unnecessary code, actually I ended up having to remove the Classes/Objects approach and had to stick with just a simple function to do all the the work, I will explain the reasons for this approach later on.

from microbit import *

#initialize nunchuk
i2c.write(0x52, bytes([0x40,0x00]), repeat=False)
sleep(1)

def read_nunchuk ():
    i2c.write(0x52, b'\x00', repeat=False)
    sleep(1)
    buf = i2c.read(0x52, 6, repeat=False)
    data = [(0x17 + (0x17 ^ buf[i])) for i in range(6)]
    #axis_X, axis_Y
    return data[0],data[1]

while True:
    joyX, joyY = read_nunchuk()
    
    if joyX < 100:
        display.show("<")
    elif joyX > 154:
        display.show(">")
    else:
        display.show("-")
    sleep(10)

 

 

This I²C test is also available in the file microbit_wii-nunchuk_test.py attached.

 

Playing Bit Pong with a Nintendo Nunchuk Controller

To wrap up my review (and as part of my RoadTest application), I wanted to modify an existing game to add the ability to control it -or to control part of it- using the Nunchuk Controller via I²C, so I took the pong game for the :GAME ZIP 64 and modified to use the Nunchuk as a way to control the movements for Player1 which ended up working pretty well and it was very simple to accomplish .

 

 

Initially I tried to incorporate the source code found earlier into the pong game, but this ended with a Memory Error that I couldn't fix with the recommendations. After several tests, I had to remove all the unnecessary code and had to replace the Classes/Objects approach to a single function that did the necessary work to make things work and to avoid the Memory Error.

 

from microbit import *
import neopixel
from random import randint

# Enable NeoPixels to use x & y values
def np_plot(x, y, r, g, b):
    np[x+(y*8)] = (r, g, b)
  
def start_sequence(x_position):
    if x_position == 7:
        ball_x = 1
        ball_y = 3
        direction = 1
    elif x_position == 0:
        ball_x = 6
        ball_y = 4
        direction = 2
    start_square_x = [3, 4, 3, 4]
    start_square_y = [3, 3, 4, 4]
    for start_y in start_square_y:
        for start_x in start_square_x:
            np_plot(start_x, start_y, 20, 0, 0)
    np.show()
    sleep(500)
    for start_y in start_square_y:
        for start_x in start_square_x:
            np_plot(start_x, start_y, 20, 20, 0)
    np.show()
    sleep(500)
    for start_y in start_square_y:
        for start_x in start_square_x:
            np_plot(start_x, start_y, 0, 20, 0)
    np.show()
    sleep(500)
    for start_y in start_square_y:
        for start_x in start_square_x:
            np_plot(start_x, start_y, 0, 0, 0)
    np.show()
    pin2.write_analog(511)
    pin2.set_analog_period(1)
    sleep(500)
    pin2.write_analog(0)   
    
#Haptic feedback function
def hit():
    pin1.write_digital(1)
    sleep(150)
    pin1.write_digital(0)

# reads and returns X,Y axis values (nunchuk i2c)
def read_nunchuk ():
    i2c.write(0x52, b'\x00', repeat=False)
    sleep(1)
    buf = i2c.read(0x52, 6, repeat=False)
    data = [(0x17 + (0x17 ^ buf[i])) for i in range(6)]
    #axis_X, axis_Y
    return data[0],data[1]
    
# Game setup
np = neopixel.NeoPixel(pin0, 64) #changed from 32 to 64 to get full 8x8 array
col_combo = [[0, 0, 0], [20, 0, 0], [0, 20, 0], [0, 0, 20], [20, 20, 20]]
player_1_x, player_1_y = 0, 1
player_2_x, player_2_y = 7, 6
ball_x, ball_y = 1, 3
timer, angle_up, angle_down = 0, 0, 0
direction = 1
win_count, player_1_score, player_2_score = 0, 0, 0
playing = True
end = False

#initialize nunchuk
i2c.write(0x52, bytes([0x40,0x00]), repeat=False)
sleep(1)

display.scroll("BIT PONG")

start_sequence(7)

while playing == True:
    
    # Display
    # Display grid
    for y in range(0, 8):
        for x in range(0, 8): #Changed 4 to 8 to enable 8x8 grid
            np_plot(x, y, col_combo[0][0], col_combo[0][1], col_combo[0][2])
    # Display player bars
    # Player 1
    player_1_y_bar = [player_1_y - 1, player_1_y, player_1_y + 1]
    for y_1 in player_1_y_bar:
        np_plot(player_1_x, y_1, 20, 0, 0)
    # Player 2
    player_2_y_bar = [player_2_y - 1, player_2_y, player_2_y + 1]
    for y_2 in player_2_y_bar:
        np_plot(player_2_x, y_2, 0, 0, 20)
    # Display ball
    np_plot(ball_x, ball_y, 20, 20, 20)
    np.show()
    
    # Movement
    # Player 1 (Red - nunchuk center is ~127)
    joyX, joyY = read_nunchuk()
    # Left
    if joyX < 100 and player_1_y > 1:
        player_1_y -= 1
    # Right
    if joyX > 154 and player_1_y < 6:
        player_1_y += 1
    # Player 2 (Blue)
    # Left
    if pin16.read_digital() == 0 and player_2_y < 6:
        player_2_y += 1
    # Right
    if pin15.read_digital() == 0 and player_2_y > 1:
        player_2_y -= 1
    
    #Ball bounces off player 1 pad
    if direction % 2 == 0 and ball_x == 1 and (ball_y == player_1_y or ball_y == player_1_y - 1 or ball_y == player_1_y + 1):
        hit()
        direction += 1
        timer = 0
        if angle_up == 0 and angle_down == 0:    
            if ball_y == player_1_y:
                angle_up = 0
                angle_down = 0
            elif ball_y == player_1_y - 1:
                angle_up = 1
                angle_down = 0
            elif ball_y == player_1_y + 1:
                angle_up = 0
                angle_down = 1
        if ball_y == 0:    
            angle_up = 0
            angle_down = 1
        elif ball_y == 7:
            angle_up = 1
            angle_down = 0
    #Ball bounces off player 2 pad
    elif direction % 2 != 0 and ball_x == 6 and (ball_y == player_2_y or ball_y == player_2_y - 1 or ball_y == player_2_y + 1):
        hit()
        direction += 1
        timer = 0
        if angle_up == 0 and angle_down == 0:
            if ball_y == player_2_y:
                angle_up = 0
                angle_down = 0
            if ball_y == player_2_y - 1:
                angle_up = 1
                angle_down = 0
            elif ball_y == player_2_y + 1:
                angle_up = 0
                angle_down = 1
        if ball_y == 0:    
            angle_up = 0
            angle_down = 1
        elif ball_y == 7:
            angle_up = 1
            angle_down = 0
    #Ball bounces off wall
    if ball_x > 1 and ball_x < 6:
        if ball_y == 0:    
            if angle_up == 1:
                angle_up = 0
                angle_down = 1
            elif angle_down == 1:
                angle_up = 1
                angle_down = 0
        elif ball_y == 7:
            if angle_up == 1:
                angle_up = 0
                angle_down = 1
            elif angle_down == 1:
                angle_up = 1
                angle_down = 0

    # Ball movement
    timer += 1
    if timer == 3:
        if direction % 2 != 0 and angle_up == 0 and angle_down == 0: #Straight right
            ball_x += 1
        elif direction % 2 != 0 and angle_up == 1 and angle_down == 0: #Up from left
            ball_y -= 1
            ball_x += 1
        elif direction % 2 != 0 and angle_up == 0 and angle_down == 1: #Down from left
            ball_y += 1
            ball_x += 1
        elif direction % 2 == 0 and angle_up == 0 and angle_down == 0: #Straight left
            ball_x -= 1
        elif direction % 2 == 0 and angle_up == 1 and angle_down == 0: #Up from right
            ball_y -= 1
            ball_x -= 1
        elif direction % 2 == 0 and angle_up == 0 and angle_down == 1: #Down from right
            ball_y += 1
            ball_x -= 1
        timer = 0

    #Scoring
    if ball_x == 0 or ball_x == 7:
        np.clear()
        win_count += 1
        if ball_x == 7:
            player_1_score += 1
            ball_x = 1
            ball_y = 3
            direction = 1
        if ball_x == 0:
            player_2_score += 1
            ball_x = 6
            ball_y = 4
            direction = 2
        if win_count < 3:
            start_sequence(ball_x)
            
    #Game end check
    if win_count >= 3:
        playing = False
        end = True

if end == True:
    np.clear()
    if player_1_score > player_2_score:
        display.scroll('Red Wins!', wait=False, loop=True)
    elif player_2_score > player_1_score:
        display.scroll('Blue Wins!', wait=False, loop=True)

 

This Bit Pong modification is also available in the file game-zip-64_bit_pong_nunchuk.py attached.

 

Conclusion

The :GAME ZIP 64 is a fantastic piece of hardware with a lot of potential: It feels solid and works very well for its intended purpose -when all the LEDs work properly of course -. Finally, after the modifications I had to do to make my Bit Pong example work, I came to the conclusion that the resources of the micro:bit paired together with the :GAME ZIP 64 are somehow very limited, but it accomplishes the educational goal very well with simple examples.

 

Thank you for reading this review and a big thanks to Element14 for letting me participate in this Road Test.

Anonymous