.. index:: multichannel driver, channel facade, shared controller Multichannel instrument drivers =============================== Some instruments expose several measurement channels through one physical communication session. mpylab represents every logical channel as a normal graph node while a shared controller owns the connection and device-wide state. This pattern is used by: * ``pm_gt_8542c_multichannel`` and ``pm_rs_nrp_multichannel``; * ``pm_lumiloop_lspm_multichannel``; * ``prb_lumiloop_lsprobe_multichannel``. The generic lifecycle and facade infrastructure lives in :mod:`mpylab.device.multichannel_common`. Power-meter quantity conversion is implemented in :mod:`mpylab.device.powermeter_multichannel_common`, while LUMILOOP protocol and waveform helpers remain in :mod:`mpylab.device.lumiloop_multichannel_common`. Controller and facade model --------------------------- Each driver instance is a *facade* for one ``[Channel_N]`` section. Facades for the same physical instrument share one communication session and lock, device-wide frequency and mode settings, and an acquisition generation. The final facade calling ``Quit()`` closes the connection. Shared settings must agree; conflicting facade configuration is rejected. .. index:: acquisition mode; independent, acquisition mode; synchronized Acquisition modes ----------------- ``acquisition`` in ``[Init_Value]`` has two defined values: ``independent`` Every channel request performs its own acquisition. This is the default when the option is omitted. ``synchronized`` One instrument-level acquisition produces a shared snapshot. Facades read their channel from the same generation, independent of call order. A new ``Trigger()`` or repeated read requests a new generation. Synchronized means one grouped instrument cycle. It guarantees exact simultaneous sampling only where the instrument and sensors support it. Unsupported modes raise ``ValueError``. The GT 8542C supports only ``independent``; the R&S NRP groups channels using ``INIT:ALL``. ``GetDataNB(retrigger=...)`` accepts booleans and ``ON/OFF``, ``TRUE/FALSE``, ``YES/NO``, and ``1/0``. Until hardware reports completion, nonblocking drivers return ``(-1, None)``. Common INI structure -------------------- The physical device is configured once in ``[Init_Value]``. Each logical channel has its own section and graph node: .. code-block:: ini [Init_Value] nr_of_channels: 2 acquisition: synchronized [Channel_1] name: Forward unit: dBm [Channel_2] name: Reflected unit: dBm Some drivers use ``channels`` as their native count option. During real operation hardware discovery is authoritative and a mismatch is reported. Virtual operation requires an explicit count. Giga-tronics and R&S power meters --------------------------------- The Giga-tronics 8542C is always a two-channel ``independent`` instrument. The R&S NRP supports one or two configured sensors, verifies their presence, and explicitly maps calculation blocks to sensors, for example ``CALC2`` to ``SENS2``. .. code-block:: ini [Init_Value] gpib: 22 nr_of_channels: 2 acquisition: synchronized measurement_timeout: 60 poll_interval: 0.01 [Channel_1] name: Forward unit: dBm swr1: 1.1 swr2: 1.1 LUMILOOP LSPM ------------- ``meter_serial_number`` selects one LSPM attached to the TCP server. An optional version suffix makes the selection unambiguous. Without it, the currently selected meter is used. Commands address this meter rather than SCPI scope ``0``, which would address all enumerated meters. .. code-block:: ini [Init_Value] visa: TCPIP::127.0.0.1::10001::SOCKET channels: 2 meter_serial_number: 12345:2.0 acquisition: synchronized measurement_duration: 0.1 minimum_samples: 2 ready_timeout: 60 trigger_timeout: 30 LUMILOOP LSProbe ---------------- Server enumeration order is not a stable probe identity. Bind each logical channel using serial number and, where needed, version: .. code-block:: ini [Init_Value] visa: TCPIP::127.0.0.1::10000::SOCKET channels: 2 acquisition: synchronized measurement_duration: 0.1 [Channel_1] name: Probe1 unit: Voverm probe_serial_number: 101 probe_version: 2.0 Once one channel specifies ``probe_serial_number``, every configured probe channel must do so. Results are mapped by identity, not response order. Field-probe interface --------------------- On successful ``GetData()``, every concrete field-probe driver returns ``(status, [probe_x, probe_y, probe_z])``. The three components are :class:`scuq.quantities.Quantity` values in ``V/m`` and always use this order in the probe coordinate system. Mapping and rotation into cell coordinates deliberately happen in the measurement class; see :ref:`en-dot-fieldprobe-orientation`. Real acquisition requires a finite positive correction frequency set through ``SetFreq()``. ``Trigger()`` consistently returns ``(status, 0)``. ``GetDataNB(retrigger=...)`` preserves the same result structure and reads the current value before optionally retriggering. Drivers without a genuinely asynchronous instrument interface use the blocking ``GetData()`` fallback. ``GetBatteryState()`` returns ``(status, value)`` with a relative numeric value or ``None`` when no battery status is available. .. index:: measurement duration, waveform averaging, type-A uncertainty Duration-based LUMILOOP acquisition ----------------------------------- A positive ``measurement_duration`` selects triggered waveform averaging. The number of samples is ``max(minimum_samples, ceil(measurement_duration * sample_rate))``. The effective sample rate is queried from hardware; ``virtual_sample_rate`` is used only in virtual mode. ``ready_timeout`` limits mode readiness and ``trigger_timeout`` limits waveform completion. LSPM samples are converted from dBm to watts before calculating mean and type-A uncertainty. LSProbe components are averaged in V/m; their type-A uncertainty is combined with the non-reducible probe specification. Testing and diagnostics ----------------------- All concrete modules provide a virtual smoke test: .. code-block:: console python -m mpylab.device.pm_gt_8542c_multichannel python -m mpylab.device.pm_rs_nrp_multichannel python -m mpylab.device.pm_lumiloop_lspm_multichannel python -m mpylab.device.prb_lumiloop_lsprobe_multichannel Power-meter INIs can also be opened with ``python -m mpylab.device.powermeter_ui path/to/powermeter.ini``. Before production use, test channel order, nonblocking polling, timeouts, hardware identity mapping, conflicting facade configuration, and shutdown after the final ``Quit()``. See :doc:`driver development `, the :doc:`curated driver API <../../api/drivers>`, and the :doc:`complete API <../../api/full-reference>`.