Skip to content

Prologix¤

Prologix (Interface) ¤

Prologix(equipment: Equipment)

Use Prologix hardware to establish a connection.

For the GPIB-ETHERNET Controller, the format of the address string is Prologix::HOST::1234::PAD[::SAD], where HOST is the hostname or IP address of the Prologix hardware, 1234 is the ethernet port that is open on the Prologix hardware, PAD (Primary GPIB Address) is an integer value between 0 and 30, and SAD (Secondary GPIB Address) is an integer value between 96 and 126 (SAD is optional). For example,

  • Prologix::192.168.1.110::1234::6
  • Prologix::192.168.1.110::1234::6::96
  • Prologix::prologix-00-21-69-01-31-04::1234::6
    (typically, the hostname is prologix-<MAC Address>)

For the GPIB-USB Controller, the format of the address string is Prologix::PORT::PAD[::SAD], where PORT is the name of the serial port of the Prologix hardware, PAD (Primary GPIB Address) is an integer value between 0 and 30, and SAD (Secondary GPIB Address) is an integer value between 96 and 126 (SAD is optional). For example,

  • Prologix::COM3::6
  • Prologix::/dev/ttyUSB0::6::112

Alternatively, to clearly separate the Prologix hardware address from the GPIB address you may include GPIB:: in the address, for example,

  • Prologix::192.168.1.110::1234::GPIB::6
  • Prologix::COM3::GPIB::22::96

Parameters:

Name Type Description Default
equipment Equipment

An Equipment instance.

required

A Connection instance supports the following properties for using Prologix hardware, as well as the properties defined in Serial (for a GPIB-USB Controller) and in Socket (for a GPIB-ETHERNET Controller).

Connection Properties:

Name Type Description
eoi bool

Whether to assert the End or Identify (EOI) hardware line. Default: True

eos int

GPIB termination character(s) to append to the message that is sent to the equipment. Default: 3

  • 0: CR+LF
  • 1: CR
  • 2: LF
  • 3: no termination
eot_char int | str

A user-specified character to append to the reply that the Prologix hardware sends back to the computer when eot_enable is True and EOI is detected. Must have an ASCII value <256, e.g., eot_char=42 appends * (ASCII 42) when EOI is detected. Default: 0

eot_enable bool

Enable or disable the appending of a user-specified character, eot_char, when the Prologix hardware sends a reply back to the computer. Default: False

escape_characters bool

Whether to escape the LF, CR, ESC and + characters when writing a message to the Prologix hardware. Default: True

read_tmo_ms int

The inter-character timeout value, in milliseconds, to be used in the read command and the serial_poll command, i.e., the delay since the last character was read. The read_tmo_ms timeout value is not to be confused with the total time for which data is read. The read_tmo_ms value must be between 1 and 3000 milliseconds. Default: 1000

Important

The Prologix Connection Properties are the same for all equipment that are attached to the Prologix hardware. If different equipment require different properties you must manage the settings appropriately, such as by writing ++eoi 0 to disable the use of the End or Identify line before reading from the equipment and then perhaps writing ++eoi 1 to re-enable it afterwards. Only the escape_characters property is associated with the Prologix instance.

