LArPix Control Core¶
Controllers¶
-
class
larpix.controller.
Controller
[source]¶ Controls a collection of LArPix Chip objects.
Reading data:
The specific interface for reading data is selected by specifying the
io
attribute. These objects all have similar behavior for reading in new data. On initialization, the object will discard any LArPix packets sent from ASICs. To begin saving incoming packets, callstart_listening()
. Data will then build up in some form of internal register or queue. The queue can be emptied with a call toread()
, which empties the queue and returns a list of Packet objects that were in the queue. Theio
object will still be listening for new packets during and after this process. If the queue/register fills up, data may be discarded/lost. To stop saving incoming packets and retrieve any packets still in the queue, callstop_listening()
. While the Controller is listening, packets can be sent using the appropriate methods without interrupting the incoming data stream.With the the LArPix v2 asic, a network io structure is used. To keep track of this network and to insure the proper bring-up procedure is followed. The controller has a
network
attribute. This is an ordered dict with multiple layers corresponding to the chip key layers. It assumes that each hydra network is distinct on a given io channel. On a given io channel, the hydra network is represented as three directed graphsmiso_us
,miso_ds
, andmosi
.:controller.network[1] # Represents all networks on io group 1 controller.network[1][1] # Represents the network on io group 1, io channel 1 controller.network[1][1]['mosi'] # directed graph representing mosi links
Nodes within the network are added automatically whenever you add a chip to the controller:
list(controller.network[1][1]['mosi'].nodes()) # chip ids of known mosi nodes list(controller.network[1][1]['miso_us'].nodes()) # chip ids of known miso_us nodes list(controller.network[1][1]['miso_ds'].nodes()) # chip ids of known miso_ds nodes controller.network[1][1]['miso_us'].nodes[5] # attributes associated with node 5 controller.add_chip('1-1-6', version=2, root=True) list(controller.network[1][1]['miso_us'].nodes()) # [5, 6]
The ‘root’ node is used to indicate which chips should be brought up first when initializing the network.
Accessing connections between nodes is done via edges:
list(controller.network[1][1]['miso_us'].edges()) # [] controller.add_network_link(1,1,'miso_us',(6,5),0) # link chips 6 -> 5 in the miso_us graph via chip 6's uart channel 0 list(controller.network[1][1]['miso_us'].edges()) # [(6,5)] direction indicates the data flow direction controller.network[1][1]['miso_us'].edges[(6,5)] # attributes associated with link ('uart': 0)
In order to set up a ‘working’ network, you’ll need to add the proper links in the miso_ds and mosi graphs as well.:
controller.add_network_link(1,1,'miso_ds',(5,6),2) controller.add_network_link(1,1,'mosi',(6,5),0) controller.add_network_link(1,1,'mosi',(5,6),2)
External systems (e.g. the fpga you are using to communicate with the chips) are conventionally called
'ext0', 'ext1', ...
and shouldn’t be forgotten in the network configuration! These nodes are used to determine the miso/mosi configuration for the linked chips.:controller.add_network_link(1,1,'mosi',('ext',6),1) # link chip 6 to 'ext' via chip 6's uart channel 0 controller.add_network_link(1,1,'miso_ds',(6,'ext'),1) # same for miso_ds list(controller.network[1][1]['miso_ds'].edges()) list(controller.network[1][1]['mosi'].edges())
To then initialize a component on the network, run controller.init_network(1,1,6). This will modify the correct registers of chip 1-1-6 and send the configuration commands to the system.:
controller.init_network(1,1,6) controller.init_network(1,1,5)
Keep in mind, the order in which you initialize the network is important (e.g. chip 6 needs to be initialized before chip 5 since it is upstream from chip 6).
You may also reset a particular node with reset_network(<io_group>,<io_channel>,<chip_id>) which resets the network configuration of a particular node.:
controller.reset_network(1,1,5) controller.reset_network(1,1,6)
This is all rather tedious to do manually, so there a few shortcuts to make declaring and configuring the network easier. If you don’t want to initialize or reset each node in order, you may allow the controller to figure out the proper order (based on the root nodes) and configure all of the chips.:
controller.init_network(1,1) # configure the 1-1 network controller.reset_network(1,1) # revert the 1-1 network to it's original state
In the event that you need to access the chip keys of a network in the order of their depth within the network, use:
controller.get_network_keys(1,1) # get a list of chip keys starting with the root node and descending into the network controller.get_network_keys(1,1,root_first_traversal=False) # get a list of chip keys starting with the chips deepest in the network and ascending
You may also specify a network configuration file and use this to create all of the necessary network links and chips. See <https://larpix-control.readthedocs.io/en/stable/api/configs/controller.html> for how to create one of these files. This is the generally recommended means of creating and loading a Hydra io network.:
# as an example for bringing up a hydra network from a config file controller.load('<network config file>.json') # load your network and chips for io_group, io_channels in controller.network.items(): for io_channel in io_channels: controller.init_network(io_group, io_channel) # update configurations and write to chips
Properties and attributes:
chips
: theChip
objects that the controller controlsreads
: list of all the PacketCollections that have been sent back to this controller. PacketCollections are created byrun
,write_configuration
,read_configuration
,multi_write_configuration
,multi_read_configuration
, andstore_packets
.network
: a collection of networkx directed graph objects representing the miso_us, miso_ds, and mosi connections between chips (not applicable for v1 asics)
-
add_chip
(chip_key, version=2, config=None, root=False)[source]¶ Add a specified chip to the Controller chips.
Parameters: - chip_key – chip key to specify unique chip
- version – asic version of chip
- config – configuration to assign chip when creating (otherwise uses default)
- root – specifies if this is a root node as used by the hydra io network
Returns: Chip
that was added
-
add_network_link
(io_group, io_channel, network_name, chip_ids, uart)[source]¶ Adds a link within the specified network (
mosi
,miso_ds
, ormiso_us
) on the specified uart. Directionality is important: first key represents the tail (where packets are coming from) and the second is the head (where packets are going). The uart channel refers to the tail’s uart channel (for'miso_*'
) and to the head’s uart channel for ('mosi'
). Links can be formed with non-key objects to allow for network communications with objects that are not larpix chips (e.g. an external fpga).For example to specify a miso downstream link between chips
'1-1-3'
and'1-1-2'
on chip'1-1-3'
’s uart 0, the arguments should be:controller.add_network_link('miso_ds', 1, 1, (3,2), 0)
This represents a link where chip
'1-1-3'
will transfer packets out of its uart 0 to a destination of chip'1-1-2'
(unspecified uart).No network validation is performed, so use with caution!
Parameters: - network_name –
str
from('miso_us','miso_ds','mosi')
- io_group – io group to add network link in
- io_channel – io channel to add network link in
- chip_ids –
tuple
of two chip ids to link (order is important – first is ‘tail’ second is ‘head’, data flows from the ‘tail’ to the ‘head’ in all networks) - uart –
int
referring to which uart channel this link occurs over, for'miso_*'
networks the uart channel refers to the uart on the sender (i.e. the ‘tail’ of the edge in the directed graph), but for'mosi'
networks the uart channel refers to the uart on the receiver (i.e. the ‘head’ of the edge in the directed graph)
- network_name –
-
add_network_node
(io_group, io_channel, network_names, chip_id, root=False)[source]¶ Adds a node to the specified network (
mosi
,miso_ds
, ormiso_us
) with no links. Generally, this is not needed as network nodes are added automatically with thecontroller.add_chip()
method. ‘Special’ (i.e. non-key) nodes can be specified to insert nodes that do not represent larpix chips (e.g. an external fpga). A node can be declared as a root node, which is used as a flag to select the starting node during initialization.Parameters: - network_names – list of networks or name of single network to create a node in
- io_group – io group to create node within
- io_channel – io channel to create node within
- chip_id – chip id to associate with node (note that all chip ids must be unique on a network)
- root – specifies if this node should be a root node (default=False)
-
get_network_ids
(io_group, io_channel, root_first_traversal=True)[source]¶ Returns a list of chip ids in order of depth within the miso_us network
Parameters: - io_group – io group of network
- io_channel – io channel of network
- root_first_traversal –
True
to traverse network starting from root nodes then increasing in network depth,False
to traverse network starting from nodes furthest from root nodes and then decreasing in network depth
-
get_network_keys
(io_group, io_channel, root_first_traversal=True)[source]¶ Returns a list of chip ids in order of depth within the miso_us network
Parameters: - io_group – io group of network
- io_channel – io channel of network
- root_first_traversal –
True
to traverse network starting from root nodes then increasing in network depth,False
to traverse network starting from nodes furthest from root nodes and then decreasing in network depth
-
remove_chip
(chip_key)[source]¶ Remove a specified chip from the Controller chips.
Parameters: chip_key – chip key to specify unique chip
-
load
(filename)[source]¶ Loads the specified file that describes the chip ids and IO network
Parameters: filename – File path to configuration file
-
load_network
(filename, version=2)[source]¶ Loads the specified file using the hydra io network configuration format with either a miso_us_uart_map/miso_ds_uart_map/mosi_uart_map specification or a miso_uart_map/mosi_uart_map/usds_uart_map specification.
After loading the network, running
controller.init_network(<io group>, <io channel>)
will configure the chips with specified chip ids in the order declared in fileParameters: filename – File path to configuration file
-
load_controller
(filename)[source]¶ Loads the specified file using the basic key, chip format
The chip key is the Controller access key that gets communicated to/from the io object when sending and receiving packets.
Parameters: filename – File path to configuration file
-
grow_network
(io_group, io_channel, chip_id, miso_uart_map=[3, 0, 1, 2], mosi_uart_map=[0, 1, 2, 3], usds_link_map=[2, 3, 0, 1], chip_id_generator=<function Controller._default_chip_id_generator>, timeout=0.01, modify_mosi=False, differential=True, version=2)[source]¶ Recurisve algorithm to auto-complete a network from a stub. It works by attempting to link to each available upstream node in succession, keeping links that are verified. Repeats on each newly generated node until no possible links remain.
To use with a completely unconfigured network you must first configure the root node representing the control system:
controller.add_network_node(io_group, io_channel, controller.network_names, 'ext', root=True)
You can then grow the network from this stub:
controller.grow_network(io_group, io_channel, 'ext')
This algorithim is limited to a regular geometry defined by the same miso_uart_map/mosi_uart_map/usds_link_map for each chip.
Parameters: - io_group – the io group designation for the network
- io_channel – the io channel designation for the network
- chip_id – the chip id of the chip to start growth from
- miso_uart_map – a length 4 iterable indicating the miso channel used to send data to a chip at position i relative to the active chip
- mosi_uart_map – a length 4 iterable indicating the mosi channel used to receive data from a chip at position i relative to the active chip
- usds_link_map – a length 4 iterable indicating the relative position of the active chip from the perspective of the chip at position i
- chip_id_generator – a function that takes a controller, io_group, and io_channel and returns a unique chip id for that network
- timeout – the time duration in seconds to wait for a response from each configured node
- modify_mosi – flag to configure each chip’s mosi, if set to
True
algorithm will also write the mosi configuration when probing chips, this will almost certainly leave you with deaf nodes and is not what you want. Leave at defaultFalse
- differential –
True
to also enable differential signalling
Returns: the generated ‘miso_us’, ‘miso_ds’, and ‘mosi’ networks as a dict
-
init_network_and_verify
(io_group=1, io_channel=1, chip_id=None, timeout=0.2, retries=10, modify_mosi=True, differential=True)[source]¶ Runs init network, verifying that registers are updated properly at each step Will exit if any chip network configuration cannot be set correctly after
retries
attempts
-
init_network
(io_group=1, io_channel=1, chip_id=None, modify_mosi=True, differential=True)[source]¶ Configure a Hydra io node specified by chip_id, if none are specified, load complete network To configure a Hydra io network, the following steps are followed:
- Enable miso_us of parent chip
- Enable mosi of parent chip
- Write chip_id to chip on io group + io channel (assuming chip id 1)
- Write enable_miso_downstream to chip chip_id (also enable differential if desired)
- Write enable_mosi to chip chip_id (optional)
-
reset_network
(io_group=1, io_channel=1, chip_id=None)[source]¶ Resets the hydra IO network To reset a Hydra io network node, the following steps are followed:
- Write enable_mosi [1,1,1,1] to chip
- Write enable_miso_downstream [0,0,0,0] to chip
- Write chip_id 1 to chip
- Disable miso_us channel of parent chip
If no chip_id is specified, network is reset in reverse order (starting from chips with no outgoing miso_us connections, working up the miso_us tree)
-
read
()[source]¶ Read any packets that have arrived and return (packets, bytestream) where bytestream is the bytes that were received.
The returned list will contain packets that arrived since the last call to
read
orstart_listening
, whichever was most recent.
-
write_configuration
(chip_key, registers=None, write_read=0, message=None, connection_delay=0.2)[source]¶ Send the configurations stored in chip.config to the LArPix ASIC.
By default, sends all registers. If registers is an int, then only that register is sent. If registers is a string, then the sent registers will set by looking at the configuration register map. If registers is an iterable, then all of the registers in the iterable are sent.
If write_read == 0 (default), the configurations will be sent and the current listening state will not be affected. If the controller is currently listening, then the listening state will not change and the value of write_read will be ignored. If write_read > 0 and the controller is not currently listening, then the controller will listen for
write_read
seconds beginning immediately before the packets are sent out, read the io queue, and save the packets into thereads
data member. Note that the controller will only read the queue once, so if a lot of data is expected, you should handle the reads manually and set write_read to 0 (default).
-
read_configuration
(chip_key, registers=None, timeout=1, message=None, connection_delay=0.2)[source]¶ Send “configuration read” requests to the LArPix ASIC.
By default, request all registers. If registers is an int, then only that register is reqeusted. If registers is an iterable, then all of the registers in the iterable are requested.
If the controller is currently listening, then the requests will be sent and no change to the listening state will occur. (The value of
timeout
will be ignored.) If the controller is not currently listening, then the controller will listen fortimeout
seconds beginning immediately before the first packet is sent out, and will save any received packets in thereads
data member.
-
multi_write_configuration
(chip_reg_pairs, write_read=0, message=None, connection_delay=0.2)[source]¶ Send multiple write configuration commands at once.
chip_reg_pairs
should be a list/iterable whose elements are an valid arguments toController.write_configuration
, excluding thewrite_read
argument. Just like in the singleController.write_configuration
, settingwrite_read > 0
will have the controller read data during and after it writes, for however many seconds are specified.Examples:
These first 2 are equivalent and write the full configurations
>>> controller.multi_write_configuration([chip_key1, chip_key2, ...]) >>> controller.multi_write_configuration([(chip_key1, None), chip_key2, ...])
These 2 write the specified registers for the specified chips in the specified order
>>> controller.multi_write_configuration([(chip_key1, 1), (chip_key2, 2), ...]) >>> controller.multi_write_configuration([(chip_key1, range(10)), chip_key2, ...])
-
multi_read_configuration
(chip_reg_pairs, timeout=1, message=None, connection_delay=0.2)[source]¶ Send multiple read configuration commands at once.
chip_reg_pairs
should be a list/iterable whose elements are chip keys (to read entire configuration) or (chip_key, registers) tuples to read only the specified register(s). Registers could beNone
(i.e. all), anint
for that register only, or an iterable of ints.Examples:
These first 2 are equivalent and read the full configurations
>>> controller.multi_read_configuration([chip_key1, chip_key2, ...]) >>> controller.multi_read_configuration([(chip_key1, None), chip_key2, ...])
These 2 read the specified registers for the specified chips in the specified order
>>> controller.multi_read_configuration([(chip_key1, 1), (chip_key2, 2), ...]) >>> controller.multi_read_configuration([(chip_key1, range(10)), chip_key2, ...])
-
run
(timelimit, message)[source]¶ Read data from the LArPix ASICs for the given
timelimit
and associate the received Packets with the givenmessage
.
-
verify_registers
(chip_key_register_pairs, timeout=1, connection_delay=0.02, n=1)[source]¶ Read chip configuration from specified chip and registers and return
True
if the read chip configuration matches the current configuration stored in chip instance.Parameters: - chip_key_register_pair – a
list
of key register pairs as documented incontroller.multi_read_configuration
- timeout – set how long to wait for response in seconds (optional)
- n – sets maximum recursion depth, will continue to attempt to verify registers until this depth is reached or all registers have responded, a value <1 allows for infinite recursion (optional)
Returns: 2-
tuple
of abool
representing if all registers match and adict
representing all differences. Differences are specified as{<chip_key>: {<register>: (<expected>, <read>)}}
- chip_key_register_pair – a
-
verify_configuration
(chip_keys=None, timeout=1, connection_delay=0.02, n=1)[source]¶ Read chip configuration from specified chip(s) and return
True
if the read chip configuration matches the current configuration stored in chip instance.chip_keys
can be a single chip key, a list of chip keys, orNone
. Ifchip_keys
isNone
all chips will be verified.Also returns a dict containing the values of registers that are different (read register, stored register)
Parameters: - chip_keys –
list
of chip_keys to verify - timeout – how long to wait for response in seconds
- n – set recursion limit for rechecking non-responding registers
Returns: 2-
tuple
with same format ascontroller.verify_registers
- chip_keys –
-
verify_network
(chip_keys=None, timeout=1)[source]¶ Read chip network configuration from specified chip(s) and return
True
if the read chip configurations matches Only valid for v2 chips.Parameters: - chip_keys –
list
of chip_keys to verify or singe chip_key to verify - timeout – how long to wait for response in seconds
Returns: 2-
tuple
with same format ascontroller.verify_registers
- chip_keys –
-
enforce_registers
(chip_key_register_pairs, timeout=1, connection_delay=0.02, n=1, n_verify=1)[source]¶ Read chip configuration from specified chip and registers and write registers to read chip configurations that do not match the current configuration stored in chip instance.
Parameters: - chip_key_register_pair – a
list
of key register pairs as documented incontroller.multi_read_configuration
- timeout – set how long to wait for response in seconds (optional)
- n – sets maximum recursion depth, will continue to attempt to enforce registers until this depth is reached or all registers have responded, a value <1 allows for infinite recursion (optional)
- n_verify – maximum recursion depth for verify registers (optional)
Returns: 2-
tuple
with same format ascontroller.verify_registers
- chip_key_register_pair – a
-
enforce_configuration
(chip_keys=None, timeout=1, connection_delay=0.02, n=1, n_verify=1)[source]¶ Read chip configuration from specified chip(s) and write registers to read chip configuration that do not match the current configuration stored in chip instance.
chip_keys
can be a single chip key, a list of chip keys, orNone
. Ifchip_keys
isNone
all chip configs will be enforced.Also returns a dict containing the values of registers that are different (read register, stored register)
Parameters: - chip_keys –
list
of chip_keys to verify - timeout – how long to wait for response in seconds
- n – set recursion limit for enforcing non-matching registers (optional)
- n_verify – set recursion limit for verifying registers (optional)
Returns: 2-
tuple
with same format ascontroller.verify_registers
- chip_keys –
-
enable_analog_monitor
(chip_key, channel)[source]¶ Enable the analog monitor on a single channel on the specified chip. Note: If monitoring a different chip, call disable_analog_monitor first to ensure that the monitor to that chip is disconnected.
-
disable_analog_monitor
(chip_key=None, channel=None)[source]¶ Disable the analog monitor for a specified chip and channel, if none are specified disable the analog monitor for all chips in self.chips and all channels
-
enable_testpulse
(chip_key, channel_list, start_dac=255)[source]¶ Prepare chip for pulsing - enable testpulser and set a starting dac value for specified chip/channel
-
issue_testpulse
(chip_key, pulse_dac, min_dac=0, read_time=0.1)[source]¶ Reduce the testpulser dac by
pulse_dac
and write_read to chip forread_time
seconds
-
disable_testpulse
(chip_key=None, channel_list=None)[source]¶ Disable testpulser for specified chip/channels. If none specified, disable for all chips/channels
-
disable
(chip_key=None, channel_list=None)[source]¶ Update channel mask to disable specified chips/channels. If none specified, disable all chips/channels
Chips¶
-
class
larpix.chip.
Chip
(chip_key, version=2)[source]¶ Represents one LArPix chip and helps with configuration and packet generation.
-
is_chip_id_set
()[source]¶ Check if chip id (as specified by unique key) matches the chip id stored in the configuration. Only valid for v2 asics, if v1 asic, will always return
True
Note: Even if this function returns True, it’s possible the chip ID has not been sent from the larpix-control software onto the ASIC hardware
-
get_configuration_packets
(packet_type, registers=None)[source]¶ Return a list of Packet objects to read or write (depending on
packet_type
) the specified configuration registers (or all registers by default).
-
get_configuration_write_packets
(registers=None)[source]¶ Return a list of Packet objects to write corresponding to the specified configuration registers (all by default)
-
get_configuration_read_packets
(registers=None)[source]¶ Return a list of Packet objects to write corresponding to the specified configuration registers (all by default)
-
Chip keys¶
-
class
larpix.key.
Key
(*args)[source]¶ A unique specification for routing data to a particular detector sub-system. At the core, a key is represented by 3-unsigned 1-byte integer fields which refer to an id code within a layer of the LArPix DAQ system heirarchy. Field 0 represents the io group id number, field 1 represents the io channel connecting to a MISO/MOSI pair, and field 2 represents the chip id. The io group is the device controlling a set of MOSI/MISO pairs, the io channel is a single MOSI/MISO pair controlling a collection of LArPix asics, and the chip id uniquely identifies a chip on a single MISO/MISO network.
Each field should be a 1-byte unsigned integer (0-255) providing a unique lookup value for each component in the system. The id values of 0 and 255 are reserved for special functionality.
A key can be specified by a string of
'<io group>-<io channel>-<chip id>'
, by io group, io channel, and chip id, or by using other Keys.Keys are hashed by their string representation and are equivalent to their string representation so:
key = Key(1,1,1) # io group, io channel, chip id key == Key('1-1-1') # True key == Key(key) # True key == '1-1-1' # True key == (1,1,1) # True d = { key: 'example' } d[key] == 'example' # True d['1-1-1'] == 'example' # True
Keys are “psuedo-immutable”, i.e. you cannot change a Key’s io_group, io_channel, or chip_id after it has been created.
-
keystring
¶ Key string specifying key io group, io channel, and chip id in the format:
'<io group>-<io channel>-<chip id>'
-
chip_id
¶ 1-byte unsigned integer representing the physical chip id (hardwired for v1 ASICs, assigned dynamically for v2 ASICs)
-
io_channel
¶ 1-byte unsigned integer representing the physical io channel. This identifies a single MOSI/MISO pair used to communicate with a single network of up to 254 chips.
-
io_group
¶ 1-byte unsigned integer representing the physical device used to read out up to 254 io channels.
-
static
is_valid_keystring
(keystring)[source]¶ Check if keystring can be interpreted as a larpix.Key
Returns: True
if the keystring can be interpreted as a larpix.Key
-
Packets¶
-
class
larpix.packet.packet_v1.
Packet_v1
(bytestream=None)[source]¶ A single 54-bit LArPix UART data packet.
LArPix Packet objects have attributes for inspecting and modifying the contents of the packet.
Internally, packets are represented as an array of bits, and the different attributes use Python “properties” to seamlessly convert between the bits representation and a more intuitive integer representation. The bits representation can be inspected with the
bits
attribute.Packet objects do not restrict you from adjusting an attribute for an inappropriate packet type. For example, you can create a data packet and then set
packet.register_address = 5
. This will adjust the packet bits corresponding to a configuration packet’s “register_address” region, which is probably not what you want for your data packet.Packets have a parity bit which enforces odd parity, i.e. the sum of all the individual bits in a packet must be an odd number. The parity bit can be accessed as above using the
parity_bit_value
attribute. The correct parity bit can be computed usingcompute_parity()
, and the validity of a packet’s parity can be checked usinghas_valid_parity()
. When constructing a new packet, the correct parity bit can be assigned usingassign_parity()
.Individual packets can be printed to show a human-readable interpretation of the packet contents. The printed version adjusts its output based on the packet type, so a data packet will show the data word, timestamp, etc., while a configuration packet will show the register address and register data.
-
bytes
()[source]¶ Construct the bytes that make up the packet.
Byte 0 is the first byte that would be sent out and contains the first 8 bits of the packet (i.e. packet type and part of the chip ID).
Note: The internal bits representation of the packet has a different endian-ness compared to the output of this method.
-
-
class
larpix.packet.packet_v2.
Packet_v2
(bytestream=None)[source]¶ Representation of a 64 bit LArPix v2 (or LightPix v1) UART data packet.
Packet_v2 objects are internally represented as bitarrays, but a variety of helper properties allow one to access and set the data stored in the bitarrays in a natural fashion. E.g.:
p = Packet_v2() # initialize a packet of zeros p.packet_type # fetch packet type bits and convert to uint p.packet_type = 2 # set the packet type to a config write packet print(p.bits) # the bits have been updated!
Packet_v2 objects don’t enforce any value validation, so set these fields with caution!
In FIFO diagnostics mode, the bits are to be interpreted in a different way. At this point, there is no way for the
Packet_v2
to automatically know if it is in FIFO diagnostics mode. If you are operating the chips in this mode you can manually setPacket_v2.fifo_diagnostics_enabled = True
to interpret data packets in this fashion by default, or setpacket.fifo_diagnostics_enabled = True
for a single packet. Just remember that if you modifypacket.fifo_diagnostics_enabled
, it will no longer use the default.
-
class
larpix.packet.timestamp_packet.
TimestampPacket
(timestamp=None, code=None)[source]¶ A packet-like object which just contains an integer timestamp.
This class implements many methods used by Packet, so it functions smoothly in lists of packets and in PacketCollection.
If neither
timestamp
norcode
is provided then this TimestampPacket will have a timestamp ofNone
until it is manually set.Parameters: - timestamp – optional, integer timestamp of this packet
- code – optional, encoded timestamp as a 7-byte unsigned int
obtainable from calling the
bytes
method.
-
class
larpix.packet.message_packet.
MessagePacket
(message, timestamp)[source]¶ A packet-like object which contains a string message and timestamp.
Parameters: - message – a string message of length less than 64
- timestamp – the timestamp of the message
-
class
larpix.packet.packet_collection.
PacketCollection
(packets, bytestream=None, message='', read_id=None, skipped=None)[source]¶ Represents a group of packets that were sent to or received from LArPix.
Index into the PacketCollection as if it were a list:
>>> collection[0] Packet(b'') >>> first_ten = collection[:10] >>> len(first_ten) 10 >>> type(first_ten) larpix.larpix.PacketCollection >>> first_ten.message 'my packets | subset slice(None, 10, None)'
To view the bits representation, add ‘bits’ to the index:
>>> collection[0, 'bits'] '00000000 00000000 00000000 00000000 00000000 00000000 000111' >>> bits_format_first_10 = collection[:10, 'bits'] >>> type(bits_format_first_10[0]) str
-
extract
(*attrs, **selection)[source]¶ Extract the given attribute(s) from packets specified by selection and return a list.
Any attribute of a Packet is a valid attribute or selection
Usage:
>>> # Return a list of adc counts from any data packets >>> dataword = collection.extract('dataword', packet_type=0) >>> # Return a list of timestamps from chip 2 data >>> timestamps = collection.extract('timestamp', chip_id=2, packet_type=Packet_v2.DATA_PACKET) >>> # Return the most recently read global threshold from chip 5 >>> threshold = collection.extract('register_value', register_address=32, packet_type=3, chip_id=5)[-1] >>> # Return multiple attributes >>> chip_keys, channel_ids = zip(*collection.extract('chip_key','channel_id'))
Note
selecting on
timestamp
will also select TimestampPacket values.
-