Skip to content

Commit 6d6dae2

Browse files
committed
added master , cavity and tune device
1 parent c5bde8a commit 6d6dae2

File tree

3 files changed

+134
-24
lines changed

3 files changed

+134
-24
lines changed

src/dt4acc/custom_tango/ioc/devices/master_clock_device.py

Lines changed: 18 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -95,55 +95,49 @@ def frequency(self, value: float):
9595
@attribute(
9696
name="lattice_info/ref_freq",
9797
dtype=float,
98-
access=AttrWriteType.READ_WRITE,
98+
access=AttrWriteType.READ,
9999
label="Lattice reference frequency",
100100
unit="kHz",
101101
format="%8.1f",
102102
)
103103
def ref_freq(self) -> float:
104-
"""Reference frequency - equivalent to EPICS lattice_info:ref_freq."""
104+
"""Reference frequency - equivalent to EPICS lattice_info:ref_freq (READ-ONLY).
105+
106+
This value is automatically updated when the main frequency is changed.
107+
In EPICS, this is implemented as aIn (analog input - read-only).
108+
"""
105109
return self._ref_freq
106110

107-
@ref_freq.write
108-
def ref_freq(self, value: float):
109-
"""Set reference frequency."""
110-
self._ref_freq = float(value)
111-
logger.info(f"Updated reference frequency to {value}")
112-
113111
@attribute(
114112
name="lattice_info/ref_freq/khz/up",
115113
dtype=int,
116-
access=AttrWriteType.READ_WRITE,
114+
access=AttrWriteType.READ,
117115
label="Lattice ref freq integer part",
118116
unit="kHz",
119117
)
120118
def ref_freq_khz_up(self) -> int:
121-
"""Reference frequency integer part - equivalent to EPICS lattice_info:ref_freq:khz:up."""
119+
"""Reference frequency integer part - equivalent to EPICS lattice_info:ref_freq:khz:up (READ-ONLY).
120+
121+
This value is automatically updated when the main frequency is changed.
122+
In EPICS, this is implemented as longIn (long integer input - read-only).
123+
"""
122124
return self._ref_freq_khz_up
123125

124-
@ref_freq_khz_up.write
125-
def ref_freq_khz_up(self, value: int):
126-
"""Set reference frequency integer part."""
127-
self._ref_freq_khz_up = int(value)
128-
logger.info(f"Updated ref freq integer part to {value}")
129-
130126
@attribute(
131127
name="lattice_info/ref_freq/khz/frac",
132128
dtype=int,
133-
access=AttrWriteType.READ_WRITE,
129+
access=AttrWriteType.READ,
134130
label="Lattice ref freq fractional part",
135131
unit="mHz",
136132
)
137133
def ref_freq_khz_frac(self) -> int:
138-
"""Reference frequency fractional part - equivalent to EPICS lattice_info:ref_freq:khz:frac."""
134+
"""Reference frequency fractional part - equivalent to EPICS lattice_info:ref_freq:khz:frac (READ-ONLY).
135+
136+
This value is automatically updated when the main frequency is changed.
137+
In EPICS, this is implemented as longIn (long integer input - read-only).
138+
"""
139139
return self._ref_freq_khz_frac
140140

