Source code for herosdevices.hardware.menlo.beat_loop

"""Base class for a Menlo Systems OFC-stabilization beat-note loop (repetition rate, CEO)."""

from .functional_layer import FunctionalLayerModule


[docs] class BeatLoop(FunctionalLayerModule): """Base for an OFC-stabilization loop that locks a beat note to a target frequency. Covers the `mainControls` shape shared by the OFC's repetition-rate and CEO loops (see :py:class:`~herosdevices.hardware.menlo.RepetitionRate` and :py:class:`~herosdevices.hardware.menlo.CEO`). Both loops also expose a `dds` sub-tree identical in shape to :py:class:`~herosdevices.hardware.menlo.DDS`'s, therefore concrete subclasses mix that in directly (`class RepetitionRate(DDS, BeatLoop)`). """ DEFAULT_OBSERVABLES: dict[str, dict[str, str]] = { "locked": {"path": "mainControls.lock", "unit": ""}, "fast_output_monitor": {"path": "mainControls.fastOutput.monitor", "unit": "V"}, "slow_output_monitor": {"path": "mainControls.slowOutput.monitor", "unit": "V"}, } @property def locked(self) -> bool: """Whether the loop is currently locked.""" return self.ofc.get_node(self._path("mainControls.lock")) @locked.setter def locked(self, locked: bool) -> None: self.ofc.set_node(self._path("mainControls.lock"), locked) @property def fast_output_locked(self) -> bool: """Whether the loop's fast feedback branch is currently locked. Read-only status.""" return self.ofc.get_node(self._path("mainControls.fastOutput.locked")) @property def fast_output_monitor(self) -> float: """Monitor voltage of the loop's fast feedback branch. Read-only.""" return self.ofc.get_node(self._path("mainControls.fastOutput.monitor")) @property def fast_output_setpoint(self) -> float: """Setpoint of the loop's fast feedback branch.""" return self.ofc.get_node(self._path("mainControls.fastOutput.setpoint")) @fast_output_setpoint.setter def fast_output_setpoint(self, setpoint: float) -> None: self.ofc.set_node(self._path("mainControls.fastOutput.setpoint"), setpoint) @property def slow_output_locked(self) -> bool: """Whether the loop's slow feedback branch is currently locked. Read-only status.""" return self.ofc.get_node(self._path("mainControls.slowOutput.locked")) @property def slow_output_monitor(self) -> float: """Monitor voltage of the loop's slow feedback branch. Read-only.""" return self.ofc.get_node(self._path("mainControls.slowOutput.monitor")) @property def slow_output_setpoint(self) -> float: """Setpoint of the loop's slow feedback branch.""" return self.ofc.get_node(self._path("mainControls.slowOutput.setpoint")) @slow_output_setpoint.setter def slow_output_setpoint(self, setpoint: float) -> None: self.ofc.set_node(self._path("mainControls.slowOutput.setpoint"), setpoint)
[docs] def unlock_here(self) -> None: """Unlock the loop and immediately re-engage it at the current beat frequency. Shared with :py:class:`~herosdevices.hardware.menlo.LaserLock`, which uses the same `mainControls.unlockHere` node name. Inferred from context (Menlo's own naming and the sibling `lock`/setpoint nodes) rather than verified against vendor documentation: releases the lock if engaged, then re-engages it using the beat note as it currently stands as the new setpoint, instead of servoing to a previously configured setpoint. """ self.ofc.call_method(self._path("mainControls.unlockHere"))