From 5a50d1920eca7839e5800ad43586e210c396968d Mon Sep 17 00:00:00 2001 From: Bernardo Carvalho Date: Mon, 19 May 2025 17:17:53 +0100 Subject: [PATCH] Added MIRNOV Signals Signed-off-by: Bernardo Carvalho --- Trees/CreateIsttokMARTe.tcl | 264 ++++++++++++++++++++++++++++++++++ Trees/IpfnDevices/ATCA_IOP.py | 153 ++++++++++++++++++++ 2 files changed, 417 insertions(+) create mode 100644 Trees/CreateIsttokMARTe.tcl create mode 100644 Trees/IpfnDevices/ATCA_IOP.py diff --git a/Trees/CreateIsttokMARTe.tcl b/Trees/CreateIsttokMARTe.tcl new file mode 100644 index 0000000..9b529cd --- /dev/null +++ b/Trees/CreateIsttokMARTe.tcl @@ -0,0 +1,264 @@ +edit isttokmarte/new + +add node .INP +add node .REFS +add node .ERRORS +add node .CONTROLS +add node .STATES +add node .PERF +add node TIME/usage=signal +add node TIMED/usage=signal + +add node .DIAGNOSTICS +add node .HARDWARE +set def .HARDWARE +add node .ATCA_1 +add node .ATCA_2 +# set def \ISTTOKSDAS::TOP.HARDWARE.ATCA1 +set def .ATCA_1 +add node IOC_0/model=IOCMIMORT +add node IOC_1/model=IOCMIMORT +set def \ISTTOKMARTE::TOP.HARDWARE.ATCA_1.IOC_1" +put SLOT "2" +# put CLOCK_FREQ "20000" + +set def \ISTTOKMARTE::TOP.HARDWARE.ATCA_2" +add node IOP_9/model=ATCA_IOP +set def \ISTTOKMARTE::TOP.HARDWARE.ATCA_2.IOP_9" +put RT_DECIM "200" +put SLOT "9" +set def \isttokmarte::top.hardware.atca_2.iop_9.channel_0 +# calibration on 14/05/2025 +put gain "1.73887463e-05" +put inp_decim "gain * adc_decim" +put inp_integ "gain * adc_integ / \isttokmarte::top.hardware.atca_2.iop_9.rt_decim / \isttokmarte::top.hardware.atca_2.iop_9.clock_freq" +set def \isttokmarte::top.hardware.atca_2.iop_9.channel_1 +put gain "1.73937683e-05" +put inp_decim "gain * adc_decim" +put inp_integ "gain * adc_integ / \isttokmarte::top.hardware.atca_2.iop_9.rt_decim / \isttokmarte::top.hardware.atca_2.iop_9.clock_freq" +set def \isttokmarte::top.hardware.atca_2.iop_9.channel_2 +put gain "1.74275762e-05" +put inp_decim "gain * adc_decim" +put inp_integ "gain * adc_integ / \isttokmarte::top.hardware.atca_2.iop_9.rt_decim / \isttokmarte::top.hardware.atca_2.iop_9.clock_freq" +set def \isttokmarte::top.hardware.atca_2.iop_9.channel_3 +put gain "1.74994244e-05" +put inp_decim "gain * adc_decim" +put inp_integ "gain * adc_integ / \isttokmarte::top.hardware.atca_2.iop_9.rt_decim / \isttokmarte::top.hardware.atca_2.iop_9.clock_freq" +set def \isttokmarte::top.hardware.atca_2.iop_9.channel_4 +put gain "1.73826859e-05" +put inp_decim "gain * adc_decim" +put inp_integ "gain * adc_integ / \isttokmarte::top.hardware.atca_2.iop_9.rt_decim / \isttokmarte::top.hardware.atca_2.iop_9.clock_freq" +set def \isttokmarte::top.hardware.atca_2.iop_9.channel_5 +put gain "1.74439575e-05" +put inp_decim "gain * adc_decim" +put inp_integ "gain * adc_integ / \isttokmarte::top.hardware.atca_2.iop_9.rt_decim / \isttokmarte::top.hardware.atca_2.iop_9.clock_freq" +set def \isttokmarte::top.hardware.atca_2.iop_9.channel_6 +put gain "1.74532093e-05" +put inp_decim "gain * adc_decim" +put inp_integ "gain * adc_integ / \isttokmarte::top.hardware.atca_2.iop_9.rt_decim / \isttokmarte::top.hardware.atca_2.iop_9.clock_freq" +set def \isttokmarte::top.hardware.atca_2.iop_9.channel_7 +put gain "1.73723740e-05" +put inp_decim "gain * adc_decim" +put inp_integ "gain * adc_integ / \isttokmarte::top.hardware.atca_2.iop_9.rt_decim / \isttokmarte::top.hardware.atca_2.iop_9.clock_freq" +set def \isttokmarte::top.hardware.atca_2.iop_9.channel_8 +put gain "1.71925327e-05" +put inp_decim "gain * adc_decim" +put inp_integ "gain * adc_integ / \isttokmarte::top.hardware.atca_2.iop_9.rt_decim / \isttokmarte::top.hardware.atca_2.iop_9.clock_freq" +set def \isttokmarte::top.hardware.atca_2.iop_9.channel_9 +put gain "1.72739424e-05" +put inp_decim "gain * adc_decim" +put inp_integ "gain * adc_integ / \isttokmarte::top.hardware.atca_2.iop_9.rt_decim / \isttokmarte::top.hardware.atca_2.iop_9.clock_freq" +set def \isttokmarte::top.hardware.atca_2.iop_9.channel_10 +put gain "1.73809822e-05" +put inp_decim "gain * adc_decim" +put inp_integ "gain * adc_integ / \isttokmarte::top.hardware.atca_2.iop_9.rt_decim / \isttokmarte::top.hardware.atca_2.iop_9.clock_freq" +set def \isttokmarte::top.hardware.atca_2.iop_9.channel_11 +put gain "1.74412886e-05" +put inp_decim "gain * adc_decim" +put inp_integ "gain * adc_integ / \isttokmarte::top.hardware.atca_2.iop_9.rt_decim / \isttokmarte::top.hardware.atca_2.iop_9.clock_freq" + +#set def \ISTTOKMARTE::TOP.INP +#add node MEAS0/usage=signal +#add node MEAS0D/usage=signal +#add node MEAS0F/usage=signal +#add node MEAS0FD/usage=signal +#add node MEAS1/usage=signal +#add node MEAS1D/usage=signal +#add node MEAS1F/usage=signal +#add node MEAS1FD/usage=signal + +set def \ISTTOKMARTE::TOP.REFS +add node REF0/usage=signal +add node REF0D/usage=signal +add node REF1/usage=signal +add node REF1D/usage=signal + +set def \ISTTOKMARTE::TOP.ERRORS +add node ERROR0/usage=signal +add node ERROR0D/usage=signal +add node ERROR1/usage=signal +add node ERROR1D/usage=signal + +set def \ISTTOKMARTE::TOP.CONTROLS +add node CONTROL0/usage=signal +add node CONTROL0D/usage=signal +add node CONTROL1/usage=signal +add node CONTROL1D/usage=signal + +set def \ISTTOKMARTE::TOP.STATES +add node STATE0/usage=signal +add node STATE0D/usage=signal +add node STATE1/usage=signal +add node STATE1D/usage=signal +add node STATE2/usage=signal +add node STATE2D/usage=signal +add node STATE3/usage=signal +add node STATE3D/usage=signal + +set def \ISTTOKMARTE::TOP.PERF +add node CYCLET/usage=signal +add node CYCLETD/usage=signal + +set def \ISTTOKMARTE::TOP.DIAGNOSTICS +add node MAGNETICS +set def .MAGNETICS +add node .MIRNOV +set def .MIRNOV +add node PROBE1 +add node PROBE2 +add node PROBE3 +add node PROBE4 +add node PROBE5 +add node PROBE6 +add node PROBE7 +add node PROBE8 +add node PROBE9 +add node PROBE10 +add node PROBE11 +add node PROBE12 +set def \ISTTOKMARTE::TOP.DIAGNOSTICS.MAGNETICS.MIRNOV.PROBE1 +add node ANGLE/usage=numeric +put ANGLE "15.1" +add node AREA/usage=numeric +# Total area: turns * A : 0.0049**2 * 50 +put AREA "0.0012005" +add node POL/usage=numeric +put POL "-1" +add node SIG/usage=signal +put SIG "POL * \ISTTOKMARTE::TOP.HARDWARE.ATCA_2.IOP_9.CHANNEL_0.INP_INTEG" +set def \ISTTOKMARTE::TOP.DIAGNOSTICS.MAGNETICS.MIRNOV.PROBE2 +add node ANGLE/usage=numeric +put ANGLE "30.2" +add node AREA/usage=numeric +put AREA "0.0012005" +add node POL/usage=numeric +put POL "-1" +add node SIG/usage=signal +put SIG "POL * \ISTTOKMARTE::TOP.HARDWARE.ATCA_2.IOP_9.CHANNEL_1.INP_INTEG" +set def \ISTTOKMARTE::TOP.DIAGNOSTICS.MAGNETICS.MIRNOV.PROBE3 +add node ANGLE/usage=numeric +put ANGLE "30.2" +add node AREA/usage=numeric +put AREA "0.0012005" +add node POL/usage=numeric +put POL "1" +add node SIG/usage=signal +put SIG "POL * \ISTTOKMARTE::TOP.HARDWARE.ATCA_2.IOP_9.CHANNEL_2.INP_INTEG" +set def \ISTTOKMARTE::TOP.DIAGNOSTICS.MAGNETICS.MIRNOV.PROBE4 +add node ANGLE/usage=numeric +put ANGLE "30.2" +add node AREA/usage=numeric +put AREA "0.0012005" +add node POL/usage=numeric +put POL "-1" +add node SIG/usage=signal +put SIG "POL * \ISTTOKMARTE::TOP.HARDWARE.ATCA_2.IOP_9.CHANNEL_3.INP_INTEG" + +set def \ISTTOKMARTE::TOP.DIAGNOSTICS.MAGNETICS.MIRNOV.PROBE5 +add node ANGLE/usage=numeric +put ANGLE "30.2" +add node AREA/usage=numeric +put AREA "0.0012005" +add node POL/usage=numeric +put POL "1" +add node SIG/usage=signal +put SIG "POL * \ISTTOKMARTE::TOP.HARDWARE.ATCA_2.IOP_9.CHANNEL_4.INP_INTEG" +set def \ISTTOKMARTE::TOP.DIAGNOSTICS.MAGNETICS.MIRNOV.PROBE6 +add node ANGLE/usage=numeric +put ANGLE "30.2" +add node AREA/usage=numeric +put AREA "0.0012005" +add node POL/usage=numeric +put POL "1" +add node SIG/usage=signal +put SIG "POL * \ISTTOKMARTE::TOP.HARDWARE.ATCA_2.IOP_9.CHANNEL_5.INP_INTEG" + +set def \ISTTOKMARTE::TOP.DIAGNOSTICS.MAGNETICS.MIRNOV.PROBE7 +add node ANGLE/usage=numeric +put ANGLE "30.2" +add node AREA/usage=numeric +put AREA "0.0012005" +add node POL/usage=numeric +put POL "1" +add node SIG/usage=signal +put SIG "POL * \ISTTOKMARTE::TOP.HARDWARE.ATCA_2.IOP_9.CHANNEL_6.INP_INTEG" +set def \ISTTOKMARTE::TOP.DIAGNOSTICS.MAGNETICS.MIRNOV.PROBE8 +add node ANGLE/usage=numeric +put ANGLE "30.2" +add node AREA/usage=numeric +put AREA "0.0012005" +add node POL/usage=numeric +put POL "1" +add node SIG/usage=signal +put SIG "POL * \ISTTOKMARTE::TOP.HARDWARE.ATCA_2.IOP_9.CHANNEL_7.INP_INTEG" + +set def \ISTTOKMARTE::TOP.DIAGNOSTICS.MAGNETICS.MIRNOV.PROBE9 +add node ANGLE/usage=numeric +put ANGLE "30.2" +add node AREA/usage=numeric +put AREA "0.0012005" +add node POL/usage=numeric +put POL "1" +add node SIG/usage=signal +put SIG "POL * \ISTTOKMARTE::TOP.HARDWARE.ATCA_2.IOP_9.CHANNEL_8.INP_INTEG" +set def \ISTTOKMARTE::TOP.DIAGNOSTICS.MAGNETICS.MIRNOV.PROBE10 +add node ANGLE/usage=numeric +put ANGLE "30.2" +add node AREA/usage=numeric +put AREA "0.0012005" +add node POL/usage=numeric +put POL "1" +add node SIG/usage=signal +put SIG "POL * \ISTTOKMARTE::TOP.HARDWARE.ATCA_2.IOP_9.CHANNEL_9.INP_INTEG" + +set def \ISTTOKMARTE::TOP.DIAGNOSTICS.MAGNETICS.MIRNOV.PROBE11 +add node ANGLE/usage=numeric +put ANGLE "30.2" +add node AREA/usage=numeric +put AREA "0.0012005" +add node POL/usage=numeric +put POL "-1" +add node SIG/usage=signal +put SIG "POL * \ISTTOKMARTE::TOP.HARDWARE.ATCA_2.IOP_9.CHANNEL_10.INP_INTEG" +set def \ISTTOKMARTE::TOP.DIAGNOSTICS.MAGNETICS.MIRNOV.PROBE12 +add node ANGLE/usage=numeric +put ANGLE "30.2" +add node AREA/usage=numeric +put AREA "0.0012005" +add node POL/usage=numeric +put POL "1" +add node SIG/usage=signal +put SIG "POL * \ISTTOKMARTE::TOP.HARDWARE.ATCA_2.IOP_9.CHANNEL_11.INP_INTEG" + + +write +close +# set tree isttokmarte +# create pulse 100 +exit +# edit isttokmarte/shot=-1 +#TCL> set def \ISTTOKMARTE::TOP.HARDWARE.ATCA_2.IOP_9.CHANNEL_0 +# TCL> put INP_DECIM "GAIN * ADC_DECIM" +#TCL> put INP_INTEG "GAIN * ADC_INTEG / .HARDWARE.ATCA_2.IOP_9.RT_DECIM / .HARDWARE.ATCA_2.IOP_9.CLOCK_FREQ" + +# TCL> write diff --git a/Trees/IpfnDevices/ATCA_IOP.py b/Trees/IpfnDevices/ATCA_IOP.py new file mode 100644 index 0000000..16139e4 --- /dev/null +++ b/Trees/IpfnDevices/ATCA_IOP.py @@ -0,0 +1,153 @@ +from MDSplus import Device, Data, Range, Dimension, Window, Signal, Int16Array + +NUM_CHANNELS = 16 + +class ATCA_IOP(Device): + """ + ATCA IPFN IOP Digitizer, 16 channel, 18 bit digitizer, Chopper, Integrator + + This class inherits from the generic Device class + Class Device provides the basic methods required by MDSplus, in particular the Add metod + called when a new instance of this device has to be created in a tree in editing + it is therefore only necessary to add here the device specific methods such as init and store + It is however necessary to define the structure of the device, so that the superclass' Add method can + build the appropiate device subtree. This information is specified as a list of dictionaries + every element of the list specifies a node of the subtree associated with the device. The mandatory dictionary items +# for each node are: +# - path : the path name relative to the subtree root of the node +# - type : the type (usage) of the node, which can be either 'text', 'numeric', 'signal', 'action', 'structure' +# optional dictionary items formeach node are: +# - value : initial value forn that node +# - valueExpr : initial value when specified as an expression +# - options : a (list of) NCI options for the tree node, such as 'no_write_model', 'no_write_shot', 'compress_on_put' +# field parts will contain the list of dictionaries, and will be used by Device superclass. +# +# in the following methods, defice fields are referred by the syntax: self., where field_name is derived by the +# path of the corresponding tree node relative to the subtree (as specified by the corresponding path dictionary item), where #letters are lowercase and the dots and colons are replaced by underscores (except the first one). +# For example, tree node :ADDR is accessed by field self.addr and .CHANNEL_1:DATA by field self.channel_1_data +# All there firlds are TreeNode instances and therefore all TreeNode methods such as Data() or putData() can be used. +""" + parts = [ + {'path': ':SLOT', 'type': 'numeric'}, { + 'path': ':COMMENT', 'type': 'text'}, + {'path': ':CLOCK_FREQ', 'type': 'numeric', 'value': 10000}, + {'path': ':RT_DECIM', 'type': 'numeric', 'value': 200}, + {'path': ':TRIG_SOURCE', 'type': 'numeric', 'value': 0}, + {'path': ':ADC_BITS', 'type': 'numeric', 'value': 18}, + ] + + for i in range(NUM_CHANNELS): + parts.extend([ + {'path': '.CHANNEL_%d' % (i), 'type': 'structure'}, + # %.5e" % (10./2**17) + {'path': '.CHANNEL_%d:GAIN' % ( + i), 'type': 'numeric', 'value': 1.73887463e-05}, + {'path': '.CHANNEL_%d:EO_OFFSET' % ( + i), 'type': 'numeric', 'value': 0}, + {'path': '.CHANNEL_%d:WO_OFFSET' % ( + i), 'type': 'numeric', 'value': 0.0}, + {'path': '.CHANNEL_%d:START_IDX' % ( + i), 'type': 'numeric', 'value': 0}, + {'path': '.CHANNEL_%d:END_IDX' % ( + i), 'type': 'numeric', 'value': 1000}, + {'path': '.CHANNEL_%d:ADC_DECIM' % (i), 'type': 'signal'}, + {'path': '.CHANNEL_%d:ADC_DECIM_D' % (i), 'type': 'signal'}, + {'path': '.CHANNEL_%d:INP_DECIM' % (i), 'type': 'signal'}, + # 'value': "GAIN * ADC_DECIM"}, + {'path': '.CHANNEL_%d:ADC_INTEG' % (i), 'type': 'signal'}, + {'path': '.CHANNEL_%d:ADC_INTEG_D' % (i), 'type': 'signal'}, + {'path': '.CHANNEL_%d:INP_INTEG' % (i), 'type': 'signal'}, + # 'value': "GAIN * ADC_INTEG / RT_DECIM / CLOCK_FREQ"}, + ]) + parts.extend([ + {'path': ':INIT_ACTION', 'type': 'action', + 'valueExpr': "Action(Dispatch('ATCA_SERVER','INIT',50,None),Method(None,'init',head))", + 'options': ('no_write_shot',)}, + {'path': ':STORE_ACTION', 'type': 'action', + 'valueExpr': "Action(Dispatch('ATCA_SERVER','STORE',50,None),Method(None,'store',head))", + 'options': ('no_write_shot',)}, + ]) + del( i) + +# {'path': '.CHANNEL_%d:ADC_INTEG' % (i), 'type': 'signal', 'options': ( +# 'no_write_model', 'compress_on_put')}, +# ----------------INIT------------------- +# init method, called to configure the ADC device. It will read configuration from the corresponding subtree +# and it will download configuration to the device + def init(self): + # Need to import some classes from MDSplus package + # The device will be configured via a shared library (libDemoAdc in the MDSplus distribution) defining the following routines: + # initialize(char *addr, int clockFreq, int postTriggerSamples) + # where clockFreq can have the following values: + # - 1 -> clock freq. = 1KHz + # - 2 -> clock freq. = 5KHz + # - 3 -> clock freq. = 10KHz + # - 4 -> clock freq. = 50 KHz + # - 5 -> clock freq. = 100KHz + # trigger(char *addr) + # acquire(char *addr, short *c1, short *c2 short *c3, short *c4) + # the routine acquire returns 4 simulated sinusoidal waveform signals at the following frequencies: + # Channel 1: 10Hz + # Channel 2: 50 Hz + # Channel 3: 100 Hz + # Channel 4: 200Hz + # + # The addr argument passed to all device routines is not used and simulates the device identifier + # used in real devices + # + + # return success + return 1 + +# -------------STORE################################################ +# store method, called to get samples from the ADC and to store waveforms in the tree + def store(self): + # import required symbols from MDSSplus and ctypes packages + + # return success (odd numbers in MDSplus) + return 1 + + +""" +# in the following, we'll get data items in two steps (on the same line): +# 1) instantiate a TreeNode object, passing the integer nid to the constructor +# 2) read and evaluate (in the case the content is an expression) its content via TreeNode.data() method +# all data access operation will be but in a try block in order to check for missing or wrong configuration data + try: + address = self.addr.data() +# we expect to get a string in addr + except: + print ('Missing addr in device') + return 0 + +# read the clock frequency and convert to clock mode. We use a dictionary for the conversion, and assume + clockDict = {1000: 1, 5000: 2, 10000: 3, 50000: 4, 100000: 5} + try: + clockFreq = self.clock_freq.data() + clockMode = clockDict[clockFreq] + except: + print ('Missing or invalid clock frequency') + return 0 + +# read Post Trigger Samples and check for consistency + try: + pts = self.pts.data() + except: + print ('Missing or invalid Post Trigger Samples') + return 0 + +# all required configuation collected. Call external routine initialize passing the right parameters +# we use ctypes functions to convert python variable to appropriate C types to be passed to the external routine +# try: + print(address) + deviceLibCDLL.initialize( + c_char_p(address.encode()), c_int(clockMode), c_int(pts)) + #try: + # deviceLibCDLL.initialize( + # c_char_p(address), c_int(clockMode), c_int(pts)) + #except: + # print('Error initializing driver') + # return 0 +""" + +