;Keysight DSO-X 2014A
;2022/1/25  REV A shows example with each channel measuring a different way
:2022/1/25  added wavegen shutoff and rearranged the setup menu
;2022/1/22  bicycleguy copied from gby Tektronix MDO3000, MDO4000, MSO4000, DPO400 Oscilloscopes

; Trying to test with Keysight (AGILENT TECHNOLOGIES) DSO-X 2014A over Ethernet.
; By adding metadef entries probably would work with:
; xx and possibly others.
; This file does not change inteface for 2 versus 4 channels.
; To make usage simple, all supported devices have the same handle name.

;Socket interface and LXI are possible.  This uses LXI interface by default.

;*IDN? returns: AGILENT TECHNOLOGIES,<Model>,<Serial Num>,<FW version num>

;Log values are alphabetized by handle name.  To help get log data order the same below
;uses "hack" of starting each handle name with letter "M" even if actual name does not.

#metadef 
#idstring AGILENT TECHNOLOGIES,DSO-X 2014A, 
#name Keysight DS0X2014A
#replaceText MaxCH 4 
#replaceText MaxBW 200M 
#replaceText MaxSample 2..0G 
#sections QuadMode QuadSetup QuadInterface ReadStandard

#metadef 
#idstring AGILENT TECHNOLOGIES,DSO-X 2012A, 
#name Keysight DS0X2012A
#replaceText MaxCH 2 
#replaceText MaxBW 100M 
#replaceText MaxSample 2..0G 
#sections DualInterface ReadStandard

#metadef 
#idstring AGILENT TECHNOLOGIES,DSO-X 2024A, 
#name Keysight DS0X2024A
#replaceText MaxCH 4 
#replaceText MaxBW 200M 
#replaceText MaxSample 2..0G 
#sections QuadMode QuadSetup QuadInterface ReadStandard

#meta
#idstring AGILENT TECHNOLOGIES,DSO-X 2014A
#name Keysight DS0X2014A
#handle DSOX2014A
#port LXI
#author bicycleguy
#notes This file supports and has been partially tested with a Keysight DS0X2014A oscilloscope communicating over Ethernet.  It probably would support other Agilent and KeySight scope family by adding appriopriate #metadef sections.  Logs the 4 channel measurements.  Uses LXI communications only.

; A list of possible column name with unit and formatter (SI, Time, Int, D0..D6) 
; Format: #value ColumnName Unit Format {Selector}
; Selector is only used when column layout varies with mode, this often require the use of #cmdMode
#Value Meas1 V SI 
#Value Meas2 Vpp SI 
#Value Meas3 Vavg SI 
#Value Meas4 Vrms SI

; How to poll for data, this is used for table and #values?
; a #askMode, #cmdMode and #prepareSample is used before this is string is used.--
; Number of returned values must match number of columns defined with #value
; This is a single line command

#askValues 
:MEAS:VAMP? CHAN1;:MEAS:VPP? CHAN2;:MEAS:VAV? CHAN3;:MEAS:VRMS? CHAN4
;:MEAS:VAMP? CHAN1;:MEAS:VAMP? CHAN2;:MEAS:VAMP? CHAN3;:MEAS:VAMP? CHAN4
;:MEAS:VAMP? CHAN1;:MEAS:VAMP? CHAN2;:MEAS:VAMP? CHAN3;:MEAS:PHAS? CHAN1,CHAN2


; Format of answer: f=float, u=remove trailing letters, x=skip, *=Zero upper case values if this value is 0
; MDO3000 and others echo the command with the number and need readformat xf to skip over the command echo.
; DSOX does not echo the command and needs readformat just ffff
#metaSection ReadSkip
#askValuesReadFormat xFxFxFxFxF
#metaSection

#metaSection ReadStandard
#askValuesReadFormat FFFFF
#metaSection

; There must be a line for each of the original device commands that will be used, converting it to a similar SCPI command
;#scpiCmd init tx command to init
;#scpiCmd values? txrx? command to read current value or values. It is possible to define value1?, value2?, etc. and then use them all with a ; between in the #askValues statement.

; Accept this delay when reading values (seconds)
#readingDelay 2

; Mode change have a longer delay on reading values (seconds)
#modeChangeDelay 10


; String to ask about actual meter mode, it is mostly used for DMM's
; This is a single line command
;#askMode 


; When one of these commands are used through the command interface a new configuration will be done before using #askMode
; Only one word for each #mayModifyMode
; Specify command without initial colon and in the shortest possible form
;#mayModifyMode 


