Skip to content

Commit ccfa429

Browse files
committed
docs: add full documentation site — getting started, configuration, hardware
Replace placeholder index with proper content. Add getting_started.md (install, first steps, decode, examples), configuration.md (BarcodeConfig fields, all presets table), hardware.md (Bpod inject_barcode_states, pigpio, custom hardware). Expand mkdocs.yml nav and align markdown extensions with pypulsepal. Add Ruff badge and docs link to README.
1 parent 5a643fd commit ccfa429

6 files changed

Lines changed: 297 additions & 8 deletions

File tree

README.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,11 @@
11
# TTL Barcoder
22

33
[![PyPI](https://img.shields.io/pypi/v/ttl-barcoder.svg)](https://pypi.org/project/ttl-barcoder)
4+
[![Ruff](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/v2.json)](https://github.com/astral-sh/ruff)
45

56
Generate and decode binary barcodes over TTL signals to synchronize multiple data acquisition systems.
7+
8+
**[→ Full documentation](https://murineshiftwork.github.io/ttl-barcoder)**
69
Barcodes encode a timestamp or random value as a sequence of timed HIGH/LOW pulses, transmittable over any digital output.
710

811

docs/configuration.md

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
# Configuration
2+
3+
## BarcodeConfig
4+
5+
`BarcodeConfig` is a Pydantic v2 model. All fields are validated on construction.
6+
7+
```python
8+
from ttl_barcoder.core import BarcodeConfig, TTLType, TimestampPrecision
9+
10+
config = BarcodeConfig(
11+
ttl_type=TTLType.timestamp, # or TTLType.random
12+
barcode_bits=37, # 16–64 bits
13+
timestamp_precision=TimestampPrecision.milliseconds, # s / ms / us
14+
bit_duration_ms=35.0,
15+
init_duration_ms=10.0,
16+
tolerance=0.25,
17+
)
18+
```
19+
20+
### Fields
21+
22+
| Field | Type | Default | Description |
23+
|---|---|---|---|
24+
| `ttl_type` | `TTLType` | `timestamp` | Barcode value source: `timestamp` or `random` |
25+
| `barcode_bits` | `int` | `37` | Number of data bits (16–64) |
26+
| `timestamp_precision` | `TimestampPrecision` | `milliseconds` | Time resolution for timestamp barcodes |
27+
| `bit_duration_ms` | `float` | `35.0` | Duration of each data bit in ms |
28+
| `init_duration_ms` | `float` | `10.0` | Duration of the preamble pulse in ms |
29+
| `tolerance` | `float` | `0.25` | Fractional timing tolerance for decoding (0–1) |
30+
31+
### TTLType
32+
33+
- `TTLType.timestamp` — encodes Unix time quantised to the configured precision
34+
- `TTLType.random` — draws from a numpy RNG; value is a random integer in `[0, 2^barcode_bits)`
35+
36+
### TimestampPrecision
37+
38+
- `TimestampPrecision.seconds` — 1 s resolution
39+
- `TimestampPrecision.milliseconds` — 1 ms resolution (default)
40+
- `TimestampPrecision.microseconds` — 1 µs resolution
41+
42+
## Presets
43+
44+
Presets cover common hardware setups. Load with `get_preset`:
45+
46+
```python
47+
from ttl_barcoder.core import get_preset
48+
49+
config = get_preset("conservative")
50+
barcoder = BarcodeTTL(config)
51+
```
52+
53+
| Preset | Bits | Precision | Bit duration | TX duration | Coverage |
54+
|---|---|---|---|---|---|
55+
| `default` | 37 | ms | 35 ms | ~1355 ms | 4.4 yr |
56+
| `high_speed` | 32 | ms | 25 ms | ~848 ms | 49 days |
57+
| `conservative` | 37 | ms | 50 ms | ~1940 ms | 4.4 yr |
58+
| `high_precision` | 42 | µs | 50 ms | ~2190 ms | 51 days |
59+
| `random` | 32 || 35 ms | ~1148 ms ||
60+
61+
**TX duration** = total transmission time including preamble.
62+
**Coverage** = time range before timestamp wraps (timestamp barcodes only).
63+
64+
## Choosing a preset
65+
66+
- **Default**: general-purpose; suitable for most neuroscience rigs with ~1 s alignment tolerance.
67+
- **Conservative**: slower bit rate; use when hardware timing jitter is high (>10 ms).
68+
- **High speed**: shorter total duration; use when inter-trial intervals are short.
69+
- **High precision**: microsecond timestamps; use when sub-millisecond alignment is needed and hardware supports it.
70+
- **Random**: non-temporal ID; use when you want trial identity rather than wall-clock alignment.

docs/getting_started.md

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
# Getting Started
2+
3+
## Installation
4+
5+
```bash
6+
pip install ttl-barcoder # core only
7+
pip install ttl-barcoder[bpod] # + Bpod StateMachine integration
8+
pip install ttl-barcoder[pigpio] # + Raspberry Pi GPIO via pigpio
9+
pip install ttl-barcoder[all] # all extras
10+
```
11+
12+
Or with uv:
13+
14+
```bash
15+
uv add ttl-barcoder
16+
uv add "ttl-barcoder[bpod]"
17+
```
18+
19+
## First steps
20+
21+
Generate a timestamp barcode and inspect the timing sequence:
22+
23+
```python
24+
from ttl_barcoder.core import BarcodeTTL
25+
26+
barcoder = BarcodeTTL()
27+
barcoder.prepare() # generate value and compute timing sequence
28+
sequence = barcoder.get_sequence() # [(level: bool, duration_ms: float), ...]
29+
30+
print(barcoder.value) # integer timestamp value encoded
31+
print(len(sequence)) # number of TTL transitions
32+
```
33+
34+
Each entry in `sequence` is a `(level, duration_ms)` pair: hold the output
35+
at `level` (True = HIGH, False = LOW) for `duration_ms` milliseconds, then
36+
move to the next entry.
37+
38+
## Decode from edge timestamps
39+
40+
After recording the TTL signal, recover the barcode value from the edge
41+
timestamps (in milliseconds):
42+
43+
```python
44+
from ttl_barcoder.core import BarcodeTTL, BarcodeConfig
45+
46+
config = BarcodeConfig()
47+
barcoder = BarcodeTTL(config)
48+
49+
edge_times_ms = [0.0, 10.5, 45.2, ...] # rising + falling edges in order
50+
decoded_value = barcoder.decode(edge_times_ms)
51+
print(decoded_value)
52+
```
53+
54+
## Examples
55+
56+
The `examples/` directory contains:
57+
58+
| File | Description |
59+
|---|---|
60+
| `dry_simulation.py` | Full encode → decode walkthrough, no hardware needed |
61+
| `bpod_loopback.py` | Bpod StateMachine with loopback test |
62+
| `pigpio_send.py` | Raspberry Pi GPIO transmission |
63+
64+
Run the simulation example to verify the installation:
65+
66+
```bash
67+
python examples/dry_simulation.py
68+
```
69+
70+
## Development setup
71+
72+
```bash
73+
git clone https://github.com/murineshiftwork/ttl-barcoder.git
74+
cd ttl-barcoder
75+
uv sync --extra dev
76+
uv run pre-commit install --hook-type pre-commit --hook-type commit-msg
77+
uv run pytest
78+
```

docs/hardware.md

Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
# Hardware Integration
2+
3+
## Bpod
4+
5+
The Bpod integration injects barcode timing states into a pybpodapi `StateMachine`.
6+
The barcode is transmitted as a series of BNC output states; the last injected
7+
state chains to whatever state you specify as `last_state_name`.
8+
9+
### Installation
10+
11+
```bash
12+
pip install ttl-barcoder[bpod]
13+
```
14+
15+
### Usage
16+
17+
```python
18+
from ttl_barcoder.core import BarcodeTTL
19+
from ttl_barcoder.hardware.bpod import inject_barcode_states
20+
21+
barcoder = BarcodeTTL()
22+
barcoder.prepare()
23+
24+
inject_barcode_states(
25+
sma, # pybpodapi StateMachine
26+
barcoder.get_sequence(),
27+
bnc_channel="BNC1", # Bpod BNC output channel
28+
first_state_name="barcode_start",
29+
last_state_name="next_trial", # state to enter after barcode finishes
30+
)
31+
```
32+
33+
### State naming
34+
35+
`inject_barcode_states` adds one state per barcode bit plus preamble and
36+
trailer states. The `first_state_name` is the entry point — set this as the
37+
`state_change_conditions` target from your preceding state. The sequence
38+
chains internally and exits to `last_state_name` when complete.
39+
40+
### Channel
41+
42+
Pass any BNC output channel supported by your Bpod model, e.g. `"BNC1"` or
43+
`"BNC2"`. The same channel must be wired to the recording system input.
44+
45+
---
46+
47+
## Raspberry Pi GPIO (pigpio)
48+
49+
!!! note "lgpio migration planned"
50+
The current implementation uses `pigpio`. Support for `lgpio` (compatible
51+
with Raspberry Pi 5 and newer kernels) is planned — see the
52+
[GitHub issue tracker](https://github.com/murineshiftwork/ttl-barcoder/issues).
53+
54+
### Installation
55+
56+
```bash
57+
pip install ttl-barcoder[pigpio]
58+
```
59+
60+
`pigpio` requires the pigpio daemon to be running on the Pi:
61+
62+
```bash
63+
sudo pigpiod
64+
```
65+
66+
### Usage
67+
68+
```python
69+
from ttl_barcoder.core import BarcodeTTL
70+
from ttl_barcoder.hardware.pigpio import send_barcode_sequence
71+
72+
barcoder = BarcodeTTL()
73+
barcoder.prepare()
74+
send_barcode_sequence(barcoder.get_sequence(), pin=18)
75+
```
76+
77+
`pin` is the BCM GPIO pin number. The function is blocking — it returns after
78+
the full sequence has been transmitted.
79+
80+
### Timing accuracy
81+
82+
`pigpio` provides hardware-timed waveforms with ~1 µs jitter, well within the
83+
default 25 % tolerance. Ensure the pigpio daemon is started with sufficient
84+
priority (`sudo pigpiod -t 0`) on loaded systems.
85+
86+
---
87+
88+
## Custom hardware
89+
90+
For any hardware not listed above, consume the timing sequence directly:
91+
92+
```python
93+
sequence = barcoder.get_sequence()
94+
# sequence: list of (level: bool, duration_ms: float)
95+
96+
for level, duration_ms in sequence:
97+
your_output.set(level)
98+
time.sleep(duration_ms / 1000.0)
99+
```
100+
101+
The sequence is hardware-agnostic — any output that can switch a digital line
102+
and hold it for a specified duration can transmit a barcode.

docs/index.md

Lines changed: 35 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,41 @@
11
# TTL Barcoder
22

3+
[![PyPI](https://img.shields.io/pypi/v/ttl-barcoder.svg)](https://pypi.org/project/ttl-barcoder)
4+
[![Ruff](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/v2.json)](https://github.com/astral-sh/ruff)
5+
36
Generate and decode binary barcodes over TTL signals to synchronize multiple data acquisition systems.
7+
Barcodes encode a timestamp or random value as a sequence of timed HIGH/LOW pulses,
8+
transmittable over any digital output.
9+
10+
## Key features
11+
12+
- Timestamp barcodes: encode Unix time at second, millisecond, or microsecond precision
13+
- Random barcodes: 16–64 bit random values from a seeded numpy RNG
14+
- Hardware-agnostic core: timing sequences are plain Python lists — no hardware dependency
15+
- Bpod integration: inject barcode states directly into a pybpodapi `StateMachine`
16+
- Raspberry Pi GPIO: send sequences over any GPIO pin via `pigpio`
17+
- Decoder: recover barcode value from edge timestamps with configurable tolerance
18+
- Validated configuration: Pydantic v2 `BarcodeConfig` with presets for common setups
19+
20+
## Quick start
21+
22+
```python
23+
from ttl_barcoder.core import BarcodeTTL, BarcodeConfig, TTLType
24+
25+
# Timestamp barcode (default) — encodes current time at ms precision
26+
barcoder = BarcodeTTL()
27+
barcoder.prepare() # generates value + timing sequence
28+
sequence = barcoder.get_sequence() # [(level: bool, duration_ms: float), ...]
29+
30+
# Random barcode
31+
config = BarcodeConfig(ttl_type=TTLType.random, barcode_bits=32)
32+
barcoder = BarcodeTTL(config)
33+
barcoder.prepare()
34+
sequence = barcoder.get_sequence()
35+
```
436

5-
> This is a documentation placeholder. Full content will be added in a future release.
6-
> For now, see the [README on GitHub](https://github.com/murineshiftwork/ttl-barcoder#readme) for installation, configuration, and usage examples.
37+
[Getting Started](getting_started.md) for installation and a step-by-step walkthrough.
738

8-
## Quick links
39+
[Configuration](configuration.md) for `BarcodeConfig` options and presets.
940

10-
- [Source code](https://github.com/murineshiftwork/ttl-barcoder)
11-
- [Issue tracker](https://github.com/murineshiftwork/ttl-barcoder/issues)
12-
- [PyPI](https://pypi.org/project/ttl-barcoder)
41+
[Hardware](hardware.md) for Bpod and Raspberry Pi GPIO integration.

mkdocs.yml

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,16 @@ theme:
1818

1919
markdown_extensions:
2020
- admonition
21-
- pymdownx.highlight
21+
- pymdownx.highlight:
22+
anchor_linenums: true
2223
- pymdownx.superfences
23-
- toc
24+
- pymdownx.tabbed:
25+
alternate_style: true
26+
- toc:
27+
permalink: true
2428

2529
nav:
2630
- Home: index.md
31+
- Getting Started: getting_started.md
32+
- Configuration: configuration.md
33+
- Hardware: hardware.md

0 commit comments

Comments
 (0)