Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
162 changes: 162 additions & 0 deletions docs/LIFU_Interface_api.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,162 @@
**API Documentation** for the High-Level LIFU interface `LIFUInterface` based on
the contents of `LIFUInterface.py`, `LIFUHVController.py`, and
`LIFUTXDevice.py`.

---

# `LIFUInterface` API Documentation

The `LIFUInterface` class provides a high-level interface for managing the LIFU
system, including the **TX transmitter module** and the **high voltage (HV)
controller**. It encapsulates all communication and configuration for loading
ultrasound solutions, performing hardware checks, and controlling sonication
operations.

---

## Initialization

```python
interface = LIFUInterface()
tx_connected, hv_connected = interface.is_device_connected()

if not tx_connected:
print("TX device not connected. Attempting to turn on 12V...")
interface.hvcontroller.turn_12v_on()

# Give time for the TX device to power up and enumerate over USB
time.sleep(2)

# Cleanup and recreate interface to reinitialize USB devices
interface.stop_monitoring()
del interface
time.sleep(1) # Short delay before recreating

print("Reinitializing LIFU interface after powering 12V...")
interface = LIFUInterface()

# Re-check connection
tx_connected, hv_connected = interface.is_device_connected()

if tx_connected and hv_connected:
print("✅ LIFU Device fully connected.")
else:
print("❌ LIFU Device NOT fully connected.")
print(f" TX Connected: {tx_connected}")
print(f" HV Connected: {hv_connected}")
sys.exit(1)
```

---

## Core Components

- `txdevice`: Instance of `TxDevice` that controls the transmitter module.
- `hvcontroller`: Instance of `HVController` to control high voltage behavior.
- `signal_connect`, `signal_disconnect`, `signal_data_received`: Signals emitted
by the UART layer (if async mode is enabled).

---

## Key Methods

### Device Monitoring

| Method | Description |
| --------------------------------------- | ------------------------------------------------------- |
| `start_monitoring(interval: int = 1)` | Start asynchronous monitoring of USB connection status. |
| `stop_monitoring()` | Stop USB device monitoring. |
| `is_device_connected() -> (bool, bool)` | Returns a tuple `(tx_connected, hv_connected)`. |

---

### Solution Management

| Method | Description |
| ----------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------- |
| `set_solution(solution, profile_index=1, profile_increment=True, trigger_mode="sequence", turn_hv_on=True)` | Load and apply a full ultrasound solution to both TX and HV. |
| `check_solution(solution)` | Validate the provided solution against voltage and safety limits. |
| `get_max_voltage(solution)` | Return the safe maximum voltage for a solution. |
| `get_max_voltage_table()` | Return a Pandas DataFrame showing max voltage per duty cycle and sequence duration. |
| `get_sequence_duty_cycle(solution)` | Compute the duty cycle from the sequence config. |
| `get_sequence_duration(solution)` | Compute the total sequence duration from the solution config. |

---

### Sonication Control

| Method | Description |
| -------------------- | ------------------------------------------------- |
| `start_sonication()` | Powers on HV and starts the pulse trigger for TX. |
| `stop_sonication()` | Stops TX trigger and powers down HV. |
| `set_status(status)` | Set the current system status enum. |
| `get_status()` | Retrieve current internal status enum. |

---

### Context Manager Support

```python
with LIFUInterface() as interface:
tx_connected, hv_connected = interface.is_device_connected()
...
```

---

## Status Enum

The `LIFUInterfaceStatus` enum provides internal state tracking:

| Status Constant | Meaning |
| -------------------- | ----------------------- |
| `STATUS_COMMS_ERROR` | Communication failure |
| `STATUS_SYS_OFF` | System is off |
| `STATUS_SYS_POWERUP` | System is powering on |
| `STATUS_SYS_ON` | System is on |
| `STATUS_PROGRAMMING` | Programming in progress |
| `STATUS_READY` | System ready |
| `STATUS_NOT_READY` | System not ready |
| `STATUS_RUNNING` | Sonication running |
| `STATUS_FINISHED` | Sonication finished |
| `STATUS_ERROR` | System in error state |

---

## Example: Load and Trigger

```python
from openlifu.plan.solution import Solution

solution = Solution(
name="Test",
voltage=40,
pulse={"frequency": 2e6, "duration": 2e-6},
delays=[0] * 32,
apodizations=[1] * 32,
sequence={
"pulse_interval": 0.01,
"pulse_count": 1,
"pulse_train_interval": 0.0,
"pulse_train_count": 1,
},
)

interface.set_solution(solution)
interface.start_sonication()
time.sleep(1)
interface.stop_sonication()
```

---

## Notes