; Prepare the meter to response to #askValues
;#prepareSample arm:sour imm;:arm:count 1;:trig:sour imm;:trig:count 1;:trig:samp:count 1;init

; Initial commands to meter when establishing connection, used to disable local control
;#initCmd  

; Final command to meter before breaking connection, used to restore local control
;#finalCmd 

; Used to turn output off for power supplies, generators and electronic loads
;Also AXIS2.DIS?; for dual axis.  Delay at end add ;[xxx] for xxx mSec delay after.
;#outputOff 
#outputOff :WGEN:OUTPut 0

#metaSection DualInterface
#interfaceType OSC OSC:2
#metaSection

#metaSection QuadInterface
#interfaceType OSC OSC:2 OSC:3 OSC:4
#metaSection

;********  Scope channel set ups.
; Using multi-channel interface in scripts requires vars set for OSC:2, OSC:3, etc in scripts.
; For example:
;  =var osc1=getDevice("OSC")
;  =var osc2=getDevice("OSC:2")
;  =var osc3=getDevice("OSC:3")

#interface setCHCoupling CH(channel):COUPLING (value)
#interface getCHCoupling CH(channel):COUPLING?
:readmath: getMatch(value, "[a-zA-Z]*$")
:string:

#interface setCHScale CH(channel):SCALE (value)
#interface getCHScale CH(channel):SCALE?
:readmath: getMatch(value, "( |^)[-+.0-9].*")

#interface setCHBW CH(channel):BWLimit (value)
#interface getCHBW CH(channel):BWLimit?
:readmath: getMatch(value, "( |^)[-+.0-9].*")

#interface setCHTermination CH(channel):TERMINATION (value)
#interface getCHTermination CH(channel):TERMINATION?
:readmath: getMatch(value, "( |^)[-+.0-9].*")

#interface setCHState SELECT:CH(channel) (value)
#interface getCHState SELECT:CH(channel)?
:readmath: getMatch(value, "( |^)[-+.0-9].*")

;************* Measurement 1-n set up and read
;  Usage is setXXX(<device handle>+":n", <value>)
;           getXXX(<device handle>+":n")
;  where n is the measurement number.  Tyically only 1 through 4 for dual or quad channel scopes.
;  Newer Series 5, Series 6 scopes might have more measurement channels depending.
#interface setMeasSource1 MEASUREMENT:MEAS(channel):SOURCE1 (value)
#interface getMeasSource1 MEASUREMENT:MEAS(channel):SOURCE1?
:readmath: getMatch(value, "[a-zA-Z0-9]*$")
:string:

#interface setMeasSource2 MEASUREMENT:MEAS(channel):SOURCE2 (value)
#interface getMeasSource2 MEASUREMENT:MEAS(channel):SOURCE2?
:readmath: getMatch(value, "[a-zA-Z0-9]*$")
:string:

#interface setMeasType MEASUREMENT:MEAS(channel):TYPE (value)
#interface getMeasType MEASUREMENT:MEAS(channel):TYPE?
:readmath: getMatch(value, "[a-zA-Z]*$")
:string:

#interface setMeasState MEASUREMENT:MEAS(channel):STATE (value)
#interface getMeasState MEASUREMENT:MEAS(channel):STATE?
;:readmath: formatInt(getMatch(value, "( |^)[-+.0-9].*"),1,1)
:readmath: getMatch(value, "( |^)[-+.0-9].*")

#interface getMeasValue MEASUREMENT:MEAS(channel):VALUE?
:readmath: getMatch(value, "( |^)[-+.0-9].*")

#interface getMeasMean MEASUREMENT:MEAS(channel):MEAN?
:readmath: getMatch(value, "( |^)[-+.0-9].*")

#interface getMeasMin MEASUREMENT:MEAS(channel):MINI?
:readmath: getMatch(value, "( |^)[-+.0-9].*")

#interface getMeasMax MEASUREMENT:MEAS(channel):MAXI?
:readmath: getMatch(value, "( |^)[-+.0-9].*")

#interface getMeasStdDev MEASUREMENT:MEAS(channel):STDDEV?
:readmath: getMatch(value, "( |^)[-+.0-9].*")

;************* Measurement I(mmediate) set up and read

#interface setMeasISource1 MEASUREMENT:IMMED:SOURCE1 (value)
#interface getMeasISource1 MEASUREMENT:IMMED:SOURCE1?
:readmath: getMatch(value, "[a-zA-Z0-9]*$")
:string:

#interface setMeasISource2 MEASUREMENT:IMMED:SOURCE2 (value)
#interface getMeasISource2 MEASUREMENT:IMMED:SOURCE2?
:readmath: getMatch(value, "[a-zA-Z0-9]*$")
:string:

