Skip to main content

Migrating from the hardware API

If you have code against the IHWAPI (sp209api_*, sp259api_*, sp1000gapi_*), this page maps it onto the SDK.

Nothing forces you to move: the hardware API documentation stays online and existing integrations keep working. But the IHWAPI is frozen: it opens a device and hands you transitions, and that is all. Decoders, triggers, measurements, pattern generation, export and remote access are in the SDK only and will not be back-ported.

The workflow, side by side​

The IHWAPI's five steps, and what replaces them.

1. Create a handle and list devices​

The IHWAPI needs a handle per device family, and a device list you must free.

sp259api_handle handle;
sp259api_create_new_handle(&handle, SP259_MODEL);
sp259api_create_device_list(handle);
uint8_t count = sp259api_get_devices_count(handle);
device_descriptor_t descriptor;
sp259api_get_device_descriptor(handle, 0, &descriptor);

The SDK has one call, and the same one for every device family:

with ScanaStudio.connect() as server:
for device in server.devices():
print(device.key, device.name, device.serial)

2. Open a device​

sp259api_device_open(handle, descriptor.serial_number);
/* or */
sp259api_device_open_first(handle);

Becomes opening a workspace on that device:

workspace = server.create("hw:SP259-000123")

3. Configure and start a capture​

The IHWAPI fills a settings struct and a trigger description, then launches:

sp259api_settings_t settings;
sp259api_trigger_description_t trigger;
/* fill both in */
sp259api_launch_new_capture_simple_trigger(handle, &settings, &trigger);

while (!sp259api_get_capture_done_flag(handle)) { /* poll */ }

The SDK takes the settings as arguments and waits for you:

last = workspace.capture.run(
samples=1_000_000,
sample_rate=25_000_000,
trigger=Trigger.rising(channel=0, position=0.1),
)

No polling loop. run() waits; start() returns at once and wait() blocks later. The flags (get_capture_done_flag, get_ready_flag, get_triggered_flag, get_config_done_flag) are replaced by capture.state, capture.running and capture.trigger_count.

4. Retrieve the samples​

The IHWAPI keeps a per-channel iterator you reset and walk:

sp259api_trs_reset(handle, channel);
while (sp259api_trs_is_not_last(handle, channel)) {
sp259api_trs_t transition = sp259api_trs_get_next(handle, channel);
/* transition.sample_index, transition.value */
}

The SDK gives you the window you ask for, and pages it for you:

for edge in workspace.data.transitions(channel=0):
edge.sample
edge.level

trs_before and trs_get_previous become level_at, next_edge and previous_edge. See Reading captured data.

The encoding is the same

Both APIs store transitions rather than samples. In both, the first record of a window is the level in force where the window starts, so its index may precede the start you asked for. If your IHWAPI code already handles that, it needs no change.

5. Close​

sp259api_device_close(handle);
sp259api_free_device_list(handle);
sp259api_free(handle);

Becomes:

workspace.close() # the context manager closes the connection

create, open and attach​

There are three ways to get a workspace:

CallGives you
server.create(device)A new workspace on a device
server.open(path)A workspace from a .scana file
server.attach(id)One already running on the server
create and open both take a string

If you have pre-release code written against an earlier SDK, where open(device) created a workspace on a device, that call still compiles and now tries to load a file named se254. The failure is a file-not-found at runtime, or silence if a file of that name happens to exist. Search your code for open( and decide, per call, whether it should be create.

The C library has the same shape: ss_server_create(server, "se254") for a device, ss_server_open(server, "/data/run.scana") for a file.

Concept mapping​

IHWAPISDK
A device handle (sp259api_handle)A workspace, but see the note below
One API per family (sp209api_*, sp259api_*, sp1000gapi_*)One API for all of them
sp259api_create_device_list + get_devices_count + get_device_descriptordevices()
device_open / device_open_firstserver.create("hw:<serial>")
launch_new_capture_simple_triggercapture.start() / capture.run()
get_capture_done_flag, get_ready_flag, get_triggered_flagcapture.state, capture.running, capture.trigger_count
request_abortcapture.stop()
get_available_samplescapture.last_sample
get_trigger_positionThe position you passed to the trigger builder
trs_reset + trs_get_next + trs_is_not_lastdata.transitions(channel)
trs_before, trs_get_previousdata.level_at, data.previous_edge
get_last_errorRaised exceptions, or ss_last_error() in C
get_fpga_version, get_hw_versionworkspace.device_info()
device_close, free_device_list, freeworkspace.close() and closing the client
A workspace is not a handle

An IHWAPI handle lives in your process and dies with it. A workspace lives on the server and does not. Ending your program does not end a capture. That is what makes leave-and-rejoin possible, and it is also why a script that opens workspaces and never closes them leaves them running for as long as the server does.

What has no IHWAPI equivalent​

These have no IHWAPI counterpart:

Migrating incrementally​

You do not have to rewrite everything at once. The IHWAPI drives the USB device directly and the SDK drives a server, so they cannot share one device, but they can live in the same code base while you move test by test.

The usual order:

  1. Port the capture and sample reading first. It is a near-mechanical translation of the five steps above, and it is most of the code.
  2. Replace hand-written protocol parsing with a decoder.
  3. Replace hand-rolled timing arithmetic with measurements, if you want the numbers saved alongside the capture.
One device at a time

A physical device belongs to one workspace, and a workspace to one server. While the SDK's server holds a device, an IHWAPI program cannot open it, and the other way round. Migrate a bench wholesale rather than running both against the same analyser.