Skip to content

TDTZBUS User Guide

Use TDTZBUS to trigger and manage zBUS device racks from MATLAB or Python.

Requirements

  • TDT Drivers

  • TDT ActiveX package

  • Python only: pywin32

About TDTZBUS

TDTZBUS is a wrapper for the zBUSx ActiveX control that installs with the TDT ActiveX package. It provides access to the zBUS (connect, fire the zBusTrigA and zBusTrigB triggers, flush and reset racks, look up device addresses and microcode versions) and is generally easier to use than calling the zBUSx object directly.

The main convenience is the triggers: the wrapper takes the trigger type by name rather than as a magic number, and supplies the minimum delay for you.

TDTZBUS installs with the ActiveX controls into:

C:\TDT\ActiveX\ActXExamples\Matlab
C:\TDT\ActiveX\ActXExamples\py

or you can download it in the ActiveX Controls example zip.

TDTZBUS Functionality

Note

See zBUS Device in the ActiveX User Reference for the complete zBUSx programming guide.

Creating a TDTZBUS object

Input Parameter Values
'INTERFACE' String, interface type. Can be 'USB', 'USB3' or 'GB' (default for fiber optic interface)
zBUS = TDTZBUS();

% or over USB 3.0
zBUS = TDTZBUS('INTERFACE', 'USB3');
from TDTZBUS import TDTZBUS

zb = TDTZBUS()

# or over USB 3.0
zb = TDTZBUS(interface='USB3')
zBUS = actxserver('ZBUS.x');
if zBUS.ConnectZBUS('GB') == 0
    error('Unable to connect')
end

Triggers

zBusTrigA and zBusTrigB trigger several processors simultaneously, either in one rack or across every rack.

Argument Values
rack 0 for every rack (default), or a single rack number
type 'PULSE' (default), 'HIGH' or 'LOW'
delay Delay in ms before the trigger, minimum 2 ms per rack

Confirming a trigger fired

From microcode v57 onward these calls return 0 even when the trigger fired correctly, so the wrapper does not report the return value. To confirm a trigger, link the zTrig output to a digital output on the device, or to a parameter tag you can read back.

To generate a single sample pulse, put an EdgeDetect after the zTrig component in your circuit.

zBUS.trigA;                  % pulse trigger A on every rack
zBUS.trigA(1);               % pulse trigger A on rack 1 only
zBUS.trigA(1, 'HIGH');       % hold rack 1 high
zBUS.trigA(1, 'LOW');        % and back low
zBUS.trigB(0, 'PULSE', 10);  % trigger B, every rack, 10 ms delay
zb.trigA()                   # pulse trigger A on every rack
zb.trigA(1)                  # pulse trigger A on rack 1 only
zb.trigA(1, 'HIGH')          # hold rack 1 high
zb.trigA(1, 'LOW')           # and back low
zb.trigB(0, 'PULSE', 10)     # trigger B, every rack, 10 ms delay
% 0 = pulse, 1 = high, 2 = low
zBUS.zBusTrigA(0, 0, 2);
zBUS.zBusTrigA(1, 0, 2);
zBUS.zBusTrigA(1, 1, 2);
zBUS.zBusTrigA(1, 2, 2);
zBUS.zBusTrigB(0, 0, 10);

Flushing and Resetting a Rack

flush clears the I/O lines to remove bad data from the buffers. reset resets the rack's logical connection to the computer, clearing data lines and restoring device connections. Both default to rack 1.

zBUS.flush(1);
zBUS.reset(1);
zb.flush(1)
zb.reset(1)
zBUS.FlushIO(1);
zBUS.HardwareReset(1);   % returns 0 on success

Device Address and Version

Both take a device name and an optional device number (default 1). The wrapper maps the name to the numeric device ID the control expects.

addr returns 0 if there is no such device. Otherwise even numbers are position 1 of a rack and odd numbers position 2: 2 = rack 1 position 1, 3 = rack 1 position 2, 4 = rack 2 position 1.

version returns 0 if there is no such device, otherwise the microcode version.

address = zBUS.addr('PA5');        % address of PA5 #1
version = zBUS.version('RZ6', 2);  % microcode version of RZ6 #2

if zBUS.version('RP2') < 50
    disp('Update your microcode to run with this ActiveX')
end
address = zb.addr('PA5')           # address of PA5 #1
version = zb.version('RZ6', 2)     # microcode version of RZ6 #2

if zb.version('RP2') < 50:
    print('Update your microcode to run with this ActiveX')
% the raw control takes numeric device IDs
address = zBUS.GetDeviceAddr(33, 1);       % 33 = PA5
version = zBUS.GetDeviceVersion(54, 2);    % 54 = RZ6

if zBUS.GetDeviceVersion(35, 1) < 50       % 35 = RP2
    disp('Update your microcode to run with this ActiveX')
end

Recognised device names, and the IDs they map to:

PA5 RP2 RL2 RA16 RV8 RX5 RX6 RX7 RX8 RZ2 RZ5 RZ6
33 35 36 37 38 45 46 47 48 50 53 54

Synchronising Rack Clocks

sync minimises drift between racks. The first rack listed is the master and the rest take their clock from it. A raw bitmask is also accepted.

Warning

This only works with the UB1/UZ4 USB 1.1 interfaces and always returns 0 on any other interface type. Connect the Sync lines with short BNC cables and T-connectors to minimise noise.

zBUS.sync([1 3]);   % rack 1 is master, rack 3 follows
zBUS.sync(5);       % the same thing as a bitmask
zb.sync([1, 3])     # rack 1 is master, rack 3 follows
zb.sync(5)          # the same thing as a bitmask
zBUS.zBusSync(5);   % bitmask only

Checking for Errors

Returns the last error string, or an empty string if there was none. Note that an unsuccessful return is not always a zBUS error: asking for a device that does not exist legitimately returns 0.

if zBUS.version('PA5') == 0
    disp(zBUS.error);
end
if zb.version('PA5') == 0:
    print(zb.error())

Examples Using TDTZBUS

You can find examples installed with ActiveX in:

C:\TDT\ActiveX\ActXExamples\Matlab
C:\TDT\ActiveX\ActXExamples\py

or you can download them in the ActiveX Controls example zip.

Report what is on the bus, then toggle trigger A:

import time
from TDTZBUS import TDTZBUS

zb = TDTZBUS()

for device in ('RZ2', 'RZ5', 'RZ6', 'RP2', 'RX6', 'RX8'):
    version = zb.version(device)
    if version:
        print('{0} #1 at address {1}, microcode v{2}'.format(
            device, zb.addr(device), version))

for _ in range(5):
    zb.trigA(0, 'HIGH')
    time.sleep(2)
    zb.trigA(0, 'LOW')
    time.sleep(2)
zBUS = TDTZBUS();

devices = {'RZ2', 'RZ5', 'RZ6', 'RP2', 'RX6', 'RX8'};
for i = 1:numel(devices)
    version = zBUS.version(devices{i});
    if version > 0
        fprintf('%s #1 at address %d, microcode v%d\n', ...
            devices{i}, zBUS.addr(devices{i}), version);
    end
end

for i = 1:5
    zBUS.trigA(0, 'HIGH');
    pause(2);
    zBUS.trigA(0, 'LOW');
    pause(2);
end