Skip to content

Commit 4573b20

Browse files
Update LIFU hardware documentation (#359)
* Update API documentation * Update LIFU_Interface_api.md * Fix TV and HV docs * Update High Level Interface Doc
1 parent 7017594 commit 4573b20

3 files changed

Lines changed: 235 additions & 60 deletions

File tree

docs/LIFU_Interface_api.md

Lines changed: 162 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,162 @@
1+
**API Documentation** for the High-Level LIFU interface `LIFUInterface` based on
2+
the contents of `LIFUInterface.py`, `LIFUHVController.py`, and
3+
`LIFUTXDevice.py`.
4+
5+
---
6+
7+
# `LIFUInterface` API Documentation
8+
9+
The `LIFUInterface` class provides a high-level interface for managing the LIFU
10+
system, including the **TX transmitter module** and the **high voltage (HV)
11+
controller**. It encapsulates all communication and configuration for loading
12+
ultrasound solutions, performing hardware checks, and controlling sonication
13+
operations.
14+
15+
---
16+
17+
## Initialization
18+
19+
```python
20+
interface = LIFUInterface()
21+
tx_connected, hv_connected = interface.is_device_connected()
22+
23+
if not tx_connected:
24+
print("TX device not connected. Attempting to turn on 12V...")
25+
interface.hvcontroller.turn_12v_on()
26+
27+
# Give time for the TX device to power up and enumerate over USB
28+
time.sleep(2)
29+
30+
# Cleanup and recreate interface to reinitialize USB devices
31+
interface.stop_monitoring()
32+
del interface
33+
time.sleep(1) # Short delay before recreating
34+
35+
print("Reinitializing LIFU interface after powering 12V...")
36+
interface = LIFUInterface()
37+
38+
# Re-check connection
39+
tx_connected, hv_connected = interface.is_device_connected()
40+
41+
if tx_connected and hv_connected:
42+
print("✅ LIFU Device fully connected.")
43+
else:
44+
print("❌ LIFU Device NOT fully connected.")
45+
print(f" TX Connected: {tx_connected}")
46+
print(f" HV Connected: {hv_connected}")
47+
sys.exit(1)
48+
```
49+
50+
---
51+
52+
## Core Components
53+
54+
- `txdevice`: Instance of `TxDevice` that controls the transmitter module.
55+
- `hvcontroller`: Instance of `HVController` to control high voltage behavior.
56+
- `signal_connect`, `signal_disconnect`, `signal_data_received`: Signals emitted
57+
by the UART layer (if async mode is enabled).
58+
59+
---
60+
61+
## Key Methods
62+
63+
### Device Monitoring
64+
65+
| Method | Description |
66+
| --------------------------------------- | ------------------------------------------------------- |
67+
| `start_monitoring(interval: int = 1)` | Start asynchronous monitoring of USB connection status. |
68+
| `stop_monitoring()` | Stop USB device monitoring. |
69+
| `is_device_connected() -> (bool, bool)` | Returns a tuple `(tx_connected, hv_connected)`. |
70+
71+
---
72+
73+
### Solution Management
74+
75+
| Method | Description |
76+
| ----------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------- |
77+
| `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. |
78+
| `check_solution(solution)` | Validate the provided solution against voltage and safety limits. |
79+
| `get_max_voltage(solution)` | Return the safe maximum voltage for a solution. |
80+
| `get_max_voltage_table()` | Return a Pandas DataFrame showing max voltage per duty cycle and sequence duration. |
81+
| `get_sequence_duty_cycle(solution)` | Compute the duty cycle from the sequence config. |
82+
| `get_sequence_duration(solution)` | Compute the total sequence duration from the solution config. |
83+
84+
---
85+
86+
### Sonication Control
87+
88+
| Method | Description |
89+
| -------------------- | ------------------------------------------------- |
90+
| `start_sonication()` | Powers on HV and starts the pulse trigger for TX. |
91+
| `stop_sonication()` | Stops TX trigger and powers down HV. |
92+
| `set_status(status)` | Set the current system status enum. |
93+
| `get_status()` | Retrieve current internal status enum. |
94+
95+
---
96+
97+
### Context Manager Support
98+
99+
```python
100+
with LIFUInterface() as interface:
101+
tx_connected, hv_connected = interface.is_device_connected()
102+
...
103+
```
104+
105+
---
106+
107+
## Status Enum
108+
109+
The `LIFUInterfaceStatus` enum provides internal state tracking:
110+
111+
| Status Constant | Meaning |
112+
| -------------------- | ----------------------- |
113+
| `STATUS_COMMS_ERROR` | Communication failure |
114+
| `STATUS_SYS_OFF` | System is off |
115+
| `STATUS_SYS_POWERUP` | System is powering on |
116+
| `STATUS_SYS_ON` | System is on |
117+
| `STATUS_PROGRAMMING` | Programming in progress |
118+
| `STATUS_READY` | System ready |
119+
| `STATUS_NOT_READY` | System not ready |
120+
| `STATUS_RUNNING` | Sonication running |
121+
| `STATUS_FINISHED` | Sonication finished |
122+
| `STATUS_ERROR` | System in error state |
123+
124+
---
125+
126+
## Example: Load and Trigger
127+
128+
```python
129+
from openlifu.plan.solution import Solution
130+
131+
solution = Solution(
132+
name="Test",
133+
voltage=40,
134+
pulse={"frequency": 2e6, "duration": 2e-6},
135+
delays=[0] * 32,
136+
apodizations=[1] * 32,
137+
sequence={
138+
"pulse_interval": 0.01,
139+
"pulse_count": 1,
140+
"pulse_train_interval": 0.0,
141+
"pulse_train_count": 1,
142+
},
143+
)
144+
145+
interface.set_solution(solution)
146+
interface.start_sonication()
147+
time.sleep(1)
148+
interface.stop_sonication()
149+
```
150+
151+
---
152+
153+
## Notes
154+
155+
- The TX and HV devices are initialized independently using their respective USB
156+
VID/PIDs.
157+
- If devices are disconnected, `turn_12v_on()` can be used to power the TX
158+
device before retrying connection.
159+
- Use `check_solution()` to verify safety constraints before applying any
160+
configuration.
161+
- `Solution` objects can be converted to `dict` automatically by
162+
`LIFUInterface`.

docs/hv_controller_api.md

Lines changed: 20 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
## **API Documentation** for the High Voltage Controller
2+
13
# HVController API Documentation
24

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

1416
interface = LIFUInterface(TX_test_mode=False)
1517
tx_connected, hv_connected = interface.is_device_connected()
18+
1619
if tx_connected and hv_connected:
1720
print("LIFU Device Fully connected.")
1821
else:
@@ -36,8 +39,10 @@ if not hv_connected:
3639
| `get_version()` | Returns firmware version as `vX.Y.Z` |
3740
| `get_hardware_id()` | Returns the 16-byte hardware ID as a hex string |
3841
| `echo(data: bytes)` | Echoes back sent data, useful for testing |
42+
| `toggle_led()` | Toggles onboard LED |
3943
| `soft_reset()` | Sends a soft reset to the device |
40-
| `enter_dfu()` | Put the device into DFU mode |
44+
| `enter_dfu()` | Puts the device into DFU (firmware update) mode |
45+
| `close()` | Disconnects UART if connected |
4146

4247
---
4348

@@ -90,25 +95,30 @@ if not hv_connected:
9095

9196
### Advanced Control
9297

93-
| Method | Description |
94-
| ------------------------------ | ----------------------------------------- |
95-
| `set_dacs(hvp, hvm, hrp, hrm)` | Sets DAC outputs for high voltage control |
98+
| Method | Description |
99+
| ------------------------------ | ------------------------------------------------------ |
100+
| `set_dacs(hvp, hvm, hrp, hrm)` | Sets DAC outputs (0–4095) for fine voltage calibration |
96101

97102
---
98103

99104
## Notes
100105

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

105110
---
106111

107112
## Example
108113

109114
```python
110-
interface.hvcontroller.turn_12v_on()
111-
interface.hvcontroller.set_voltage(60.0)
112-
print(f"Output Voltage: {interface.hvcontroller.get_voltage()} V")
113-
interface.hvcontroller.turn_hv_on()
115+
hv = interface.hvcontroller
116+
117+
hv.turn_12v_on()
118+
hv.set_voltage(60.0)
119+
print(f"Output Voltage: {hv.get_voltage()} V")
120+
hv.turn_hv_on()
121+
hv.set_rgb_led(2) # Set LED to BLUE
122+
fan_speed = hv.get_fan_speed(0)
123+
print(f"Bottom fan is running at {fan_speed}%")
114124
```

docs/tx_device_api.md

Lines changed: 53 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
**API Documentation** for the Transmitter Device Controller
2+
3+
---
4+
15
# TxDevice API Documentation
26

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

1115
```python
12-
from openlifu.io.LIFUHVController import HVController
13-
from openlifu.io.LIFUUart import LIFUUart
16+
from openlifu.io.LIFUTXDevice import TxDevice
17+
from openlifu.io.LIFUInterface import LIFUInterface
1418

1519
interface = LIFUInterface(TX_test_mode=False)
1620
tx_connected, hv_connected = interface.is_device_connected()
17-
if tx_connected and hv_connected:
18-
print("LIFU Device Fully connected.")
19-
else:
20-
print(f"LIFU Device NOT Fully Connected. TX: {tx_connected}, HV: {hv_connected}")
2121

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

4445
---
4546

4647
### Trigger Configuration
4748

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

5657
---
5758

5859
### Register Operations
5960

60-
| Method | Description |
61-
| --------------------------------------------- | -------------------------------- |
62-
| `write_register(identifier, addr, value)` | Write to a single register |
63-
| `write_register_verify(addr, value)` | Write and verify a register |
64-
| `read_register(addr)` | Read a register value |
65-
| `write_block(identifier, start_addr, values)` | Write a block of register values |
66-
| `write_block_verify(start_addr, values)` | Verified block write |
61+
| Method | Description |
62+
| --------------------------------------------- | ------------------------------------------- |
63+
| `read_register(addr)` | Read a 16-bit register value |
64+
| `write_register(identifier, addr, value)` | Write a value to a specific register |
65+
| `write_register_verify(addr, value)` | Write and verify value to a register |
66+
| `write_block(identifier, start_addr, values)` | Write a block of register values to a chip |
67+
| `write_block_verify(start_addr, values)` | Write and verify a block of register values |
6768

6869
---
6970

70-
### Device Setup
71+
### Device Setup & Control
7172

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

8081
---
8182

8283
### Pulse/Delay Profiles
8384

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

9091
---
9192

9293
## Data Classes
9394

94-
- `Tx7332PulseProfile`: Defines frequency, cycles, duty cycle, inversion, etc.
95-
- `Tx7332DelayProfile`: Defines delays and apodization for each channel
96-
- `TxDeviceRegisters`: Holds and manages TX chip register blocks per transmitter
95+
- `Tx7332PulseProfile`: Defines TX waveform: frequency, duration, duty cycle,
96+
inversion, etc.
97+
- `Tx7332DelayProfile`: Defines delay + apodization per channel (32 channels
98+
supported)
99+
- `TxDeviceRegisters`: Holds per-chip register maps and manages write blocks
100+
101+
---
102+
103+
## Notes
104+
105+
- Each register block is managed per TX chip and may need verification.
106+
- Profiles assume 32-channel TX chip configurations.
107+
- Delay units are in seconds, apodization values from 0–1.
108+
- Trigger configuration must be set before `start_trigger()`.
97109

98110
---
99111

100112
## Example
101113

102114
```python
103115
pulse = {"frequency": 3e6, "duration": 2e-6}
104-
delays = [0] * 32
105-
apods = [1] * 32
116+
delays = [0.0] * 32
117+
apods = [1.0] * 32
106118
sequence = {
107119
"pulse_interval": 0.01,
108120
"pulse_count": 1,
109121
"pulse_train_interval": 0.0,
110122
"pulse_train_count": 1,
111123
}
112124

113-
# Apply configuration
114125
if tx.is_connected():
115126
tx.set_solution(pulse, delays, apods, sequence)
116127
tx.start_trigger()
117128
```
118-
119-
---
120-
121-
## Notes
122-
123-
- Profile management assumes 32 transmit channels per chip.
124-
- Delay units default to seconds unless specified.
125-
- Device must be enumerated before applying register values.

0 commit comments

Comments
 (0)