Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 11 additions & 3 deletions sentio_prober_control/Sentio/CommandGroups/ProbeCommandGroup.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
from sentio_prober_control.Sentio.Enumerations import ProbePosition, XyReference, ZReference, ChuckSite
from sentio_prober_control.Sentio.Response import Response
from sentio_prober_control.Sentio.CommandGroups.CommandGroupBase import CommandGroupBase

from sentio_prober_control.Sentio.Compatibility import Compatibility, CompatibilityLevel

class ProbeCommandGroup(CommandGroupBase):
"""This command group contains functions for working with motorized prober.
Expand Down Expand Up @@ -143,7 +143,12 @@ def get_probe_z(self, probe: ProbePosition, ref: ZReference) -> float:
Returns:
The z position in micrometer.
"""
self.comm.send(f"get_positioner_z {probe.to_string()},{ref.to_string()}")

# Note:
# Even in Sentio 24.x the ref parameter is expected in long form! This is why we use
# CompatibilityLevel.Sentio_25_2 here.
self.comm.send(f"get_positioner_z {probe.to_string()},{ref.to_string(CompatibilityLevel.Sentio_25_2)}")

resp = Response.check_resp(self.comm.read_line())
return float(resp.message())

Expand Down Expand Up @@ -225,7 +230,10 @@ def move_probe_z(self, probe: ProbePosition, ref: ZReference, z: float) -> float
The z position after the move in micrometer (from zero).
"""

self.comm.send(f"move_positioner_z {probe.to_string()},{ref.to_string()},{z}")
# Note:
# Even in Sentio 24.x the ref parameter is expected in long form! This is why we use
# CompatibilityLevel.Sentio_25_2 here.
self.comm.send(f"move_positioner_z {probe.to_string()},{ref.to_string(CompatibilityLevel.Sentio_25_2)},{z}")
resp = Response.check_resp(self.comm.read_line())
return float(resp.message())

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
from typing import Tuple


from sentio_prober_control.Sentio.Compatibility import Compatibility, CompatibilityLevel
from sentio_prober_control.Sentio.Enumerations import ProbePosition, UvwAxis, FiberType, CompatibilityLevel
from sentio_prober_control.Sentio.Response import Response
from sentio_prober_control.Sentio.CommandGroups.CommandGroupBase import CommandGroupBase
Expand Down Expand Up @@ -228,8 +228,7 @@ def download_graph_data(self, file_path: str, file_name: str) -> None:
Returns:
A Response object containing the command execution status.
"""
if self.prober.compatibility_level < CompatibilityLevel.Sentio_25:
raise NotImplementedError(f"download_graph_data is not supported in compatibility level {self.prober.compatibility_level}.")
Compatibility.assert_min(CompatibilityLevel.Sentio_25_2)

self.comm.send(f"siph:download_graph_data {file_path}, {file_name}")
Response.check_resp(self.comm.read_line())
Expand Down
38 changes: 38 additions & 0 deletions sentio_prober_control/Sentio/Compatibility.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
from enum import IntEnum


class CompatibilityLevel(IntEnum):
""" Compatibility level of the prober.

The compatibility level is determined at time of instantiating the prober class.
It is used to determine which features are available in the prober. This enum
only contains SENTIO versions which introduces API changes.
"""
Undefined = 0,
Sentio_24 = 1,
Sentio_25_2 = 2


class Compatibility:
"""Compatibility class to determine the compatibility level of the prober.

The compatibility level is determined at time of instantiating the prober class.
It is used to determine which features are available in the prober. This class
only contains SENTIO versions which introduces API changes.
"""

# Default compatibility level is Undefined
level : CompatibilityLevel = CompatibilityLevel.Undefined

@staticmethod
def assert_min(level : CompatibilityLevel) -> None:
"""Asserts that the compatibility level is at least the given level.

Args:
level (CompatibilityLevel): The minimum compatibility level required.

Raises:
RuntimeError: If the current compatibility level is lower than the required level.
"""
if Compatibility.level < level:
raise RuntimeError(f"Compatibility level {Compatibility.level} is lower than required {level}.")
63 changes: 40 additions & 23 deletions sentio_prober_control/Sentio/Enumerations.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@

from deprecated import deprecated

from sentio_prober_control.Sentio.Compatibility import CompatibilityLevel, Compatibility


class AccessLevel(Enum):
"""Specifies a SENTIO access level.

Expand Down Expand Up @@ -376,17 +379,6 @@ def to_string(self):
return switcher.get(self, "Invalid ColorScheme")


class CompatibilityLevel(Enum):
""" Compatibility level of the prober.

