diff --git a/pydevices/HtsDevices/acq2106_435sc.py b/pydevices/HtsDevices/acq2106_435sc.py index f9791a44e0..de9f545192 100644 --- a/pydevices/HtsDevices/acq2106_435sc.py +++ b/pydevices/HtsDevices/acq2106_435sc.py @@ -46,6 +46,7 @@ class _ACQ2106_435SC(acq2106_435st._ACQ2106_435ST): ] def init(self): + self.slots = super(_ACQ2106_435SC, self).getSlots() freq = int(self.freq.data()) @@ -62,11 +63,10 @@ def init(self): raise MDSplus.DevBAD_PARAMETER( "FREQ must be 10000, 20000, 40000, 80000 or 128000; not %d" % (freq,)) - for card in self.slots: - self.setGainsOffsets(card) - self.slots[card].SC32_GAIN_COMMIT = 1 + for site in self.slots: + self.setGainsOffsets(site) if self.debug: - print("GAINs Committed for site %s" % (card,)) + print("GAINs Committed for site %s" % (site,)) # Here, the argument to the init of the superclass: # - init(True) => use resampling function: @@ -81,80 +81,92 @@ def getUUT(self): uut = acq400_hapi.Acq2106(self.node.data(), monitor=False, has_wr=True) return uut - - def setGainsOffsets(self, card): + def computeGains(self, g): + g1opts = [ 1000, 100, 10, 1 ] + g2opts = [ 1, 2, 5, 10 ] + + for g1opt in g1opts: + if g >= g1opt: + g1 = g1opt + g2 = g // g1opt + if g2 not in g2opts: + raise MDSplus.DevBAD_PARAMETER( + "SC_GAIN must be computable from (one of: 1000, 100, 10, 1) * (one of: 1, 2, 5, 10) ; not %d" % (g,)) + return (g1, g2) + + def setGainsOffsets(self, site): import epics import socket + if site not in [1, 3, 5]: + # (slw) TODO: Improve + print('site is not 1, 3, or 5') + return + + # TODO: we should probably replace this with a EPICS_NAME node instead of asking for the hostname domainName = socket.gethostbyaddr(str(self.node.data()))[0] splitDomainName = domainName.split(".") #For EPICS PV definitions hardcoded in D-Tacq's "/tmp/records.dbl", # the ACQs DNS hostnames/domain names should be of the format _ - if "-" in splitDomainName[0]: - epicsDomainName = splitDomainName[0].replace("-", "_") - else: - epicsDomainName = splitDomainName[0] - - for ic in range(1,32+1): - if card == 1: - pvg1 = "{}:{}:SC32:G1:{:02d}".format(epicsDomainName, card, ic) - pv = epics.PV(pvg1) - valueg1 = str(getattr(self, 'INPUT_%3.3d:SC_GAIN1' % (ic,)).data()) - pv.put(valueg1, wait=True) - - pvg2 = "{}:{}:SC32:G2:{:02d}".format(epicsDomainName, card, ic) - pv = epics.PV(pvg2) - valueg2 = str(getattr(self, 'INPUT_%3.3d:SC_GAIN2' % (ic,)).data()) - pv.put(valueg2, wait=True) - - pvg3 = "{}:{}:SC32:OFFSET:{:02d}".format(epicsDomainName, card, ic) - pv = epics.PV(pvg3) - valueg3 = str(getattr(self, 'INPUT_%3.3d:SC_OFFSET' % (ic,)).data()) - pv.put(valueg3, wait=True) - - elif card == 3: - pvg1 = "{}:{}:SC32:G1:{:02d}".format(epicsDomainName, card, ic) - pv = epics.PV(pvg1) - valueg1 = str(getattr(self, 'INPUT_%3.3d:SC_GAIN1' % (ic+32,)).data()) - pv.put(valueg1, wait=True) - - pvg2 = "{}:{}:SC32:G2:{:02d}".format(epicsDomainName, card, ic) - pv = epics.PV(pvg2) - valueg2 = str(getattr(self, 'INPUT_%3.3d:SC_GAIN2' % (ic+32,)).data()) - pv.put(valueg2, wait=True) - - pvg3 = "{}:{}:SC32:OFFSET:{:02d}".format(epicsDomainName, card, ic) - pv = epics.PV(pvg3) - valueg3 = str(getattr(self, 'INPUT_%3.3d:SC_OFFSET' % (ic+32,)).data()) - pv.put(valueg3, wait=True) - - elif card == 5: - pvg1 = "{}:{}:SC32:G1:{:02d}".format(epicsDomainName, card, ic) - pv = epics.PV(pvg1) - valueg1 = str(getattr(self, 'INPUT_%3.3d:SC_GAIN1' % (ic+64,)).data()) - pv.put(valueg1, wait=True) - - pvg2 = "{}:{}:SC32:G2:{:02d}".format(epicsDomainName, card, ic) - pv = epics.PV(pvg2) - valueg2 = str(getattr(self, 'INPUT_%3.3d:SC_GAIN2' % (ic+64,)).data()) - pv.put(valueg2, wait=True) - - pvg3 = "{}:{}:SC32:OFFSET:{:02d}".format(epicsDomainName, card, ic) - pv = epics.PV(pvg3) - valueg3 = str(getattr(self, 'INPUT_%3.3d:SC_OFFSET' % (ic+64,)).data()) - pv.put(valueg3, wait=True) - - def setChanScale(self, node, num): - #Raw input channel, where the conditioning has been applied: - input_chan = self.__getattr__('INPUT_%3.3d' % num) - chan = self.__getattr__(node) - #Un-conditioning the signal: - chan.setSegmentScale( - MDSplus.ADD(MDSplus.DIVIDE(MDSplus.MULTIPLY(input_chan.COEFFICIENT, MDSplus.dVALUE()), - MDSplus.MULTIPLY(input_chan.SC_GAIN1, input_chan.SC_GAIN2)), - MDSplus.SUBTRACT(input_chan.OFFSET, input_chan.SC_OFFSET)) + epicsDomainName = splitDomainName[0].replace("-", "_") + + # Choosing the input offset (0, 32, 64) depending of the selected site: + input_offset = { 1: 0, 3: 32, 5: 64 }[site] + + for i in range(32): + gain = str(getattr(self, 'INPUT_%3.3d:SC_GAIN' % (i + input_offset + 1,)).data()) + + parts = gain.split(",") + + if len(parts) == 2: + gain1 = int(float(parts[0])) + gain2 = int(float(parts[1])) + else: + gain1, gain2 = self.computeGains(int(float(gain))) + + offset = getattr(self, 'INPUT_%3.3d:SC_OFFSET' % (i + input_offset + 1,)).data() + + pvg1 = "{}:{}:SC32:G1:{:02d}".format(epicsDomainName, site, i + 1) + pv = epics.PV(pvg1) + valueg1 = str(gain1) + pv.put(valueg1, wait=True) + + pvg2 = "{}:{}:SC32:G2:{:02d}".format(epicsDomainName, site, i + 1) + pv = epics.PV(pvg2) + valueg2 = str(gain2) + pv.put(valueg2, wait=True) + + pvg3 = "{}:{}:SC32:OFFSET:{:02d}".format(epicsDomainName, site, i + 1) + pv = epics.PV(pvg3) + valueg3 = str(offset) + pv.put(valueg3, wait=True) + + pv = epics.PV('{}:{}:SC32:GAIN:COMMIT'.format(epicsDomainName, site)) + pv.put('1') + + # target_path = path to the node to call setSegmentScale on. + # input_path = path to parent node for the input channel, typically INPUT_xxx, default to target_path + def setChanScale(self, target_path, input_path=None): + target_node = self.__getattr__(target_path) + input_node = target_node + + if input_path: + input_node = self.__getattr__(input_path) + + # Attention: For versions of the firmware v498 or greater in all the ACQ SC32 the calibration coefficients and offsets + # already take into account the gains and offsets of the signal conditioning stages. + + # = (coefficient * value) + offset + target_node.setSegmentScale( + MDSplus.ADD( + MDSplus.MULTIPLY( + input_node.COEFFICIENT, + MDSplus.dVALUE() + ), + input_node.OFFSET ) + ) def assemble(cls): @@ -164,7 +176,7 @@ def assemble(cls): { 'path': ':INPUT_%3.3d' % (i+1,), 'type': 'SIGNAL', - 'valueExpr': 'head.setChanScale("INPUT_%3.3d", %d)' % (i+1, i+1), + 'valueExpr': 'head.setChanScale("INPUT_%3.3d")' % (i+1,), 'options': ('no_write_model', 'write_once',) }, { @@ -186,15 +198,8 @@ def assemble(cls): }, { # Local (per channel) SC gains - 'path': ':INPUT_%3.3d:SC_GAIN1' % (i+1,), - 'type':'NUMERIC', - 'value':1, - 'options':('no_write_shot',) - }, - { - # Local (per channel) SC gains - 'path': ':INPUT_%3.3d:SC_GAIN2' % (i+1,), - 'type':'NUMERIC', + 'path': ':INPUT_%3.3d:SC_GAIN' % (i+1,), + 'type':'TEXT', 'value':1, 'options':('no_write_shot',) }, @@ -205,20 +210,11 @@ def assemble(cls): 'value':0, 'options':('no_write_shot',) }, - { - # Conditioned signal goes here: - 'path': ':INPUT_%3.3d:SC_INPUT' % (i+1,), - 'type': 'SIGNAL', - 'valueExpr': - 'ADD(MULTIPLY(head.INPUT_%3.3d, MULTIPLY(head.INPUT_%3.3d.SC_GAIN1, head.INPUT_%3.3d.SC_GAIN2)), head.INPUT_%3.3d.SC_OFFSET)' - % (i+1,i+1,i+1,i+1), - 'options': ('no_write_model','write_once',) - }, { # Re-sampling streaming data goes here: 'path': ':INPUT_%3.3d:RESAMPLED' % (i+1,), 'type': 'SIGNAL', - 'valueExpr': 'head.setChanScale("INPUT_%3.3d:RESAMPLED", %d)' % (i+1, i+1), + 'valueExpr': 'head.setChanScale("INPUT_%3.3d:RESAMPLED", "INPUT_%3.3d")' % (i+1, i+1), 'options': ('no_write_model', 'write_once',) }, ] diff --git a/pydevices/HtsDevices/acq2106_435st.py b/pydevices/HtsDevices/acq2106_435st.py index 959a1e8dae..078d72101e 100755 --- a/pydevices/HtsDevices/acq2106_435st.py +++ b/pydevices/HtsDevices/acq2106_435st.py @@ -190,7 +190,7 @@ def __init__(self, dev): self.dev = dev - self.nchans = self.dev.sites*32 + self.nchans = self.dev.sites * 32 self.resampling = self.dev.resampling self.seg_length = self.dev.seg_length.data() @@ -240,8 +240,8 @@ def lcma(arr): if nacc_str == '0,0,0': nacc_sample = 1 else: - nacc_tuple = ast.literal_eval(nacc_str) - nacc_sample = nacc_tuple[0] + nacc_sample = int(nacc_str.split(",")[0]) + if self.dev.debug: print("The ACQ NACC sample value is {}".format(nacc_sample)) @@ -470,7 +470,7 @@ def init(self, resampling = False, armed_by_transient = False): eoff = uut.cal_eoff[1:] self.chans = [] - nchans = uut.nchan() + nchans = self.sites * 32 for ii in range(nchans): self.chans.append(getattr(self, 'INPUT_%3.3d' % (ii+1)))