Metadata-Version: 2.4
Name: ikalogic-scanastudio
Version: 0.2.4
Summary: Python SDK for ScanaStudio v6 logic analysers and pattern generators
Keywords: scanastudio,ikalogic,logic-analyzer,protocol-decoder,pattern-generator,instrumentation,sdk,api
Author: IKALOGIC
Author-email: IKALOGIC <contact@ikalogic.com>
License-Expression: MIT
License-File: LICENSE
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: Intended Audience :: Manufacturing
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Software Development :: Embedded Systems
Classifier: Topic :: Scientific/Engineering
Classifier: Typing :: Typed
Requires-Dist: pydantic>=2.7
Requires-Dist: websockets>=13.0
Requires-Python: >=3.10
Project-URL: Documentation, https://www.ikalogic.com/kb/scanastudio-api/
Project-URL: Homepage, https://www.ikalogic.com/logic-analyzers/
Project-URL: Repository, https://github.com/ikalogic/scanastudio-v6
Description-Content-Type: text/markdown

# ikalogic-scanastudio

Python SDK for [ScanaStudio v6](https://www.ikalogic.com/logic-analyzers/), the
software behind Ikalogic logic analysers and pattern generators.

ScanaStudio runs a server that owns the devices and speaks one WebSocket
protocol. The interface is a client of that protocol, and so is this package —
so everything you can do in the application, you can do from a script: capture,
decode, measure, generate patterns and export.

```sh
pip install ikalogic-scanastudio
```

## Capture and decode

```python
from ikalogic_scanastudio import ScanaStudio, Trigger

with ScanaStudio.connect() as server:
    workspace = server.create("se254")  # a demo device: no hardware needed

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

    i2c = workspace.decoders.add(
        "i2c.js",
        {"ch_scl": workspace.channel("I2C SCL"), "ch_sda": workspace.channel("I2C SDA")},
        wait=True,
    )
    for packet in i2c.packets():
        print(f"{workspace.capture.seconds(packet.start):.6f}s  {packet.title}: {packet.content}")

    workspace.export_csv("packets.csv", source="packets", instances=[i2c.instance_id])
```

`server.create` takes a demo key such as `se254`, or `hw:<serial>` for real
hardware; `server.devices()` lists both. `server.open` takes the path of a
`.scana` instead, and `server.attach` joins a workspace already running.

⚠️ A demo device generates pseudo-random noise, not protocol traffic. It runs
the whole path — capture, decode, measure, export — which is what makes it
useful for writing and testing a script without hardware, but a decoder run on
it finds structure by chance.

## Read the raw signal

```python
for edge in workspace.data.transitions(channel=0):
    print(edge.sample, edge.level)
```

The iterator pages for you, however long the capture. The first edge it yields
is the level in force where you started reading, so a window describes itself.

## Find out what a decoder takes

```python
for option in workspace.decoders.options("i2c.js"):
    print(option)
# ch_sda: SDA Channel (ch_selector) = None
# address_format [Advanced options]: Address display format (combo)
#     one of ['HEX', 'Binary', 'Decimal'] = 'HEX'
```

Pass those by id or by caption, as Python values — a channel number, a combo
entry by name, a flag as `True`. Anything left out keeps the script's default.

## Leave a capture running

The server owns the workspace, so disconnecting destroys nothing. Start a long
acquisition, go away, and come back to it:

```python
with ScanaStudio.connect() as server:
    workspace = server.create("hw:SP259-000123")
    workspace.capture.start(samples=2_000_000_000)
    print("running as workspace", workspace.id)

# later, from anywhere
with ScanaStudio.connect("ws://bench.local:4911") as server:
    for session in server.workspaces():
        print(session.workspace_id, session.device_name, session.state)
    workspace = server.attach(session.workspace_id)
    workspace.capture.wait()
```

⚠️ A server listening beyond loopback has **no authentication**: whoever reaches
the port has the devices.

## What is where

| | |
|---|---|
| `server.devices()`, `server.workspaces()` | what you can open, and what is already open |
| `server.capabilities(device)` | the rates, depths and thresholds it offers |
| `server.scripts` | the decoder library, which belongs to the server |
| `workspace.capture` | arming, running and waiting |
| `workspace.data` | raw edges, packets, items, hex |
| `workspace.decoders` | attaching and configuring decoders |
| `workspace.markers` | time markers |
| `workspace.measures` | measurements between two markers |
| `workspace.pattern` | the pattern generator |
| `workspace.events` | everything the server pushes |

## Versions

This SDK speaks protocol 7. `ScanaStudio.connect` refuses a server that speaks
another, since a mismatch means one of the two needs updating. The protocol
itself is documented in
[`api/schema/protocol.md`](https://github.com/ikalogic/scanastudio-v6/blob/main/api/schema/protocol.md).

MIT licensed.
