usbtmc-lite 0.1.2
A minimal, readable USBTMC implementation for learning and simple use cases
Requires Python: >=3.13
Keywords: instrument, instrument-control, measurement, scpi, usb, usbtmc, visa

# usbtmc-lite

Minimal USBTMC (USB Test and Measurement Class) implementation for Python.

Communicate with USBTMC-compliant instruments via USB. Lightweight design with IEEE 488.2 block data transfer support.

## Features

- Simple API for instrument communication (write/read/query)
- IEEE 488.2 block data transfer
- Status byte register access
- Keysight firmware mode unlock utility

## Installation

```bash
pip install usbtmc-lite
```

### Windows

Requires libusb-1.0.dll. Download from [libusb releases](https://github.com/libusb/libusb/releases).

### Linux

```bash
sudo apt install libusb-1.0-0
```

You may need to configure udev rules:

```bash
# /etc/udev/rules.d/99-usbtmc.rules
SUBSYSTEM=="usb", ATTR{idVendor}=="0957", MODE="0666"
```

## Quick Start

```python
from usbtmc_lite import USBTMC
from usbtmc_lite.utils import find_usbtmc_devices, get_device, get_backend

backend = get_backend("./libusb-1.0.dll")  # Linux/macOS: get_backend()
devices = find_usbtmc_devices(backend=backend)
device = get_device(devices, vendor_id=0x0957, product_id=0x0618)

with USBTMC() as usbtmc:
    usbtmc.open(device)
    print(usbtmc.query("*IDN?"))
```

## Examples

### Basic Communication

```python
from usbtmc_lite import USBTMC
from usbtmc_lite.utils import find_usbtmc_devices, get_device, get_backend

backend = get_backend("./libusb-1.0.dll")
devices = find_usbtmc_devices(backend=backend)
device = get_device(devices, vendor_id=0x0957, product_id=0x0618)

with USBTMC() as usbtmc:
    usbtmc.open(device)
    usbtmc.write("*RST")
    print(usbtmc.query("*IDN?"))
```

### Multiple Identical Devices

```python
from usbtmc_lite import USBTMC
from usbtmc_lite.utils import find_usbtmc_devices, get_device, get_backend

backend = get_backend()
devices = find_usbtmc_devices(backend=backend)

# Use serial number to distinguish
device = get_device(devices, 0x0957, 0x0618, serial_number="MY12345678")

with USBTMC() as usbtmc:
    usbtmc.open(device)
    print(usbtmc.query("*IDN?"))
```

### Block Data Transfer

```python
from usbtmc_lite import USBTMC
from usbtmc_lite.utils import find_usbtmc_devices, get_device, get_backend

backend = get_backend()
devices = find_usbtmc_devices(backend=backend)
device = get_device(devices, 0x0957, 0x0618)

with USBTMC() as usbtmc:
    usbtmc.open(device)
    
    # Upload waveform data
    usbtmc.write_block_data(":DATA:UPLOAD", waveform_bytes)
    
    # Download waveform data
    usbtmc.write(":DATA:DOWNLOAD?")
    data = usbtmc.read_block_data(timeout=10000)
```

### Unlock Keysight Firmware Mode

Some Keysight USB modular instruments power on in firmware update mode:

```python
from usbtmc_lite.utils import (
    get_backend,
    find_firmware_mode_devices,
    unlock_keysight_device,
    find_usbtmc_devices,
)
import time

backend = get_backend("./libusb-1.0.dll")

fw_devices = find_firmware_mode_devices(backend=backend)
if fw_devices:
    print(f"Found {len(fw_devices)} device(s) in firmware mode")
    unlock_keysight_device(fw_devices[0])
    time.sleep(3)  # Wait for USB re-enumeration

devices = find_usbtmc_devices(backend=backend)
```

## API Reference

### USBTMC

| Method | Description |
|--------|-------------|
| `open(device)` | Open connection to USB device |
| `close()` | Close connection |
| `write(text)` | Send text command |
| `write_bytes(data)` | Send raw bytes |
| `read(length, timeout)` | Read text response |
| `read_bytes(length, timeout)` | Read raw bytes |
| `query(text, timeout)` | Write and read |
| `write_block_data(command, data)` | Write IEEE 488.2 block data |
| `read_block_data(timeout)` | Read IEEE 488.2 block data |
| `clear()` | Clear device buffers |
| `read_status_byte_register()` | Read IEEE 488.2 status byte |

| Property | Description |
|----------|-------------|
| `opened` | True if device is connected |
| `device` | Underlying PyUSB device object |
| `terminator_write` | Write terminator (default: `\n`) |
| `terminator_read` | Read terminator (default: `\n`) |

### Utilities

| Function | Description |
|----------|-------------|
| `get_backend(dll_path=None)` | Get libusb backend |
| `find_usbtmc_devices(backend, vendor_id, product_id)` | Find USBTMC devices |
| `get_device(devices, vendor_id, product_id, serial_number)` | Get specific device |
| `find_firmware_mode_devices(backend, vendor_id)` | Find devices in firmware update mode |
| `unlock_keysight_device(device)` | Switch Keysight device to USBTMC mode |

## License

Apache License 2.0