Source code in src/msl/equipment/interfaces/prologix.py
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
def __init__(self, equipment: Equipment) -> None:
    """Use [Prologix](https://prologix.biz/) hardware to establish a connection.

    For the GPIB-ETHERNET Controller, the format of the [address][msl.equipment.schema.Connection.address]
    string is `Prologix::HOST::1234::PAD[::SAD]`, where `HOST` is the hostname or IP address of the Prologix
    hardware, `1234` is the ethernet port that is open on the Prologix hardware, PAD (Primary GPIB Address)
    is an integer value between 0 and 30, and SAD (Secondary GPIB Address) is an integer value between
    96 and 126 (SAD is optional). For example,

    * `Prologix::192.168.1.110::1234::6`
    * `Prologix::192.168.1.110::1234::6::96`
    * `Prologix::prologix-00-21-69-01-31-04::1234::6` <br/>
       (typically, the hostname is `prologix-<MAC Address>`)

    For the GPIB-USB Controller, the format of the [address][msl.equipment.schema.Connection.address]
    string is `Prologix::PORT::PAD[::SAD]`, where `PORT` is the name of the serial port of the Prologix
    hardware, `PAD` (Primary GPIB Address) is an integer value between 0 and 30, and SAD (Secondary
    GPIB Address) is an integer value between 96 and 126 (SAD is optional). For example,

    * `Prologix::COM3::6`
    * `Prologix::/dev/ttyUSB0::6::112`

    Alternatively, to clearly separate the Prologix hardware address from the GPIB address you may include
    `GPIB::` in the address, for example,

    * `Prologix::192.168.1.110::1234::GPIB::6`
    * `Prologix::COM3::GPIB::22::96`

    Args:
        equipment: An [Equipment][] instance.

    A [Connection][msl.equipment.schema.Connection] instance supports the following _properties_
    for using Prologix hardware, as well as the _properties_ defined in
    [Serial][msl.equipment.interfaces.serial.Serial] (for a GPIB-USB Controller) and in
    [Socket][msl.equipment.interfaces.socket.Socket] (for a GPIB-ETHERNET Controller).

    Attributes: Connection Properties:
        eoi (bool): Whether to assert the End or Identify (EOI) hardware line. _Default: `True`_
        eos (int): GPIB termination character(s) to append to the message that is sent
            to the equipment. _Default: `3`_

            * `0`: CR+LF
            * `1`: CR
            * `2`: LF
            * `3`: no termination

        eot_char (int | str): A user-specified character to append to the reply that the Prologix hardware
            sends back to the computer when `eot_enable` is `True` and EOI is detected. Must have an ASCII
            value &lt;256, e.g., `eot_char=42` appends `*` (ASCII 42) when EOI is detected. _Default: `0`_
        eot_enable (bool): Enable or disable the appending of a user-specified character, `eot_char`,
            when the Prologix hardware sends a reply back to the computer. _Default: `False`_
        escape_characters (bool): Whether to escape the `LF`, `CR`, `ESC` and `+` characters when writing
            a message to the Prologix hardware. _Default: `True`_
        read_tmo_ms (int): The inter-character timeout value, in milliseconds, to be used in the *read*
            command and the *serial_poll* command, i.e., the delay since the last character was read. The
            `read_tmo_ms` timeout value is not to be confused with the total time for which data is
            read. The `read_tmo_ms` value must be between 1 and 3000 milliseconds. _Default: `1000`_

    !!! important
        The Prologix Connection Properties are the same for _all_ equipment that are attached to the
        Prologix hardware. If different equipment require different properties you must manage the
        settings appropriately, such as by writing `++eoi 0` to disable the use of the End or
        Identify line before reading from the equipment and then perhaps writing `++eoi 1`
        to re-enable it afterwards. Only the `escape_characters` property is associated with the
        [Prologix][] instance.
    """
    self._addr: bytes = b""
    super().__init__(equipment)

    assert equipment.connection is not None  # noqa: S101
    info = parse_prologix_address(equipment.connection.address)
    if info is None:
        msg = f"Invalid Prologix address {equipment.connection.address!r}"
        raise ValueError(msg)

    pad = info.pad
    if pad < MIN_PAD_ADDRESS or pad > MAX_PAD_ADDRESS:
        msg = f"Invalid primary GPIB address {pad}, must be in the range [{MIN_PAD_ADDRESS}, {MAX_PAD_ADDRESS}]"
        raise ValueError(msg)

    sad = info.sad
    if sad is not None and (sad < MIN_SAD_ADDRESS or sad > MAX_SAD_ADDRESS):
        msg = f"Invalid secondary GPIB address {sad}, must be in the range [{MIN_SAD_ADDRESS}, {MAX_SAD_ADDRESS}]"
        raise ValueError(msg)

    self._addr = f"++addr {pad}\n".encode() if sad is None else f"++addr {pad} {sad}\n".encode()
    self._pad: int = pad
    self._sad: int | None = sad
    self._plus_plus_read_char: int | str = "eoi"
    self._hw_address: str = info.hw_address

    props = equipment.connection.properties

    try:
        self._controller: PrologixUSB | PrologixEthernet = Prologix._controllers[self._hw_address]
    except KeyError:
        address = f"TCP::{self._hw_address}::{info.enet_port}" if info.enet_port else f"ASRL{self._hw_address}"
        e = Equipment(connection=Connection(address, **props))
        self._controller = PrologixEthernet(e) if info.enet_port else PrologixUSB(e)
        self._controller._str = f"Prologix<{info.hw_address}>"  # noqa: SLF001
        Prologix._controllers[self._hw_address] = self._controller
        Prologix._selected_addresses[self._hw_address] = b""

    # There are two steps involved when writing a message to the equipment
    # 1) Computer -> Prologix
    # 2) Prologix -> Equipment
    # Prologix needs to know when a message has been received in full, but cannot consume
    # any characters that are meant to be passed on to the Equipment. The LF, CR, ESC and +
    # characters are consumed by Prologix. If any of these characters are destined for the
    # Equipment, then it must be preceded by the escape character, ESC (ASCII 27).
    # All un-escaped LF, CR, ESC and + characters in Step 1 are consumed by Prologix (according to the manual).

    self._write_termination: bytes | None = self._controller.write_termination  # termination for Equipment (Step 2)
    self._controller.write_termination = b"\n"  # termination for Prologix (Step 1)

    self._escape_characters: bool = bool(props.get("escape_characters", True))

    _ = self._controller.write("++mode 1\n")  # CONTROLLER mode
    _ = self._controller.write("++auto 0\n")  # write "++read eoi|<char>" before reading

    eoi = 1 if props.get("eoi", True) else 0
    _ = self._controller.write(f"++eoi {eoi}\n")

    eos = props.get("eos", 3)
    _ = self._controller.write(f"++eos {eos}\n")

    self.set_eot_char(props.get("eot_char", 0))
    self.set_eot_enable(props.get("eot_enable", False))

    read_tmo_ms = props.get("read_tmo_ms", 1000)
    _ = self._controller.write(f"++read_tmo_ms {read_tmo_ms}\n")

    self._ensure_gpib_address_selected()

