From 70991a301cc7aa8bccd80916d7c53b48ced958fa Mon Sep 17 00:00:00 2001 From: Alejandro Homs Date: Tue, 26 Nov 2019 15:08:37 +0100 Subject: [PATCH 1/7] CT2: SPEC: support multiple P201 boards --- spec/bliss/ct2.mac | 410 +++++++++++++++++++++++++++++++++++---------- 1 file changed, 322 insertions(+), 88 deletions(-) diff --git a/spec/bliss/ct2.mac b/spec/bliss/ct2.mac index 8f3ea6320d..6143843cc9 100644 --- a/spec/bliss/ct2.mac +++ b/spec/bliss/ct2.mac @@ -1,118 +1,335 @@ -def ct2_config(cnum, type, unit, module, chan) '{ - local mne factor ctrl_dev - global CT2_MAC_HDW[] - ctrl_dev = ct2_ADDR - CT2_MAC_HDW[ctrl_dev]["last"] = CT2_MAC_HDW[ctrl_dev]["t0"] = time() - if (type == "ctrl") { - printf("Using P201 \"%s\" counters\n", ctrl_dev) - return - } - mne = cnt_mne(cnum) - if (chan == 0) { - printf("Configuring \"%s\" as timer\n", mne) - factor = counter_par(cnum, "scale") - tango_put(ctrl_dev, "timer_freq", factor) - tango_put(ctrl_dev, "acq_mode", "IntTrigReadout") - tango_put(ctrl_dev, "acq_point_period", 0) - CT2_MAC_HDW[ctrl_dev]["int_cnt"] = 11 - } -}' +#======================================================================== +# This file is part of the bliss project +# +# Copyright (c) 2015-2019 Beamline Control Unit, ESRF +# Distributed under the GNU LGPLv3. See LICENSE for more info. +#===================================================================== + + +need stlist + +#===================================================================== +# DEBUG / PROFILING +#===================================================================== if (!(whatis("__ct2_profile") & 2)) rdef __ct2_profile \'#$*\' def ct2_profiling '{ if ((whatis("__ct2_profile")>>16) <= 5) { # just a # sign -> off - rdef __ct2_profile "eprintf(\"ct2: %s %s %f \", FnId, addon, y = ((x = time()) - CT2_MAC_HDW[ctrl_dev][\"last\"])); CT2_MAC_HDW[ctrl_dev][\"last\"] = x; if(y > 0.01) eprintf(\"too long \"); eprint" + rdef __ct2_profile "eprintf(\"... CT2: %s %s %f \", FnId, addon, _ct2_y = ((_ct2_x = time()) - CT2_MAC_HDW[ctrl_dev][\"last\"])); CT2_MAC_HDW[ctrl_dev][\"last\"] = _ct2_x; if(_ct2_y > 0.01) eprintf(\"[too long!] \"); addon=\"\" ; eprint" print "CT2 profiling is ON" } else { rdef __ct2_profile \'#$*\' print "CT2 profiling is OFF" } -} -' +}' + +#===================================================================== +# CONFIG +#===================================================================== + +def ct2_config(cnum, type, unit, module, chan) '{ + local FnId addon; FnId="ct2_config" + local mne ctrl_dev + global CT2_MAC_HDW[] + global CT2_MAC_LIST[] + ctrl_dev = ct2_ADDR + + addon =sprintf(" cnum[%s] type[%s] unit[%s] module[%s] chan[%s] ", cnum, type, unit, module, chan) + __ct2_profile + + if (type == "ctrl") { + if (unit <= CT2_MAC_HDW["last_config_unit"]) { + + __ct2_profile " RESET globals" + unglobal CT2_MAC_HDW; global CT2_MAC_HDW[] + CT2_MAC_HDW["timer_list"] = "" + unglobal CT2_MAC_HDW_LAST; global CT2_MAC_HDW_LAST[] + list_init CT2_MAC_LIST + } + + CT2_MAC_HDW["last_config_unit"] = unit + + printf("CT2: Using P201 \"%s\" counters\n", ctrl_dev) + list_add(CT2_MAC_LIST, ctrl_dev) + list_setpar(CT2_MAC_LIST, ctrl_dev, "unit", unit) + list_setpar(CT2_MAC_LIST, ctrl_dev, "master_unit", -1) + list_setpar(CT2_MAC_LIST, ctrl_dev, "int_cnt", 0) + CT2_MAC_HDW[ctrl_dev]["slaves"] = "" + return + } + + if (type == "cnt") { + if (chan == 0) { + mne = cnt_mne(cnum) + local timer_list, sep + printf("CT2: Configuring \"%s\" as timer\n", mne) + list_setpar(CT2_MAC_LIST, ctrl_dev, "int_cnt", 11) + list_setpar(CT2_MAC_LIST, ctrl_dev, "master_unit", unit) + timer_list = CT2_MAC_HDW["timer_list"] + sep = length(timer_list) ? " " : "" + timer_list = sprintf("%s%s%s", timer_list, sep, mne) + CT2_MAC_HDW["timer_list"] = timer_list + return + } + + return + } + printf("CT2: WARNING unknow type=%s, unit=%s\n", type, unit) + return ".error." +}' + + +#===================================================================== +# CMD +#===================================================================== def ct2_cmd(cnum, key, p1, p2) '{ - local chan is_running ctrl_dev acq_chan acq_chan_list[] sep val[] int_cnt - local cnt_idx cnt_i x y FnId - FnId="ct2_cmd" + local FnId addon; FnId="ct2_cmd" + local chan ctrl_dev global CT2_MAC_HDW_LAST[] + + addon =sprintf(" cnum[%s] key[%s] p1[%s] p2[%s] ", cnum, key, p1, p2) + __ct2_profile + + ctrl_dev = ct2_ADDR if (cnum != "..") chan = counter_par(cnum, "channel") if (key == "get_status") { - __ct2_profile key " 1" - is_running = (tango_get(ctrl_dev, "acq_status") == "Running") - __ct2_profile key " 2" - CT2_MAC_HDW[ctrl_dev]["running"] = is_running - return is_running + return ct2_get_status(cnum, ctrl_dev, chan) } else if (key == "prestart_all") { - CT2_MAC_HDW[ctrl_dev]["last"] = CT2_MAC_HDW[ctrl_dev]["t0"] = time() - CT2_MAC_HDW[ctrl_dev]["acq_channels"] = "" - CT2_MAC_HDW[ctrl_dev]["nb_channels"] = 0 - CT2_MAC_HDW_LAST["valid"] = 0 + return ct2_prestart_all(ctrl_dev) } else if (key == "start_one") { - __ct2_profile key " 1" - if (chan != 0) { - acq_chan = CT2_MAC_HDW[ctrl_dev]["acq_channels"] - sep = length(acq_chan) ? " " : "" - acq_chan = sprintf("%s%s%d", acq_chan, sep, chan) - CT2_MAC_HDW[ctrl_dev]["acq_channels"] = acq_chan - cnt_idx = CT2_MAC_HDW[ctrl_dev]["nb_channels"]++ - counter_par(cnum, "counter_idx", cnt_idx, "add") - __ct2_profile key " chan != 0" - } else { - if (p1 != CT2_MAC_HDW[ctrl_dev]["lastp1"]) { - tango_put(ctrl_dev, "acq_expo_time", p1) - CT2_MAC_HDW[ctrl_dev]["lastp1"] = p1 - __ct2_profile key " chan == 0 tango_put expo time" - } - if (CT2_MAC_HDW[ctrl_dev]["acq_channels"] != CT2_MAC_HDW[ctrl_dev]["lastacq_channels"]) { - split(CT2_MAC_HDW[ctrl_dev]["acq_channels"], acq_chan_list) - tango_put(ctrl_dev, "acq_channels", acq_chan_list) - CT2_MAC_HDW[ctrl_dev]["lastacq_channels"] = CT2_MAC_HDW[ctrl_dev]["acq_channels"] - __ct2_profile key " tango_put acq_channels" - } - if (1 != CT2_MAC_HDW[ctrl_dev]["lastacq_nb_points"]) { - tango_put(ctrl_dev, "acq_nb_points", 1) - CT2_MAC_HDW[ctrl_dev]["lastacq_nb_points"] = 1 - __ct2_profile key " tango_put acq_nb_points" - } - tango_io(ctrl_dev, "prepare_acq") - __ct2_profile key " tango_io prepare_acq" - tango_io(ctrl_dev, "start_acq") - __ct2_profile key " tango_io start_acq" - } + return ct2_start_one(cnum, ctrl_dev, chan, p1, p2) } else if (key == "counts") { - __ct2_profile key " 1" - if (!CT2_MAC_HDW_LAST["valid"]) { - tango_get(ctrl_dev, "counters", val) - __ct2_profile key " valid tango_get counters" - int_cnt = CT2_MAC_HDW[ctrl_dev]["int_cnt"] - if (val[int_cnt - 1] != 0) { - cnt_idx = (chan ? chan : int_cnt) - 1 - return val[cnt_idx] - } - TANGO_ERR = -1 - tango_get(ctrl_dev, "data", val) - __ct2_profile key " valid tango_get data " - if (TANGO_ERR != "0") - return -1 - for (cnt_i in val) - CT2_MAC_HDW_LAST[cnt_i] = val[cnt_i] - CT2_MAC_HDW_LAST["valid"] = 1 - } - if (chan) - cnt_idx = counter_par(cnum, "counter_idx") - else - cnt_idx = CT2_MAC_HDW[ctrl_dev]["nb_channels"] - return CT2_MAC_HDW_LAST[cnt_idx] + return ct2_counts(cnum, ctrl_dev, chan, p1) + } else if (key == "halt_one") { + # nothing to do } else if (key == "halt_all") { tango_io(ctrl_dev, "stop_acq") __ct2_profile key " stop_acq " + } else { + printf("CT2: %s WARNING: ignored: %s\n", FnId, key) + } +}' + +#--------------------------------------------------------------------- +#--------------------------------------------------------------------- +def ct2_get_status(cnum, ctrl_dev, chan) '{ + local is_running, nb_timers, timer_list[], i + nb_timers = split(CT2_MAC_HDW["timer_list"], timer_list) + for (i = 0; i < nb_timers; i++) { + local timer_mne, timer_cnum, timer_dev + timer_mne = timer_list[i] + timer_cnum = cnt_num(timer_mne) + timer_dev = counter_par(timer_cnum, "address") + is_running = ct2_get_timer_status(timer_cnum, timer_dev, 0) + if (is_running) + return 1 + } + return 0 +}' + +#--------------------------------------------------------------------- +#--------------------------------------------------------------------- +def ct2_get_timer_status(cnum, ctrl_dev, chan) '{ + local FnId addon; FnId="ct2_get_timer_status" + local is_running + __ct2_profile "(trace 1)" + is_running = (tango_get(ctrl_dev, "acq_status") == "Running") + __ct2_profile "(trace 2)" + CT2_MAC_HDW[ctrl_dev]["running"] = is_running + return is_running +}' + +#--------------------------------------------------------------------- +#--------------------------------------------------------------------- +def ct2_prestart_all(ctrl_dev) '{ + CT2_MAC_HDW[ctrl_dev]["acq_channels"] = "" + CT2_MAC_HDW[ctrl_dev]["nb_channels"] = 0 + CT2_MAC_HDW_LAST[ctrl_dev]["valid"] = 0 +}' + +#--------------------------------------------------------------------- +#--------------------------------------------------------------------- +def ct2_start_one(cnum, ctrl_dev, chan, p1, p2) '{ + local FnId addon; FnId="ct2_start_one" + __ct2_profile "(trace 1)" + if (chan != 0) { + return ct2_start_counter_chan(cnum, ctrl_dev, chan, p1, p2) + } else { + return ct2_start_timer_chan(cnum, ctrl_dev, chan, p1, p2) + } +}' + +#--------------------------------------------------------------------- +#--------------------------------------------------------------------- +def ct2_start_counter_chan(cnum, ctrl_dev, chan, p1, p2) '{ + local FnId addon; FnId ="ct2_start_counter_chan" + local acq_chan, sep, master_idx, master_ctrl, slaves, cnt_idx + local cnt_master, master_ctrl_master, master_ctrl_unit + + acq_chan = CT2_MAC_HDW[ctrl_dev]["acq_channels"] + sep = length(acq_chan) ? " " : "" + acq_chan = sprintf("%s%s%d", acq_chan, sep, chan) + CT2_MAC_HDW[ctrl_dev]["acq_channels"] = acq_chan + cnt_idx = CT2_MAC_HDW[ctrl_dev]["nb_channels"]++ + counter_par(cnum, "counter_idx", cnt_idx, "add") + + cnt_master = list_getpar(CT2_MAC_LIST, ctrl_dev, "master_unit") + if (cnt_master != -1) + return + + master_idx = int(counter_par(cnum, "master")) + master_ctrl = list_item(CT2_MAC_LIST, master_idx + 1) + if (master_ctrl == -1) { + printf("CT2: %s ERROR: CT2 %s master parameter is invalid: %s\n", \ + FnId, ctrl_dev, master_idx) + return ".error." + } + + master_ctrl_master = list_getpar(CT2_MAC_LIST, master_ctrl, "master_unit") + master_ctrl_unit = list_getpar(CT2_MAC_LIST, master_ctrl, "unit") + if (master_ctrl_master!= master_ctrl_unit) { + printf("CT2: %s ERROR: CT2 %s master parameter points to a non-master device %s\n", \ + FnId, ctrl_dev, master_ctrl) + return ".error." + } + + list_setpar(CT2_MAC_LIST, ctrl_dev, "master_unit", master_ctrl_unit) + slaves = CT2_MAC_HDW[master_ctrl]["slaves"] + sep = length(slaves) ? " " : "" + slaves = sprintf("%s%s%s", slaves, sep, ctrl_dev) + CT2_MAC_HDW[master_ctrl]["slaves"] = slaves +}' + +#------------------------------------------------------------------- +#------------------------------------------------------------------- +def ct2_start_timer_chan(cnum, ctrl_dev, chan, p1, p2) '{ + local i nb_timers timer_list[] mne + + ct2_prepare_timer_chan_and_slaves(cnum, ctrl_dev, chan, p1, p2) + + # all the timers are started at once, do nothing if not the last + nb_timers = split(CT2_MAC_HDW["timer_list"], timer_list) + mne = cnt_mne(cnum) + if (mne != timer_list[nb_timers - 1]) + return + + # start all timers in reverse order + for (i = nb_timers - 1; i >= 0; i--) { + local timer_mne, timer_cnum, timer_dev + timer_mne = timer_list[i] + timer_cnum = cnt_num(timer_mne) + timer_dev = counter_par(timer_cnum, "address") + ct2_start_timer_chan_and_slaves(timer_cnum, timer_dev, 0, p1, p2) + } +}' + +#--------------------------------------------------------------------- +#--------------------------------------------------------------------- +def ct2_prepare_timer_chan_and_slaves(cnum, ctrl_dev, chan, p1, p2) '{ + local FnId addon; FnId ="ct2_prepare_timer_chan_and_slaves" + local nb_ctrls, ctrl_list[], i, dev, is_master + local factor, acq_mode, acq_chan_list[] + + nb_ctrls = split(CT2_MAC_HDW[ctrl_dev]["slaves"], ctrl_list) + ctrl_list[nb_ctrls++] = ctrl_dev + + for (i = 0; i < nb_ctrls; i++) { + local acq_mode + dev = ctrl_list[i] + is_master = (dev == ctrl_dev) + factor = counter_par(cnum, "scale") + acq_mode = is_master ? "IntTrigReadout" : "ExtGate" + tango_put(dev, "timer_freq", factor) + tango_put(dev, "acq_mode", acq_mode) + tango_put(dev, "acq_point_period", 0) + tango_put(dev, "acq_expo_time", p1) + __ct2_profile "start_one" " chan == 0 tango_put expo time" + + split(CT2_MAC_HDW[dev]["acq_channels"], acq_chan_list) + tango_put(dev, "acq_channels", acq_chan_list) + __ct2_profile "start_one" " tango_put acq_channels" + + tango_put(dev, "acq_nb_points", 1) + __ct2_profile "start_one" " tango_put acq_nb_points" + + tango_io(dev, "prepare_acq") + __ct2_profile "start_one" " tango_io prepare_acq" } }' + +#--------------------------------------------------------------------- +#--------------------------------------------------------------------- +def ct2_start_timer_chan_and_slaves(cnum, ctrl_dev, chan, p1, p2) '{ + local FnId addon; FnId="ct2_start_timer_chan_and_slaves" + local nb_ctrls, ctrl_list[], i, dev + + nb_ctrls = split(CT2_MAC_HDW[ctrl_dev]["slaves"], ctrl_list) + ctrl_list[nb_ctrls++] = ctrl_dev + + for (i = 0; i < nb_ctrls; i++) { + dev = ctrl_list[i] + tango_io(dev, "start_acq") + __ct2_profile "start_one" " tango_io start_acq" + } +}' + +#--------------------------------------------------------------------- +#--------------------------------------------------------------------- +# counter -> p1 +# 0x01 : This scaler is accumulating seconds +# 0x10 : This scaler is first of several in the unit +# 0x2000000 : This is a NAC_CNTR + +def ct2_counts(cnum, ctrl_dev, chan, p1) '{ + local FnId addon; FnId="ct2_counts" + local cnt_idx + __ct2_profile "(trace 1)" + if (!CT2_MAC_HDW_LAST[ctrl_dev]["valid"]) { + local int_cnt, val, cnt_i + tango_get(ctrl_dev, "counters", val) + int_cnt = list_getpar(CT2_MAC_LIST, ctrl_dev, "int_cnt") + + if (val[int_cnt - 1] != 0) { + addon=sprintf(" ctrl_dev[%s] int_cnt[%s] chan[%s] cnt_idx[%s] p1[%s] ", ctrl_dev, int_cnt, chan, cnt_idx, p1) + __ct2_profile " valid tango_get counters (trace 1)" + cnt_idx = (chan ? chan : int_cnt) - 1 + return val[cnt_idx] + } + + + addon=sprintf(" ctrl_dev[%s] int_cnt[%s] chan[%s] cnt_idx[%s] p1[%s] ", ctrl_dev, int_cnt, chan, cnt_idx, p1) + __ct2_profile " valid tango_get counters (trace 2)" + + TANGO_ERR = -1 + tango_get(ctrl_dev, "data", val) + __ct2_profile " valid tango_get data " + if (TANGO_ERR != "0") + return -1 + for (cnt_i in val) + CT2_MAC_HDW_LAST[ctrl_dev][cnt_i] = val[cnt_i] + CT2_MAC_HDW_LAST[ctrl_dev]["valid"] = 1 + } + if (chan) + cnt_idx = counter_par(cnum, "counter_idx") + else + cnt_idx = CT2_MAC_HDW[ctrl_dev]["nb_channels"] + return CT2_MAC_HDW_LAST[ctrl_dev][cnt_idx] +}' + +#------------------------------------------------------------------- +#------------------------------------------------------------------- def ct2_get(cnum, key, val_arr) '{ + local FnId addon; FnId="ct2_get" local ctrl_dev arr_keys + + addon =sprintf(" cnum[%s] key[%s] ", cnum, key) + __ct2_profile + + ctrl_dev = counter_par(cnum, "address") if (key == "?") { printf("%s\n%s\n%s\n", \ @@ -128,8 +345,16 @@ def ct2_get(cnum, key, val_arr) '{ return tango_get(ctrl_dev, key) } }' + +#--------------------------------------------------------------------- +#--------------------------------------------------------------------- def ct2_put(cnum, key, val) '{ + local FnId addon; FnId="ct2_put" local ctrl_dev mode_str + + addon =sprintf(" cnum[%s] key[%s] val[%s] ", cnum, key, val) + __ct2_profile + ctrl_dev = counter_par(cnum, "address") if (key == "?") { printf("%s\n%s\n%s\n", \ @@ -140,8 +365,16 @@ def ct2_put(cnum, key, val) '{ } return tango_put(ctrl_dev, key, val) }' + +#--------------------------------------------------------------------- +#--------------------------------------------------------------------- def ct2_io(cnum, cmd) '{ + local FnId addon; FnId="ct2_io" local ctrl_dev mode_str val val_arr[] + + addon =sprintf(" cnum[%s] cmd[%s] ", cnum, cmd) + __ct2_profile + ctrl_dev = counter_par(cnum, "address") if (cmd == "?") { printf("%s\n%s\n", \ @@ -151,3 +384,4 @@ def ct2_io(cnum, cmd) '{ } tango_io(ctrl_dev, cmd) }' + -- GitLab From 921a663b4df14a39aae653f8d7d9b78ee83adafe Mon Sep 17 00:00:00 2001 From: Alejandro Homs Puron Date: Thu, 5 Mar 2020 13:58:48 +0100 Subject: [PATCH 2/7] CT2: add acq_channels_data_indexes * Return indexes of acq_channels in (hardware-sorted) data point * Use systematically in SPEC --- bliss/controllers/ct2/device.py | 5 +++++ bliss/tango/servers/ct2_ds/ct2_ds.py | 9 +++++++++ spec/bliss/ct2.mac | 18 ++++++++++++------ 3 files changed, 26 insertions(+), 6 deletions(-) diff --git a/bliss/controllers/ct2/device.py b/bliss/controllers/ct2/device.py index 3d21ba29bf..912e5a9edf 100644 --- a/bliss/controllers/ct2/device.py +++ b/bliss/controllers/ct2/device.py @@ -791,6 +791,11 @@ class CT2(object): def acq_channels(self, acq_channels): self.__acq_channels = acq_channels + @property + def acq_channels_data_indexes(self): + sorted_channels = sorted(self.acq_channels) + return [sorted_channels.index(x) for x in self.acq_channels] + @property def timer_freq(self): return self.__timer_freq diff --git a/bliss/tango/servers/ct2_ds/ct2_ds.py b/bliss/tango/servers/ct2_ds/ct2_ds.py index f57b983431..9ce9e9aef0 100644 --- a/bliss/tango/servers/ct2_ds/ct2_ds.py +++ b/bliss/tango/servers/ct2_ds/ct2_ds.py @@ -176,6 +176,15 @@ class CT2(Device): def acq_channels(self, acq_channels): self.device.acq_channels = acq_channels + @attribute( + dtype=("int16",), + max_dim_x=12, + label="Active channel indexes in data point", + doc="List of indexes in data point (first is 0)", + ) + def acq_channels_data_indexes(self): + return tuple(self.device.acq_channels_data_indexes) + @attribute( dtype="float64", label="Timer clock freq.", diff --git a/spec/bliss/ct2.mac b/spec/bliss/ct2.mac index 6143843cc9..536d1d987f 100644 --- a/spec/bliss/ct2.mac +++ b/spec/bliss/ct2.mac @@ -231,7 +231,7 @@ def ct2_start_timer_chan(cnum, ctrl_dev, chan, p1, p2) '{ #--------------------------------------------------------------------- def ct2_prepare_timer_chan_and_slaves(cnum, ctrl_dev, chan, p1, p2) '{ local FnId addon; FnId ="ct2_prepare_timer_chan_and_slaves" - local nb_ctrls, ctrl_list[], i, dev, is_master + local nb_ctrls, ctrl_list[], i, j, dev, is_master local factor, acq_mode, acq_chan_list[] nb_ctrls = split(CT2_MAC_HDW[ctrl_dev]["slaves"], ctrl_list) @@ -253,6 +253,12 @@ def ct2_prepare_timer_chan_and_slaves(cnum, ctrl_dev, chan, p1, p2) '{ tango_put(dev, "acq_channels", acq_chan_list) __ct2_profile "start_one" " tango_put acq_channels" + # store acq_channels_data_indexes for standard counters + tango_get(dev, "acq_channels_data_indexes", acq_chan_list) + __ct2_profile "start_one" " tango_get acq_channels_data_indexes" + for (j in acq_chan_list) + CT2_MAC_HDW[dev][sprintf("idx_%d", j)] = acq_chan_list[j] + tango_put(dev, "acq_nb_points", 1) __ct2_profile "start_one" " tango_put acq_nb_points" @@ -286,7 +292,7 @@ def ct2_start_timer_chan_and_slaves(cnum, ctrl_dev, chan, p1, p2) '{ def ct2_counts(cnum, ctrl_dev, chan, p1) '{ local FnId addon; FnId="ct2_counts" - local cnt_idx + local cnt_idx, arr_key __ct2_profile "(trace 1)" if (!CT2_MAC_HDW_LAST[ctrl_dev]["valid"]) { local int_cnt, val, cnt_i @@ -313,10 +319,10 @@ def ct2_counts(cnum, ctrl_dev, chan, p1) '{ CT2_MAC_HDW_LAST[ctrl_dev][cnt_i] = val[cnt_i] CT2_MAC_HDW_LAST[ctrl_dev]["valid"] = 1 } - if (chan) - cnt_idx = counter_par(cnum, "counter_idx") - else - cnt_idx = CT2_MAC_HDW[ctrl_dev]["nb_channels"] + # use acq_channels_data_indexes for standard counters, nb_channels for timers + cnt_idx = counter_par(cnum, "counter_idx") + arr_key = chan ? sprintf("idx_%d", cnt_idx) : "nb_channels" + cnt_idx = CT2_MAC_HDW[ctrl_dev][arr_key] return CT2_MAC_HDW_LAST[ctrl_dev][cnt_idx] }' -- GitLab From ddc5ed21e4b8e6112eba967a3bc52d44b173e22c Mon Sep 17 00:00:00 2001 From: Alejandro Homs Puron Date: Fri, 26 Feb 2021 16:52:09 +0100 Subject: [PATCH 3/7] SPEC CT2: remove warning message on ignored commands --- spec/bliss/ct2.mac | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/spec/bliss/ct2.mac b/spec/bliss/ct2.mac index 536d1d987f..f0743a2a43 100644 --- a/spec/bliss/ct2.mac +++ b/spec/bliss/ct2.mac @@ -108,9 +108,7 @@ def ct2_cmd(cnum, key, p1, p2) '{ # nothing to do } else if (key == "halt_all") { tango_io(ctrl_dev, "stop_acq") - __ct2_profile key " stop_acq " - } else { - printf("CT2: %s WARNING: ignored: %s\n", FnId, key) + __ct2_profile key " stop_acq " } }' -- GitLab From 2738d26cca54d52d1b26f538d7fe78e5c92aeebd Mon Sep 17 00:00:00 2001 From: Alejandro Homs Puron Date: Fri, 13 Jul 2018 19:31:03 +0200 Subject: [PATCH 4/7] SPEC CT2: allow multi-point acq. per count: * Timer (sec) master counter is no-longer mandatory (default freq: 1 MHz) * Add acq_mode, acq_nb_points, acq_point_period and status counter parameters * Support disabled counters --- bliss/controllers/ct2/device.py | 5 +- spec/bliss/ct2.mac | 338 ++++++++++++++++++++++---------- 2 files changed, 233 insertions(+), 110 deletions(-) diff --git a/bliss/controllers/ct2/device.py b/bliss/controllers/ct2/device.py index 912e5a9edf..32782c18c7 100644 --- a/bliss/controllers/ct2/device.py +++ b/bliss/controllers/ct2/device.py @@ -26,6 +26,7 @@ import logging import time import numpy import gevent +import math from gevent import select from louie import dispatcher @@ -599,9 +600,9 @@ class CT2(object): timer_cmp, out_cmp = None, None if self.__has_int_exp(): - timer_cmp = int(point_period) + timer_cmp = math.ceil(point_period) if self.output_counter: - out_cmp = int(expo_time) + out_cmp = math.ceil(expo_time) return timer_cmp, out_cmp diff --git a/spec/bliss/ct2.mac b/spec/bliss/ct2.mac index f0743a2a43..e86c83a43d 100644 --- a/spec/bliss/ct2.mac +++ b/spec/bliss/ct2.mac @@ -30,7 +30,7 @@ def ct2_profiling '{ def ct2_config(cnum, type, unit, module, chan) '{ local FnId addon; FnId="ct2_config" - local mne ctrl_dev + local mne, ctrl_dev, all_chan, first_chan, master_str global CT2_MAC_HDW[] global CT2_MAC_LIST[] ctrl_dev = ct2_ADDR @@ -43,42 +43,101 @@ def ct2_config(cnum, type, unit, module, chan) '{ __ct2_profile " RESET globals" unglobal CT2_MAC_HDW; global CT2_MAC_HDW[] - CT2_MAC_HDW["timer_list"] = "" unglobal CT2_MAC_HDW_LAST; global CT2_MAC_HDW_LAST[] list_init CT2_MAC_LIST } CT2_MAC_HDW["last_config_unit"] = unit - printf("CT2: Using P201 \"%s\" counters\n", ctrl_dev) list_add(CT2_MAC_LIST, ctrl_dev) list_setpar(CT2_MAC_LIST, ctrl_dev, "unit", unit) - list_setpar(CT2_MAC_LIST, ctrl_dev, "master_unit", -1) - list_setpar(CT2_MAC_LIST, ctrl_dev, "int_cnt", 0) - CT2_MAC_HDW[ctrl_dev]["slaves"] = "" + list_setpar(CT2_MAC_LIST, ctrl_dev, "master_dev", "") + list_setpar(CT2_MAC_LIST, ctrl_dev, "int_cnt", 11) + list_setpar(CT2_MAC_LIST, ctrl_dev, "acq_mode", "") + list_setpar(CT2_MAC_LIST, ctrl_dev, "acq_expo_time", -1) + list_setpar(CT2_MAC_LIST, ctrl_dev, "acq_point_period", 0) + list_setpar(CT2_MAC_LIST, ctrl_dev, "acq_nb_points", 1) + list_setpar(CT2_MAC_LIST, ctrl_dev, "timer_freq", 1e6) + list_setpar(CT2_MAC_LIST, ctrl_dev, "all_channels", "") return + } else if (type != "cnt") { + printf("CT2: WARNING unknown type=%s, unit=%s\n", type, unit) + return ".error." } - - if (type == "cnt") { - if (chan == 0) { - mne = cnt_mne(cnum) - local timer_list, sep - printf("CT2: Configuring \"%s\" as timer\n", mne) - list_setpar(CT2_MAC_LIST, ctrl_dev, "int_cnt", 11) - list_setpar(CT2_MAC_LIST, ctrl_dev, "master_unit", unit) - timer_list = CT2_MAC_HDW["timer_list"] - sep = length(timer_list) ? " " : "" - timer_list = sprintf("%s%s%s", timer_list, sep, mne) - CT2_MAC_HDW["timer_list"] = timer_list - return + + all_chan = list_getpar(CT2_MAC_LIST, ctrl_dev, "all_channels") + first_chan = (all_chan == "") + mne = cnt_mne(cnum) + all_chan = sprintf("%s%s%s", all_chan, length(all_chan) ? " " : "", mne) + list_setpar(CT2_MAC_LIST, ctrl_dev, "all_channels", all_chan) + + master_str = ct2_check_master(cnum, ctrl_dev, chan) + if (master_str == ".error.") + return ".error." + + if (first_chan) + printf("CT2: Using P201 \"%s\" counters%s\n", ctrl_dev, master_str) + + if (chan == 0) { + printf("CT2: Configuring \"%s\" as timer\n", mne) + list_setpar(CT2_MAC_LIST, ctrl_dev, "timer_freq", \ + counter_par(cnum, "scale")) + } +}' + +def ct2_check_master(cnum, ctrl_dev, chan) '{ + local dev, master_dev, i, prev_master, master_str + + # check for "master" parameter in controller/counter + dev = counter_par(cnum, "master") + if (dev != 0) { + for (i = 1; i <= list_n(CT2_MAC_LIST); i++) + if (list_item(CT2_MAC_LIST, i) == dev) + break + if (i > list_n(CT2_MAC_LIST)) { + printf("CT2: Invalid controller (%s/%s) master: %s\n", \ + cnt_mne(cnum), ctrl_dev, dev) + return ".error." } - - return + if (list_getpar(CT2_MAC_LIST, dev, "master_dev") != dev) { + printf("CT2: %s master points to a slave device %s\n", ctrl_dev, \ + dev) + return ".error." + } + master_dev = dev + } else + master_dev = ctrl_dev + + prev_master = list_getpar(CT2_MAC_LIST, ctrl_dev, "master_dev") + if (prev_master == "") { + list_setpar(CT2_MAC_LIST, ctrl_dev, "master_dev", master_dev) + if (master_dev == ctrl_dev) + master_str = " [Master]" + else + master_str = sprintf(" [Slave of %s]", master_dev) + } else if (prev_master != master_dev) { + printf("CT2: WARNING %s master changed to %s (was %s)\n", ctrl_dev, \ + master_dev, prev_master) + printf("CT2: Is \"master\" a counter parameter? %s\n", \ + "Must be a controller one") + return ".error." } - printf("CT2: WARNING unknow type=%s, unit=%s\n", type, unit) - return ".error." + + return master_str }' +def ct2_get_master_list() '{ + local i, dev, master_list, sep + + master_list = "" + for (i = 0; i < list_n(CT2_MAC_LIST); i++) { + dev = list_item(CT2_MAC_LIST, i + 1) + sep = length(master_list) ? " " : "" + if (list_getpar(CT2_MAC_LIST, dev, "master_dev") == dev) + master_list = sprintf("%s%s%s", master_list, sep, dev) + } + return master_list +}' #===================================================================== # CMD @@ -97,7 +156,7 @@ def ct2_cmd(cnum, key, p1, p2) '{ if (cnum != "..") chan = counter_par(cnum, "channel") if (key == "get_status") { - return ct2_get_status(cnum, ctrl_dev, chan) + return ct2_get_status() } else if (key == "prestart_all") { return ct2_prestart_all(ctrl_dev) } else if (key == "start_one") { @@ -114,15 +173,11 @@ def ct2_cmd(cnum, key, p1, p2) '{ #--------------------------------------------------------------------- #--------------------------------------------------------------------- -def ct2_get_status(cnum, ctrl_dev, chan) '{ - local is_running, nb_timers, timer_list[], i - nb_timers = split(CT2_MAC_HDW["timer_list"], timer_list) - for (i = 0; i < nb_timers; i++) { - local timer_mne, timer_cnum, timer_dev - timer_mne = timer_list[i] - timer_cnum = cnt_num(timer_mne) - timer_dev = counter_par(timer_cnum, "address") - is_running = ct2_get_timer_status(timer_cnum, timer_dev, 0) +def ct2_get_status() '{ + local is_running, nb_masters, master_list[], i + nb_masters = split(ct2_get_master_list(), master_list) + for (i = 0; i < nb_masters; i++) { + is_running = ct2_get_master_status(master_list[i]) if (is_running) return 1 } @@ -131,8 +186,8 @@ def ct2_get_status(cnum, ctrl_dev, chan) '{ #--------------------------------------------------------------------- #--------------------------------------------------------------------- -def ct2_get_timer_status(cnum, ctrl_dev, chan) '{ - local FnId addon; FnId="ct2_get_timer_status" +def ct2_get_master_status(ctrl_dev) '{ + local FnId addon; FnId="ct2_get_master_status" local is_running __ct2_profile "(trace 1)" is_running = (tango_get(ctrl_dev, "acq_status") == "Running") @@ -144,8 +199,17 @@ def ct2_get_timer_status(cnum, ctrl_dev, chan) '{ #--------------------------------------------------------------------- #--------------------------------------------------------------------- def ct2_prestart_all(ctrl_dev) '{ + local nb_chan, i, acq_chan_list[] CT2_MAC_HDW[ctrl_dev]["acq_channels"] = "" CT2_MAC_HDW[ctrl_dev]["nb_channels"] = 0 + CT2_MAC_HDW[ctrl_dev]["act_channels"] = 0 + CT2_MAC_HDW[ctrl_dev]["slaves"] = "" + CT2_MAC_HDW["started_masters"] = 0 + nb_chan = split(list_getpar(CT2_MAC_LIST, ctrl_dev, "all_channels"), \ + acq_chan_list) + for (i = 0; i < nb_chan; i++) + if (!counter_par(cnt_num(acq_chan_list[i]), "disable")) + CT2_MAC_HDW[ctrl_dev]["act_channels"]++ CT2_MAC_HDW_LAST[ctrl_dev]["valid"] = 0 }' @@ -153,98 +217,102 @@ def ct2_prestart_all(ctrl_dev) '{ #--------------------------------------------------------------------- def ct2_start_one(cnum, ctrl_dev, chan, p1, p2) '{ local FnId addon; FnId="ct2_start_one" - __ct2_profile "(trace 1)" - if (chan != 0) { - return ct2_start_counter_chan(cnum, ctrl_dev, chan, p1, p2) - } else { - return ct2_start_timer_chan(cnum, ctrl_dev, chan, p1, p2) - } -}' + local acq_chan, sep, cnt_idx + local nb_chan, acq_chan_list[], all_chan_started + local nb_slaves, slave_list[], i + local master_dev, is_master, slaves, sep -#--------------------------------------------------------------------- -#--------------------------------------------------------------------- -def ct2_start_counter_chan(cnum, ctrl_dev, chan, p1, p2) '{ - local FnId addon; FnId ="ct2_start_counter_chan" - local acq_chan, sep, master_idx, master_ctrl, slaves, cnt_idx - local cnt_master, master_ctrl_master, master_ctrl_unit - - acq_chan = CT2_MAC_HDW[ctrl_dev]["acq_channels"] - sep = length(acq_chan) ? " " : "" - acq_chan = sprintf("%s%s%d", acq_chan, sep, chan) - CT2_MAC_HDW[ctrl_dev]["acq_channels"] = acq_chan - cnt_idx = CT2_MAC_HDW[ctrl_dev]["nb_channels"]++ - counter_par(cnum, "counter_idx", cnt_idx, "add") - - cnt_master = list_getpar(CT2_MAC_LIST, ctrl_dev, "master_unit") - if (cnt_master != -1) - return + __ct2_profile "(trace 1)" - master_idx = int(counter_par(cnum, "master")) - master_ctrl = list_item(CT2_MAC_LIST, master_idx + 1) - if (master_ctrl == -1) { - printf("CT2: %s ERROR: CT2 %s master parameter is invalid: %s\n", \ - FnId, ctrl_dev, master_idx) - return ".error." + if (chan != 0) { + acq_chan = CT2_MAC_HDW[ctrl_dev]["acq_channels"] + sep = length(acq_chan) ? " " : "" + acq_chan = sprintf("%s%s%d", acq_chan, sep, chan) + CT2_MAC_HDW[ctrl_dev]["acq_channels"] = acq_chan + nb_chan = split(acq_chan, acq_chan_list) + cnt_idx = nb_chan - 1 + counter_par(cnum, "counter_idx", cnt_idx, "add") } - master_ctrl_master = list_getpar(CT2_MAC_LIST, master_ctrl, "master_unit") - master_ctrl_unit = list_getpar(CT2_MAC_LIST, master_ctrl, "unit") - if (master_ctrl_master!= master_ctrl_unit) { - printf("CT2: %s ERROR: CT2 %s master parameter points to a non-master device %s\n", \ - FnId, ctrl_dev, master_ctrl) - return ".error." + master_dev = list_getpar(CT2_MAC_LIST, ctrl_dev, "master_dev") + is_master = (master_dev == ctrl_dev) + if (!is_master) { + slaves = CT2_MAC_HDW[master_dev]["slaves"] + nb_slaves = split(slaves, slave_list) + for (i = 0; i < nb_slaves; i++) { + if (slave_list[i] == ctrl_dev) + break + } + if (i == nb_slaves) { + sep = length(slaves) ? " " : "" + slaves = sprintf("%s%s%s", slaves, sep, ctrl_dev) + CT2_MAC_HDW[master_dev]["slaves"] = slaves + } } - list_setpar(CT2_MAC_LIST, ctrl_dev, "master_unit", master_ctrl_unit) - slaves = CT2_MAC_HDW[master_ctrl]["slaves"] - sep = length(slaves) ? " " : "" - slaves = sprintf("%s%s%s", slaves, sep, ctrl_dev) - CT2_MAC_HDW[master_ctrl]["slaves"] = slaves + all_chan_started = (++CT2_MAC_HDW[ctrl_dev]["nb_channels"] == \ + CT2_MAC_HDW[ctrl_dev]["act_channels"]) + if (is_master && all_chan_started) + return ct2_start_master(ctrl_dev, chan, p1, p2) }' #------------------------------------------------------------------- #------------------------------------------------------------------- -def ct2_start_timer_chan(cnum, ctrl_dev, chan, p1, p2) '{ - local i nb_timers timer_list[] mne +def ct2_start_master(ctrl_dev, chan, p1, p2) '{ + local i, nb_masters, master_list[] - ct2_prepare_timer_chan_and_slaves(cnum, ctrl_dev, chan, p1, p2) + ct2_prepare_master_and_slaves(ctrl_dev, chan, p1, p2) - # all the timers are started at once, do nothing if not the last - nb_timers = split(CT2_MAC_HDW["timer_list"], timer_list) - mne = cnt_mne(cnum) - if (mne != timer_list[nb_timers - 1]) + # all the ctrls are started at once, do nothing if not the last + nb_masters = split(ct2_get_master_list(), master_list) + if (++CT2_MAC_HDW["started_masters"] < nb_masters) return - # start all timers in reverse order - for (i = nb_timers - 1; i >= 0; i--) { - local timer_mne, timer_cnum, timer_dev - timer_mne = timer_list[i] - timer_cnum = cnt_num(timer_mne) - timer_dev = counter_par(timer_cnum, "address") - ct2_start_timer_chan_and_slaves(timer_cnum, timer_dev, 0, p1, p2) - } + # start all masters in reverse order + for (i = nb_masters - 1; i >= 0; i--) + ct2_start_master_and_slaves(master_list[i]) }' #--------------------------------------------------------------------- #--------------------------------------------------------------------- -def ct2_prepare_timer_chan_and_slaves(cnum, ctrl_dev, chan, p1, p2) '{ - local FnId addon; FnId ="ct2_prepare_timer_chan_and_slaves" +def ct2_prepare_master_and_slaves(ctrl_dev, chan, p1, p2) '{ + local FnId addon; FnId ="ct2_prepare_master_and_slaves" local nb_ctrls, ctrl_list[], i, j, dev, is_master local factor, acq_mode, acq_chan_list[] + local acq_expo_time, acq_point_period, acq_nb_points + local is_null_point_period, is_trig_readout, needs_point_period nb_ctrls = split(CT2_MAC_HDW[ctrl_dev]["slaves"], ctrl_list) + # start this as the last controller ctrl_list[nb_ctrls++] = ctrl_dev for (i = 0; i < nb_ctrls; i++) { - local acq_mode dev = ctrl_list[i] is_master = (dev == ctrl_dev) - factor = counter_par(cnum, "scale") - acq_mode = is_master ? "IntTrigReadout" : "ExtGate" + factor = list_getpar(CT2_MAC_LIST, dev, "timer_freq") + acq_mode = list_getpar(CT2_MAC_LIST, dev, "acq_mode") + if (acq_mode == "") + acq_mode = is_master ? "IntTrigReadout" : "ExtGate" + acq_expo_time = list_getpar(CT2_MAC_LIST, dev, "acq_expo_time") + if (acq_expo_time == -1) + acq_expo_time = p1 + acq_point_period = list_getpar(CT2_MAC_LIST, dev, "acq_point_period") + acq_nb_points = list_getpar(CT2_MAC_LIST, dev, "acq_nb_points") + is_trig_readout = (acq_mode == "IntTrigReadout") + is_null_point_period = (acq_point_period == 0) + needs_point_period = (!is_trig_readout && (acq_mode != "ExtGate")) + if (is_trig_readout && !is_null_point_period) { + printf("Error: TrigReadout and point_period is not NULL\n") + return ".error." + } else if (needs_point_period && is_null_point_period) { + printf("Error: acq mode is %s and point_period is NULL\n", acq_mode) + return ".error." + } + tango_put(dev, "timer_freq", factor) tango_put(dev, "acq_mode", acq_mode) - tango_put(dev, "acq_point_period", 0) - tango_put(dev, "acq_expo_time", p1) + tango_put(dev, "acq_point_period", acq_point_period) + tango_put(dev, "acq_expo_time", acq_expo_time) __ct2_profile "start_one" " chan == 0 tango_put expo time" split(CT2_MAC_HDW[dev]["acq_channels"], acq_chan_list) @@ -257,7 +325,7 @@ def ct2_prepare_timer_chan_and_slaves(cnum, ctrl_dev, chan, p1, p2) '{ for (j in acq_chan_list) CT2_MAC_HDW[dev][sprintf("idx_%d", j)] = acq_chan_list[j] - tango_put(dev, "acq_nb_points", 1) + tango_put(dev, "acq_nb_points", acq_nb_points) __ct2_profile "start_one" " tango_put acq_nb_points" tango_io(dev, "prepare_acq") @@ -267,8 +335,8 @@ def ct2_prepare_timer_chan_and_slaves(cnum, ctrl_dev, chan, p1, p2) '{ #--------------------------------------------------------------------- #--------------------------------------------------------------------- -def ct2_start_timer_chan_and_slaves(cnum, ctrl_dev, chan, p1, p2) '{ - local FnId addon; FnId="ct2_start_timer_chan_and_slaves" +def ct2_start_master_and_slaves(ctrl_dev) '{ + local FnId addon; FnId="ct2_start_master_and_slaves" local nb_ctrls, ctrl_list[], i, dev nb_ctrls = split(CT2_MAC_HDW[ctrl_dev]["slaves"], ctrl_list) @@ -291,7 +359,9 @@ def ct2_start_timer_chan_and_slaves(cnum, ctrl_dev, chan, p1, p2) '{ def ct2_counts(cnum, ctrl_dev, chan, p1) '{ local FnId addon; FnId="ct2_counts" local cnt_idx, arr_key + local nb_chan, acq_chan_list[] __ct2_profile "(trace 1)" + nb_chan = split(CT2_MAC_HDW[ctrl_dev]["acq_channels"], acq_chan_list) if (!CT2_MAC_HDW_LAST[ctrl_dev]["valid"]) { local int_cnt, val, cnt_i tango_get(ctrl_dev, "counters", val) @@ -304,26 +374,78 @@ def ct2_counts(cnum, ctrl_dev, chan, p1) '{ return val[cnt_idx] } - addon=sprintf(" ctrl_dev[%s] int_cnt[%s] chan[%s] cnt_idx[%s] p1[%s] ", ctrl_dev, int_cnt, chan, cnt_idx, p1) __ct2_profile " valid tango_get counters (trace 2)" TANGO_ERR = -1 - tango_get(ctrl_dev, "data", val) + acq_nb_points = list_getpar(CT2_MAC_LIST, ctrl_dev, "acq_nb_points") + ulong array v[acq_nb_points][nb_chan + 2] + tango_get(ctrl_dev, "data", v) __ct2_profile " valid tango_get data " if (TANGO_ERR != "0") return -1 - for (cnt_i in val) - CT2_MAC_HDW_LAST[ctrl_dev][cnt_i] = val[cnt_i] + for (cnt_i = 0; cnt_i < nb_chan + 2; cnt_i++) + CT2_MAC_HDW_LAST[ctrl_dev][cnt_i] = array_op("sum", v[:][cnt_i]) CT2_MAC_HDW_LAST[ctrl_dev]["valid"] = 1 } # use acq_channels_data_indexes for standard counters, nb_channels for timers - cnt_idx = counter_par(cnum, "counter_idx") - arr_key = chan ? sprintf("idx_%d", cnt_idx) : "nb_channels" - cnt_idx = CT2_MAC_HDW[ctrl_dev][arr_key] + cnt_idx = chan ? counter_par(cnum, "counter_idx") : nb_chan return CT2_MAC_HDW_LAST[ctrl_dev][cnt_idx] }' +#===================================================================== +# PARAM +#===================================================================== + +def ct2_par(cnum, key, action, p1) '{ + local ctrl_dev chan mne val[] int_cnt acq_mode_table[] acq_mode aux_key + mne = cnt_mne(cnum) + + ctrl_dev = ct2_ADDR + if (key == "?") { + printf("%s%s\n", \ + "acq_mode, acq_expo_time, acq_point_period, acq_nb_points, ", \ + "status") + return + } + if (cnum != "..") + chan = counter_par(cnum, "channel") + + if (key == "counter_idx") { + aux_key = sprintf("%s_counter_idx", mne) + if (action == "set") + CT2_MAC_HDW[ctrl_dev][aux_key] = p1 + return CT2_MAC_HDW[ctrl_dev][aux_key] + } else if (key == "status") { + ct2_get(cnum, "counters_status", val) + int_cnt = list_getpar(CT2_MAC_LIST, ctrl_dev, "int_cnt") + cnt_idx = (chan ? chan : int_cnt) - 1 + return val[cnt_idx] + } else if (key == "acq_mode") { + acq_mode_table[0] = "IntTrigReadout" + acq_mode_table[1] = "SoftTrigReadout" + acq_mode_table[2] = "IntTrigSingle" + acq_mode_table[3] = "IntTrigMulti" + acq_mode_table[4] = "ExtTrigSingle" + acq_mode_table[5] = "ExtTrigMulti" + acq_mode_table[6] = "ExtGate" + acq_mode_table[7] = "ExtTrigReadout" + acq_mode_table["nr"] = 8 + if (action == "set") + list_setpar(CT2_MAC_LIST, ctrl_dev, key, acq_mode_table[p1]) + for (acq_mode = 0; acq_mode < acq_mode_table["nr"]; acq_mode++) + if (acq_mode_table[acq_mode] == list_getpar(CT2_MAC_LIST, \ + ctrl_dev, key)) + break + return acq_mode + } else if ((key == "acq_expo_time") || (key == "acq_point_period") || \ + (key == "acq_nb_points")) { + if (action == "set") + list_setpar(CT2_MAC_LIST, ctrl_dev, key, p1) + return list_getpar(CT2_MAC_LIST, ctrl_dev, key) + } +}' + #------------------------------------------------------------------- #------------------------------------------------------------------- def ct2_get(cnum, key, val_arr) '{ -- GitLab From 81b340de6881ce86ae1ec23e90ffaa9b58acb2a2 Mon Sep 17 00:00:00 2001 From: Alejandro Homs Puron Date: Tue, 26 Jan 2021 23:53:42 +0100 Subject: [PATCH 5/7] SPEC CT2: add ct2_list_xxx helpers --- spec/bliss/ct2.mac | 110 +++++++++++++++++++++++++++------------------ 1 file changed, 67 insertions(+), 43 deletions(-) diff --git a/spec/bliss/ct2.mac b/spec/bliss/ct2.mac index e86c83a43d..5fbc6b9dff 100644 --- a/spec/bliss/ct2.mac +++ b/spec/bliss/ct2.mac @@ -24,13 +24,53 @@ def ct2_profiling '{ } }' +#===================================================================== +# LIST STRINGS +#===================================================================== + +def ct2_list_init() '{ + return " " +}' + +def ct2_list_includes(cnt_l, cnt_s) '{ + return (index(cnt_l, sprintf(" %s ", cnt_s)) > 0) +}' + +def ct2_list_add(cnt_l, cnt_s, multi_set) '{ + if (!multi_set && ct2_list_includes(cnt_l, cnt_s)) + return cnt_l + return sprintf("%s%s ", cnt_l, cnt_s) +}' + +def ct2_list_del(cnt_l, cnt_s) '{ + local arr[] cnt_nb cnt_i new_l + if (!ct2_list_includes(cnt_l, cnt_s)) + return cnt_l + new_l = ct2_list_init() + cnt_nb = ct2_list_split(cnt_l, arr) + for (cnt_i = 0; cnt_i < cnt_nb; cnt_i++) + if (arr[cnt_i] != cnt_s) + new_l = ct2_list_add(new_l, arr[cnt_i]) + return new_l +}' + +def ct2_list_n(cnt_l) '{ + local arr[] + return ct2_list_split(cnt_l, arr) +}' + +def ct2_list_split(cnt_l, arr) '{ + return split(substr(cnt_l, 2), arr) +}' + + #===================================================================== # CONFIG #===================================================================== def ct2_config(cnum, type, unit, module, chan) '{ local FnId addon; FnId="ct2_config" - local mne, ctrl_dev, all_chan, first_chan, master_str + local mne, ctrl_dev, chan_l, first_chan, master_str global CT2_MAC_HDW[] global CT2_MAC_LIST[] ctrl_dev = ct2_ADDR @@ -58,18 +98,18 @@ def ct2_config(cnum, type, unit, module, chan) '{ list_setpar(CT2_MAC_LIST, ctrl_dev, "acq_point_period", 0) list_setpar(CT2_MAC_LIST, ctrl_dev, "acq_nb_points", 1) list_setpar(CT2_MAC_LIST, ctrl_dev, "timer_freq", 1e6) - list_setpar(CT2_MAC_LIST, ctrl_dev, "all_channels", "") + list_setpar(CT2_MAC_LIST, ctrl_dev, "all_channels", ct2_list_init()) return } else if (type != "cnt") { printf("CT2: WARNING unknown type=%s, unit=%s\n", type, unit) return ".error." } - all_chan = list_getpar(CT2_MAC_LIST, ctrl_dev, "all_channels") - first_chan = (all_chan == "") + chan_l = list_getpar(CT2_MAC_LIST, ctrl_dev, "all_channels") + first_chan = (chan_l == ct2_list_init()) mne = cnt_mne(cnum) - all_chan = sprintf("%s%s%s", all_chan, length(all_chan) ? " " : "", mne) - list_setpar(CT2_MAC_LIST, ctrl_dev, "all_channels", all_chan) + list_setpar(CT2_MAC_LIST, ctrl_dev, "all_channels", \ + ct2_list_add(chan_l, mne)) master_str = ct2_check_master(cnum, ctrl_dev, chan) if (master_str == ".error.") @@ -127,14 +167,13 @@ def ct2_check_master(cnum, ctrl_dev, chan) '{ }' def ct2_get_master_list() '{ - local i, dev, master_list, sep + local i, dev, master_list - master_list = "" + master_list = ct2_list_init() for (i = 0; i < list_n(CT2_MAC_LIST); i++) { dev = list_item(CT2_MAC_LIST, i + 1) - sep = length(master_list) ? " " : "" if (list_getpar(CT2_MAC_LIST, dev, "master_dev") == dev) - master_list = sprintf("%s%s%s", master_list, sep, dev) + master_list = ct2_list_add(master_list, dev) } return master_list }' @@ -175,7 +214,7 @@ def ct2_cmd(cnum, key, p1, p2) '{ #--------------------------------------------------------------------- def ct2_get_status() '{ local is_running, nb_masters, master_list[], i - nb_masters = split(ct2_get_master_list(), master_list) + nb_masters = ct2_list_split(ct2_get_master_list(), master_list) for (i = 0; i < nb_masters; i++) { is_running = ct2_get_master_status(master_list[i]) if (is_running) @@ -199,14 +238,14 @@ def ct2_get_master_status(ctrl_dev) '{ #--------------------------------------------------------------------- #--------------------------------------------------------------------- def ct2_prestart_all(ctrl_dev) '{ - local nb_chan, i, acq_chan_list[] - CT2_MAC_HDW[ctrl_dev]["acq_channels"] = "" + local nb_chan, i, l, acq_chan_list[] + CT2_MAC_HDW[ctrl_dev]["acq_channels"] = ct2_list_init() CT2_MAC_HDW[ctrl_dev]["nb_channels"] = 0 CT2_MAC_HDW[ctrl_dev]["act_channels"] = 0 - CT2_MAC_HDW[ctrl_dev]["slaves"] = "" + CT2_MAC_HDW[ctrl_dev]["slaves"] = ct2_list_init() CT2_MAC_HDW["started_masters"] = 0 - nb_chan = split(list_getpar(CT2_MAC_LIST, ctrl_dev, "all_channels"), \ - acq_chan_list) + l = list_getpar(CT2_MAC_LIST, ctrl_dev, "all_channels") + nb_chan = ct2_list_split(l, acq_chan_list) for (i = 0; i < nb_chan; i++) if (!counter_par(cnt_num(acq_chan_list[i]), "disable")) CT2_MAC_HDW[ctrl_dev]["act_channels"]++ @@ -217,37 +256,23 @@ def ct2_prestart_all(ctrl_dev) '{ #--------------------------------------------------------------------- def ct2_start_one(cnum, ctrl_dev, chan, p1, p2) '{ local FnId addon; FnId="ct2_start_one" - local acq_chan, sep, cnt_idx - local nb_chan, acq_chan_list[], all_chan_started - local nb_slaves, slave_list[], i - local master_dev, is_master, slaves, sep + local acq_chan, cnt_idx, all_chan_started + local master_dev, is_master, slaves __ct2_profile "(trace 1)" if (chan != 0) { acq_chan = CT2_MAC_HDW[ctrl_dev]["acq_channels"] - sep = length(acq_chan) ? " " : "" - acq_chan = sprintf("%s%s%d", acq_chan, sep, chan) - CT2_MAC_HDW[ctrl_dev]["acq_channels"] = acq_chan - nb_chan = split(acq_chan, acq_chan_list) - cnt_idx = nb_chan - 1 + cnt_idx = ct2_list_n(acq_chan) + CT2_MAC_HDW[ctrl_dev]["acq_channels"] = ct2_list_add(acq_chan, chan) counter_par(cnum, "counter_idx", cnt_idx, "add") } master_dev = list_getpar(CT2_MAC_LIST, ctrl_dev, "master_dev") is_master = (master_dev == ctrl_dev) if (!is_master) { - slaves = CT2_MAC_HDW[master_dev]["slaves"] - nb_slaves = split(slaves, slave_list) - for (i = 0; i < nb_slaves; i++) { - if (slave_list[i] == ctrl_dev) - break - } - if (i == nb_slaves) { - sep = length(slaves) ? " " : "" - slaves = sprintf("%s%s%s", slaves, sep, ctrl_dev) - CT2_MAC_HDW[master_dev]["slaves"] = slaves - } + slaves = ct2_list_add(CT2_MAC_HDW[master_dev]["slaves"], ctrl_dev) + CT2_MAC_HDW[master_dev]["slaves"] = slaves } all_chan_started = (++CT2_MAC_HDW[ctrl_dev]["nb_channels"] == \ @@ -264,7 +289,7 @@ def ct2_start_master(ctrl_dev, chan, p1, p2) '{ ct2_prepare_master_and_slaves(ctrl_dev, chan, p1, p2) # all the ctrls are started at once, do nothing if not the last - nb_masters = split(ct2_get_master_list(), master_list) + nb_masters = ct2_list_split(ct2_get_master_list(), master_list) if (++CT2_MAC_HDW["started_masters"] < nb_masters) return @@ -282,7 +307,7 @@ def ct2_prepare_master_and_slaves(ctrl_dev, chan, p1, p2) '{ local acq_expo_time, acq_point_period, acq_nb_points local is_null_point_period, is_trig_readout, needs_point_period - nb_ctrls = split(CT2_MAC_HDW[ctrl_dev]["slaves"], ctrl_list) + nb_ctrls = ct2_list_split(CT2_MAC_HDW[ctrl_dev]["slaves"], ctrl_list) # start this as the last controller ctrl_list[nb_ctrls++] = ctrl_dev @@ -315,7 +340,7 @@ def ct2_prepare_master_and_slaves(ctrl_dev, chan, p1, p2) '{ tango_put(dev, "acq_expo_time", acq_expo_time) __ct2_profile "start_one" " chan == 0 tango_put expo time" - split(CT2_MAC_HDW[dev]["acq_channels"], acq_chan_list) + ct2_list_split(CT2_MAC_HDW[dev]["acq_channels"], acq_chan_list) tango_put(dev, "acq_channels", acq_chan_list) __ct2_profile "start_one" " tango_put acq_channels" @@ -339,7 +364,7 @@ def ct2_start_master_and_slaves(ctrl_dev) '{ local FnId addon; FnId="ct2_start_master_and_slaves" local nb_ctrls, ctrl_list[], i, dev - nb_ctrls = split(CT2_MAC_HDW[ctrl_dev]["slaves"], ctrl_list) + nb_ctrls = ct2_list_split(CT2_MAC_HDW[ctrl_dev]["slaves"], ctrl_list) ctrl_list[nb_ctrls++] = ctrl_dev for (i = 0; i < nb_ctrls; i++) { @@ -358,10 +383,9 @@ def ct2_start_master_and_slaves(ctrl_dev) '{ def ct2_counts(cnum, ctrl_dev, chan, p1) '{ local FnId addon; FnId="ct2_counts" - local cnt_idx, arr_key - local nb_chan, acq_chan_list[] + local cnt_idx, arr_key, nb_chan __ct2_profile "(trace 1)" - nb_chan = split(CT2_MAC_HDW[ctrl_dev]["acq_channels"], acq_chan_list) + nb_chan = ct2_list_n(CT2_MAC_HDW[ctrl_dev]["acq_channels"]) if (!CT2_MAC_HDW_LAST[ctrl_dev]["valid"]) { local int_cnt, val, cnt_i tango_get(ctrl_dev, "counters", val) -- GitLab From d70693f2684500922d378a753b0c3557d4a2f0d5 Mon Sep 17 00:00:00 2001 From: Alejandro Homs Puron Date: Mon, 16 Jul 2018 16:07:08 +0200 Subject: [PATCH 6/7] CT2: add integrator_channels support: do not reset counter on EOC * Support timer-only (no counter) configurations --- bliss/controllers/ct2/device.py | 21 +++++- bliss/tango/servers/ct2_ds/ct2_ds.py | 13 ++++ spec/bliss/ct2.mac | 102 +++++++++++++++++++-------- 3 files changed, 106 insertions(+), 30 deletions(-) diff --git a/bliss/controllers/ct2/device.py b/bliss/controllers/ct2/device.py index 32782c18c7..6db9c045b3 100644 --- a/bliss/controllers/ct2/device.py +++ b/bliss/controllers/ct2/device.py @@ -152,6 +152,7 @@ class CT2(object): self.__acq_point_period = None self.__acq_nb_points = 1 self.__acq_channels = () + self.__integrator_channels = None self.__timer_freq = 12.5E6 self.__event_loop = None self.__trigger_on_start = True @@ -524,7 +525,7 @@ class CT2(object): channels = tuple(self.acq_channels) all_channels = channels + (timer_ct, point_nb_ct) - integrator = dict([(ct, False) for ct in channels]) + integrator = dict(zip(channels, self.integrator_channels)) # change the start and stop sources for the active channels for ch_nb in channels: ct_config = card_o.get_counter_config(ch_nb) @@ -649,6 +650,8 @@ class CT2(object): raise ValueError("Acq. point period only allowed in %s" % mode_str) if self.__has_ext_sync() and not self.input_channel: raise ValueError("Must provide in_config in ext-trig modes") + if len(self.acq_channels) != len(self.integrator_channels): + raise ValueError("acq_channels / integrator_channels size mismatch") self.stop_acq() if self.acq_mode not in self.StdModes: @@ -797,6 +800,22 @@ class CT2(object): sorted_channels = sorted(self.acq_channels) return [sorted_channels.index(x) for x in self.acq_channels] + def __default_integrator_channels(self): + return [False for ct in self.acq_channels] + + @property + def integrator_channels(self): + if self.__integrator_channels is not None: + return self.__integrator_channels + return self.__default_integrator_channels() + + @integrator_channels.setter + def integrator_channels(self, integrator_channels): + integrator_channels = list(map(bool, integrator_channels)) + if integrator_channels == self.__default_integrator_channels(): + integrator_channels = None + self.__integrator_channels = integrator_channels + @property def timer_freq(self): return self.__timer_freq diff --git a/bliss/tango/servers/ct2_ds/ct2_ds.py b/bliss/tango/servers/ct2_ds/ct2_ds.py index 9ce9e9aef0..8932a5b70e 100644 --- a/bliss/tango/servers/ct2_ds/ct2_ds.py +++ b/bliss/tango/servers/ct2_ds/ct2_ds.py @@ -185,6 +185,19 @@ class CT2(Device): def acq_channels_data_indexes(self): return tuple(self.device.acq_channels_data_indexes) + @attribute( + dtype=("int16",), + max_dim_x=12, + label="Integrator channels", + doc="List indicating if corresponding acq_channel is integrator", + ) + def integrator_channels(self): + return tuple(self.device.integrator_channels) + + @integrator_channels.setter + def integrator_channels(self, integrator_channels): + self.device.integrator_channels = integrator_channels + @attribute( dtype="float64", label="Timer clock freq.", diff --git a/spec/bliss/ct2.mac b/spec/bliss/ct2.mac index 5fbc6b9dff..60ccc14cad 100644 --- a/spec/bliss/ct2.mac +++ b/spec/bliss/ct2.mac @@ -99,6 +99,7 @@ def ct2_config(cnum, type, unit, module, chan) '{ list_setpar(CT2_MAC_LIST, ctrl_dev, "acq_nb_points", 1) list_setpar(CT2_MAC_LIST, ctrl_dev, "timer_freq", 1e6) list_setpar(CT2_MAC_LIST, ctrl_dev, "all_channels", ct2_list_init()) + list_setpar(CT2_MAC_LIST, ctrl_dev, "integ_channels", ct2_list_init()) return } else if (type != "cnt") { printf("CT2: WARNING unknown type=%s, unit=%s\n", type, unit) @@ -238,17 +239,18 @@ def ct2_get_master_status(ctrl_dev) '{ #--------------------------------------------------------------------- #--------------------------------------------------------------------- def ct2_prestart_all(ctrl_dev) '{ - local nb_chan, i, l, acq_chan_list[] + local nb_chan, i, chan_l, a_l, chan_arr[] CT2_MAC_HDW[ctrl_dev]["acq_channels"] = ct2_list_init() + CT2_MAC_HDW[ctrl_dev]["acq_integ_channels"] = ct2_list_init() CT2_MAC_HDW[ctrl_dev]["nb_channels"] = 0 - CT2_MAC_HDW[ctrl_dev]["act_channels"] = 0 + CT2_MAC_HDW[ctrl_dev]["act_channels"] = ct2_list_init() CT2_MAC_HDW[ctrl_dev]["slaves"] = ct2_list_init() CT2_MAC_HDW["started_masters"] = 0 - l = list_getpar(CT2_MAC_LIST, ctrl_dev, "all_channels") - nb_chan = ct2_list_split(l, acq_chan_list) + chan_l = list_getpar(CT2_MAC_LIST, ctrl_dev, "all_channels") + nb_chan = ct2_list_split(chan_l, chan_arr) for (i = 0; i < nb_chan; i++) - if (!counter_par(cnt_num(acq_chan_list[i]), "disable")) - CT2_MAC_HDW[ctrl_dev]["act_channels"]++ + if (!counter_par(cnt_num(chan_arr[i]), "disable")) + ++CT2_MAC_HDW[ctrl_dev]["nb_channels"] CT2_MAC_HDW_LAST[ctrl_dev]["valid"] = 0 }' @@ -256,18 +258,27 @@ def ct2_prestart_all(ctrl_dev) '{ #--------------------------------------------------------------------- def ct2_start_one(cnum, ctrl_dev, chan, p1, p2) '{ local FnId addon; FnId="ct2_start_one" - local acq_chan, cnt_idx, all_chan_started + local chan_l, cnt_idx, all_chan_started, nb_act_chan local master_dev, is_master, slaves __ct2_profile "(trace 1)" if (chan != 0) { - acq_chan = CT2_MAC_HDW[ctrl_dev]["acq_channels"] - cnt_idx = ct2_list_n(acq_chan) - CT2_MAC_HDW[ctrl_dev]["acq_channels"] = ct2_list_add(acq_chan, chan) - counter_par(cnum, "counter_idx", cnt_idx, "add") - } + chan_l = CT2_MAC_HDW[ctrl_dev]["acq_channels"] + cnt_idx = ct2_list_n(chan_l) + CT2_MAC_HDW[ctrl_dev]["acq_channels"] = ct2_list_add(chan_l, chan) + chan_l = CT2_MAC_HDW[ctrl_dev]["acq_integ_channels"] + chan_l = ct2_list_add(chan_l, counter_par(cnum, "integrator"), 1) + CT2_MAC_HDW[ctrl_dev]["acq_integ_channels"] = chan_l + } else + cnt_idx = -1 + counter_par(cnum, "counter_idx", cnt_idx, "add") + chan_l = CT2_MAC_HDW[ctrl_dev]["act_channels"] + chan_l = ct2_list_add(chan_l, cnt_mne(cnum)) + nb_act_chan = ct2_list_n(chan_l) + CT2_MAC_HDW[ctrl_dev]["act_channels"] = chan_l + master_dev = list_getpar(CT2_MAC_LIST, ctrl_dev, "master_dev") is_master = (master_dev == ctrl_dev) if (!is_master) { @@ -275,8 +286,7 @@ def ct2_start_one(cnum, ctrl_dev, chan, p1, p2) '{ CT2_MAC_HDW[master_dev]["slaves"] = slaves } - all_chan_started = (++CT2_MAC_HDW[ctrl_dev]["nb_channels"] == \ - CT2_MAC_HDW[ctrl_dev]["act_channels"]) + all_chan_started = (nb_act_chan == CT2_MAC_HDW[ctrl_dev]["nb_channels"]) if (is_master && all_chan_started) return ct2_start_master(ctrl_dev, chan, p1, p2) }' @@ -303,7 +313,7 @@ def ct2_start_master(ctrl_dev, chan, p1, p2) '{ def ct2_prepare_master_and_slaves(ctrl_dev, chan, p1, p2) '{ local FnId addon; FnId ="ct2_prepare_master_and_slaves" local nb_ctrls, ctrl_list[], i, j, dev, is_master - local factor, acq_mode, acq_chan_list[] + local factor, acq_mode, chan_arr[] local acq_expo_time, acq_point_period, acq_nb_points local is_null_point_period, is_trig_readout, needs_point_period @@ -340,15 +350,21 @@ def ct2_prepare_master_and_slaves(ctrl_dev, chan, p1, p2) '{ tango_put(dev, "acq_expo_time", acq_expo_time) __ct2_profile "start_one" " chan == 0 tango_put expo time" - ct2_list_split(CT2_MAC_HDW[dev]["acq_channels"], acq_chan_list) - tango_put(dev, "acq_channels", acq_chan_list) + ct2_list_split(CT2_MAC_HDW[dev]["acq_channels"], chan_arr) + tango_put(dev, "acq_channels", chan_arr) __ct2_profile "start_one" " tango_put acq_channels" - # store acq_channels_data_indexes for standard counters - tango_get(dev, "acq_channels_data_indexes", acq_chan_list) - __ct2_profile "start_one" " tango_get acq_channels_data_indexes" - for (j in acq_chan_list) - CT2_MAC_HDW[dev][sprintf("idx_%d", j)] = acq_chan_list[j] + ct2_list_split(CT2_MAC_HDW[dev]["acq_integ_channels"], chan_arr) + tango_put(dev, "integrator_channels", chan_arr) + __ct2_profile "start_one" " tango_put acq_channels" + + if (ct2_list_n(CT2_MAC_HDW[dev]["acq_channels"])) { + # store acq_channels_data_indexes for standard counters + tango_get(dev, "acq_channels_data_indexes", chan_arr) + __ct2_profile "start_one" " tango_get acq_channels_data_indexes" + for (j in chan_arr) + CT2_MAC_HDW[dev][sprintf("idx_%d", j)] = chan_arr[j] + } tango_put(dev, "acq_nb_points", acq_nb_points) __ct2_profile "start_one" " tango_put acq_nb_points" @@ -383,7 +399,8 @@ def ct2_start_master_and_slaves(ctrl_dev) '{ def ct2_counts(cnum, ctrl_dev, chan, p1) '{ local FnId addon; FnId="ct2_counts" - local cnt_idx, arr_key, nb_chan + local cnt_idx, arr_key, nb_chan, nb_points, chan_l, chan_arr[] + local nb_act_chan, aux_cnum __ct2_profile "(trace 1)" nb_chan = ct2_list_n(CT2_MAC_HDW[ctrl_dev]["acq_channels"]) if (!CT2_MAC_HDW_LAST[ctrl_dev]["valid"]) { @@ -402,14 +419,25 @@ def ct2_counts(cnum, ctrl_dev, chan, p1) '{ __ct2_profile " valid tango_get counters (trace 2)" TANGO_ERR = -1 - acq_nb_points = list_getpar(CT2_MAC_LIST, ctrl_dev, "acq_nb_points") - ulong array v[acq_nb_points][nb_chan + 2] - tango_get(ctrl_dev, "data", v) + nb_points = list_getpar(CT2_MAC_LIST, ctrl_dev, "acq_nb_points") + ulong array v[nb_points][nb_chan + 2] + nb_points = tango_get(ctrl_dev, "data", v) / (nb_chan + 2) __ct2_profile " valid tango_get data " if (TANGO_ERR != "0") return -1 - for (cnt_i = 0; cnt_i < nb_chan + 2; cnt_i++) - CT2_MAC_HDW_LAST[ctrl_dev][cnt_i] = array_op("sum", v[:][cnt_i]) + + chan_l = CT2_MAC_HDW[ctrl_dev]["act_channels"] + nb_act_chan = ct2_list_split(chan_l, chan_arr) + for (cnt_i = 0; cnt_i < nb_act_chan; cnt_i++) { + aux_cnum = cnt_num(chan_arr[cnt_i]) + cnt_idx = counter_par(aux_cnum, "counter_idx") + if (cnt_idx == -1) + cnt_idx = nb_chan + if (counter_par(aux_cnum, "integrator")) + CT2_MAC_HDW_LAST[ctrl_dev][cnt_idx] = v[nb_points - 1][cnt_idx] + else + CT2_MAC_HDW_LAST[ctrl_dev][cnt_idx] = array_op("sum", v[:][cnt_idx]) + } CT2_MAC_HDW_LAST[ctrl_dev]["valid"] = 1 } # use acq_channels_data_indexes for standard counters, nb_channels for timers @@ -422,7 +450,9 @@ def ct2_counts(cnum, ctrl_dev, chan, p1) '{ #===================================================================== def ct2_par(cnum, key, action, p1) '{ - local ctrl_dev chan mne val[] int_cnt acq_mode_table[] acq_mode aux_key + local ctrl_dev, chan, mne, val[], int_cnt, acq_mode_table[], acq_mode + local chan_l + mne = cnt_mne(cnum) ctrl_dev = ct2_ADDR @@ -440,6 +470,20 @@ def ct2_par(cnum, key, action, p1) '{ if (action == "set") CT2_MAC_HDW[ctrl_dev][aux_key] = p1 return CT2_MAC_HDW[ctrl_dev][aux_key] + } else if (key == "integrator") { + chan_l = list_getpar(CT2_MAC_LIST, ctrl_dev, "integ_channels") + if (action == "set") { + if (p1) { + if (chan == 0) { + printf("Error: timer cannot be integrator\n") + return ".error." + } + chan_l = ct2_list_add(chan_l, mne) + } else + chan_l = ct2_list_del(chan_l, mne) + list_setpar(CT2_MAC_LIST, ctrl_dev, "integ_channels", chan_l) + } + return ct2_list_includes(chan_l, mne) } else if (key == "status") { ct2_get(cnum, "counters_status", val) int_cnt = list_getpar(CT2_MAC_LIST, ctrl_dev, "int_cnt") -- GitLab From a5c2e7cc69556cdac8816e78b5075ef282ef35ff Mon Sep 17 00:00:00 2001 From: Alejandro Homs Puron Date: Tue, 18 May 2021 16:44:01 +0200 Subject: [PATCH 7/7] DOC CT2: add SPEC multi-board configuration --- doc/docs/config_p201.md | 29 ++++++++++++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) diff --git a/doc/docs/config_p201.md b/doc/docs/config_p201.md index ef270616be..c749c2fa22 100644 --- a/doc/docs/config_p201.md +++ b/doc/docs/config_p201.md @@ -497,7 +497,7 @@ Counter or Macro Counter/Timer on the previous screen). If you add a CT2 timer, the *Chan* must be **0**. The CT2 timer is capable of working in 6 different frequencies: 1.25 KHz, 10 KHz, 125 KHz, 1 MHz, 12.5 MHz and 100 MHz. The spec *Scale Factor* selects this frequency. The standard -working frequency is 1 MHz which correspondes to a *Scale Factor* of 1E6. +working frequency is 1 MHz which corresponds to a *Scale Factor* of 1E6. Example: Scaler (Counter) Configuration @@ -507,6 +507,33 @@ Example: 1 p201_3 p201_3 MAC_CNT 0 3 counter 1 +#### Multiple P201 boards + +Multiple P201 boards can be configured in Spec; each board requires an independent +entry in the SCALERS controller list. By default a board is configured as master and +started independently. CT2 masters are started sequentially (from last to first in the +config) so there is an intrinsic (accumulative) delay in their synchronization. A +better synchronization is obtained, as explained before, by connecting the output +channel of a master to the trigger input of the slave(s). The relation master/slave +must be explicitly indicated in the config of each slave controller through the *master* +parameter. To access the controller parameters go the *Motor and Counter Device +Configuration (Not CAMAC)*, move the cursor on top of the SCALER slave controller and +type 'p'. Then add the *master* parameter and set it to the Tango device name +(controller ADDR) of the master device: + + Custom Parameters for "Macro Counter/Timer" Unit 1 1/1 configured + + NAME VALUE + master id00/ct2/p201_lid001_0 + +The definition of the timer of each P201 board (channel 0) is optional. It is +recommended to set the main (first) *timebase* counter as a CT2 timer. This +configuration will allow that all the CT2 masters count for the specified time. Even if +the main timer can be a *Software Timer* and different CT2 boards can be configured +as independent masters, each CT2 board will be stopped as soon as the *Software Timer* +finishes, resulting in shorting and non-deterministic counting intervals. + + ## Supported acquisition types Here is a brief summary of the current acquisition types supported by -- GitLab