Skip to content

Commit

Permalink
Merge pull request #844 from lnls-sirius/add-hlfofb
Browse files Browse the repository at this point in the history
Add HL FOFB IOC and devices
  • Loading branch information
anacso17 authored Sep 27, 2022
2 parents 7cdf9b3 + 4008986 commit 3fa26ce
Show file tree
Hide file tree
Showing 14 changed files with 2,475 additions and 89 deletions.
2 changes: 1 addition & 1 deletion siriuspy/siriuspy/VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
2.52.0
2.53.0
34 changes: 34 additions & 0 deletions siriuspy/siriuspy/clientconfigdb/types/si_fastorbcorr_respm.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
"""SI fast orbit correction response matrix configuration.
Values in _template_dict are arbitrary. They are used just to compare with
corresponding values when a new configuration is tried to be inserted in the
servconf database.
"""
from copy import deepcopy as _dcopy


def get_dict():
"""Return configuration type dictionary."""
module_name = __name__.split('.')[-1]
_dict = {
'config_type_name': module_name,
'value': _dcopy(_template),
'check': False,
}
return _dict


# Fast Orbit Correction Response Matrix for Sirius:
# -First bpm in the list is the first seen by the beam during injection
# -First ch in the list is the first seen by the beam during injection
# -First cv in the list is the first seen by the beam during injection
# -RF is the last component;
# -Units: bpm --> um; (ch, cv) --> urad; RF --> Hz
#
# | BPMXi | | Mik ... Mil ... Min | | CHk |
# | ... | = | ... ... ... ... ... | * | ... |
# | BPMYj | | Mjk ... Mjl ... Mjn | | CVl |
# | ... |
# | RFn |

_template = 320*[161*[0.0]]
4 changes: 2 additions & 2 deletions siriuspy/siriuspy/clientconfigdb/types/si_fofb.py
Original file line number Diff line number Diff line change
Expand Up @@ -181,8 +181,8 @@ def get_dict():
'SI-20C3:PS-FCV',
]
_corr_propts = [
[':CtrlLoopKp-SP', 5000000, 0.0], # PI Kp parameter
[':CtrlLoopTi-SP', 300, 0.0], # PI Ti parameter
[':CurrLoopKp-SP', 5000000, 0.0], # current loop Kp parameter
[':CurrLoopTi-SP', 300, 0.0], # current loop Ti parameter
[':CurrGain-SP', 6.25e-5, 0.0], # current gain
[':CurrOffset-SP', 0, 0.0], # current offset
[':VoltGain-SP', 1.12916762036e-4, 0.0], # voltage gain
Expand Down
19 changes: 10 additions & 9 deletions siriuspy/siriuspy/cycle/conn.py
Original file line number Diff line number Diff line change
Expand Up @@ -760,7 +760,7 @@ class FOFBPSCycler:
# NOTE: this could be a class derived from one of the Device classes.

properties = [
'Current-SP', 'Current-Mon', 'PwrState-Sts',
'Current-SP', 'Current-Mon', 'PwrState-Sts', 'FOFBAccClear-Cmd',
'AlarmsAmp-Mon', 'OpMode-Sel', 'OpMode-Sts',
]

Expand Down Expand Up @@ -840,21 +840,17 @@ def is_prepared(self, _, wait=5):
return self.check_current_zero(wait)

def set_opmode_slowref(self):
"""Set OpMode to closed_loop_manual, if needed."""
"""Set OpMode-Sel to manual, if needed."""
if self.check_opmode_slowref(wait=1):
return True
sts = _pv_conn_put(
self['OpMode-Sel'],
_PSConst.OpModeFOFB.closed_loop_manual)
sts = _pv_conn_put(self['OpMode-Sel'], _PSConst.OpModeFOFBSel.manual)
_time.sleep(TIMEOUT_SLEEP)
return sts

def check_opmode_slowref(self, wait=10):
"""Check if OpMode is closed_loop_manual."""
"""Check if OpMode-Sts is manual."""
return _pv_timed_get(
self['OpMode-Sts'],
_PSConst.OpModeFOFB.closed_loop_manual,
wait=wait)
self['OpMode-Sts'], _PSConst.OpModeFOFBSts.manual, wait=wait)

def cycle(self):
"""Cycle. This function may run in a thread."""
Expand All @@ -871,6 +867,11 @@ def check_final_state(self, _):
return _Const.CycleEndStatus.Interlock
return _Const.CycleEndStatus.Ok