controller property ¤

controller: Serial | Socket

The connection to the Prologix Controller for this equipment.

The returned type depends on whether a GPIB-USB or a GPIB-ETHERNET Controller is used to communicate with the equipment.

Use this property if you want more direct access to the Prologix Controller.

encoding property writable ¤

encoding: str

The encoding that is used for read and write operations.

equipment property ¤

equipment: Equipment

The Equipment associated with the interface.

escape_characters property writable ¤

escape_characters: bool

Whether to escape the \n (ASCII 10), \r (ASCII 13), ESC (ASCII 27) and + (ASCII 43) characters before a write operation.

max_read_size property writable ¤

max_read_size: int

The maximum number of bytes that can be read.

pad property ¤

pad: int

Returns the primary GPIB address.

read_termination property writable ¤

read_termination: bytes | None

The termination character sequence that is used for a read operation.

Reading stops when the equipment stops sending data or the read_termination character sequence is detected. If you set the read_termination to be equal to a variable of type str, it will be encoded as bytes.

rstrip property writable ¤

rstrip: bool

Whether to remove trailing whitespace from read messages.

sad property ¤

sad: int | None

Returns the secondary GPIB address.

timeout property writable ¤

timeout: float | None

The timeout, in seconds, to use for the connection to the Prologix hardware.

This timeout value is not to be confused with the read_tmo_ms command that Prologix Controllers accept. To set the inter-character delay, i.e., the delay since the last character was read or for the serial_poll command, write the ++read_tmo_ms <time> message to the Controller (or define it in the Connection properties).

write_termination property writable ¤

write_termination: bytes | None

The termination character sequence that is appended to write messages.

If you set the write_termination to be equal to a variable of type str, it will be encoded as bytes.

clear ¤

clear() -> None

Send the Selected Device Clear (SDC) command.

Source code in src/msl/equipment/interfaces/prologix.py
248
249
250
251
252
def clear(self) -> None:
    """Send the Selected Device Clear (SDC) command."""
    with self._controller.lock:
        self._ensure_gpib_address_selected()
        _ = self._controller.write(b"++clr\n")

disconnect ¤

disconnect() -> None

Disconnect from the equipment.

Calling this method does not close the underlying Serial or Socket connection to the Prologix Controller since the connection to the Prologix Controller may still be required to send messages to other GPIB devices that are attached to the Controller.

Source code in src/msl/equipment/interfaces/prologix.py
265
266
267
268
269
270
271
272
273
274
275
def disconnect(self) -> None:  # pyright: ignore[reportImplicitOverride]
    """Disconnect from the equipment.

    Calling this method does not close the underlying [Serial][msl.equipment.interfaces.serial.Serial]
    or [Socket][msl.equipment.interfaces.socket.Socket] connection to the Prologix Controller since
    the connection to the Prologix Controller may still be required to send messages to other GPIB
    devices that are attached to the Controller.
    """
    if self._addr:
        self._addr = b""
        super().disconnect()

group_execute_trigger ¤

group_execute_trigger(*addresses: int) -> None

Send the Group Execute Trigger command to equipment at the specified addresses.

Up to 15 addresses may be specified. If no address is specified then the Group Execute Trigger command is issued to the currently-addressed equipment.

Parameters:

Name Type Description Default
addresses int

