## A Python library for Trgen Device
Project description
trgenpy 🐍🧠
A Python library for Trgen Device
The full documentation is available here.
Index
Getting started
How to install
To install this package use is required Python >= 3.9
pip install trgenpy
Architecture
As explained in this Mermaid diagram, we see that we can "attach" n (0-25) TrgenPorts to the TrgenClient
graph TD
A[TrgenClient]
A --> Impl[TrgenImplementation]
A --> B0[TrgenPort 0]
A --> B1[TrgenPort 1]
A --> BN[TrgenPort n]
B0 --> P0[TrgenPin]
B1 --> P1[TrgenPin]
BN --> PN[TrgenPin]
B0 --> M0[Memory]
B1 --> M1[Memory]
BN --> MN[Memory]
M0 --> I0[Instruction 0]
M0 --> I1[Instruction 1]
M0 --> I2[Instruction n]
M1 --> J0[Instruction 0]
M1 --> J1[Instruction 1]
M1 --> J2[Instruction n]
MN --> K0[Instruction 0]
MN --> K1[Instruction 1]
MN --> K2[Instruction n]
client = TrgenClient() # now I can use this client for any purpose.
Each TrgenPortcan be programmed with a bunch of instructions.
We can use the function set_instruction() in many memory slots.
Finally, we can use set_trgen_memory to a specific TrgenPort and execute the TrgenClient with client.start()
NOTE
Each TrgenPort can support a list of N instructions, where N = 2^MTML (Max TrgenPort Memory Length)
the import ways
# you can us it like this:
import trgenpy as tp
client = tp.TrgenClient()
# or like this:
from from trgenpy import TrgenClient,TrgenPin,active_for_us,unactive_for_us,end,wait_ne,wait_pe
client = TrgenClient()
Client
The TrgenClient is the object that stores all the information about the socket connection between you and the Trgen.
You can instantiate the TrgenClient object like this:
client = TrgenClient()
Once the client object is created you can connect to Trgen...
client.connect()
...or check device availability
isAavailable = client.is_available() # true / false
Single TrgenPort Send
To send a defaul trigger signal (positive square with a logic state of 20µs) you can use the sendTrigger() function:
client.sendTrigger()
Custom Trigger Send
If you want to send trigger to a custom list inside the pinout you can use the sendCustomTrigger() function:
client.sendCustomTrigger([TrgenPin.NS0,TrgenPin.GPIO0])
Sending Markers
If you want to send a marker value to all (Neuroscan,Synamps and GPIO) ports you can use the sendMarker() function:
client.sendMarker(13)
Pin Binary Mapping
Both sendMarker() and sendCustomTrigger() use a binary mapping system where each pin corresponds to a specific bit position. This allows for efficient encoding of multiple pin states in a single value:
| Pin | Binary Position | Decimal Value | Binary Representation |
|---|---|---|---|
| NS0 | Bit 0 (2^0) | 1 | 00000001 |
| NS1 | Bit 1 (2^1) | 2 | 00000010 |
| NS2 | Bit 2 (2^2) | 4 | 00000100 |
| NS3 | Bit 3 (2^3) | 8 | 00001000 |
| NS4 | Bit 4 (2^4) | 16 | 00010000 |
| NS5 | Bit 5 (2^5) | 32 | 00100000 |
| NS6 | Bit 6 (2^6) | 64 | 01000000 |
| NS7 | Bit 7 (2^7) | 128 | 10000000 |
This suggests the pins might be mapped differently than the sequential naming suggests. Please verify the complete mapping to ensure accuracy.
Examples based on your observation:
sendMarker(1)→ activates only NS0sendMarker(128)→ activates only NS6sendMarker(129)→ activates NS0 + NS6 (binary: 10000001)
This same mapping applies to Synamps (SA0-SA7) and GPIO (GPIO0-GPIO7) pins when using their respective marker parameters.
if you want invert the bit order, just flag the LSB argument (Trueby default)
client.sendMarker(13,LSB=False)
if you want to send different markers simultaiously on different ports you can use the arguments:
markerNSmarkerSAmarkerGPIO
like this:
client.sendMarker(markerNS=8,markerSA=2,markerGPIO=15)
TrgenPort
The TrgenPort object defines a single trigger behaviours through its id.
This is the list of supported TrgenPin values for the Trgen:
TrgenPin List
- Neuroscan IDs
The Neuroscan pinout (only for used pins) goes from 0 to 7
[NS0,NS1,NS2,NS3,NS4,NS5,NS6,NS7]
- Synamps IDs
The Neuroscan pinout (only for used pins) goes from 0 to 7
[SA0,SA1,SA2,SA3,SA4,SA5,SA6,SA7]
- TMSI/O IDs
TMSOTMSI
- GPIO IDs
The GPIO pinout goes from 0 to 7
[GPIO0,GPIO01,GPIO02,GPIO03,GPIO04,GPIO05,GPIO06,GPIO07]
You can instantiate the TrgenPort object with:
neuroScan = TrgenClient.create_trgen(TrgenPin.NS3)
passing ad only argument the constant from TrgenPin
Now you're ready to define the instruction set for TrgenPort with the set_instruction() function.
Each trgenport has a memory property, a list that can contain 32 instructions, so this function is defined:
def set_instruction(self, index, instruction):
# index: 0-32 value
# instruction: instruction_code
Each instruction code can be encoded using the Instruction Helpers
# call the function directly on the same TrgenPort object
neuroScan.set_instruction(0, active_for_us(5))
neuroScan.set_instruction(1, unactive_for_us(3))
# ...
Instruction Helpers
The supported instruction set for TrgenPort is:
| Instruction | 1° Param | 2° Param | Description |
|---|---|---|---|
unactive_for_us(us) |
µ seconds duration | Set the unactivation time for µ seconds | |
active_for_us(us) |
µ seconds duration | Set the activation time for µ seconds | |
wait_pe(tr) |
TrgenPort ID | Wait the positive edge for a specific TrgenPort ID | |
wait_ne(tr) |
TrgenPort ID | Wait the negative edge for a specific TrgenPort ID | |
repeat(addr,time) |
Instruction address | Time of repeat | Set the activation time for µ seconds |
end() |
End the behaviour | ||
not_admissible() |
Empty instruction, it has to be placed after the end() |
You can access to the mtml value by
# Add this in try block to manage errors
try:
impl = client.get_implementation()
mtml = impml.mtml
except InvalidAckError as e:
print(f"⚠️ ACK sbagliato: {e}")
except AckFormatError as e:
print(f"⚠️ ACK malformato: {e}")
except TimeoutError as e:
print(f"⏱️ Timeout: {e}")
Native Commands
IIT's Trgen can receive some commands, the full instruction set includes:
- Program TrgenPort
- Start TrgenPort
- Set GPIO I/O Direction
- Request Implementation parameters
- Request TrgenPort Status
- Set the TrgenPort level
- Get GPIO I/O Direction
- Get the TrgenPort Level
- Stop the TrgenPort
Program TrgenPort
You can program a trigger memory in two ways:
- Default trigger using
program_default_trigger()
This sets a predefined impulse of duration (default 20µs).
tr = client.create_trgen(TrgenPin.GPIO0)
client.program_default_trigger(tr, us=50) # impulse of 50µs
- Advanced programming by manually setting instructions with
set_instruction()
tr = client.create_trgen(TrgenPin.NS1)
tr.set_instruction(0, active_for_us(10))
tr.set_instruction(1, unactive_for_us(5))
tr.set_instruction(2, repeat(0, 3))
tr.set_instruction(3, end())
client.set_trgen_memory(tr)
Start Trigger
After programming triggers, you can start them with:
client.start()
This command makes the Trgen execute all programmed triggers.
Remember: you must have previously sent at least one trigger memory.
Set GPIO I/O Direction
the "byte" way
# Set GPIO directions (example: GPIO0-3 as outputs)
client.set_gpio_direction(0b00001111)
helper way
You can use this helper to build the complete or partial pinout map to set.
# we choose to set just GPIO0 -> High and the GPIO1 -> Low
mask = DirectionConfig().out(TrgenPin.GPIO0).in(TrgenPin.GPIO1).build()
# once you have it, you can use it as argument in the set_level function
client.set_gpio_direction(mask)
Request Implementation
You can get information about the hardware configuration (number of channels, memory length, etc.) with:
impl = client.get_implementation()
print(impl.memory_length) # max number of instructions per trigger
Request TrgenPort Status
To check current status of triggers (active/inactive state):
status = client.get_status()
print(status)
This returns an integer bitmask where each bit represents the state of a trigger pin.
Set the Trigger level
the "byte" way
You can change polarity (active-high or active-low) of all triggers:
# Set all triggers active-high
client.set_level(0xFF)
# Set only GPIO0 active-high, rest active-low
client.set_level(0b00000001)
helper way
You can use this helper to build the complete or partial pinout map to set.
# we choose to set just GPIO0 -> High and the GPIO1 -> Low
mask = LevelConfig().high(TrgenPin.GPIO0, TrgenPin.TMSO).low(TrgenPin.GPIO1).build()
# once you have it, you can use it as argument in the set_level function
client.set_level(mask)
Get the GPIO I/O Direction
To retrieve the current GPIO configuration:
gpio_state = client.get_gpio_direction()
print(bin(gpio_state))
Get the Trigger Level
To check trigger polarity:
level = client.get_level()
print(bin(level))
E-Prime integration
trgenpy offers a wrapper version to integrate its behaviour inside the E-Prime software via Python COM-visible.
Install pywin32
pip install pywin32
Register the COM wrapper
python trgen_com.py --register
So that you can use in E-Prime like this
Dim tb
Set tb = CreateObject("Trgen.COM")
If tb.IsAvailable() Then
tb.Connect
tb.SendTrigger
tb.SendMarker 13
Else
MsgBox "Trgen not available!"
End If
E-Prime example
See here for the complete examples
How to build
trgenpy uses setuptools to have a much clear and minimal build process.
Step 1 - install twine
pip install --upgrade build twine
Step 2 - build
python -m build
Step 3 - use it anywhere!
In the same directory (pwd) of this project, run:
pip install .
Deploy
twine upload --repository testpypi dist/*
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file trgenpy-1.0.0.tar.gz.
File metadata
- Download URL: trgenpy-1.0.0.tar.gz
- Upload date:
- Size: 20.1 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.4
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
1caa3475c2f128ea417f1b1256c90230cd41590ee439a8d61b21fd65ba693949
|
|
| MD5 |
4399423b00ceb436d21f62f31b2b03f1
|
|
| BLAKE2b-256 |
f7f57ec55ff48c1c6328e642f4afd60a6e41a468970af850f35f6c3cbb0a59ff
|
File details
Details for the file trgenpy-1.0.0-py3-none-any.whl.
File metadata
- Download URL: trgenpy-1.0.0-py3-none-any.whl
- Upload date:
- Size: 18.1 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.4
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
de7f5895e1de0ea9c4a1c29969c3eeebc27b48e71b26bc4878589e467a82dd4d
|
|
| MD5 |
451a7cd57f5aa69102cbd551a52a6adf
|
|
| BLAKE2b-256 |
27589937f83f259a31eefd44e4f456f975d05640922f12ca1dcb9107a2397138
|