def clear_fofbacc(self):
"""Clear FOFB accumulator."""
self['FOFBAccClear-Cmd'].value = 1
return True

def _get_duration_and_waveform(self):
"""Get duration and waveform."""
time, wfm = _fc_get_default_waveform(psname=self.psname)
Expand Down
54 changes: 38 additions & 16 deletions siriuspy/siriuspy/cycle/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -111,18 +111,7 @@ def cyclers(self, new_cyclers):
self._triggers = _get_trigger_by_psname(self._cyclers.keys())

if self._include_sitrims:
# trims psnames
self.trimnames = _PSSearch.get_psnames(
{'sec': 'SI', 'sub': '[0-2][0-9](M|C).*', 'dis': 'PS',
'dev': '(CH|CV|QS|QD.*|QF.*|Q[1-4])'})

# trims triggers
self._si_aux_triggers = [
'SI-Glob:TI-Mags-Skews', 'SI-Glob:TI-Mags-Corrs',
'SI-Glob:TI-Mags-QTrims']
self._triggers.update(self._si_aux_triggers)

# move CV-2 and QS of C2 to trims group, if they are in cyclers
# independent fbp magnets
qs_c2 = _PSSearch.get_psnames(
{'sec': 'SI', 'sub': '[0-2][0-9]C2', 'dis': 'PS',
'dev': 'QS'})
Expand All @@ -132,9 +121,24 @@ def cyclers(self, new_cyclers):
chv_id = _PSSearch.get_psnames(
{'sec': 'SI', 'sub': '[0-2][0-9]S(A|B|P)', 'dis': 'PS',
'dev': 'C(H|V)'})
for psn in qs_c2 + cv2_c2 + chv_id:
indfbp = qs_c2 + cv2_c2 + chv_id
# trims psnames
trimnames = set(_PSSearch.get_psnames(
{'sec': 'SI', 'sub': '[0-2][0-9](M|C|S).*', 'dis': 'PS',
'dev': '(CH|CV|QS|QD.*|QF.*|Q[1-4])'}))
self.trimnames = list(trimnames - set(indfbp))

# trims triggers
self._si_aux_triggers = [
'SI-Glob:TI-Mags-Skews', 'SI-Glob:TI-Mags-Corrs',
'SI-Glob:TI-Mags-QTrims']
self._triggers.update(self._si_aux_triggers)

# move CV-2 and QS of C2 to trims group, if they are in cyclers
for psn in indfbp:
if psn in self._cyclers.keys():
self._aux_cyclers[psn] = self._cyclers.pop(psn)
self.trimnames.append(psn)
else:
self.trimnames = list()

Expand Down Expand Up @@ -764,7 +768,7 @@ def check_pwrsupplies_slowref(self, psnames, timeout=TIMEOUT_CHECK):
for psname, sts in self._checks_result.items():
if sts:
continue
opmdes = 'closed_loop_manual' if 'FC' in psname else 'SlowRef'
opmdes = 'manual' if 'FC' in psname else 'SlowRef'
self._update_log(psname+' is not in '+opmdes+'.', error=True)
status &= False
return status
Expand Down Expand Up @@ -813,6 +817,23 @@ def check_pwrsupplies_current_zero(self, psnames, timeout=TIMEOUT_CHECK):
status &= False
return status

def clear_pwrsupplies_fofbacc(self, psnames):
"""Send clear accumulator command to FOFB power supplies."""
psnames = {
p for p in psnames
if _PSSearch.conv_psname_2_psmodel(p) == 'FOFB_PS'
}
if not psnames:
return

for idx, psname in enumerate(psnames):
cycler = self._get_cycler(psname)
cycler.clear_fofbacc()
if idx % 5 == 4 or idx == len(psnames)-1:
self._update_log(
'Sent clear FOFBAcc command to {0}/{1}'.format(
str(idx+1), str(len(psnames))))

# --- main commands ---

def save_timing_initial_state(self):
Expand Down Expand Up @@ -916,7 +937,7 @@ def cycle_trims(self):