The primary (and optional secondary) GPIB addresses. If a secondary address is specified then it must follow its corresponding primary address, for example,

  • group_execute_trigger(1, 11, 17) → primary, primary, primary
  • group_execute_trigger(3, 96, 12, 21) → primary, secondary, primary, primary
()
Source code in src/msl/equipment/interfaces/prologix.py
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
def group_execute_trigger(self, *addresses: int) -> None:
    """Send the Group Execute Trigger command to equipment at the specified addresses.

    Up to 15 addresses may be specified. If no address is specified then the
    Group Execute Trigger command is issued to the currently-addressed equipment.

    Args:
        addresses: The primary (and optional secondary) GPIB addresses. If a secondary address is
            specified then it must follow its corresponding primary address, for example,

            * `group_execute_trigger(1, 11, 17)` &#8594; primary, primary, primary
            * `group_execute_trigger(3, 96, 12, 21)` &#8594; primary, secondary, primary, primary
    """
    command = "++trg"
    if addresses:
        command += " " + " ".join(str(a) for a in addresses)
    _ = self._controller.write(command)

interface_clear ¤

interface_clear() -> None

Perform interface clear.

Resets the GPIB bus by asserting the interface clear (IFC) bus line for a duration of at least 150 microseconds.

Source code in src/msl/equipment/interfaces/prologix.py
317
318
319
320
321
322
323
def interface_clear(self) -> None:
    """Perform interface clear.

    Resets the GPIB bus by asserting the *interface clear* (IFC) bus line for a duration of at
    least 150 microseconds.
    """
    _ = self._controller.write(b"++ifc\n")

local ¤

local() -> None

Enables front panel operation of the device, GTL GPIB command.

Source code in src/msl/equipment/interfaces/prologix.py
325
326
327
328
329
def local(self) -> None:
    """Enables front panel operation of the device, `GTL` GPIB command."""
    with self._controller.lock:
        self._ensure_gpib_address_selected()
        _ = self._controller.write(b"++loc\n")

prologix_help ¤

prologix_help() -> list[tuple[str, str]]

Get the command-syntax help for the Prologix hardware.

Returns:

Type Description
list[tuple[str, str]]

The help as a list of (command, description) tuples.

Source code in src/msl/equipment/interfaces/prologix.py
345
346
347
348
349
350
351
352
353
354
355
356
357
358
def prologix_help(self) -> list[tuple[str, str]]:
    """Get the command-syntax help for the Prologix hardware.

    Returns:
        The help as a [list][] of `(command, description)` [tuple][]s.
    """
    h: list[tuple[str, str]] = []
    # ignore the first line in the reply, "The following commands are available:"
    _ = self._controller.query(b"++help\n")
    while True:
        cmd, msg = map(str.strip, self._controller.read().split("--"))
        h.append((cmd, msg))
        if cmd == "++help":  # pragma: no branch
            return h

query ¤

query(
    message: bytes | str,
    *,
    delay: float = 0.0,
    decode: Literal[True] = True,
    dtype: None = None,
    fmt: MessageFormat = ...,
    size: int | None = ...
) -> str
query(
    message: bytes | str,
    *,
    delay: float = 0.0,
    decode: Literal[False] = False,
    dtype: None = None,
    fmt: MessageFormat = ...,
    size: int | None = ...
) -> bytes
query(
    message: bytes | str,
    *,
    delay: float = 0.0,
    decode: bool = ...,
    dtype: MessageDataType = ...,
    fmt: MessageFormat = ...,
    size: int | None = ...
) -> NumpyArray1D
query(
    message: bytes | str,
    *,
    delay: float = 0.0,
    decode: bool = True,
    dtype: MessageDataType | None = None,
    fmt: MessageFormat = None,
    size: int | None = None
) -> bytes | str | NumpyArray1D

Convenience method for performing a write followed by a read.

Parameters:

Name Type Description Default
message bytes | str

The message to write to the equipment.

required
delay float

Time delay, in seconds, to wait between the write and read operations.

0.0
decode bool

Whether to decode the returned message (i.e., convert the message to a str) or keep the message as bytes. Ignored if dtype is not None.

True
dtype MessageDataType | None

The data type of the elements in the returned message. Can be any object that numpy dtype supports. For messages that are of scalar type (i.e., a single number) it is more efficient to not specify dtype but to pass the returned message to the int or float class to convert the message to the appropriate numeric type. See MessageDataType for more details.

None
fmt MessageFormat

The format that the returned message data is in. Ignored if dtype is None. See MessageFormat for more details.

None
size int | None

The number of bytes to read. Ignored if the value is None.

