For responsive controls and high performance gaming, high adapter latency is extremely undesirable. Let's look at why and how it happens and what
can be done to minimize it.
If expressed with words, an adapter works like this:
- At a fixed interval, the adapter polls the controller to detect state changes (buttons, axis, etc).
- When a change is detected, the adapter sends an event to the PC.
- But USB devices are also polled by the PC at a fixed interval. This means that to send the event, the adapter actually has to wait until the next USB poll.
There are two main contributors to latency:
- The controller poll interval: Adapters commonly poll controllers at 16ms intervals. This makes sense as it mimics what most games
do in polling the controller once per video frame. But it also means that if you push fire 1ms after the poll, the adapter will only
know it at the next poll, 15ms later.
- The USB poll interval: For an USB low speed device, the minimum interval is 10ms. Depending on the timing, if the adapter learns
about the button press right after the USB poll took place, the computer won't know about it for another 10ms. In the worst case
scenario, the 15ms latency from point 1 adds to the 10ms, totalling 25ms.
Here is a sequence chart to visualize the above:
The chart clearly shows:
- Latency source 1: The button press occurs, but the adapter knows about it later when it polls the controller.
- Latency source 2: The adapter finally knows about the button press but has to wait for the next USB poll to report it to the PC.
Given the above an obvious solution comes to mind: USB and controller polls both should take place as often as possible. Let's examine both:
- USB polls: This is a simple matter of setting the USB endpoint descriptor bInterval field to a low value. For USB Low speed devices,
the minimum interval is 10ms. For USB Full speed devices, the minimum is 1ms. This adapter, being a full speed device, uses the minimum value of 1ms.
- Controller polls: By default, this adapter polls at 5ms intervals. But this can be changed using the management tool. Setting this to a
very low value does not appear to cause problems with standard controllers, but incompatibilities could arise when using third party controllers or adapters.
It is worth noting that there is another approach to reducing USB poll induced latency by timing the controller polls such that they take place a few
moments before the next USB poll. But with a 1 ms USB poll interval, it's not really necessary.
|Adapter||USB type||Controller poll interval||USB poll interval||Worst case||Comments|
|raphnet gcn64usb v3 (The one on this very page)||Full speed||5ms default||1ms||6ms||If controller poll is configured to the minimum value of 2ms, worst case is only 3ms.|
|raphnet gc/n64 usb v2 (predecessor)||Low speed||4ms||5ms||14ms||Due to the report size, two USB polls are necessary to transmit an event, hence the 14ms worst case instead of 9ms|
|Non-raphnet adapters (for reference)|
|Mayflash dual N64 to USB||Low speed||16ms||8ms||24ms||bInterval = 8ms, controller poll interval verified using an oscilloscope.|
|Mayflash GC (4x) to USB (PC mode)||Full sped||8ms||1ms||9ms||bInterval = 1ms, controller poll interval verified using an oscilloscope.|
Even though the minimum poll interval for an USB low speed device is 10ms, it is possible to cheat and use a lower value. Because it works.
The worst case value given for non-raphnet adapters assumes that no attempt is made to synchronize controller reads with USB polls (i.e. reading the
controller right before the USB poll). If they are doing synchronisation, then the usb poll interval (or a fraction of it depending on design margins) needs to be subtracted from the worst case value.
Since firmware version 3.2.1, there are several modes (or personalities) allowing a more
accurate adapter USB product name to be displayed. For instance, if you built a N64 to USB adapter,
the adapter can now appear as "N64 to USB" instead of "GC/N64 to USB".
Also, since firmware version 3.3.1, there are also two player modes.
Configuring the personality and/or enabling a two payer mode must be done using the gcn64ctl
- Install the adapter management tool. It has a graphical user interface, but command-line
tools will be installed along with it. There will be an entry in the start menu (or the new equivalent
and concept of the day) to open a terminal in the folder where the tool executables are.
- Connect the adapter to configure. Only one adapter should be connected at the time.
- Execute the command with the appropriate mode argument.
# Syntax for configuring an adaptater
gcn64ctl -f --set_mode xx
(where xx must be replaced by the appropriate numerical code)
|Code||Name||Number of players|
|0||GC/N64 to USB v??||1|
|1||N64 to USB v??||1|
|2||Gamecube to USB v??||1|
|16||Dual GC/N64 to USB v??||2|
|17||Dual N64 to USB v??||2|
|18||Dual Gamecube to USB v??||2|
Since firmware version 3.6.0, the adapter supports Gamecube keyboards.
raphnet ADAP-2XGC-USB-V and ASCII ASC-1901PO
For the adapter to recognize the adapter and act as an USB keyboard on the PC side, keyboard mode must
first be enabled with the adapter manager.
The current mode is saved in the adapter and automatically recalled each time you connect the adapter.
As there is only one port on single-player adapters, those only support the keyboard part or the
joystick part, but not both at the same time, unless you use two adapters.
When the adapter is in keyboard mode, the keyboard cable (white) must be connected. Connecting the joystick cable (purple)
or a regular Gamecube controller has no effect when the adapter is in keyboard mode.
Connect the joystick cable (purle) to port 1 and the keyboard cable (white) to port 2. The adapter will present
itself as a Keyboard and a Joystick on the PC side.
Under Windows 10, the two-player adapter in keyboard mode appears as a composite device in Devices and Printers
: Uncaught ArgumentCountError: Too few arguments to function figure(), 1 passed in /homepages/12/d162902012/htdocs/www/electronique/gcn64_usb_adapter_gen3/index_en.php on line 367 and at least 2 expected in /homepages/12/d162902012/htdocs/www/php_includes/toolkit.php:460
#0 /homepages/12/d162902012/htdocs/www/electronique/gcn64_usb_adapter_gen3/index_en.php(367): figure('composite_devic...')
thrown in /homepages/12/d162902012/htdocs/www/php_includes/toolkit.php
on line 460