Project Report USB Gameboy
Project Report USB Gameboy
Project Report USB Gameboy
Abstract
This project aimed to enable a Nintendo Game Boy Advance (GBA) to be used as a personal
digital assistant by creating a USB communication interface between a Windows PC and a GBA,
which would require no hardware-specific drivers or user-configuration.
USB v1.1 is implemented on a Microchip PIC16F877 micro-controller (using the CCS compiler
add-on) and a Philips Semiconductor PDIUSBD12 low-level USB chip which handles interactions
with the USB bus.
An interface with GBA is achieved via UART and then use the USB implementation by means of
the (USB-IF defined) Human Interface Device (HID) class to transfer user-data.
Keywords
USB, Embedded System, PIC, Game Boy Advance, Hardware, PDIUSBD12, PIC16F877
Table of Contents
1 - Introduction...................................................................................................................................1
1.1 - Introduction to Game Boy.......................................................................................................2
1.2 - Introduction to Universal Serial Bus.......................................................................................4
USB Classes................................................................................................................................5
USB Speed & Traffic..................................................................................................................6
2 - Author's assessment of the project..............................................................................................8
2.1 - What is the technical contribution of this project?..................................................................8
2.2 - Why should this contribution be considered relevant / important to computer science?........8
2.3 - How can others make use of the work in this project?............................................................8
2.4 - Why should this project be considered an achievement?........................................................9
2.5 - What are the weaknesses of this project?................................................................................9
3 - Getting Started............................................................................................................................10
3.1 - Evaluating USB.....................................................................................................................10
3.2 - The GBA Communications Port...........................................................................................11
Choosing a tool-chain...............................................................................................................12
DevKit Advance...................................................................................................................13
HAM.....................................................................................................................................13
General Purpose Mode..............................................................................................................14
Pin-out and Voltages.................................................................................................................14
Running code on a GBA...........................................................................................................16
3.3 - Choosing a micro-controller..................................................................................................17
A brief introduction to PIC micro-controllers...........................................................................18
4 - Preparing the Hardware.............................................................................................................20
4.1 - GBA UART communications...............................................................................................20
4.2 - PC Debugging Tools.............................................................................................................21
Advanced Serial Port Monitor..................................................................................................22
USB Command Verifier............................................................................................................23
Snoopy Pro................................................................................................................................23
HHD USB Monitor...................................................................................................................24
4.3 - System Hardware...................................................................................................................25
PDIUSBD12 USB Interface Device with Parallel Bus.............................................................25
SoftConnect..........................................................................................................................25
GoodLink..............................................................................................................................26
PIC16F877 40-Pin 8-bit CMOS FLASH Micro-controller.......................................................26
Assembling the Hardware.........................................................................................................28
Verifying the System.................................................................................................................30
5 - Learning enough to Enumerate.................................................................................................32
5.1 - The USB Enumeration Process.............................................................................................32
USB STALLs and Bus-resets....................................................................................................34
5.2 - USB Control Transfers..........................................................................................................34
The Setup Stage.........................................................................................................................34
bmRequestType....................................................................................................................35
bRequest...............................................................................................................................35
wValue..................................................................................................................................35
wIndex..................................................................................................................................35
wLength................................................................................................................................35
The Data Stage..........................................................................................................................35
Breakdown............................................................................................................................62
If time allows:.......................................................................................................................62
Methods.....................................................................................................................................62
Pre-requisites phase..............................................................................................................62
Maturing phase.....................................................................................................................62
Implementation phase...........................................................................................................63
If time allows:.......................................................................................................................63
Timetable..................................................................................................................................63
Resources..................................................................................................................................64
11.2 - Parts list for Master Schematic............................................................................................64
Table of Illustrations
Illustration 1.1.1 - A Game Boy Advance............................................................................................2
Illustration 1.1.2 - A Game Boy Advance SP (GBA:SP).....................................................................2
Illustration 1.2.1 - A USB plug.............................................................................................................4
Illustration 3.2.1 - The HAM Banner.................................................................................................13
Illustration 3.2.2 - GBA CommProbe.................................................................................................14
Illustration 3.2.3 - A GBA Link-cable................................................................................................15
Illustration 3.2.4 - GBA Communication plug and socket.................................................................15
Illustration 3.2.5 - A "Flash 2 Advance" cable...................................................................................16
Illustration 3.2.6 - The GBA bootstrap loader....................................................................................16
Illustration 3.2.7 - A "Multi-Boot v2" cable.......................................................................................17
Illustration 4.1.1 - GBA-PC UART Schematic (taken from DarkFader.net).....................................20
Illustration 4.1.2 - MAX3232 Level Converter..................................................................................21
Illustration 4.2.1 - A Dumb Terminal.................................................................................................22
Illustration 4.2.2 - Advanced Serial Port Monitor..............................................................................22
Illustration 4.2.3 - USB Command Verifier.......................................................................................23
Illustration 4.2.4 - SnoopyPro 0.20 showing an enumeration log......................................................23
Illustration 4.2.5 - HHD USB Monitor showing an enumeration log................................................24
Illustration 4.3.1 - PDISUBD12 pin configuration.............................................................................25
Illustration 4.3.2 - PIC16F877 pin configuration...............................................................................27
Illustration 4.3.3 - Master schematic for project hardware.................................................................28
Illustration 4.3.4 - Photo of final hardware.........................................................................................29
Illustration 4.3.5 - A Dumb Terminal.................................................................................................31
Illustration 6.1.1 - Flowchart of the Firmware's USB Interrupt Service Routine...............................45
Illustration 6.2.1 - Successful enumeration........................................................................................46
1 - INTRODUCTION
1 - Introduction
This project was conceived to bring the connectivity of a Personal Digital Assistant to a
Nintendo Game Boy Advance portable games console (herein GBA) by creating a USB link
between GBA and PC.
This project idea occurred to me when I was considering purchasing a PDA for myself, and
realised that the functionality I considered important was actually quite basic (Scheduler, To-do list
and Address Book). I personally own a GBA which I usually carry with me and use to pass idle
time at bus-stops and so on. One day I thought If I was to get a PDA, I'd have to carry two things
around with me; I would keep my GBA with me because the games available on a PDA pale in
comparison to those on the GBA and would never hold my interest. This, coupled with my
knowledge of the GBA homebrew community (more detail on page 2) led me to settling on this
project.
The main focus of the project was to create a USB implementation that allowed data to be sent
between the GBA and the PC, using tools available to the university. A USB implementation
requires a micro-controller to handle protocol requests, as well as appropriate circuitry to interface
with a USB bus, so this project concentrates on creating an embedded system to realise such an
implementation.
A variety of USB helper chips are available, usually intended for handling interactions with the
USB bus, such as signalling and error-recovery. Many such chips were considered before settling on
the Philips PDIUSBD12, chosen because detailed implementation schematics and source code on
how to interface with a Microchip PIC micro-controller was available in C (most other example
source code was only available in assembly), and the Computer Science department have
equipment, expertise and experience using PIC micro-controllers.
The largest hurdle in the project was implementing the necessary protocol functions to enable a
USB device to be configured by a host (a PC running Windows XP in this case), a process termed
enumeration. Until the device is configured by the host, there are no user-accessible events or data
to aid debugging at the host, rendering software USB sniffers useless for this crucial portion of
the development. Debugging had to be done at the device, but interleaving statements which
transmitted this debugging data complicated development and required careful progress.
CHAPTER 1 - INTRODUCTION
Once the device did enumerate successfully, an implementation of the Human Interface Device
(HID) class, as defined in a USB class standard, was implemented and used to send user data
between the PC and firmware, while the communications between the developed hardware and
GBA were handled by a UART link.
and
produced the necessary tool-chains and technical documentation to enable any hobbyist to write and
compile C code which would run on the GBA hardware.
There are two main methods to getting home-brew code to run on a GBA writing the compiled
binary onto a flash cartridge which is compatible with system, or making use of the GBA's bootstrap
loader.
A variety of flash cartridges designed specifically for this purpose are commercially available,
and are written using either a custom hardware writer, or much more commonly in recent times, by
making use of the GBA's bootstrap loader.
When there is no cartridge in the GBA (or the user holds down certain buttons when powering
the unit on) the system enters multiboot mode (sometimes called netboot), where it listens on its
communications port for a host that wishes to send bootstrap code. Intended to allow multiple units
to play a multi-player game when only one game cartridge is available. Bootstrap code is limited by
the size of available RAM: 256kB, however this is sufficient for most home-brew applications. This
mode is often used to transmit a small loader into the GBA which then acts as a pass-through
between PC and GBA, allowing appropriate PC software to rewrite a compatible flash cartridge
inserted into the GBA via the GBA hardware this method is preferred by most as it reduces wear
on the cartridge's tracks (as there is no need to keep removing and inserting the cartridge between
GBA and a cartridge writer) and is both cheaper and more compact than buying a special writer.
The GBA does not offer any operating system, and it is up the developer to make appropriate use
of the available hardware for instance instead of drawing moving objects on the display pixel-bypixel every frame of animation, it is much better to draw them once into Object Memory and then
place one of the display layers into sprite-mode and set the Object Attribute Memory appropriately
for each object setting coordinates, rotation and opacity thereby allowing the GBA's video
hardware to take care of rendering the object while the CPU handles other tasks.
The communications port of GBA is intended for creating small wired networks of 2-4 GBA
units for multi-player games and for interfacing with peripherals. So apart from supporting propriety
Nintendo networking protocols it offers a general purpose mode and a buffered UART mode. The
general purpose mode allows individual pins to be set logic-high, logic-low or as input while the
UART mode is suitable for interfacing with RS232 once some voltage-level conversion has taken
place, when used the GBA offers hardware flow control using Clear-To-Send/Request-To-Send
(CTS/RTS) lines.
www.thepernproject.com
CHAPTER 1 - INTRODUCTION
maximum of 127 ports including all hubs, with the root hub (so-called
the host) also taking up a port).
Version 1.0 was released in January 1996, and specified a host-orientated design where a single
host per bus controls all communication[2]. All bus traffic is initiated and controlled by the host,
with the direction being one of IN or OUT and always from the perspective of the host, regardless
what context is being discussed this is the terminology the standard utilises.
When a USB device is attached to a host a process termed enumeration occurs where the host
queries the device about its capabilities and requirements and then issues commands to place the
device in a configured state, while also taking care of loading drivers in the host operating system as
appropriate (this includes querying the user for compatible drivers).
This process makes USB truly plug-and-play as the enumeration process is a well-defined part of
the standard, allowing devices to be uniquely identified by the host. USB is also fully hot
swappable, allowing the removal of any device at any time without adversely affecting the
operating system3. When a device is removed the hub it was connected to makes a note of this event
and sets a flag which the host will retrieve when it next polls the hub device attachments are
handled in a similar manner.
A major strength of USB is that it is easy to gain more ports unlike legacy ports such as the
parallel port it is not necessary to open the PC case and insert a PCI / ISA card while the machine is
powered off, instead a USB hub can be inserted into a free port while the system is powered to
expand the number of USB ports, this is possible because USB hubs are devices themselves. Some
products have hubs in them as a secondary function, such as a USB keyboard which provides
convenient USB sockets to attach a mouse or PDA/smart-phone cradle. Such a product would
3 This does not imply that no data will be lost or no corruption incurred, only that the system remains operational.
enumerate as a composite device made up of keyboard and hub, and each component would in turn
be enumerated.
Unlike legacy ports, USB does not make any assumptions about the data it will be used to
communicate. For instance the parallel port was designed with printers in mind, and so of the 25pins on the PC connector, only 8 are intended for true data while the others are intended to be used
as status lines, similarly the serial port was intended for interfacing with terminals and modem
equipment, and features a Ring Indicator status line on the connector.
Instead, USB connectors only have 4 lines (VBUS, Data+, Data- and Ground) and provides the
facility to to create logical channels (termed pipes) between software endpoints on the host/device.
These pipes are synonymous to byte streams, while the endpoints are mono-directional addresses.
By making endpoints mono-directional the task of implementing the protocol in software (the
firmware) is simplified as each endpoint direction is implied. This functionality also provides a
convenient way to separate protocol data (such as that used in enumeration) from the true data the
device sources/sinks.
USB was intended to be a universal replacement, and to that end it support 4 transfer types:
control transfers used to issue requests specified by the USB standard, for instance those
used in enumeration conversations; however it can also be used for arbitrary data. All devices
must support control transfers or they are unable to enumerate.
isochronous transfers data is transferred at a guaranteed rate (usually as fast as possible), this
is the only transfer type where data is not retransmitted on an error. Example use: real-time
audio/video
interrupt transfers have guaranteed latency (to an upper bound), Example use: pointing
devices and keyboards.
bulk transfers large sporadic transfers which make use of all available bandwidth without
guarantee of rate of latency. Lowest priority transfer type. Example use: file transfers.
USB Classes
Devices often share attributes in common, for instance all mice send movement data and button
clicks, and so it is useful to define a standard which encompasses these common attributes. USB has
a notion of classes which perform just such a purpose, and has defined a number of classes, such
as Human Interface Device (HID) class (which I have used in this project) and mass storage device
class.
Classes are like templates on which implementations can be created, their implementation can
CHAPTER 1 - INTRODUCTION
extend the class, so long a it doesn't contradict the class specification. This is useful in, for instance,
USB flash drives with special functionality, perhaps an encrypted area of memory when attached
to the system the host may not be able to find specific drivers for the device which can perform the
secure transactions, and so loads the operating system's default mass storage class driver instead;
making the basic functionality available to the user until a custom driver is installed (at which time
the device will be re-enumerated and the special driver will be loaded).
As stated previously, this project made use of the Human Interface Device (HID) class, which
uses a standardised structure, called a report, to describe data being transmitted in either direction,
and allows multiple report structures to be defined on an endpoint, enabling efficient use of the
system's available bandwidth or power important in laptop environments, especially if the device
is bus-powered by the host by allowing the report to be chosen dynamically by the device. Useful
in monitoring applications as a short no change can be sent, or a group of related readings can be
sent when something changes.
The report structure defined in the standard even has the option to attach associated compositions
of SI units4, such as grammes or seconds, to any data in the report, potentially allowing a generic
monitor application on the host to parse data from almost any HID-class device and display
readings in a (potentially) useful manner.
2.3 - How can others make use of the work in this project?
Anyone wishing to create a USB interface to a PC could make use of this work to help them
overcome the basic difficulties of working with the PDIUSBD12 chip and USB in general.
Additionally, anyone wishing to create a Game Boy Advance communication link could find
enough information in this project to use either General Purpose Mode (4-pin bi-directional
communications) or UART mode of the GBA, as well as the necessary details about cabling and
some example code for each mode.
Because standard HID-class reports (data structures defined in a report descriptor) are used in
this project, data to be transferred has structure, so only this and the main() loop need to be
adapted to work with a different data format for use in a different application. All the basic
functionality to enumerate the device as a HID-class compliant device have been developed, as well
as the necessary functions to transmit and receive data as a HID device.
2.3 - HOW CAN OTHERS MAKE USE OF THE WORK IN THIS PROJECT?
A (.NET-based) Windows XP example application has been used to demonstrate data transfers in
both directions, and serves as an example on how to create the PC application that detects and uses
a USB device.
3 - Getting Started
When I originally started on this project I had no special knowledge about USB, little experience
in programming my GBA and my most similar undertaking to date was the CG152 project in my
first year, where a team-mate and I created Pong using a SWET5 board; nor was I familiar with
programming in C the language I ultimately used to program both the firmware and the GBA.
Because of this uncertainty a very cautious approach of tackling the largest risk first was adopted.
The purpose of this section is to show the considerations made during the infancy of the project, and
to justify the decisions.
In my original project specification (see section 11.1 on page 62) I identified the following areas
for consideration:
1. Evaluating USB as both suitable for the project, as well as viable/achievable
2. Experiment and learn about programming the GBA communications port.
3. Choosing a micro-controller on which to base the project architecture
USB Central
http://www.lvr.com/usb.htm
These websites offered much detail and provided a complete picture of what is involved at every
stage between concept and final product.
The first, BeyondLogic.org, detailed a great variety of USB developer boards and integrated
5 SWET I believe this stands for Super Warwick Electronic Toy
10
circuits designed to take care of the lower-level functions of a physical USB device, such as
signalling / transmitting data and interacting with the bus, which was most encouraging. At first I
was suspicious of this website which offered so much information (including multi-part article
entitled USB in a Nutshell) for nothing in return, while offering no product. A bit of research
showed that the site is run by a Senior Technician by the name of Craig Peacock, of Flinders
University, Australia which set my suspicions at ease. This resource showed me how I might
achieve my project goals.
The second, www.lvr.com, is run by Lakeview research who publish technical books such as
USB Complete which I eventually bought and used as my main point of reference through-out the
project. The site itself contains (links to) many useful utilities to aid development, such as sniffers
which allow logging of USB traffic on a Windows host PC as well as example source code. The site
and book made it possible to bring all the information together and build the system up using the
schematic and source-code from BeyondLogic.org.
A key document at this time was BeyondLogic.org's USB in a Nutshell Chapter 7
PDIUSBD11 and PIC16F87x Example[3], which detailed an example implementation using a
Philips USB IC and a Microchip PIC micro-controller; complete with schematic and source code in
C all other examples I found coded their firmwares in various assembly languages, which I did not
wish to spend time learning. Of all the information I found, this example implementation was the
most useful and the most relevant.
The Computer Science department have, and use, Microchip PIC micro-controllers frequently,
making this document only more relevant after some research into the Philips PDIUSBD11 was
undertaken it was deemed suitable, but unfortunately had also been discontinued. Philips offered the
PDIUSBD12 a an alternative, apparently identical in functionality, but using a parallel data bus
instead of an I2C one. The PDIUSBD12 was chosen after careful consideration, but due to the
industrial nature of such ICs was only available to buy in batch. The department ordered in the
smallest batch we could find: 27 PDIUSBD12 chips.
For details of the PDIUSBD12, please see section 4.3 PDIUSBD12 USB Interface Device with
Parallel Bus on page 25
11
Expl.
SC Data Bit
(0=Low, 1=High)
SD Data Bit
(0=Low, 1=High)
SI Data Bit
(0=Low, 1=High)
SO Data Bit
(0=Low, 1=High)
SC Direction
(0=Input, 1=Output)
SD Direction
(0=Input, 1=Output)
SI Direction
(0=Input, 1=Output, but see below)
SO Direction
(0=Input, 1=Output)
Interrupt Request
(0=Disable, 1=Enable)
Not used
Must be "0" for General-Purpose Mode
Must be "1" for General-Purpose or JOYBUS Mode
SI should be always used as Input to avoid problems with other hardware which does not expect data to
be output there.
128h - SIOCNT - SIO Control, not used in GENERAL-PURPOSE Mode This register is not used in
general purpose mode.
In this entry 134h is the memory address offset from 0x4000000 of the RCNT register, and SC,
SD, SI and SO refer to individual pins on the communication port and denote Serial-Clock, SerialData, Serial-In and Serial-Out respectively. Not all of this was explicitly in the documentation, and
was inferred from looking at the source code of other members of the homebrew community.
Hopeful that I would be able to create a small test application, allowing me to manually set pins
logic-high/low or input and display the register contents accordingly, I needed to install an
appropriate tool-chain with which to develop the application.
Choosing a tool-chain
Because GBA homebrew has been an interest of mine for some years, I knew immediately that
this choice would be between the two most popular development kits: DevKit Advance and
12
HAM either of these would provide me with useful reference source code from others in the
community, as well as good community support.
DevKit Advance
A SourceForge6 project since November 2002, DevKit Advance was the first GBAdevelopment tool-chain I encountered some 3 years back. DevKit Advance describes itself as
follows:
DevKit Advance is distribution of GCC, popular among independent Game Boy Advance
developers, with the goal of making the creation GBA software as painless as possible for
beginners while not getting in the way of the advanced developer.
The main advantage of this tool-chain is its purity - it offers a means for compiling
C/C++ to a binary files which is in the correct format to be run on actual hardware, all that is
required is to include a header files called gba.h. Of course this is also its main disadvantage
as it does nothing to facilitate the quick development of code.
I originally learnt to develop for the GBA system from a tutorial7 which used this kit, and
so expected that this would be my tool-chain of choice.
HAM
only a few clicks to get everything setup, the IDE supports code completion specific to the
HAM library (referred to as HAMlib) and compiling is fully automated through makefiles
which are handled by the IDE additionally it comes with an impressive collection of
demonstration applications which show how each feature of HAMlib (and hence the GBA
hardware itself) work.
HAM also boasts many convenience features, for instance the IDE has build targets for
Flash, Multi-Boot v2 and Visual Boy Advance - which are the three main ways of testing
6 SourceForge.net is an on-line collaborative software development management system, often used for open-source
projects
7 See http://www.thepernproject.com
13
code: writing it to a flash cartridge (as mentioned in section 1.1), sending it over as a bootstrap
via appropriate cable, and running it in a popular GBA emulator for the PC.
The disadvantage of HAM is that it is not open-source; two versions are available: free and
registered. The two versions are identical except for a banner (see illustration 3.2.1) and the
associated overhead it requires which is displayed on all code compiled with the free
version. Registering is entirely optional, and costs a nominal 25.
The library contained some very useful functions such as ham_DrawText() which
works in a similar manner to printf() on a PC the GBA does not have a character-based
display meaning text needs to be rendered, making this is a very welcome feature especially
for this project as I intend to do simple code demonstrations and debugging output, so text
was all I expected to need.
I was leaning towards HAM at this point because it offered a way to quickly develop. Any source
code I found written using HAM was sure to work in my installation, while the same could not be
said of DevKit Advance, as my experience with it had taught me, which tends to be customised in
hard to duplicate ways by its users. DevKit advance isn't very windows friendly either, and expects
bash-type shell.
I chose to go with the HAM system, and have not regretted it.
and a binary can be found on the attached CD, along with usage instructions (see section 8.1 on
page 59).
there is no connector for this pin on either end of the link-cable, as it is not meaningful to do so. I
took readings using a standard GBA and a GBA:SP and noted that the voltages are consistent to +/0.05V on both.
When the pins are configured as input, and not connected to anything they float high.
As an aside, I have read that when playing games intended for older Game Boy models (such as
Game Boy or Game Boy Colour) the communication port operates at +5V, instead of +3.31V,
which is interesting as all Game Boy systems have run on 2xAA (or 2xAAA) batteries.
My obtained results were as follows:
Colour
Pin#
Pin Name
UART Role
Voltage
VCC
Red
SO Serial-Out
TX
3.31V
Orange
SI Serial-In
RX
3.31V
Brown
SD Serial-Data
RTS
3.31V
Green
SC Serial-Clock
CTS
3.31V
Blue
GND
0V
I read a warning about pin# 5 to the effect of On GBA power-up this is an output, so a 1K
resistor ought to be inserted between this and any voltage converter logic to prevent two outputs
from shorting each other out on the Developer's Resource GBA website8, and this did indeed cause
strange behaviour later on the in the project: if the GBA was connected to my project hardware
8 Specifically at http://www.devrs.com/gba/files/gbadevfaqs.php#PCGCable
15
when powering on the GBA, it would often fail to boot and the screen would remain blank, and if
the GBA was left attached to the project hardware and turned off it would emit a feint buzzing
sound on the speaker, and the older GBA model's power indicator would remain lit all a result of
overlooking this warning.
16
It is usual within the home-brew community to use PC-based GBA emulators to create and debug
most code, however this was not an option for me as no emulator exists which adequately emulates
the communication port, and testing on hardware would be required at all stages even if one were
available.
An oversight in the design of the Flash 2 Advance
software means it is not possible to send user data as
the bootstrap. No alternative software that utilises this
system supports such a function, probably because the
bootstrap code is stored in the cable's firmware10. So I
purchased a Multi-Boot v2 cable (referred to as just
MBv2 in the home-brew community).
The MBv2 cable is designed and produced by an
active member of the home-brew community, and offers the ability to transmit user-code through
the multi-boot protocol, as well as developer utilities such as an RS232 DB9 connector to allow
convenient debugging from the GBA via UART (by providing level-conversion and connector).
By testing development iterations through multi-boot the process is streamlined considerably as
only two steps are required to run binary data: reset the GBA and transmit the data to it, the hassle
of resetting, loading, configuring the PC side, writing, resetting, testing, repeating is avoided. Even
the resetting step can be automated if you are willing to solder an extension from the GBA reset line
to a pin provided on the back of the MBv2 cable, next to the DB9 connector (see Illustration 3.2.7 A "Multi-Boot v2" cable, above). The MBv2 also provides some source code libraries for utilising
the DB9 connector on the cable from both the GBA and from the PC, even providing a program to
interact with the GBA UART mode through the MBv2, allowing GBA UART to be used on a PC
with only a parallel port, handy for developing on my laptop!
To summarise, the MBv2 is a developer's cable that streamlines development, while the Flash 2
Advance is a tool for storing data on a GBA cartridge. Both are supported by the HAM IDE, which
offers keyboard shortcuts to compile and transmit data using either methods.
17
As it happens, the department's technicians have and frequently use Microchip PICmicro microcontrollers, and have all the necessary equipment, tools and documentation to develop for them
using a C-like language. Perhaps more importantly, they also have considerable experience
developing for them.
The PIC family used in the BeyondLogic.org schematic, a PIC16F87x, is also used by the
department in many of the more-involved projects. So a chip suitable for use in the schematic was
confidently available while offering a familiar way of coding for it.
I spoke with Mr Rod Moore on the subject of PICs as they relate to my project, and showed him
the PDIUSBD12's specification and BeyondLogic's schematic (which used a different USB IC), and
he felt confident that the change from I2C to a parallel bus would not complicate matters
considerably. I was confident to use the PIC recommended to me, a PIC16F877, after familiarizing
myself with a simpler PIC (a PIC16F84A).
Timers
Analogue-to-Digital converters
Voltage Comparators
Capture/Compare/PWM modules
LCD Drivers
Microchip offer a free IDE, MPLAB IDE (currently v7.10), which lives up to the claim of being
easy-to-use. The department have, and use, this development environment with an additional CCS-
18
11 The fairly powerful PIC16F877 used in this project costs around 2.50 at the time of writing
19
20
code. I was able to used the pre-compiled binary on my GBA and use Advanced Serial Port
Monitor on my PC to send and receive characters to the GBA. Advanced Serial Port monitor
performs the same functionality as HyperTerminal, but offers some simple improvements in logging
capabilities. However, the GBA binary I was using was designed for code transfer and execution,
and not for use as a dumb terminal, so while I was able to verify the connection worked to a limited
degree it had no further use. I noted that this configuration required the use of the CTS/RTS13 lines,
which would prove inconvenient as the UART libraries of the PIC development tools available to
me did not implement these signals.
Thankfully, I discovered another GBA UART demo on FiveMouse.com[6]. This demo mimicked
the functionality of a dumb terminal, echoing ASCII characters it received and sending key-presses
back. I was able to rework the source code to compile in HAM and quickly made minor
modifications to remove the need for CTS/RTS signals.
My UARTTest application is included on the attached CD (see section 8.1 on page 59). This
application does tend to lose data when doing bulk transfers, due to the time it takes to render
characters into the GBA screen-buffer a simpler application which only echo's data back at the
sender does not lose any data, as no internal buffering is done.
This application successfully interfaced with a dumb-terminal, PC serial port and PIC microcontroller during tests.
21
As will be seen later, most of my debugging efforts were conducted by a UART connection to
the PIC micro-controller, and I quickly found that a dumb-terminal was not adequate as did not
offer the ability to scroll back screen-fulls of text. HyperTerminal comes bundled with Windows
and appeared to offer the ability to scroll back and also to log data to a file, but I encountered
problems with it. HyperTerminal would corrupt it's scroll-back buffer rendering it's scrolling ability
useless it would interleave the current screen with the scroll-back data and produce what appeared
to be reasonable debug logs, I was only made aware of this problem when using both
HyperTerminal and a dumb-terminal at the same time. Additionally, in a frustrating episode, I came
to learn the hard way that HyperTerminal ignores all communications in both directions if ScrollLock is enabled, without warning.
Advanced Serial Port Monitor14 offered accurate results, as well as a few niceties such as not
locking the file it is logging to, allowing me to manually insert comments and breaks between tests,
as well as tagging certain data.
14 http://www.kmint21.com/serial-port-monitor/
22
Snoopy Pro
Snoopy Pro16 is an open-source project to develop a utility for windows which allows logging
and analysing of USB traffic between the hardware and device driver. It works well and offers a
15 http://www.usb.org/developers/tools/
16 http://sourceforge.net/projects/usbsnoop/
23
Interestingly, I found Snoopy Pro's simplicity to be an advantage when I wanted to reverseengineer some existing USB hardware to get an idea about USB descriptors, HHD USB Monitor
17 http://www.hhdsoftware.com/usbmon.html
24
presented the descriptors as interpreted information, while Snoopy Pro presented them as raw hex
with a simple outline above, which I preferred as it facilitated easy duplicating in my source code.
transfer
modes
of
USB:
control,
interrupt,
isochronous and bulk and also provides 64kB double-buffering on it's main endpoint.
Two feature specific to this chip made it stand out among the rest and helped make the decision
to utilise it in this project: SoftConnectTM and GoodLinkTM.
SoftConnect
SoftConnect is a feature whereby the chip's presence of the USB bus can be controlled by
software. A full-speed device's presence on a USB bus is indicated by a pull-up resistor on the
upstream data line, SoftConnect allows this pull-up resistor to be connected and disconnected
from the bus using firmware useful for bus-powered systems as it allows the firmware to
ensure everything is ready for USB traffic to commence before advertising it's presence on the
USB bus. It is also part of the specification that an un-enumerated device may consume up to
100mA of power from the bus, and up to 500mA on request, if the host permits.
18 Full-speed as in the USB specification's definitions of low-speed, full-speed and high-speed devices.
25
GoodLink
A GoodLink pin drives an LED which indicates (without firmware intervention) the status
of the connection: If not lit the device is not configured or active, if blinking there is traffic,
and if steady it is configured and awaiting traffic.
These features, along with the data sheet[7] led me to believe that Philips had taken care over
their design, and kept the developer in mind while doing so I felt this would be a polished product
that I would be happy to work with.
The micro-controller interacts with the D12 in one of three ways: read, write or command.
Commands are sent to the D12 by placing the command byte on the bus and then strobing the A0
pin, the status of a command can usually be obtained by immediately following it with a read of the
bus (strobing the RD_N pin). When not writing commands, the last selected endpoint's buffer is
filled on a write operation.
A good way to get a feel for the responsibilities of the D12 in a device are to view a sample of it's
supported commands. The most important are:
Set Address/Enable: Set the address that the D12 responds to on the USB bus.
Set mode: Choose which transfer-type configuration of the D12's endpoints are active.
Read Interrupt Register: Indicates which endpoint triggered the last interrupt (for use with a
Read Endpoint Status command), or signals a bus reset / suspend change.
Acknowledge Setup: When a setup token is received, the D12 flushes its buffers, disables the
validate and clear buffer commands and will only re-enable them when this command is
performed. This ensures that the firmware knows about the setup token before sending any
data.
Other commands that need no explanation: Read Last Transaction Status, Read Buffer, Write
Buffer
26
Analogue-to-Digital
converters
Technologies
Inc.
provide
22
to aid
MCLR/VPP
RA0/AN0
1
2
40
39
RB7/PGD
RB6/PGC
RA1/AN1
RA2/AN2/VREF-
38
RB5
37
RA3/AN3/VREF+
36
35
RB4
RB3/PGM
RA4/T0CKI
5
6
RA5/AN4/SS
34
RB1
RE0/RD/AN5
RE1/WR/AN6
33
9
10
32
31
RB0/INT
VDD
11
12
RD7/PSP7
RD6/PSP6
RD5/PSP5
RE2/CS/AN7
VDD
VSS
13
30
29
28
OSC2/CLKOUT
14
27
RD4/PSP4
RC0/T1OSO/T1CKI
15
16
26
25
RC7/RX/DT
17
24
18
23
19
20
22
21
VSS
OSC1/CLKIN
RC1/T1OSI/CCP2
RC2/CCP1
RC3/SCK/SCL
RD0/PSP0
RB2
RD1/PSP1
RC6/TX/CK
RC5/SDO
RC4/SDI/SDA
RD3/PSP3
RD2/PSP2
27
10uF
DCD
DSR
1
120
120
R4
SW1
2
3
SW2
4
120
120
R5
R6
TD
DTR
SGND
DB9_Connector
C1
R7
4k7
R3
RD
SW3
5
6
SW4
7
8
9
10
5V
11
12
13
X1
14
15
4MHz
16
17
18
19
20
MCLRn/Vpp
RB7/PGD
RA0/AN0
RB6/PGC
RA1/AN1
RB5
RA2/AN2/VREF-
RB4
RA3/AN3/VREF+
RB3/PGM
RA4/T0CKI
RB2
RA5/AN4/SSn
RB1
RE0/AN5/RDn
RB0/INT
Vdd
RE2/AN7/CSn
Vss
Vdd
RD7/PSP7
Vss
RD6/PSP6
OSC1/CLKIN
RD5/PSP5
OSC2/CLKOUT
RD4/PSP4
RC0/T1OSO/T1CKI
RC7/RX/DT
RC1/T1OSI/CCP2
RC6/TX/CK
RC2/CCP1
RC5/SDO
RC3/SCK/SCL
RC4/SDI/SDA
RD0/PSP0
RD3/PSP3
RD1/PSP1
RD2/PSP2
CTS
RI
39
38
37
36
5V
35
34
C2
0.1uF
33
RE1/AN6/WRn
RTS
D4
40
5V
32
16
31
C3
0.1uF
30
+C1
+V
3
4
C4
0.1uF
11
25
10
24
12
23
C6
+C2
-V
6
0.1uF
-C2
27
26
-C1
29
28
C5
0.1uF
Vcc
T1IN
T1OUT
T2IN
T2OUT
R1OUT
R1IN
R2OUT
R2IN
14
7
13
8
22
GND
21
MAX3232
SC
15
PIC16F877
1
2
3
4
5
6
7
8
9
5V
10
R8
11
4k7
12
13
14
SD
DATA<0>
A0
DATA<1>
VOUT3.3
DATA<2>
D+
DATA<3>
D-
GND
Vdd
DATA<4>
XTAL2
DATA<5>
XTAL1
DATA<6>
GL_N
DATA<7>
RESET_N
ALE
CS_N
EOT_N
DMACK_N
SUSPEND
CLKOUT
INT_N
DMREQ
WR_N
RD_N
SI
28
27
SO
26
GND
25
24
D+
D-
22
21
Shield
X2
23
6MHz
PB1
D3
20
19
R1
4k7
18
17
16
GBA_Header
5V
D1
VBUS
GND
Shield
R2
1M
USB_Header
15
PDIUSBD12
Notes:
This schematic is included on the attached CD in PDF and original ProSchematic format, along
with a shareware version of ProSchematic for Windows.
A parts list is available in section 11.2 Parts list for Master Schematic on page 64.
The data bus between the D12 and P877 connects Data <0> to RD0/PSP0, and Data <1>
to RD1/PSP1 etc.
28
LED current-limiting resistor values have been omitted, as this depends on the LED used.
PB1 (near USB_Header) is a break-on-push button intended for resetting the system (see 6.3
PDIUSBD12 Reset issue on page 48).
This design can be bus-powered (as it was in this project) or otherwise the usefulness of PB1
assumes that the system is bus powered in either case the D12's EOT_N must always be
connected to USB VBUS via the potential divider shown.
The PIC16F877 and PDIUSBD12 are connected via a byte-wide parallel bus and control lines
WR_N, RD_N and status lines INT_N, SUSPEND. The D12 is connected to a USB cable with a
USB-A male plug on the end (the end required for inserting into a host PC) and hence is connected
to a USB bus when the plug is inserted.
The PIC16F877's USART port (pins 25 & 26) is connected directly to a GBA link cable,
allowing the P877's USART register to buffer I/O and trigger interrupts on complete reception of a
character from the GBA introducing a level of multi-tasking into the firmware. No 'glue-logic' was
necessary as the GBA and P877 TTL23 voltages were within tolerance of one another.
Another UART connection, implemented in software routines this time, was connected via a
MAX3232 RS232 voltage-level converter, creating an interface between the system and a dumbterminal or PC serial port; and was used for debugging.
23 TTL: Transistor-Transistor Logic
29
In my implementation the system was bus-powered, so if the system was on (powered) it was
safe to assume it was connected to an active host. The only required connection to the USB VBUS
line is the D12's EOT_N pin, which is used for detecting the presence of the bus, aside from this the
use of VBUS is entirely optional.
As mentioned in the introduction, debugging was made difficult by the time-constraints imposed
by the USB host. Transmitting characters over UART would cause unacceptable delays that often
changed the outcome of the device's interaction with the host. Apart from making debugging data as
concise as possible (and unfortunately somewhat cryptic) I added a row of DIP switches which
would control the debugging level. Three switches were used to enter a binary number in the range
0-7, with 0 being most verbose and 7 being silent except for uncaught exception type errors (such
as passing invalid constants to a function, indicating a mistake in the program code itself). When the
system was reset the DIP switch values would be read in and the debugging level set internally, the
DIP switches would not be read again until the next reset.
Another of the DIP switches was used to select if the GBA UART connection should be used for
generating report data used later in the project (please see 5.5 Report structures and descriptors on
page 42) or if the data should be randomised this was a convenience feature used during the final
phase of firmware development.
LEDs were used to indicate USB power, PIC status (toggled upon receiving a character from the
GBA) and the PDIUSBD12's GoodLink indicator (described on page 26.)
30
The D12 triggers a bus-reset interrupt as soon as it is powered, the falling-edge of which is
usually missed by the PIC which takes longer to start-up.
When held in reset (noting the issues with resets mentioned previously), the D12's INT_N line
goes active high, offering a good opportunity to ensure this important line is readable in both
states (active low being achieved by bringing the D12 out of reset).
RD_N and WR_N must be explicitly opposite logics, it is not sufficient to set one and leave the
other inactive.
24
instruction . I was content that the system operated as designed and moved onto writing the
firmware.
GoodLink.c is included on the attached CD, please see 8.3 Firmware source code (including
examples from Philips) on page 59.
Debugging was done using a dumb-terminal, allowing interaction between myself and the
firmware. This proved very useful for stepping through the firmware step-by-step and verifying all
logic levels and wire connections on the board, as well as allowing me to view the results of businteractions with the D12. This sped up development considerably by allowing a test-first approach
to development, implementing each request of the enumeration process as it arose thus ensuring
progress was always been made.
24 Please note that at this time I had the dumb terminal connected to where the GBA-connector is in the schematic.
31
During enumeration the device will move through four states defined by the USB specification:
Powered, Default, Address and Configured. A typical sequence of events for an enumeration with a
Windows host are (adapted from [2]):
1. The user plugs a device into a USB port.
Either directly into the root hub, or anywhere downstream of it. The hub provides power to the
port and the device is in the Powered state.
2. The hub detects the device
There is a 15k pull-down resistor on each data-line of the hub's USB port, the presence of a
1.5k pull-up resistor on either line signals a device's presence. if the pull-up is on D+ it is a
full-speed device and if D- a low-speed device.
The hub provides power but does not yet transmit USB traffic as the device will not be ready yet.
3. The host learns of the new device
When the host next polls the hub's status, it will learn of the new device attachment
4. The hub detects whether a device is low or full speed
The hub detects which of the data-lines has the higher voltage when the bus is idle, and hence
detect the device speed.
5. The hub resets the device
The host instructs the hub to reset the device. This is done by holding both D+ and D- lines in
logic low. These lines usually have opposite logic states.
6. The host learns if a full-speed device supports high-speed
High-speed devices (being the fastest USB 2.0 supports) send special signals during reset which
high-speed hubs can detect and respond to. Full and low-speed devices do not send any special
signals.
32
7. The hub established a signal path between the device and the bus
When the hub removes the reset, the device is in the Default state and it's firmware must be ready
to respond to control transfers over the default pipe at Endpoint 0. The device assumes the
default address of 0x00, the device is now permitted to draw up to 100mA from the bus.
8. The host sends a Get_Descriptor request to learn the maximum packet size of the default
pipe
This is sent to the default address 0x00, endpoint 0. The host enumerates only a single device at a
time, so only one device will respond even if many were simultaneously attached. The eighth
byte of the device descriptor contains the maximum packet size supported by Endpoint 0 (see 5.4
Example: The Device Descriptor on page 38). Windows hosts request 64 bytes of the descriptor,
but as soon as they have received the first 8 bytes (and obtained the maximum packet size) will
request the hub to reset the device. The specification doesn't require a reset here, as all devices
should be able to abandon control transfers if the host issues another Setup packet, but doing so
is a precaution that ensures the device will be in a known state when the reset ends.
This reset during a control-transfer often leads developers to believe there is a fault in their
firmware[2][3].
9. The host assigns an address
Using a Set_Address request. The device reads this address, then acknowledges and stores the
new address. The device is now in the Address state. All communications from this point use the
new address, and the address remains valid until detached, reset or the host powers down.
10.The host learns about the device's abilities
The host again requests the device descriptor, this time reading all of the response. This describes
the maximum packet size for Endpoint 0, the number of configurations the device supports and
other basic information about the device, such as supported USB version and vendor ID.
11.The host assigns and loads a device driver
Using this descriptor the host chooses and loads a device driver. In Windows, this is done by
trying to match the Vendor and Product IDs and the (optional) Release Number of the descriptor
with its driver database. Failing this, Windows attempts to match with any class, subclass and
protocol values received from the device. Once loaded is it common for the driver to request the
retransmission of descriptors or the transmission of class-specific descriptors.
12.The host's device driver selects a configuration
If the device supports multiple configurations the device driver will select one of these and send
33
the device a Set_Configuration request, even if the device only supports a single configuration.
Once acknowledged by the device, the device is in the Configured state and is now ready for normal
use.
Enumeration is complete.
Control transfers can be used to transfer any data, not just requests defined in the specification. A
defined request will begin with the setup stage, alerting the device that this control transfer brings a
request defined in the specification. Setup transactions are high priority: if the device is in the
middle of another control transfer (including another setup transaction) it must abandon that transfer
and respond to the new Setup transaction.
34
bmRequestType
This is a bit-mapped byte which specifies the direction of data flow for the data stage, the
type of request (one of: standard request, class request or vendor-specified request) and the
recipient (one of: device, specific interface, endpoint or other element).
bRequest
This is a byte which specifies the request, in the context obtained from bmRequest.
wValue
These two bytes (a word) can be used by the host to pass information to the device, such as
a new address during a Set Address request.
wIndex
These are another two bytes the host can use to pass information to the device. Typically it
is used to pass an index or offset, such as an interface of endpoint number. This data is
interpreted in the context of the particular request.
wLength
These bytes specify how much data is to be transferred. When the direction is OUT25 this is
the exact number of bytes to follow, when the direction is IN this is the maximum number of
bytes the device may return. The device may return fewer, signalling the end of the transfer by
sending a zero-length packet.
If the wLength field in the Setup transaction is 0, there is no data stage: for example the Set
Configuration request passes it's data in the wValue field of the setup stage and hence does not
require a data stage.
Multiple packets are sent as required until all the data has been transmitted, using the largest
packet-size the endpoint supports (which is specified in the descriptors, please see section 5.4 on
page 37).
25 Recall that all traffic is from the host's perspective: OUT of host, IN to host.
35
Set Address
Purpose: The host specifies an address to use in future communications
Source of Data: none
Data Length: 0
Contents of Value field: New device address. Allowed values are 1 through 127. Each device
on the bus, including the root hub, has a unique address.
Contents of Index field: 0n
Comments: This request is unlike most other requests because the device doesn't carry out the
request until it has completed the Status stage of the request by sending a 0-length data packet. The
host sends the status stage's token packet to the default address, so the device must detect and
respond to this packet before changing its address.
A device must send a handshake packet26 within 50ms after receiving the request, and it must
complete the request within 2ms of completing the status stage. After completion of this request, all
communications immediately use the new address.
Get Descriptor
Purpose: The host requests a specific descriptor
Source of Data: device
Data Length: Variable, host requests certain number of bytes of descriptor. If the descriptor is
longer that the data length given, return the requested number of bytes only, if equal or shorter send
the complete descriptor; in both cases descriptors are sent in one or more packets as needed. If the
26 These are not discussed in this report, they're basic function to acknowledge each transaction phase.
36
complete descriptor is being sent, and its length is an even multiple of the endpoint's maximum
packet size, the transmission will end by transmitting a full packet, but because of this the host will
expect more data therefore the end of transmission must be explicitly signalled by sending a 0length packet. In a USB transfer additional packets are expected after any packet which is the
maximum allowed length (the maximum packet size, defined in a descriptor), hence a packet which
is smaller (including empty) will end the transfer.
Contents of Value field: High byte: descriptor type. Low byte: descriptor value.
Contents of Index field: For string descriptors, LanguageID, 0 otherwise.
Comments: There are 7 types of descriptor, two of which are only applicable to high-speed
devices leaving 5 types of descriptor relevant to this project: device, configuration, interface,
endpoint and string. These are covered in 5.4 USB Descriptors, below.
Configuration descriptor requests are special: the host expects the configuration descriptor, and
all interface and endpoint descriptors it refers to, to be returned.
Set Configuration
Purpose: Instruct device to use the selected configuration
Source of Data: none
Data Length: 0
Contents of Value field: The lower byte specified a configuration by number. If this value
matches a supported configuration the device selects this configuration. A value of 0 indicates not
configured, if this occurs the device enters the Address state and requires a new Set Configuration
request before it is ready for use again.
Contents of Index field: 0
Comments: Upon completion, the device enters the configured state, many of the other standard
USB requests require the device to be in this state.
37
descriptors which contain information about the device's use of power and the number
interfaces supported by the configuration. Each interface descriptor has zero or more endpoint
descriptors that contain the information needed to communication with an endpoint. An
interface with no endpoint descriptors can still use the control endpoint for communications.
Required?
Device
Yes
Configuration
Yes
Interface
Yes
Endpoint
String
interface_power
String descriptors are used to store descriptive uni-code text to help the end-user identify their
device on the host, such as the product name and model. These are not used by the operating system
in any special way, but are typically displayed by configuration applications, such as Windows'
Device Manager and in a pop-up balloon during first enumeration on a Windows XP/2000 system.
Specific classes (including the vendor-defined class) devices may have their own descriptors,
which may or may not be mandatory for the class. This provides a structured way to store
information needed to ensure ease-of-use and to uphold plug-and-play ideals.
Each descriptor contains a value describing its type, usually followed by the descriptor size (in
bytes) and then by a number of fields specific to the descriptor. Of interest to this project are the
following:
Type
Value (hex)
Standard
Descriptor
Device
Configuration
String
Interface
Endpoint
Class
21
HID
22
Report
23
Physical
38
which was the reference I used due its clear break-down and least-you-need-know approach. The
device descriptor of the project's HID-Mouse implementation is a good example (copied from HIDMouse.c, see 8.3 Firmware source code (including examples from Philips) on page 59):
0x12,
//BYTE bLength
0x01,
//BYTE bDescriptorType
0x10,
//WORD (Lo) bcdUSB version supported
0x01,
//WORD (Hi) bcdUSB version supported
0x00,
//BYTE bDeviceClass
0x00,
//BYTE bDeviceSubClass
0x00,
//BYTE bDeviceProtocol
D12_CTRL_BUFFER_SIZE,
//BYTE bMaxPacketSize (probably 16 bytes)
0x25,
//WORD (Lo) idVendor (Lakeview Research (of USB Complete))
0x09,
//WORD (Hi) idVendor (Lakeview Research (of USB Complete))
0x34,
//WORD (Lo) idProduct (for compatability with HID Class app)
0x12,
//WORD (Hi) idProduct (for compatability with HID Class app)
0x88,
//WORD (Lo) bcdDevice
0x02,
//WORD (Hi) bcdDevice
0x01,
//BYTE iManufacturer
0x02,
//BYTE iProduct
0x03,
//BYTE iSerialNumber
0x01
//BYTE bNumConfigurations
//BYTE bLength
//BYTE bDescriptorType
The first byte denotes the length of the descriptor (18 bytes), second the descriptor type as
defined in the specification (device).
0x10,
0x01,
0x00,
0x00,
0x00,
//WORD
//WORD
//BYTE
//BYTE
//BYTE
The first two of these bytes make up a binary-coded decimal (01.1.0 USB v1.1), then the
device class (not specified27), subclass (not specified) and protocol (use depends on class).
D12_CTRL_BUFFER_SIZE,
0x25,
//WORD (Lo)
0x09,
//WORD (Hi)
0x34,
//WORD (Lo)
0x12,
//WORD (Hi)
0x88,
//WORD (Lo)
0x02,
//WORD (Hi)
Now the size of the D12's control endpoint buffer (16 bytes, held in a #define), followed by
the vendor ID, product ID and device code (release version of the product) as another binary-coded
decimal.
0x01,
0x02,
0x03,
0x01
//BYTE
//BYTE
//BYTE
//BYTE
iManufacturer
iProduct
iSerialNumber
bNumConfigurations
39
And finally, 3 string descriptor indexes (1, 2 and 3 in this example all three are used, if they
were not wanted these bytes should be null) for manufacturer, product and serial number. This is
useful, for instance, in a camera to store the camera model: E.G. MPD-4500 Pro) and how many
configurations the device supports (1 in this example).
The vendor ID must be registered with the USB-IF28, which costs a $2500 (USD) yearly
subscription at the time of writing.
The name Human Interface Device implies that the HID class is for interacting directly with
people, and this is indeed the primary intention of the HID class, however it is not limited to this.
Any device which can function within the limitations imposed by the HID class is a viable HID
device.
The main properties of a HID are thus:
All transfers conform to a data structure called a report. The structure of a report is defined in a
HID class report descriptor, providing considerable flexibility to the developer and potential
portability to both the user and developer.
Each transfer can contain a small to moderate amount of data. For a low-speed device the
maximum is 8 bytes per transaction, for a full-speed device (such as the PDIUSBD12) the
maximum is 64 bytes per transaction, and for a high-speed device 1024 bytes per transaction..
The device may send data to the host at unpredictable times: there is no way for the computer
to know when the user will press a key on the keyboard, so the host's driver polls the device
periodically to obtain new data.
The maximum speed of transfers is limited. At full speed the host guarantees no more than 1
transaction per millisecond for a maximum transfer rate of 64 kB/s.
The rate of transmission is not guaranteed, only the latency (i.e. polling interval). For instance
if a device is configured for 10ms intervals, the time between transactions may be any period
40
HIDs primarily transfer data from device to host, but the opposite is possible the classic
example is a joystick with force-feedback. All HID transfers use either the default control pipe, or
an interrupt pipe on another endpoint. HIDs are required to have an interrupt IN endpoint for
sending data to the host, and interrupt OUT endpoint is optional. This was not the case in USB v1.0
and so Windows 98 Gold, the first version of Windows to support HIDs, does not support the
interrupt endpoint but instead uses the USB v1.0 Get Report control request. Use of this request is
discouraged in the current version of USB.
An interrupt endpoint is best for low-latency data which is time-critical (such as movement data
from a mouse), while control transfers are better for transferring configuration data or similar which
is not time-critical.
Because HIDs are defined on a per-interface basis it is possible that a HID be only part of a USB
device, for instance a video player may also implement a HID interface for software control of the
machine's functionality.
Firmware Requirements
Device descriptors must identify at least one HID class interface and support an interrupt IN
endpoint, in addition to the default control pipe. It must also contain a report descriptor which
defines the data structure used for transmitted data (termed reports).
To send data the device is required to support Get Report requests which use control transfers to
transmit data, and interrupt IN transfers which do not use requests at all (interrupt data is buffered
internally and transmitted when the host next polls the device). To receive data it must support Set
Report control transfers and, optionally, interrupt OUT transfers.
As mentioned previously, all HID data are transmitted in data structures termed reports. These
reports mus be specified in the HID report descriptor using a format defined in the HID
specification. Devices may support one or more reports (i.e. can have multiple data-structures).
Reports come in three flavours: Input, Output and Feature. As with all USB traffic, this is from
the perspective of the host Input reports go from device-to-host, Output from host-to-device and
Feature reports can go in either direction.
41
0x01,
0x04,
0x01,
0x01,
0x00,
This defines the report to be a Joystick, and allows the host's operating system HID driver to load
any appropriate modules to interpret the rest of the structure.
0x05,
0x19,
0x29,
0x15,
0x25,
0x95,
0x75,
0x81,
0x09,
0x01,
0x03,
0x00,
0x01,
0x03,
0x01,
0x02,
//
//
//
//
//
//
//
//
USAGE_PAGE (Button)
USAGE_MINIMUM (Button 1)
USAGE_MAXIMUM (Button 3)
LOGICAL_MINIMUM (0)
LOGICAL_MAXIMUM (1)
REPORT_COUNT (3)
REPORT_SIZE (1)
INPUT (Data,Var,Abs)
This defines 3 1-bit buttons. Specifying logical properties allows scaling for instance: if the
application expects a pressure the button could be scaled to be the maximum possible pressure by
setting its logical maximum appropriately.
0x95, 0x01,
0x75, 0x05,
0x81, 0x03,
//
//
//
REPORT_COUNT (1)
REPORT_SIZE (5)
INPUT (Cnst,Var,Abs)
Here some some generic data is defined. This case it is used as padding to complete a byte (3x 1bit + 1x 5-bit).
0x05,
0x09,
0x09,
0x15,
0x25,
0x75,
0x95,
0x81,
42
0x01,
0x30,
0x31,
0x81,
0x7f,
0x08,
0x02,
0x06,
//
//
//
//
//
//
//
//
Here we define the axis of the joystick, and scale it to 127, using a byte for each axis.
0x06,
0x09,
0x75,
0x95,
0x91,
0x00, 0xff,
0x01,
0x08,
0x02,
0x02,
//
//
//
//
//
This defines a new entity for transmitting two bytes from host-to-device. This is not needed by
joysticks, nor does it interfere with them. It was added to demonstrate my implementation of Set
Report control transfers in the firmware, coupled with a PC application which sent data. This is an
example of a class-extension, it does not contradict or affect the normal functioning of the joystick
class, but provides additional functionality to software that supports it. It is interesting to note that
this extension does not require special drivers, as report data is available to user-mode29 application
through a Microsoft HID API; instead an application with special support is required.
0xc0,
0xc0
//
END_COLLECTION
// END_COLLECTION
These bytes close the collections and end the report descriptor.
In reiterate: HIDs use interrupt transfers to transmit structured data as defined above, with a
guaranteed latency.
See 8.3 Firmware source code (including examples from Philips) on page 59 for the complete
source.
29 Windows systems make a distinction between system and user components, the latter not being permitted to access
hardware or memory directly.
43
44
This diagram is not intended to be complete, but to show the high-level structure of the
firmware's interrupt service routine. The entry point is the incoming line at the top left, and the exit
point is just below it on the N branch of INT_N Low?.
45
6.2 - Development
After some notable difficulties (see 6.3 Notable
problems encountered on page 47) the firmware
successfully enumerated a HID device, which would fail
to start (the HID components not yet being implemented).
See Enumerated.c and Enumerated II.c (details
at end of section)
This was the first proper feedback to be received from
Windows, and from this point development sped up
considerably, concentrating on implementing request
handlers and adding functionality, instead of fiddling with
settings in the dark.
Soon enough a working implementation of a HID-
Illustration
enumeration
6.2.1
Successful
Mouse (with the string descriptor MeerMouse) was completed, transmitting identical report data
on each interrupt. The report descriptor defined positional data to use relative distances (instead of
absolute coordinated), which caused the cursor to crawl steadily along the screen. From there it was
little work to have the mouse moving in all directions, then activating buttons, and from there using
the GBA (via USART interrupts) to control this data by means of the UARTTest application. See
HID-Mouse.c
However, it was impossible to test host-to-device report transfers, as mice (and keyboards) are
locked by the system on Windows for security reasons, this meant that a user-mode application
cannot obtain a handle to the device nor interact directly with it.
HID-Mouse was converted to HID-Joystick, which uses a near-identical report structure but does
not suffer a system-lock. A test application obtained from www.lvr.com/usb (written on the .
NET framework) allowed the firmware's implementation of the Set Report request to be quickly
tested, and was demonstrated during the project presentation, the joystick movement being easily
observed from the Game Controllers panel in Control Panel. See HID-Joystick.c.
Source code for all check-points and implementations is included on the attached CD, please see
8.3 Firmware source code (including examples from Philips) on page 59 for details. The PC-side
HID-class test application is also on the CD. The default VendorID and ProductID that the
application starts with match that of the device created.
46
byte of the configuration descriptor, and checking string descriptor indexes31) the new solution was
both much more memory-efficient and also much more compact, readable and elegant when
compared to the array-pointer solution used previously.
Debugging issues
Debugging needed to be done at the device as no useful data is available from the host before
enumeration completes. This was achieved by using the PIC16F877's hardware USART to transmit
text using printf() statements in the firmware.
This introduced sizeable delay, as each character takes considerable time to transmit. At a baud
rate of 9.6kbps it takes 0.104ms per bit, including stop and start bits, resulting in a time of 1.146ms
to transmit a single character. The fastest reliable baud rate achievable on a PIC running at 4MHz
(according to the CCS-compiler I used) was 19.2kbps, resulting in a time of 0.573ms per character.
This delay would alter the outcome of USB bus transactions. If the D12 does not have data to
send when the host requests some, it will return a STALL token, after receiving 3 or more STALL
tokens the host will give up and the transaction will fail.
The simplest way to remove these delays would be to remove all printf() statements and
avoid them entirely, but this was not an option. Instead I aimed to avoid delays whenever possible
by adding debugging levels to the firmware. I connected a set of DIP switches to the PIC, the
values of which would be read on start-up, dictating the debugging level. Three switches were used
to indicate how detailed debugging should be, offering a range of 0 (most verbose) to 7 (only
display errors in the firmware itself). All debugging statements in the firmware would compare their
debugging level with that of the current execution, and only display if their level was equal or
higher.
This worked well, level 7 debugging, the most concise, would be used until a problem was
encountered at which time the debugging level would be lowered (and hence made more verbose)
and then the firmware restarted displaying more detail at the expense of a slightly altered execution
time. This would be repeated until enough detailed was gathered to resolve the issue.
Some errors could not be debugged using this approach, as the different timings of debugging
levels would alter the outcome of the execution.
48
Eventually I discovered a note in the PDIUSBD12 FAQ[10] on the Philips Semiconductors website:
Q: What should be the width of the reset pulse PDIUSBD12?
A: The external reset pulse width has to be 500 s (min.). When the reset pin is LOW, make
sure the CS_N pin is in the inactive state; otherwise, the device may enter Test mode.
Because CS_N is permanently tied low in my setup, the D12 would always enter test mode when
I wanted it to reset, and I was unsuccessful in ensuring CS_N was in the inactive state during a reset
despite efforts. After spending considerable time on the issue, I cut my losses and instead added a
push-button which breaks the circuit between VBUS and the reset of the system when pushed. This
provided a convenient way to reset the entire system during debugging, which did not wear out the
tracks of my USB plug and socket (I was unplugging and reinserting constantly until the addition of
this button).
I discovered from the USB-IF's Developers [sic] Discussion Board32 from someone in a similar
position to me that:
The D12 has special support built in to it for changing the address value at the correct time.
Issuing the SET ADDRESS ENABLE command (0xD0) to the D12 only updates a holding
register
The D12 will wait until the appropriate time (right after the zero length packet representing the
STATUS phase gets INd by the host) before it actually switches from the default address (0) to
the new address.
32 http://www.usb.org/phpbb/
49
This proved to be correct, by amending my firmware to perform the Set Address D12 command
before initiating the status stage the device became considerably more compatible. Until this change
the device would enumerate on my development PC but would fail to enumerate on any other
machines I attempted (all Windows XP SP2 systems), once this change was made the device would
enumerate on all machine I tried it on.
I believe the presence of two USB sniffers (see 4.2 Snoopy Pro and 4.2 HHD USB Monitor on
page 23) on my development PC relaxed the timing restrictions of USB by incurring soft delays,
thereby allowing the device to enumerate while other PCs were not as accommodating.
50
7 - EVALUATION
7 - Evaluation
7.1 - Did the project achieve its goals?
The goals of this project, as described in the original project specification[11], para-phrase as
follows:
To create an interface between a PC and a Nintendo Game Boy Advance (GBA) system which
is easy to use (specifically: requires no special drivers, and no user configuration) and to
create some proof-of-concept software that shows the use of this interface to communicate
between the two.
51
CHAPTER 7 - EVALUATION
No configuration required
Device-PC Interface
While the HID tester application offers the ability specify the VendorID and
ProductID of the device, in practice this would be coded into the application and not
available to the end-user to change, or would be acquired through a Windows API if looking
for any attached device from a class of devices.
Hence there is nothing to configure, the enumeration process negotiates an address for the
device, and software acquires a handle on the device via its VendorID, ProductID and
(optionally) its DeviceID (release number), or again through an API call if only the device
type is important. The user is only required to attach the device and start an application which
utilises it.
It is true to say that no configuration is required to use the device when attached to a PC.
GBA-Device Interface
The UART baud rate (9600) utilised between device and GBA is non-negotiable, and both
the are coded to use the same settings. However, if the device was to be used as a generic
GBA PC interface, it is unlikely that these settings will be coded into the GBA, and in this
respect this goal was not achieved.
Overcoming this would require creating a negotiation protocol, similar to the process of
enumeration, for the GBA. Such a task is non-trivial, beyond the scope of this project, and as
such has not been attempted.
It was not the aim of this project to implement a serial port over USB, and so I do not
consider this failure to be significant.
Proof-of-Concept Applications
Two applications were needed to effectively demonstrate the working system, one on the GBA
and one of the PC.
GBA UARTTest
A dumb-terminal like application for the GBA was developed during the course of this
project, which effectively demonstrates use of UART communications on the GBA. Received
data is displayed as hexadecimal on the screen, and button presses are transmitted as ASCII
characters (for instance up is transmitted as '^', down as 'v', left as '<' and so on).
The GBA interfaces with the device via UART and so this application is all that is needed
52
Due to time constraints, a HID tester application from the open-source community was
used to test the device. It utilises standard Windows API calls to obtain a handle on the USB
device by specifying the device's VendorID and ProductID, which are defined in the
device descriptor of the firmware, see 5.4 Example: The Device Descriptor on page 38.
Once a handle is obtained, the application can send and receive reports with the device.
The report data the device sends is generated either by the GBA or randomly, depending on
the state of a DIP switch (labelled SW4 in Illustration 4.3.3 - Master schematic for project
hardware on page 28). The report data consists of two single-byte axis and a byte button map,
hence the ASCII transmissions of the GBA are converted to relative-coordinate axis data35 by
the P877 before transmission.
This application effectively demonstrates USB Device communication, and hence USB
GBA communication in both directions.
53
CHAPTER 7 - EVALUATION
operating systems (such as Mac OS X) which are part of the standard, but not correctly implemented
in the firmware. As mentioned earlier, this is the case with Windows 98 Gold and the HID Get
Report request which it uses, requiring use of the control pipe to transfers reports, instead of the
usual interrupt endpoint. As no thorough testing with other systems was undertaken I can only be
sure the device is compatible with Windows XP.
As in USB itself, the device is a slave to the host, and hence the GBA is a slave to the PC
application. Transmissions from the GBA are buffered in the P877 until the host polls for them. It is
up to the PC software to make best use of the GBA to perform its intended task. The current
demonstration applications have no intelligence, meaning that, for instance, the GBA does not
receive confirmation from the P877 that a character it sent was received and there is no flow
control.
Development of the PC aspects of this project were limited by time, and relatively little
understanding of how an application interacts with a device was obtained. For instance, it is not
clear how the native HID class driver of Windows handles interrupt data it acquired when no
application is sinking it, as is the case when using the HID-Joystick firmware when not running the
HID Tester application or viewing the data in the Game Controllers panel of Control Panel.
If I had to do this project again, I would reconsider my choice of USB interface chip. During this
project I discovered a USB solution chip family called EZ-USB, manufactured by Cypress37.
This family of chips have an integrated micro-controller. An EZ-USB does not feature static
memory, but rather needs to be loaded with a firmware upon attachment to a host PC. When
attached to a host, the device enumerates itself as an EZ-USB device and a tool supplied by Cypress
is used to load the device with firmware this can be automated (as in the case of commercial
deployment). The tool, fxload, has a Linux version as well.
7.3 - Limitations
The firmware contains some known limitations, which were not addressed for various reasons,
and the project itself was limited in some respects. The major limitations are summarised below.
54
7.3 - LIMITATIONS
An internal buffer on the P877 large enough to accommodate such reports cannot be allocated
due to RAM limitations. Code is in place to deal with such requests, adapted from the algorithm
used for transmitting descriptor data over the (much smaller) control endpoint buffers, which is core
to the enumeration process and known to work with multi-transaction data (as used during device
enumeration). However, it was not possible to adequately test this adapted implementation.
By increasing the amount of available memory (perhaps by attaching an external RAM module,
or using a higher-specification micro-controller) this could be over come.
55
CHAPTER 7 - EVALUATION
However, it is worth noting that Get Report requests are extremely rare, and not used at all in
Windows XP which favours interrupt transfers, as per the recommendation of the current HID class
specification.
56
7.3 - LIMITATIONS
Both the PIC16F877 and PDISUBD12 feature a low-power state which may well provide an
answer for this, the PDIUSBD12 data sheet suggests that the PDIUSBD12 can be woken by either
the micro-controller or USB bus it is attached to, and will trigger and interrupt for the latter.
Dynamic Sensors
While learning of the HID report structure, and its ability to associate units of measurement with
data fields, it occurred to me that a generic monitoring application for the host PC could be created,
which would parse the report descriptor and setup a display of the data with associated units, as well
as providing data logging and visualisation based on the units.
This could provide a convenient interface to connect multiple devices each monitoring different
things, and have them dynamically allocated screen-space (or equivalent) to visualise the data, or in
a more complex system were all readings relate to the same model, allow further refinement of
simulations.
Specifically it occurred to me that such a facility would be useful in creating mobile robots, as
sensors connected via USB could have associated units and scales specified in their report
descriptor(s). This could ultimately lead to a pseudo-generic mobile robot for which individuals
could construct complex sensors, each able to process readings to produce other readings (such as is
done in triangulating position from sonar data).
57
CHAPTER 7 - EVALUATION
(CBI). Both implement very few class-requests, two for bulk-only and just a single Accept Device
Specific Command request for CBI. A descriptor defines what set of command blocks the device
actually uses to manage its data.
The current Mass Storage Device specification supports 5 command blocks ranging from
Reduced Block Commands (RBC) which is typically used in Flash devices, to SCSI transparent
command set.
It appears that the USB side of the implementation would be minimal, the focus being on
implementing a command block appropriate to the storage medium used.
58
environment,
pre-compiled
binary
suitable
for
multi-boot40
and
file
INSTRUCTIONS.TXT which serves to explain the application's purpose and it's usage.
VisualBoy Advance, a GBA emulator for Windows, has been included for convenience; however
it is of limited use as it does not emulate the communication port.
HAM is available from http://www.ngine.com and a version is included on the disc for
your convenience. Please be sure to check the website for the most up-to-date version.
Source
59
CHAPTER 9 - ACKNOWLEDGEMENTS
9 - Acknowledgements
I would like to thank Dr. Roger Packwood for his invaluable advice, open approach and teaching
me to always tackle the highest-risk first in my work. I also wish to thank Mr Rod Moore for his
advice and enthusiasm about this project, it is satisfying to know that this work may be used by
others. Finally, I would like to thank Mr Barry Thorne, Mr Franc Buxton and Mr Stuart Valentine
for welcoming me to their laboratory and creating a friendly atmosphere where I quickly felt at
home.
I wish to formally acknowledge the work of Jan Axelson, author of USB Complete[2] which
served as my key reference throughout the course of this project.
I also wish to formally acknowledge the work of Craig Peacock, of Flinders University,
Australia, who is the maintainer for BeyondLogic.org and its USB in a NutShell[3] multi-part
article, around which the ground-work of this project was based.
60
10 - REFERENCES
10 - References
[1] Nintendo - Customer Service -- Corporate Info - Company History, viewed Wed, 6 Apr 2005,
http://www.nintendo.com/corp/history.jsp (on attached CD)
[2] Jan Axelson, USB Complete: Everything You Need to Develop Custom USB Peripherals,
Lakeview Research, 2001. ISBN 0-965082-990
[3] USB in a NutShell, viewed Tue, 12 Apr 2005,
http://www.beyondlogic.org/usbnutshell/usb7.htm (on attached CD)
[4] Gameboy Advance Technical Info (GBATEK), viewed Wed, 6 Apr 2005,
http://www.work.de/nocash/gbatek.htm (on attached CD)
[5] DarkFader.net Game Boy Advance Development, viewed Thui, 14 Apr 2005,
darkfader.net/gba/main.html#GbaTool (on attached CD)
[6] FiveMouse.com GBA Web Server, viewed Thu, 14 Apr 2005,
http://www.fivemouse.com/gba/ (on attached CD)
[7] PDIUSBD12: USB interface device with parallel bus, Koninklijke Philips Electronics N.V.,
2001 (on attached CD)
[8] PIC16F87x: 28/40-Pin 8-Bit CMOS FLASH Microcontrollers, Microchip Technology Inc., 2001
(on attached CD)
[9] Firmware Programming Guide for the PDIUSBD12, Koninklijke Philips Electronics N.V., (on
attached CD)
[10] Philips PDIUSBD12 FAQ, viewed Mon, 18 Apr 2005,
http://www.semiconductors.philips.com/cgi-bin/faq/
11: Robert Meerman, Project Spec: Making a Personal Digital Assistant on a Game Boy Advance,
(see Appendix), 2004
61
CHAPTER 11 - APPENDICES
11 - Appendices
11.1 - Project Specification
Making a Personal Digital Assistant on a Game Boy Advance
Problem
Powerful Personal Digital Assistants (PDAs) and smart-phones are becoming common place and
are increasingly used to entertain their users with games. This is fine for those that predominately
want an organiser and think of games as a bonus, but what about those that prefer the games, but
would still like some organisational capability? Portable games consoles are powerful enough to run
simple PDA-like applications but they lack the connectivity that PDAs and smart-phones have in
abundance.
Objectives
To create an interface between a PC and a Nintendo Game Boy Advance (GBA) system which is as
easy to use as any existing PDA and to create some proof-of-concept software that shows the use of
this interface to communicate between the two.
Breakdown
The applications will be expanded to work with real data, such as the to-do lists / contact list
of larger applications such as MS Outlook using SyncML.
Methods
Pre-requisites phase
Probing the chosen PC interface and testing code which manipulates this while determining
the properties of the signals (voltage etc.)
Once the results from the above are predictable and well understood:
Create some signal translation circuits as applicable (perhaps the voltages are different for
each device, that would be taken care of here)
Probing / coding the micro-controller with some test data and getting a feel for the
capabilities of the device (response times, speed, caveats)
Implementation phase
Assemble the interface made up of the GBA connector cable, PC connector cable and microcontroller.
Set-up micro-controller to be identified and used by the PC (as applicable to the chosen PC
port i.e. USB will need PnP information, protocol setup etc.).
NB that the GBA does not require special set-up as it does not have an operating system.
Instead it is only required that the multi-player port chip-set is in the correct mode (chosen
during pre-requisites phase)
Create some proof-of-concept software which makes use of the new connectivity of the GBA such
as synchronising a to-do list, contact list or similar task.
Code an application for the GBA which displays incoming data on-screen.
Code an application for the PC which generates test data and sends it to the GBA.
Once this is working:
Code applications to do the reverse (PC -> GBA)
Combine these into single bi-directional applications which swap test-data.
If time allows:
The protocol of the GBA will be improved to resemble a more orthodox protocol.
Timetable
Checkpoint
End of week 5
End of week 6
End of week 7
End of week 8
End of week 9
End of week 2 Term 2
End of week 4 Term 2
End of week 6 Term 2
Description
Chosen PC port
Finished reading up on GBA multilayer port,
experimentation/probing started
Chosen micro-controller
Experiments / probing PC port under way
Start designing/profile needs of translation
circuits
Micro-controller experiments under way
Interface able to (partially) transmit / receive data
Interface stable and working
Start development of applications
Minimal applications complete
Test on other PCs (non-development ones) for
installation issues and compatibility
Project report is in draft essay form which
contains all relevant information, but may been
reworking.
63
CHAPTER 11 - APPENDICES
Resources
The following will be required in addition to those currently available to me within the department
(such as the Linux workstations):
Direct access to the parallel port on at least one workstation (for programming the GBA
hardware using my personal 3rd-party programmers)
Direct access to the serial port on at least one workstation (for debugging the GBA hardware
in real-time using my personal 3rd-party debugger)
Frequent access to a PIC-programmer (for the interface micro-controller)
Manuals (possibly online) which explain how to use the PIC-programmer
Manuals / reference on programming PICs (dependant on the brand of PIC chosen, it is
expected that the project supervisor will guide this choice to best suit the resources
available)
64
Part Value
10uF
0.1uF
1M
120
4.7k
PDIUSBD12
PIC16F877
MAX3232
4MHz
6MHz
Description
Electrolytic Capacitor
Electrolytic Capacitor
Light Emitting Diode
Push button normally closed
Resistor
Resistor
Resistor
Single pole switch
USB Interface Device
Micro-controller
RS232 level translator
Ceramic Resonator
Crystal
Component Header
Qty
1
5
3
1
1
4
3
4
1
1
1
1
1
2
Parts
C1
C2 C3 C4 C5 C6
D1 D3 D4
PB1
R2
R3 R4 R5 R6
R1 R7 R8
SW1 SW2 SW3 SW4
X1
X2
GBA_Header USB_Header