None

Returns:

Type Description
bytes | str | NumpyArray1D

The message from the equipment. If dtype is specified, then the message is returned as an numpy.ndarray, if decode is True then the message is returned as a str, otherwise the message is returned as bytes.

Source code in src/msl/equipment/interfaces/prologix.py
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
def query(
    self,
    message: bytes | str,
    *,
    delay: float = 0.0,
    decode: bool = True,
    dtype: MessageDataType | None = None,
    fmt: MessageFormat = None,
    size: int | None = None,
) -> bytes | str | NumpyArray1D:
    """Convenience method for performing a [write][msl.equipment.interfaces.prologix.Prologix.write]
    followed by a [read][msl.equipment.interfaces.prologix.Prologix.read].

    Args:
        message: The message to write to the equipment.
        delay: Time delay, in seconds, to wait between the _write_ and _read_ operations.
        decode: Whether to decode the returned message (i.e., convert the message to a [str][])
            or keep the message as [bytes][]. Ignored if `dtype` is not `None`.
        dtype: The data type of the elements in the returned message. Can be any object that numpy
            [dtype][numpy.dtype] supports. For messages that are of scalar type (i.e., a single number)
            it is more efficient to not specify `dtype` but to pass the returned message to the
            [int][] or [float][] class to convert the message to the appropriate numeric type.
            See [MessageDataType][msl.equipment._types.MessageDataType] for more details.
        fmt: The format that the returned message data is in. Ignored if `dtype` is `None`.
            See [MessageFormat][msl.equipment._types.MessageFormat] for more details.
        size: The number of bytes to read. Ignored if the value is `None`.

    Returns:
        The message from the equipment. If `dtype` is specified, then the message is
            returned as an [numpy.ndarray][], if `decode` is `True` then the message
            is returned as a [str][], otherwise the message is returned as [bytes][].
    """  # noqa: D205
    if not isinstance(message, bytes):
        message = message.encode(encoding=self._controller.encoding)

    if message.startswith(b"++"):  # message is (probably) for the Prologix hardware
        if not message.endswith(b"\n"):
            message += b"\n"
        with self._controller.lock:
            self._ensure_gpib_address_selected()
            return self._controller.query(message, delay=delay, decode=decode, size=size)

    _ = self.write(message)
    if delay > 0:
        time.sleep(delay)
    if dtype:
        return self.read(dtype=dtype, fmt=fmt, size=size)
    return self.read(decode=decode, size=size)

read ¤

read(
    *,
    decode: Literal[True] = True,
    dtype: None = None,
    fmt: MessageFormat = ...,
    size: int | None = ...
) -> str
read(
    *,
    decode: Literal[False] = False,
    dtype: None = None,
    fmt: MessageFormat = ...,
    size: int | None = ...
) -> bytes
read(
    *,
    decode: bool = ...,
    dtype: MessageDataType = ...,
    fmt: MessageFormat = ...,
    size: int | None = ...
) -> NumpyArray1D
read(
    *,
    decode: bool = True,
    dtype: MessageDataType | None = None,
    fmt: MessageFormat = None,
    size: int | None = None
) -> bytes | str | NumpyArray1D

Read a message from the equipment.

See MessageBased.read() for more details about when this method returns.

Parameters:

Name Type Description Default
decode bool

Whether to decode the message (i.e., convert the message to a str) or keep the message as bytes. Ignored if dtype is not None.

True
dtype MessageDataType | None

The data type of the elements in the returned message. Can be any object that numpy dtype supports. For messages that are of scalar type (i.e., a single number) it is more efficient to not specify dtype but to pass the returned message to the int or float class to convert the message to the appropriate numeric type. See MessageDataType for more details.

None
fmt MessageFormat

The format that the returned message data is in. Ignored if dtype is None. See MessageFormat for more details.

None
size int | None

The number of bytes to read. Ignored if the value is None.

None

Returns:

Type Description
bytes | str | NumpyArray1D

The message from the equipment. If dtype is specified, then the message is returned as a numpy ndarray, if decode is True then the message is returned as a str, otherwise the message is returned as bytes.