- The TX and HV devices are initialized independently using their respective USB
VID/PIDs.
- If devices are disconnected, `turn_12v_on()` can be used to power the TX
device before retrying connection.
- Use `check_solution()` to verify safety constraints before applying any
configuration.
- `Solution` objects can be converted to `dict` automatically by
`LIFUInterface`.
30 changes: 20 additions & 10 deletions docs/hv_controller_api.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
## **API Documentation** for the High Voltage Controller

# HVController API Documentation

The `HVController` class provides an interface to control and monitor a
Expand All @@ -13,6 +15,7 @@ from openlifu.io.LIFUUart import LIFUUart

interface = LIFUInterface(TX_test_mode=False)
tx_connected, hv_connected = interface.is_device_connected()

if tx_connected and hv_connected:
print("LIFU Device Fully connected.")
else:
Expand All @@ -36,8 +39,10 @@ if not hv_connected:
| `get_version()` | Returns firmware version as `vX.Y.Z` |
| `get_hardware_id()` | Returns the 16-byte hardware ID as a hex string |
| `echo(data: bytes)` | Echoes back sent data, useful for testing |
| `toggle_led()` | Toggles onboard LED |
| `soft_reset()` | Sends a soft reset to the device |
| `enter_dfu()` | Put the device into DFU mode |
| `enter_dfu()` | Puts the device into DFU (firmware update) mode |
| `close()` | Disconnects UART if connected |

---

Expand Down Expand Up @@ -90,25 +95,30 @@ if not hv_connected:

### Advanced Control

| Method | Description |
| ------------------------------ | ----------------------------------------- |
| `set_dacs(hvp, hvm, hrp, hrm)` | Sets DAC outputs for high voltage control |
| Method | Description |
| ------------------------------ | ------------------------------------------------------ |
| `set_dacs(hvp, hvm, hrp, hrm)` | Sets DAC outputs (0–4095) for fine voltage calibration |

---

## Notes

- Most methods raise `ValueError` if UART is not connected.
- All operations clear the UART buffer after use.
- Demo mode behavior returns mocked values.
- Demo mode returns default values without sending real commands.
- All commands clear the UART buffer after execution.

---

## Example

```python
interface.hvcontroller.turn_12v_on()
interface.hvcontroller.set_voltage(60.0)
print(f"Output Voltage: {interface.hvcontroller.get_voltage()} V")
interface.hvcontroller.turn_hv_on()
hv = interface.hvcontroller

hv.turn_12v_on()
hv.set_voltage(60.0)
print(f"Output Voltage: {hv.get_voltage()} V")
hv.turn_hv_on()
hv.set_rgb_led(2) # Set LED to BLUE
fan_speed = hv.get_fan_speed(0)
print(f"Bottom fan is running at {fan_speed}%")
```
103 changes: 53 additions & 50 deletions docs/tx_device_api.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
**API Documentation** for the Transmitter Device Controller

Comment thread
georgevigelette marked this conversation as resolved.
---

# TxDevice API Documentation

The `TxDevice` class provides a high-level interface for communicating with and
Expand All @@ -9,15 +13,11 @@ backend.
## Initialization

