Source code for psj_lib.devices.nv_family.nv_family_channel

"""NV family channel model and capability mapping.

This module defines the shared channel-level capabilities for supported
NV-series amplifiers.
"""

from typing import Awaitable

from ..base.piezo_channel import PiezoChannel
from ..base.capabilities import *
from .capabilities.nv_setpoint import NVSetpoint
from .capabilities.nv_modulation_source import NVModulationSource, NVModulationSourceTypes
from .capabilities.nv_monitor_output import NVMonitorOutputSource, NVMonitorOutput
from .capabilities.nv_status_register import NVStatusRegister

[docs] class NVFamilyChannel(PiezoChannel): """Base channel for NV-series amplifiers. This class provides common channel capabilities across open-loop and closed-loop NV variants. Common capabilities include: - Setpoint and position control/readback - Status register access with NV-specific flag decoding - Modulation source selection - Monitor output routing - Open-loop unit and limit queries Example: >>> channel = device.channels[0] >>> await channel.setpoint.set(25.0) >>> pos = await channel.position.get() >>> status = await channel.status.get() >>> print(pos, status.over_temperature) """ BACKUP_COMMANDS: set[str] = { "monwpa", "setk", "cloop" } """NV channel commands included in backup/restore operations.""" GLOBAL_COMMANDS: set[str] = { "ERROR", "dspvmin", "dspvmax", } """ Commands that should belong to a channel, but the device expects them without a channel ID prefix. Handled specially in the _write method. """ # Capability descriptors setpoint: NVSetpoint = CapabilityDescriptor( NVSetpoint, { NVSetpoint.CMD_SETPOINT: "set", } ) """Channel setpoint capability. Readback value is always the last set value, due to the lack of direct readback for this value in NV devices. Example: >>> await channel.setpoint.set(40.0) >>> target = await channel.setpoint.get() """ position: Position = CapabilityDescriptor( Position, { Position.CMD_POSITION: "rk" } ) """Channel position readback capability. Example: >>> actual = await channel.position.get() """ modulation_source: NVModulationSource = CapabilityDescriptor( NVModulationSource, { NVModulationSource.CMD_SOURCE: "setk" }, sources=NVModulationSourceTypes ) """Channel modulation source selection. Expects :class:`~psj_lib.devices.nv_family.capabilities.nv_modulation_source.NVModulationSourceTypes` values. Readback value is always the last set value, due to the lack of direct readback for this value in NV devices. """ monitor_output: NVMonitorOutput = CapabilityDescriptor( NVMonitorOutput, { NVMonitorOutput.CMD_OUTPUT_SRC: "monwpa" }, sources=NVMonitorOutputSource ) """Analog monitor output source routing. Expects :class:`~psj_lib.devices.nv_family.capabilities.nv_monitor_output.NVMonitorOutputSource` values. Readback value is always the last set value, due to the lack of direct readback for this value in NV devices. """ openloop_unit: Unit = CapabilityDescriptor( Unit, { Unit.CMD_UNIT: "unitol" } ) """Open-loop unit readback capability. Example: >>> unit = await channel.openloop_unit.get() """ openloop_limits: Limits = CapabilityDescriptor( Limits, { Limits.CMD_LOWER_LIMIT: "dspvmin", Limits.CMD_UPPER_LIMIT: "dspvmax" } ) """Open-loop lower and upper limit queries. Example: >>> lower, upper = await channel.openloop_limits.get_range() """ status: Status = CapabilityDescriptor( Status, { Status.CMD_STATUS: "ERROR" }, register_type=NVStatusRegister, ) """NV status register access. Returns :class:`~psj_lib.devices.nv_family.capabilities.nv_status_register.NVStatusRegister` for interpreted per-channel flags. """ async def _write(self, cmd: str, params: list[PiezoChannel.Param] | None) -> Awaitable[list[str]]: """Send channel command, with special handling for global NV status command.""" if not self._write_cb: raise RuntimeError("No write callback defined for this channel.") # Do not send channel ID for some commands if cmd in self.GLOBAL_COMMANDS: return await self._write_cb(None, cmd, params) return await self._write_cb(self._channel_id, cmd, params)