Skip to content


Switch branches/tags

Name already in use

A tag already exists with the provided branch name. Many Git commands accept both tag and branch names, so creating this branch may cause unexpected behavior. Are you sure you want to create this branch?

Latest commit


Git stats


Failed to load latest commit information.
Latest commit message
Commit time


USB response boxes with real-time accuracy.

Often in psychological experiments, researchers wish to record button presses with accurate timing. Operating system timing resolution may be inadequate, so out-of-band timing channels are required.

This project centers around a USB keyboard-like device that allows a user to measure its latency.

Keyboard Quick Start

To use as a USB keyboard, plug-and-play. The default keys are:

  • Four-button version (left-to-right)

    • Top row: w x y z
    • Metal: _
  • Eight-button version (left-to-right)

    • Top row: a b c d
    • Middle row: e f g h
    • Metal: _

Note: if the home key (the metal pin near the center-bottom of the response box) is held, subsequent key presses will be shifted, e.g. 'a' will become 'A'.

Timing Measurements

Round-trip delay d is calculated as per the SNTP protocol, section 5:

Timestamp Name          ID   When Generated
Originate Timestamp     T1   time request sent by client
Receive Timestamp       T2   time request received by server
Transmit Timestamp      T3   time reply sent by server
Destination Timestamp   T4   time reply received by client

The roundtrip delay d and system clock offset t are defined as:

d = (T4 - T1) - (T3 - T2)     t = ((T2 - T1) + (T3 - T4)) / 2.

Timing measurement from psych-button uses a modified version of SNTP, where psych-button responds to a timing request with a single number that corresponds to T3-T2. In this scheme, T2 is always 0. T3 is measured in integer microseconds. Offset is not used, because psych-button doesn't keep a wall clock time. The only figure we're interested in is the round-trip delay.

This procedure is done at least once, usually before an experiment, but can be done at any point in time except during data collection.

PC (note system time T1), send character: 'T'
psych-button: T3
PC (note time of reply T4, calculate d given T3, T2=0)

Python pyserial example

cd examples/

The results from this test is a list of 100 numbers, corresponding to timing measurements before (t1) sending a T and after (t2). The plot below (generated by this script, written in J) shows the results of one such test, highlighting the standard deviation (blue), variance (red), arithmetic mean (green) and differences (t2i - t1i, violet):

Usage (Keyboard)

The Keyboard interface sends a keydown event when a button is pressed, or a keyup event when it is released.

The Keyboard interface is plug and play. By default, the 4 (or 8) buttons correspond to w, x, y, and z keyboard events. The "home" button prints a _ (underbar). Open a text editor and use the response box to "type" letters.

button key
0 w
1 x
2 y
3 z

Note: the 8-button box has the default alphabet abcdefgh

Usage (Serial)

Serial mode allows for monitoring the keys pressed, just like Keyboard mode, but in addition provides the following commands:

Command Function
l list alphabet
L modify alphabet
T query latency

Note: These commands are processed immediately and may interrupt data taking, so only use them when not waiting for data.

When any button changes, the Serial interface responds by printing the state of all the buttons on a single line.

To use the serial interface, open a serial terminal on your computer using a program such as pyserial. Use the following settings:

  • 9600 baud
  • 8 data bits
  • no parity
  • 1 stop bit

Pressing and holding the b0 button (and no others) will result in one line of output:

1 0 0 0 0

Meanwhile, if you press the b3 button, while continuing to hold b0, the next output will be:

1 0 0 1 0

Finally, releasing the b3 button, and then releasing the b0 button, will produce this output:

0 0 0 1 0
0 0 0 0 0

The eight-button box is similar (here showing b1 pressed, then released):

0 1 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0

Note: the "home" button is the last value in the line.


Source code built with platformio, a cross-platform command-line based build tool and dependency manager.

Related Reading