#interface setMeasIType MEASUREMENT:IMMED:TYPE (value)
#interface getMeasIType MEASUREMENT:IMMED:TYPE?
:readmath: getMatch(value, "[a-zA-Z]*$")
:string:

#interface getMeasIValue MEASUREMENT:IMMED:VALUE?
:readmath: getMatch(value, "( |^)[-+.0-9].*")


;*********  Horizontal setups
#interface setHorizontalScale HORIZONTAL:SCALE (value)
#interface getHorizontalScale HORIZONTAL:SCALE?
:readmath: getMatch(value, "( |^)[-+.0-9].*")

;*********  Acquire Mode Commands
#interface setAcquireMode ACQUIRE:MODE (value)
#interface getAcquireMode ACQUIRE:MODE?
:readmath: getMatch(value, "[a-zA-Z]*$")
:string:

#interface setRecordLength HORIZONTAL:RECORDLENGTH (value)
#interface getRecordLength HORIZONTAL:RECORDLENGTH?
:readmath: getMatch(value, "[0-9]*$")

;*********  Trigger Commands
#interface setForceTrigger TRIGGER FORCE

#interface setTriggerCoupling TRIGGER:A:EDGE:COUPLING (value)
#interface getTriggerCoupling TRIGGER:A:EDGE:COUPLING?
:readmath: getMatch(value, "[a-zA-Z]*$")
:string:

#interface setTriggerSource TRIGGER:A:EDGE:SOURCE (value)
#interface getTriggerSource TRIGGER:A:EDGE:SOURCE?
:readmath: getMatch(value, "[a-zA-Z0-9]*$")
:string:

#interface setTriggerSlope TRIGGER:A:EDGE:SLOPE (value)
#interface getTriggerSlope TRIGGER:A:EDGE:SLOPE?
:readmath: getMatch(value, "[a-zA-Z]*$")
:string:

#interface setTriggerLevel TRIGGER:A:LEVEL (value)
#interface getTriggerLevel TRIGGER:A:LEVEL?
:readmath: getMatch(value, "( |^)[-+.0-9].*")

#interface setTriggerType TRIGGER:A:TYPE (value)
#interface getTriggerType TRIGGER:A:TYPE?
:readmath: getMatch(value, "[a-zA-Z]*$")
:string:

#interface setTriggerMode TRIGGER:A:MODE (value)
#interface getTriggerMode TRIGGER:A:MODE?
:readmath: getMatch(value, "[a-zA-Z]*$")
:string:


;*********  MATH Channel Commands
#interface setMath1Type MATH1:TYPE (value)
#interface getMath1Type MATH1:TYPE?
:readmath: getMatch(value, "[a-zA-Z]*$")
:string:

#interface setMath1Definition MATH1:DEFINE ("\""+value+"\"")
#interface getMath1Definition MATH1:DEFINE?
;:readmath: getMatch(value, "[a-zA-Z]*$")
:readmath: getMatch(value, "\"(.*)\"")
:string:

#interface setMath1State SELECT:MATH (value)
#interface getMath1State SELECT:MATH?
:readmath: getMatch(value, "( |^)[-+.0-9].*")

#interface setMath1Scale MATH1:VERTICAL:SCALE (value)
#interface getMath1Scale MATH1:VERTICAL:SCALE?
:readmath: getMatch(value, "( |^)[-+.0-9].*")

; Acquisition Channel On/Off Popup.  Note:  Does not remove channels for 2 channel scopes.

#cmdModeLayout 2 4

#cmdMode CH1_On _ :CHAN1:DISP 1
#cmdMode CH1_Off _ :CHAN1:DISP 0
#cmdMode CH2_On _ CHAN2:DISP 1
#cmdMode CH2_Off _ CHAN2:DISP 0

#metaSection QuadMode
;Section for channels 3 and 4 only on quad channel scopes.

#cmdMode CH3_On _ CHAN3:DISP 1
#cmdMode CH3_Off _ CHAN3:DISP 0
#cmdMode CH4_On _ CHAN4:DISP 1
#cmdMode CH4_Off _ CHAN4:DISP 0

;#cmdModeCheck DoIT m2 0
;[localmode] CHAN4:DISP 1
;[localmode] CHAN4:DISP 0

#metaSection


; Main tabbed popup for controlling each channel individually.

; ************  Channel 1 tab   **********************************
#cmdSetup color _ CH_1
(255,255,128)