self._update_log('Preparing to cycle CHs, QSs and QTrims...')
trims = _PSSearch.get_psnames({
'sec': 'SI', 'sub': '[0-2][0-9](M|C).*', 'dis': 'PS',
'sec': 'SI', 'sub': '[0-2][0-9](M|C|S).*', 'dis': 'PS',
'dev': '(CH|QS|QD.*|QF.*|Q[1-4])'})
if not self.cycle_trims_subset(trims, timeout=4*TIMEOUT_CHECK):
self._update_log(
Expand All @@ -925,7 +946,7 @@ def cycle_trims(self):

self._update_log('Preparing to cycle CVs...')
trims = _PSSearch.get_psnames({
'sec': 'SI', 'sub': '[0-2][0-9](M|C).*', 'dis': 'PS',
'sec': 'SI', 'sub': '[0-2][0-9](M|C|S).*', 'dis': 'PS',
'dev': 'CV'})
if not self.cycle_trims_subset(trims, timeout=4*TIMEOUT_CHECK):
self._update_log(
Expand Down Expand Up @@ -966,6 +987,7 @@ def cycle(self):
self.set_pwrsupplies_slowref(self.psnames)
if not self.check_pwrsupplies_slowref(self.psnames):
return False
self.clear_pwrsupplies_fofbacc(self.psnames)

# Indicate cycle end
self._update_log('Cycle finished!')
Expand Down
4 changes: 3 additions & 1 deletion siriuspy/siriuspy/devices/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,15 @@

from .bbb import BunchbyBunch
from .blscreen import BeamlineScreen
from .bpm import BPM, FamBPMs
from .bpm import BPM, FamBPMs, BPMLogicalTrigger
from .currinfo import CurrInfoTranspEff, CurrInfoLinear, \
CurrInfoBO, CurrInfoSI, CurrInfoAS
from .dcct import DCCT
from .device import Device, DeviceApp, Devices, DeviceNC
from .egun import EGBias, EGFilament, EGHVPS, EGTriggerPS, EGPulsePS, EGun
from .energy import Energy
from .fofb import FOFBCtrlDCC, BPMDCC, FOFBCtrlRef, FamFOFBControllers, \
FamFastCorrs, HLFOFB
from .ict import ICT, TranspEff
from .ids import IDCorrectors, APU, APUFeedForward
from .injsys import ASPUStandbyHandler, BOPSRampStandbyHandler, \
Expand Down
60 changes: 59 additions & 1 deletion siriuspy/siriuspy/devices/bpm.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@
from threading import Event as _Flag
import numpy as _np

from .device import Device as _Device, Devices as _Devices
from .device import Device as _Device, Devices as _Devices, \
ProptyDevice as _ProptyDevice
from ..diagbeam.bpm.csdev import Const as _csbpm
from ..search import BPMSearch as _BPMSearch
from ..namesys import SiriusPVName as _PVName
Expand Down Expand Up @@ -1086,3 +1087,60 @@ def mturn_wait_update_flags(self, timeout=10) -> int:
def _mturn_set_flag(self, pvname, **kwargs):
_ = kwargs
self._mturn_flags[pvname].set()


class BPMLogicalTrigger(_ProptyDevice):
"""BPM Logical Trigger device."""

_properties = (
'RcvSrc-Sel', 'RcvSrc-Sts',
'RcvInSel-SP', 'RcvInSel-RB',
'TrnSrc-Sel', 'TrnSrc-Sts',
'TrnOutSel-SP', 'TrnOutSel-RB',
)

def __init__(self, bpmname, index):
"""Init."""
if not _BPMSearch.is_valid_devname(bpmname):
raise NotImplementedError(bpmname)
if not 0 <= int(index) <= 23:
raise NotImplementedError(index)
super().__init__(
bpmname, 'TRIGGER'+str(index),
properties=BPMLogicalTrigger._properties)

@property
def receiver_source(self):
"""Receiver source."""
return self['RcvSrc-Sts']

@receiver_source.setter
def receiver_source(self, value):
self['RcvSrc-Sel'] = value

@property
def receiver_in_sel(self):
"""Receiver in selection."""
return self['RcvInSel-RB']

@receiver_in_sel.setter
def receiver_in_sel(self, value):
self['RcvInSel-SP'] = value

@property
def transmitter_source(self):
"""Transmitter source."""
return self['TrnSrc-Sts']

@transmitter_source.setter
def transmitter_source(self, value):
self['TrnSrc-Sel'] = value

@property
def transmitter_out_sel(self):
"""Transmitter out selection."""
return self['TrnOutSel-RB']

@transmitter_out_sel.setter
def transmitter_out_sel(self, value):
self['TrnOutSel-SP'] = value
Loading

0 comments on commit 3fa26ce

Please sign in to comment.