```python
from openlifu.io.LIFUHVController import HVController
from openlifu.io.LIFUUart import LIFUUart
from openlifu.io.LIFUTXDevice import TxDevice
from openlifu.io.LIFUInterface import LIFUInterface

interface = LIFUInterface(TX_test_mode=False)
tx_connected, hv_connected = interface.is_device_connected()
if tx_connected and hv_connected:
print("LIFU Device Fully connected.")
else:
print(f"LIFU Device NOT Fully Connected. TX: {tx_connected}, HV: {hv_connected}")

if not tx_connected:
print("TX Device not connected.")
Expand All @@ -35,91 +35,94 @@ if not tx_connected:
| `is_connected()` | Check if the TX device is connected |
| `ping()` | Send a ping command to check connectivity |
| `get_version()` | Get the firmware version (e.g., `v0.1.1`) |
| `echo(data: bytes)` | Send and receive echo data to verify communication |
| `toggle_led()` | Toggle the device onboard LED |
| `get_hardware_id()` | Return the 16-byte hardware ID in hex format |
| `soft_reset()` | Perform a software reset on the device |
| `echo(data: bytes)` | Send and receive echo data to verify communication |
| `toggle_led()` | Toggle the onboard status LED |
| `soft_reset()` | Perform a software reset on the TX device |
| `enter_dfu()` | Put the device into DFU mode |
| `close()` | Close the UART connection |

---

### Trigger Configuration

| Method | Description |
| ------------------------------------ | ------------------------------------------- |
| `set_trigger(...)` | Configure triggering with manual parameters |
| `set_trigger_json(data: dict)` | Set trigger via JSON dictionary |
| `get_trigger()` | Return current trigger config as a dict |
| `get_trigger_json()` | Retrieve raw JSON trigger data |
| `start_trigger()` / `stop_trigger()` | Begin or halt triggering |
| Method | Description |
| ------------------------------------ | ------------------------------------------ |
| `set_trigger(...)` | Configure trigger with parameters directly |
| `set_trigger_json(data: dict)` | Set trigger using JSON config |
| `get_trigger()` | Return current trigger config (parsed) |
| `get_trigger_json()` | Return raw JSON config from device |
| `start_trigger()` / `stop_trigger()` | Begin or halt the trigger sequence |

---

### Register Operations

| Method | Description |
| --------------------------------------------- | -------------------------------- |
| `write_register(identifier, addr, value)` | Write to a single register |
| `write_register_verify(addr, value)` | Write and verify a register |
| `read_register(addr)` | Read a register value |
| `write_block(identifier, start_addr, values)` | Write a block of register values |
| `write_block_verify(start_addr, values)` | Verified block write |
| Method | Description |
| --------------------------------------------- | ------------------------------------------- |
| `read_register(addr)` | Read a 16-bit register value |
| `write_register(identifier, addr, value)` | Write a value to a specific register |
| `write_register_verify(addr, value)` | Write and verify value to a register |
| `write_block(identifier, start_addr, values)` | Write a block of register values to a chip |
| `write_block_verify(start_addr, values)` | Write and verify a block of register values |

---

### Device Setup
### Device Setup & Control

| Method | Description |
| ---------------------------------------- | ----------------------------------------- |
| `enum_tx7332_devices(num)` | Scan for TX7332 devices |
| `demo_tx7332(identifier)` | Set test waveform to TX7332 |
| `apply_all_registers()` | Apply all configured profiles to hardware |
| `write_ti_config_to_tx_device(path, id)` | Load and apply config from TI text file |
| `print` | Print TX interface info |
| Method | Description |
| ---------------------------------------- | ---------------------------------------------- |
| `enum_tx7332_devices(num)` | Enumerate and initialize TX7332 devices |
| `demo_tx7332(identifier)` | Set demo waveform to a TX7332 chip |
| `apply_all_registers()` | Push all defined register sets to hardware |
| `write_ti_config_to_tx_device(path, id)` | Load TI register config from `.txt` and apply |
| `print()` | Print internal TX state (overridden `__str__`) |

---

### Pulse/Delay Profiles

| Method | Description |
| ---------------------------------------------- | ----------------------------------- |
| `set_solution(pulse, delays, apods, seq, ...)` | Apply full beamforming config |
| `add_pulse_profile(profile)` | Add pulse shape settings |
| `add_delay_profile(profile)` | Add delay+apodization configuration |
| Method | Description |
| ---------------------------------------------- | ------------------------------------------ |
| `set_solution(pulse, delays, apods, seq, ...)` | Apply full beamforming config and sequence |
| `add_pulse_profile(profile)` | Add or replace pulse waveform config |
| `add_delay_profile(profile)` | Add or replace delay + apodization profile |

---

## Data Classes

- `Tx7332PulseProfile`: Defines frequency, cycles, duty cycle, inversion, etc.
- `Tx7332DelayProfile`: Defines delays and apodization for each channel
- `TxDeviceRegisters`: Holds and manages TX chip register blocks per transmitter
- `Tx7332PulseProfile`: Defines TX waveform: frequency, duration, duty cycle,
inversion, etc.
- `Tx7332DelayProfile`: Defines delay + apodization per channel (32 channels
supported)
- `TxDeviceRegisters`: Holds per-chip register maps and manages write blocks

---

## Notes

- Each register block is managed per TX chip and may need verification.
- Profiles assume 32-channel TX chip configurations.
- Delay units are in seconds, apodization values from 0–1.
- Trigger configuration must be set before `start_trigger()`.

---

## Example

```python
pulse = {"frequency": 3e6, "duration": 2e-6}
delays = [0] * 32
apods = [1] * 32
delays = [0.0] * 32
apods = [1.0] * 32
sequence = {
"pulse_interval": 0.01,
"pulse_count": 1,
"pulse_train_interval": 0.0,
"pulse_train_count": 1,
}

# Apply configuration
if tx.is_connected():
tx.set_solution(pulse, delays, apods, sequence)
tx.start_trigger()
```

---

## Notes

- Profile management assumes 32 transmit channels per chip.
- Delay units default to seconds unless specified.
- Device must be enumerated before applying register values.
Loading