-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathREADME.bsas_only
339 lines (256 loc) · 13.9 KB
/
README.bsas_only
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
1. Introduction
----------------------------------------------------------------
BSAS (Beam Synchronous Acquisition Service) provides timestamp and pulse ID
aligned waveform data to the high-level application. Different from BSA, that
provides the data in separate waveforms, BSAS uses NTTable PV to make a
structured data format in a 2-D table.
There are multiple rows on the NTTable. All data in a row is aligned with a
specific timestamp and pulse ID. Each row corresponds to statistical
calculations made with one of more data points collected between one row and
the other. For example, if 10 data points are in use for the calculations, row1
will contain statistical data from the first 10 points, row2 will contain
statistical data from the next 10 points, and so on.
Of course, if the row contains data from one single data point, then the data
on that row is the straight data itself, without any calculations. We are
calling this case as "non-statistical data".
The number of data points used per row depends on how the rates are configured
for the BSAS service.
There are multiple columns on the NTTable PV: timestamp-seconds,
timestamp-nanoseconds, pulse ID and one or more signal columns. The number of
signal columns is configurable and is always a sub-set of the signals created
with the bsaAdd() and bsaAddSecondary() commands explained in the main README file.
Each signal column is actually a group of 6 columns:
.CNT: number of accumulated samples in the row
for statistical data .CNT >= 2
for non-statistical data .CNT = 1
.VAL: delegate sample (very first sample in the row for the statistical
data)
.AVG: arithmetic mean of the samples
.RMS: standard deviation of the samples
.MIN: minimum value from the samples
.MAX: maximum value from the samples
Before it sounds more confusing, it is better to provide a few examples. Let's
work with the position X signal for the BPM. The PV correspondent to the signal
is, for example, BPM:GUNB:123:X.
Here's the header of the table that will be generated by BSAS with this
example:
secondsPastEpoch | nanoseconds | pulseId | BPM:GUNB:123:X.CNT | BPM:GUNB:123:X.VAL | BPM:GUNB:123:X.AVG | BPM:GUNB:123:X.RMS | BPM:GUNB:123:X.MIN | BPM:GUNB:123:X.MAX
Unless you have a large monitor, the text probably wrapped to another line. So,
just to make it more legible in this README file, allow me to call the entire
BPM:GUNB:123:X PV as just X. This is a better view of the header:
secondsPastEpoch | nanoseconds | pulseId | X.CNT | X.VAL | X.AVG | X.RMS | X.MIN | X.MAX
Let's say that with a given configuration, each row is formed with statistical
data from 10 data points. This would be a table filled with a few rows:
secondsPastEpoch | nanoseconds | pulseId | X.CNT | X.VAL | X.AVG | X.RMS | X.MIN | X.MAX
--------------------------------------------------------------------------------------------
104239 | 660001087 | 96793970000 | 10 | 0.63 | 0.59 | 0.61 | 0.34 | 0.72
104239 | 660010087 | 96793970010 | 10 | 0.56 | 0.57 | 0.60 | 0.41 | 0.65
The BPM has 3 signals: X, Y, and TMIT:
- BPM:GUNB:123:X
- BPM:GUNB:123:Y
- BPM:GUNB:123:TMIT
With just 3 signals, the header will already be huge:
secondsPastEpoch | nanoseconds | pulseId | BPM:GUNB:123:X.CNT | BPM:GUNB:123:X.VAL | BPM:GUNB:123:X.AVG | BPM:GUNB:123:X.RMS | BPM:GUNB:123:X.MIN | BPM:GUNB:123:X.MAX | BPM:GUNB:123:Y.CNT | BPM:GUNB:123:Y.VAL | BPM:GUNB:123:Y.AVG | BPM:GUNB:123:Y.RMS | BPM:GUNB:123:Y.MIN | BPM:GUNB:123:Y.MAX | BPM:GUNB:123:TMIT.CNT | BPM:GUNB:123:TMIT.VAL | BPM:GUNB:123:TMIT.AVG | BPM:GUNB:123:TMIT.RMS | BPM:GUNB:123:TMIT.MIN | BPM:GUNB:123:TMIT.MAX
Once the table gets to 100 rows, you already get 2,100 cells on the table. You
can easily see that the idea for this service is not for a human being to look
at the table and take conclusions.
The idea here is to have a software to read this data and perform data analysis
on it.
Later you will see that bsaDriver provides PVs to configure 4 different
timing filters. Although the PVs reside on the IOC, the records are connected
to a central IOC using the DOL and OMSL fields of each record. This guarantees
that all IOCs running BSAS will run with the same timing filter.
The central configuration is done at the TPG Support IOC and there's a team
that decides how to configure each of the four available filters. There are no
user defined filters, like in BSA and BSSS.
2. Timing filtering and how it affects the counts on a table
----------------------------------------------------------------
Although the timing filters are configured by a responsible team, it's good to
understand how this is done.
There are 3 rates that need to be configured:
- Acquisition Rate: frequency at which the firmware will read a signal.
- Row Advance: frequency at which the statistical calculation stops for the
current row and starts for the next row.
- Table Reset: frequency at which the entire table is replaced with a new
content.
Let's say that we configured the acquisition rate at 1 kHz. This just means
that the firmware will read all signals 1000 times per second. If this is a
BPM, it means that X, Y, and TMIT will be read 1000 times per second.
Now, we configure Row Advance to 100 Hz. This means that the firmware will only
go to the next row after 100 Hz. What happens during this time? 10 data points
are collected for X, Y, and TMIT. So, you can see how this configuration of
rates made the count per row to be 10. The AVG, RMS, MIN, and MAX will be
calculated over these 10 points, and the CNT column will show 10.
Finally, let's configure the Table Reset rate to 1 Hz. What happens during this
1 second? 100 rows are created during 1 second and, then, the entire table
current available to pvget is thrown away and a new table content with new 100
rows are made available. So, the relation between the Row Advance rate and the
Table Reset rate defines how many rows a table will have.
More information about how to view the table with pvget will be shown later.
If you are interested in a complete BSAS design and implementation detail
explanation, please check up the following slide deck:
https://1drv.ms/p/s!AsH0Qpew48nUh7xfkO4-X_lMj48VmA?e=6Ea8FP
3. Automatically copy the list of BSA signals made previously with bsaAdd() and
bsaAddSecondary() to BSAS:
-------------------------------------------------------------------------------
Use the bsasAssociateBsaChannels to make the association with BSA channels.
This command needs to be called anywhere after the bsaAsynDriverConfigure()
command, already explained in the main README file.
# Initialize BSAS driver
# make association with BSA channels: bsasAssociateBsaChannels(<BSA port name>)
bsasAssociateBsaChannels("bsaPort")
*Remark*: the <BSA port name> should be the same string id which was used for
bsaAsynDriverConfigure()
4. Configure table header titles
--------------------------------
As seen previously, BSAS provides a 2-D table with a header. The strings that
represent each header must be configured.
We are naming the header title for each signal as <signal_header>. For each
<signal_header> the following columns will be created:
<signal_header>.CNT, <signal_header>.VAL, <signal_header>.AVG, <signal_header>.RMS, <signal_header>.MIN, <signal_header>.MAX
We've been conventioning to use the DEVICE_PREFIX macro to name header titles.
The DEVICE_PREFIX can be, for example, BPM:LI24:123.
This is the command to configure the header titles:
# bsasBaseName(<BSA key>, <signal_header>)
BSA key is the same key used in bsaAdd() or bsaAddSecondary() commands as described
in the main README file.
Examples:
bsasBaseName("TMITAMC0", "${DEVICE_PREFIX}:TMIT")
bsasBaseName("XFIXEDPAMC0", "${DEVICE_PREFIX}:X")
bsasBaseName("YFIXEDPAMC0", "${DEVICE_PREFIX}:Y")
5. Configure BSAS driver
------------------------
As briefly mentioned in item 1, BSAS can be configured with 4 different timing
filters and, for each timing filter, there's one NTTable with the results of
the statistical calculations. These 4 NTTables are accessed through the pvget
EPICS command.
The NTTable PVs are completely created with C++ code. There's no EPICS database
with macro substitution to load from. When configuring the BSAS driver, the PV
name of the 4 NTTables need to be defined.
Each IOC will have exactly 4 NTTables exposed, independently of how many
devices the IOC is controlling. For example, a BPM IOC can have 2 devices with
2 different PV prefixes, but still, it will publish the same 4 NTTables as an
IOC with a single device.
To handle all the cases we conventioned that the prefix for all NTTables will
be the BSAS prefix, which is unique for each IOC.
# configure BSAS driver: bsasAsynDriverConfigure(<bsas port>, <register path>, <NTTable PV1>, <NTTable PV2>, <NTTable PV3>, <NTTable PV4>)
# Remarks: the ioc shell does NOT allow multiple-line input for a command,
# thus, we need to list up all of the arguments in a single line.
# BSAS_PREFIX can be, for example:
# BSAS:GUNB:BP01:1
# Observe that the instance field must start with 1 and increment only if
# the IOC connects to more than one carrier board. The order of the
# elements is required by convention: SC_DIAG0, SC_BSYD, SC_HXR, SC_SXR.
bsasAsynDriverConfigure("bsasPort", "mmio/AmcCarrierCore/AmcCarrierBsa/Bsas", "${BSAS_PREFIX}:SC_DIAG0", "${BSAS_PREFIX}:SC_BSYD", "${BSAS_PREFIX}:SC_HXR", "${BSAS_PREFIX}:SC_SXR")
<bsas port> can be any string you see fit. You will use <bsas port> later on,
so make sure you give it a meaningful name.
*Remark*: the register path may be different from the example above. It depends
on the application. The example, though, will probably fit most applications.
6. Load BSAS rate control template in st.cmd
---------------------------------------------
This database provides:
- a PV to stop the BSAS service locally.
- PVs with diagnostic data from the firmware.
- PVs used for timing filtering. These PVs are not meant to be altered locally
and should not be shown to the user on the GUIs. These PVs are tied to the
TPG support IOC application with the DOL and OMSL record fields.
There's a hidden ${GLOBAL} macro that defaults to TPG:SYS0:1. This matches the
dev TPG in B34 and also in production. If you are using a different TPG, you
need to redefine ${GLOBAL} with the correct prefix of the TPG.
Example: GLOBAL=TPG:B15:1
# BSAS Destination/Rates Control PVs
# BSAS_PREFIX can be, for example:
# BSAS:GUNB:BP01:1
# Observe that the instance field must start with 1 and increment only if
# the IOC connects to more than one carrier board.
dbLoadRecords("db/bsasCtrl.db", "BSAS=${BSAS_PREFIX},PORT=bsasPort")
Here's how one of the PVs will result with this example:
BSAS:LI24:BP01:1:BSAS_LOCAL -> Disconnects from the global PVs from the TPG
support IOC. This is to be used in case you
want to test specific timing filters
independent of what is configured in TPG.
Activating the BSAS_LOCAL PV will bring a major
alarm so you don't forget to bring it back to
Global after the tests.
All other PVs in this database are the controls of 12 timing filters which are
all integrated with the global control from the TPG Support IOC.
7. Load BSAS channel control (enable/disable, signal filtering) template
------------------------------------------------------------------------
This database provides a mechanism to enable/disable and to select severity
for each signal individually.
Examples of prefixes:
DEVICE1_PREFIX = BPM:GUNB:123
DEVICE2_PREFIX = BPM:GUNB:345
# BSAS Severity Filtering for each signal
dbLoadRecords("db/bsas.db", "DEV=${DEVICE1_PREFIX},PORT=bsasPort,BSAKEY=TMITAMC0,SECN=TMIT")
dbLoadRecords("db/bsas.db", "DEV=${DEVICE1_PREFIX},PORT=bsasPort,BSAKEY=XFIXEDPAMC0,SECN=X")
dbLoadRecords("db/bsas.db", "DEV=${DEVICE1_PREFIX},PORT=bsasPort,BSAKEY=YFIXEDPAMC0,SECN=Y")
dbLoadRecords("db/bsas.db", "DEV=${DEVICE2_PREFIX},PORT=bsasPort,BSAKEY=TMITAMC1,SECN=TMIT")
dbLoadRecords("db/bsas.db", "DEV=${DEVICE2_PREFIX},PORT=bsasPort,BSAKEY=XFIXEDPAMC1,SECN=X")
dbLoadRecords("db/bsas.db", "DEV=${DEVICE2_PREFIX},PORT=bsasPort,BSAKEY=YFIXEDPAMC1,SECN=Y")
This will result in:
BPM:GUNB:123:TMITBSASCHNMASK
BPM:GUNB:123:TMITBSASCHNSEVR
BPM:GUNB:123:XBSASCHNMASK
BPM:GUNB:123:XBSASCHNSEVR
BPM:GUNB:123:YBSASCHNMASK
BPM:GUNB:123:YBSASCHNSEVR
BPM:GUNB:345:TMITBSASCHNMASK
BPM:GUNB:345:TMITBSASCHNSEVR
BPM:GUNB:345:XBSASCHNMASK
BPM:GUNB:345:XBSASCHNSEVR
BPM:GUNB:345:YBSASCHNMASK
BPM:GUNB:345:YBSASCHNSEVR
8. Read out NTTtable
--------------------
First get a PV list in a host:
$ pvlist <host>
Example:
khkim@lcls-dev3 ~ $ pvlist cpu-b084-sp18
BSAS:GUNB:BP01:1:SC_HXR
BSAS:GUNB:BP01:1:SC_SXR
BSAS:GUNB:BP01:1:SC_BSYD
BSAS:GUNB:BP01:1:SC_DIAG0
Check the PV structure:
$ pvinfo <PV name>
Example:
khkim@lcls-dev3 ~ $ pvinfo BSAS:GUNB:BP01:1:SC_HXR
BSAS:GUNB:BP01:1:SC_HXR
Server: 134.79.217.42:5075
Type:
epics:nt/NTTable:1.0
string[] labels
structure value
uint[] secondsPastEpoch
uint[] nanoseconds
ulong[] pulseId
uint[] pv0_cnt
double[] pv0_val
double[] pv0_avg
double[] pv0_rms
double[] pv0_min
double[] pv0_max
uint[] pv1_cnt
double[] pv1_val
double[] pv1_avg
double[] pv1_rms
double[] pv1_min
double[] pv1_max
uint[] pv2_cnt
double[] pv2_val
double[] pv2_avg
double[] pv2_rms
double[] pv2_min
double[] pv2_max
uint[] pv30_cnt
double[] pv30_val
double[] pv30_avg
double[] pv30_rms
double[] pv30_min
double[] pv30_max
Get data from the NTTable PV
$ pvget <PV name>
Example:
pvget BSAS:GUNB:BP01:1:SC_HXR
The result is too big to be added to this README, but the table structure was
already explained in item 1.