Source code in src/msl/equipment/interfaces/prologix.py
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
def read(
    self,
    *,
    decode: bool = True,
    dtype: MessageDataType | None = None,
    fmt: MessageFormat = None,
    size: int | None = None,
) -> bytes | str | NumpyArray1D:
    r"""Read a message from the equipment.

    See [MessageBased.read()][msl.equipment.interfaces.message_based.MessageBased.read] for more
    details about when this method returns.

    !!! note "See Also"
        [set_plus_plus_read_char][msl.equipment.interfaces.prologix.Prologix.set_plus_plus_read_char]

    Args:
        decode: Whether to decode the message (i.e., convert the message to a [str][])
            or keep the message as [bytes][]. Ignored if `dtype` is not `None`.
        dtype: The data type of the elements in the returned message. Can be any object that numpy
            [dtype][numpy.dtype] supports. For messages that are of scalar type (i.e., a single number)
            it is more efficient to not specify `dtype` but to pass the returned message to the
            [int][] or [float][] class to convert the message to the appropriate numeric type.
            See [MessageDataType][msl.equipment._types.MessageDataType] for more details.
        fmt: The format that the returned message data is in. Ignored if `dtype` is `None`.
            See [MessageFormat][msl.equipment._types.MessageFormat] for more details.
        size: The number of bytes to read. Ignored if the value is `None`.

    Returns:
        The message from the equipment. If `dtype` is specified, then the message is returned
            as a numpy [ndarray][numpy.ndarray], if `decode` is `True` then the message
            is returned as a [str][], otherwise the message is returned as [bytes][].
    """
    with self._controller.lock:
        self._ensure_gpib_address_selected()
        _ = self._controller.write(f"++read {self._plus_plus_read_char}\n")
        return self._controller.read(decode=decode, dtype=dtype, fmt=fmt, size=size)  # type: ignore[arg-type]

remote_enable ¤

remote_enable(state: bool) -> None

Whether to enable or disable front panel operation of the device.

Parameters:

Name Type Description Default
state bool

If True, the device goes to remote mode (local lockout), False for local mode.

required
Source code in src/msl/equipment/interfaces/prologix.py
528
529
530
531
532
533
534
535
536
537
538
539
def remote_enable(self, state: bool) -> None:  # noqa: FBT001
    """Whether to enable or disable front panel operation of the device.

    Args:
        state: If `True`, the device goes to remote mode (local lockout), `False` for local mode.
    """
    if state:
        with self._controller.lock:
            self._ensure_gpib_address_selected()
            _ = self._controller.write(b"++llo\n")
    else:
        self.local()

reset_controller ¤

reset_controller() -> None

Performs a power-on reset of the Prologix Controller.

It takes about five seconds for the Controller to reboot.

Source code in src/msl/equipment/interfaces/prologix.py
541
542
543
544
545
546
def reset_controller(self) -> None:
    """Performs a power-on reset of the Prologix Controller.

    It takes about five seconds for the Controller to reboot.
    """
    _ = self._controller.write(b"++rst\n")

serial_poll ¤

serial_poll(pad: int | None = None, sad: int | None = None) -> int

Read status byte / serial poll.

Parameters:

Name Type Description Default
pad int | None

The primary GPIB address to poll. If not specified, uses the primary address of the instantiated class.

None
sad int | None

The secondary GPIB address to poll. If not specified, uses the secondary address of the instantiated class.

None

Returns:

Type Description
int
Source code in src/msl/equipment/interfaces/prologix.py
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
def serial_poll(self, pad: int | None = None, sad: int | None = None) -> int:
    """Read status byte / serial poll.

    Args:
        pad: The primary GPIB address to poll. If not specified, uses the
            primary address of the instantiated class.
        sad: The secondary GPIB address to poll. If not specified, uses the
            secondary address of the instantiated class.

    Returns:
        The [status value](https://linux-gpib.sourceforge.io/doc_html/reference-globals-ibsta.html).
    """
    p = self._pad if pad is None else pad
    s = self._sad if sad is None else sad
    cmd = f"++spoll {p} {s}" if s is not None else f"++spoll {p}"
    try:
        return int(self._controller.query(cmd, decode=False))
    except ValueError:  # pragma: no cover
        return 0

set_eot_char ¤

set_eot_char(char: bytes | str | int) -> None

Set a user-specified character to append to the reply from the Prologix Controller back to the computer.

This character is appended only if eot_enable is True and EOI is detected.

See Also

set_eot_enable

Parameters:

Name Type Description Default
char bytes | str | int

Must be an ASCII value <256, e.g., 42 appends * (ASCII 42) when EOI is detected.

required
Source code in src/msl/equipment/interfaces/prologix.py
582
583
584
585
586
587
588
589
590
591
592
593
def set_eot_char(self, char: bytes | str | int) -> None:
    """Set a user-specified character to append to the reply from the Prologix Controller back to the computer.

    This character is appended only if `eot_enable` is `True` and EOI is detected.

    !!! note "See Also"
        [set_eot_enable][msl.equipment.interfaces.prologix.Prologix.set_eot_enable]

    Args:
        char: Must be an ASCII value &lt;256, e.g., `42` appends `*` (ASCII 42) when EOI is detected.
    """
    _ = self._controller.write(f"++eot_char {_char_to_int(char)}\n")