#cmdSetup buttonsOn CH1_Display CH_1
:read: :CHAN1:DISP?
:readMath: getMatch(value, "( |^)[-+.0-9].*")
:write: :CHAN1:DISP
:color: (255,255,128)
:tip: Turns CH1 display on or off
Off 0
On 1

#cmdSetup number Volts/Division CH_1
:read: CHAN1:SCALE?
:readmath: getMatch(value, "( |^)[-+.0-9].*")
:write: CHAN1:SCALE
:tip: Volts/Division command sets the vertical sensitivity in Volts/div.
V .010 50

#cmdSetup button Zero_Position CH_1
:write: CHAN1:OFFSET 0
:tip: The Zero Position button will put 0 signal mid screen.

#cmdSetup comboboxhot Coupling CH_1
:read: CHAN1:COUPLING?
:readmath: getMatch(value, "\\b(\\w+)\\s*$")
:write: CHAN1:COUPLING
:tip: The Coupling command selects the coupling mode of the specified input channel.
DC DC
AC AC

#cmdSetup radio Bandwidth_Limit CH_1
:read: CHAN1:BWLimit?
:readmath: getMatch(value, "( |^)[-+.0-9].*")
:write: CHAN1:BWLimit (value)
:tip: Sets the bandwidth limit in MHz.
20M 1
Full 0

#cmdSetup radio Invert CH_1
:read: CHAN1:INVERT?
:readmath: getMatch(value, "( |^)[-+.0-9].*")
:write: CHAN1:INVERT
:tip: Normal or invert/times -1.
Off 0
On 1

; ************  Channel 2 tab   **********************************
#cmdSetup color _ CH_2
(0,255,255)

#cmdSetup buttonsOn CH2_Display CH_2
:read: :CHAN2:DISP?
:readMath: getMatch(value, "( |^)[-+.0-9].*")
:write: :CHAN2:DISP
:color: (0,255,255)
:tip: Turns CH2 display on or off
Off 0
On 1

#cmdSetup number Volts/Division CH_2
:read: CHAN2:SCALE?
:readmath: getMatch(value, "( |^)[-+.0-9].*")
:write: CHAN2:SCALE
:tip: Volts/Division command sets the vertical sensitivity in Volts/div.
V .010 50

#cmdSetup button Zero_Position CH_2
:write: CHAN2:OFFSET 0
:tip: The Zero Position button will put 0 signal mid screen.

#cmdSetup comboboxhot Coupling CH_2
:read: CHAN2:COUPLING?
:readmath: getMatch(value, "\\b(\\w+)\\s*$")
:write: CHAN2:COUPLING
:tip: The Coupling command selects the coupling mode of the specified input channel.
DC DC
AC AC

#cmdSetup radio Bandwidth_Limit CH_2
:read: CHAN2:BWLimit?
:readmath: getMatch(value, "( |^)[-+.0-9].*")
:write: CHAN2:BWLimit (value)
:tip: Sets the bandwidth limit in MHz.
20M 1
Full 0

#cmdSetup radio Invert CH_2
:read: CHAN2:INVERT?
:readmath: getMatch(value, "( |^)[-+.0-9].*")
:write: CHAN2:INVERT
:tip: Normal or invert/times -1.
Off 0
On 1

#metaSection QuadSetup
;Section for channels 3 and 4 only on quad channel scopes.

; ************  Channel 3 tab   **********************************
#cmdSetup color _ CH_3
(255,0,255)

#cmdSetup buttonsOn CH3_Display CH_3
:read: :CHAN3:DISP?
:readMath: getMatch(value, "( |^)[-+.0-9].*")
:write: :CHAN3:DISP
:color: (255,0,255)
:tip: Turns CH3 display on or off
Off 0
On 1

#cmdSetup number Volts/Division CH_3
:read: CHAN3:SCALE?
:readmath: getMatch(value, "( |^)[-+.0-9].*")
:write: CHAN3:SCALE
:tip: Volts/Division command sets the vertical sensitivity in Volts/div.
V .010 50

#cmdSetup button Zero_Position CH_3
:write: CHAN3:OFFSET 0
:tip: The Zero Position button will put 0 signal mid screen.

#cmdSetup comboboxhot Coupling CH_3
:read: CHAN3:COUPLING?
:readmath: getMatch(value, "\\b(\\w+)\\s*$")
:write: CHAN3:COUPLING
:tip: The Coupling command selects the coupling mode of the specified input channel.
DC DC
AC AC