The compatibility level is determined at time of instantiating the prober class.
It is used to determine which features are available in the prober.
"""
Undefined = 0,
Sentio_24 = 1,
Sentio_25 = 2


@deprecated(reason="duplicated; use DieCompensationMode instead.")
class Compensation(Enum):
Lateral = 0
Expand Down Expand Up @@ -2056,18 +2048,43 @@ class ZReference(Enum):
Ready = 7
RealPos = 8

def to_string(self):
switcher = {
ZReference.Contact: "C",
ZReference.Separation: "S",
ZReference.Hover: "H",
ZReference.Zero: "Z",
ZReference.Current: "R",
ZReference.Vce1: "VCE01",
ZReference.Vce2: "VCE02",
ZReference.Ready: "Ready",
ZReference.RealPos: "RealPos",
}
def to_string(self, compat_level : CompatibilityLevel = CompatibilityLevel.Undefined) -> str:
if compat_level == CompatibilityLevel.Undefined:
compat_level = Compatibility.level

if compat_level < CompatibilityLevel.Sentio_25_2:
# This is the original implementation for SENTIO <25.2.
# Older versions of SENTIO are inconsistent with what they expect
# as remote command parameters. Most older remote commands accept both
# long and short form of the z reference although some may only work with
# the long form.
switcher = {
ZReference.Contact: "C",
ZReference.Separation: "S",
ZReference.Hover: "H",
ZReference.Zero: "Z",
ZReference.Current: "R",
ZReference.Vce1: "VCE01",
ZReference.Vce2: "VCE02",
ZReference.Ready: "Ready",
ZReference.RealPos: "RealPos",
}
else:
# This is for SENTIO >=25.2.
# Newer versions of SENTIO always accept both long and short versions.
# For clarity the long version is used exclusively.
switcher = {
ZReference.Contact: "Contact",
ZReference.Separation: "Separation",
ZReference.Hover: "Hover",
ZReference.Zero: "Zero",
ZReference.Current: "Current",
ZReference.Vce1: "VCE01",
ZReference.Vce2: "VCE02",
ZReference.Ready: "Ready",
ZReference.RealPos: "RealPos",
}

return switcher.get(self, "Invalid chuck z reference")

@staticmethod
Expand Down
56 changes: 23 additions & 33 deletions sentio_prober_control/Sentio/ProberSentio.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@
ChuckPositionHint,
ChuckSite,
ChuckSpeed,
CompatibilityLevel,
ThetaReference,
DialogButtons,
LoadPosition,
Expand All @@ -28,7 +27,7 @@
XyReference,
ZReference
)

from sentio_prober_control.Sentio.Compatibility import CompatibilityLevel, Compatibility
from sentio_prober_control.Sentio.ProberBase import ProberBase, ProberException
from sentio_prober_control.Sentio.Response import Response
from sentio_prober_control.Communication.CommunicatorBase import CommunicatorBase
Expand Down Expand Up @@ -62,6 +61,7 @@ class SentioCommunicationType(Enum):
Gpib = 1
Visa = 2



class SentioProber(ProberBase):
"""This class represents the SENTIO probe station in python.
Expand Down Expand Up @@ -90,9 +90,7 @@ def __init__(self, comm: CommunicatorBase):
"""
ProberBase.__init__(self, comm)

self.__name = "SentioProber"
self.comm.send("*RCS 1") # switch to the native SENTIO remote command set

# Standard command groups
self.aux: AuxCommandGroup = AuxCommandGroup(self)
self.loader: LoaderCommandGroup = LoaderCommandGroup(self)
self.map: WafermapCommandGroup = WafermapCommandGroup(self)
Expand All @@ -104,16 +102,10 @@ def __init__(self, comm: CommunicatorBase):
self.vision: VisionCommandGroup = VisionCommandGroup(self)
self.setup: SetupCommandGroup = SetupCommandGroup(self)

# Command groups for stages; Only available for Sentio > 25.2
self.scope: StageCommandGroup = StageCommandGroup(self, Stage.Scope, True)
self.chuck: StageCommandGroup = StageCommandGroup(self, Stage.Chuck, False)

# deprecated command groups; may be removed at any time.
# DO NOT USE THEM IN NEW CODE!
self.compensation: CompensationCommandGroup = CompensationCommandGroup(self)
self.__name = "SentioProber"
self.comm.send("*RCS 1") # switch to the native SENTIO remote command set

version : str = self.status.get_version()
self._compatibility_level = CompatibilityLevel.Undefined

# Extract version string
match = re.search(r"Version:\s*([\d\.]+)", version)
Expand All @@ -122,32 +114,30 @@ def __init__(self, comm: CommunicatorBase):
parts = version.split(".")
major = int(parts[0]) if len(parts) > 0 else None
minor = int(parts[1]) if len(parts) > 1 else None
release = int(parts[2]) if len(parts) > 2 else None
if major==24:
self._compatibility_level = CompatibilityLevel.Sentio_24
elif major==25:
self._compatibility_level = CompatibilityLevel.Sentio_25
Compatibility.level = CompatibilityLevel.Sentio_24
elif major==25 and (minor==2 or (minor==1 and release==99)):
Compatibility.level = CompatibilityLevel.Sentio_25_2
else:
self._compatibility_level = CompatibilityLevel.Undefined
Compatibility.level = CompatibilityLevel.Undefined

@property
def compatibility_level(self) -> CompatibilityLevel:
"""Get the compatibility level of the prober.
#
# More command groups not supported by all SENTIO versions.
#

The compatibility level is determined at time of instantiating the prober
class by executing the prober.status.get_verison() command. It is used to
determine which features are available in the probers remote command API.
"""
return self._compatibility_level
# Command groups for stages; Only available for Sentio > 25.2
if Compatibility.level >= CompatibilityLevel.Sentio_25_2:
self.scope: StageCommandGroup = StageCommandGroup(self, Stage.Scope, True)
self.chuck: StageCommandGroup = StageCommandGroup(self, Stage.Chuck, False)

@compatibility_level.setter
def compatibility_level(self, value: CompatibilityLevel) -> None:
"""Set the compatibility level of the prober.
#
# Deprecated command groups
#
# DO NOT USE THEM IN NEW CODE! They will be removed in the future!

self.compensation: CompensationCommandGroup = CompensationCommandGroup(self)

This setter allows overriding the compatibility level of the prober to set it
to a specific version. This can be done to keep compatibility with older
scripts.
"""
self._compatibility_level = value

def abort_command(self, cmd_id: int) -> Response:
"""Stop an ongoing asynchronous remote command.
Expand Down