Getting help

Email Tom Dealtry -


The following are instructions on how to communicate with the NOvA timing distrubution unit (TDU). The TDU distributes timing information throughout the system, handles synchronisation between boards, and includes automatic propagation delay calculation & compensation. For a full list of functions, check the TDU FPGA Firmware Guide

There are a couple of ways to communicate with the TDU:

Hardware connection information. If you don't have access to the hardware, you can run a basic emulator

A list of commands will show you what you can (currently) do, along with a list of error codes for you to understand the response.

Communication with the TDU

Source the lbnerc code (up to date instructions at Running_DAQ_Interface)

cd /data/lbnedaq/daqarea
source fireup

In the following, $LBNERCROOT refers to the root path of your lbnerc install (it's not actually a variable that's set!)

Using the xmlrpc server is preferred, since the TDU can only handle a single connection at a time (using the xmlrpc server is a good way to prevent problems if multiple processes attempt to control the TDU at the same time).

It should also be noted the the default values of host and ports of the TDU and XMLRPC server in the scripts here are what is shown here, therefore, in most circumstances, you can run without providing these options.

Communication via xmlrpc server

The first step is to initialise the xmlrpc server (if it hasn't been already). The options -T and -P refer to the TDU host & port respectively (the master in this example). The optiosn -H and -r refer to the host & port the xmlrpc server is being created on.

tdu -T -P 10001 -H localhost -r 50008

Next, you can use call the xmlrpc server to communicate with the TDU.

python rc/tdu/testing_scripts/ -T localhost -p 50008

This will print out a list of commands and exit. To actually do something, add one (or more) switches
-P    calls do_ping()
-g calls get_status()
-s calls do_time_sync()
-d calls do_delay_calc() followed by do_time_sync()
-i calls read_tdu_id()

Note that you can use multiple switches in a single call, and operations are performed in the order listed above.
If you want to do something else, then you can either add in a new option, or write a new script based on

The result of each command is printed to screen, along with "(SUCCESS)" or "(FAILURE)".

To kill the xmlrpc server, pass the -k argument to

Communication with TDU directly

python rc/tdu/testing_scripts/ -T -P 10001

By default this will do_ping(), and if successful do_time_sync().
A couple of switches allow you to do more:
-d    calls do_delay_calc()
-t calls debug_read_all_registers()

If you want to do something else, then you can either add in a new option, or write a new script based on

Running an emulator

If you don't have access to the hardware, you can run on a (very basic) emulator.

python $LBNERCROOT/rc/tdu/testing_scripts/ -T localhost -P 50007

List of commands

All 'get', 'do', and 'read' commands return an error code with a common numbering scheme ("0" means success). 'get' commands also return additional information.

'get' commands

  • get_status()
    Returns [error_code, ready_to_do]. When ready_to_do is True, the control register can be modified (i.e. a 'do' command can be performed)
  • get_nova_time(init_nova_time=False)
    Returns [error_code, nova_time]. nova_time is a 64-bit integer.
    Note: do_time_sync() must have been called since the last power cycle (TOCHECK: or immediately prior to this operation?), or you need to pass a value init_nova_time=True to force an update without the time sync (TOCHECK: does this update the correct register?)

'do' commands

All 'do' commands should be run on the master

  • do_ping()
    ping the TDU
  • do_time_sync()
    Perform a time synchronisation (this calls get_status() internally)
  • do_delay_calc()
    Perform a propagation delay calculation (this calls get_status() internally)
  • do_send_sync_pulse()
    Send a sync pulse (this calls get_status() internally)
  • debug_do_write_control_reg(data_to_or)
    Write the control register to perform a none standard operation (this calls get_status() internally)

'read' commands

  • read_tdu_id()
    Read out the TDU version & ID numbers
  • read_tdu_status()
    Read out the TDU's current operating conditions (current, voltage, temperature, fan status, FPGA status)
  • read_gps_status()
    Read out the GPS status (faults, timeouts, sat count, etc. + current UTC time)
  • read_error_registers()
    Read out the error registers
  • read_control_reg()
    Read out the control register
  • debug_read_all_registers()
    Read out all the registers. Also comes with some hints on what the 'default' for normal operating conditions is.

Other commands

  • close_socket()
    Safely close the connection to the TDU
  • reinit_client(ntries)
    Calls close_socket(), and then performs ntries attempts to reconnect to the TDU (with 10 second sleeps)

Error codes

0          Success!
100-119    Wrong number of bytes received
120-139    Zero bytes received - connection to the TDU has probably been lost, try resending command to find out
140-159    Connection to TDU was lost, but has been recovered. Resend your command
-200/-201  Invalid register/data on receive
+200/+201  Invalid register/data on send
300        Cannot perform a 'do' command (get_status() returns ready_to_do=False after 10 attempts including 2 seconds of sleep)
301        Not ready to sync (TDU status error)
302        Not ready to sync (GPS status error)
400        Error found in error registers
500        Propagation delay calculation failure

List of TDU IP addresses

  • Master:
  • Slave:
  • ... (to be expanded)

The port is ALWAYS 10001 (unless you're communciating with an emulator)

All 'do' commands should be run on the master.

Using the NOvA GUI (TDUControl) - OLD & BROKEN

To start TDUControl, use the following steps:

  1. log into the lbnedaq account on lbne35t-gateway01
  2. source /data/lbnedaq/novadaq/setup/
  3. TDUControl -m
  4. enter the IP address of the Master TDU into the GUI (

Alternatively for steps 3 & 4, you can run TDUControl -m -t