; Aim TTi (THURLBY THANDAR) CPX series power supplies
; Note, there is a rebrand of these supplies as Sorensen XPF series.
; Serial communications is not supported with this device file only
;     LXi via Ethernet
;     Port 9221 via Ethernet
;     LXi via USB should work if driver is installed.
;     LXi, Port tested via Ethernet
; 
; 12/29/2020 Rev A   Originate based on Keithley 2260B series file

; Manual is here: https://lygte-info.dk/project/TestControllerConfigDevice%20UK.html

; There are 7 power supplies in this Aim TTi CPX family but only 3 with computer control interfaces.
; Model				W		V		A		Type
; CPX200DP	 		180W	0~60V	0~10A	Dual
; CPX400SP			420W	0~60V	0~20A	Single
; CPX400DP			840W	0~60V	0~20A	Dual

; Below are the Sorensen re-brands:
; Model				W		V		A		Type
; XPF 60-20P		420W	0~60V	0~20A	Single
; XPF 60-20DP		840W	0~60V	0~20A	Dual

; Has a web page at <ip> address.
;  If there is a password and you don't know it, push the LAN RESET button in on the rear panel.
; Below range limits includes the 10% overage on V, I and 10% to 110% on protection limits.

; Tested min long time logging interval is 100 mSec for On/Off, V, I for a dual unit.  70 mSec short duration.

; Remote connection turns front panel off.

#metadef
#idstring THURLBY THANDAR, CPX200DP
#name Aim TTi CPX200DP
#handle CPX200DP
#replaceText MaxVoltage 60
#replaceText MaxCurrent 10
#replaceText MaxWatt 180
#replaceText MinPVolt 1
#replaceText MaxPVolt 66
#replaceText MinPCurrent 0.01
#replaceText MaxPCurrent 11
#sections Dual

#metadef
#idstring THURLBY THANDAR, CPX400SP
#name Aim TTi CPX400SP
#handle CPX400SP
#replaceText MaxVoltage 60
#replaceText MaxCurrent 10
#replaceText MaxWatt 180
#replaceText MinPVolt 1
#replaceText MaxPVolt 66
#replaceText MinPCurrent 0.01
#replaceText MaxPCurrent 22
#sections Dual

#metadef
#handle CPX400DP
#replaceText MaxVoltage 60
#replaceText MaxCurrent 20
#replaceText MaxWatt 420
#replaceText MinPVolt 1
#replaceText MaxPVolt 66
#replaceText MinPCurrent 0.01
#replaceText MaxPCurrent 22
#sections Dual

#meta
#idstring THURLBY THANDAR, CPX400DP
#name Aim TTi CPX400DP
#handle CPX400DP
; Per manual "The port number is fixed at 9221."
#port LXI 9221 com
#author gby
#notes Supports Aim TTi (Thurlby and Thandar) CPX series power supplies that are programmable: CPX200P, CPX200DP, and CPX400D.  Tested with CPX400DP.  LXI interface not working???


; 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 CH1_On - D0
#value CH1_Voltage Vdc D3 
#value CH1_Current Adc D3
#value CH2_On - D0
#value CH2_Voltage Vdc D3 
#value CH2_Current Adc D3

; 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 OP1?;V1O?;I1O?;OP2?;V2O?;I2O?

; Format of answer: f=float, u=remove trailing letters, x=skip, *=Zero upper case values if this value is 0
#askValuesReadFormat fuufuu

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

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


; 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
#outputOff OPALL 0


;  **********  Generic Power Supply Interface  *******
;  Modeled after existing Keithley 2280 series power supply from 10/19/20
; Using multi-channel interface in scripts requires vars set for PS, PS:2 in scripts.
; For example:
;  =var PS1=getDevice("PS")
;  =var PS2=getDevice("PS:2")

#metaSection Single
#interfaceType PS
#metaSection

#metaSection Dual
#interfaceType PS PS:2
#metaSection

#interface setCHVoltage V(channel) (value)
#interface getCHVoltage V(channel)?
:readmath: getMatch(value, "( |^)[-+.0-9].*")

#interface setCHCurrent I(channel) (value)
#interface getCurrent I(channel)?
:readmath: getMatch(value, "( |^)[-+.0-9].*")

#interface setOVP OVP(channel) (value)
#interface getOVP OVP(channel)?
:readmath: getMatch(value, "( |^)[-+.0-9].*")