#cmdSetup radio Bandwidth_Limit CH_3
:read: CHAN3:BWLimit?
:readmath: getMatch(value, "( |^)[-+.0-9].*")
:write: CHAN3:BWLimit (value)
:tip: Sets the bandwidth limit in MHz.
20M 1
Full 0

#cmdSetup radio Invert CH_3
:read: CHAN3:INVERT?
:readmath: getMatch(value, "( |^)[-+.0-9].*")
:write: CHAN3:INVERT
:tip: Normal or invert/times -1.
Off 0
On 1

; ************  Channel 4 tab   **********************************
#cmdSetup color _ CH_4
(0,166,0)

#cmdSetup buttonsOn CH4_Display CH_4
:read: :CHAN4:DISP?
:readMath: getMatch(value, "( |^)[-+.0-9].*")
:write: :CHAN4:DISP
:color: (0,166,0)
:tip: Turns CH4 display on or off
Off 0
On 1

#cmdSetup number Volts/Division CH_4
:read: CHAN4:SCALE?
:readmath: getMatch(value, "( |^)[-+.0-9].*")
:write: CHAN4:SCALE
:tip: Volts/Division command sets the vertical sensitivity in Volts/div.
V .010 50

#cmdSetup button Zero_Position CH_4
:write: CHAN4:OFFSET 0
:tip: The Zero Position button will put 0 signal mid screen.

#cmdSetup comboboxhot Coupling CH_4
:read: CHAN4:COUPLING?
:readmath: getMatch(value, "\\b(\\w+)\\s*$")
:write: CHAN4:COUPLING
:tip: The Coupling command selects the coupling mode of the specified input channel.
DC DC
AC AC

#cmdSetup radio Bandwidth_Limit CH_4
:read: CHAN4:BWLimit?
:readmath: getMatch(value, "( |^)[-+.0-9].*")
:write: CHAN4:BWLimit (value)
:tip: Sets the bandwidth limit in MHz.
20M 1
Full 0

#cmdSetup radio Invert CH_4
:read: CHAN4:INVERT?
:readmath: getMatch(value, "( |^)[-+.0-9].*")
:write: CHAN4:INVERT
:tip: Normal or invert/times -1.
Off 0
On 1

#metaSection

; ************  Horizontal/trig   **********************************

#cmdSetup number Time/Division
:read: :TIMebase:SCALe?
:readmath: getMatch(value, "( |^)[-+.0-9].*")
:write: :TIMebase:SCALe
:tip: Sets the horizontal time per division in sec.
Sec 2e-9 50

#cmdSetup comboboxhot Aquire_Mode
:read: ACQuire:TYPE?
:readmath: getMatch(value, "[a-zA-Z]*$")
:write: ACQuire:TYPE
:tip: Sets how points are sampled.
Normal NORM
Peak_Detect PEAK
Hi_Res HRES
Average AVER

#cmdSetup radio Trigger_Mode
:read: :TRIGger:SWEep?
:readmath: getMatch(value, "[a-zA-Z]*$")
:string:
:write: :TRIGger:SWEep
:tip: Sets trigger mode; auto retrigger or only on valid trigger.
Auto AUTO
Normal NORM

#cmdSetup comboboxhot Trigger_Source
:read: :TRIGger:EDGE:SOURce?
:readmath: getMatch(value, "[a-zA-Z0-9]*$")
:write: :TRIGger:EDGE:SOURce 
:tip: Selects source signal for trigger.
CH1 CHAN1
CH2 CHAN2
CH3 CHAN3
CH4 CHAN4
LINE LINE
Wave_gen WGEN
D0 DIG0
D1 DIG1
D2 DIG2
D3 DIG3
D4 DIG4
External EXT

#cmdSetup comboboxhot Trigger_Slope
:read: TRIGGER:EDGE:SLOPE?
:readmath: getMatch(value, "[a-zA-Z]*$")
:string:
:write: TRIGGER:EDGE:SLOPE
:tip: Normal or invert/times -1.
Rising POS
Falling NEG
Either EITH
Alternate ALT

#cmdSetup comboboxhot Trigger_Coupling
:read: TRIGGER:EDGE:COUPLING?
:readmath: getMatch(value, "[a-zA-Z]*$")
:write: TRIGGER:EDGE:COUPLING
:tip: Sets coupling method to trigger circuit.
DC DC
AC AC
LF_Reject LFR

#cmdSetup number Trigger_Level
:read: TRIGGER:EDGE:LEVEL?
:readmath: getMatch(value, "( |^)[-+.0-9].*")
:write: TRIGGER:EDGE:LEVEL
:tip: Sets the level for edge triggering.
V -1e6 1e6