set_eot_enable ¤

set_eot_enable(enable: bool | int) -> None

Enables or disables the appending of a user-specified character.

See Also

set_eot_char

Parameters:

Name Type Description Default
enable bool | int

Whether to enable or disable the appending of a user-specified character.

required
Source code in src/msl/equipment/interfaces/prologix.py
595
596
597
598
599
600
601
602
603
604
605
def set_eot_enable(self, enable: bool | int) -> None:  # noqa: FBT001
    """Enables or disables the appending of a user-specified character.

    !!! note "See Also"
        [set_eot_char][msl.equipment.interfaces.prologix.Prologix.set_eot_char]

    Args:
        enable: Whether to enable or disable the appending of a user-specified character.
    """
    state = 1 if enable else 0
    _ = self._controller.write(f"++eot_enable {state}\n")

set_plus_plus_read_char ¤

set_plus_plus_read_char(char: bytes | str | int | None = None) -> None

Set the character to send when the ++read eoi|<char> message is written in read.

Parameters:

Name Type Description Default
char bytes | str | int | None

If None then use the EOI hardware line (the ++read eoi message is sent), otherwise ++read <char>. The decimal value of char must be in the range [0..255].

None
Source code in src/msl/equipment/interfaces/prologix.py
607
608
609
610
611
612
613
614
def set_plus_plus_read_char(self, char: bytes | str | int | None = None) -> None:
    """Set the character to send when the `++read eoi|<char>` message is written in [read][msl.equipment.interfaces.prologix.Prologix.read].

    Args:
        char: If `None` then use the EOI hardware line (the `++read eoi` message is sent),
            otherwise `++read <char>`. The decimal value of `char` must be in the range [0..255].
    """  # noqa: E501
    self._plus_plus_read_char = "eoi" if char is None else _char_to_int(char)

trigger ¤

trigger() -> None

Trigger device.

Source code in src/msl/equipment/interfaces/prologix.py
632
633
634
635
def trigger(self) -> None:
    """Trigger device."""
    cmd = f"++trg {self._pad}\n" if self._sad is None else f"++trg {self._pad} {self._sad}\n"
    _ = self._controller.write(cmd)

wait ¤

wait(
    mask: int,
    *,
    delay: float = 0.05,
    pad: int | None = None,
    sad: int | None = None,
    timeout: float | None = None
) -> int

Wait for an event.

Parameters:

Name Type Description Default
mask int

Wait until one of the conditions specified in mask is true. See here for the bit values that the mask supports. If mask=0, then this method will return immediately.

required
delay float

The number of seconds to wait between checking for an event.

0.05
pad int | None

The primary GPIB address to poll. If not specified, uses the primary address of the instantiated class.

None
sad int | None

The secondary GPIB address to poll. If not specified, uses the secondary address of the instantiated class.

None
timeout float | None

The maximum number of seconds to wait before raising TimeoutError if an event has not occurred. A value of None means wait forever.

None

Returns:

Type Description
int
Source code in src/msl/equipment/interfaces/prologix.py
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
def wait(
    self,
    mask: int,
    *,
    delay: float = 0.05,
    pad: int | None = None,
    sad: int | None = None,
    timeout: float | None = None,
) -> int:
    """Wait for an event.

    Args:
        mask: Wait until one of the conditions specified in `mask` is true.
            See [here](https://linux-gpib.sourceforge.io/doc_html/reference-globals-ibsta.html)
            for the bit values that the `mask` supports. If `mask=0`,
            then this method will return immediately.
        delay: The number of seconds to wait between checking for an event.
        pad: The primary GPIB address to poll. If not specified, uses the
            primary address of the instantiated class.
        sad: The secondary GPIB address to poll. If not specified, uses the
            secondary address of the instantiated class.
        timeout: The maximum number of seconds to wait before raising [TimeoutError][]
            if an event has not occurred. A value of `None` means wait forever.

    Returns:
        The [status value](https://linux-gpib.sourceforge.io/doc_html/reference-globals-ibsta.html).
    """
    p = self._pad if pad is None else pad
    s = self._sad if sad is None else sad
    t0 = time.time()
    while True:
        status = self.serial_poll(pad=p, sad=s)
        if (status & mask) or (mask == 0):
            return status

        if timeout and time.time() > t0 + timeout:
            msg = f"An event has not occurred after {timeout} seconds"
            raise TimeoutError(msg)

        time.sleep(delay)