141-
@ref_freq_khz_frac.write
142-
def ref_freq_khz_frac(self, value: int):
143-
"""Set reference frequency fractional part."""
144-
self._ref_freq_khz_frac = int(value)
145-
logger.info(f"Updated ref freq fractional part to {value}")
146-
147141
@command(dtype_in=None, doc_in="Reset master clock to initial values")
148142
def reset(self):
149143
"""Reset master clock to initial values."""
Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
import numpy as np
2+
from tango import AttrWriteType, DevState
3+
from tango.server import Device, attribute, command
4+
5+
from ....core.utils.logger import get_logger
6+
7+
logger = get_logger()
8+
9+
10+
class TuneDevice(Device):
11+
"""Tango device for managing tune parameters.
12+
13+
This device matches the EPICS tune PV structure exactly, providing the same
14+
functionality as the EPICS SoftIOC implementation.
15+
16+
Tune devices manage the betatron tune values for x and y planes and a counter.
17+
18+
EPICS PVs:
19+
- TUNECC:x (analog output, precision 9)
20+
- TUNECC:y (analog output, precision 9)
21+
- TUNECC:count (long output)
22+
"""
23+
24+
def init_device(self):
25+
"""Initialize the device with default values matching EPICS tune PV setup."""
26+
Device.init_device(self)
27+
self.set_state(DevState.ON)
28+
29+
# Initialize tune data matching EPICS initialize_tune_pvs()
30+
self._tune_x = 0.0
31+
self._tune_y = 0.0
32+
self._count = 0
33+
34+
logger.info("TuneDevice initialized successfully")
35+
36+
@attribute(
37+
name="TUNECC/x",
38+
dtype=float,
39+
access=AttrWriteType.READ_WRITE,
40+
label="Tune X",
41+
format="%12.9f",
42+
)
43+
def tune_x(self) -> float:
44+
"""Tune value for X plane - equivalent to EPICS TUNECC:x."""
45+
return self._tune_x
46+
47+
@tune_x.write
48+
def tune_x(self, value: float):
49+
"""Set tune X value."""
50+
self._tune_x = float(value)
51+
logger.info(f"Updated tune X to {value}")
52+
53+
@attribute(
54+
name="TUNECC/y",
55+
dtype=float,
56+
access=AttrWriteType.READ_WRITE,
57+
label="Tune Y",
58+
format="%12.9f",
59+
)
60+
def tune_y(self) -> float:
61+
"""Tune value for Y plane - equivalent to EPICS TUNECC:y."""
62+
return self._tune_y
63+
64+
@tune_y.write
65+
def tune_y(self, value: float):
66+
"""Set tune Y value."""
67+
self._tune_y = float(value)
68+
logger.info(f"Updated tune Y to {value}")
69+
70+
@attribute(
71+
name="TUNECC/count",
72+
dtype=int,
73+
access=AttrWriteType.READ_WRITE,
74+
label="Tune count",
75+
)
76+
def count(self) -> int:
77+
"""Tune count - equivalent to EPICS TUNECC:count."""
78+
return self._count
79+
80+
@count.write
81+
def count(self, value: int):
82+
"""Set tune count."""
83+
self._count = int(value)
84+
logger.info(f"Updated tune count to {value}")
85+
86+
@command(dtype_in=None, doc_in="Reset tune values to defaults")
87+
def reset(self):
88+
"""Reset tune values to defaults."""
89+
self._tune_x = 0.0
90+
self._tune_y = 0.0
91+
self._count = 0
92+
logger.info("Tune device reset to default values")
93+
return "Tune device reset to default values"
94+
95+
@command(dtype_in=None, doc_in="Get tune information")
96+
def get_tune_info(self):
97+
"""Get tune information."""
98+
return {
99+
"tune_x": self._tune_x,
100+
"tune_y": self._tune_y,
101+
"count": self._count
102+
}
103+

src/dt4acc/custom_tango/tango_device_setup.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
from dt4acc.custom_tango.ioc.devices.cavity_device import CavityDevice
2828
from dt4acc.custom_tango.ioc.devices.master_clock_device import MasterClockDevice
2929
from dt4acc.custom_tango.ioc.devices.other_pvs_device import OtherPVsDevice
30+
from dt4acc.custom_tango.ioc.devices.tune_device import TuneDevice
3031

3132
logger = get_logger()
3233

@@ -216,6 +217,17 @@ def register_all_devices(server_name="SimpleTangoServer", instance_name="test"):
216217
except Exception as e:
217218
logger.info(f" ⚠️ Cavity device {device_name} already registered: {e}")
218219

220+
# Register Tune device (dedicated device for tune measurements)
221+
db_device_info = DbDevInfo()
222+
db_device_info._class = "TuneDevice"
223+
db_device_info.server = f"{server_name}/{instance_name}"
224+
db_device_info.name = f"{server_name}/{instance_name}/tune_device"
225+
try:
226+
db.add_device(db_device_info)
227+
logger.info(" ✅ Registered Tune device")
228+
except Exception as e:
229+
logger.info(f" ⚠️ Tune device already registered: {e}")
230+
219231
logger.info("✅ All devices registered successfully")
220232
print("✅ All devices registered successfully")
221233

@@ -247,6 +259,7 @@ def get_all_device_classes():
247259
CavityDevice, # Dedicated device for cavity management
248260
MasterClockDevice, # Dedicated device for master clock management
249261
OtherPVsDevice, # Dedicated device for other PVs (dummy, current)
262+
TuneDevice, # Dedicated device for tune measurements
250263
])
251264

252265
logger.info(f"✅ Collected {len(device_classes)} device classes")

0 commit comments

Comments
 (0)