#interface setOCP OCP(channel) (value)
#interface getOCP OCP(channel)?
:readmath: getMatch(value, "( |^)[-+.0-9].*")

#interface setOn OP(channel) (value)
#interface getOn OP(channel)?
:readmath: getMatch(value, "( |^)[-+.0-9].*")

#interface setAllOn OPALL (value)
#interface getAllOn OPALL?
:readmath: getMatch(value, "( |^)[-+.0-9].*")

#interface SetTripReset TRIPRST

;  Pull values from #askValues used for logging.  Index goes 0 to n.
#interface readCH1Current 2
#interface readCH1Voltage 1

#metaSection Dual
; CONFIG set to 2 is two independent supplies.  Set to 0 for tracking mode.
#interface setMode CONFIG (value)
#interface getMode CONFIG?

#interface readCH2Current 5
#interface readCH2Voltage 4

; 0 is Track and 2 is independent
#interface setConfig (value)
#metaSection

; **********  Mode Popup Turn Supply On/Off   ***********

#metaSection Single
#cmdModeLayout 2 1
#metaSection

#metaSection Dual
#cmdModeLayout 2 3
#metaSection
 

#cmdMode _V1_Off_ _
OP1 0

#cmdMode _V1_On_ _
OP1 1

; ************  Additions For Dual Supply   **********************************

#metaSection Dual
#cmdMode _V2_Off_ _
OP1 0

#cmdMode _V2_On_ _
OP1 1

#cmdMode _All_Off_ _
OPALL 0

#cmdMode _All_On_ _
OPALL 1
#metaSection

; **********  Setup Popup   ***********

#cmdSetup number CH1_V Settings
:read: V1?
:readmath: getMatch(value, "( |^)[-+.0-9].*")
:write: V1
Vdc  0 MaxVoltage

#cmdSetup number CH1_I Settings
:read: I1?
:readmath: getMatch(value, "( |^)[-+.0-9].*")
:write: I1
Adc  0 MaxCurrent

#metaSection Dual
#cmdSetup number CH2_V Settings
:read: V2?
:readmath: getMatch(value, "( |^)[-+.0-9].*")
:write: V2
Vdc  0 MaxVoltage

#cmdSetup number CH2_I Settings
:read: I2?
:readmath: getMatch(value, "( |^)[-+.0-9].*")
:write: I2
Adc  0 MaxCurrent
#metaSection

#cmdSetup number Voltage Protect_Limits
:read: OVP1?
:readmath: getMatch(value, "( |^)[-+.0-9].*")
:write: OVP1
Vdc  MinPVolt MaxPVolt

#cmdSetup number Current Protect_Limits
:read: OCP1?
:readmath: getMatch(value, "( |^)[-+.0-9].*")
:write: OCP1
Adc  MinPCurrent MaxPCurrent

#metaSection Dual
#cmdSetup number Voltage Protect_Limits
:read: OVP2?
:readmath: getMatch(value, "( |^)[-+.0-9].*")
:write: OVP2
Vdc  MinPVolt MaxPVolt

#cmdSetup number Current Protect_Limits
:read: OCP2?
:readmath: getMatch(value, "( |^)[-+.0-9].*")
:write: OCP2
Adc  MinPCurrent MaxPCurrent
#metaSection

#cmdSetup buttonsOn CH1
:read: OP1?
:write: OP1
:color: (0,255,0)
:tip: Turn output on or off
:updatealloff:
Off 0
On 1

#metaSection Dual
#cmdSetup buttonsOn CH2
:read: OP2?
:write: OP2
:color: (0,255,0)
:tip: Turn output on or off
:updatealloff:
Off 0
On 1
#metaSection

#cmdSetup radio V1_Pre
:read: V1?
:readmath: getMatch(value, "( |^)[-+.0-9].*")
:update: Voltage
:write: V1
3.3_V 3.3
5_V 5
12_V 12
24_V 24

#metaSection Dual
#cmdSetup radio V2_Pre
:read: V2?
:readmath: getMatch(value, "( |^)[-+.0-9].*")
:update: Voltage
:write: V2
3.3_V 3.3
5_V 5
12_V 12
24_V 24

#cmdSetup radio Tracking
:read: CONFIG?
:readmath: 
:write: CONFIG
Independent 2
Tracking 0
#metaSection