wait_for_srq ¤

wait_for_srq(*, delay: float = 0.05, timeout: float | None = None) -> int

Wait for the SRQ interrupt line to be asserted.

This method will return when the Prologix Controller receives a service request from any device. If there are multiple devices connected to the Prologix Controller, you must determine which device asserted the service request.

Parameters:

Name Type Description Default
delay float

The number of seconds to wait between checking if SRQ has been asserted.

0.05
timeout float | None

The maximum number of seconds to wait before raising TimeoutError if the SRQ line is not asserted. A value of None means wait forever.

None

Returns:

Type Description
int
Source code in src/msl/equipment/interfaces/prologix.py
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
def wait_for_srq(self, *, delay: float = 0.05, timeout: float | None = None) -> int:
    """Wait for the SRQ interrupt line to be asserted.

    This method will return when the Prologix Controller receives a service request
    from *any* device. If there are multiple devices connected to the Prologix Controller,
    you must determine which device asserted the service request.

    Args:
        delay: The number of seconds to wait between checking if SRQ has been asserted.
        timeout: The maximum number of seconds to wait before raising [TimeoutError][]
            if the SRQ line is not asserted. A value of `None` means wait forever.

    Returns:
        The [status value](https://linux-gpib.sourceforge.io/doc_html/reference-globals-ibsta.html).
    """
    t0 = time.time()
    while True:
        if int(self._controller.query(b"++srq\n")) == 1:
            return self.serial_poll()

        if timeout and time.time() > t0 + timeout:
            msg = f"SRQ line has not been asserted after {timeout} seconds"
            raise TimeoutError(msg)

        time.sleep(delay)

write ¤

write(
    message: bytes | str,
    *,
    data: Sequence1D | None = None,
    dtype: MessageDataType = "<f",
    fmt: MessageFormat = "ieee"
) -> int

Write a message to the equipment.

Parameters:

Name Type Description Default
message bytes | str

The message to write to the equipment.

required
data Sequence1D | None

The data to append to message.

None
dtype MessageDataType

The data type to use to convert each element in data to bytes. Ignored if data is None. See MessageDataType for more details.

'<f'
fmt MessageFormat

The format to use to convert data to bytes. Ignored if data is None. See MessageFormat for more details.

'ieee'

Returns:

Type Description
int

The number of bytes written.

Source code in src/msl/equipment/interfaces/prologix.py
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
def write(
    self,
    message: bytes | str,
    *,
    data: Sequence1D | None = None,
    dtype: MessageDataType = "<f",
    fmt: MessageFormat = "ieee",
) -> int:
    """Write a message to the equipment.

    !!! note "See Also"
        [escape_characters][msl.equipment.interfaces.prologix.Prologix.escape_characters]

    Args:
        message: The message to write to the equipment.
        data: The data to append to `message`.
        dtype: The data type to use to convert each element in `data` to bytes. Ignored
            if `data` is `None`. See [MessageDataType][msl.equipment._types.MessageDataType]
            for more details.
        fmt: The format to use to convert `data` to bytes. Ignored if `data` is `None`.
            See [MessageFormat][msl.equipment._types.MessageFormat] for more details.

    Returns:
        The number of bytes written.
    """
    if not isinstance(message, bytes):
        message = message.encode(encoding=self._controller.encoding)

    if message.startswith(b"++"):
        # The message is (probably) for the Prologix hardware
        # Prologix termination is b"\n" not self._write_termination (which is for the Equipment)
        if not message.endswith(b"\n"):
            message += b"\n"
        return self._controller.write(message, data=data, dtype=dtype, fmt=fmt)

    if data is not None:
        message += to_bytes(data, fmt=fmt, dtype=dtype)

    if self._write_termination and not message.endswith(self._write_termination):
        message += self._write_termination

    if self._escape_characters:
        # Escape \n \r ESC + characters so that Prologix does not consume them but passes them on to the Equipment
        # ASCII code ESC is decimal 27 (octal 033, hexadecimal 0x1B)
        message = message.replace(b"\033", b"\033\033")  # must be first
        message = message.replace(b"\n", b"\033\n")
        message = message.replace(b"\r", b"\033\r")
        message = message.replace(b"+", b"\033+")

    with self._controller.lock:
        self._ensure_gpib_address_selected()
        # Add an un-escaped \n for Prologix to know it has received the full message from the Computer
        return self._controller.write(message + b"\n")