From 0e7401efac321026d4f6cc101d0831bfe15c7cde Mon Sep 17 00:00:00 2001 From: Ian Gillingham Date: Tue, 11 Mar 2025 12:58:24 +0000 Subject: [PATCH 01/29] Range change time delay --- G3HALLPR/iocBoot/iocG3HALLPR-IOC-01/st-common.cmd | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/G3HALLPR/iocBoot/iocG3HALLPR-IOC-01/st-common.cmd b/G3HALLPR/iocBoot/iocG3HALLPR-IOC-01/st-common.cmd index ef31c2774..5e9721db8 100644 --- a/G3HALLPR/iocBoot/iocG3HALLPR-IOC-01/st-common.cmd +++ b/G3HALLPR/iocBoot/iocG3HALLPR-IOC-01/st-common.cmd @@ -33,9 +33,9 @@ epicsEnvSet("P", "$(MYPVPREFIX)$(IOCNAME):") ## Load our record instances dbLoadRecords("$(G3HALLPR)/db/group3hallprobe.db","PVPREFIX=$(MYPVPREFIX),P=$(P),RECSIM=$(RECSIM=0),DISABLE=$(DISABLE=0),PORT=$(DEVICE)") -dbLoadRecords("$(G3HALLPR)/db/group3hallprobe_probe.db","P=$(P),SENSORID=0,ADDR=$(ADDR0=0),PORT=$(DEVICE),NAME=$(NAME0=probe0),SCALE=$(SCALE0=1),FIELD_SCAN_RATE=$(FIELD_SCAN_RATE=1 second),TEMP_SCAN_RATE=$(TEMP_SCAN_RATE=5 second),FLNK=$(FLNK0=)") -dbLoadRecords("$(G3HALLPR)/db/group3hallprobe_probe.db","P=$(P),SENSORID=1,ADDR=$(ADDR1=1),PORT=$(DEVICE),NAME=$(NAME1=probe1),SCALE=$(SCALE1=1),FIELD_SCAN_RATE=$(FIELD_SCAN_RATE=1 second),TEMP_SCAN_RATE=$(TEMP_SCAN_RATE=5 second),FLNK=$(FLNK1=)") -dbLoadRecords("$(G3HALLPR)/db/group3hallprobe_probe.db","P=$(P),SENSORID=2,ADDR=$(ADDR2=2),PORT=$(DEVICE),NAME=$(NAME2=probe2),SCALE=$(SCALE2=1),FIELD_SCAN_RATE=$(FIELD_SCAN_RATE=1 second),TEMP_SCAN_RATE=$(TEMP_SCAN_RATE=5 second),FLNK=$(FLNK2=)") +dbLoadRecords("$(G3HALLPR)/db/group3hallprobe_probe.db","PVPREFIX=$(MYPVPREFIX),IOCNAME=$(IOCNAME),P=$(P),SENSORID=0,ADDR=$(ADDR0=0),PORT=$(DEVICE),NAME=$(NAME0=probe0),SCALE=$(SCALE0=1),FIELD_SCAN_RATE=$(FIELD_SCAN_RATE=1 second),TEMP_SCAN_RATE=$(TEMP_SCAN_RATE=5 second),FLNK=$(FLNK0=)") +dbLoadRecords("$(G3HALLPR)/db/group3hallprobe_probe.db","PVPREFIX=$(MYPVPREFIX),IOCNAME=$(IOCNAME),P=$(P),SENSORID=1,ADDR=$(ADDR1=1),PORT=$(DEVICE),NAME=$(NAME1=probe1),SCALE=$(SCALE1=1),FIELD_SCAN_RATE=$(FIELD_SCAN_RATE=1 second),TEMP_SCAN_RATE=$(TEMP_SCAN_RATE=5 second),FLNK=$(FLNK1=)") +dbLoadRecords("$(G3HALLPR)/db/group3hallprobe_probe.db","PVPREFIX=$(MYPVPREFIX),IOCNAME=$(IOCNAME),P=$(P),SENSORID=2,ADDR=$(ADDR2=2),PORT=$(DEVICE),NAME=$(NAME2=probe2),SCALE=$(SCALE2=1),FIELD_SCAN_RATE=$(FIELD_SCAN_RATE=1 second),TEMP_SCAN_RATE=$(TEMP_SCAN_RATE=5 second),FLNK=$(FLNK2=)") ##ISIS## Stuff that needs to be done after all records are loaded but before iocInit is called < $(IOCSTARTUP)/preiocinit.cmd From 9452eaae64201fe459bf05d192441bcdd4585727 Mon Sep 17 00:00:00 2001 From: Ian Gillingham Date: Tue, 25 Mar 2025 10:55:03 +0000 Subject: [PATCH 02/29] IPS: work around limitation of getting legacy status from SCPI protocol --- IPS/IPS-IOC-01App/Db/ips.db | 41 +++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/IPS/IPS-IOC-01App/Db/ips.db b/IPS/IPS-IOC-01App/Db/ips.db index a820c7c22..609ab482c 100644 --- a/IPS/IPS-IOC-01App/Db/ips.db +++ b/IPS/IPS-IOC-01App/Db/ips.db @@ -554,6 +554,47 @@ record(ai, "$(P)MAGNET:INDUCTANCE") { info(archive, "VAL") } +# --------------- The following work around limitation of getting legacy status from SCPI protocol ------------- + +# Get the status DWORD from each group UID +record(mbbiDirect, "$(P)GET:MAGNET:SUPPLY:STATUS") { + field(DESC, "Examine status") + field(DTYP, "stream") + field(INP, "@OxInstIPS.protocol getMagnetSupplyStatus($(P)) $(PORT)") + field(NOBT, "32") + field(SCAN, "1 second") + + field(SIML, "$(P)SIM") + field(SIOL, "$(P)SIM:DONOTHING") + field(SDIS, "$(P)DISABLE") +} + +# Determine the quench status from the supply status bit +record(bi, "$(P)MAGNET:SUPPLY:STATUS:QUENCHED") { + field(DESC, "Quench status") + field(DTYP, "Soft Channel") + field(SCAN, "Passive") + field(INP, "$(P)GET:MAGNET:SUPPLY:STATUS.B8 CP MS") + field(ZNAM, "No") + field(ONAM, "Yes") + field(ZSV, "NO_ALARM") + field(OSV, "MAJOR") +} + +# The over temperature status should be an or'd output from the numerous temperature alarms +record(bi, "$(P)MAGNET:SUPPLY:STATUS:OVERTEMP") { + field(DESC, "Temperature status") + field(DTYP, "Soft Channel") + field(SCAN, "Passive") + field(INP, "$(P)GET:MAGNET:SUPPLY:STATUS.B4 CP MS") + field(ZNAM, "No") + field(ONAM, "Yes") + field(ZSV, "NO_ALARM") + field(OSV, "MAJOR") +} + +# -------------------------------------------------------------------------------------------------------------- + # # Run the Examine Status command, X. # The reply comes back and is split amongst other records. record(stringin, "$(P)GET:STATUS") { From 4ec5b4ab5679f56560426145b41bfd458de38642 Mon Sep 17 00:00:00 2001 From: Ian Gillingham Date: Thu, 27 Mar 2025 15:38:55 +0000 Subject: [PATCH 03/29] Initial updates to EPICS database for SCPI protocol migration --- IPS/IPS-IOC-01App/Db/ips.db | 245 +++++++++++++++++++++++++++++++++++- 1 file changed, 242 insertions(+), 3 deletions(-) diff --git a/IPS/IPS-IOC-01App/Db/ips.db b/IPS/IPS-IOC-01App/Db/ips.db index 609ab482c..876189a6f 100644 --- a/IPS/IPS-IOC-01App/Db/ips.db +++ b/IPS/IPS-IOC-01App/Db/ips.db @@ -24,7 +24,7 @@ record(bo, "$(P)DISABLE") # # Run the Version command, V. # # The string was too long to put model and version into same record. # # Scan this once, probably not needed again. -# The reply comes back and is split amongst other records. +# The reply comes back and is split amongst other records in the StreamDevice protocol file. record(stringin, "$(P)GET:VERSION") { field(DESC, "Examine status") field(DTYP, "stream") @@ -37,6 +37,7 @@ record(stringin, "$(P)GET:VERSION") { field(SDIS, "$(P)DISABLE") } +# Updated in GET:VERSION call to getVersion() record(stringin, "$(P)MODEL") { field(DESC, "Model") field(DTYP, "Soft Channel") @@ -44,12 +45,14 @@ record(stringin, "$(P)MODEL") { field(FLNK, "$(P)VERSION") } +# Updated in GET:VERSION call to getVersion() record(stringin, "$(P)VERSION") { field(DESC, "Firmware version.") field(DTYP, "Soft Channel") field(SCAN, "Passive") } +## !! Check this for SCPI - IJG 27/3/25 # # Readback from Cn part of Examine command return. record(mbbi, "$(P)CONTROL") { field(DESC, "Control status") @@ -92,6 +95,7 @@ record(mbbi, "$(P)CONTROL") { info(alarm, "IPS") } +## !! Modify for SCPI - IJG 27/3/25 # Grab remote vs local control record(mbbo, "$(P)CONTROL:SP") { field(DESC, "Set remote/local control") @@ -141,6 +145,7 @@ record(mbbi, "$(P)ACTIVITY") { info(archive, "VAL") } +## !! Modify for SCPI - IJG 27/3/25 # Hold means maintaining present current. # Clamped means you cannot adjust it - powers up in this # state. Only the set activity hold command can get out @@ -415,6 +420,7 @@ record(ai, "$(P)MAGNET:CURR:PERSISTENT") { info(archive, "VAL") } +## ==== CURR:TRIP needs to be derived somehow. It is not in the SCPI protocol. ==== # The current at which a trip last occurred. Am not sure if by trip, they mean # a quench or a problem with the level meter. Believe the unit will take the current # and field to zero if there is a trip, so this parameter preserves what was happening @@ -452,6 +458,7 @@ record(ai, "$(P)MAGNET:FIELD:PERSISTENT") { info(archive, "VAL") } +## ==== FIELD:TRIP needs to be derived somehow. It is not in the SCPI protocol. ==== # The field at which a trip last occurred. See current for explanation. record(ai, "$(P)FIELD:TRIP") { field(DESC, "Trip field readback") @@ -569,6 +576,102 @@ record(mbbiDirect, "$(P)GET:MAGNET:SUPPLY:STATUS") { field(SDIS, "$(P)DISABLE") } +# Determine the switch heater mismatch status from the supply status bit +record(bi, "$(P)MAGNET:SUPPLY:STATUS:SWHTRMISMATCH") { + field(DESC, "Switch heater mismatch status") + field(DTYP, "Soft Channel") + field(SCAN, "Passive") + field(INP, "$(P)GET:MAGNET:SUPPLY:STATUS.B0 CP MS") + field(ZNAM, "No") + field(ONAM, "Yes") + field(ZSV, "NO_ALARM") + field(OSV, "MAJOR") +} + +# Determine the Over Temperature (rundown resistors) status from the supply status bit +record(bi, "$(P)MAGNET:SUPPLY:STATUS:OTRUNDOWNRES") { + field(DESC, "Over temp rundown resistors status") + field(DTYP, "Soft Channel") + field(SCAN, "Passive") + field(INP, "$(P)GET:MAGNET:SUPPLY:STATUS.B1 CP MS") + field(ZNAM, "No") + field(ONAM, "Yes") + field(ZSV, "NO_ALARM") + field(OSV, "MAJOR") +} + +# Determine the Over Temperature (sense resistor) status from the supply status bit +record(bi, "$(P)MAGNET:SUPPLY:STATUS:OTSENSERES") { + field(DESC, "Over temp sense resistor status") + field(DTYP, "Soft Channel") + field(SCAN, "Passive") + field(INP, "$(P)GET:MAGNET:SUPPLY:STATUS.B2 CP MS") + field(ZNAM, "No") + field(ONAM, "Yes") + field(ZSV, "NO_ALARM") + field(OSV, "MAJOR") +} + +# Determine the Over Temperature (PCB) status from the supply status bit +record(bi, "$(P)MAGNET:SUPPLY:STATUS:OTPCB") { + field(DESC, "Over temp PCB status") + field(DTYP, "Soft Channel") + field(SCAN, "Passive") + field(INP, "$(P)GET:MAGNET:SUPPLY:STATUS.B3 CP MS") + field(ZNAM, "No") + field(ONAM, "Yes") + field(ZSV, "NO_ALARM") + field(OSV, "MAJOR") +} + +# Determine the calibration failure status from the supply status bit +record(bi, "$(P)MAGNET:SUPPLY:STATUS:CALIBFAIL") { + field(DESC, "Calibration failure status") + field(DTYP, "Soft Channel") + field(SCAN, "Passive") + field(INP, "$(P)GET:MAGNET:SUPPLY:STATUS.B4 CP MS") + field(ZNAM, "No") + field(ONAM, "Yes") + field(ZSV, "NO_ALARM") + field(OSV, "MAJOR") +} + +# Determine the MSP430 firmware error failure status from the supply status bit +record(bi, "$(P)MAGNET:SUPPLY:STATUS:FWFAIL") { + field(DESC, "Firmware failure status") + field(DTYP, "Soft Channel") + field(SCAN, "Passive") + field(INP, "$(P)GET:MAGNET:SUPPLY:STATUS.B5 CP MS") + field(ZNAM, "No") + field(ONAM, "Yes") + field(ZSV, "NO_ALARM") + field(OSV, "MAJOR") +} + +# Determine the rundown resistors failure status from the supply status bit +record(bi, "$(P)MAGNET:SUPPLY:STATUS:RRFAIL") { + field(DESC, "Rundown resistors failure status") + field(DTYP, "Soft Channel") + field(SCAN, "Passive") + field(INP, "$(P)GET:MAGNET:SUPPLY:STATUS.B6 CP MS") + field(ZNAM, "No") + field(ONAM, "Yes") + field(ZSV, "NO_ALARM") + field(OSV, "MAJOR") +} + +# Determine the MSP430 RS-485 failure status from the supply status bit +record(bi, "$(P)MAGNET:SUPPLY:STATUS:RS485FAIL") { + field(DESC, "MSP430 RS485 failure status") + field(DTYP, "Soft Channel") + field(SCAN, "Passive") + field(INP, "$(P)GET:MAGNET:SUPPLY:STATUS.B7 CP MS") + field(ZNAM, "No") + field(ONAM, "Yes") + field(ZSV, "NO_ALARM") + field(OSV, "MAJOR") +} + # Determine the quench status from the supply status bit record(bi, "$(P)MAGNET:SUPPLY:STATUS:QUENCHED") { field(DESC, "Quench status") @@ -581,12 +684,112 @@ record(bi, "$(P)MAGNET:SUPPLY:STATUS:QUENCHED") { field(OSV, "MAJOR") } +# Determine the catch detection status from the supply status bit +record(bi, "$(P)MAGNET:SUPPLY:STATUS:CATCH") { + field(DESC, "PSU Catch status") + field(DTYP, "Soft Channel") + field(SCAN, "Passive") + field(INP, "$(P)GET:MAGNET:SUPPLY:STATUS.B9 CP MS") + field(ZNAM, "No") + field(ONAM, "Yes") + field(ZSV, "NO_ALARM") + field(OSV, "MAJOR") +} + +# Determine the Sense amplifier over temperature status from the supply status bit +record(bi, "$(P)MAGNET:SUPPLY:STATUS:OTSENSEAMP") { + field(DESC, "Over temp sense amp") + field(DTYP, "Soft Channel") + field(SCAN, "Passive") + field(INP, "$(P)GET:MAGNET:SUPPLY:STATUS.BC CP MS") + field(ZNAM, "No") + field(ONAM, "Yes") + field(ZSV, "NO_ALARM") + field(OSV, "MAJOR") +} + +# Determine amplifier 1 over temperature status from the supply status bit +record(bi, "$(P)MAGNET:SUPPLY:STATUS:OTAMP1") { + field(DESC, "Over temp amp 1") + field(DTYP, "Soft Channel") + field(SCAN, "Passive") + field(INP, "$(P)GET:MAGNET:SUPPLY:STATUS.BD CP MS") + field(ZNAM, "No") + field(ONAM, "Yes") + field(ZSV, "NO_ALARM") + field(OSV, "MAJOR") +} + +# Determine amplifier 2 over temperature status from the supply status bit +record(bi, "$(P)MAGNET:SUPPLY:STATUS:OTAMP2") { + field(DESC, "Over temp amp 2") + field(DTYP, "Soft Channel") + field(SCAN, "Passive") + field(INP, "$(P)GET:MAGNET:SUPPLY:STATUS.BE CP MS") + field(ZNAM, "No") + field(ONAM, "Yes") + field(ZSV, "NO_ALARM") + field(OSV, "MAJOR") +} + +# Determine PWM Cutoff status from the supply status bit +record(bi, "$(P)MAGNET:SUPPLY:STATUS:PWMCUTOFF") { + field(DESC, "PWM Cutoff status") + field(DTYP, "Soft Channel") + field(SCAN, "Passive") + field(INP, "$(P)GET:MAGNET:SUPPLY:STATUS.BF CP MS") + field(ZNAM, "No") + field(ONAM, "Yes") + field(ZSV, "NO_ALARM") + field(OSV, "MAJOR") +} + +# Determine Voltage ADC error status from the supply status bit +record(bi, "$(P)MAGNET:SUPPLY:STATUS:VADCERROR") { + field(DESC, "Voltage ADC error status") + field(DTYP, "Soft Channel") + field(SCAN, "Passive") + field(INP, "$(P)GET:MAGNET:SUPPLY:STATUS.B10 CP MS") + field(ZNAM, "No") + field(ONAM, "Yes") + field(ZSV, "NO_ALARM") + field(OSV, "MAJOR") +} + +# Determine Current ADC error status from the supply status bit +record(bi, "$(P)MAGNET:SUPPLY:STATUS:IADCERROR") { + field(DESC, "Current ADC error status") + field(DTYP, "Soft Channel") + field(SCAN, "Passive") + field(INP, "$(P)GET:MAGNET:SUPPLY:STATUS.B11 CP MS") + field(ZNAM, "No") + field(ONAM, "Yes") + field(ZSV, "NO_ALARM") + field(OSV, "MAJOR") +} + # The over temperature status should be an or'd output from the numerous temperature alarms +record(calc, "$(P)MAGNET:SUPPLY:STATUS:OVERTEMP:CALC") { + field(DESC, "Temperature status calc (combined)") + field(DTYP, "Soft Channel") + field(SCAN, "Passive") + field(INPA, "$(P)GET:MAGNET:SUPPLY:OTRUNDOWNRES CP MS") + field(INPB, "$(P)GET:MAGNET:SUPPLY:OTSENSERES CP MS") + field(INPC, "$(P)GET:MAGNET:SUPPLY:OTPCB CP MS") + field(INPD, "$(P)GET:MAGNET:SUPPLY:OTSENSEAMP CP MS") + field(INPE, "$(P)GET:MAGNET:SUPPLY:OTAMP1 CP MS") + field(INPF, "$(P)GET:MAGNET:SUPPLY:OTAMP2 CP MS") + field(CALC, "A|B|C|D|E|F") + field(ZSV, "NO_ALARM") + field(OSV, "MAJOR") +} + +# Determine the Over Temperature status from the or'd calc record (OVERTEMP:CALC) record(bi, "$(P)MAGNET:SUPPLY:STATUS:OVERTEMP") { - field(DESC, "Temperature status") + field(DESC, "Temperature status (combined)") field(DTYP, "Soft Channel") field(SCAN, "Passive") - field(INP, "$(P)GET:MAGNET:SUPPLY:STATUS.B4 CP MS") + field(INP, "$(P)GET:MAGNET:SUPPLY:STATUS:OVERTEMP:CALC CP MS") field(ZNAM, "No") field(ONAM, "Yes") field(ZSV, "NO_ALARM") @@ -608,11 +811,47 @@ record(stringin, "$(P)GET:STATUS") { field(SDIS, "$(P)DISABLE") } +## Derive the SYSTEM:HWFAULT status from the status bits +## This collates the various possible hardware faults into a single record, +## which in the legacy protocol is a single value (Xm bit 4). +record(calc, "$(P)STS:SYSTEM:HWFAULT:CALC") { + field(DESC, "System hardware fault status calc") + field(DTYP, "Soft Channel") + field(SCAN, "Passive") + field(INPA, "$(P)MAGNET:SUPPLY:STATUS:SWHTRMISMATCH CP MS") + field(INPB, "$(P)MAGNET:SUPPLY:STATUS:CALIBFAIL CP MS") + field(INPC, "$(P)MAGNET:SUPPLY:STATUS:FWFAIL CP MS") + field(INPD, "$(P)MAGNET:SUPPLY:STATUS:RRFAIL CP MS") + field(INPE, "$(P)MAGNET:SUPPLY:STATUS:RS485FAIL CP MS") + field(INPF, "$(P)MAGNET:SUPPLY:STATUS:CATCH CP MS") + field(INPG, "$(P)MAGNET:SUPPLY:STATUS:PWMCUTOFF CP MS") + field(INPH, "$(P)MAGNET:SUPPLY:STATUS:VADCERROR CP MS") + field(INPI, "$(P)MAGNET:SUPPLY:STATUS:IADCERROR CP MS") + field(CALC, "(A>0||B>0||C>0||D>0||E>0||F>0||G>0||H>0||I>0) ? 1 : 0") + field(ZSV, "NO_ALARM") + field(OSV, "MAJOR") +} + +## Derive the SYSTEM:FAULT status from the status bits +## This collates the various possible faults into a single record, in alignment with the legacy protocol. +record(calc, "$(P)STS:SYSTEM:FAULT:CALC") { + field(DESC, "System fault status calc") + field(DTYP, "Soft Channel") + field(SCAN, "Passive") + field(INPA, "$(P)MAGNET:SUPPLY:STATUS:QUENCHED CP MS") + field(INPB, "$(P)MAGNET:SUPPLY:STATUS:OVERTEMP CP MS") + field(INPC, "$(P)MAGNET:SUPPLY:STATUS:HWFAULT:CALC CP MS") + field(CALC, "(A>0) ? 1 : (B>0) ? 2 : (C>0) ? 8 : 0") + field(ZSV, "NO_ALARM") + field(OSV, "MAJOR") +} + # # Readback from m of Xmn part of Examine command return. record(mbbi, "$(P)STS:SYSTEM:FAULT") { field(DESC, "System fault status") field(DTYP, "Soft Channel") field(SCAN, "Passive") + field(INP, "$(P)STS:SYSTEM:FAULT:CALC CP MS") field(ZRST, "Normal") field(ZRVL, "0") field(ZRSV, "NO_ALARM") From c10d6d3a69baf9843b952a003f9917bdc1d6614f Mon Sep 17 00:00:00 2001 From: Lowri Jenkins Date: Fri, 14 Feb 2025 09:53:28 +0000 Subject: [PATCH 04/29] initial state machine commit --- DDSSTRES/iocBoot/iocDDSSTRES-IOC-01/st-common.cmd | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/DDSSTRES/iocBoot/iocDDSSTRES-IOC-01/st-common.cmd b/DDSSTRES/iocBoot/iocDDSSTRES-IOC-01/st-common.cmd index 3fc8c686f..801a2449b 100644 --- a/DDSSTRES/iocBoot/iocDDSSTRES-IOC-01/st-common.cmd +++ b/DDSSTRES/iocBoot/iocDDSSTRES-IOC-01/st-common.cmd @@ -37,8 +37,11 @@ dbLoadRecords("$(DDSSTRES)/db/tensile_stress_rig_internal.db","PVPREFIX=$(MYPVPR cd "${TOP}/iocBoot/${IOC}" iocInit + ## Start any sequence programs -#seq sncxxx,"user=wtn43451" +seq start_or_load, "P=$(MYPVPREFIX)$(IOCNAME)" ##ISIS## Stuff that needs to be done after iocInit is called e.g. sequence programs < $(IOCSTARTUP)/postiocinit.cmd + + From da2a28393ca9b381a64af02a64897974036feca3 Mon Sep 17 00:00:00 2001 From: Ian Gillingham Date: Tue, 11 Mar 2025 12:58:24 +0000 Subject: [PATCH 05/29] Range change time delay --- G3HALLPR/iocBoot/iocG3HALLPR-IOC-01/st-common.cmd | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/G3HALLPR/iocBoot/iocG3HALLPR-IOC-01/st-common.cmd b/G3HALLPR/iocBoot/iocG3HALLPR-IOC-01/st-common.cmd index ef31c2774..5e9721db8 100644 --- a/G3HALLPR/iocBoot/iocG3HALLPR-IOC-01/st-common.cmd +++ b/G3HALLPR/iocBoot/iocG3HALLPR-IOC-01/st-common.cmd @@ -33,9 +33,9 @@ epicsEnvSet("P", "$(MYPVPREFIX)$(IOCNAME):") ## Load our record instances dbLoadRecords("$(G3HALLPR)/db/group3hallprobe.db","PVPREFIX=$(MYPVPREFIX),P=$(P),RECSIM=$(RECSIM=0),DISABLE=$(DISABLE=0),PORT=$(DEVICE)") -dbLoadRecords("$(G3HALLPR)/db/group3hallprobe_probe.db","P=$(P),SENSORID=0,ADDR=$(ADDR0=0),PORT=$(DEVICE),NAME=$(NAME0=probe0),SCALE=$(SCALE0=1),FIELD_SCAN_RATE=$(FIELD_SCAN_RATE=1 second),TEMP_SCAN_RATE=$(TEMP_SCAN_RATE=5 second),FLNK=$(FLNK0=)") -dbLoadRecords("$(G3HALLPR)/db/group3hallprobe_probe.db","P=$(P),SENSORID=1,ADDR=$(ADDR1=1),PORT=$(DEVICE),NAME=$(NAME1=probe1),SCALE=$(SCALE1=1),FIELD_SCAN_RATE=$(FIELD_SCAN_RATE=1 second),TEMP_SCAN_RATE=$(TEMP_SCAN_RATE=5 second),FLNK=$(FLNK1=)") -dbLoadRecords("$(G3HALLPR)/db/group3hallprobe_probe.db","P=$(P),SENSORID=2,ADDR=$(ADDR2=2),PORT=$(DEVICE),NAME=$(NAME2=probe2),SCALE=$(SCALE2=1),FIELD_SCAN_RATE=$(FIELD_SCAN_RATE=1 second),TEMP_SCAN_RATE=$(TEMP_SCAN_RATE=5 second),FLNK=$(FLNK2=)") +dbLoadRecords("$(G3HALLPR)/db/group3hallprobe_probe.db","PVPREFIX=$(MYPVPREFIX),IOCNAME=$(IOCNAME),P=$(P),SENSORID=0,ADDR=$(ADDR0=0),PORT=$(DEVICE),NAME=$(NAME0=probe0),SCALE=$(SCALE0=1),FIELD_SCAN_RATE=$(FIELD_SCAN_RATE=1 second),TEMP_SCAN_RATE=$(TEMP_SCAN_RATE=5 second),FLNK=$(FLNK0=)") +dbLoadRecords("$(G3HALLPR)/db/group3hallprobe_probe.db","PVPREFIX=$(MYPVPREFIX),IOCNAME=$(IOCNAME),P=$(P),SENSORID=1,ADDR=$(ADDR1=1),PORT=$(DEVICE),NAME=$(NAME1=probe1),SCALE=$(SCALE1=1),FIELD_SCAN_RATE=$(FIELD_SCAN_RATE=1 second),TEMP_SCAN_RATE=$(TEMP_SCAN_RATE=5 second),FLNK=$(FLNK1=)") +dbLoadRecords("$(G3HALLPR)/db/group3hallprobe_probe.db","PVPREFIX=$(MYPVPREFIX),IOCNAME=$(IOCNAME),P=$(P),SENSORID=2,ADDR=$(ADDR2=2),PORT=$(DEVICE),NAME=$(NAME2=probe2),SCALE=$(SCALE2=1),FIELD_SCAN_RATE=$(FIELD_SCAN_RATE=1 second),TEMP_SCAN_RATE=$(TEMP_SCAN_RATE=5 second),FLNK=$(FLNK2=)") ##ISIS## Stuff that needs to be done after all records are loaded but before iocInit is called < $(IOCSTARTUP)/preiocinit.cmd From cb65419d99c5ad63945106de38fdddb6fc2f47d7 Mon Sep 17 00:00:00 2001 From: Ian Gillingham Date: Tue, 25 Mar 2025 10:55:03 +0000 Subject: [PATCH 06/29] IPS: work around limitation of getting legacy status from SCPI protocol --- IPS/IPS-IOC-01App/Db/ips.db | 41 +++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/IPS/IPS-IOC-01App/Db/ips.db b/IPS/IPS-IOC-01App/Db/ips.db index a820c7c22..609ab482c 100644 --- a/IPS/IPS-IOC-01App/Db/ips.db +++ b/IPS/IPS-IOC-01App/Db/ips.db @@ -554,6 +554,47 @@ record(ai, "$(P)MAGNET:INDUCTANCE") { info(archive, "VAL") } +# --------------- The following work around limitation of getting legacy status from SCPI protocol ------------- + +# Get the status DWORD from each group UID +record(mbbiDirect, "$(P)GET:MAGNET:SUPPLY:STATUS") { + field(DESC, "Examine status") + field(DTYP, "stream") + field(INP, "@OxInstIPS.protocol getMagnetSupplyStatus($(P)) $(PORT)") + field(NOBT, "32") + field(SCAN, "1 second") + + field(SIML, "$(P)SIM") + field(SIOL, "$(P)SIM:DONOTHING") + field(SDIS, "$(P)DISABLE") +} + +# Determine the quench status from the supply status bit +record(bi, "$(P)MAGNET:SUPPLY:STATUS:QUENCHED") { + field(DESC, "Quench status") + field(DTYP, "Soft Channel") + field(SCAN, "Passive") + field(INP, "$(P)GET:MAGNET:SUPPLY:STATUS.B8 CP MS") + field(ZNAM, "No") + field(ONAM, "Yes") + field(ZSV, "NO_ALARM") + field(OSV, "MAJOR") +} + +# The over temperature status should be an or'd output from the numerous temperature alarms +record(bi, "$(P)MAGNET:SUPPLY:STATUS:OVERTEMP") { + field(DESC, "Temperature status") + field(DTYP, "Soft Channel") + field(SCAN, "Passive") + field(INP, "$(P)GET:MAGNET:SUPPLY:STATUS.B4 CP MS") + field(ZNAM, "No") + field(ONAM, "Yes") + field(ZSV, "NO_ALARM") + field(OSV, "MAJOR") +} + +# -------------------------------------------------------------------------------------------------------------- + # # Run the Examine Status command, X. # The reply comes back and is split amongst other records. record(stringin, "$(P)GET:STATUS") { From c6f4d56cf6641b16ccf224e9d50ba08a5e7229f2 Mon Sep 17 00:00:00 2001 From: Ian Gillingham Date: Thu, 27 Mar 2025 15:38:55 +0000 Subject: [PATCH 07/29] Initial updates to EPICS database for SCPI protocol migration --- IPS/IPS-IOC-01App/Db/ips.db | 245 +++++++++++++++++++++++++++++++++++- 1 file changed, 242 insertions(+), 3 deletions(-) diff --git a/IPS/IPS-IOC-01App/Db/ips.db b/IPS/IPS-IOC-01App/Db/ips.db index 609ab482c..876189a6f 100644 --- a/IPS/IPS-IOC-01App/Db/ips.db +++ b/IPS/IPS-IOC-01App/Db/ips.db @@ -24,7 +24,7 @@ record(bo, "$(P)DISABLE") # # Run the Version command, V. # # The string was too long to put model and version into same record. # # Scan this once, probably not needed again. -# The reply comes back and is split amongst other records. +# The reply comes back and is split amongst other records in the StreamDevice protocol file. record(stringin, "$(P)GET:VERSION") { field(DESC, "Examine status") field(DTYP, "stream") @@ -37,6 +37,7 @@ record(stringin, "$(P)GET:VERSION") { field(SDIS, "$(P)DISABLE") } +# Updated in GET:VERSION call to getVersion() record(stringin, "$(P)MODEL") { field(DESC, "Model") field(DTYP, "Soft Channel") @@ -44,12 +45,14 @@ record(stringin, "$(P)MODEL") { field(FLNK, "$(P)VERSION") } +# Updated in GET:VERSION call to getVersion() record(stringin, "$(P)VERSION") { field(DESC, "Firmware version.") field(DTYP, "Soft Channel") field(SCAN, "Passive") } +## !! Check this for SCPI - IJG 27/3/25 # # Readback from Cn part of Examine command return. record(mbbi, "$(P)CONTROL") { field(DESC, "Control status") @@ -92,6 +95,7 @@ record(mbbi, "$(P)CONTROL") { info(alarm, "IPS") } +## !! Modify for SCPI - IJG 27/3/25 # Grab remote vs local control record(mbbo, "$(P)CONTROL:SP") { field(DESC, "Set remote/local control") @@ -141,6 +145,7 @@ record(mbbi, "$(P)ACTIVITY") { info(archive, "VAL") } +## !! Modify for SCPI - IJG 27/3/25 # Hold means maintaining present current. # Clamped means you cannot adjust it - powers up in this # state. Only the set activity hold command can get out @@ -415,6 +420,7 @@ record(ai, "$(P)MAGNET:CURR:PERSISTENT") { info(archive, "VAL") } +## ==== CURR:TRIP needs to be derived somehow. It is not in the SCPI protocol. ==== # The current at which a trip last occurred. Am not sure if by trip, they mean # a quench or a problem with the level meter. Believe the unit will take the current # and field to zero if there is a trip, so this parameter preserves what was happening @@ -452,6 +458,7 @@ record(ai, "$(P)MAGNET:FIELD:PERSISTENT") { info(archive, "VAL") } +## ==== FIELD:TRIP needs to be derived somehow. It is not in the SCPI protocol. ==== # The field at which a trip last occurred. See current for explanation. record(ai, "$(P)FIELD:TRIP") { field(DESC, "Trip field readback") @@ -569,6 +576,102 @@ record(mbbiDirect, "$(P)GET:MAGNET:SUPPLY:STATUS") { field(SDIS, "$(P)DISABLE") } +# Determine the switch heater mismatch status from the supply status bit +record(bi, "$(P)MAGNET:SUPPLY:STATUS:SWHTRMISMATCH") { + field(DESC, "Switch heater mismatch status") + field(DTYP, "Soft Channel") + field(SCAN, "Passive") + field(INP, "$(P)GET:MAGNET:SUPPLY:STATUS.B0 CP MS") + field(ZNAM, "No") + field(ONAM, "Yes") + field(ZSV, "NO_ALARM") + field(OSV, "MAJOR") +} + +# Determine the Over Temperature (rundown resistors) status from the supply status bit +record(bi, "$(P)MAGNET:SUPPLY:STATUS:OTRUNDOWNRES") { + field(DESC, "Over temp rundown resistors status") + field(DTYP, "Soft Channel") + field(SCAN, "Passive") + field(INP, "$(P)GET:MAGNET:SUPPLY:STATUS.B1 CP MS") + field(ZNAM, "No") + field(ONAM, "Yes") + field(ZSV, "NO_ALARM") + field(OSV, "MAJOR") +} + +# Determine the Over Temperature (sense resistor) status from the supply status bit +record(bi, "$(P)MAGNET:SUPPLY:STATUS:OTSENSERES") { + field(DESC, "Over temp sense resistor status") + field(DTYP, "Soft Channel") + field(SCAN, "Passive") + field(INP, "$(P)GET:MAGNET:SUPPLY:STATUS.B2 CP MS") + field(ZNAM, "No") + field(ONAM, "Yes") + field(ZSV, "NO_ALARM") + field(OSV, "MAJOR") +} + +# Determine the Over Temperature (PCB) status from the supply status bit +record(bi, "$(P)MAGNET:SUPPLY:STATUS:OTPCB") { + field(DESC, "Over temp PCB status") + field(DTYP, "Soft Channel") + field(SCAN, "Passive") + field(INP, "$(P)GET:MAGNET:SUPPLY:STATUS.B3 CP MS") + field(ZNAM, "No") + field(ONAM, "Yes") + field(ZSV, "NO_ALARM") + field(OSV, "MAJOR") +} + +# Determine the calibration failure status from the supply status bit +record(bi, "$(P)MAGNET:SUPPLY:STATUS:CALIBFAIL") { + field(DESC, "Calibration failure status") + field(DTYP, "Soft Channel") + field(SCAN, "Passive") + field(INP, "$(P)GET:MAGNET:SUPPLY:STATUS.B4 CP MS") + field(ZNAM, "No") + field(ONAM, "Yes") + field(ZSV, "NO_ALARM") + field(OSV, "MAJOR") +} + +# Determine the MSP430 firmware error failure status from the supply status bit +record(bi, "$(P)MAGNET:SUPPLY:STATUS:FWFAIL") { + field(DESC, "Firmware failure status") + field(DTYP, "Soft Channel") + field(SCAN, "Passive") + field(INP, "$(P)GET:MAGNET:SUPPLY:STATUS.B5 CP MS") + field(ZNAM, "No") + field(ONAM, "Yes") + field(ZSV, "NO_ALARM") + field(OSV, "MAJOR") +} + +# Determine the rundown resistors failure status from the supply status bit +record(bi, "$(P)MAGNET:SUPPLY:STATUS:RRFAIL") { + field(DESC, "Rundown resistors failure status") + field(DTYP, "Soft Channel") + field(SCAN, "Passive") + field(INP, "$(P)GET:MAGNET:SUPPLY:STATUS.B6 CP MS") + field(ZNAM, "No") + field(ONAM, "Yes") + field(ZSV, "NO_ALARM") + field(OSV, "MAJOR") +} + +# Determine the MSP430 RS-485 failure status from the supply status bit +record(bi, "$(P)MAGNET:SUPPLY:STATUS:RS485FAIL") { + field(DESC, "MSP430 RS485 failure status") + field(DTYP, "Soft Channel") + field(SCAN, "Passive") + field(INP, "$(P)GET:MAGNET:SUPPLY:STATUS.B7 CP MS") + field(ZNAM, "No") + field(ONAM, "Yes") + field(ZSV, "NO_ALARM") + field(OSV, "MAJOR") +} + # Determine the quench status from the supply status bit record(bi, "$(P)MAGNET:SUPPLY:STATUS:QUENCHED") { field(DESC, "Quench status") @@ -581,12 +684,112 @@ record(bi, "$(P)MAGNET:SUPPLY:STATUS:QUENCHED") { field(OSV, "MAJOR") } +# Determine the catch detection status from the supply status bit +record(bi, "$(P)MAGNET:SUPPLY:STATUS:CATCH") { + field(DESC, "PSU Catch status") + field(DTYP, "Soft Channel") + field(SCAN, "Passive") + field(INP, "$(P)GET:MAGNET:SUPPLY:STATUS.B9 CP MS") + field(ZNAM, "No") + field(ONAM, "Yes") + field(ZSV, "NO_ALARM") + field(OSV, "MAJOR") +} + +# Determine the Sense amplifier over temperature status from the supply status bit +record(bi, "$(P)MAGNET:SUPPLY:STATUS:OTSENSEAMP") { + field(DESC, "Over temp sense amp") + field(DTYP, "Soft Channel") + field(SCAN, "Passive") + field(INP, "$(P)GET:MAGNET:SUPPLY:STATUS.BC CP MS") + field(ZNAM, "No") + field(ONAM, "Yes") + field(ZSV, "NO_ALARM") + field(OSV, "MAJOR") +} + +# Determine amplifier 1 over temperature status from the supply status bit +record(bi, "$(P)MAGNET:SUPPLY:STATUS:OTAMP1") { + field(DESC, "Over temp amp 1") + field(DTYP, "Soft Channel") + field(SCAN, "Passive") + field(INP, "$(P)GET:MAGNET:SUPPLY:STATUS.BD CP MS") + field(ZNAM, "No") + field(ONAM, "Yes") + field(ZSV, "NO_ALARM") + field(OSV, "MAJOR") +} + +# Determine amplifier 2 over temperature status from the supply status bit +record(bi, "$(P)MAGNET:SUPPLY:STATUS:OTAMP2") { + field(DESC, "Over temp amp 2") + field(DTYP, "Soft Channel") + field(SCAN, "Passive") + field(INP, "$(P)GET:MAGNET:SUPPLY:STATUS.BE CP MS") + field(ZNAM, "No") + field(ONAM, "Yes") + field(ZSV, "NO_ALARM") + field(OSV, "MAJOR") +} + +# Determine PWM Cutoff status from the supply status bit +record(bi, "$(P)MAGNET:SUPPLY:STATUS:PWMCUTOFF") { + field(DESC, "PWM Cutoff status") + field(DTYP, "Soft Channel") + field(SCAN, "Passive") + field(INP, "$(P)GET:MAGNET:SUPPLY:STATUS.BF CP MS") + field(ZNAM, "No") + field(ONAM, "Yes") + field(ZSV, "NO_ALARM") + field(OSV, "MAJOR") +} + +# Determine Voltage ADC error status from the supply status bit +record(bi, "$(P)MAGNET:SUPPLY:STATUS:VADCERROR") { + field(DESC, "Voltage ADC error status") + field(DTYP, "Soft Channel") + field(SCAN, "Passive") + field(INP, "$(P)GET:MAGNET:SUPPLY:STATUS.B10 CP MS") + field(ZNAM, "No") + field(ONAM, "Yes") + field(ZSV, "NO_ALARM") + field(OSV, "MAJOR") +} + +# Determine Current ADC error status from the supply status bit +record(bi, "$(P)MAGNET:SUPPLY:STATUS:IADCERROR") { + field(DESC, "Current ADC error status") + field(DTYP, "Soft Channel") + field(SCAN, "Passive") + field(INP, "$(P)GET:MAGNET:SUPPLY:STATUS.B11 CP MS") + field(ZNAM, "No") + field(ONAM, "Yes") + field(ZSV, "NO_ALARM") + field(OSV, "MAJOR") +} + # The over temperature status should be an or'd output from the numerous temperature alarms +record(calc, "$(P)MAGNET:SUPPLY:STATUS:OVERTEMP:CALC") { + field(DESC, "Temperature status calc (combined)") + field(DTYP, "Soft Channel") + field(SCAN, "Passive") + field(INPA, "$(P)GET:MAGNET:SUPPLY:OTRUNDOWNRES CP MS") + field(INPB, "$(P)GET:MAGNET:SUPPLY:OTSENSERES CP MS") + field(INPC, "$(P)GET:MAGNET:SUPPLY:OTPCB CP MS") + field(INPD, "$(P)GET:MAGNET:SUPPLY:OTSENSEAMP CP MS") + field(INPE, "$(P)GET:MAGNET:SUPPLY:OTAMP1 CP MS") + field(INPF, "$(P)GET:MAGNET:SUPPLY:OTAMP2 CP MS") + field(CALC, "A|B|C|D|E|F") + field(ZSV, "NO_ALARM") + field(OSV, "MAJOR") +} + +# Determine the Over Temperature status from the or'd calc record (OVERTEMP:CALC) record(bi, "$(P)MAGNET:SUPPLY:STATUS:OVERTEMP") { - field(DESC, "Temperature status") + field(DESC, "Temperature status (combined)") field(DTYP, "Soft Channel") field(SCAN, "Passive") - field(INP, "$(P)GET:MAGNET:SUPPLY:STATUS.B4 CP MS") + field(INP, "$(P)GET:MAGNET:SUPPLY:STATUS:OVERTEMP:CALC CP MS") field(ZNAM, "No") field(ONAM, "Yes") field(ZSV, "NO_ALARM") @@ -608,11 +811,47 @@ record(stringin, "$(P)GET:STATUS") { field(SDIS, "$(P)DISABLE") } +## Derive the SYSTEM:HWFAULT status from the status bits +## This collates the various possible hardware faults into a single record, +## which in the legacy protocol is a single value (Xm bit 4). +record(calc, "$(P)STS:SYSTEM:HWFAULT:CALC") { + field(DESC, "System hardware fault status calc") + field(DTYP, "Soft Channel") + field(SCAN, "Passive") + field(INPA, "$(P)MAGNET:SUPPLY:STATUS:SWHTRMISMATCH CP MS") + field(INPB, "$(P)MAGNET:SUPPLY:STATUS:CALIBFAIL CP MS") + field(INPC, "$(P)MAGNET:SUPPLY:STATUS:FWFAIL CP MS") + field(INPD, "$(P)MAGNET:SUPPLY:STATUS:RRFAIL CP MS") + field(INPE, "$(P)MAGNET:SUPPLY:STATUS:RS485FAIL CP MS") + field(INPF, "$(P)MAGNET:SUPPLY:STATUS:CATCH CP MS") + field(INPG, "$(P)MAGNET:SUPPLY:STATUS:PWMCUTOFF CP MS") + field(INPH, "$(P)MAGNET:SUPPLY:STATUS:VADCERROR CP MS") + field(INPI, "$(P)MAGNET:SUPPLY:STATUS:IADCERROR CP MS") + field(CALC, "(A>0||B>0||C>0||D>0||E>0||F>0||G>0||H>0||I>0) ? 1 : 0") + field(ZSV, "NO_ALARM") + field(OSV, "MAJOR") +} + +## Derive the SYSTEM:FAULT status from the status bits +## This collates the various possible faults into a single record, in alignment with the legacy protocol. +record(calc, "$(P)STS:SYSTEM:FAULT:CALC") { + field(DESC, "System fault status calc") + field(DTYP, "Soft Channel") + field(SCAN, "Passive") + field(INPA, "$(P)MAGNET:SUPPLY:STATUS:QUENCHED CP MS") + field(INPB, "$(P)MAGNET:SUPPLY:STATUS:OVERTEMP CP MS") + field(INPC, "$(P)MAGNET:SUPPLY:STATUS:HWFAULT:CALC CP MS") + field(CALC, "(A>0) ? 1 : (B>0) ? 2 : (C>0) ? 8 : 0") + field(ZSV, "NO_ALARM") + field(OSV, "MAJOR") +} + # # Readback from m of Xmn part of Examine command return. record(mbbi, "$(P)STS:SYSTEM:FAULT") { field(DESC, "System fault status") field(DTYP, "Soft Channel") field(SCAN, "Passive") + field(INP, "$(P)STS:SYSTEM:FAULT:CALC CP MS") field(ZRST, "Normal") field(ZRVL, "0") field(ZRSV, "NO_ALARM") From 3c282a825cbd3d354b8f4cb5c2505629dd4af822 Mon Sep 17 00:00:00 2001 From: Ian Gillingham Date: Tue, 1 Apr 2025 14:11:16 +0100 Subject: [PATCH 08/29] Added new db file for SCPI instead of legacy protocol. --- IPS/IPS-IOC-01App/Db/ips_scpi.db | 1262 ++++++++++++++++++++++++++++++ 1 file changed, 1262 insertions(+) create mode 100644 IPS/IPS-IOC-01App/Db/ips_scpi.db diff --git a/IPS/IPS-IOC-01App/Db/ips_scpi.db b/IPS/IPS-IOC-01App/Db/ips_scpi.db new file mode 100644 index 000000000..011bf92cb --- /dev/null +++ b/IPS/IPS-IOC-01App/Db/ips_scpi.db @@ -0,0 +1,1262 @@ +record(bo, "$(P)SIM") +{ + field(SCAN, "Passive") + field(DTYP, "Soft Channel") + field(ZNAM, "NO") + field(ONAM, "YES") + field(VAL, "$(RECSIM=0)") + field(PINI, "YES") +} + +record(bo, "$(P)DISABLE") +{ + field(DESC, "Disable comms") + field(PINI, "YES") + field(VAL, "$(DISABLE=0)") + field(OMSL, "supervisory") + field(ZNAM, "COMMS ENABLED") + field(ONAM, "COMMS DISABLED") +} + +######################################################### +# START OF RECORDS FOR READBACK FROM VERSION COMMAND. +# # Readback of the instrument model and version info. +# # Run the Version command, V. +# # The string was too long to put model and version into same record. +# # Scan this once, probably not needed again. +# The reply comes back and is split amongst other records in the StreamDevice protocol file. +record(stringin, "$(P)GET:VERSION") { + field(DESC, "Examine status") + field(DTYP, "stream") + field(INP, "@OxInstIPS.protocol getVersion($(P)) $(PORT)") + field(PINI, "YES") + field(FLNK, "$(P)MODEL") + field(SCAN, "Passive") + field(SIML, "$(P)SIM") + field(SIOL, "$(P)SIM:DONOTHING") + field(SDIS, "$(P)DISABLE") +} + +# Updated in GET:VERSION call to getVersion() +record(stringin, "$(P)MODEL") { + field(DESC, "Model") + field(DTYP, "Soft Channel") + field(SCAN, "Passive") + field(FLNK, "$(P)VERSION") +} + +# Updated in GET:VERSION call to getVersion() +record(stringin, "$(P)VERSION") { + field(DESC, "Firmware version.") + field(DTYP, "Soft Channel") + field(SCAN, "Passive") +} + +## !! Check this for SCPI - IJG 27/3/25 +# # Readback from Cn part of Examine command return. +record(mbbi, "$(P)CONTROL") { + field(DESC, "Control status") + field(DTYP, "Soft Channel") + field(SCAN, "1 second") + field(ZRST, "Local & Locked") + field(ZRVL, "0") + field(ZRSV, "NO_ALARM") + field(ONST, "Remote & Locked") + field(ONVL, "1") + field(ONSV, "NO_ALARM") + field(TWST, "Local & Unlocked") + field(TWVL, "2") + field(TWSV, "NO_ALARM") + field(THST, "Remote & Unlocked") + field(THVL, "3") + field(THSV, "NO_ALARM") + + # Modes 4-7 come back from device. Manual does not make it clear what the + # differences are. Keeping them as separate items in case they are useful + # for diagnostics later on. + field(FRST, "Auto-Run-Down") + field(FRVL, "4") + field(FRSV, "MAJOR") + field(FVST, "Auto-Run-Down") + field(FVVL, "5") + field(FVSV, "MAJOR") + field(SXST, "Auto-Run-Down") + field(SXVL, "6") + field(SXSV, "MAJOR") + field(SVST, "Auto-Run-Down") + field(SVVL, "7") + field(SVSV, "MAJOR") + + field(SIML, "$(P)SIM") + field(SIOL, "$(P)SIM:CONTROL") + field(SDIS, "$(P)DISABLE") + + info(archive, "VAL") + info(alarm, "IPS") +} + +## !! Modify for SCPI - IJG 27/3/25 +# Grab remote vs local control +record(mbbo, "$(P)CONTROL:SP") { + field(DESC, "Set remote/local control") + field(DTYP, "stream") + field(SCAN, "Passive") + field(OUT, "@OxInstIPS.protocol setControl $(PORT)") + field(ZRST, "Local & Locked") + field(ZRVL, "0") + field(ONST, "Remote & Locked") + field(ONVL, "1") + field(TWST, "Local & Unlocked") + field(TWVL, "2") + field(THST, "Remote & Unlocked") + field(THVL, "3") + + field(SIML, "$(P)SIM") + field(SIOL, "$(P)SIM:CONTROL:SP") + field(SDIS, "$(P)DISABLE") +} + +# Readback from An part of Examine command return. +# Hold means maintaining present current. +# Clamped means you cannot adjust it - powers up in this +# state. Only the set activity hold command can get out +# of the clamped state. Hold will interrupt a sweep. +record(mbbi, "$(P)ACTIVITY") { + field(DESC, "Activity status") + field(DTYP, "Soft Channel") + field(SCAN, "1 second") + field(ZRST, "Hold") + field(ZRVL, "0") + field(ZRSV, "NO_ALARM") + field(ONST, "To Setpoint") + field(ONVL, "1") + field(ONSV, "NO_ALARM") + field(TWST, "To Zero") + field(TWVL, "2") + field(TWSV, "NO_ALARM") + field(FRST, "Clamped") + field(FRVL, "4") + field(FRSV, "MAJOR") + + field(SIML, "$(P)SIM") + field(SIOL, "$(P)SIM:ACTIVITY") + field(SDIS, "$(P)DISABLE") + + info(archive, "VAL") +} + +## !! Modify for SCPI - IJG 27/3/25 +# Hold means maintaining present current. +# Clamped means you cannot adjust it - powers up in this +# state. Only the set activity hold command can get out +# of the clamped state. Hold will interrupt a sweep. +record(mbbo, "$(P)ACTIVITY:SP") { + field(DESC, "Activity control") + field(DTYP, "stream") + field(SCAN, "Passive") + field(OUT, "@OxInstIPS.protocol setActivity $(PORT)") + field(ZRST, "Hold") + field(ZRVL, "0") + field(ONST, "To Setpoint") + field(ONVL, "1") + field(TWST, "To Zero") + field(TWVL, "2") + field(FRST, "Clamp") + field(FRVL, "4") + + field(SIML, "$(P)SIM") + field(SIOL, "$(P)SIM:ACTIVITY:SP") + field(SDIS, "$(P)DISABLE") +} + +# Think this is the present current the unit is trying to supply. +record(ai, "$(P)CURR") { + field(DESC, "Demand current readback") + field(DTYP, "stream") + field(SCAN, "1 second") + field(INP, "@OxInstIPS.protocol getDemandCurrent $(PORT)") + field(EGU, "A") + field(PREC, "4") + + field(SIML, "$(P)SIM") + field(SIOL, "$(P)SIM:CURRENT") + field(SDIS, "$(P)DISABLE") + + info(archive, "VAL") +} + +# The present current setpoint. +record(ai, "$(P)CURR:SP:RBV") { + field(DESC, "Setpoint current readback") + field(DTYP, "stream") + field(SCAN, "1 second") + field(INP, "@OxInstIPS.protocol getSetpointCurrent $(PORT)") + field(EGU, "A") + field(PREC, "4") + + field(SIML, "$(P)SIM") + field(SIOL, "$(P)SIM:CURRENT") + field(SDIS, "$(P)DISABLE") + + info(archive, "VAL") +} + +# The present voltage. +record(ai, "$(P)SUPPLY:VOLT") { + field(DESC, "Supply voltage readback") + field(DTYP, "stream") + field(SCAN, "1 second") + field(INP, "@OxInstIPS.protocol getSupplyVoltage $(PORT)") + field(EGU, "V") + field(PREC, "8") + + field(SIML, "$(P)SIM") + field(SIOL, "$(P)SIM:SUPPLY:VOLT") + field(SDIS, "$(P)DISABLE") + + field(FLNK, "$(P)SUPPLY:VOLT:_STABILITY:BUF") + + info(archive, "VAL") +} + +record(compress, "$(P)SUPPLY:VOLT:_STABILITY:BUF") { + field(INP, "$(P)SUPPLY:VOLT") + field(ALG, "Circular Buffer") + field(NSAM, "5") + field(FLNK, "$(P)SUPPLY:VOLT:_STABILITY:LOW") +} + +record(compress, "$(P)SUPPLY:VOLT:_STABILITY:LOW") { + field(INP, "$(P)SUPPLY:VOLT:_STABILITY:BUF") + field(ALG, "N to 1 Low Value") + field(NSAM, "1") + field(N, "5") + field(FLNK, "$(P)SUPPLY:VOLT:_STABILITY:HIGH") +} + +record(compress, "$(P)SUPPLY:VOLT:_STABILITY:HIGH") { + field(INP, "$(P)SUPPLY:VOLT:_STABILITY:BUF") + field(ALG, "N to 1 High Value") + field(NSAM, "1") + field(N, "5") + field(FLNK, "$(P)SUPPLY:VOLT:_STABILITY:CALC") +} + +record(calcout, "$(P)SUPPLY:VOLT:_STABILITY:CALC") { + field(INPA, "$(P)SUPPLY:VOLT:_STABILITY:HIGH") + field(INPB, "$(P)SUPPLY:VOLT:_STABILITY:LOW") + field(CALC, "ABS(A-B)<$(STABILITY_VOLTAGE)") + field(OUT, "$(P)SUPPLY:VOLT:STABLE PP") + field(OOPT, "Every Time") +} + +record(bo, "$(P)SUPPLY:VOLT:STABLE") { + field(ZNAM, "NO") + field(ONAM, "YES") + info(archive, "VAL") +} + +# The present current measured. +record(ai, "$(P)MAGNET:CURR:MEAS") { + field(DESC, "Measured magnet current readback") + field(DTYP, "stream") + field(SCAN, "1 second") + field(INP, "@OxInstIPS.protocol getMeasuredMagnetCurrent $(PORT)") + field(EGU, "A") + field(PREC, "4") + + field(SIML, "$(P)SIM") + field(SIOL, "$(P)SIM:MAGNET:CURR:MEAS") + field(SDIS, "$(P)DISABLE") + + info(archive, "VAL") +} + +# The present sweeprate for current. +record(ai, "$(P)CURR:RATE") { + field(DESC, "Current sweep rate readback") + field(DTYP, "stream") + field(SCAN, "1 second") + field(INP, "@OxInstIPS.protocol getCurrentSweepRate $(PORT)") + field(EGU, "A/min") + field(PREC, "3") + + field(SIML, "$(P)SIM") + field(SIOL, "$(P)SIM:CURR:RATE") + field(SDIS, "$(P)DISABLE") + + info(archive, "VAL") +} + +# The field the unit is attempting to create. +record(ai, "$(P)FIELD") { + field(DESC, "Demand field readback") + field(DTYP, "stream") + field(SCAN, "1 second") + field(INP, "@OxInstIPS.protocol getDemandField $(PORT)") + field(EGU, "T") + field(PREC, "5") + + field(SIML, "$(P)SIM") + field(SIOL, "$(P)SIM:FIELD") + field(SDIS, "$(P)DISABLE") + + info(INTEREST, "LOW") + info(archive, "VAL") +} + +record(ao, "$(P)FIELD:SP") { + field(DESC, "Set setpoint field") + field(SCAN, "Passive") + field(EGU, "T") + field(PREC, "5") + field(DRVH, "$(MAX_FIELD)") + field(DRVL, "-$(MAX_FIELD)") + + field(SIML, "$(P)SIM") + field(SIOL, "$(P)SIM:FIELD") + field(SDIS, "$(P)DISABLE") + info(archive, "VAL") +} + +# Set the Field Setpoint (i.e. the field the unit will go to and hold for the magnet.) +record(ao, "$(P)FIELD:SP:_RAW") { + field(DESC, "Send raw field to box") + field(DTYP, "stream") + field(SCAN, "Passive") + field(OUT, "@OxInstIPS.protocol setSetpointField $(PORT)") + field(EGU, "T") + field(PREC, "5") + field(DRVH, "$(MAX_FIELD)") + field(DRVL, "-$(MAX_FIELD)") + + field(SIML, "$(P)SIM") + field(SIOL, "$(P)SIM:FIELD") + field(SDIS, "$(P)DISABLE") + info(archive, "VAL") +} + +# The present field setpoint. The target field the unit will aim for when +# told to go to the setpoint. +record(ai, "$(P)FIELD:SP:RBV") { + field(DESC, "Setpoint field readback") + field(DTYP, "stream") + field(SCAN, "1 second") + field(INP, "@OxInstIPS.protocol getSetpointField $(PORT)") + field(EGU, "T") + field(PREC, "5") + + field(SIML, "$(P)SIM") + field(SIOL, "$(P)SIM:FIELD") + field(SDIS, "$(P)DISABLE") + info(archive, "VAL") +} + +# The present sweeprate (a.k.a. ramprate) for adjusting the field. +record(ai, "$(P)FIELD:RATE") { + field(DESC, "Field sweep rate readback") + field(DTYP, "stream") + field(SCAN, "1 second") + field(INP, "@OxInstIPS.protocol getFieldSweepRate $(PORT)") + field(EGU, "T/min") + field(PREC, "4") + + field(LOLO, "0") + field(LLSV, "MAJOR") + + field(SIML, "$(P)SIM") + field(SIOL, "$(P)SIM:FIELD:RATE") + field(SDIS, "$(P)DISABLE") + info(INTEREST, "HIGH") + info(archive, "VAL") +} + +record(ao, "$(P)FIELD:RATE:SP") { + field(DESC, "Set field sweep rate") + field(DTYP, "stream") + field(SCAN, "Passive") + field(OUT, "@OxInstIPS.protocol setFieldSweepRate $(PORT)") + field(EGU, "T/min") + field(PREC, "4") + field(DRVH, "$(MAX_SWEEP_RATE)") + field(DRVL, "0") + field(ASG, "$(MANAGER_ASG)") + + field(SIML, "$(P)SIM") + field(SIOL, "$(P)SIM:FIELD:RATE:SP") + field(SDIS, "$(P)DISABLE") +} + +# The voltage at which the unit will stop ramping/sweeping at the sweeprate +# requested, but reduce it to protect the voltage. +record(ai, "$(P)VOLT:LIMIT:SOFTWARE") { + field(DESC, "Software voltage limit readback") + field(DTYP, "stream") + field(SCAN, "1 second") + field(INP, "@OxInstIPS.protocol getSoftwareVoltageLimit $(PORT)") + field(EGU, "V") + field(PREC, "8") + + field(SIML, "$(P)SIM") + field(SIOL, "$(P)SIM:SOFTWAREVOLTAGELIMIT") + field(SDIS, "$(P)DISABLE") +} + +# This is the current that is in the magnet, which in the case of a magnet with a switch +# and a heater is preserved even when the power unit is not connected (cos of how +# superconducting magnets behave). +record(ai, "$(P)MAGNET:CURR:PERSISTENT") { + field(DESC, "Persistent magnet current readback") + field(DTYP, "stream") + field(SCAN, "1 second") + field(INP, "@OxInstIPS.protocol getPersistentMagnetCurrent $(PORT)") + field(EGU, "A") + field(PREC, "4") + + field(SIML, "$(P)SIM") + field(SIOL, "$(P)SIM:PERSISTENTMAGNETCURRENT") + field(SDIS, "$(P)DISABLE") + + info(archive, "VAL") +} + +## ==== CURR:TRIP needs to be derived somehow. It is not in the SCPI protocol. ==== +# The current at which a trip last occurred. Am not sure if by trip, they mean +# a quench or a problem with the level meter. Believe the unit will take the current +# and field to zero if there is a trip, so this parameter preserves what was happening +# at the time of the trip. +record(ai, "$(P)CURR:TRIP") { + field(DESC, "Trip current readback") + field(DTYP, "stream") + field(SCAN, "1 second") + field(INP, "@OxInstIPS.protocol getTripCurrent $(PORT)") + field(EGU, "A") + field(PREC, "4") + + field(SIML, "$(P)SIM") + field(SIOL, "$(P)SIM:TRIPCURRENT") + field(SDIS, "$(P)DISABLE") + + info(archive, "VAL") +} + +# The field in the magnet due to the persistent current. See current for explanation. +record(ai, "$(P)MAGNET:FIELD:PERSISTENT") { + field(DESC, "Persistent magnet field readback") + field(DTYP, "stream") + field(SCAN, "1 second") + field(INP, "@OxInstIPS.protocol getPersistentMagnetField $(PORT)") + field(EGU, "T") + field(PREC, "5") + + field(SIML, "$(P)SIM") + field(SIOL, "$(P)SIM:PERSISTENTMAGNETFIELD") + field(SDIS, "$(P)DISABLE") + + info(INTEREST, "LOW") + + info(archive, "VAL") +} + +## ==== FIELD:TRIP needs to be derived somehow. It is not in the SCPI protocol. ==== +# The field at which a trip last occurred. See current for explanation. +record(ai, "$(P)FIELD:TRIP") { + field(DESC, "Trip field readback") + field(DTYP, "stream") + field(SCAN, "1 second") + field(INP, "@OxInstIPS.protocol getTripField $(PORT)") + field(EGU, "T") + field(PREC, "5") + + field(SIML, "$(P)SIM") + field(SIOL, "$(P)SIM:TRIPFIELD") + field(SDIS, "$(P)DISABLE") + + info(archive, "VAL") +} + +# The current being provided to the heater. +# Our magnets do not have heaters, so this is not relevant. +record(ai, "$(P)HEATER:CURR") { + field(DESC, "Heater current readback") + field(DTYP, "stream") + field(SCAN, "1 second") + field(INP, "@OxInstIPS.protocol getHeaterCurrent $(PORT)") + field(EGU, "mA") + field(PREC, "4") + + field(SIML, "$(P)SIM") + field(SIOL, "$(P)SIM:HEATERCURRENT") + field(SDIS, "$(P)DISABLE") + + info(archive, "VAL") +} + +# The lower limit for the current. This refers to a limit on the controller and +# is nothing to do with EPICS record limit or alarm fields. +record(ai, "$(P)CURR:LIMIT:NEG") { + field(DESC, "Neg current limit readback") + field(DTYP, "stream") + field(SCAN, "1 second") + field(INP, "@OxInstIPS.protocol getNegCurrentLimit $(PORT)") + field(EGU, "A") + field(PREC, "4") + + field(SIML, "$(P)SIM") + field(SIOL, "$(P)SIM:NEGCURRENTLIMIT") + field(SDIS, "$(P)DISABLE") + + info(archive, "VAL") +} + +# The higher limit for the current. This refers to a limit on the controller and +# is nothing to do with EPICS record limit or alarm fields. +record(ai, "$(P)CURR:LIMIT:POS") { + field(DESC, "Pos current limit readback") + field(DTYP, "stream") + field(SCAN, "1 second") + field(INP, "@OxInstIPS.protocol getPosCurrentLimit $(PORT)") + field(EGU, "A") + field(PREC, "4") + + field(SIML, "$(P)SIM") + field(SIOL, "$(P)SIM:POSCURRENTLIMIT") + field(SDIS, "$(P)DISABLE") + + info(archive, "VAL") +} + +# The resistance of the lead from the unit to the magnet that carries +# the current. This is set by the supplier in the controller, all this +# record does is read and report the value. +record(ai, "$(P)RESISTANCE:LEAD") { + field(DESC, "Leadresistance readback") + field(DTYP, "stream") + field(SCAN, "1 second") + field(INP, "@OxInstIPS.protocol getLeadResistance $(PORT)") + field(EGU, "mohm") + field(PREC, "5") + + field(SIML, "$(P)SIM") + field(SIOL, "$(P)SIM:LEADRESISTANCE") + field(SDIS, "$(P)DISABLE") + + info(archive, "VAL") +} + +# The inductance of the magnet. Believe this is also set by the supplier +# as a calibration. +record(ai, "$(P)MAGNET:INDUCTANCE") { + field(DESC, "Magnet inductance readback") + field(DTYP, "stream") + field(SCAN, "1 second") + field(INP, "@OxInstIPS.protocol getMagnetInductance $(PORT)") + field(EGU, "H") + field(PREC, "5") + + field(SIML, "$(P)SIM") + field(SIOL, "$(P)SIM:MAGNETINDUCTANCE") + field(SDIS, "$(P)DISABLE") + + info(archive, "VAL") +} + +# --------------- The following work around limitation of getting legacy status from SCPI protocol ------------- + +# Get the status DWORD from each group UID +record(mbbiDirect, "$(P)GET:MAGNET:SUPPLY:STATUS") { + field(DESC, "Examine status") + field(DTYP, "stream") + field(INP, "@OxInstIPS.protocol getMagnetSupplyStatus($(P)) $(PORT)") + field(NOBT, "32") + field(SCAN, "1 second") + + field(SIML, "$(P)SIM") + field(SIOL, "$(P)SIM:DONOTHING") + field(SDIS, "$(P)DISABLE") +} + +# Determine the switch heater mismatch status from the supply status bit +record(bi, "$(P)MAGNET:SUPPLY:STATUS:SWHTRMISMATCH") { + field(DESC, "Switch heater mismatch status") + field(DTYP, "Soft Channel") + field(SCAN, "Passive") + field(INP, "$(P)GET:MAGNET:SUPPLY:STATUS.B0 CP MS") + field(ZNAM, "No") + field(ONAM, "Yes") + field(ZSV, "NO_ALARM") + field(OSV, "MAJOR") +} + +# Determine the Over Temperature (rundown resistors) status from the supply status bit +record(bi, "$(P)MAGNET:SUPPLY:STATUS:OTRUNDOWNRES") { + field(DESC, "Over temp rundown resistors status") + field(DTYP, "Soft Channel") + field(SCAN, "Passive") + field(INP, "$(P)GET:MAGNET:SUPPLY:STATUS.B1 CP MS") + field(ZNAM, "No") + field(ONAM, "Yes") + field(ZSV, "NO_ALARM") + field(OSV, "MAJOR") +} + +# Determine the Over Temperature (sense resistor) status from the supply status bit +record(bi, "$(P)MAGNET:SUPPLY:STATUS:OTSENSERES") { + field(DESC, "Over temp sense resistor status") + field(DTYP, "Soft Channel") + field(SCAN, "Passive") + field(INP, "$(P)GET:MAGNET:SUPPLY:STATUS.B2 CP MS") + field(ZNAM, "No") + field(ONAM, "Yes") + field(ZSV, "NO_ALARM") + field(OSV, "MAJOR") +} + +# Determine the Over Temperature (PCB) status from the supply status bit +record(bi, "$(P)MAGNET:SUPPLY:STATUS:OTPCB") { + field(DESC, "Over temp PCB status") + field(DTYP, "Soft Channel") + field(SCAN, "Passive") + field(INP, "$(P)GET:MAGNET:SUPPLY:STATUS.B3 CP MS") + field(ZNAM, "No") + field(ONAM, "Yes") + field(ZSV, "NO_ALARM") + field(OSV, "MAJOR") +} + +# Determine the calibration failure status from the supply status bit +record(bi, "$(P)MAGNET:SUPPLY:STATUS:CALIBFAIL") { + field(DESC, "Calibration failure status") + field(DTYP, "Soft Channel") + field(SCAN, "Passive") + field(INP, "$(P)GET:MAGNET:SUPPLY:STATUS.B4 CP MS") + field(ZNAM, "No") + field(ONAM, "Yes") + field(ZSV, "NO_ALARM") + field(OSV, "MAJOR") +} + +# Determine the MSP430 firmware error failure status from the supply status bit +record(bi, "$(P)MAGNET:SUPPLY:STATUS:FWFAIL") { + field(DESC, "Firmware failure status") + field(DTYP, "Soft Channel") + field(SCAN, "Passive") + field(INP, "$(P)GET:MAGNET:SUPPLY:STATUS.B5 CP MS") + field(ZNAM, "No") + field(ONAM, "Yes") + field(ZSV, "NO_ALARM") + field(OSV, "MAJOR") +} + +# Determine the rundown resistors failure status from the supply status bit +record(bi, "$(P)MAGNET:SUPPLY:STATUS:RRFAIL") { + field(DESC, "Rundown resistors failure status") + field(DTYP, "Soft Channel") + field(SCAN, "Passive") + field(INP, "$(P)GET:MAGNET:SUPPLY:STATUS.B6 CP MS") + field(ZNAM, "No") + field(ONAM, "Yes") + field(ZSV, "NO_ALARM") + field(OSV, "MAJOR") +} + +# Determine the MSP430 RS-485 failure status from the supply status bit +record(bi, "$(P)MAGNET:SUPPLY:STATUS:RS485FAIL") { + field(DESC, "MSP430 RS485 failure status") + field(DTYP, "Soft Channel") + field(SCAN, "Passive") + field(INP, "$(P)GET:MAGNET:SUPPLY:STATUS.B7 CP MS") + field(ZNAM, "No") + field(ONAM, "Yes") + field(ZSV, "NO_ALARM") + field(OSV, "MAJOR") +} + +# Determine the quench status from the supply status bit +record(bi, "$(P)MAGNET:SUPPLY:STATUS:QUENCHED") { + field(DESC, "Quench status") + field(DTYP, "Soft Channel") + field(SCAN, "Passive") + field(INP, "$(P)GET:MAGNET:SUPPLY:STATUS.B8 CP MS") + field(ZNAM, "No") + field(ONAM, "Yes") + field(ZSV, "NO_ALARM") + field(OSV, "MAJOR") +} + +# Determine the catch detection status from the supply status bit +record(bi, "$(P)MAGNET:SUPPLY:STATUS:CATCH") { + field(DESC, "PSU Catch status") + field(DTYP, "Soft Channel") + field(SCAN, "Passive") + field(INP, "$(P)GET:MAGNET:SUPPLY:STATUS.B9 CP MS") + field(ZNAM, "No") + field(ONAM, "Yes") + field(ZSV, "NO_ALARM") + field(OSV, "MAJOR") +} + +# Determine the Sense amplifier over temperature status from the supply status bit +record(bi, "$(P)MAGNET:SUPPLY:STATUS:OTSENSEAMP") { + field(DESC, "Over temp sense amp") + field(DTYP, "Soft Channel") + field(SCAN, "Passive") + field(INP, "$(P)GET:MAGNET:SUPPLY:STATUS.BC CP MS") + field(ZNAM, "No") + field(ONAM, "Yes") + field(ZSV, "NO_ALARM") + field(OSV, "MAJOR") +} + +# Determine amplifier 1 over temperature status from the supply status bit +record(bi, "$(P)MAGNET:SUPPLY:STATUS:OTAMP1") { + field(DESC, "Over temp amp 1") + field(DTYP, "Soft Channel") + field(SCAN, "Passive") + field(INP, "$(P)GET:MAGNET:SUPPLY:STATUS.BD CP MS") + field(ZNAM, "No") + field(ONAM, "Yes") + field(ZSV, "NO_ALARM") + field(OSV, "MAJOR") +} + +# Determine amplifier 2 over temperature status from the supply status bit +record(bi, "$(P)MAGNET:SUPPLY:STATUS:OTAMP2") { + field(DESC, "Over temp amp 2") + field(DTYP, "Soft Channel") + field(SCAN, "Passive") + field(INP, "$(P)GET:MAGNET:SUPPLY:STATUS.BE CP MS") + field(ZNAM, "No") + field(ONAM, "Yes") + field(ZSV, "NO_ALARM") + field(OSV, "MAJOR") +} + +# Determine PWM Cutoff status from the supply status bit +record(bi, "$(P)MAGNET:SUPPLY:STATUS:PWMCUTOFF") { + field(DESC, "PWM Cutoff status") + field(DTYP, "Soft Channel") + field(SCAN, "Passive") + field(INP, "$(P)GET:MAGNET:SUPPLY:STATUS.BF CP MS") + field(ZNAM, "No") + field(ONAM, "Yes") + field(ZSV, "NO_ALARM") + field(OSV, "MAJOR") +} + +# Determine Voltage ADC error status from the supply status bit +record(bi, "$(P)MAGNET:SUPPLY:STATUS:VADCERROR") { + field(DESC, "Voltage ADC error status") + field(DTYP, "Soft Channel") + field(SCAN, "Passive") + field(INP, "$(P)GET:MAGNET:SUPPLY:STATUS.B10 CP MS") + field(ZNAM, "No") + field(ONAM, "Yes") + field(ZSV, "NO_ALARM") + field(OSV, "MAJOR") +} + +# Determine Current ADC error status from the supply status bit +record(bi, "$(P)MAGNET:SUPPLY:STATUS:IADCERROR") { + field(DESC, "Current ADC error status") + field(DTYP, "Soft Channel") + field(SCAN, "Passive") + field(INP, "$(P)GET:MAGNET:SUPPLY:STATUS.B11 CP MS") + field(ZNAM, "No") + field(ONAM, "Yes") + field(ZSV, "NO_ALARM") + field(OSV, "MAJOR") +} + +# The over temperature status should be an or'd output from the numerous temperature alarms +record(calc, "$(P)MAGNET:SUPPLY:STATUS:OVERTEMP:CALC") { + field(DESC, "Temperature status calc (combined)") + field(DTYP, "Soft Channel") + field(SCAN, "Passive") + field(INPA, "$(P)GET:MAGNET:SUPPLY:OTRUNDOWNRES CP MS") + field(INPB, "$(P)GET:MAGNET:SUPPLY:OTSENSERES CP MS") + field(INPC, "$(P)GET:MAGNET:SUPPLY:OTPCB CP MS") + field(INPD, "$(P)GET:MAGNET:SUPPLY:OTSENSEAMP CP MS") + field(INPE, "$(P)GET:MAGNET:SUPPLY:OTAMP1 CP MS") + field(INPF, "$(P)GET:MAGNET:SUPPLY:OTAMP2 CP MS") + field(CALC, "A|B|C|D|E|F") + field(ZSV, "NO_ALARM") + field(OSV, "MAJOR") +} + +# Determine the Over Temperature status from the or'd calc record (OVERTEMP:CALC) +record(bi, "$(P)MAGNET:SUPPLY:STATUS:OVERTEMP") { + field(DESC, "Temperature status (combined)") + field(DTYP, "Soft Channel") + field(SCAN, "Passive") + field(INP, "$(P)GET:MAGNET:SUPPLY:STATUS:OVERTEMP:CALC CP MS") + field(ZNAM, "No") + field(ONAM, "Yes") + field(ZSV, "NO_ALARM") + field(OSV, "MAJOR") +} + +# -------------------------------------------------------------------------------------------------------------- + +## Derive the SYSTEM:HWFAULT status from the status bits +## This collates the various possible hardware faults into a single record, +## which in the legacy protocol is a single value (Xm bit 4). +record(calc, "$(P)STS:SYSTEM:HWFAULT:CALC") { + field(DESC, "System hardware fault status calc") + field(DTYP, "Soft Channel") + field(SCAN, "Passive") + field(INPA, "$(P)MAGNET:SUPPLY:STATUS:SWHTRMISMATCH CP MS") + field(INPB, "$(P)MAGNET:SUPPLY:STATUS:CALIBFAIL CP MS") + field(INPC, "$(P)MAGNET:SUPPLY:STATUS:FWFAIL CP MS") + field(INPD, "$(P)MAGNET:SUPPLY:STATUS:RRFAIL CP MS") + field(INPE, "$(P)MAGNET:SUPPLY:STATUS:RS485FAIL CP MS") + field(INPF, "$(P)MAGNET:SUPPLY:STATUS:CATCH CP MS") + field(INPG, "$(P)MAGNET:SUPPLY:STATUS:PWMCUTOFF CP MS") + field(INPH, "$(P)MAGNET:SUPPLY:STATUS:VADCERROR CP MS") + field(INPI, "$(P)MAGNET:SUPPLY:STATUS:IADCERROR CP MS") + field(CALC, "(A>0||B>0||C>0||D>0||E>0||F>0||G>0||H>0||I>0) ? 1 : 0") + field(ZSV, "NO_ALARM") + field(OSV, "MAJOR") +} + +## Derive the SYSTEM:FAULT status from the status bits +## This collates the various possible faults into a single record, in alignment with the legacy protocol. +record(calc, "$(P)STS:SYSTEM:FAULT:CALC") { + field(DESC, "System fault status calc") + field(DTYP, "Soft Channel") + field(SCAN, "Passive") + field(INPA, "$(P)MAGNET:SUPPLY:STATUS:QUENCHED CP MS") + field(INPB, "$(P)MAGNET:SUPPLY:STATUS:OVERTEMP CP MS") + field(INPC, "$(P)MAGNET:SUPPLY:STATUS:HWFAULT:CALC CP MS") + field(CALC, "(A>0) ? 1 : (B>0) ? 2 : (C>0) ? 8 : 0") + field(ZSV, "NO_ALARM") + field(OSV, "MAJOR") +} + +# # Readback from m of Xmn part of Examine command return. +record(mbbi, "$(P)STS:SYSTEM:FAULT") { + field(DESC, "System fault status") + field(DTYP, "Soft Channel") + field(SCAN, "Passive") + field(INP, "$(P)STS:SYSTEM:FAULT:CALC CP MS") + field(ZRST, "Normal") + field(ZRVL, "0") + field(ZRSV, "NO_ALARM") + field(ONST, "Quenched") + field(ONVL, "1") + field(ONSV, "MAJOR") + field(TWST, "Overheated") + field(TWVL, "2") + field(TWSV, "MAJOR") + field(FRST, "Warming Up") + field(FRVL, "4") + field(FRSV, "MAJOR") + field(EIST, "Fault") + field(EIVL, "8") + field(EISV, "MAJOR") + + info(archive, "VAL") +} + +# # Readback from n of Xmn part of Examine command return. +record(mbbi, "$(P)STS:SYSTEM:LIMIT") { + field(DESC, "System limit status") + field(DTYP, "Soft Channel") + field(SCAN, "Passive") + field(ZRST, "Normal") + field(ZRVL, "0") + field(ZRSV, "NO_ALARM") + field(ONST, "On +ve V Limit") + field(ONVL, "1") + field(ONSV, "MINOR") + field(TWST, "On -ve V Limit") + field(TWVL, "2") + field(TWSV, "MINOR") + field(FRST, "Current too -ve") + field(FRVL, "4") + field(FRSV, "MINOR") + field(EIST, "Current too +ve") + field(EIVL, "8") + field(EISV, "MINOR") + + info(archive, "VAL") +} + +# Readback from SWHT command. +# OFF -> switch closed, ON -> switch open. +record(mbbi, "$(P)HEATER:STATUS") { + field(DESC, "Heater status") + field(DTYP, "Soft Channel") + field(SCAN, "1 second") + field(INP, "@OxInstIPS.protocol getHeaterStatus $(PORT)") + field(ZRST, "Off") + field(ZRVL, "0") + field(ONST, "On") + field(ONVL, "1") + + field(SIML, "$(P)SIM") + field(SIOL, "$(P)SIM:HEATER:STATUS") + field(SDIS, "$(P)DISABLE") + + info(archive, "VAL") +} + +record(bo, "$(P)HEATER:STATUS:SP") { + field(DESC, "Set Remote/Local Control") + field(DTYP, "stream") + field(SCAN, "Passive") + field(OUT, "@OxInstIPS.protocol setHeaterStatus $(PORT)") + field(ZNAM, "Off") + field(ONAM, "On") + + field(SIML, "$(P)SIM") + field(SIOL, "$(P)SIM:HEATER:STATUS:SP") + field(SDIS, "$(P)DISABLE") +} + +# Amount of time to wait for heater to warm up/cool down. **CAN CAUSE MAGNET TO QUENCH IF SET TOO LOW** +# Oxford Instruments labview driver uses 30s. ISIS cryogenics have asked us to increase this to 60s, +# which is more conservative. +# The HEATER_WAITTIME IOC macro, which is _not_ user-facing, has a default of 60s. +# Configurable to lower values to shorten time for IOC tests. + +record(ao, "$(P)HEATER:WAITTIME") { + field(DESC, "Time to wait for heater") + field(VAL, "$(HEATER_WAITTIME)") + field(PINI, "YES") + info(archive, "VAL") +} + +# CALC record to coerce heater status values. Heater can be off in states 0 or 2, and in error in states 5 or 8, +# and circular buffer (N to 1 Low Value) only looks for lowest (0). +# Output 1 only if heater is on, 0 if off and all other states, including errors. + +record(calc, "$(P)HEATER:_STATUS_CALC") { + field(DESC, "Binary Heater Status") + field(INPA, "$(P)HEATER:STATUS CP MS") + field(CALC, "(A=1)?1:0") # If heater is on, output 1, otherwise 0 + info(archive, "VAL") +} + +# COMPRESS Record with circular buffer to store $(HEATER_WAITTIME) worth of HEATER:STATUS values +# Used with second COMPRESS record below to check heater has been on for at least $(HEATER_WAITTIME) after starting IOC + +record(compress, "$(P)HEATER:_STATUS_BUFFER") { + field(DESC, "Buffer of heater status values") + field(INP, "$(P)HEATER:_STATUS_CALC.VAL") + field(ALG, "Circular Buffer") + field(NSAM, "$(HEATER_WAITTIME)") + field(SCAN, "1 second") + field(FLNK, "$(P)HEATER:_STATUS_BUFFER_LOWEST") +} + +# COMPRESS record to monitor above and output lowest value in buffer. +# If '1' then whole buffer contains '1' and therefore heater has been ON for at least $(HEATER_WAITTIME) +# If '0' then heater has been OFF at some point in $(HEATER_WAITTIME) + +record(compress, "$(P)HEATER:_STATUS_BUFFER_LOWEST") { + field(DESC, "Lowest value of heater status buffer") + field(INP, "$(P)HEATER:_STATUS_BUFFER") + field(ALG, "N to 1 Low Value") + field(NSAM, "1") + field(N, "$(HEATER_WAITTIME)") + field(FLNK, "$(P)HEATER:ONTIME_OK") + info(archive, "VAL") +} + +# BO record to indicate whether or not heater been on for at least $(HEATER_WAITTIME). Monitored by statemachine to determine whether or not OK to set field. + +record(bo, "$(P)HEATER:ONTIME_OK") { + field(DESC, "Heater on for at least $(HEATER_WAITTIME)s") + field(DTYP, "Soft Channel") + field(SCAN, "Passive") + field(OMSL, "closed_loop") + field(DOL, "$(P)HEATER:_STATUS_BUFFER_LOWEST.VAL") + field(ZNAM, "Heater OFF in last $(HEATER_WAITTIME)s") + field(ONAM, "Heater ON for > $(HEATER_WAITTIME)s") + info(archive, "VAL") +} + + +# Readback from m of Mmn part of Examine command return. +# The Display is in Amps or Tesla. The Magnet Sweep is fast or slow. +record(mbbi, "$(P)SWEEPMODE:PARAMS") { + field(DESC, "Mode status") + field(DTYP, "Soft Channel") + field(SCAN, "Passive") + field(ZRST, "Amps Fast") + field(ZRVL, "0") + field(ONST, "Tesla Fast") + field(ONVL, "1") + field(TWST, "Amps Fast") + field(TWVL, "2") + field(THST, "Tesla Fast") + field(THVL, "3") + field(FRST, "Amps Slow") + field(FRVL, "4") + field(FVST, "Tesla Slow") + field(FVVL, "5") + field(SXST, "Amps Slow") + field(SXVL, "6") + field(SVST, "Tesla Slow") + field(SVVL, "7") + field(EIST, "Amps Unaffected") + field(EIVL, "8") + field(NIST, "Tesla Unaffected") + field(NIVL, "9") + + field(VAL, "3") + field(PINI, "YES") + + field(SIML, "$(P)SIM") + field(SIOL, "$(P)SIM:SWEEPMODE:PARAMS") + field(SDIS, "$(P)DISABLE") + + info(archive, "VAL") +} + +# To set the sweep and display mode - its a bit confusing as there +# are duplicates, but we do not present this choice to the user. +# +record(mbbo, "$(P)SWEEPMODE:PARAMS:SP") { + field(DESC, "Set sweep and display mode.") + field(DTYP, "stream") + field(SCAN, "Passive") + field(ZRST, "Amps Fast") + field(ZRVL, "0") + field(ONST, "Tesla Fast") + field(ONVL, "1") + field(TWST, "Amps Fast") + field(TWVL, "2") + field(THST, "Tesla Fast") + field(THVL, "3") + field(FRST, "Amps Slow") + field(FRVL, "4") + field(FVST, "Tesla Slow") + field(FVVL, "5") + field(SXST, "Amps Slow") + field(SXVL, "6") + field(SVST, "Tesla Slow") + field(SVVL, "7") + field(EIST, "Amps Unaffected") + field(EIVL, "8") + field(NIST, "Tesla Unaffected") + field(NIVL, "9") + field(OUT, "@OxInstIPS.protocol setMode $(PORT)") + + field(VAL, "3") + field(PINI, "YES") + + field(SIML, "$(P)SIM") + field(SIOL, "$(P)SIM:SWEEPMODE:PARAMS:SP") + field(SDIS, "$(P)DISABLE") +} + +# Readback from n of Mmn part of Examine command return. +# (Ignore the Pmn part of the Examine command return - no records for this.) +# 0 output constant, 1, 2, 3 output changing +record(mbbi, "$(P)STS:SWEEPMODE:SWEEP") { + field(DESC, "Mode status") + field(DTYP, "Soft Channel") + field(SCAN, "Passive") + field(ZRST, "At rest") + field(ZRVL, "0") + field(ONST, "Sweeping") + field(ONVL, "1") + field(TWST, "Sweep Limiting") + field(TWVL, "2") + field(THST, "Swping & Lmting") + field(THVL, "3") + + field(SIML, "$(P)SIM") + field(SIOL, "$(P)SIM:STS:SWEEPMODE:SWEEP") + field(SDIS, "$(P)DISABLE") + + info(archive, "VAL") +} + +# To capture bits of mismatching status protocol. +# We do not do much with it at the moment. +record(stringin, "$(P)DBG:STS:MISMATCH") { + field(DESC, "Mismatching protocol string.") + field(DTYP, "Soft Channel") + field(SCAN, "Passive") +} + +# Diddle with the comms and reported resolution. +# This is the nasty Q command which does not reply and whose +# info does not get reported by the status command. +# This may be needed after power cycle of IPS or if it has +# been connected to the Oxford Instruments Windows Application +# to allow EPICS to talk to it and to allow the resolution to be extended. +# Are not supporting setting these things individually, just setting +# what we want. +record(ao, "$(P)SET:COMMSRES") { + field(DESC, "Set ext. resn, no LF") + field(DTYP, "stream") + field(SCAN, "Passive") + field(VAL, "6") + field(PINI, "YES") + field(OUT, "@OxInstIPS.protocol setCommsResExtended $(PORT)") + + field(SIML, "$(P)SIM") + field(SIOL, "$(P)SIM:DONOTHING") + field(SDIS, "$(P)DISABLE") +} + +# Diddle with the comms wait interval. +# Probably will not need this, but put it here in case we do. Will not put access to this +# on the GUI. +record(ao, "$(P)SET:WAITINTERVAL") { + field(DESC, "Set wait interval") + field(DTYP, "stream") + field(SCAN, "Passive") + field(EGU, "ms") + field(OUT, "@OxInstIPS.protocol setWaitInterval $(PORT)") + + field(SIML, "$(P)SIM") + field(SIOL, "$(P)SIM:DONOTHING") + field(SDIS, "$(P)DISABLE") +} + +record(bo, "$(P)PERSISTENT") { + field(DESC, "Set magnet to persistent") + field(ZNAM, "NO") + field(ONAM, "YES") + field(PINI, "YES") + info(autosaveFields, "VAL") + info(INTEREST, "HIGH") + info(archive, "VAL") +} + +# Play nicely with blocks/genie_python +alias("$(P)PERSISTENT", "$(P)PERSISTENT:SP") + + +record(mbbo, "$(P)STATEMACHINE") { + field(DESC, "What the IOC is doing") + + field(ZRVL, "0") + field(ZRST, "Initial state") + + field(ONVL, "1") + field(ONST, "At field") + + field(TWVL, "2") + field(TWST, "Set PSU to match magnet") + + field(THVL, "3") + field(THST, "Wait for volts stable") + + field(FRVL, "4") + field(FRST, "Ensure heater on & warm") + + field(FVVL, "5") + field(FVST, "Set PSU to setpoint") + + field(SXVL, "6") + field(SXST, "Turn heater off & wait") + + field(SVVL, "7") + field(SVST, "Set PSU to zero") + + info(archive, "VAL") +} + + +### +### Records to be more "friendly" to the user. +### + +record(calc, "$(P)FIELD:USER") { + field(DESC, "Field readback") + field(INPA, "$(P)MAGNET:FIELD:PERSISTENT CP MS") + field(INPB, "$(P)FIELD CP MS") + field(INPC, "$(P)HEATER:STATUS CP MS") + field(CALC, "(C=0||C=2)?A:B") # If heater is present and switched off, display persistent field, else display PSU field + field(ASG, "READONLY") + field(EGU, "T") + field(PREC, "5") + info(interest, "HIGH") + info(archive, "VAL") +} + +alias("$(P)FIELD:SP", "$(P)FIELD:USER:SP") # "User" setpoint is same as "normal" setpoint + + +### Simulation record - Just to stop errors, doesn't do anything + +record(ao, "$(P)SIM:DONOTHING") {} + +record(mbbo, "$(P)SIM:SWEEPMODE:PARAMS") { + field(ZRST, "Amps Fast") + field(ZRVL, "0") + field(ONST, "Tesla Fast") + field(ONVL, "1") + field(TWST, "Amps Fast") + field(TWVL, "2") + field(THST, "Tesla Fast") + field(THVL, "3") + field(FRST, "Amps Slow") + field(FRVL, "4") + field(FVST, "Tesla Slow") + field(FVVL, "5") + field(SXST, "Amps Slow") + field(SXVL, "6") + field(SVST, "Tesla Slow") + field(SVVL, "7") + field(EIST, "Amps Unaffected") + field(EIVL, "8") + field(NIST, "Tesla Unaffected") + field(NIVL, "9") +} + +alias("$(P)SIM:SWEEPMODE:PARAMS", "$(P)SIM:SPEEPMODE:PARAMS:SP") + +record(bo, "$(P)SIM:HEATER:STATUS") { + field(ZNAM, "Off") + field(ONAM, "On") +} + +alias("$(P)SIM:HEATER:STATUS", "$(P)SIM:HEATER:STATUS:SP") + +record(ao, "$(P)SIM:MAGNETINDUCTANCE"){} +record(ao, "$(P)SIM:LEADRESISTANCE"){} +record(ao, "$(P)SIM:POSCURRENTLIMIT"){} +record(ao, "$(P)SIM:NEGCURRENTLIMIT"){} +record(ao, "$(P)SIM:HEATERCURRENT"){} +record(ao, "$(P)SIM:TRIPFIELD"){} +record(ao, "$(P)SIM:TRIPCURRENT"){} +record(ao, "$(P)SIM:CURR:RATE"){} +record(ao, "$(P)SIM:SUPPLY:VOLT"){} +record(ao, "$(P)SIM:CURRENT"){} +record(ao, "$(P)SIM:SOFTWAREVOLTAGELIMIT"){} +record(ao, "$(P)SIM:FIELD:RATE"){} +record(ao, "$(P)SIM:FIELD"){} +alias("$(P)SIM:FIELD:RATE", "$(P)SIM:FIELD:RATE:SP") + +record(mbbo, "$(P)SIM:ACTIVITY") { + field(ZRST, "Hold") + field(ZRVL, "0") + field(ONST, "To Setpoint") + field(ONVL, "1") + field(TWST, "To Zero") + field(TWVL, "2") + field(FRST, "Clamp") + field(FRVL, "4") +} + +alias("$(P)SIM:ACTIVITY", "$(P)SIM:ACTIVITY:SP") + +record(mbbo, "$(P)SIM:CONTROL") { + field(ZRST, "Local & Locked") + field(ZRVL, "0") + field(ONST, "Remote & Locked") + field(ONVL, "1") + field(TWST, "Local & Unlocked") + field(TWVL, "2") + field(THST, "Remote & Unlocked") + field(THVL, "3") +} + +alias("$(P)SIM:CONTROL", "$(P)SIM:CONTROL:SP") From 707fde7324c949ed5b2fb4f824f4634a206894ff Mon Sep 17 00:00:00 2001 From: Ian Gillingham Date: Tue, 1 Apr 2025 15:14:55 +0100 Subject: [PATCH 09/29] Reverted ips.db to original to continue development of SCPI option in ips_scpi.db --- IPS/IPS-IOC-01App/Db/ips.db | 282 +----------------------------------- 1 file changed, 1 insertion(+), 281 deletions(-) diff --git a/IPS/IPS-IOC-01App/Db/ips.db b/IPS/IPS-IOC-01App/Db/ips.db index 876189a6f..a820c7c22 100644 --- a/IPS/IPS-IOC-01App/Db/ips.db +++ b/IPS/IPS-IOC-01App/Db/ips.db @@ -24,7 +24,7 @@ record(bo, "$(P)DISABLE") # # Run the Version command, V. # # The string was too long to put model and version into same record. # # Scan this once, probably not needed again. -# The reply comes back and is split amongst other records in the StreamDevice protocol file. +# The reply comes back and is split amongst other records. record(stringin, "$(P)GET:VERSION") { field(DESC, "Examine status") field(DTYP, "stream") @@ -37,7 +37,6 @@ record(stringin, "$(P)GET:VERSION") { field(SDIS, "$(P)DISABLE") } -# Updated in GET:VERSION call to getVersion() record(stringin, "$(P)MODEL") { field(DESC, "Model") field(DTYP, "Soft Channel") @@ -45,14 +44,12 @@ record(stringin, "$(P)MODEL") { field(FLNK, "$(P)VERSION") } -# Updated in GET:VERSION call to getVersion() record(stringin, "$(P)VERSION") { field(DESC, "Firmware version.") field(DTYP, "Soft Channel") field(SCAN, "Passive") } -## !! Check this for SCPI - IJG 27/3/25 # # Readback from Cn part of Examine command return. record(mbbi, "$(P)CONTROL") { field(DESC, "Control status") @@ -95,7 +92,6 @@ record(mbbi, "$(P)CONTROL") { info(alarm, "IPS") } -## !! Modify for SCPI - IJG 27/3/25 # Grab remote vs local control record(mbbo, "$(P)CONTROL:SP") { field(DESC, "Set remote/local control") @@ -145,7 +141,6 @@ record(mbbi, "$(P)ACTIVITY") { info(archive, "VAL") } -## !! Modify for SCPI - IJG 27/3/25 # Hold means maintaining present current. # Clamped means you cannot adjust it - powers up in this # state. Only the set activity hold command can get out @@ -420,7 +415,6 @@ record(ai, "$(P)MAGNET:CURR:PERSISTENT") { info(archive, "VAL") } -## ==== CURR:TRIP needs to be derived somehow. It is not in the SCPI protocol. ==== # The current at which a trip last occurred. Am not sure if by trip, they mean # a quench or a problem with the level meter. Believe the unit will take the current # and field to zero if there is a trip, so this parameter preserves what was happening @@ -458,7 +452,6 @@ record(ai, "$(P)MAGNET:FIELD:PERSISTENT") { info(archive, "VAL") } -## ==== FIELD:TRIP needs to be derived somehow. It is not in the SCPI protocol. ==== # The field at which a trip last occurred. See current for explanation. record(ai, "$(P)FIELD:TRIP") { field(DESC, "Trip field readback") @@ -561,243 +554,6 @@ record(ai, "$(P)MAGNET:INDUCTANCE") { info(archive, "VAL") } -# --------------- The following work around limitation of getting legacy status from SCPI protocol ------------- - -# Get the status DWORD from each group UID -record(mbbiDirect, "$(P)GET:MAGNET:SUPPLY:STATUS") { - field(DESC, "Examine status") - field(DTYP, "stream") - field(INP, "@OxInstIPS.protocol getMagnetSupplyStatus($(P)) $(PORT)") - field(NOBT, "32") - field(SCAN, "1 second") - - field(SIML, "$(P)SIM") - field(SIOL, "$(P)SIM:DONOTHING") - field(SDIS, "$(P)DISABLE") -} - -# Determine the switch heater mismatch status from the supply status bit -record(bi, "$(P)MAGNET:SUPPLY:STATUS:SWHTRMISMATCH") { - field(DESC, "Switch heater mismatch status") - field(DTYP, "Soft Channel") - field(SCAN, "Passive") - field(INP, "$(P)GET:MAGNET:SUPPLY:STATUS.B0 CP MS") - field(ZNAM, "No") - field(ONAM, "Yes") - field(ZSV, "NO_ALARM") - field(OSV, "MAJOR") -} - -# Determine the Over Temperature (rundown resistors) status from the supply status bit -record(bi, "$(P)MAGNET:SUPPLY:STATUS:OTRUNDOWNRES") { - field(DESC, "Over temp rundown resistors status") - field(DTYP, "Soft Channel") - field(SCAN, "Passive") - field(INP, "$(P)GET:MAGNET:SUPPLY:STATUS.B1 CP MS") - field(ZNAM, "No") - field(ONAM, "Yes") - field(ZSV, "NO_ALARM") - field(OSV, "MAJOR") -} - -# Determine the Over Temperature (sense resistor) status from the supply status bit -record(bi, "$(P)MAGNET:SUPPLY:STATUS:OTSENSERES") { - field(DESC, "Over temp sense resistor status") - field(DTYP, "Soft Channel") - field(SCAN, "Passive") - field(INP, "$(P)GET:MAGNET:SUPPLY:STATUS.B2 CP MS") - field(ZNAM, "No") - field(ONAM, "Yes") - field(ZSV, "NO_ALARM") - field(OSV, "MAJOR") -} - -# Determine the Over Temperature (PCB) status from the supply status bit -record(bi, "$(P)MAGNET:SUPPLY:STATUS:OTPCB") { - field(DESC, "Over temp PCB status") - field(DTYP, "Soft Channel") - field(SCAN, "Passive") - field(INP, "$(P)GET:MAGNET:SUPPLY:STATUS.B3 CP MS") - field(ZNAM, "No") - field(ONAM, "Yes") - field(ZSV, "NO_ALARM") - field(OSV, "MAJOR") -} - -# Determine the calibration failure status from the supply status bit -record(bi, "$(P)MAGNET:SUPPLY:STATUS:CALIBFAIL") { - field(DESC, "Calibration failure status") - field(DTYP, "Soft Channel") - field(SCAN, "Passive") - field(INP, "$(P)GET:MAGNET:SUPPLY:STATUS.B4 CP MS") - field(ZNAM, "No") - field(ONAM, "Yes") - field(ZSV, "NO_ALARM") - field(OSV, "MAJOR") -} - -# Determine the MSP430 firmware error failure status from the supply status bit -record(bi, "$(P)MAGNET:SUPPLY:STATUS:FWFAIL") { - field(DESC, "Firmware failure status") - field(DTYP, "Soft Channel") - field(SCAN, "Passive") - field(INP, "$(P)GET:MAGNET:SUPPLY:STATUS.B5 CP MS") - field(ZNAM, "No") - field(ONAM, "Yes") - field(ZSV, "NO_ALARM") - field(OSV, "MAJOR") -} - -# Determine the rundown resistors failure status from the supply status bit -record(bi, "$(P)MAGNET:SUPPLY:STATUS:RRFAIL") { - field(DESC, "Rundown resistors failure status") - field(DTYP, "Soft Channel") - field(SCAN, "Passive") - field(INP, "$(P)GET:MAGNET:SUPPLY:STATUS.B6 CP MS") - field(ZNAM, "No") - field(ONAM, "Yes") - field(ZSV, "NO_ALARM") - field(OSV, "MAJOR") -} - -# Determine the MSP430 RS-485 failure status from the supply status bit -record(bi, "$(P)MAGNET:SUPPLY:STATUS:RS485FAIL") { - field(DESC, "MSP430 RS485 failure status") - field(DTYP, "Soft Channel") - field(SCAN, "Passive") - field(INP, "$(P)GET:MAGNET:SUPPLY:STATUS.B7 CP MS") - field(ZNAM, "No") - field(ONAM, "Yes") - field(ZSV, "NO_ALARM") - field(OSV, "MAJOR") -} - -# Determine the quench status from the supply status bit -record(bi, "$(P)MAGNET:SUPPLY:STATUS:QUENCHED") { - field(DESC, "Quench status") - field(DTYP, "Soft Channel") - field(SCAN, "Passive") - field(INP, "$(P)GET:MAGNET:SUPPLY:STATUS.B8 CP MS") - field(ZNAM, "No") - field(ONAM, "Yes") - field(ZSV, "NO_ALARM") - field(OSV, "MAJOR") -} - -# Determine the catch detection status from the supply status bit -record(bi, "$(P)MAGNET:SUPPLY:STATUS:CATCH") { - field(DESC, "PSU Catch status") - field(DTYP, "Soft Channel") - field(SCAN, "Passive") - field(INP, "$(P)GET:MAGNET:SUPPLY:STATUS.B9 CP MS") - field(ZNAM, "No") - field(ONAM, "Yes") - field(ZSV, "NO_ALARM") - field(OSV, "MAJOR") -} - -# Determine the Sense amplifier over temperature status from the supply status bit -record(bi, "$(P)MAGNET:SUPPLY:STATUS:OTSENSEAMP") { - field(DESC, "Over temp sense amp") - field(DTYP, "Soft Channel") - field(SCAN, "Passive") - field(INP, "$(P)GET:MAGNET:SUPPLY:STATUS.BC CP MS") - field(ZNAM, "No") - field(ONAM, "Yes") - field(ZSV, "NO_ALARM") - field(OSV, "MAJOR") -} - -# Determine amplifier 1 over temperature status from the supply status bit -record(bi, "$(P)MAGNET:SUPPLY:STATUS:OTAMP1") { - field(DESC, "Over temp amp 1") - field(DTYP, "Soft Channel") - field(SCAN, "Passive") - field(INP, "$(P)GET:MAGNET:SUPPLY:STATUS.BD CP MS") - field(ZNAM, "No") - field(ONAM, "Yes") - field(ZSV, "NO_ALARM") - field(OSV, "MAJOR") -} - -# Determine amplifier 2 over temperature status from the supply status bit -record(bi, "$(P)MAGNET:SUPPLY:STATUS:OTAMP2") { - field(DESC, "Over temp amp 2") - field(DTYP, "Soft Channel") - field(SCAN, "Passive") - field(INP, "$(P)GET:MAGNET:SUPPLY:STATUS.BE CP MS") - field(ZNAM, "No") - field(ONAM, "Yes") - field(ZSV, "NO_ALARM") - field(OSV, "MAJOR") -} - -# Determine PWM Cutoff status from the supply status bit -record(bi, "$(P)MAGNET:SUPPLY:STATUS:PWMCUTOFF") { - field(DESC, "PWM Cutoff status") - field(DTYP, "Soft Channel") - field(SCAN, "Passive") - field(INP, "$(P)GET:MAGNET:SUPPLY:STATUS.BF CP MS") - field(ZNAM, "No") - field(ONAM, "Yes") - field(ZSV, "NO_ALARM") - field(OSV, "MAJOR") -} - -# Determine Voltage ADC error status from the supply status bit -record(bi, "$(P)MAGNET:SUPPLY:STATUS:VADCERROR") { - field(DESC, "Voltage ADC error status") - field(DTYP, "Soft Channel") - field(SCAN, "Passive") - field(INP, "$(P)GET:MAGNET:SUPPLY:STATUS.B10 CP MS") - field(ZNAM, "No") - field(ONAM, "Yes") - field(ZSV, "NO_ALARM") - field(OSV, "MAJOR") -} - -# Determine Current ADC error status from the supply status bit -record(bi, "$(P)MAGNET:SUPPLY:STATUS:IADCERROR") { - field(DESC, "Current ADC error status") - field(DTYP, "Soft Channel") - field(SCAN, "Passive") - field(INP, "$(P)GET:MAGNET:SUPPLY:STATUS.B11 CP MS") - field(ZNAM, "No") - field(ONAM, "Yes") - field(ZSV, "NO_ALARM") - field(OSV, "MAJOR") -} - -# The over temperature status should be an or'd output from the numerous temperature alarms -record(calc, "$(P)MAGNET:SUPPLY:STATUS:OVERTEMP:CALC") { - field(DESC, "Temperature status calc (combined)") - field(DTYP, "Soft Channel") - field(SCAN, "Passive") - field(INPA, "$(P)GET:MAGNET:SUPPLY:OTRUNDOWNRES CP MS") - field(INPB, "$(P)GET:MAGNET:SUPPLY:OTSENSERES CP MS") - field(INPC, "$(P)GET:MAGNET:SUPPLY:OTPCB CP MS") - field(INPD, "$(P)GET:MAGNET:SUPPLY:OTSENSEAMP CP MS") - field(INPE, "$(P)GET:MAGNET:SUPPLY:OTAMP1 CP MS") - field(INPF, "$(P)GET:MAGNET:SUPPLY:OTAMP2 CP MS") - field(CALC, "A|B|C|D|E|F") - field(ZSV, "NO_ALARM") - field(OSV, "MAJOR") -} - -# Determine the Over Temperature status from the or'd calc record (OVERTEMP:CALC) -record(bi, "$(P)MAGNET:SUPPLY:STATUS:OVERTEMP") { - field(DESC, "Temperature status (combined)") - field(DTYP, "Soft Channel") - field(SCAN, "Passive") - field(INP, "$(P)GET:MAGNET:SUPPLY:STATUS:OVERTEMP:CALC CP MS") - field(ZNAM, "No") - field(ONAM, "Yes") - field(ZSV, "NO_ALARM") - field(OSV, "MAJOR") -} - -# -------------------------------------------------------------------------------------------------------------- - # # Run the Examine Status command, X. # The reply comes back and is split amongst other records. record(stringin, "$(P)GET:STATUS") { @@ -811,47 +567,11 @@ record(stringin, "$(P)GET:STATUS") { field(SDIS, "$(P)DISABLE") } -## Derive the SYSTEM:HWFAULT status from the status bits -## This collates the various possible hardware faults into a single record, -## which in the legacy protocol is a single value (Xm bit 4). -record(calc, "$(P)STS:SYSTEM:HWFAULT:CALC") { - field(DESC, "System hardware fault status calc") - field(DTYP, "Soft Channel") - field(SCAN, "Passive") - field(INPA, "$(P)MAGNET:SUPPLY:STATUS:SWHTRMISMATCH CP MS") - field(INPB, "$(P)MAGNET:SUPPLY:STATUS:CALIBFAIL CP MS") - field(INPC, "$(P)MAGNET:SUPPLY:STATUS:FWFAIL CP MS") - field(INPD, "$(P)MAGNET:SUPPLY:STATUS:RRFAIL CP MS") - field(INPE, "$(P)MAGNET:SUPPLY:STATUS:RS485FAIL CP MS") - field(INPF, "$(P)MAGNET:SUPPLY:STATUS:CATCH CP MS") - field(INPG, "$(P)MAGNET:SUPPLY:STATUS:PWMCUTOFF CP MS") - field(INPH, "$(P)MAGNET:SUPPLY:STATUS:VADCERROR CP MS") - field(INPI, "$(P)MAGNET:SUPPLY:STATUS:IADCERROR CP MS") - field(CALC, "(A>0||B>0||C>0||D>0||E>0||F>0||G>0||H>0||I>0) ? 1 : 0") - field(ZSV, "NO_ALARM") - field(OSV, "MAJOR") -} - -## Derive the SYSTEM:FAULT status from the status bits -## This collates the various possible faults into a single record, in alignment with the legacy protocol. -record(calc, "$(P)STS:SYSTEM:FAULT:CALC") { - field(DESC, "System fault status calc") - field(DTYP, "Soft Channel") - field(SCAN, "Passive") - field(INPA, "$(P)MAGNET:SUPPLY:STATUS:QUENCHED CP MS") - field(INPB, "$(P)MAGNET:SUPPLY:STATUS:OVERTEMP CP MS") - field(INPC, "$(P)MAGNET:SUPPLY:STATUS:HWFAULT:CALC CP MS") - field(CALC, "(A>0) ? 1 : (B>0) ? 2 : (C>0) ? 8 : 0") - field(ZSV, "NO_ALARM") - field(OSV, "MAJOR") -} - # # Readback from m of Xmn part of Examine command return. record(mbbi, "$(P)STS:SYSTEM:FAULT") { field(DESC, "System fault status") field(DTYP, "Soft Channel") field(SCAN, "Passive") - field(INP, "$(P)STS:SYSTEM:FAULT:CALC CP MS") field(ZRST, "Normal") field(ZRVL, "0") field(ZRSV, "NO_ALARM") From af80bedd9f1e5b50759fa5aca044682e9a0360c8 Mon Sep 17 00:00:00 2001 From: Ian Gillingham Date: Tue, 1 Apr 2025 15:18:17 +0100 Subject: [PATCH 10/29] Reverted ips.db to original to continue development of SCPI option in ips_scpi.db (take 2) --- IPS/IPS-IOC-01App/Db/ips.db | 282 +----------------------------------- 1 file changed, 1 insertion(+), 281 deletions(-) diff --git a/IPS/IPS-IOC-01App/Db/ips.db b/IPS/IPS-IOC-01App/Db/ips.db index 876189a6f..a820c7c22 100644 --- a/IPS/IPS-IOC-01App/Db/ips.db +++ b/IPS/IPS-IOC-01App/Db/ips.db @@ -24,7 +24,7 @@ record(bo, "$(P)DISABLE") # # Run the Version command, V. # # The string was too long to put model and version into same record. # # Scan this once, probably not needed again. -# The reply comes back and is split amongst other records in the StreamDevice protocol file. +# The reply comes back and is split amongst other records. record(stringin, "$(P)GET:VERSION") { field(DESC, "Examine status") field(DTYP, "stream") @@ -37,7 +37,6 @@ record(stringin, "$(P)GET:VERSION") { field(SDIS, "$(P)DISABLE") } -# Updated in GET:VERSION call to getVersion() record(stringin, "$(P)MODEL") { field(DESC, "Model") field(DTYP, "Soft Channel") @@ -45,14 +44,12 @@ record(stringin, "$(P)MODEL") { field(FLNK, "$(P)VERSION") } -# Updated in GET:VERSION call to getVersion() record(stringin, "$(P)VERSION") { field(DESC, "Firmware version.") field(DTYP, "Soft Channel") field(SCAN, "Passive") } -## !! Check this for SCPI - IJG 27/3/25 # # Readback from Cn part of Examine command return. record(mbbi, "$(P)CONTROL") { field(DESC, "Control status") @@ -95,7 +92,6 @@ record(mbbi, "$(P)CONTROL") { info(alarm, "IPS") } -## !! Modify for SCPI - IJG 27/3/25 # Grab remote vs local control record(mbbo, "$(P)CONTROL:SP") { field(DESC, "Set remote/local control") @@ -145,7 +141,6 @@ record(mbbi, "$(P)ACTIVITY") { info(archive, "VAL") } -## !! Modify for SCPI - IJG 27/3/25 # Hold means maintaining present current. # Clamped means you cannot adjust it - powers up in this # state. Only the set activity hold command can get out @@ -420,7 +415,6 @@ record(ai, "$(P)MAGNET:CURR:PERSISTENT") { info(archive, "VAL") } -## ==== CURR:TRIP needs to be derived somehow. It is not in the SCPI protocol. ==== # The current at which a trip last occurred. Am not sure if by trip, they mean # a quench or a problem with the level meter. Believe the unit will take the current # and field to zero if there is a trip, so this parameter preserves what was happening @@ -458,7 +452,6 @@ record(ai, "$(P)MAGNET:FIELD:PERSISTENT") { info(archive, "VAL") } -## ==== FIELD:TRIP needs to be derived somehow. It is not in the SCPI protocol. ==== # The field at which a trip last occurred. See current for explanation. record(ai, "$(P)FIELD:TRIP") { field(DESC, "Trip field readback") @@ -561,243 +554,6 @@ record(ai, "$(P)MAGNET:INDUCTANCE") { info(archive, "VAL") } -# --------------- The following work around limitation of getting legacy status from SCPI protocol ------------- - -# Get the status DWORD from each group UID -record(mbbiDirect, "$(P)GET:MAGNET:SUPPLY:STATUS") { - field(DESC, "Examine status") - field(DTYP, "stream") - field(INP, "@OxInstIPS.protocol getMagnetSupplyStatus($(P)) $(PORT)") - field(NOBT, "32") - field(SCAN, "1 second") - - field(SIML, "$(P)SIM") - field(SIOL, "$(P)SIM:DONOTHING") - field(SDIS, "$(P)DISABLE") -} - -# Determine the switch heater mismatch status from the supply status bit -record(bi, "$(P)MAGNET:SUPPLY:STATUS:SWHTRMISMATCH") { - field(DESC, "Switch heater mismatch status") - field(DTYP, "Soft Channel") - field(SCAN, "Passive") - field(INP, "$(P)GET:MAGNET:SUPPLY:STATUS.B0 CP MS") - field(ZNAM, "No") - field(ONAM, "Yes") - field(ZSV, "NO_ALARM") - field(OSV, "MAJOR") -} - -# Determine the Over Temperature (rundown resistors) status from the supply status bit -record(bi, "$(P)MAGNET:SUPPLY:STATUS:OTRUNDOWNRES") { - field(DESC, "Over temp rundown resistors status") - field(DTYP, "Soft Channel") - field(SCAN, "Passive") - field(INP, "$(P)GET:MAGNET:SUPPLY:STATUS.B1 CP MS") - field(ZNAM, "No") - field(ONAM, "Yes") - field(ZSV, "NO_ALARM") - field(OSV, "MAJOR") -} - -# Determine the Over Temperature (sense resistor) status from the supply status bit -record(bi, "$(P)MAGNET:SUPPLY:STATUS:OTSENSERES") { - field(DESC, "Over temp sense resistor status") - field(DTYP, "Soft Channel") - field(SCAN, "Passive") - field(INP, "$(P)GET:MAGNET:SUPPLY:STATUS.B2 CP MS") - field(ZNAM, "No") - field(ONAM, "Yes") - field(ZSV, "NO_ALARM") - field(OSV, "MAJOR") -} - -# Determine the Over Temperature (PCB) status from the supply status bit -record(bi, "$(P)MAGNET:SUPPLY:STATUS:OTPCB") { - field(DESC, "Over temp PCB status") - field(DTYP, "Soft Channel") - field(SCAN, "Passive") - field(INP, "$(P)GET:MAGNET:SUPPLY:STATUS.B3 CP MS") - field(ZNAM, "No") - field(ONAM, "Yes") - field(ZSV, "NO_ALARM") - field(OSV, "MAJOR") -} - -# Determine the calibration failure status from the supply status bit -record(bi, "$(P)MAGNET:SUPPLY:STATUS:CALIBFAIL") { - field(DESC, "Calibration failure status") - field(DTYP, "Soft Channel") - field(SCAN, "Passive") - field(INP, "$(P)GET:MAGNET:SUPPLY:STATUS.B4 CP MS") - field(ZNAM, "No") - field(ONAM, "Yes") - field(ZSV, "NO_ALARM") - field(OSV, "MAJOR") -} - -# Determine the MSP430 firmware error failure status from the supply status bit -record(bi, "$(P)MAGNET:SUPPLY:STATUS:FWFAIL") { - field(DESC, "Firmware failure status") - field(DTYP, "Soft Channel") - field(SCAN, "Passive") - field(INP, "$(P)GET:MAGNET:SUPPLY:STATUS.B5 CP MS") - field(ZNAM, "No") - field(ONAM, "Yes") - field(ZSV, "NO_ALARM") - field(OSV, "MAJOR") -} - -# Determine the rundown resistors failure status from the supply status bit -record(bi, "$(P)MAGNET:SUPPLY:STATUS:RRFAIL") { - field(DESC, "Rundown resistors failure status") - field(DTYP, "Soft Channel") - field(SCAN, "Passive") - field(INP, "$(P)GET:MAGNET:SUPPLY:STATUS.B6 CP MS") - field(ZNAM, "No") - field(ONAM, "Yes") - field(ZSV, "NO_ALARM") - field(OSV, "MAJOR") -} - -# Determine the MSP430 RS-485 failure status from the supply status bit -record(bi, "$(P)MAGNET:SUPPLY:STATUS:RS485FAIL") { - field(DESC, "MSP430 RS485 failure status") - field(DTYP, "Soft Channel") - field(SCAN, "Passive") - field(INP, "$(P)GET:MAGNET:SUPPLY:STATUS.B7 CP MS") - field(ZNAM, "No") - field(ONAM, "Yes") - field(ZSV, "NO_ALARM") - field(OSV, "MAJOR") -} - -# Determine the quench status from the supply status bit -record(bi, "$(P)MAGNET:SUPPLY:STATUS:QUENCHED") { - field(DESC, "Quench status") - field(DTYP, "Soft Channel") - field(SCAN, "Passive") - field(INP, "$(P)GET:MAGNET:SUPPLY:STATUS.B8 CP MS") - field(ZNAM, "No") - field(ONAM, "Yes") - field(ZSV, "NO_ALARM") - field(OSV, "MAJOR") -} - -# Determine the catch detection status from the supply status bit -record(bi, "$(P)MAGNET:SUPPLY:STATUS:CATCH") { - field(DESC, "PSU Catch status") - field(DTYP, "Soft Channel") - field(SCAN, "Passive") - field(INP, "$(P)GET:MAGNET:SUPPLY:STATUS.B9 CP MS") - field(ZNAM, "No") - field(ONAM, "Yes") - field(ZSV, "NO_ALARM") - field(OSV, "MAJOR") -} - -# Determine the Sense amplifier over temperature status from the supply status bit -record(bi, "$(P)MAGNET:SUPPLY:STATUS:OTSENSEAMP") { - field(DESC, "Over temp sense amp") - field(DTYP, "Soft Channel") - field(SCAN, "Passive") - field(INP, "$(P)GET:MAGNET:SUPPLY:STATUS.BC CP MS") - field(ZNAM, "No") - field(ONAM, "Yes") - field(ZSV, "NO_ALARM") - field(OSV, "MAJOR") -} - -# Determine amplifier 1 over temperature status from the supply status bit -record(bi, "$(P)MAGNET:SUPPLY:STATUS:OTAMP1") { - field(DESC, "Over temp amp 1") - field(DTYP, "Soft Channel") - field(SCAN, "Passive") - field(INP, "$(P)GET:MAGNET:SUPPLY:STATUS.BD CP MS") - field(ZNAM, "No") - field(ONAM, "Yes") - field(ZSV, "NO_ALARM") - field(OSV, "MAJOR") -} - -# Determine amplifier 2 over temperature status from the supply status bit -record(bi, "$(P)MAGNET:SUPPLY:STATUS:OTAMP2") { - field(DESC, "Over temp amp 2") - field(DTYP, "Soft Channel") - field(SCAN, "Passive") - field(INP, "$(P)GET:MAGNET:SUPPLY:STATUS.BE CP MS") - field(ZNAM, "No") - field(ONAM, "Yes") - field(ZSV, "NO_ALARM") - field(OSV, "MAJOR") -} - -# Determine PWM Cutoff status from the supply status bit -record(bi, "$(P)MAGNET:SUPPLY:STATUS:PWMCUTOFF") { - field(DESC, "PWM Cutoff status") - field(DTYP, "Soft Channel") - field(SCAN, "Passive") - field(INP, "$(P)GET:MAGNET:SUPPLY:STATUS.BF CP MS") - field(ZNAM, "No") - field(ONAM, "Yes") - field(ZSV, "NO_ALARM") - field(OSV, "MAJOR") -} - -# Determine Voltage ADC error status from the supply status bit -record(bi, "$(P)MAGNET:SUPPLY:STATUS:VADCERROR") { - field(DESC, "Voltage ADC error status") - field(DTYP, "Soft Channel") - field(SCAN, "Passive") - field(INP, "$(P)GET:MAGNET:SUPPLY:STATUS.B10 CP MS") - field(ZNAM, "No") - field(ONAM, "Yes") - field(ZSV, "NO_ALARM") - field(OSV, "MAJOR") -} - -# Determine Current ADC error status from the supply status bit -record(bi, "$(P)MAGNET:SUPPLY:STATUS:IADCERROR") { - field(DESC, "Current ADC error status") - field(DTYP, "Soft Channel") - field(SCAN, "Passive") - field(INP, "$(P)GET:MAGNET:SUPPLY:STATUS.B11 CP MS") - field(ZNAM, "No") - field(ONAM, "Yes") - field(ZSV, "NO_ALARM") - field(OSV, "MAJOR") -} - -# The over temperature status should be an or'd output from the numerous temperature alarms -record(calc, "$(P)MAGNET:SUPPLY:STATUS:OVERTEMP:CALC") { - field(DESC, "Temperature status calc (combined)") - field(DTYP, "Soft Channel") - field(SCAN, "Passive") - field(INPA, "$(P)GET:MAGNET:SUPPLY:OTRUNDOWNRES CP MS") - field(INPB, "$(P)GET:MAGNET:SUPPLY:OTSENSERES CP MS") - field(INPC, "$(P)GET:MAGNET:SUPPLY:OTPCB CP MS") - field(INPD, "$(P)GET:MAGNET:SUPPLY:OTSENSEAMP CP MS") - field(INPE, "$(P)GET:MAGNET:SUPPLY:OTAMP1 CP MS") - field(INPF, "$(P)GET:MAGNET:SUPPLY:OTAMP2 CP MS") - field(CALC, "A|B|C|D|E|F") - field(ZSV, "NO_ALARM") - field(OSV, "MAJOR") -} - -# Determine the Over Temperature status from the or'd calc record (OVERTEMP:CALC) -record(bi, "$(P)MAGNET:SUPPLY:STATUS:OVERTEMP") { - field(DESC, "Temperature status (combined)") - field(DTYP, "Soft Channel") - field(SCAN, "Passive") - field(INP, "$(P)GET:MAGNET:SUPPLY:STATUS:OVERTEMP:CALC CP MS") - field(ZNAM, "No") - field(ONAM, "Yes") - field(ZSV, "NO_ALARM") - field(OSV, "MAJOR") -} - -# -------------------------------------------------------------------------------------------------------------- - # # Run the Examine Status command, X. # The reply comes back and is split amongst other records. record(stringin, "$(P)GET:STATUS") { @@ -811,47 +567,11 @@ record(stringin, "$(P)GET:STATUS") { field(SDIS, "$(P)DISABLE") } -## Derive the SYSTEM:HWFAULT status from the status bits -## This collates the various possible hardware faults into a single record, -## which in the legacy protocol is a single value (Xm bit 4). -record(calc, "$(P)STS:SYSTEM:HWFAULT:CALC") { - field(DESC, "System hardware fault status calc") - field(DTYP, "Soft Channel") - field(SCAN, "Passive") - field(INPA, "$(P)MAGNET:SUPPLY:STATUS:SWHTRMISMATCH CP MS") - field(INPB, "$(P)MAGNET:SUPPLY:STATUS:CALIBFAIL CP MS") - field(INPC, "$(P)MAGNET:SUPPLY:STATUS:FWFAIL CP MS") - field(INPD, "$(P)MAGNET:SUPPLY:STATUS:RRFAIL CP MS") - field(INPE, "$(P)MAGNET:SUPPLY:STATUS:RS485FAIL CP MS") - field(INPF, "$(P)MAGNET:SUPPLY:STATUS:CATCH CP MS") - field(INPG, "$(P)MAGNET:SUPPLY:STATUS:PWMCUTOFF CP MS") - field(INPH, "$(P)MAGNET:SUPPLY:STATUS:VADCERROR CP MS") - field(INPI, "$(P)MAGNET:SUPPLY:STATUS:IADCERROR CP MS") - field(CALC, "(A>0||B>0||C>0||D>0||E>0||F>0||G>0||H>0||I>0) ? 1 : 0") - field(ZSV, "NO_ALARM") - field(OSV, "MAJOR") -} - -## Derive the SYSTEM:FAULT status from the status bits -## This collates the various possible faults into a single record, in alignment with the legacy protocol. -record(calc, "$(P)STS:SYSTEM:FAULT:CALC") { - field(DESC, "System fault status calc") - field(DTYP, "Soft Channel") - field(SCAN, "Passive") - field(INPA, "$(P)MAGNET:SUPPLY:STATUS:QUENCHED CP MS") - field(INPB, "$(P)MAGNET:SUPPLY:STATUS:OVERTEMP CP MS") - field(INPC, "$(P)MAGNET:SUPPLY:STATUS:HWFAULT:CALC CP MS") - field(CALC, "(A>0) ? 1 : (B>0) ? 2 : (C>0) ? 8 : 0") - field(ZSV, "NO_ALARM") - field(OSV, "MAJOR") -} - # # Readback from m of Xmn part of Examine command return. record(mbbi, "$(P)STS:SYSTEM:FAULT") { field(DESC, "System fault status") field(DTYP, "Soft Channel") field(SCAN, "Passive") - field(INP, "$(P)STS:SYSTEM:FAULT:CALC CP MS") field(ZRST, "Normal") field(ZRVL, "0") field(ZRSV, "NO_ALARM") From 303555e81e8bbb2bdf30d684c82bbe62a028ebe5 Mon Sep 17 00:00:00 2001 From: Ian Gillingham Date: Thu, 5 Jun 2025 15:08:33 +0100 Subject: [PATCH 11/29] Created the ips scpi test framework and further work on the db --- IPS/IPS-IOC-01App/Db/Makefile | 1 + IPS/IPS-IOC-01App/Db/ips.db | 11 + IPS/IPS-IOC-01App/Db/ips_scpi.db | 451 +++++++++++++------------------ IPS/iocBoot/iocIPS-IOC-01/st.cmd | 22 +- 4 files changed, 215 insertions(+), 270 deletions(-) diff --git a/IPS/IPS-IOC-01App/Db/Makefile b/IPS/IPS-IOC-01App/Db/Makefile index 5e0e290b2..812f763a9 100644 --- a/IPS/IPS-IOC-01App/Db/Makefile +++ b/IPS/IPS-IOC-01App/Db/Makefile @@ -11,6 +11,7 @@ include $(TOP)/configure/CONFIG # Create and install (or just install) into /db # databases, templates, substitutions like this DB += ips.db +DB += ips_scpi.db #---------------------------------------------------- # If .db template is not named *.template add diff --git a/IPS/IPS-IOC-01App/Db/ips.db b/IPS/IPS-IOC-01App/Db/ips.db index a820c7c22..16876e8be 100644 --- a/IPS/IPS-IOC-01App/Db/ips.db +++ b/IPS/IPS-IOC-01App/Db/ips.db @@ -1,3 +1,14 @@ +# Set the PROTOCOL PV to LEGACY +# This facilitates the UI to show/hide protocol specific settings +record (stringin, "$(P)PROTOCOL") +{ + field(DESC, "Inform the UI which protocol to use") + field(DTYP, "Soft Channel") + field(SCAN, "Passive") + field(VAL, "LEGACY") + field(PINI, "YES") +} + record(bo, "$(P)SIM") { field(SCAN, "Passive") diff --git a/IPS/IPS-IOC-01App/Db/ips_scpi.db b/IPS/IPS-IOC-01App/Db/ips_scpi.db index 011bf92cb..5ee7162d6 100644 --- a/IPS/IPS-IOC-01App/Db/ips_scpi.db +++ b/IPS/IPS-IOC-01App/Db/ips_scpi.db @@ -1,3 +1,14 @@ +# Set the PROTOCOL PV to SCPI +# This facilitates the UI to show/hide protocol specific settings +record (stringin, "$(P)PROTOCOL") +{ + field(DESC, "Inform the UI which protocol to use") + field(DTYP, "Soft Channel") + field(SCAN, "Passive") + field(VAL, "SCPI") + field(PINI, "YES") +} + record(bo, "$(P)SIM") { field(SCAN, "Passive") @@ -28,7 +39,7 @@ record(bo, "$(P)DISABLE") record(stringin, "$(P)GET:VERSION") { field(DESC, "Examine status") field(DTYP, "stream") - field(INP, "@OxInstIPS.protocol getVersion($(P)) $(PORT)") + field(INP, "@OxInstIPS_SCPI.protocol getVersion($(P)) $(PORT)") field(PINI, "YES") field(FLNK, "$(P)MODEL") field(SCAN, "Passive") @@ -52,79 +63,21 @@ record(stringin, "$(P)VERSION") { field(SCAN, "Passive") } -## !! Check this for SCPI - IJG 27/3/25 -# # Readback from Cn part of Examine command return. -record(mbbi, "$(P)CONTROL") { - field(DESC, "Control status") - field(DTYP, "Soft Channel") - field(SCAN, "1 second") - field(ZRST, "Local & Locked") - field(ZRVL, "0") - field(ZRSV, "NO_ALARM") - field(ONST, "Remote & Locked") - field(ONVL, "1") - field(ONSV, "NO_ALARM") - field(TWST, "Local & Unlocked") - field(TWVL, "2") - field(TWSV, "NO_ALARM") - field(THST, "Remote & Unlocked") - field(THVL, "3") - field(THSV, "NO_ALARM") - - # Modes 4-7 come back from device. Manual does not make it clear what the - # differences are. Keeping them as separate items in case they are useful - # for diagnostics later on. - field(FRST, "Auto-Run-Down") - field(FRVL, "4") - field(FRSV, "MAJOR") - field(FVST, "Auto-Run-Down") - field(FVVL, "5") - field(FVSV, "MAJOR") - field(SXST, "Auto-Run-Down") - field(SXVL, "6") - field(SXSV, "MAJOR") - field(SVST, "Auto-Run-Down") - field(SVVL, "7") - field(SVSV, "MAJOR") - - field(SIML, "$(P)SIM") - field(SIOL, "$(P)SIM:CONTROL") - field(SDIS, "$(P)DISABLE") - - info(archive, "VAL") - info(alarm, "IPS") -} - -## !! Modify for SCPI - IJG 27/3/25 -# Grab remote vs local control -record(mbbo, "$(P)CONTROL:SP") { - field(DESC, "Set remote/local control") - field(DTYP, "stream") - field(SCAN, "Passive") - field(OUT, "@OxInstIPS.protocol setControl $(PORT)") - field(ZRST, "Local & Locked") - field(ZRVL, "0") - field(ONST, "Remote & Locked") - field(ONVL, "1") - field(TWST, "Local & Unlocked") - field(TWVL, "2") - field(THST, "Remote & Unlocked") - field(THVL, "3") - - field(SIML, "$(P)SIM") - field(SIOL, "$(P)SIM:CONTROL:SP") - field(SDIS, "$(P)DISABLE") -} +# CONTROL and CONTROL:SP records have been removed from the SCPI variant database +# as the SCPI command set does not manage the panel lock in the same was as legacy and +# Magnet Group advised to remove this feature, as they always want to be able to control +# the IPS via the front panel. IJG 13/05/2025 -# Readback from An part of Examine command return. +# Readback from STAT:DEV:GRPZ:PSU:ACTN command return (in getActivity()). # Hold means maintaining present current. # Clamped means you cannot adjust it - powers up in this # state. Only the set activity hold command can get out # of the clamped state. Hold will interrupt a sweep. record(mbbi, "$(P)ACTIVITY") { field(DESC, "Activity status") - field(DTYP, "Soft Channel") + field(DTYP, "stream") field(SCAN, "1 second") + field(INP, "@OxInstIPS_SCPI.protocol getActivity($(P)) $(PORT)") field(ZRST, "Hold") field(ZRVL, "0") field(ZRSV, "NO_ALARM") @@ -154,7 +107,7 @@ record(mbbo, "$(P)ACTIVITY:SP") { field(DESC, "Activity control") field(DTYP, "stream") field(SCAN, "Passive") - field(OUT, "@OxInstIPS.protocol setActivity $(PORT)") + field(OUT, "@OxInstIPS_SCPI.protocol setActivity $(PORT)") field(ZRST, "Hold") field(ZRVL, "0") field(ONST, "To Setpoint") @@ -174,7 +127,7 @@ record(ai, "$(P)CURR") { field(DESC, "Demand current readback") field(DTYP, "stream") field(SCAN, "1 second") - field(INP, "@OxInstIPS.protocol getDemandCurrent $(PORT)") + field(INP, "@OxInstIPS_SCPI.protocol getDemandCurrent $(PORT)") field(EGU, "A") field(PREC, "4") @@ -190,7 +143,7 @@ record(ai, "$(P)CURR:SP:RBV") { field(DESC, "Setpoint current readback") field(DTYP, "stream") field(SCAN, "1 second") - field(INP, "@OxInstIPS.protocol getSetpointCurrent $(PORT)") + field(INP, "@OxInstIPS_SCPI.protocol getSetpointCurrent $(PORT)") field(EGU, "A") field(PREC, "4") @@ -206,7 +159,7 @@ record(ai, "$(P)SUPPLY:VOLT") { field(DESC, "Supply voltage readback") field(DTYP, "stream") field(SCAN, "1 second") - field(INP, "@OxInstIPS.protocol getSupplyVoltage $(PORT)") + field(INP, "@OxInstIPS_SCPI.protocol getSupplyVoltage $(PORT)") field(EGU, "V") field(PREC, "8") @@ -261,7 +214,7 @@ record(ai, "$(P)MAGNET:CURR:MEAS") { field(DESC, "Measured magnet current readback") field(DTYP, "stream") field(SCAN, "1 second") - field(INP, "@OxInstIPS.protocol getMeasuredMagnetCurrent $(PORT)") + field(INP, "@OxInstIPS_SCPI.protocol getMeasuredMagnetCurrent $(PORT)") field(EGU, "A") field(PREC, "4") @@ -277,7 +230,7 @@ record(ai, "$(P)CURR:RATE") { field(DESC, "Current sweep rate readback") field(DTYP, "stream") field(SCAN, "1 second") - field(INP, "@OxInstIPS.protocol getCurrentSweepRate $(PORT)") + field(INP, "@OxInstIPS_SCPI.protocol getCurrentSweepRate $(PORT)") field(EGU, "A/min") field(PREC, "3") @@ -293,7 +246,7 @@ record(ai, "$(P)FIELD") { field(DESC, "Demand field readback") field(DTYP, "stream") field(SCAN, "1 second") - field(INP, "@OxInstIPS.protocol getDemandField $(PORT)") + field(INP, "@OxInstIPS_SCPI.protocol getDemandField $(PORT)") field(EGU, "T") field(PREC, "5") @@ -324,7 +277,7 @@ record(ao, "$(P)FIELD:SP:_RAW") { field(DESC, "Send raw field to box") field(DTYP, "stream") field(SCAN, "Passive") - field(OUT, "@OxInstIPS.protocol setSetpointField $(PORT)") + field(OUT, "@OxInstIPS_SCPI.protocol setSetpointField $(PORT)") field(EGU, "T") field(PREC, "5") field(DRVH, "$(MAX_FIELD)") @@ -342,7 +295,7 @@ record(ai, "$(P)FIELD:SP:RBV") { field(DESC, "Setpoint field readback") field(DTYP, "stream") field(SCAN, "1 second") - field(INP, "@OxInstIPS.protocol getSetpointField $(PORT)") + field(INP, "@OxInstIPS_SCPI.protocol getSetpointField $(PORT)") field(EGU, "T") field(PREC, "5") @@ -357,7 +310,7 @@ record(ai, "$(P)FIELD:RATE") { field(DESC, "Field sweep rate readback") field(DTYP, "stream") field(SCAN, "1 second") - field(INP, "@OxInstIPS.protocol getFieldSweepRate $(PORT)") + field(INP, "@OxInstIPS_SCPI.protocol getFieldSweepRate $(PORT)") field(EGU, "T/min") field(PREC, "4") @@ -375,7 +328,7 @@ record(ao, "$(P)FIELD:RATE:SP") { field(DESC, "Set field sweep rate") field(DTYP, "stream") field(SCAN, "Passive") - field(OUT, "@OxInstIPS.protocol setFieldSweepRate $(PORT)") + field(OUT, "@OxInstIPS_SCPI.protocol setFieldSweepRate $(PORT)") field(EGU, "T/min") field(PREC, "4") field(DRVH, "$(MAX_SWEEP_RATE)") @@ -393,7 +346,7 @@ record(ai, "$(P)VOLT:LIMIT:SOFTWARE") { field(DESC, "Software voltage limit readback") field(DTYP, "stream") field(SCAN, "1 second") - field(INP, "@OxInstIPS.protocol getSoftwareVoltageLimit $(PORT)") + field(INP, "@OxInstIPS_SCPI.protocol getSoftwareVoltageLimit $(PORT)") field(EGU, "V") field(PREC, "8") @@ -409,7 +362,7 @@ record(ai, "$(P)MAGNET:CURR:PERSISTENT") { field(DESC, "Persistent magnet current readback") field(DTYP, "stream") field(SCAN, "1 second") - field(INP, "@OxInstIPS.protocol getPersistentMagnetCurrent $(PORT)") + field(INP, "@OxInstIPS_SCPI.protocol getPersistentMagnetCurrent $(PORT)") field(EGU, "A") field(PREC, "4") @@ -429,7 +382,7 @@ record(ai, "$(P)CURR:TRIP") { field(DESC, "Trip current readback") field(DTYP, "stream") field(SCAN, "1 second") - field(INP, "@OxInstIPS.protocol getTripCurrent $(PORT)") + # field(INP, "@OxInstIPS_SCPI.protocol getTripCurrent $(PORT)") field(EGU, "A") field(PREC, "4") @@ -445,7 +398,7 @@ record(ai, "$(P)MAGNET:FIELD:PERSISTENT") { field(DESC, "Persistent magnet field readback") field(DTYP, "stream") field(SCAN, "1 second") - field(INP, "@OxInstIPS.protocol getPersistentMagnetField $(PORT)") + field(INP, "@OxInstIPS_SCPI.protocol getPersistentMagnetField $(PORT)") field(EGU, "T") field(PREC, "5") @@ -464,7 +417,7 @@ record(ai, "$(P)FIELD:TRIP") { field(DESC, "Trip field readback") field(DTYP, "stream") field(SCAN, "1 second") - field(INP, "@OxInstIPS.protocol getTripField $(PORT)") + # field(INP, "@OxInstIPS_SCPI.protocol getTripField $(PORT)") field(EGU, "T") field(PREC, "5") @@ -481,7 +434,7 @@ record(ai, "$(P)HEATER:CURR") { field(DESC, "Heater current readback") field(DTYP, "stream") field(SCAN, "1 second") - field(INP, "@OxInstIPS.protocol getHeaterCurrent $(PORT)") + field(INP, "@OxInstIPS_SCPI.protocol getHeaterCurrent $(PORT)") field(EGU, "mA") field(PREC, "4") @@ -498,7 +451,7 @@ record(ai, "$(P)CURR:LIMIT:NEG") { field(DESC, "Neg current limit readback") field(DTYP, "stream") field(SCAN, "1 second") - field(INP, "@OxInstIPS.protocol getNegCurrentLimit $(PORT)") + field(INP, "@OxInstIPS_SCPI.protocol getNegCurrentLimit $(PORT)") field(EGU, "A") field(PREC, "4") @@ -515,7 +468,7 @@ record(ai, "$(P)CURR:LIMIT:POS") { field(DESC, "Pos current limit readback") field(DTYP, "stream") field(SCAN, "1 second") - field(INP, "@OxInstIPS.protocol getPosCurrentLimit $(PORT)") + field(INP, "@OxInstIPS_SCPI.protocol getPosCurrentLimit $(PORT)") field(EGU, "A") field(PREC, "4") @@ -533,7 +486,7 @@ record(ai, "$(P)RESISTANCE:LEAD") { field(DESC, "Leadresistance readback") field(DTYP, "stream") field(SCAN, "1 second") - field(INP, "@OxInstIPS.protocol getLeadResistance $(PORT)") + field(INP, "@OxInstIPS_SCPI.protocol getLeadResistance $(PORT)") field(EGU, "mohm") field(PREC, "5") @@ -550,7 +503,7 @@ record(ai, "$(P)MAGNET:INDUCTANCE") { field(DESC, "Magnet inductance readback") field(DTYP, "stream") field(SCAN, "1 second") - field(INP, "@OxInstIPS.protocol getMagnetInductance $(PORT)") + field(INP, "@OxInstIPS_SCPI.protocol getMagnetInductance $(PORT)") field(EGU, "H") field(PREC, "5") @@ -567,7 +520,7 @@ record(ai, "$(P)MAGNET:INDUCTANCE") { record(mbbiDirect, "$(P)GET:MAGNET:SUPPLY:STATUS") { field(DESC, "Examine status") field(DTYP, "stream") - field(INP, "@OxInstIPS.protocol getMagnetSupplyStatus($(P)) $(PORT)") + field(INP, "@OxInstIPS_SCPI.protocol getMagnetSupplyStatus($(P)) $(PORT)") field(NOBT, "32") field(SCAN, "1 second") @@ -771,17 +724,14 @@ record(bi, "$(P)MAGNET:SUPPLY:STATUS:IADCERROR") { # The over temperature status should be an or'd output from the numerous temperature alarms record(calc, "$(P)MAGNET:SUPPLY:STATUS:OVERTEMP:CALC") { field(DESC, "Temperature status calc (combined)") - field(DTYP, "Soft Channel") field(SCAN, "Passive") - field(INPA, "$(P)GET:MAGNET:SUPPLY:OTRUNDOWNRES CP MS") - field(INPB, "$(P)GET:MAGNET:SUPPLY:OTSENSERES CP MS") - field(INPC, "$(P)GET:MAGNET:SUPPLY:OTPCB CP MS") - field(INPD, "$(P)GET:MAGNET:SUPPLY:OTSENSEAMP CP MS") - field(INPE, "$(P)GET:MAGNET:SUPPLY:OTAMP1 CP MS") - field(INPF, "$(P)GET:MAGNET:SUPPLY:OTAMP2 CP MS") + field(INPA, "$(P)MAGNET:SUPPLY:STATUS:OTRUNDOWNRES CP MS") + field(INPB, "$(P)MAGNET:SUPPLY:STATUS:OTSENSERES CP MS") + field(INPC, "$(P)MAGNET:SUPPLY:STATUS:OTPCB CP MS") + field(INPD, "$(P)MAGNET:SUPPLY:STATUS:OTSENSEAMP CP MS") + field(INPE, "$(P)MAGNET:SUPPLY:STATUS:OTAMP1 CP MS") + field(INPF, "$(P)MAGNET:SUPPLY:STATUS:OTAMP2 CP MS") field(CALC, "A|B|C|D|E|F") - field(ZSV, "NO_ALARM") - field(OSV, "MAJOR") } # Determine the Over Temperature status from the or'd calc record (OVERTEMP:CALC) @@ -789,7 +739,7 @@ record(bi, "$(P)MAGNET:SUPPLY:STATUS:OVERTEMP") { field(DESC, "Temperature status (combined)") field(DTYP, "Soft Channel") field(SCAN, "Passive") - field(INP, "$(P)GET:MAGNET:SUPPLY:STATUS:OVERTEMP:CALC CP MS") + field(INP, "$(P)MAGNET:SUPPLY:STATUS:OVERTEMP:CALC CP MS") field(ZNAM, "No") field(ONAM, "Yes") field(ZSV, "NO_ALARM") @@ -803,7 +753,6 @@ record(bi, "$(P)MAGNET:SUPPLY:STATUS:OVERTEMP") { ## which in the legacy protocol is a single value (Xm bit 4). record(calc, "$(P)STS:SYSTEM:HWFAULT:CALC") { field(DESC, "System hardware fault status calc") - field(DTYP, "Soft Channel") field(SCAN, "Passive") field(INPA, "$(P)MAGNET:SUPPLY:STATUS:SWHTRMISMATCH CP MS") field(INPB, "$(P)MAGNET:SUPPLY:STATUS:CALIBFAIL CP MS") @@ -815,22 +764,17 @@ record(calc, "$(P)STS:SYSTEM:HWFAULT:CALC") { field(INPH, "$(P)MAGNET:SUPPLY:STATUS:VADCERROR CP MS") field(INPI, "$(P)MAGNET:SUPPLY:STATUS:IADCERROR CP MS") field(CALC, "(A>0||B>0||C>0||D>0||E>0||F>0||G>0||H>0||I>0) ? 1 : 0") - field(ZSV, "NO_ALARM") - field(OSV, "MAJOR") } ## Derive the SYSTEM:FAULT status from the status bits ## This collates the various possible faults into a single record, in alignment with the legacy protocol. record(calc, "$(P)STS:SYSTEM:FAULT:CALC") { field(DESC, "System fault status calc") - field(DTYP, "Soft Channel") field(SCAN, "Passive") field(INPA, "$(P)MAGNET:SUPPLY:STATUS:QUENCHED CP MS") field(INPB, "$(P)MAGNET:SUPPLY:STATUS:OVERTEMP CP MS") - field(INPC, "$(P)MAGNET:SUPPLY:STATUS:HWFAULT:CALC CP MS") + field(INPC, "$(P)STS:SYSTEM:HWFAULT:CALC CP MS") field(CALC, "(A>0) ? 1 : (B>0) ? 2 : (C>0) ? 8 : 0") - field(ZSV, "NO_ALARM") - field(OSV, "MAJOR") } # # Readback from m of Xmn part of Examine command return. @@ -886,9 +830,9 @@ record(mbbi, "$(P)STS:SYSTEM:LIMIT") { # OFF -> switch closed, ON -> switch open. record(mbbi, "$(P)HEATER:STATUS") { field(DESC, "Heater status") - field(DTYP, "Soft Channel") + field(DTYP, "stream") field(SCAN, "1 second") - field(INP, "@OxInstIPS.protocol getHeaterStatus $(PORT)") + field(INP, "@OxInstIPS_SCPI.protocol getHeaterStatus $(PORT)") field(ZRST, "Off") field(ZRVL, "0") field(ONST, "On") @@ -905,7 +849,7 @@ record(bo, "$(P)HEATER:STATUS:SP") { field(DESC, "Set Remote/Local Control") field(DTYP, "stream") field(SCAN, "Passive") - field(OUT, "@OxInstIPS.protocol setHeaterStatus $(PORT)") + field(OUT, "@OxInstIPS_SCPI.protocol setHeaterStatus $(PORT)") field(ZNAM, "Off") field(ONAM, "On") @@ -964,7 +908,8 @@ record(compress, "$(P)HEATER:_STATUS_BUFFER_LOWEST") { info(archive, "VAL") } -# BO record to indicate whether or not heater been on for at least $(HEATER_WAITTIME). Monitored by statemachine to determine whether or not OK to set field. +# BO record to indicate whether or not heater been on for at least $(HEATER_WAITTIME). +# Monitored by statemachine to determine whether or not OK to set field. record(bo, "$(P)HEATER:ONTIME_OK") { field(DESC, "Heater on for at least $(HEATER_WAITTIME)s") @@ -978,102 +923,18 @@ record(bo, "$(P)HEATER:ONTIME_OK") { } -# Readback from m of Mmn part of Examine command return. -# The Display is in Amps or Tesla. The Magnet Sweep is fast or slow. -record(mbbi, "$(P)SWEEPMODE:PARAMS") { - field(DESC, "Mode status") - field(DTYP, "Soft Channel") - field(SCAN, "Passive") - field(ZRST, "Amps Fast") - field(ZRVL, "0") - field(ONST, "Tesla Fast") - field(ONVL, "1") - field(TWST, "Amps Fast") - field(TWVL, "2") - field(THST, "Tesla Fast") - field(THVL, "3") - field(FRST, "Amps Slow") - field(FRVL, "4") - field(FVST, "Tesla Slow") - field(FVVL, "5") - field(SXST, "Amps Slow") - field(SXVL, "6") - field(SVST, "Tesla Slow") - field(SVVL, "7") - field(EIST, "Amps Unaffected") - field(EIVL, "8") - field(NIST, "Tesla Unaffected") - field(NIVL, "9") - - field(VAL, "3") - field(PINI, "YES") - - field(SIML, "$(P)SIM") - field(SIOL, "$(P)SIM:SWEEPMODE:PARAMS") - field(SDIS, "$(P)DISABLE") - - info(archive, "VAL") -} - -# To set the sweep and display mode - its a bit confusing as there -# are duplicates, but we do not present this choice to the user. -# -record(mbbo, "$(P)SWEEPMODE:PARAMS:SP") { - field(DESC, "Set sweep and display mode.") - field(DTYP, "stream") - field(SCAN, "Passive") - field(ZRST, "Amps Fast") - field(ZRVL, "0") - field(ONST, "Tesla Fast") - field(ONVL, "1") - field(TWST, "Amps Fast") - field(TWVL, "2") - field(THST, "Tesla Fast") - field(THVL, "3") - field(FRST, "Amps Slow") - field(FRVL, "4") - field(FVST, "Tesla Slow") - field(FVVL, "5") - field(SXST, "Amps Slow") - field(SXVL, "6") - field(SVST, "Tesla Slow") - field(SVVL, "7") - field(EIST, "Amps Unaffected") - field(EIVL, "8") - field(NIST, "Tesla Unaffected") - field(NIVL, "9") - field(OUT, "@OxInstIPS.protocol setMode $(PORT)") - - field(VAL, "3") - field(PINI, "YES") - - field(SIML, "$(P)SIM") - field(SIOL, "$(P)SIM:SWEEPMODE:PARAMS:SP") - field(SDIS, "$(P)DISABLE") -} - +# SWEEPMODE:PARAMS and SWEEPMODE:SWEEP +# These have been removed as they are meaningless in SCPI protocol. +# Documentation from the old legacy db. # Readback from n of Mmn part of Examine command return. # (Ignore the Pmn part of the Examine command return - no records for this.) # 0 output constant, 1, 2, 3 output changing -record(mbbi, "$(P)STS:SWEEPMODE:SWEEP") { - field(DESC, "Mode status") - field(DTYP, "Soft Channel") - field(SCAN, "Passive") - field(ZRST, "At rest") - field(ZRVL, "0") - field(ONST, "Sweeping") - field(ONVL, "1") - field(TWST, "Sweep Limiting") - field(TWVL, "2") - field(THST, "Swping & Lmting") - field(THVL, "3") - - field(SIML, "$(P)SIM") - field(SIOL, "$(P)SIM:STS:SWEEPMODE:SWEEP") - field(SDIS, "$(P)DISABLE") - - info(archive, "VAL") -} +# +# According to the documented legacy command, the m part of the Mmn X command response +# is either 0 or 1, so for the life of me I can't see how this mbbi could +# assume any value above 1. This record does not appear to be referenced anywhere, including in the OPI. +# So will keep as was but PINI to zero. +# IJG - April 2025 # To capture bits of mismatching status protocol. # We do not do much with it at the moment. @@ -1083,42 +944,7 @@ record(stringin, "$(P)DBG:STS:MISMATCH") { field(SCAN, "Passive") } -# Diddle with the comms and reported resolution. -# This is the nasty Q command which does not reply and whose -# info does not get reported by the status command. -# This may be needed after power cycle of IPS or if it has -# been connected to the Oxford Instruments Windows Application -# to allow EPICS to talk to it and to allow the resolution to be extended. -# Are not supporting setting these things individually, just setting -# what we want. -record(ao, "$(P)SET:COMMSRES") { - field(DESC, "Set ext. resn, no LF") - field(DTYP, "stream") - field(SCAN, "Passive") - field(VAL, "6") - field(PINI, "YES") - field(OUT, "@OxInstIPS.protocol setCommsResExtended $(PORT)") - - field(SIML, "$(P)SIM") - field(SIOL, "$(P)SIM:DONOTHING") - field(SDIS, "$(P)DISABLE") -} - -# Diddle with the comms wait interval. -# Probably will not need this, but put it here in case we do. Will not put access to this -# on the GUI. -record(ao, "$(P)SET:WAITINTERVAL") { - field(DESC, "Set wait interval") - field(DTYP, "stream") - field(SCAN, "Passive") - field(EGU, "ms") - field(OUT, "@OxInstIPS.protocol setWaitInterval $(PORT)") - - field(SIML, "$(P)SIM") - field(SIOL, "$(P)SIM:DONOTHING") - field(SDIS, "$(P)DISABLE") -} - +# PERSISTENT pv is the magnet persistent mode in the cryomagnet statemachine. record(bo, "$(P)PERSISTENT") { field(DESC, "Set magnet to persistent") field(ZNAM, "NO") @@ -1188,30 +1014,6 @@ alias("$(P)FIELD:SP", "$(P)FIELD:USER:SP") # "User" setpoint is same as "normal record(ao, "$(P)SIM:DONOTHING") {} -record(mbbo, "$(P)SIM:SWEEPMODE:PARAMS") { - field(ZRST, "Amps Fast") - field(ZRVL, "0") - field(ONST, "Tesla Fast") - field(ONVL, "1") - field(TWST, "Amps Fast") - field(TWVL, "2") - field(THST, "Tesla Fast") - field(THVL, "3") - field(FRST, "Amps Slow") - field(FRVL, "4") - field(FVST, "Tesla Slow") - field(FVVL, "5") - field(SXST, "Amps Slow") - field(SXVL, "6") - field(SVST, "Tesla Slow") - field(SVVL, "7") - field(EIST, "Amps Unaffected") - field(EIVL, "8") - field(NIST, "Tesla Unaffected") - field(NIVL, "9") -} - -alias("$(P)SIM:SWEEPMODE:PARAMS", "$(P)SIM:SPEEPMODE:PARAMS:SP") record(bo, "$(P)SIM:HEATER:STATUS") { field(ZNAM, "Off") @@ -1248,15 +1050,128 @@ record(mbbo, "$(P)SIM:ACTIVITY") { alias("$(P)SIM:ACTIVITY", "$(P)SIM:ACTIVITY:SP") -record(mbbo, "$(P)SIM:CONTROL") { - field(ZRST, "Local & Locked") +# SWEEPMODE:PARAMS and SWEEPMODE:SWEEP +# These are meaningless in SCPI protocol. +# Documentation from the old legacy db. +# Readback from n of Mmn part of Examine command return. +# (Ignore the Pmn part of the Examine command return - no records for this.) +# 0 output constant, 1, 2, 3 output changing +# +# According to the documented legacy command, the m part of the Mmn X command response +# is either 0 or 1, so for the life of me I can't see how this mbbi could +# assume any value above 1. This record does not appear to be referenced anywhere, including in the OPI. +# So will keep as was but PINI to zero. +# IJG - April 2025 +# Update May 2025: This record is used in the SNL state machine and is presently required just to +# make the state machine work. So these records have been re-appended to this db file, until such time that +# a better solution is found. + +# Readback from m of Mmn part of Examine command return. +# The Display is in Amps or Tesla. The Magnet Sweep is fast or slow. +record(mbbi, "$(P)SWEEPMODE:PARAMS") { + field(DESC, "Mode status") + field(DTYP, "Soft Channel") + field(SCAN, "Passive") + field(ZRST, "Amps Fast") + field(ZRVL, "0") + field(ONST, "Tesla Fast") + field(ONVL, "1") + field(TWST, "Amps Fast") + field(TWVL, "2") + field(THST, "Tesla Fast") + field(THVL, "3") + field(FRST, "Amps Slow") + field(FRVL, "4") + field(FVST, "Tesla Slow") + field(FVVL, "5") + field(SXST, "Amps Slow") + field(SXVL, "6") + field(SVST, "Tesla Slow") + field(SVVL, "7") + field(EIST, "Amps Unaffected") + field(EIVL, "8") + field(NIST, "Tesla Unaffected") + field(NIVL, "9") + + field(VAL, "3") + field(PINI, "YES") + + field(SIML, "$(P)SIM") + field(SIOL, "$(P)SIM:SWEEPMODE:PARAMS") + field(SDIS, "$(P)DISABLE") + + info(archive, "VAL") +} + +# To set the sweep and display mode - its a bit confusing as there +# are duplicates, but we do not present this choice to the user. +# +record(mbbo, "$(P)SWEEPMODE:PARAMS:SP") { + field(DESC, "Set sweep and display mode.") + field(DTYP, "stream") + field(SCAN, "Passive") + field(ZRST, "Amps Fast") + field(ZRVL, "0") + field(ONST, "Tesla Fast") + field(ONVL, "1") + field(TWST, "Amps Fast") + field(TWVL, "2") + field(THST, "Tesla Fast") + field(THVL, "3") + field(FRST, "Amps Slow") + field(FRVL, "4") + field(FVST, "Tesla Slow") + field(FVVL, "5") + field(SXST, "Amps Slow") + field(SXVL, "6") + field(SVST, "Tesla Slow") + field(SVVL, "7") + field(EIST, "Amps Unaffected") + field(EIVL, "8") + field(NIST, "Tesla Unaffected") + field(NIVL, "9") + # field(OUT, "@OxInstIPS.protocol setMode $(PORT)") + + field(VAL, "3") + field(PINI, "YES") + + field(SIML, "$(P)SIM") + field(SIOL, "$(P)SIM:SWEEPMODE:PARAMS:SP") + field(SDIS, "$(P)DISABLE") +} + +# In the legacy version, this used to be the readback from n of Mmn part of Examine command return. +# 0 output constant, 1, 2, 3 output changing +# The SCPI protocol doesn't directly offer this, so it has to be derived via the ACTIVITY record (DEV:GRPZ:PSU:ACTN) +# Direction from Alex Jones: "A response of HOLD or CLMP would be equivalent to n=0 in the response of the X command +# in the old protocol. Responses of RTOS or RTOZ would be equivalent to n=1. +# There is no equivalent for the m=0,1 fast/slow ramps, but we do not use this feature anyway." + +record(calcout, "$(P)_SWEEPMODE:SWEEP:CALC") { + field(INPA, "$(P)ACTIVITY.RVAL CP") + # 0 = HOLD, 1 = RTOS, 2 = RTOZ, 4 = CLMP + field(CALC, "((A==0)||(A==4))?0:1") + field(OUT, "$(P)STS:SWEEPMODE:SWEEP PP") + field(OOPT, "Every Time") +} + +record(mbbi, "$(P)STS:SWEEPMODE:SWEEP") { + field(DESC, "Mode status") + field(DTYP, "Soft Channel") + field(SCAN, "Passive") + field(ZRST, "At rest") field(ZRVL, "0") - field(ONST, "Remote & Locked") + field(ONST, "Sweeping") field(ONVL, "1") - field(TWST, "Local & Unlocked") + field(TWST, "Sweep Limiting") field(TWVL, "2") - field(THST, "Remote & Unlocked") + field(THST, "Swping & Lmting") field(THVL, "3") + + field(SIML, "$(P)SIM") + field(SIOL, "$(P)SIM:STS:SWEEPMODE:SWEEP") + field(SDIS, "$(P)DISABLE") + + info(archive, "VAL") } -alias("$(P)SIM:CONTROL", "$(P)SIM:CONTROL:SP") diff --git a/IPS/iocBoot/iocIPS-IOC-01/st.cmd b/IPS/iocBoot/iocIPS-IOC-01/st.cmd index 2a56d86f6..0502c9274 100644 --- a/IPS/iocBoot/iocIPS-IOC-01/st.cmd +++ b/IPS/iocBoot/iocIPS-IOC-01/st.cmd @@ -4,7 +4,8 @@ ## everywhere it appears in this file # Increase this if you get <> or discarded messages warnings in your errlog output -errlogInit2(65536, 256) +#errlogInit2(65536, 256) +errlogInit2(65536, 1024) < envPaths @@ -48,8 +49,25 @@ $(IFNOTDEVSIM) $(IFNOTRECSIM) asynSetOption("L0",0,"ixoff","N") epicsEnvSet("P", "$(MYPVPREFIX)$(IOCNAME):") +# The STREAMPROTOCOL env var should be set to either "LEGACY" (default) or "SCPI" +# Set the database and protocol file names accordingly +stringiftest("STREAMPROTOCOL_SCPI", "$(STREAMPROTOCOL=)", 4, "SCPI") +$(IFNOTSTREAMPROTOCOL_SCPI) epicsEnvSet "DBFILE" "ips.db" +$(IFSTREAMPROTOCOL_SCPI) epicsEnvSet "DBFILE" "ips_scpi.db" +$(IFNOTSTREAMPROTOCOL_SCPI) epicsEnvSet "PROTOCOLFILE" "OxInstIPS.protocol" +$(IFSTREAMPROTOCOL_SCPI) epicsEnvSet "PROTOCOLFILE" "OxInstIPS_SCPI.protocol" + +### IJG Diagnostics during development +#var streamError 1 +#var streamDebug 1 +#var streamDebugColored 1 +#var streamErrorDeadTime 30 +#var streamMsgTimeStamped 1 +#streamSetLogfile("streamdevice_logfile.txt") +################## + ## Load our record instances -dbLoadRecords("db/ips.db","PVPREFIX=$(MYPVPREFIX),P=$(P),RECSIM=$(RECSIM=0),DISABLE=$(DISABLE=0),PORT=$(DEVICE),MAX_FIELD=$(MAX_FIELD=7.0),MAX_SWEEP_RATE=$(MAX_SWEEP_RATE=1.0),STABILITY_VOLTAGE=$(STABILITY_VOLTAGE=0.1),HEATER_WAITTIME=$(HEATER_WAITTIME=60),MANAGER_ASG=$(MANAGER_ASG=MANAGER)") +dbLoadRecords("db/$(DBFILE)","PVPREFIX=$(MYPVPREFIX),P=$(P),RECSIM=$(RECSIM=0),DISABLE=$(DISABLE=0),PORT=$(DEVICE),MAX_FIELD=$(MAX_FIELD=7.0),MAX_SWEEP_RATE=$(MAX_SWEEP_RATE=1.0),STABILITY_VOLTAGE=$(STABILITY_VOLTAGE=0.1),HEATER_WAITTIME=$(HEATER_WAITTIME=60),MANAGER_ASG=$(MANAGER_ASG=MANAGER)") ##ISIS## Stuff that needs to be done after all records are loaded but before iocInit is called < $(IOCSTARTUP)/preiocinit.cmd From b80d381293635ca71cbd60d4fa4ddc7608d2ce8e Mon Sep 17 00:00:00 2001 From: Ian Gillingham Date: Tue, 10 Jun 2025 09:25:00 +0100 Subject: [PATCH 12/29] st.cmd: Commented out asynTraceMask() calls for diagnostic logging. Left in place as comment in case needed again at a future date --- IPS/iocBoot/iocIPS-IOC-01/st.cmd | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/IPS/iocBoot/iocIPS-IOC-01/st.cmd b/IPS/iocBoot/iocIPS-IOC-01/st.cmd index 0502c9274..6924b173e 100644 --- a/IPS/iocBoot/iocIPS-IOC-01/st.cmd +++ b/IPS/iocBoot/iocIPS-IOC-01/st.cmd @@ -42,6 +42,10 @@ $(IFNOTDEVSIM) $(IFNOTRECSIM) asynSetOption("L0",0,"crtscts","N") $(IFNOTDEVSIM) $(IFNOTRECSIM) asynSetOption("L0",0,"ixon","N") $(IFNOTDEVSIM) $(IFNOTRECSIM) asynSetOption("L0",0,"ixoff","N") +# Uncomment these for StreamDevice debugging +# asynSetTraceMask("L0", -1, 0x9) +# asynSetTraceIOMask("L0", -1, 0x2) + ## Load record instances ##ISIS## Load common DB records From e10153ff6db2a00bccdb923d9abc0c3efc1c7a5f Mon Sep 17 00:00:00 2001 From: Ian Gillingham Date: Thu, 26 Jun 2025 15:40:30 +0100 Subject: [PATCH 13/29] Commenced adding Level Sensor board support --- IPS/IPS-IOC-01App/Db/Makefile | 1 + IPS/IPS-IOC-01App/Db/ips_scpi.db | 88 ++++++++++++++++++++++ IPS/IPS-IOC-01App/Db/ips_scpi_levels.db | 99 +++++++++++++++++++++++++ IPS/iocBoot/iocIPS-IOC-01/st.cmd | 7 +- 4 files changed, 192 insertions(+), 3 deletions(-) create mode 100644 IPS/IPS-IOC-01App/Db/ips_scpi_levels.db diff --git a/IPS/IPS-IOC-01App/Db/Makefile b/IPS/IPS-IOC-01App/Db/Makefile index 812f763a9..0c4dba80c 100644 --- a/IPS/IPS-IOC-01App/Db/Makefile +++ b/IPS/IPS-IOC-01App/Db/Makefile @@ -12,6 +12,7 @@ include $(TOP)/configure/CONFIG # databases, templates, substitutions like this DB += ips.db DB += ips_scpi.db +DB += ips_scpi_levels.db #---------------------------------------------------- # If .db template is not named *.template add diff --git a/IPS/IPS-IOC-01App/Db/ips_scpi.db b/IPS/IPS-IOC-01App/Db/ips_scpi.db index 5ee7162d6..43d145577 100644 --- a/IPS/IPS-IOC-01App/Db/ips_scpi.db +++ b/IPS/IPS-IOC-01App/Db/ips_scpi.db @@ -1175,3 +1175,91 @@ record(mbbi, "$(P)STS:SWEEPMODE:SWEEP") { info(archive, "VAL") } +# Poll system alarms: This record repeatedly sends the READ:SYS:ALRM command +# and the response is parsed by records dedicated to each board type with SCAN of "I/O Intr" +record(ao, "$(P)STS:_POLLSYSTEM:ALARMS") { + field(DESC, "Poll system alarms") + field(DTYP, "stream") + field(SCAN, "5 second") + field(OUT, "@OxInstIPS_SCPI.protocol getSysAlarms $(PORT)") + + field(SIML, "$(P)SIM") + field(SIOL, "$(P)SIM:STS:_POLLSYSTEM:ALARMS") + field(SDIS, "$(P)DISABLE") +} + +record(mbbi, "$(P)STS:SYSTEM:ALARM:TBOARD") { + field(DESC, "Temperature board alarm status") + field(DTYP, "stream") + field(SCAN, "I/O Intr") + field(VAL, "0") + #field(PINI, "YES") + field(INP, "@OxInstIPS_SCPI.protocol readSysAlarmsTemperatureBoard $(PORT)") + field(ZRST, "OK") + field(ZRVL, "0") + field(ZRSV, "NO_ALARM") + field(ONST, "Open Circuit") + field(ONVL, "1") + field(ONSV, "MAJOR") + field(TWST, "Short Circuit") + field(TWSV, "2") + field(TWSV, "MAJOR") + field(THST, "Calibration Error") + field(THVL, "3") + field(THSV, "MAJOR") + field(FRST, "Firmware Error") + field(FRVL, "4") + field(FRSV, "MAJOR") + field(FVST, "Board Not Configured") + field(FVVL, "5") + field(FVSV, "MAJOR") + + field(SIML, "$(P)SIM") + field(SIOL, "$(P)SIM:STS:SYSTEM:ALARM:TBOARD") + field(SDIS, "$(P)DISABLE") + + info(archive, "VAL") +} + +record(mbbi, "$(P)STS:SYSTEM:ALARM:LBOARD") { + field(DESC, "Level board alarm status") + field(DTYP, "stream") + field(SCAN, "I/O Intr") + field(VAL, "0") + # field(PINI, "YES") + field(INP, "@OxInstIPS_SCPI.protocol readSysAlarmsLevelMeterBoard $(PORT)") + field(ZRST, "OK") + field(ZRVL, "0") + field(ZRSV, "NO_ALARM") + field(ONST, "Open Circuit") + field(ONVL, "1") + field(ONSV, "MAJOR") + field(TWST, "Short Circuit") + field(TWVL, "2") + field(TWSV, "MAJOR") + field(THST, "ADC Error") + field(THVL, "3") + field(THSV, "MAJOR") + field(FRST, "Over Demand") + field(FRVL, "4") + field(FRSV, "MAJOR") + field(FVST, "Over Temperature") + field(FVVL, "5") + field(FVSV, "MAJOR") + field(SXST, "Firmware Error") + field(SXVL, "6") + field(SXSV, "MAJOR") + field(SVST, "Board Not Configured") + field(SVVL, "7") + field(SVSV, "MAJOR") + field(EIST, "No Reserve") + field(EIVL, "8") + field(EISV, "MAJOR") + + field(SIML, "$(P)SIM") + field(SIOL, "$(P)SIM:STS:SYSTEM:ALARM:LBOARD") + field(SDIS, "$(P)DISABLE") + + info(archive, "VAL") +} + diff --git a/IPS/IPS-IOC-01App/Db/ips_scpi_levels.db b/IPS/IPS-IOC-01App/Db/ips_scpi_levels.db new file mode 100644 index 000000000..ce52f9fda --- /dev/null +++ b/IPS/IPS-IOC-01App/Db/ips_scpi_levels.db @@ -0,0 +1,99 @@ +#################################################################### +# This provide the records for the Mercury IPS Level Sensor board +#################################################################### + +record(ai, "$(P)LVL:NIT:FREQ:ZERO") { + field(DESC, "Get the N2 zero freq value") + field(DTYP, "stream") + field(SCAN, "5 second") + field(INP, "@OxInstIPS_SCPI.protocol getLevelNitFreqZero $(PORT)") + + field(SIML, "$(P)SIM") + field(SIOL, "$(P)SIM:LVL:NIT:FREQ:ZERO") + field(SDIS, "$(P)DISABLE") +} + +record(ao, "$(P)LVL:NIT:FREQ:ZERO:SP") { + field(DESC, "Set zero freq value for nitrogen level") + field(DTYP, "stream") + field(OUT, "@OxInstIPS_SCPI.protocol setLevelNitFreqZero $(PORT)") + + field(SIML, "$(P)SIM") + field(SIOL, "$(P)SIM:LVL:NIT:FREQ:FULL:SP") + field(SDIS, "$(P)DISABLE") +} + +record(ai, "$(P)LVL:NIT:FREQ:FULL") { + field(DESC, "Get the N2 full freq value") + field(DTYP, "stream") + field(SCAN, "5 second") + field(INP, "@OxInstIPS_SCPI.protocol getLevelNitFreqFull $(PORT)") + + field(SIML, "$(P)SIM") + field(SIOL, "$(P)SIM:LVL:NIT:FREQ:FULL") + field(SDIS, "$(P)DISABLE") +} + +record(ao, "$(P)LVL:NIT:FREQ:FULL:SP") { + field(DESC, "Set full freq value for nitrogen level") + field(DTYP, "stream") + field(OUT, "@OxInstIPS_SCPI.protocol setLevelNitFreqFull $(PORT)") + + field(SIML, "$(P)SIM") + field(SIOL, "$(P)SIM:LVL:NIT:FREQ:FULL:SP") + field(SDIS, "$(P)DISABLE") +} + +record(ai, "$(P)LVL:HE:EMPTY:RES") { + field(DESC, "Get empty helium resistance value") + field(DTYP, "stream") + field(SCAN, "5 second") + field(INP, "@OxInstIPS_SCPI.protocol getLevelHeEmptyRes $(PORT)") + field(EGU, "Ohm") + field(PREC, "2") + + field(SIML, "$(P)SIM") + field(SIOL, "$(P)SIM:LVL:HE:EMPTY:RES") + field(SDIS, "$(P)DISABLE") + info(archive, "VAL") +} + +record(ao, "$(P)LVL:HE:EMPTY:RES:SP") { + field(DESC, "Set empty helium resistance value") + field(DTYP, "stream") + field(OUT, "@OxInstIPS_SCPI.protocol setLevelHeEmptyRes $(PORT)") + field(EGU, "Ohm") + field(PREC, "2") + + field(SIML, "$(P)SIM") + field(SIOL, "$(P)SIM:LVL:HE:EMPTY:RES:SP") + field(SDIS, "$(P)DISABLE") + info(archive, "VAL") +} + +record(ai, "$(P)LVL:HE:FULL:RES") { + field(DESC, "Get full helium resistance value") + field(DTYP, "stream") + field(SCAN, "5 second") + field(INP, "@OxInstIPS_SCPI.protocol getLevelHeFullRes $(PORT)") + field(EGU, "Ohm") + field(PREC, "2") + + field(SIML, "$(P)SIM") + field(SIOL, "$(P)SIM:LVL:HE:FULL:RES") + field(SDIS, "$(P)DISABLE") + info(archive, "VAL") +} + +record(ao, "$(P)LVL:HE:FULL:RES:SP") { + field(DESC, "Set full helium resistance value") + field(DTYP, "stream") + field(OUT, "@OxInstIPS_SCPI.protocol setLevelHeFullRes $(PORT)") + field(EGU, "Ohm") + field(PREC, "2") + + field(SIML, "$(P)SIM") + field(SIOL, "$(P)SIM:LVL:HE:FULL:RES:SP") + field(SDIS, "$(P)DISABLE") + info(archive, "VAL") +} diff --git a/IPS/iocBoot/iocIPS-IOC-01/st.cmd b/IPS/iocBoot/iocIPS-IOC-01/st.cmd index 6924b173e..9684cd2d6 100644 --- a/IPS/iocBoot/iocIPS-IOC-01/st.cmd +++ b/IPS/iocBoot/iocIPS-IOC-01/st.cmd @@ -43,8 +43,8 @@ $(IFNOTDEVSIM) $(IFNOTRECSIM) asynSetOption("L0",0,"ixon","N") $(IFNOTDEVSIM) $(IFNOTRECSIM) asynSetOption("L0",0,"ixoff","N") # Uncomment these for StreamDevice debugging -# asynSetTraceMask("L0", -1, 0x9) -# asynSetTraceIOMask("L0", -1, 0x2) +asynSetTraceMask("L0", -1, 0x9) +asynSetTraceIOMask("L0", -1, 0x2) ## Load record instances @@ -72,8 +72,9 @@ $(IFSTREAMPROTOCOL_SCPI) epicsEnvSet "PROTOCOLFILE" "OxInstIPS_SCPI.protocol" ## Load our record instances dbLoadRecords("db/$(DBFILE)","PVPREFIX=$(MYPVPREFIX),P=$(P),RECSIM=$(RECSIM=0),DISABLE=$(DISABLE=0),PORT=$(DEVICE),MAX_FIELD=$(MAX_FIELD=7.0),MAX_SWEEP_RATE=$(MAX_SWEEP_RATE=1.0),STABILITY_VOLTAGE=$(STABILITY_VOLTAGE=0.1),HEATER_WAITTIME=$(HEATER_WAITTIME=60),MANAGER_ASG=$(MANAGER_ASG=MANAGER)") +$(IFSTREAMPROTOCOL_SCPI) dbLoadRecords("db/ips_scpi_levels.db","PVPREFIX=$(MYPVPREFIX),P=$(P),RECSIM=$(RECSIM=0),DISABLE=$(DISABLE=0),PORT=$(DEVICE),MANAGER_ASG=$(MANAGER_ASG=MANAGER)") -##ISIS## Stuff that needs to be done after all records are loaded but before iocInit is called +##ISIS## Stuff that needs to be done after all records are loaded but before iocInit is called < $(IOCSTARTUP)/preiocinit.cmd cd "${TOP}/iocBoot/${IOC}" From 6fdd8d06ea4629150c1b064c4406ee1ff0b244a8 Mon Sep 17 00:00:00 2001 From: Ian Gillingham Date: Thu, 3 Jul 2025 14:24:17 +0100 Subject: [PATCH 14/29] Added a lot of records for the helium and nitrogen level meters and sensor reading rates. --- IPS/IPS-IOC-01App/Db/ips_scpi_levels.db | 296 ++++++++++++++++++++++-- 1 file changed, 271 insertions(+), 25 deletions(-) diff --git a/IPS/IPS-IOC-01App/Db/ips_scpi_levels.db b/IPS/IPS-IOC-01App/Db/ips_scpi_levels.db index ce52f9fda..edd932393 100644 --- a/IPS/IPS-IOC-01App/Db/ips_scpi_levels.db +++ b/IPS/IPS-IOC-01App/Db/ips_scpi_levels.db @@ -2,10 +2,214 @@ # This provide the records for the Mercury IPS Level Sensor board #################################################################### +# ========= HELIUM ========= # + +record(ai, "$(P)LVL:HE:EMPTY:RES") { + field(DESC, "Get empty helium resistance value") + field(DTYP, "stream") + field(SCAN, "5 second") + field(INP, "@OxInstIPS_SCPI.protocol getLevelHeEmptyRes $(PORT)") + field(EGU, "Ohm") + field(PREC, "2") + + field(SIML, "$(P)SIM") + field(SIOL, "$(P)SIM:LVL:HE:EMPTY:RES") + field(SDIS, "$(P)DISABLE") + info(archive, "VAL") +} + +record(ao, "$(P)LVL:HE:EMPTY:RES:SP") { + field(ASG, "$(MANAGER_ASG)") + field(DESC, "Set empty helium resistance value") + field(DTYP, "stream") + field(OUT, "@OxInstIPS_SCPI.protocol setLevelHeEmptyRes $(PORT)") + field(EGU, "Ohm") + field(PREC, "2") + + field(SIML, "$(P)SIM") + field(SIOL, "$(P)SIM:LVL:HE:EMPTY:RES:SP") + field(SDIS, "$(P)DISABLE") + info(archive, "VAL") +} + +record(ai, "$(P)LVL:HE:FULL:RES") { + field(DESC, "Get full helium resistance value") + field(DTYP, "stream") + field(SCAN, "5 second") + field(INP, "@OxInstIPS_SCPI.protocol getLevelHeFullRes $(PORT)") + field(EGU, "Ohm") + field(PREC, "2") + + field(SIML, "$(P)SIM") + field(SIOL, "$(P)SIM:LVL:HE:FULL:RES") + field(SDIS, "$(P)DISABLE") + info(archive, "VAL") +} + +record(ao, "$(P)LVL:HE:FULL:RES:SP") { + field(ASG, "$(MANAGER_ASG)") + field(DESC, "Set full helium resistance value") + field(DTYP, "stream") + field(OUT, "@OxInstIPS_SCPI.protocol setLevelHeFullRes $(PORT)") + field(EGU, "Ohm") + field(PREC, "2") + + field(SIML, "$(P)SIM") + field(SIOL, "$(P)SIM:LVL:HE:FULL:RES:SP") + field(SDIS, "$(P)DISABLE") + info(archive, "VAL") +} + +record(ai, "$(P)LVL:HE:REFILL:START") { + field(DESC, "Get high helium level that starts the refill") + field(DTYP, "stream") + field(SCAN, "5 second") + field(INP, "@OxInstIPS_SCPI.protocol getLevelHeFillStartThreshold $(PORT)") + field(EGU, "%") + field(PREC, "0") + + field(SIML, "$(P)SIM") + field(SIOL, "$(P)SIM:LVL:HE:REFILL:START") + field(SDIS, "$(P)DISABLE") + info(archive, "VAL") +} + +record(ao, "$(P)LVL:HE:REFILL:START:SP") { + field(ASG, "$(MANAGER_ASG)") + field(DESC, "Set high helium level that starts the refill") + field(DTYP, "stream") + field(OUT, "@OxInstIPS_SCPI.protocol setLevelHeFillStartThreshold $(PORT)") + field(EGU, "%") + field(PREC, "0") + + field(SIML, "$(P)SIM") + field(SIOL, "$(P)LVL:HE:REFILL:START:SP") + field(SDIS, "$(P)DISABLE") + info(archive, "VAL") +} + +record(ai, "$(P)LVL:HE:REFILL:STOP") { + field(DESC, "Get high helium level that stops the refill") + field(DTYP, "stream") + field(SCAN, "5 second") + field(INP, "@OxInstIPS_SCPI.protocol getLevelHeFillStopThreshold $(PORT)") + field(EGU, "%") + field(PREC, "0") + + field(SIML, "$(P)SIM") + field(SIOL, "$(P)SIM:LVL:HE:REFILL:STOP") + field(SDIS, "$(P)DISABLE") + info(archive, "VAL") +} + +record(ao, "$(P)LVL:HE:REFILL:STOP:SP") { + field(ASG, "$(MANAGER_ASG)") + field(DESC, "Set high helium level that stops the refill") + field(DTYP, "stream") + field(OUT, "@OxInstIPS_SCPI.protocol setLevelHeFillStopThreshold $(PORT)") + field(EGU, "%") + field(PREC, "0") + + field(SIML, "$(P)SIM") + field(SIOL, "$(P)LVL:HE:REFILL:STOP:SP") + field(SDIS, "$(P)DISABLE") + info(archive, "VAL") +} + +record(mbbi, "$(P)LVL:HE:REFILLING") { + field(DESC, "Is helium refill in progress?") + field(DTYP, "stream") + field(SCAN, "5 second") + field(INP, "@OxInstIPS_SCPI.protocol getLevelHeRefilling $(PORT)") + field(ZRST, "No") + field(ZRVL, "0") + field(ZRSV, "NO_ALARM") + field(ONST, "Yes") + field(ONVL, "1") + field(ONSV, "NO_ALARM") + info(archive, "VAL") +} + +record(ai, "$(P)LVL:HE:LEVEL") { + field(DESC, "Get helium level") + field(DTYP, "stream") + field(SCAN, "5 second") + field(INP, "@OxInstIPS_SCPI.protocol getLevelHeliumLevel $(PORT)") + field(EGU, "%") + field(PREC, "0") + + field(SIML, "$(P)SIM") + field(SIOL, "$(P)SIM:LVL:HE:LEVEL") + field(SDIS, "$(P)DISABLE") + info(archive, "VAL") +} + +record(mbbi, "$(P)LVL:HE:PULSE:READ:RATE") { + field(DESC, "Get high helium reading pulse rate") + field(DTYP, "stream") + field(SCAN, "5 second") + field(INP, "@OxInstIPS_SCPI.protocol getLevelHeReadingRate $(PORT)") + field(ZRST, "Fast") + field(ZRVL, "0") + field(ZRSV, "NO_ALARM") + field(ONST, "Slow") + field(ONVL, "1") + field(ONSV, "NO_ALARM") + + field(SIML, "$(P)SIM") + field(SIOL, "$(P)SIM:LVL:HE:REFILL:STOP") + field(SDIS, "$(P)DISABLE") + info(archive, "VAL") +} + +record(bo, "$(P)LVL:HE:PULSE:READ:RATE:SP") { + field(ASG, "$(MANAGER_ASG)") + field(DESC, "Set high helium reading pulse rate") + field(DTYP, "stream") + field(OUT, "@OxInstIPS_SCPI.protocol setLevelHeReadingRate $(PORT)") + field(ZNAM, "Fast") + field(ONAM, "Slow") + + field(SIML, "$(P)SIM") + field(SIOL, "$(P)SIM:LVL:HE:PULSE:READ:RATE:SP") + field(SDIS, "$(P)DISABLE") +} + + + +# ========= NITROGEN ========= ## + +record(ai, "$(P)LVL:NIT:READ:INTERVAL") { + field(DESC, "Get the N2 sensor read interval (ms)") + field(DTYP, "stream") + field(SCAN, "5 second") + field(EGU, "ms") + field(INP, "@OxInstIPS_SCPI.protocol getLevelNitReadInterval $(PORT)") + + field(SIML, "$(P)SIM") + field(SIOL, "$(P)SIM:LVL:NIT:READ:INTERVAL") + field(SDIS, "$(P)DISABLE") +} + +record(ao, "$(P)LVL:NIT:READ:INTERVAL:SP") { + field(ASG, "$(MANAGER_ASG)") + field(DESC, "Set the N2 sensor read interval (ms)") + field(DTYP, "stream") + field(EGU, "ms") + field(OUT, "@OxInstIPS_SCPI.protocol setLevelNitReadInterval $(PORT)") + field(DRVH, "$(MAX_N2_READ_INTERVAL==5000)") + field(DRVL, "$(MIN_N2_READ_INTERVAL=0)") + + field(SIML, "$(P)SIM") + field(SIOL, "$(P)SIM:LVL:NIT:FREQ:FULL:SP") + field(SDIS, "$(P)DISABLE") +} + record(ai, "$(P)LVL:NIT:FREQ:ZERO") { field(DESC, "Get the N2 zero freq value") field(DTYP, "stream") field(SCAN, "5 second") + field(EGU, "Hz") field(INP, "@OxInstIPS_SCPI.protocol getLevelNitFreqZero $(PORT)") field(SIML, "$(P)SIM") @@ -14,18 +218,24 @@ record(ai, "$(P)LVL:NIT:FREQ:ZERO") { } record(ao, "$(P)LVL:NIT:FREQ:ZERO:SP") { + field(ASG, "$(MANAGER_ASG)") field(DESC, "Set zero freq value for nitrogen level") field(DTYP, "stream") + field(EGU, "Hz") field(OUT, "@OxInstIPS_SCPI.protocol setLevelNitFreqZero $(PORT)") + field(FLNK, "$(P)LVL:NIT:FREQ:ZERO") + field(DRVH, "$(MAX_N2_FREQ=65000)") + field(DRVL, "$(MIN_N2_FREQ=5000)") field(SIML, "$(P)SIM") - field(SIOL, "$(P)SIM:LVL:NIT:FREQ:FULL:SP") + field(SIOL, "$(P)SIM:LVL:NIT:FREQ:ZERO:SP") field(SDIS, "$(P)DISABLE") } record(ai, "$(P)LVL:NIT:FREQ:FULL") { field(DESC, "Get the N2 full freq value") field(DTYP, "stream") + field(EGU, "Hz") field(SCAN, "5 second") field(INP, "@OxInstIPS_SCPI.protocol getLevelNitFreqFull $(PORT)") @@ -35,65 +245,101 @@ record(ai, "$(P)LVL:NIT:FREQ:FULL") { } record(ao, "$(P)LVL:NIT:FREQ:FULL:SP") { + field(ASG, "$(MANAGER_ASG)") field(DESC, "Set full freq value for nitrogen level") field(DTYP, "stream") + field(EGU, "Hz") field(OUT, "@OxInstIPS_SCPI.protocol setLevelNitFreqFull $(PORT)") + field(FLNK, "$(P)LVL:NIT:FREQ:FULL") + field(DRVH, "$(MAX_N2_FREQ=65000)") + field(DRVL, "$(MIN_N2_FREQ=5000)") field(SIML, "$(P)SIM") field(SIOL, "$(P)SIM:LVL:NIT:FREQ:FULL:SP") field(SDIS, "$(P)DISABLE") } -record(ai, "$(P)LVL:HE:EMPTY:RES") { - field(DESC, "Get empty helium resistance value") +record(ai, "$(P)LVL:NIT:REFILL:START") { + field(DESC, "Get high N2 level that starts the refill") field(DTYP, "stream") field(SCAN, "5 second") - field(INP, "@OxInstIPS_SCPI.protocol getLevelHeEmptyRes $(PORT)") - field(EGU, "Ohm") - field(PREC, "2") + field(INP, "@OxInstIPS_SCPI.protocol getLevelNitFillStartThreshold $(PORT)") + field(EGU, "%") + field(PREC, "0") field(SIML, "$(P)SIM") - field(SIOL, "$(P)SIM:LVL:HE:EMPTY:RES") + field(SIOL, "$(P)SIM:LVL:NIT:REFILL:START") field(SDIS, "$(P)DISABLE") info(archive, "VAL") } -record(ao, "$(P)LVL:HE:EMPTY:RES:SP") { - field(DESC, "Set empty helium resistance value") +record(ao, "$(P)LVL:NIT:REFILL:START:SP") { + field(ASG, "$(MANAGER_ASG)") + field(DESC, "Set high N2 level that starts the refill") field(DTYP, "stream") - field(OUT, "@OxInstIPS_SCPI.protocol setLevelHeEmptyRes $(PORT)") - field(EGU, "Ohm") - field(PREC, "2") + field(OUT, "@OxInstIPS_SCPI.protocol setLevelNitFillStartThreshold $(PORT)") + field(EGU, "%") + field(PREC, "0") field(SIML, "$(P)SIM") - field(SIOL, "$(P)SIM:LVL:HE:EMPTY:RES:SP") + field(SIOL, "$(P)LVL:NIT:REFILL:START:SP") field(SDIS, "$(P)DISABLE") info(archive, "VAL") } -record(ai, "$(P)LVL:HE:FULL:RES") { - field(DESC, "Get full helium resistance value") +record(ai, "$(P)LVL:NIT:REFILL:STOP") { + field(DESC, "Get high N2 level that stops the refill") field(DTYP, "stream") field(SCAN, "5 second") - field(INP, "@OxInstIPS_SCPI.protocol getLevelHeFullRes $(PORT)") - field(EGU, "Ohm") - field(PREC, "2") + field(INP, "@OxInstIPS_SCPI.protocol getLevelNitFillStopThreshold $(PORT)") + field(EGU, "%") + field(PREC, "0") field(SIML, "$(P)SIM") - field(SIOL, "$(P)SIM:LVL:HE:FULL:RES") + field(SIOL, "$(P)SIM:LVL:NIT:REFILL:STOP") field(SDIS, "$(P)DISABLE") info(archive, "VAL") } -record(ao, "$(P)LVL:HE:FULL:RES:SP") { - field(DESC, "Set full helium resistance value") +record(ao, "$(P)LVL:NIT:REFILL:STOP:SP") { + field(ASG, "$(MANAGER_ASG)") + field(DESC, "Set high N2 level that stops the refill") field(DTYP, "stream") - field(OUT, "@OxInstIPS_SCPI.protocol setLevelHeFullRes $(PORT)") - field(EGU, "Ohm") - field(PREC, "2") + field(OUT, "@OxInstIPS_SCPI.protocol setLevelNitFillStopThreshold $(PORT)") + field(EGU, "%") + field(PREC, "0") field(SIML, "$(P)SIM") - field(SIOL, "$(P)SIM:LVL:HE:FULL:RES:SP") + field(SIOL, "$(P)LVL:NIT:REFILL:STOP:SP") field(SDIS, "$(P)DISABLE") info(archive, "VAL") } + +record(mbbi, "$(P)LVL:NIT:REFILLING") { + field(DESC, "Is N2 refill in progress?") + field(DTYP, "stream") + field(SCAN, "5 second") + field(INP, "@OxInstIPS_SCPI.protocol getLevelNitRefilling $(PORT)") + field(ZRST, "No") + field(ZRVL, "0") + field(ZRSV, "NO_ALARM") + field(ONST, "Yes") + field(ONVL, "1") + field(ONSV, "NO_ALARM") + info(archive, "VAL") +} + +record(ai, "$(P)LVL:NIT:LEVEL") { + field(DESC, "Get nitrogen level") + field(DTYP, "stream") + field(SCAN, "5 second") + field(INP, "@OxInstIPS_SCPI.protocol getLevelNitrogenLevel $(PORT)") + field(EGU, "%") + field(PREC, "0") + + field(SIML, "$(P)SIM") + field(SIOL, "$(P)SIM:LVL:NIT:LEVEL") + field(SDIS, "$(P)DISABLE") + info(archive, "VAL") +} + From 9215a31d199db18f246773d013ed43df97e6da97 Mon Sep 17 00:00:00 2001 From: Ian Gillingham Date: Thu, 3 Jul 2025 15:04:01 +0100 Subject: [PATCH 15/29] Added MIN_N2_FREQ and MAX_N2_FREQ macros to dbLoadRecords(db/ips_scpi_levels.db) --- IPS/iocBoot/iocIPS-IOC-01/st.cmd | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/IPS/iocBoot/iocIPS-IOC-01/st.cmd b/IPS/iocBoot/iocIPS-IOC-01/st.cmd index 9684cd2d6..d741f299d 100644 --- a/IPS/iocBoot/iocIPS-IOC-01/st.cmd +++ b/IPS/iocBoot/iocIPS-IOC-01/st.cmd @@ -72,7 +72,7 @@ $(IFSTREAMPROTOCOL_SCPI) epicsEnvSet "PROTOCOLFILE" "OxInstIPS_SCPI.protocol" ## Load our record instances dbLoadRecords("db/$(DBFILE)","PVPREFIX=$(MYPVPREFIX),P=$(P),RECSIM=$(RECSIM=0),DISABLE=$(DISABLE=0),PORT=$(DEVICE),MAX_FIELD=$(MAX_FIELD=7.0),MAX_SWEEP_RATE=$(MAX_SWEEP_RATE=1.0),STABILITY_VOLTAGE=$(STABILITY_VOLTAGE=0.1),HEATER_WAITTIME=$(HEATER_WAITTIME=60),MANAGER_ASG=$(MANAGER_ASG=MANAGER)") -$(IFSTREAMPROTOCOL_SCPI) dbLoadRecords("db/ips_scpi_levels.db","PVPREFIX=$(MYPVPREFIX),P=$(P),RECSIM=$(RECSIM=0),DISABLE=$(DISABLE=0),PORT=$(DEVICE),MANAGER_ASG=$(MANAGER_ASG=MANAGER)") +$(IFSTREAMPROTOCOL_SCPI) dbLoadRecords("db/ips_scpi_levels.db","PVPREFIX=$(MYPVPREFIX),P=$(P),RECSIM=$(RECSIM=0),DISABLE=$(DISABLE=0),PORT=$(DEVICE),MIN_N2_FREQ=$(MIN_N2_FREQ=5000),MAX_N2_FREQ=$(MAX_N2_FREQ=65000),MANAGER_ASG=$(MANAGER_ASG=MANAGER)") ##ISIS## Stuff that needs to be done after all records are loaded but before iocInit is called < $(IOCSTARTUP)/preiocinit.cmd From 48022bc538205df03971fcb7ac5df03b8fb3eec3 Mon Sep 17 00:00:00 2001 From: Ian Gillingham Date: Tue, 22 Jul 2025 11:31:45 +0100 Subject: [PATCH 16/29] IPS: Added STREAMPROTOCOL macro to config.xml --- IPS/iocBoot/iocIPS-IOC-01/config.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/IPS/iocBoot/iocIPS-IOC-01/config.xml b/IPS/iocBoot/iocIPS-IOC-01/config.xml index 08a1ab545..6973ad26a 100644 --- a/IPS/iocBoot/iocIPS-IOC-01/config.xml +++ b/IPS/iocBoot/iocIPS-IOC-01/config.xml @@ -8,6 +8,7 @@ + From 2a0cb1c0a9a4c39d11244d71582a2d80ba417819 Mon Sep 17 00:00:00 2001 From: Ian Gillingham Date: Tue, 29 Jul 2025 08:51:30 +0100 Subject: [PATCH 17/29] Added He & N levels records. cleaned up ips_scpi.db. build.mak now includes aSub refs from supp. --- IPS/IPS-IOC-01App/Db/ips_scpi.db | 199 ++++++++++++++++-------- IPS/IPS-IOC-01App/Db/ips_scpi_levels.db | 51 ++---- IPS/IPS-IOC-01App/src/build.mak | 2 + 3 files changed, 145 insertions(+), 107 deletions(-) diff --git a/IPS/IPS-IOC-01App/Db/ips_scpi.db b/IPS/IPS-IOC-01App/Db/ips_scpi.db index 43d145577..8194dd961 100644 --- a/IPS/IPS-IOC-01App/Db/ips_scpi.db +++ b/IPS/IPS-IOC-01App/Db/ips_scpi.db @@ -373,25 +373,25 @@ record(ai, "$(P)MAGNET:CURR:PERSISTENT") { info(archive, "VAL") } -## ==== CURR:TRIP needs to be derived somehow. It is not in the SCPI protocol. ==== +## ==== CURR:TRIP needs to be derived somehow, some time. It is not in the SCPI protocol. ==== # The current at which a trip last occurred. Am not sure if by trip, they mean # a quench or a problem with the level meter. Believe the unit will take the current # and field to zero if there is a trip, so this parameter preserves what was happening # at the time of the trip. -record(ai, "$(P)CURR:TRIP") { - field(DESC, "Trip current readback") - field(DTYP, "stream") - field(SCAN, "1 second") - # field(INP, "@OxInstIPS_SCPI.protocol getTripCurrent $(PORT)") - field(EGU, "A") - field(PREC, "4") - - field(SIML, "$(P)SIM") - field(SIOL, "$(P)SIM:TRIPCURRENT") - field(SDIS, "$(P)DISABLE") - - info(archive, "VAL") -} +#record(ai, "$(P)CURR:TRIP") { +# field(DESC, "Trip current readback") +# field(DTYP, "stream") +# field(SCAN, "1 second") +# # field(INP, "@OxInstIPS_SCPI.protocol getTripCurrent $(PORT)") +# field(EGU, "A") +# field(PREC, "4") +# +# field(SIML, "$(P)SIM") +# field(SIOL, "$(P)SIM:TRIPCURRENT") +# field(SDIS, "$(P)DISABLE") +# +# info(archive, "VAL") +#} # The field in the magnet due to the persistent current. See current for explanation. record(ai, "$(P)MAGNET:FIELD:PERSISTENT") { @@ -411,22 +411,22 @@ record(ai, "$(P)MAGNET:FIELD:PERSISTENT") { info(archive, "VAL") } -## ==== FIELD:TRIP needs to be derived somehow. It is not in the SCPI protocol. ==== +## ==== FIELD:TRIP needs to be derived somehow, some time. It is not in the SCPI protocol. ==== # The field at which a trip last occurred. See current for explanation. -record(ai, "$(P)FIELD:TRIP") { - field(DESC, "Trip field readback") - field(DTYP, "stream") - field(SCAN, "1 second") - # field(INP, "@OxInstIPS_SCPI.protocol getTripField $(PORT)") - field(EGU, "T") - field(PREC, "5") - - field(SIML, "$(P)SIM") - field(SIOL, "$(P)SIM:TRIPFIELD") - field(SDIS, "$(P)DISABLE") - - info(archive, "VAL") -} +#record(ai, "$(P)FIELD:TRIP") { +# field(DESC, "Trip field readback") +# field(DTYP, "stream") +# field(SCAN, "1 second") +# # field(INP, "@OxInstIPS_SCPI.protocol getTripField $(PORT)") +# field(EGU, "T") +# field(PREC, "5") +# +# field(SIML, "$(P)SIM") +# field(SIOL, "$(P)SIM:TRIPFIELD") +# field(SDIS, "$(P)DISABLE") +# +# info(archive, "VAL") +#} # The current being provided to the heater. # Our magnets do not have heaters, so this is not relevant. @@ -802,30 +802,6 @@ record(mbbi, "$(P)STS:SYSTEM:FAULT") { info(archive, "VAL") } -# # Readback from n of Xmn part of Examine command return. -record(mbbi, "$(P)STS:SYSTEM:LIMIT") { - field(DESC, "System limit status") - field(DTYP, "Soft Channel") - field(SCAN, "Passive") - field(ZRST, "Normal") - field(ZRVL, "0") - field(ZRSV, "NO_ALARM") - field(ONST, "On +ve V Limit") - field(ONVL, "1") - field(ONSV, "MINOR") - field(TWST, "On -ve V Limit") - field(TWVL, "2") - field(TWSV, "MINOR") - field(FRST, "Current too -ve") - field(FRVL, "4") - field(FRSV, "MINOR") - field(EIST, "Current too +ve") - field(EIVL, "8") - field(EISV, "MINOR") - - info(archive, "VAL") -} - # Readback from SWHT command. # OFF -> switch closed, ON -> switch open. record(mbbi, "$(P)HEATER:STATUS") { @@ -1177,24 +1153,38 @@ record(mbbi, "$(P)STS:SWEEPMODE:SWEEP") { # Poll system alarms: This record repeatedly sends the READ:SYS:ALRM command # and the response is parsed by records dedicated to each board type with SCAN of "I/O Intr" -record(ao, "$(P)STS:_POLLSYSTEM:ALARMS") { +record(stringin, "$(P)STS:_POLLSYSTEM:ALARMS") { field(DESC, "Poll system alarms") field(DTYP, "stream") field(SCAN, "5 second") - field(OUT, "@OxInstIPS_SCPI.protocol getSysAlarms $(PORT)") + field(INP, "@OxInstIPS_SCPI.protocol getSysAlarms $(PORT)") + field(FLNK, "$(P)STS:_POLLSYSTEM:ALARMS_SUB") field(SIML, "$(P)SIM") field(SIOL, "$(P)SIM:STS:_POLLSYSTEM:ALARMS") field(SDIS, "$(P)DISABLE") } +record(aSub, "$(P)STS:_POLLSYSTEM:ALARMS_SUB") { + field(SNAM, "handle_system_alarm_status") + field(INPA, "$(P)STS:_POLLSYSTEM:ALARMS") + field(FTA, "STRING") + field(NOA, "1") + + field(OUTA, "$(P)STS:SYSTEM:ALARM:TBOARD PP") + field(OUTB, "$(P)STS:SYSTEM:ALARM:10TBOARD PP") + field(OUTC, "$(P)STS:SYSTEM:ALARM:LBOARD PP") + field(FTVA, "LONG") + field(NOVA, "1") + + info(archive, "A VALA") +} + record(mbbi, "$(P)STS:SYSTEM:ALARM:TBOARD") { field(DESC, "Temperature board alarm status") - field(DTYP, "stream") - field(SCAN, "I/O Intr") - field(VAL, "0") - #field(PINI, "YES") - field(INP, "@OxInstIPS_SCPI.protocol readSysAlarmsTemperatureBoard $(PORT)") + field(DTYP, "Soft Channel") + field(SCAN, "Passive") + field(INP, "") field(ZRST, "OK") field(ZRVL, "0") field(ZRSV, "NO_ALARM") @@ -1221,13 +1211,44 @@ record(mbbi, "$(P)STS:SYSTEM:ALARM:TBOARD") { info(archive, "VAL") } +record(mbbi, "$(P)STS:SYSTEM:ALARM:10TBOARD") { + field(DESC, "Temperature board alarm status") + field(DTYP, "Soft Channel") + field(SCAN, "Passive") + field(VAL, "0") + field(INP, "") + field(ZRST, "OK") + field(ZRVL, "0") + field(ZRSV, "NO_ALARM") + field(ONST, "Open Circuit") + field(ONVL, "1") + field(ONSV, "MAJOR") + field(TWST, "Short Circuit") + field(TWSV, "2") + field(TWSV, "MAJOR") + field(THST, "Calibration Error") + field(THVL, "3") + field(THSV, "MAJOR") + field(FRST, "Firmware Error") + field(FRVL, "4") + field(FRSV, "MAJOR") + field(FVST, "Board Not Configured") + field(FVVL, "5") + field(FVSV, "MAJOR") + + field(SIML, "$(P)SIM") + field(SIOL, "$(P)SIM:STS:SYSTEM:ALARM:10TBOARD") + field(SDIS, "$(P)DISABLE") + + info(archive, "VAL") +} + record(mbbi, "$(P)STS:SYSTEM:ALARM:LBOARD") { field(DESC, "Level board alarm status") - field(DTYP, "stream") - field(SCAN, "I/O Intr") + field(DTYP, "Soft Channel") + field(SCAN, "Passive") field(VAL, "0") - # field(PINI, "YES") - field(INP, "@OxInstIPS_SCPI.protocol readSysAlarmsLevelMeterBoard $(PORT)") + field(INP, "") field(ZRST, "OK") field(ZRVL, "0") field(ZRSV, "NO_ALARM") @@ -1263,3 +1284,51 @@ record(mbbi, "$(P)STS:SYSTEM:ALARM:LBOARD") { info(archive, "VAL") } + +# The temperature of the magnet MB1.T1 +record(ai, "$(P)TEMP:MAGNET") { + field(DESC, "Magnet temperature") + field(DTYP, "stream") + field(SCAN, "1 second") + field(INP, "@OxInstIPS_SCPI.protocol getMagnetTemperature $(PORT)") + field(EGU, "K") + field(PREC, "4") + + field(SIML, "$(P)SIM") + field(SIOL, "$(P)SIM:TEMP:MAGNET") + field(SDIS, "$(P)DISABLE") + + info(archive, "VAL") +} + +# The temperature of the lambda plate DB8.T1 +record(ai, "$(P)TEMP:LAMBDAPLATE") { + field(DESC, "DB8.T1 temperature") + field(DTYP, "stream") + field(SCAN, "1 second") + field(INP, "@OxInstIPS_SCPI.protocol getLambdaPlateTemperature $(PORT)") + field(EGU, "K") + field(PREC, "4") + + field(SIML, "$(P)SIM") + field(SIOL, "$(P)SIM:TEMP:LAMBDAPLATE") + field(SDIS, "$(P)DISABLE") + + info(archive, "VAL") +} + +# The temperature of the lambda plate DB8.T1 +record(ai, "$(P)PRESSURE") { + field(DESC, "DB5.P1 pressure") + field(DTYP, "stream") + field(SCAN, "1 second") + field(INP, "@OxInstIPS_SCPI.protocol getPressure $(PORT)") + field(EGU, "mBar") + field(PREC, "4") + + field(SIML, "$(P)SIM") + field(SIOL, "$(P)SIM:PRESSURE") + field(SDIS, "$(P)DISABLE") + + info(archive, "VAL") +} diff --git a/IPS/IPS-IOC-01App/Db/ips_scpi_levels.db b/IPS/IPS-IOC-01App/Db/ips_scpi_levels.db index edd932393..1996757fc 100644 --- a/IPS/IPS-IOC-01App/Db/ips_scpi_levels.db +++ b/IPS/IPS-IOC-01App/Db/ips_scpi_levels.db @@ -61,7 +61,7 @@ record(ao, "$(P)LVL:HE:FULL:RES:SP") { } record(ai, "$(P)LVL:HE:REFILL:START") { - field(DESC, "Get high helium level that starts the refill") + field(DESC, "Get high He level that starts the refill") field(DTYP, "stream") field(SCAN, "5 second") field(INP, "@OxInstIPS_SCPI.protocol getLevelHeFillStartThreshold $(PORT)") @@ -76,7 +76,7 @@ record(ai, "$(P)LVL:HE:REFILL:START") { record(ao, "$(P)LVL:HE:REFILL:START:SP") { field(ASG, "$(MANAGER_ASG)") - field(DESC, "Set high helium level that starts the refill") + field(DESC, "Set high He level that starts the refill") field(DTYP, "stream") field(OUT, "@OxInstIPS_SCPI.protocol setLevelHeFillStartThreshold $(PORT)") field(EGU, "%") @@ -89,7 +89,7 @@ record(ao, "$(P)LVL:HE:REFILL:START:SP") { } record(ai, "$(P)LVL:HE:REFILL:STOP") { - field(DESC, "Get high helium level that stops the refill") + field(DESC, "Get high He level that stops the refill") field(DTYP, "stream") field(SCAN, "5 second") field(INP, "@OxInstIPS_SCPI.protocol getLevelHeFillStopThreshold $(PORT)") @@ -104,7 +104,7 @@ record(ai, "$(P)LVL:HE:REFILL:STOP") { record(ao, "$(P)LVL:HE:REFILL:STOP:SP") { field(ASG, "$(MANAGER_ASG)") - field(DESC, "Set high helium level that stops the refill") + field(DESC, "Set high He level that stops the refill") field(DTYP, "stream") field(OUT, "@OxInstIPS_SCPI.protocol setLevelHeFillStopThreshold $(PORT)") field(EGU, "%") @@ -116,20 +116,6 @@ record(ao, "$(P)LVL:HE:REFILL:STOP:SP") { info(archive, "VAL") } -record(mbbi, "$(P)LVL:HE:REFILLING") { - field(DESC, "Is helium refill in progress?") - field(DTYP, "stream") - field(SCAN, "5 second") - field(INP, "@OxInstIPS_SCPI.protocol getLevelHeRefilling $(PORT)") - field(ZRST, "No") - field(ZRVL, "0") - field(ZRSV, "NO_ALARM") - field(ONST, "Yes") - field(ONVL, "1") - field(ONSV, "NO_ALARM") - info(archive, "VAL") -} - record(ai, "$(P)LVL:HE:LEVEL") { field(DESC, "Get helium level") field(DTYP, "stream") @@ -144,26 +130,21 @@ record(ai, "$(P)LVL:HE:LEVEL") { info(archive, "VAL") } -record(mbbi, "$(P)LVL:HE:PULSE:READ:RATE") { +record(bi, "$(P)LVL:HE:PULSE:READ:RATE") { field(DESC, "Get high helium reading pulse rate") field(DTYP, "stream") field(SCAN, "5 second") field(INP, "@OxInstIPS_SCPI.protocol getLevelHeReadingRate $(PORT)") - field(ZRST, "Fast") - field(ZRVL, "0") - field(ZRSV, "NO_ALARM") - field(ONST, "Slow") - field(ONVL, "1") - field(ONSV, "NO_ALARM") + field(ZNAM, "Fast") + field(ONAM, "Slow") field(SIML, "$(P)SIM") - field(SIOL, "$(P)SIM:LVL:HE:REFILL:STOP") + field(SIOL, "$(P)SIM:LVL:HE:PULSE:READ:RATE") field(SDIS, "$(P)DISABLE") info(archive, "VAL") } record(bo, "$(P)LVL:HE:PULSE:READ:RATE:SP") { - field(ASG, "$(MANAGER_ASG)") field(DESC, "Set high helium reading pulse rate") field(DTYP, "stream") field(OUT, "@OxInstIPS_SCPI.protocol setLevelHeReadingRate $(PORT)") @@ -197,7 +178,7 @@ record(ao, "$(P)LVL:NIT:READ:INTERVAL:SP") { field(DTYP, "stream") field(EGU, "ms") field(OUT, "@OxInstIPS_SCPI.protocol setLevelNitReadInterval $(PORT)") - field(DRVH, "$(MAX_N2_READ_INTERVAL==5000)") + field(DRVH, "$(MAX_N2_READ_INTERVAL=5000)") field(DRVL, "$(MIN_N2_READ_INTERVAL=0)") field(SIML, "$(P)SIM") @@ -315,20 +296,6 @@ record(ao, "$(P)LVL:NIT:REFILL:STOP:SP") { info(archive, "VAL") } -record(mbbi, "$(P)LVL:NIT:REFILLING") { - field(DESC, "Is N2 refill in progress?") - field(DTYP, "stream") - field(SCAN, "5 second") - field(INP, "@OxInstIPS_SCPI.protocol getLevelNitRefilling $(PORT)") - field(ZRST, "No") - field(ZRVL, "0") - field(ZRSV, "NO_ALARM") - field(ONST, "Yes") - field(ONVL, "1") - field(ONSV, "NO_ALARM") - info(archive, "VAL") -} - record(ai, "$(P)LVL:NIT:LEVEL") { field(DESC, "Get nitrogen level") field(DTYP, "stream") diff --git a/IPS/IPS-IOC-01App/src/build.mak b/IPS/IPS-IOC-01App/src/build.mak index 848fac255..962a843ee 100644 --- a/IPS/IPS-IOC-01App/src/build.mak +++ b/IPS/IPS-IOC-01App/src/build.mak @@ -30,6 +30,7 @@ $(APPNAME)_DBD += stream.dbd $(APPNAME)_DBD += ReadASCII.dbd $(APPNAME)_DBD += FileList.dbd $(APPNAME)_DBD += cryomagnet.dbd +$(APPNAME)_DBD += OxInstIPS.dbd # Add all the support libraries needed by this IOC ## ISIS standard libraries ## @@ -48,6 +49,7 @@ $(APPNAME)_LIBS += calc sscan $(APPNAME)_LIBS += pcrecpp pcre libjson zlib $(APPNAME)_LIBS += efsw $(APPNAME)_LIBS += seq pv +$(APPNAME)_LIBS += OxInstIPS # FERMCHOP-IOC-01_registerRecordDeviceDriver.cpp derives from IPS-IOC-01.dbd $(APPNAME)_SRCS += $(APPNAME)_registerRecordDeviceDriver.cpp From d31cc8f63f0904c74d63a2388a0c019d530b5c7d Mon Sep 17 00:00:00 2001 From: Ian Gillingham Date: Thu, 31 Jul 2025 12:06:25 +0100 Subject: [PATCH 18/29] Added a substitutions file and associated template file to generate the discrete system alarm records. --- IPS/IPS-IOC-01App/Db/Makefile | 2 + IPS/IPS-IOC-01App/Db/ips_scpi.db | 134 -------------- IPS/IPS-IOC-01App/Db/scpi_system_alarms.db | 171 ++++++++++++++++++ .../scpi_system_alarms_discrete.substitutions | 51 ++++++ .../Db/scpi_system_alarms_discrete.template | 19 ++ IPS/iocBoot/iocIPS-IOC-01/st.cmd | 2 + 6 files changed, 245 insertions(+), 134 deletions(-) create mode 100644 IPS/IPS-IOC-01App/Db/scpi_system_alarms.db create mode 100644 IPS/IPS-IOC-01App/Db/scpi_system_alarms_discrete.substitutions create mode 100644 IPS/IPS-IOC-01App/Db/scpi_system_alarms_discrete.template diff --git a/IPS/IPS-IOC-01App/Db/Makefile b/IPS/IPS-IOC-01App/Db/Makefile index 0c4dba80c..a761d1bcd 100644 --- a/IPS/IPS-IOC-01App/Db/Makefile +++ b/IPS/IPS-IOC-01App/Db/Makefile @@ -13,6 +13,8 @@ include $(TOP)/configure/CONFIG DB += ips.db DB += ips_scpi.db DB += ips_scpi_levels.db +DB += scpi_system_alarms.db +DB += scpi_system_alarms_discrete.db #---------------------------------------------------- # If .db template is not named *.template add diff --git a/IPS/IPS-IOC-01App/Db/ips_scpi.db b/IPS/IPS-IOC-01App/Db/ips_scpi.db index 8194dd961..963c8effd 100644 --- a/IPS/IPS-IOC-01App/Db/ips_scpi.db +++ b/IPS/IPS-IOC-01App/Db/ips_scpi.db @@ -1151,140 +1151,6 @@ record(mbbi, "$(P)STS:SWEEPMODE:SWEEP") { info(archive, "VAL") } -# Poll system alarms: This record repeatedly sends the READ:SYS:ALRM command -# and the response is parsed by records dedicated to each board type with SCAN of "I/O Intr" -record(stringin, "$(P)STS:_POLLSYSTEM:ALARMS") { - field(DESC, "Poll system alarms") - field(DTYP, "stream") - field(SCAN, "5 second") - field(INP, "@OxInstIPS_SCPI.protocol getSysAlarms $(PORT)") - field(FLNK, "$(P)STS:_POLLSYSTEM:ALARMS_SUB") - - field(SIML, "$(P)SIM") - field(SIOL, "$(P)SIM:STS:_POLLSYSTEM:ALARMS") - field(SDIS, "$(P)DISABLE") -} - -record(aSub, "$(P)STS:_POLLSYSTEM:ALARMS_SUB") { - field(SNAM, "handle_system_alarm_status") - field(INPA, "$(P)STS:_POLLSYSTEM:ALARMS") - field(FTA, "STRING") - field(NOA, "1") - - field(OUTA, "$(P)STS:SYSTEM:ALARM:TBOARD PP") - field(OUTB, "$(P)STS:SYSTEM:ALARM:10TBOARD PP") - field(OUTC, "$(P)STS:SYSTEM:ALARM:LBOARD PP") - field(FTVA, "LONG") - field(NOVA, "1") - - info(archive, "A VALA") -} - -record(mbbi, "$(P)STS:SYSTEM:ALARM:TBOARD") { - field(DESC, "Temperature board alarm status") - field(DTYP, "Soft Channel") - field(SCAN, "Passive") - field(INP, "") - field(ZRST, "OK") - field(ZRVL, "0") - field(ZRSV, "NO_ALARM") - field(ONST, "Open Circuit") - field(ONVL, "1") - field(ONSV, "MAJOR") - field(TWST, "Short Circuit") - field(TWSV, "2") - field(TWSV, "MAJOR") - field(THST, "Calibration Error") - field(THVL, "3") - field(THSV, "MAJOR") - field(FRST, "Firmware Error") - field(FRVL, "4") - field(FRSV, "MAJOR") - field(FVST, "Board Not Configured") - field(FVVL, "5") - field(FVSV, "MAJOR") - - field(SIML, "$(P)SIM") - field(SIOL, "$(P)SIM:STS:SYSTEM:ALARM:TBOARD") - field(SDIS, "$(P)DISABLE") - - info(archive, "VAL") -} - -record(mbbi, "$(P)STS:SYSTEM:ALARM:10TBOARD") { - field(DESC, "Temperature board alarm status") - field(DTYP, "Soft Channel") - field(SCAN, "Passive") - field(VAL, "0") - field(INP, "") - field(ZRST, "OK") - field(ZRVL, "0") - field(ZRSV, "NO_ALARM") - field(ONST, "Open Circuit") - field(ONVL, "1") - field(ONSV, "MAJOR") - field(TWST, "Short Circuit") - field(TWSV, "2") - field(TWSV, "MAJOR") - field(THST, "Calibration Error") - field(THVL, "3") - field(THSV, "MAJOR") - field(FRST, "Firmware Error") - field(FRVL, "4") - field(FRSV, "MAJOR") - field(FVST, "Board Not Configured") - field(FVVL, "5") - field(FVSV, "MAJOR") - - field(SIML, "$(P)SIM") - field(SIOL, "$(P)SIM:STS:SYSTEM:ALARM:10TBOARD") - field(SDIS, "$(P)DISABLE") - - info(archive, "VAL") -} - -record(mbbi, "$(P)STS:SYSTEM:ALARM:LBOARD") { - field(DESC, "Level board alarm status") - field(DTYP, "Soft Channel") - field(SCAN, "Passive") - field(VAL, "0") - field(INP, "") - field(ZRST, "OK") - field(ZRVL, "0") - field(ZRSV, "NO_ALARM") - field(ONST, "Open Circuit") - field(ONVL, "1") - field(ONSV, "MAJOR") - field(TWST, "Short Circuit") - field(TWVL, "2") - field(TWSV, "MAJOR") - field(THST, "ADC Error") - field(THVL, "3") - field(THSV, "MAJOR") - field(FRST, "Over Demand") - field(FRVL, "4") - field(FRSV, "MAJOR") - field(FVST, "Over Temperature") - field(FVVL, "5") - field(FVSV, "MAJOR") - field(SXST, "Firmware Error") - field(SXVL, "6") - field(SXSV, "MAJOR") - field(SVST, "Board Not Configured") - field(SVVL, "7") - field(SVSV, "MAJOR") - field(EIST, "No Reserve") - field(EIVL, "8") - field(EISV, "MAJOR") - - field(SIML, "$(P)SIM") - field(SIOL, "$(P)SIM:STS:SYSTEM:ALARM:LBOARD") - field(SDIS, "$(P)DISABLE") - - info(archive, "VAL") -} - - # The temperature of the magnet MB1.T1 record(ai, "$(P)TEMP:MAGNET") { field(DESC, "Magnet temperature") diff --git a/IPS/IPS-IOC-01App/Db/scpi_system_alarms.db b/IPS/IPS-IOC-01App/Db/scpi_system_alarms.db new file mode 100644 index 000000000..0aab0d9a3 --- /dev/null +++ b/IPS/IPS-IOC-01App/Db/scpi_system_alarms.db @@ -0,0 +1,171 @@ +# This contains all the records which handle responses to the READ:SYS:ALRM command. +# The precise protocol was determined empirically by sending the command and observing the response +# directly from the instrument. +# Discrete records are generated for each board type and each alarm by the +# scpi_system_alarms_discrete.template and substitutions files. +# +# The base response is: READ:SYS:ALRM: which may (or may not) be followed by a board identifier, +# a tab character (9) an alarm string and a semicolon. +# +# In ABNF: +# response = "READ:SYS:ALRM:" *(error) +# error = board_id TAB error_message SEMICOLON +# board_id = 1*(ALPHA / DIGIT / ".") ; e.g. MB1.T1 +# error_message = 1*(ALPHA / DIGIT / ".") ; e.g. "Open circuit" +# TAB = %x09 ; tab character +# SEMICOLON = %x3B ; semicolon ";" +# +# The board identifiers are provided as macros: +# Macro Default +# BOARDID_MAG MB1.T1 +# BOARDID_10TMAG DB8.T1 +# BOARDID_PRESS DB5.P1 +# BOARDID_LEVEL DB1.L1 +# +# Poll system alarms: This record repeatedly sends the READ:SYS:ALRM command +# and the response is read as a string and parsed by the aSub record below. +# +record(stringin, "$(P)STS:_POLLSYSTEM:ALARMS") { + field(DESC, "Poll system alarms") + field(DTYP, "stream") + field(SCAN, "5 second") + field(INP, "@OxInstIPS_SCPI.protocol getSysAlarms $(PORT)") + field(FLNK, "$(P)STS:_POLLSYSTEM:ALARMS_SUB") + + field(SIML, "$(P)SIM") + field(SIOL, "$(P)SIM:STS:_POLLSYSTEM:ALARMS") + field(SDIS, "$(P)DISABLE") +} + +# This record is triggered by the stringin record above and parses the response. +# It extracts the board identifier and the alarm message, and writes them to the appropriate +# output fields. The output fields are then used by the mbbi and bi records below to set the +# alarm status for each board. +# +record(aSub, "$(P)STS:_POLLSYSTEM:ALARMS_SUB") { + field(SNAM, "handle_system_alarm_status") + field(INPA, "$(P)STS:_POLLSYSTEM:ALARMS NPP NMS") + field(FTA, "STRING") + field(NOA, "1") + + field(OUTA, "$(P)STS:SYSTEM:ALARM:TBOARD PP") + field(OUTB, "$(P)STS:SYSTEM:ALARM:10TBOARD PP") + field(OUTC, "$(P)STS:SYSTEM:ALARM:LBOARD PP") + field(OUTD, "$(P)STS:SYSTEM:ALARM:PBOARD PP") + field(FTVA, "LONG") + field(FTVB, "LONG") + field(FTVC, "LONG") + field(FTVD, "LONG") + field(NOVA, "1") + field(NOVB, "1") + field(NOVC, "1") + field(NOVD, "1") + + info(archive, "A VALA") +} + +### =============== Temperature board alarm status =============== ### +# Bit set Definition +# 0 Open Circuit +# 1 Short Circuit +# 2 Calibration Error +# 3 Firmware Error +# 4 Board Not Configured +# +record(mbbiDirect, "$(P)STS:SYSTEM:ALARM:TBOARD") { + field(DESC, "Temperature board alarm status") + field(DTYP, "stream") + field(INP, "") + field(NOBT, "32") + field(SCAN, "Passive") + + field(SIML, "$(P)SIM") + field(SIOL, "$(P)SIM:STS:SYSTEM:ALARM:TBOARD") + field(SDIS, "$(P)DISABLE") +} + + +### =============== 10 Temperature board alarm status =============== ### +# Bit set Definition +# 0 Open Circuit +# 1 Short Circuit +# 2 Calibration Error +# 3 Firmware Error +# 4 Board Not Configured +# +record(mbbiDirect, "$(P)STS:SYSTEM:ALARM:10TBOARD") { + field(DESC, "10T Temperature board alarm status") + field(DTYP, "stream") + field(INP, "") + field(NOBT, "32") + field(SCAN, "Passive") + + field(SIML, "$(P)SIM") + field(SIOL, "$(P)SIM:STS:SYSTEM:ALARM:10TBOARD") + field(SDIS, "$(P)DISABLE") +} + + +### =============== Levels board alarm status =============== ### +# Bit set Definition +# 0 Open Circuit +# 1 Short Circuit +# 2 ADC Error +# 3 Over demand +# 4 Over temperature +# 5 Firmware Error +# 6 Board Not Configured +# 7 No Reserve +# +record(mbbiDirect, "$(P)STS:SYSTEM:ALARM:LBOARD") { + field(DESC, "Levels board alarm status") + field(DTYP, "stream") + field(INP, "") + field(NOBT, "32") + field(SCAN, "Passive") + + field(SIML, "$(P)SIM") + field(SIOL, "$(P)SIM:STS:SYSTEM:ALARM:LBOARD") + field(SDIS, "$(P)DISABLE") +} + + +### =============== Pressure board alarm status =============== ### +# Bit set Definition +# 0 Open Circuit +# 1 Short Circuit +# 2 Calibration Error +# 3 Firmware Error +# 4 Board Not Configured +# 5 Over current +# 6 Current leakage +# 7 Power on fail +# 8 Checksum fail +# 9 Clock fail +# 10 ADC fail +# 11 Mains fail +# 12 Reference fail +# 13 +12V fail +# 14 -12V fail +# 15 +8V fail +# 16 -8V fail +# 17 Amp gain error +# 18 Amp offset error +# 19 ADC offset error +# 20 ADC PGA error +# 21 ADC XTAL error +# 22 Excitation + error +# 23 Excitation - error +# +record(mbbiDirect, "$(P)STS:SYSTEM:ALARM:PBOARD") { + field(DESC, "Pressure board alarm status") + field(DTYP, "stream") + field(INP, "") + field(NOBT, "32") + field(SCAN, "Passive") + + field(SIML, "$(P)SIM") + field(SIOL, "$(P)SIM:STS:SYSTEM:ALARM:PBOARD") + field(SDIS, "$(P)DISABLE") +} + diff --git a/IPS/IPS-IOC-01App/Db/scpi_system_alarms_discrete.substitutions b/IPS/IPS-IOC-01App/Db/scpi_system_alarms_discrete.substitutions new file mode 100644 index 000000000..8312c6ffe --- /dev/null +++ b/IPS/IPS-IOC-01App/Db/scpi_system_alarms_discrete.substitutions @@ -0,0 +1,51 @@ +file scpi_system_alarms_discrete.template { + +pattern {P, ALARM_NAME, ALARM_DESC, ALARM_INP} +{"\$(P)", "TBOARD:OPENCIRCUIT", "Temperature board Open Circuit", "TBOARD.B0"} +{"\$(P)", "TBOARD:SHORTCIRCUIT", "Temperature board Short Circuit", "TBOARD.B1"} +{"\$(P)", "TBOARD:CALIBERR", "Temperature board Calibn error", "TBOARD.B2"} +{"\$(P)", "TBOARD:FWERR", "Temperature board fw error", "TBOARD.B3"} +{"\$(P)", "TBOARD:NOTCONFIGD", "Temperature board not configd", "TBOARD.B4"} + +{"\$(P)", "10TBOARD:OPENCIRCUIT", "Temperature board Open Circuit", "10TBOARD.B0"} +{"\$(P)", "10TBOARD:SHORTCIRCUIT", "Temperature board Short Circuit", "10TBOARD.B1"} +{"\$(P)", "10TBOARD:CALIBERR", "Temperature board Calibn error", "10TBOARD.B2"} +{"\$(P)", "10TBOARD:FWERR", "Temperature board fw error", "10TBOARD.B3"} +{"\$(P)", "10TBOARD:NOTCONFIGD", "Temperature board not configd", "10TBOARD.B4"} + +{"\$(P)", "LBOARD:OPENCIRCUIT", "Levels board Open Circuit", "LBOARD.B0"} +{"\$(P)", "LBOARD:SHORTCIRCUIT", "Levels board Short Circuit", "LBOARD.B1"} +{"\$(P)", "LBOARD:ADCERR", "Levels board ADC error", "LBOARD.B2"} +{"\$(P)", "LBOARD:OVERDEMAND", "Levels board over demand", "LBOARD.B3"} +{"\$(P)", "LBOARD:OVERTEMP", "Levels board over temp", "LBOARD.B4"} +{"\$(P)", "LBOARD:FWERROR", "Levels board fw error", "LBOARD.B5"} +{"\$(P)", "LBOARD:NOTCONFIGD", "Levels board not confgd", "LBOARD.B6"} +{"\$(P)", "LBOARD:NORESERVE", "Levels board no reserve", "LBOARD.B7"} +{"\$(P)", "LBOARD:NORESERVE", "Levels board no reserve", "LBOARD.B7"} + +{"\$(P)", "PBOARD:OPENCIRCUIT", "Pressure board Open Circuit", "PBOARD.B0"} +{"\$(P)", "PBOARD:SHORTCIRCUIT", "Pressure board Short Circuit", "PBOARD.B1"} +{"\$(P)", "PBOARD:CALIBERR", "Pressure board calib error", "PBOARD.B2"} +{"\$(P)", "PBOARD:FWERR", "Pressure board fw error", "PBOARD.B3"} +{"\$(P)", "PBOARD:NOTCONFIGD", "Pressure board not confgd", "PBOARD.B4"} +{"\$(P)", "PBOARD:OVERCURRENT", "Pressure board over current", "PBOARD.B5"} +{"\$(P)", "PBOARD:CURRENTLEAK", "Pressure board current leak", "PBOARD.B6"} +{"\$(P)", "PBOARD:PWONFAIL", "Pressure board power on fail", "PBOARD.B7"} +{"\$(P)", "PBOARD:CHKSUMERR", "Pressure board chksum error", "PBOARD.B8"} +{"\$(P)", "PBOARD:CLKFAIL", "Pressure board clk fail", "PBOARD.B9"} +{"\$(P)", "PBOARD:ADCFAIL", "Pressure board ADC fail", "PBOARD.BA"} +{"\$(P)", "PBOARD:MAINSFAIL", "Pressure board mains fail", "PBOARD.BB"} +{"\$(P)", "PBOARD:REFSFAIL", "Pressure board ref fail", "PBOARD.BC"} +{"\$(P)", "PBOARD:PLUS12VFAIL", "Pressure board +12V fail", "PBOARD.BD"} +{"\$(P)", "PBOARD:MINUS12VFAIL", "Pressure board -12V fail", "PBOARD.BE"} +{"\$(P)", "PBOARD:PLUS8VFAIL", "Pressure board +8V fail", "PBOARD.BF"} +{"\$(P)", "PBOARD:MINUS8VFAIL", "Pressure board -9V fail", "PBOARD.B10"} +{"\$(P)", "PBOARD:AMPGAINERR", "Pressure board amp gain err", "PBOARD.B11"} +{"\$(P)", "PBOARD:AMPOFFSETERR", "Pressure board amp offset err", "PBOARD.B12"} +{"\$(P)", "PBOARD:ADCPGAERR", "Pressure board ADC PGA offset err", "PBOARD.B14"} +{"\$(P)", "PBOARD:ADCXTALERR", "Pressure board ADC XTAL offset err", "PBOARD.B15"} +{"\$(P)", "PBOARD:PLUSEXCITEERR", "Pressure board excitation + error", "PBOARD.B16"} +{"\$(P)", "PBOARD:MINUSEXCITEERR", "Pressure board excitation - error", "PBOARD.B17"} +{"\$(P)", "PBOARD:MINUSEXCITEERR", "Pressure board excitation - error", "PBOARD.B17"} + +} diff --git a/IPS/IPS-IOC-01App/Db/scpi_system_alarms_discrete.template b/IPS/IPS-IOC-01App/Db/scpi_system_alarms_discrete.template new file mode 100644 index 000000000..d5abe13bf --- /dev/null +++ b/IPS/IPS-IOC-01App/Db/scpi_system_alarms_discrete.template @@ -0,0 +1,19 @@ +# SCPI System Alarms Discrete Template +# This file defines the discrete alarms for the SCPI system, which are derived from the +# relevant mbbidirect records +# +record(bi, "$(P)STS:SYSTEM:ALARM:$(ALARM_NAME)") { + field(DESC, "$(ALARM_DESC)") + field(DTYP, "Soft Channel") + field(SCAN, "Passive") + field(INP, "$(P)STS:SYSTEM:ALARM:$(ALARM_INP) CP MS") + field(ZNAM, "No") + field(ONAM, "Yes") + field(ZSV, "NO_ALARM") + field(OSV, "MAJOR") + + field(SIML, "$(P)SIM") + field(SIOL, "$(P)SIM:STS:SYSTEM:ALARM:$(ALARM_NAME)") + field(SDIS, "$(P)DISABLE") + info(archive, "VAL") +} diff --git a/IPS/iocBoot/iocIPS-IOC-01/st.cmd b/IPS/iocBoot/iocIPS-IOC-01/st.cmd index d741f299d..4cc37e36e 100644 --- a/IPS/iocBoot/iocIPS-IOC-01/st.cmd +++ b/IPS/iocBoot/iocIPS-IOC-01/st.cmd @@ -73,6 +73,8 @@ $(IFSTREAMPROTOCOL_SCPI) epicsEnvSet "PROTOCOLFILE" "OxInstIPS_SCPI.protocol" ## Load our record instances dbLoadRecords("db/$(DBFILE)","PVPREFIX=$(MYPVPREFIX),P=$(P),RECSIM=$(RECSIM=0),DISABLE=$(DISABLE=0),PORT=$(DEVICE),MAX_FIELD=$(MAX_FIELD=7.0),MAX_SWEEP_RATE=$(MAX_SWEEP_RATE=1.0),STABILITY_VOLTAGE=$(STABILITY_VOLTAGE=0.1),HEATER_WAITTIME=$(HEATER_WAITTIME=60),MANAGER_ASG=$(MANAGER_ASG=MANAGER)") $(IFSTREAMPROTOCOL_SCPI) dbLoadRecords("db/ips_scpi_levels.db","PVPREFIX=$(MYPVPREFIX),P=$(P),RECSIM=$(RECSIM=0),DISABLE=$(DISABLE=0),PORT=$(DEVICE),MIN_N2_FREQ=$(MIN_N2_FREQ=5000),MAX_N2_FREQ=$(MAX_N2_FREQ=65000),MANAGER_ASG=$(MANAGER_ASG=MANAGER)") +$(IFSTREAMPROTOCOL_SCPI) dbLoadRecords("db/scpi_system_alarms.db","PVPREFIX=$(MYPVPREFIX),P=$(P),RECSIM=$(RECSIM=0),DISABLE=$(DISABLE=0),PORT=$(DEVICE),BOARDID_MAG=$(BOARDID_MAG=MB1.T1),BOARDID_10TMAG=$(BOARDID_10TMAG=DB8.T1),BOARDID_PRESS=$(BOARDID_PRESS=DB5.P1),BOARDID_LEVEL=$(BOARDID_LEVEL=DB1.L1),MANAGER_ASG=$(MANAGER_ASG=MANAGER)") +$(IFSTREAMPROTOCOL_SCPI) dbLoadRecords("db/scpi_system_alarms_discrete.db","PVPREFIX=$(MYPVPREFIX),P=$(P),RECSIM=$(RECSIM=0),DISABLE=$(DISABLE=0),PORT=$(DEVICE),MANAGER_ASG=$(MANAGER_ASG=MANAGER)") ##ISIS## Stuff that needs to be done after all records are loaded but before iocInit is called < $(IOCSTARTUP)/preiocinit.cmd From ebfcc85431569c72f796fdefbfb0137ed9c05d32 Mon Sep 17 00:00:00 2001 From: Ian Gillingham Date: Tue, 12 Aug 2025 09:03:07 +0100 Subject: [PATCH 19/29] Removed deprecated record SWEEPMODE:PARAMS:SP --- IPS/IPS-IOC-01App/Db/ips_scpi.db | 37 -------------------------------- 1 file changed, 37 deletions(-) diff --git a/IPS/IPS-IOC-01App/Db/ips_scpi.db b/IPS/IPS-IOC-01App/Db/ips_scpi.db index 963c8effd..76346722d 100644 --- a/IPS/IPS-IOC-01App/Db/ips_scpi.db +++ b/IPS/IPS-IOC-01App/Db/ips_scpi.db @@ -1079,43 +1079,6 @@ record(mbbi, "$(P)SWEEPMODE:PARAMS") { info(archive, "VAL") } -# To set the sweep and display mode - its a bit confusing as there -# are duplicates, but we do not present this choice to the user. -# -record(mbbo, "$(P)SWEEPMODE:PARAMS:SP") { - field(DESC, "Set sweep and display mode.") - field(DTYP, "stream") - field(SCAN, "Passive") - field(ZRST, "Amps Fast") - field(ZRVL, "0") - field(ONST, "Tesla Fast") - field(ONVL, "1") - field(TWST, "Amps Fast") - field(TWVL, "2") - field(THST, "Tesla Fast") - field(THVL, "3") - field(FRST, "Amps Slow") - field(FRVL, "4") - field(FVST, "Tesla Slow") - field(FVVL, "5") - field(SXST, "Amps Slow") - field(SXVL, "6") - field(SVST, "Tesla Slow") - field(SVVL, "7") - field(EIST, "Amps Unaffected") - field(EIVL, "8") - field(NIST, "Tesla Unaffected") - field(NIVL, "9") - # field(OUT, "@OxInstIPS.protocol setMode $(PORT)") - - field(VAL, "3") - field(PINI, "YES") - - field(SIML, "$(P)SIM") - field(SIOL, "$(P)SIM:SWEEPMODE:PARAMS:SP") - field(SDIS, "$(P)DISABLE") -} - # In the legacy version, this used to be the readback from n of Mmn part of Examine command return. # 0 output constant, 1, 2, 3 output changing # The SCPI protocol doesn't directly offer this, so it has to be derived via the ACTIVITY record (DEV:GRPZ:PSU:ACTN) From 1bf774b6e53515aafc65a21954143b084812e616 Mon Sep 17 00:00:00 2001 From: Ian Gillingham Date: Tue, 12 Aug 2025 09:05:27 +0100 Subject: [PATCH 20/29] Added discrete records for system alarms and corresponding macros in st.cmd --- IPS/IPS-IOC-01App/Db/scpi_system_alarms.db | 81 ++++++++++++++++--- .../scpi_system_alarms_discrete.substitutions | 2 - IPS/iocBoot/iocIPS-IOC-01/st.cmd | 6 +- 3 files changed, 75 insertions(+), 14 deletions(-) diff --git a/IPS/IPS-IOC-01App/Db/scpi_system_alarms.db b/IPS/IPS-IOC-01App/Db/scpi_system_alarms.db index 0aab0d9a3..0ef57130e 100644 --- a/IPS/IPS-IOC-01App/Db/scpi_system_alarms.db +++ b/IPS/IPS-IOC-01App/Db/scpi_system_alarms.db @@ -37,16 +37,75 @@ record(stringin, "$(P)STS:_POLLSYSTEM:ALARMS") { field(SDIS, "$(P)DISABLE") } +# The following stringout records are used to provide the board identifiers +record(stringout, "$(P)STS:SYSTEM:ALARMS:_NAME:TBOARD") { + field(DESC, "Temperature board UID name") + field(DTYP, "Soft Channel") + field(SCAN, "Passive") + field(PINI, "YES") + field(VAL, "$(BOARDID_MAG)") + field(OUT, "") + field(SIML, "$(P)SIM") + field(SIOL, "$(P)SIM:STS:SYSTEM:ALARMS:_NAME:TBOARD") + field(SDIS, "$(P)DISABLE") +} +record(stringout, "$(P)STS:SYSTEM:ALARMS:_NAME:10TBOARD") { + field(DESC, "Temperature 10T board UID name") + field(DTYP, "Soft Channel") + field(SCAN, "Passive") + field(PINI, "YES") + field(VAL, "$(BOARDID_10TMAG)") + field(OUT, "") + field(SIML, "$(P)SIM") + field(SIOL, "$(P)SIM:STS:SYSTEM:ALARMS:_NAME:10TBOARD") + field(SDIS, "$(P)DISABLE") +} +record(stringout, "$(P)STS:SYSTEM:ALARMS:_NAME:LBOARD") { + field(DESC, "Level board UID name") + field(DTYP, "Soft Channel") + field(SCAN, "Passive") + field(PINI, "YES") + field(VAL, "$(BOARDID_LEVEL)") + field(OUT, "") + field(SIML, "$(P)SIM") + field(SIOL, "$(P)SIM:STS:SYSTEM:ALARMS:_NAME:LTBOARD") + field(SDIS, "$(P)DISABLE") +} +record(stringout, "$(P)STS:SYSTEM:ALARMS:_NAME:PBOARD") { + field(DESC, "Pressure board UID name") + field(DTYP, "Soft Channel") + field(SCAN, "Passive") + field(PINI, "YES") + field(VAL, "$(BOARDID_PRESS)") + field(OUT, "") + field(SIML, "$(P)SIM") + field(SIOL, "$(P)SIM:STS:SYSTEM:ALARMS:_NAME:PBOARD") + field(SDIS, "$(P)DISABLE") +} + # This record is triggered by the stringin record above and parses the response. # It extracts the board identifier and the alarm message, and writes them to the appropriate # output fields. The output fields are then used by the mbbi and bi records below to set the # alarm status for each board. +# Board identifiers are provided as macros and passed to the aSub as input fields B-E. # record(aSub, "$(P)STS:_POLLSYSTEM:ALARMS_SUB") { field(SNAM, "handle_system_alarm_status") field(INPA, "$(P)STS:_POLLSYSTEM:ALARMS NPP NMS") +# field(INPB, "$(P):STS:SYSTEM:ALARMS:_NAME:TBOARD") +# field(INPC, "$(P):STS:SYSTEM:ALARMS:_NAME:10TBOARD") +# field(INPD, "$(P):STS:SYSTEM:ALARMS:_NAME:LBOARD") +# field(INPE, "$(P):STS:SYSTEM:ALARMS:_NAME:PBOARD") field(FTA, "STRING") + field(FTB, "STRING") + field(FTC, "STRING") + field(FTD, "STRING") + field(FTE, "STRING") field(NOA, "1") + field(NOB, "1") + field(NOC, "1") + field(NOD, "1") + field(NOE, "1") field(OUTA, "$(P)STS:SYSTEM:ALARM:TBOARD PP") field(OUTB, "$(P)STS:SYSTEM:ALARM:10TBOARD PP") @@ -60,8 +119,6 @@ record(aSub, "$(P)STS:_POLLSYSTEM:ALARMS_SUB") { field(NOVB, "1") field(NOVC, "1") field(NOVD, "1") - - info(archive, "A VALA") } ### =============== Temperature board alarm status =============== ### @@ -74,8 +131,9 @@ record(aSub, "$(P)STS:_POLLSYSTEM:ALARMS_SUB") { # record(mbbiDirect, "$(P)STS:SYSTEM:ALARM:TBOARD") { field(DESC, "Temperature board alarm status") - field(DTYP, "stream") - field(INP, "") + field(DTYP, "Soft Channel") + field(INP, "0") + field(PINI, "YES") field(NOBT, "32") field(SCAN, "Passive") @@ -95,8 +153,9 @@ record(mbbiDirect, "$(P)STS:SYSTEM:ALARM:TBOARD") { # record(mbbiDirect, "$(P)STS:SYSTEM:ALARM:10TBOARD") { field(DESC, "10T Temperature board alarm status") - field(DTYP, "stream") - field(INP, "") + field(DTYP, "Soft Channel") + field(INP, "0") + field(PINI, "YES") field(NOBT, "32") field(SCAN, "Passive") @@ -119,8 +178,9 @@ record(mbbiDirect, "$(P)STS:SYSTEM:ALARM:10TBOARD") { # record(mbbiDirect, "$(P)STS:SYSTEM:ALARM:LBOARD") { field(DESC, "Levels board alarm status") - field(DTYP, "stream") - field(INP, "") + field(DTYP, "Soft Channel") + field(INP, "0") + field(PINI, "YES") field(NOBT, "32") field(SCAN, "Passive") @@ -159,8 +219,9 @@ record(mbbiDirect, "$(P)STS:SYSTEM:ALARM:LBOARD") { # record(mbbiDirect, "$(P)STS:SYSTEM:ALARM:PBOARD") { field(DESC, "Pressure board alarm status") - field(DTYP, "stream") - field(INP, "") + field(DTYP, "Soft Channel") + field(INP, "0") + field(PINI, "YES") field(NOBT, "32") field(SCAN, "Passive") diff --git a/IPS/IPS-IOC-01App/Db/scpi_system_alarms_discrete.substitutions b/IPS/IPS-IOC-01App/Db/scpi_system_alarms_discrete.substitutions index 8312c6ffe..33dd30bfc 100644 --- a/IPS/IPS-IOC-01App/Db/scpi_system_alarms_discrete.substitutions +++ b/IPS/IPS-IOC-01App/Db/scpi_system_alarms_discrete.substitutions @@ -46,6 +46,4 @@ pattern {P, ALARM_NAME, ALARM_DESC, ALARM_INP} {"\$(P)", "PBOARD:ADCXTALERR", "Pressure board ADC XTAL offset err", "PBOARD.B15"} {"\$(P)", "PBOARD:PLUSEXCITEERR", "Pressure board excitation + error", "PBOARD.B16"} {"\$(P)", "PBOARD:MINUSEXCITEERR", "Pressure board excitation - error", "PBOARD.B17"} -{"\$(P)", "PBOARD:MINUSEXCITEERR", "Pressure board excitation - error", "PBOARD.B17"} - } diff --git a/IPS/iocBoot/iocIPS-IOC-01/st.cmd b/IPS/iocBoot/iocIPS-IOC-01/st.cmd index 4cc37e36e..8c5aa80de 100644 --- a/IPS/iocBoot/iocIPS-IOC-01/st.cmd +++ b/IPS/iocBoot/iocIPS-IOC-01/st.cmd @@ -43,8 +43,8 @@ $(IFNOTDEVSIM) $(IFNOTRECSIM) asynSetOption("L0",0,"ixon","N") $(IFNOTDEVSIM) $(IFNOTRECSIM) asynSetOption("L0",0,"ixoff","N") # Uncomment these for StreamDevice debugging -asynSetTraceMask("L0", -1, 0x9) -asynSetTraceIOMask("L0", -1, 0x2) +#asynSetTraceMask("L0", -1, 0x9) +#asynSetTraceIOMask("L0", -1, 0x2) ## Load record instances @@ -53,6 +53,8 @@ asynSetTraceIOMask("L0", -1, 0x2) epicsEnvSet("P", "$(MYPVPREFIX)$(IOCNAME):") +msgBox "Hello" + # The STREAMPROTOCOL env var should be set to either "LEGACY" (default) or "SCPI" # Set the database and protocol file names accordingly stringiftest("STREAMPROTOCOL_SCPI", "$(STREAMPROTOCOL=)", 4, "SCPI") From 7e8a32a8962af54bce3078d9061099d2010f2ee3 Mon Sep 17 00:00:00 2001 From: Ian Gillingham Date: Wed, 13 Aug 2025 08:56:08 +0100 Subject: [PATCH 21/29] Converted STS:_POLLSYSTEM:ALARMS_SUB to waveform records, as lengthy alarm messages were being truncated by stringin type. --- IPS/IPS-IOC-01App/Db/scpi_system_alarms.db | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/IPS/IPS-IOC-01App/Db/scpi_system_alarms.db b/IPS/IPS-IOC-01App/Db/scpi_system_alarms.db index 0ef57130e..e125633fd 100644 --- a/IPS/IPS-IOC-01App/Db/scpi_system_alarms.db +++ b/IPS/IPS-IOC-01App/Db/scpi_system_alarms.db @@ -25,9 +25,11 @@ # Poll system alarms: This record repeatedly sends the READ:SYS:ALRM command # and the response is read as a string and parsed by the aSub record below. # -record(stringin, "$(P)STS:_POLLSYSTEM:ALARMS") { +record(waveform, "$(P)STS:_POLLSYSTEM:ALARMS") { field(DESC, "Poll system alarms") field(DTYP, "stream") + field(FTVL, "CHAR") + field(NELM, "1000") # Adjust size as needed field(SCAN, "5 second") field(INP, "@OxInstIPS_SCPI.protocol getSysAlarms $(PORT)") field(FLNK, "$(P)STS:_POLLSYSTEM:ALARMS_SUB") @@ -96,12 +98,12 @@ record(aSub, "$(P)STS:_POLLSYSTEM:ALARMS_SUB") { # field(INPC, "$(P):STS:SYSTEM:ALARMS:_NAME:10TBOARD") # field(INPD, "$(P):STS:SYSTEM:ALARMS:_NAME:LBOARD") # field(INPE, "$(P):STS:SYSTEM:ALARMS:_NAME:PBOARD") - field(FTA, "STRING") + field(FTA, "CHAR") field(FTB, "STRING") field(FTC, "STRING") field(FTD, "STRING") field(FTE, "STRING") - field(NOA, "1") + field(NOA, "1000") field(NOB, "1") field(NOC, "1") field(NOD, "1") From 90ed1653926023c1572fd13a1af4a9d78f02a62f Mon Sep 17 00:00:00 2001 From: Ian Gillingham Date: Tue, 19 Aug 2025 13:20:02 +0100 Subject: [PATCH 22/29] st.cmd: Removed MsgBox call as no longer in debug phase on IOC start up. --- IPS/iocBoot/iocIPS-IOC-01/st.cmd | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/IPS/iocBoot/iocIPS-IOC-01/st.cmd b/IPS/iocBoot/iocIPS-IOC-01/st.cmd index 8c5aa80de..e9df65ab8 100644 --- a/IPS/iocBoot/iocIPS-IOC-01/st.cmd +++ b/IPS/iocBoot/iocIPS-IOC-01/st.cmd @@ -53,7 +53,8 @@ $(IFNOTDEVSIM) $(IFNOTRECSIM) asynSetOption("L0",0,"ixoff","N") epicsEnvSet("P", "$(MYPVPREFIX)$(IOCNAME):") -msgBox "Hello" +## Useful for debugging - giving a pause to allow the user to attach a debugger +## msgBox "Hello" # The STREAMPROTOCOL env var should be set to either "LEGACY" (default) or "SCPI" # Set the database and protocol file names accordingly From 7db187ef1dd6f8fd636557521f633f2dc390e3e9 Mon Sep 17 00:00:00 2001 From: Ian Gillingham Date: Thu, 21 Aug 2025 14:53:08 +0100 Subject: [PATCH 23/29] State machine cryomagnet.st copied and modified for SCPI mode, where SWEEPMODE:SP PV does not exist. It was clearer to implement a separate state machine than to have lots of complex conditionals in one file --- IPS/IPS-IOC-01App/src/build.mak | 1 + IPS/IPS-IOC-01App/src/cryomagnet.dbd | 1 + IPS/IPS-IOC-01App/src/cryomagnet.st | 2 +- IPS/IPS-IOC-01App/src/cryomagnet_SCPI.st | 300 +++++++++++++++++++++++ IPS/iocBoot/iocIPS-IOC-01/st.cmd | 3 +- 5 files changed, 305 insertions(+), 2 deletions(-) create mode 100644 IPS/IPS-IOC-01App/src/cryomagnet_SCPI.st diff --git a/IPS/IPS-IOC-01App/src/build.mak b/IPS/IPS-IOC-01App/src/build.mak index 962a843ee..a35e5fd38 100644 --- a/IPS/IPS-IOC-01App/src/build.mak +++ b/IPS/IPS-IOC-01App/src/build.mak @@ -54,6 +54,7 @@ $(APPNAME)_LIBS += OxInstIPS # FERMCHOP-IOC-01_registerRecordDeviceDriver.cpp derives from IPS-IOC-01.dbd $(APPNAME)_SRCS += $(APPNAME)_registerRecordDeviceDriver.cpp $(APPNAME)_SRCS += cryomagnet.st +$(APPNAME)_SRCS += cryomagnet_SCPI.st # Build the main IOC entry point on workstation OSs. $(APPNAME)_SRCS_DEFAULT += $(APPNAME)Main.cpp diff --git a/IPS/IPS-IOC-01App/src/cryomagnet.dbd b/IPS/IPS-IOC-01App/src/cryomagnet.dbd index 9d633eec7..c45e15b16 100644 --- a/IPS/IPS-IOC-01App/src/cryomagnet.dbd +++ b/IPS/IPS-IOC-01App/src/cryomagnet.dbd @@ -1 +1,2 @@ registrar(cryomagnetRegistrar) +registrar(cryomagnet_SCPIRegistrar) diff --git a/IPS/IPS-IOC-01App/src/cryomagnet.st b/IPS/IPS-IOC-01App/src/cryomagnet.st index 615af4866..7e1acf35a 100644 --- a/IPS/IPS-IOC-01App/src/cryomagnet.st +++ b/IPS/IPS-IOC-01App/src/cryomagnet.st @@ -127,7 +127,7 @@ ss cryomagnet PVPUT(activity_sp, ACTIVITY_TO_SP); epicsThreadSleep(1.0); PVPUT(sweepmode_sp, SWEEP_MODE); - } + } when( within_tolerance(field_setpoint_readback, magnet_field, field_tolerance) diff --git a/IPS/IPS-IOC-01App/src/cryomagnet_SCPI.st b/IPS/IPS-IOC-01App/src/cryomagnet_SCPI.st new file mode 100644 index 000000000..c3a09abca --- /dev/null +++ b/IPS/IPS-IOC-01App/src/cryomagnet_SCPI.st @@ -0,0 +1,300 @@ +program cryomagnet_SCPI("FIELD,FIELD_SETPOINT,FIELD_SETPOINT_ALARM,FIELD_SETPOINT_RAW,FIELD_SETPOINT_READBACK,PERSISTENT,MAGNET_FIELD,HEATER_STATUS,HEATER_STATUS_SP,HEATER_WAIT_TIME,ACTIVITY,ACTIVITY_SP,SWEEPMODE,SUPPLYVOLTAGE_STABLE,SWEEP_ACTIVE,STATEMACHINE,HEATER_ONTIME_OK") + +#include "ibexSeqPVmacros.h" +%% #include + +/* Turn on run-time debug messages */ +option +d; + +/* Make code reentrant. This is needed to run more than one instance of this program. */ +option +r; + +/* Field */ +PV(double, field_setpoint, "{FIELD_SETPOINT}", Monitor); +PV(int, field_setpoint_alarm, "{FIELD_SETPOINT_ALARM}", Monitor); +PV(double, field_setpoint_readback, "{FIELD_SETPOINT_READBACK}", Monitor); +PV(double, field_setpoint_raw, "{FIELD_SETPOINT_RAW}", Monitor); + +PV(double, psu_field, "{FIELD}", Monitor); +PV(double, magnet_field, "{MAGNET_FIELD}", Monitor); + +PV(int, persistent, "{PERSISTENT}", Monitor); + +PV(int, heater, "{HEATER_STATUS}", Monitor); +PV(int, heater_sp, "{HEATER_STATUS_SP}", Monitor); + +PV(int, activity, "{ACTIVITY}", Monitor); +PV(int, activity_sp, "{ACTIVITY_SP}", Monitor); + +PV(int, sweepmode, "{SWEEPMODE}", Monitor); + +PV(double, heater_wait_time, "{HEATER_WAIT_TIME}", Monitor); + +PV(int, supplyvoltage_stable, "{SUPPLYVOLTAGE_STABLE}", Monitor); + +PV(int, sweep_active, "{SWEEP_ACTIVE}", Monitor); + +PV(int, statemachine_pv, "{STATEMACHINE}", NoMon); + +PV(int, heater_ontime_ok, "{HEATER_ONTIME_OK}", Monitor); + + +/* If fields are the same within this tolerance, treat as the same */ +double field_tolerance = 0.0001; + +int ACTIVITY_HOLD = 0; +int ACTIVITY_TO_SP = 1; +int ACTIVITY_TO_ZERO = 2; + +/* The device varies which one it sends back but they both mean the same... */ +int SWEEP_MODE = 3; +int SWEEP_MODE_ALT = 1; + +%{ +void print_transition_scpi(char* old, char* new) { + printf("cryomagnet_SCPI.st: Moving from state %s to %s.\n", old, new); +} + +int within_tolerance_scpi(double a, double b, double tolerance) { + return fabs(a - b) < tolerance; +} +}% + +/* + * + * Documentation and further information about this state machine is available at https://github.com/ISISComputingGroup/ibex_developers_manual/wiki/OxfordInstrumentsIPS + * + */ +ss cryomagnet_SCPI +{ + + state initial + { + entry { + PVPUT(statemachine_pv, 0); + epicsThreadSleep(1.0); + } + + /* Dont do anything at all until the field setpoint is set to something & UDF_ALARM goes away. */ + when(field_setpoint_alarm == 0) { + print_transition_scpi("initial", "at_field"); + } state at_field + } + + state at_field + { + entry { + PVPUT(statemachine_pv, 1); + epicsThreadSleep(1.0); + } + + /* Heater is OFF, so in superconducting/persistent mode. */ + when( + !within_tolerance_scpi(field_setpoint, field_setpoint_readback, field_tolerance) + && field_setpoint_alarm == 0 + && (heater == 0 || heater == 2) + ) + { + print_transition_scpi("at_field", "set_psu_to_match_magnet"); + } state set_psu_to_match_magnet + + /* Heater is ON, so in conventional/non-persistent mode. */ + when( + !within_tolerance_scpi(field_setpoint, field_setpoint_readback, field_tolerance) + && field_setpoint_alarm == 0 + && heater == 1 + ) + { + print_transition_scpi("at_field", "set_psu_output"); + } state set_psu_output + } + + state set_psu_to_match_magnet + { + + /* Execute entry and exit blocks even if the next state is the same as the current state */ + option -e; + option -x; + + entry + { + PVPUT(statemachine_pv, 2); + epicsThreadSleep(1.0); + printf("Setting raw field setpoint to %f\n", magnet_field); + PVPUT(field_setpoint_raw, magnet_field); + epicsThreadSleep(1.0); + PVPUT(activity_sp, ACTIVITY_TO_SP); + epicsThreadSleep(1.0); + } + + when( + within_tolerance_scpi(field_setpoint_readback, magnet_field, field_tolerance) + && within_tolerance_scpi(psu_field, magnet_field, field_tolerance) + && ((sweepmode == SWEEP_MODE) || (sweepmode == SWEEP_MODE_ALT)) + && (sweep_active == 0) + ) + { + print_transition_scpi("set_psu_to_match_magnet", "wait_for_voltage_to_stabilise"); + } state wait_for_voltage_to_stabilise + + /* If not succeeded, re-enter state which will resend all appropriate commands */ + when(delay(300)){ + print_transition_scpi("set_psu_to_match_magnet", "set_psu_to_match_magnet"); + } state set_psu_to_match_magnet + } + + state wait_for_voltage_to_stabilise + { + + /* Execute entry and exit blocks even if the next state is the same as the current state */ + option -e; + option -x; + + entry { + PVPUT(statemachine_pv, 3); + epicsThreadSleep(1.0); + } + + when(supplyvoltage_stable == 1) { + print_transition_scpi("wait_for_voltage_to_stabilise", "ensure_switch_heater_warm"); + } state ensure_switch_heater_warm + + /* If the PSU current drifts outside of tolerance for some reason, go back to previous step */ + when(!within_tolerance_scpi(field_setpoint_readback, field_setpoint_raw, field_tolerance)) { + print_transition_scpi("wait_for_voltage_to_stabilise", "set_psu_to_match_magnet"); + } state set_psu_to_match_magnet + + /* If not stable, re-set psu to magnet current (i.e. try again from state above) */ + when (delay(300)){ + print_transition_scpi("wait_for_voltage_to_stabilise", "set_psu_to_match_magnet"); + } state set_psu_to_match_magnet + } + + state ensure_switch_heater_warm + { + + /* Execute entry and exit blocks even if the next state is the same as the current state */ + option -e; + option -x; + + entry + { + PVPUT(statemachine_pv, 4); + epicsThreadSleep(1.0); + PVPUT(activity_sp, ACTIVITY_HOLD); + epicsThreadSleep(1.0); + PVPUT(heater_sp, 1); + } + + when(activity == ACTIVITY_HOLD && heater == 1 && heater_ontime_ok == 1) + { + print_transition_scpi("ensure_switch_heater_warm", "set_psu_output"); + } state set_psu_output + + /* If heater is not switched on within timeout, retry sending commands */ + when(delay(heater_wait_time + 30.0)){ + print_transition_scpi("ensure_switch_heater_warm", "ensure_switch_heater_warm"); + } state ensure_switch_heater_warm + } + + state set_psu_output + { + + /* Execute entry and exit blocks even if the next state is the same as the current state */ + option -e; + option -x; + + entry + { + PVPUT(statemachine_pv, 5); + epicsThreadSleep(1.0); + printf("Setting raw field setpoint to %f\n", field_setpoint); + PVPUT(field_setpoint_raw, field_setpoint); + epicsThreadSleep(1.0); + PVPUT(activity_sp, ACTIVITY_TO_SP); + } + + /* Set to persistent mode */ + when( + within_tolerance_scpi(field_setpoint_readback, field_setpoint, field_tolerance) + && within_tolerance_scpi(field_setpoint, psu_field, field_tolerance) + && persistent == 1 + && (sweep_active == 0) + ) + { + print_transition_scpi("set_psu_output", "switch_off_heater"); + } state switch_off_heater + + + /* If NOT setting to persistent mode, skip ramping down the PSU and setting switch heater to OFF */ + + when( + within_tolerance_scpi(field_setpoint_readback, field_setpoint, field_tolerance) + && within_tolerance_scpi(field_setpoint, psu_field, field_tolerance) + && persistent == 0 + && (sweep_active == 0) + ) + { + print_transition_scpi("set_psu_output", "at_field"); + } state at_field + + /* If not succeeded, try resending setpoint */ + when(delay(300)){ + print_transition_scpi("set_psu_output", "set_psu_output"); + } state set_psu_output + + } + + state switch_off_heater + { + + /* Execute entry and exit blocks even if the next state is the same as the current state */ + option -e; + option -x; + + entry + { + PVPUT(statemachine_pv, 6); + epicsThreadSleep(1.0); + PVPUT(heater_sp, 0); + } + + when(heater == 0 || heater == 2) + { + epicsThreadSleep(heater_wait_time); + print_transition_scpi("switch_off_heater", "ramp_down_psu"); + } state ramp_down_psu + + /* If not succeeded, try resending setpoint */ + when(delay(30)){ + print_transition_scpi("switch_off_heater", "switch_off_heater"); + } state switch_off_heater + } + + state ramp_down_psu + { + + /* Execute entry and exit blocks even if the next state is the same as the current state */ + option -e; + option -x; + + entry + { + PVPUT(statemachine_pv, 7); + epicsThreadSleep(1.0); + PVPUT(activity_sp, ACTIVITY_TO_ZERO); + } + + when( + within_tolerance_scpi(psu_field, 0, field_tolerance) + && (sweep_active == 0) + ) + { + print_transition_scpi("ramp_down_psu", "at_field"); + } state at_field + + when(delay(300)){ + print_transition_scpi("ramp_down_psu", "ramp_down_psu"); + } state ramp_down_psu + } +} diff --git a/IPS/iocBoot/iocIPS-IOC-01/st.cmd b/IPS/iocBoot/iocIPS-IOC-01/st.cmd index e9df65ab8..75b80153e 100644 --- a/IPS/iocBoot/iocIPS-IOC-01/st.cmd +++ b/IPS/iocBoot/iocIPS-IOC-01/st.cmd @@ -86,7 +86,8 @@ cd "${TOP}/iocBoot/${IOC}" iocInit ## Start any sequence programs -seq cryomagnet, "FIELD=$(P)FIELD,FIELD_SETPOINT=$(P)FIELD:SP,FIELD_SETPOINT_ALARM=$(P)FIELD:SP.SEVR,FIELD_SETPOINT_READBACK=$(P)FIELD:SP:RBV,FIELD_SETPOINT_RAW=$(P)FIELD:SP:_RAW,PERSISTENT=$(P)PERSISTENT,MAGNET_FIELD=$(P)MAGNET:FIELD:PERSISTENT,HEATER_STATUS=$(P)HEATER:STATUS,HEATER_STATUS_SP=$(P)HEATER:STATUS:SP,HEATER_WAIT_TIME=$(P)HEATER:WAITTIME,ACTIVITY=$(P)ACTIVITY,ACTIVITY_SP=$(P)ACTIVITY:SP,SWEEPMODE=$(P)SWEEPMODE:PARAMS,SWEEPMODE_SP=$(P)SWEEPMODE:PARAMS:SP,SUPPLYVOLTAGE_STABLE=$(P)SUPPLY:VOLT:STABLE,SWEEP_ACTIVE=$(P)STS:SWEEPMODE:SWEEP,STATEMACHINE=$(P)STATEMACHINE,HEATER_ONTIME_OK=$(P)HEATER:ONTIME_OK" +$(IFNOTSTREAMPROTOCOL_SCPI) seq cryomagnet, "FIELD=$(P)FIELD,FIELD_SETPOINT=$(P)FIELD:SP,FIELD_SETPOINT_ALARM=$(P)FIELD:SP.SEVR,FIELD_SETPOINT_READBACK=$(P)FIELD:SP:RBV,FIELD_SETPOINT_RAW=$(P)FIELD:SP:_RAW,PERSISTENT=$(P)PERSISTENT,MAGNET_FIELD=$(P)MAGNET:FIELD:PERSISTENT,HEATER_STATUS=$(P)HEATER:STATUS,HEATER_STATUS_SP=$(P)HEATER:STATUS:SP,HEATER_WAIT_TIME=$(P)HEATER:WAITTIME,ACTIVITY=$(P)ACTIVITY,ACTIVITY_SP=$(P)ACTIVITY:SP,SWEEPMODE=$(P)SWEEPMODE:PARAMS,SWEEPMODE_SP=$(P)SWEEPMODE:PARAMS:SP,SUPPLYVOLTAGE_STABLE=$(P)SUPPLY:VOLT:STABLE,SWEEP_ACTIVE=$(P)STS:SWEEPMODE:SWEEP,STATEMACHINE=$(P)STATEMACHINE,HEATER_ONTIME_OK=$(P)HEATER:ONTIME_OK") +$(IFSTREAMPROTOCOL_SCPI) seq cryomagnet_SCPI, "FIELD=$(P)FIELD,FIELD_SETPOINT=$(P)FIELD:SP,FIELD_SETPOINT_ALARM=$(P)FIELD:SP.SEVR,FIELD_SETPOINT_READBACK=$(P)FIELD:SP:RBV,FIELD_SETPOINT_RAW=$(P)FIELD:SP:_RAW,PERSISTENT=$(P)PERSISTENT,MAGNET_FIELD=$(P)MAGNET:FIELD:PERSISTENT,HEATER_STATUS=$(P)HEATER:STATUS,HEATER_STATUS_SP=$(P)HEATER:STATUS:SP,HEATER_WAIT_TIME=$(P)HEATER:WAITTIME,ACTIVITY=$(P)ACTIVITY,ACTIVITY_SP=$(P)ACTIVITY:SP,SWEEPMODE=$(P)SWEEPMODE:PARAMS,SUPPLYVOLTAGE_STABLE=$(P)SUPPLY:VOLT:STABLE,SWEEP_ACTIVE=$(P)STS:SWEEPMODE:SWEEP,STATEMACHINE=$(P)STATEMACHINE,HEATER_ONTIME_OK=$(P)HEATER:ONTIME_OK") ##ISIS## Stuff that needs to be done after iocInit is called e.g. sequence programs < $(IOCSTARTUP)/postiocinit.cmd From 9e4ea1b3bd8141c4ed8ea53fe31b337233792340 Mon Sep 17 00:00:00 2001 From: Ian Gillingham Date: Thu, 28 Aug 2025 11:30:58 +0100 Subject: [PATCH 24/29] Added support for discovered alarm status 'Magnet Safety' --- IPS/IPS-IOC-01App/Db/ips_scpi_levels.db | 4 ++-- IPS/IPS-IOC-01App/Db/scpi_system_alarms.db | 1 + .../Db/scpi_system_alarms_discrete.substitutions | 1 + 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/IPS/IPS-IOC-01App/Db/ips_scpi_levels.db b/IPS/IPS-IOC-01App/Db/ips_scpi_levels.db index 1996757fc..62ecf85fb 100644 --- a/IPS/IPS-IOC-01App/Db/ips_scpi_levels.db +++ b/IPS/IPS-IOC-01App/Db/ips_scpi_levels.db @@ -122,7 +122,7 @@ record(ai, "$(P)LVL:HE:LEVEL") { field(SCAN, "5 second") field(INP, "@OxInstIPS_SCPI.protocol getLevelHeliumLevel $(PORT)") field(EGU, "%") - field(PREC, "0") + field(PREC, "2") field(SIML, "$(P)SIM") field(SIOL, "$(P)SIM:LVL:HE:LEVEL") @@ -302,7 +302,7 @@ record(ai, "$(P)LVL:NIT:LEVEL") { field(SCAN, "5 second") field(INP, "@OxInstIPS_SCPI.protocol getLevelNitrogenLevel $(PORT)") field(EGU, "%") - field(PREC, "0") + field(PREC, "2") field(SIML, "$(P)SIM") field(SIOL, "$(P)SIM:LVL:NIT:LEVEL") diff --git a/IPS/IPS-IOC-01App/Db/scpi_system_alarms.db b/IPS/IPS-IOC-01App/Db/scpi_system_alarms.db index e125633fd..c5837ac82 100644 --- a/IPS/IPS-IOC-01App/Db/scpi_system_alarms.db +++ b/IPS/IPS-IOC-01App/Db/scpi_system_alarms.db @@ -177,6 +177,7 @@ record(mbbiDirect, "$(P)STS:SYSTEM:ALARM:10TBOARD") { # 5 Firmware Error # 6 Board Not Configured # 7 No Reserve +# 8 Magnet Safety # record(mbbiDirect, "$(P)STS:SYSTEM:ALARM:LBOARD") { field(DESC, "Levels board alarm status") diff --git a/IPS/IPS-IOC-01App/Db/scpi_system_alarms_discrete.substitutions b/IPS/IPS-IOC-01App/Db/scpi_system_alarms_discrete.substitutions index 33dd30bfc..e8ff54a3c 100644 --- a/IPS/IPS-IOC-01App/Db/scpi_system_alarms_discrete.substitutions +++ b/IPS/IPS-IOC-01App/Db/scpi_system_alarms_discrete.substitutions @@ -22,6 +22,7 @@ pattern {P, ALARM_NAME, ALARM_DESC, ALARM_INP} {"\$(P)", "LBOARD:NOTCONFIGD", "Levels board not confgd", "LBOARD.B6"} {"\$(P)", "LBOARD:NORESERVE", "Levels board no reserve", "LBOARD.B7"} {"\$(P)", "LBOARD:NORESERVE", "Levels board no reserve", "LBOARD.B7"} +{"\$(P)", "LBOARD:MAGNETSAFETY", "Levels board magnet safety", "LBOARD.B8"} {"\$(P)", "PBOARD:OPENCIRCUIT", "Pressure board Open Circuit", "PBOARD.B0"} {"\$(P)", "PBOARD:SHORTCIRCUIT", "Pressure board Short Circuit", "PBOARD.B1"} From cfa967c742bcf128bbc443f5761b41ba58649e20 Mon Sep 17 00:00:00 2001 From: Ian Gillingham Date: Tue, 16 Sep 2025 13:42:17 +0100 Subject: [PATCH 25/29] ips_scpi.db: Removed FIELD and CURRENT trip status records - can not be determined from SCPI --- IPS/IPS-IOC-01App/Db/ips_scpi.db | 38 -------------------------------- 1 file changed, 38 deletions(-) diff --git a/IPS/IPS-IOC-01App/Db/ips_scpi.db b/IPS/IPS-IOC-01App/Db/ips_scpi.db index 76346722d..ff1df7958 100644 --- a/IPS/IPS-IOC-01App/Db/ips_scpi.db +++ b/IPS/IPS-IOC-01App/Db/ips_scpi.db @@ -98,7 +98,6 @@ record(mbbi, "$(P)ACTIVITY") { info(archive, "VAL") } -## !! Modify for SCPI - IJG 27/3/25 # Hold means maintaining present current. # Clamped means you cannot adjust it - powers up in this # state. Only the set activity hold command can get out @@ -373,26 +372,6 @@ record(ai, "$(P)MAGNET:CURR:PERSISTENT") { info(archive, "VAL") } -## ==== CURR:TRIP needs to be derived somehow, some time. It is not in the SCPI protocol. ==== -# The current at which a trip last occurred. Am not sure if by trip, they mean -# a quench or a problem with the level meter. Believe the unit will take the current -# and field to zero if there is a trip, so this parameter preserves what was happening -# at the time of the trip. -#record(ai, "$(P)CURR:TRIP") { -# field(DESC, "Trip current readback") -# field(DTYP, "stream") -# field(SCAN, "1 second") -# # field(INP, "@OxInstIPS_SCPI.protocol getTripCurrent $(PORT)") -# field(EGU, "A") -# field(PREC, "4") -# -# field(SIML, "$(P)SIM") -# field(SIOL, "$(P)SIM:TRIPCURRENT") -# field(SDIS, "$(P)DISABLE") -# -# info(archive, "VAL") -#} - # The field in the magnet due to the persistent current. See current for explanation. record(ai, "$(P)MAGNET:FIELD:PERSISTENT") { field(DESC, "Persistent magnet field readback") @@ -411,23 +390,6 @@ record(ai, "$(P)MAGNET:FIELD:PERSISTENT") { info(archive, "VAL") } -## ==== FIELD:TRIP needs to be derived somehow, some time. It is not in the SCPI protocol. ==== -# The field at which a trip last occurred. See current for explanation. -#record(ai, "$(P)FIELD:TRIP") { -# field(DESC, "Trip field readback") -# field(DTYP, "stream") -# field(SCAN, "1 second") -# # field(INP, "@OxInstIPS_SCPI.protocol getTripField $(PORT)") -# field(EGU, "T") -# field(PREC, "5") -# -# field(SIML, "$(P)SIM") -# field(SIOL, "$(P)SIM:TRIPFIELD") -# field(SDIS, "$(P)DISABLE") -# -# info(archive, "VAL") -#} - # The current being provided to the heater. # Our magnets do not have heaters, so this is not relevant. record(ai, "$(P)HEATER:CURR") { From e9294c1f3f83865aa49e9ab7a003e1ef165ef598 Mon Sep 17 00:00:00 2001 From: Ian Gillingham Date: Tue, 16 Sep 2025 13:52:12 +0100 Subject: [PATCH 26/29] ips_scpi.db: Moved some documentation to the Developer Manual (Oxford-instruments-Mercury-IPS.md) --- IPS/IPS-IOC-01App/Db/ips_scpi.db | 31 ------------------------------- 1 file changed, 31 deletions(-) diff --git a/IPS/IPS-IOC-01App/Db/ips_scpi.db b/IPS/IPS-IOC-01App/Db/ips_scpi.db index ff1df7958..f8220bf88 100644 --- a/IPS/IPS-IOC-01App/Db/ips_scpi.db +++ b/IPS/IPS-IOC-01App/Db/ips_scpi.db @@ -860,20 +860,6 @@ record(bo, "$(P)HEATER:ONTIME_OK") { info(archive, "VAL") } - -# SWEEPMODE:PARAMS and SWEEPMODE:SWEEP -# These have been removed as they are meaningless in SCPI protocol. -# Documentation from the old legacy db. -# Readback from n of Mmn part of Examine command return. -# (Ignore the Pmn part of the Examine command return - no records for this.) -# 0 output constant, 1, 2, 3 output changing -# -# According to the documented legacy command, the m part of the Mmn X command response -# is either 0 or 1, so for the life of me I can't see how this mbbi could -# assume any value above 1. This record does not appear to be referenced anywhere, including in the OPI. -# So will keep as was but PINI to zero. -# IJG - April 2025 - # To capture bits of mismatching status protocol. # We do not do much with it at the moment. record(stringin, "$(P)DBG:STS:MISMATCH") { @@ -988,23 +974,6 @@ record(mbbo, "$(P)SIM:ACTIVITY") { alias("$(P)SIM:ACTIVITY", "$(P)SIM:ACTIVITY:SP") -# SWEEPMODE:PARAMS and SWEEPMODE:SWEEP -# These are meaningless in SCPI protocol. -# Documentation from the old legacy db. -# Readback from n of Mmn part of Examine command return. -# (Ignore the Pmn part of the Examine command return - no records for this.) -# 0 output constant, 1, 2, 3 output changing -# -# According to the documented legacy command, the m part of the Mmn X command response -# is either 0 or 1, so for the life of me I can't see how this mbbi could -# assume any value above 1. This record does not appear to be referenced anywhere, including in the OPI. -# So will keep as was but PINI to zero. -# IJG - April 2025 -# Update May 2025: This record is used in the SNL state machine and is presently required just to -# make the state machine work. So these records have been re-appended to this db file, until such time that -# a better solution is found. - -# Readback from m of Mmn part of Examine command return. # The Display is in Amps or Tesla. The Magnet Sweep is fast or slow. record(mbbi, "$(P)SWEEPMODE:PARAMS") { field(DESC, "Mode status") From 6cf11fbdb166dca617cef8a7b2cac556a7486d10 Mon Sep 17 00:00:00 2001 From: Ian Gillingham Date: Tue, 16 Sep 2025 14:14:31 +0100 Subject: [PATCH 27/29] ips_scpi.db and ips.db: Removed misleading comment about magnet heaters not being present - they are. --- IPS/IPS-IOC-01App/Db/ips.db | 1 - IPS/IPS-IOC-01App/Db/ips_scpi.db | 6 ------ 2 files changed, 7 deletions(-) diff --git a/IPS/IPS-IOC-01App/Db/ips.db b/IPS/IPS-IOC-01App/Db/ips.db index 16876e8be..cc66ef757 100644 --- a/IPS/IPS-IOC-01App/Db/ips.db +++ b/IPS/IPS-IOC-01App/Db/ips.db @@ -480,7 +480,6 @@ record(ai, "$(P)FIELD:TRIP") { } # The current being provided to the heater. -# Our magnets do not have heaters, so this is not relevant. record(ai, "$(P)HEATER:CURR") { field(DESC, "Heater current readback") field(DTYP, "stream") diff --git a/IPS/IPS-IOC-01App/Db/ips_scpi.db b/IPS/IPS-IOC-01App/Db/ips_scpi.db index f8220bf88..641db342b 100644 --- a/IPS/IPS-IOC-01App/Db/ips_scpi.db +++ b/IPS/IPS-IOC-01App/Db/ips_scpi.db @@ -63,11 +63,6 @@ record(stringin, "$(P)VERSION") { field(SCAN, "Passive") } -# CONTROL and CONTROL:SP records have been removed from the SCPI variant database -# as the SCPI command set does not manage the panel lock in the same was as legacy and -# Magnet Group advised to remove this feature, as they always want to be able to control -# the IPS via the front panel. IJG 13/05/2025 - # Readback from STAT:DEV:GRPZ:PSU:ACTN command return (in getActivity()). # Hold means maintaining present current. # Clamped means you cannot adjust it - powers up in this @@ -391,7 +386,6 @@ record(ai, "$(P)MAGNET:FIELD:PERSISTENT") { } # The current being provided to the heater. -# Our magnets do not have heaters, so this is not relevant. record(ai, "$(P)HEATER:CURR") { field(DESC, "Heater current readback") field(DTYP, "stream") From 3035c1e136092dddadee53138e5947673d820f21 Mon Sep 17 00:00:00 2001 From: Ian Gillingham Date: Wed, 17 Sep 2025 13:01:27 +0100 Subject: [PATCH 28/29] Added ips_common.db which contains all the EPICS records common to both legacy and SCPI --- IPS/IPS-IOC-01App/Db/ips_common.db | 0 .../Db/{ips.db => ips_legacy.db} | 0 IPS/IPS-IOC-01App/src/cryomagnet_SCPI.st | 300 ------------------ 3 files changed, 300 deletions(-) create mode 100644 IPS/IPS-IOC-01App/Db/ips_common.db rename IPS/IPS-IOC-01App/Db/{ips.db => ips_legacy.db} (100%) delete mode 100644 IPS/IPS-IOC-01App/src/cryomagnet_SCPI.st diff --git a/IPS/IPS-IOC-01App/Db/ips_common.db b/IPS/IPS-IOC-01App/Db/ips_common.db new file mode 100644 index 000000000..e69de29bb diff --git a/IPS/IPS-IOC-01App/Db/ips.db b/IPS/IPS-IOC-01App/Db/ips_legacy.db similarity index 100% rename from IPS/IPS-IOC-01App/Db/ips.db rename to IPS/IPS-IOC-01App/Db/ips_legacy.db diff --git a/IPS/IPS-IOC-01App/src/cryomagnet_SCPI.st b/IPS/IPS-IOC-01App/src/cryomagnet_SCPI.st deleted file mode 100644 index c3a09abca..000000000 --- a/IPS/IPS-IOC-01App/src/cryomagnet_SCPI.st +++ /dev/null @@ -1,300 +0,0 @@ -program cryomagnet_SCPI("FIELD,FIELD_SETPOINT,FIELD_SETPOINT_ALARM,FIELD_SETPOINT_RAW,FIELD_SETPOINT_READBACK,PERSISTENT,MAGNET_FIELD,HEATER_STATUS,HEATER_STATUS_SP,HEATER_WAIT_TIME,ACTIVITY,ACTIVITY_SP,SWEEPMODE,SUPPLYVOLTAGE_STABLE,SWEEP_ACTIVE,STATEMACHINE,HEATER_ONTIME_OK") - -#include "ibexSeqPVmacros.h" -%% #include - -/* Turn on run-time debug messages */ -option +d; - -/* Make code reentrant. This is needed to run more than one instance of this program. */ -option +r; - -/* Field */ -PV(double, field_setpoint, "{FIELD_SETPOINT}", Monitor); -PV(int, field_setpoint_alarm, "{FIELD_SETPOINT_ALARM}", Monitor); -PV(double, field_setpoint_readback, "{FIELD_SETPOINT_READBACK}", Monitor); -PV(double, field_setpoint_raw, "{FIELD_SETPOINT_RAW}", Monitor); - -PV(double, psu_field, "{FIELD}", Monitor); -PV(double, magnet_field, "{MAGNET_FIELD}", Monitor); - -PV(int, persistent, "{PERSISTENT}", Monitor); - -PV(int, heater, "{HEATER_STATUS}", Monitor); -PV(int, heater_sp, "{HEATER_STATUS_SP}", Monitor); - -PV(int, activity, "{ACTIVITY}", Monitor); -PV(int, activity_sp, "{ACTIVITY_SP}", Monitor); - -PV(int, sweepmode, "{SWEEPMODE}", Monitor); - -PV(double, heater_wait_time, "{HEATER_WAIT_TIME}", Monitor); - -PV(int, supplyvoltage_stable, "{SUPPLYVOLTAGE_STABLE}", Monitor); - -PV(int, sweep_active, "{SWEEP_ACTIVE}", Monitor); - -PV(int, statemachine_pv, "{STATEMACHINE}", NoMon); - -PV(int, heater_ontime_ok, "{HEATER_ONTIME_OK}", Monitor); - - -/* If fields are the same within this tolerance, treat as the same */ -double field_tolerance = 0.0001; - -int ACTIVITY_HOLD = 0; -int ACTIVITY_TO_SP = 1; -int ACTIVITY_TO_ZERO = 2; - -/* The device varies which one it sends back but they both mean the same... */ -int SWEEP_MODE = 3; -int SWEEP_MODE_ALT = 1; - -%{ -void print_transition_scpi(char* old, char* new) { - printf("cryomagnet_SCPI.st: Moving from state %s to %s.\n", old, new); -} - -int within_tolerance_scpi(double a, double b, double tolerance) { - return fabs(a - b) < tolerance; -} -}% - -/* - * - * Documentation and further information about this state machine is available at https://github.com/ISISComputingGroup/ibex_developers_manual/wiki/OxfordInstrumentsIPS - * - */ -ss cryomagnet_SCPI -{ - - state initial - { - entry { - PVPUT(statemachine_pv, 0); - epicsThreadSleep(1.0); - } - - /* Dont do anything at all until the field setpoint is set to something & UDF_ALARM goes away. */ - when(field_setpoint_alarm == 0) { - print_transition_scpi("initial", "at_field"); - } state at_field - } - - state at_field - { - entry { - PVPUT(statemachine_pv, 1); - epicsThreadSleep(1.0); - } - - /* Heater is OFF, so in superconducting/persistent mode. */ - when( - !within_tolerance_scpi(field_setpoint, field_setpoint_readback, field_tolerance) - && field_setpoint_alarm == 0 - && (heater == 0 || heater == 2) - ) - { - print_transition_scpi("at_field", "set_psu_to_match_magnet"); - } state set_psu_to_match_magnet - - /* Heater is ON, so in conventional/non-persistent mode. */ - when( - !within_tolerance_scpi(field_setpoint, field_setpoint_readback, field_tolerance) - && field_setpoint_alarm == 0 - && heater == 1 - ) - { - print_transition_scpi("at_field", "set_psu_output"); - } state set_psu_output - } - - state set_psu_to_match_magnet - { - - /* Execute entry and exit blocks even if the next state is the same as the current state */ - option -e; - option -x; - - entry - { - PVPUT(statemachine_pv, 2); - epicsThreadSleep(1.0); - printf("Setting raw field setpoint to %f\n", magnet_field); - PVPUT(field_setpoint_raw, magnet_field); - epicsThreadSleep(1.0); - PVPUT(activity_sp, ACTIVITY_TO_SP); - epicsThreadSleep(1.0); - } - - when( - within_tolerance_scpi(field_setpoint_readback, magnet_field, field_tolerance) - && within_tolerance_scpi(psu_field, magnet_field, field_tolerance) - && ((sweepmode == SWEEP_MODE) || (sweepmode == SWEEP_MODE_ALT)) - && (sweep_active == 0) - ) - { - print_transition_scpi("set_psu_to_match_magnet", "wait_for_voltage_to_stabilise"); - } state wait_for_voltage_to_stabilise - - /* If not succeeded, re-enter state which will resend all appropriate commands */ - when(delay(300)){ - print_transition_scpi("set_psu_to_match_magnet", "set_psu_to_match_magnet"); - } state set_psu_to_match_magnet - } - - state wait_for_voltage_to_stabilise - { - - /* Execute entry and exit blocks even if the next state is the same as the current state */ - option -e; - option -x; - - entry { - PVPUT(statemachine_pv, 3); - epicsThreadSleep(1.0); - } - - when(supplyvoltage_stable == 1) { - print_transition_scpi("wait_for_voltage_to_stabilise", "ensure_switch_heater_warm"); - } state ensure_switch_heater_warm - - /* If the PSU current drifts outside of tolerance for some reason, go back to previous step */ - when(!within_tolerance_scpi(field_setpoint_readback, field_setpoint_raw, field_tolerance)) { - print_transition_scpi("wait_for_voltage_to_stabilise", "set_psu_to_match_magnet"); - } state set_psu_to_match_magnet - - /* If not stable, re-set psu to magnet current (i.e. try again from state above) */ - when (delay(300)){ - print_transition_scpi("wait_for_voltage_to_stabilise", "set_psu_to_match_magnet"); - } state set_psu_to_match_magnet - } - - state ensure_switch_heater_warm - { - - /* Execute entry and exit blocks even if the next state is the same as the current state */ - option -e; - option -x; - - entry - { - PVPUT(statemachine_pv, 4); - epicsThreadSleep(1.0); - PVPUT(activity_sp, ACTIVITY_HOLD); - epicsThreadSleep(1.0); - PVPUT(heater_sp, 1); - } - - when(activity == ACTIVITY_HOLD && heater == 1 && heater_ontime_ok == 1) - { - print_transition_scpi("ensure_switch_heater_warm", "set_psu_output"); - } state set_psu_output - - /* If heater is not switched on within timeout, retry sending commands */ - when(delay(heater_wait_time + 30.0)){ - print_transition_scpi("ensure_switch_heater_warm", "ensure_switch_heater_warm"); - } state ensure_switch_heater_warm - } - - state set_psu_output - { - - /* Execute entry and exit blocks even if the next state is the same as the current state */ - option -e; - option -x; - - entry - { - PVPUT(statemachine_pv, 5); - epicsThreadSleep(1.0); - printf("Setting raw field setpoint to %f\n", field_setpoint); - PVPUT(field_setpoint_raw, field_setpoint); - epicsThreadSleep(1.0); - PVPUT(activity_sp, ACTIVITY_TO_SP); - } - - /* Set to persistent mode */ - when( - within_tolerance_scpi(field_setpoint_readback, field_setpoint, field_tolerance) - && within_tolerance_scpi(field_setpoint, psu_field, field_tolerance) - && persistent == 1 - && (sweep_active == 0) - ) - { - print_transition_scpi("set_psu_output", "switch_off_heater"); - } state switch_off_heater - - - /* If NOT setting to persistent mode, skip ramping down the PSU and setting switch heater to OFF */ - - when( - within_tolerance_scpi(field_setpoint_readback, field_setpoint, field_tolerance) - && within_tolerance_scpi(field_setpoint, psu_field, field_tolerance) - && persistent == 0 - && (sweep_active == 0) - ) - { - print_transition_scpi("set_psu_output", "at_field"); - } state at_field - - /* If not succeeded, try resending setpoint */ - when(delay(300)){ - print_transition_scpi("set_psu_output", "set_psu_output"); - } state set_psu_output - - } - - state switch_off_heater - { - - /* Execute entry and exit blocks even if the next state is the same as the current state */ - option -e; - option -x; - - entry - { - PVPUT(statemachine_pv, 6); - epicsThreadSleep(1.0); - PVPUT(heater_sp, 0); - } - - when(heater == 0 || heater == 2) - { - epicsThreadSleep(heater_wait_time); - print_transition_scpi("switch_off_heater", "ramp_down_psu"); - } state ramp_down_psu - - /* If not succeeded, try resending setpoint */ - when(delay(30)){ - print_transition_scpi("switch_off_heater", "switch_off_heater"); - } state switch_off_heater - } - - state ramp_down_psu - { - - /* Execute entry and exit blocks even if the next state is the same as the current state */ - option -e; - option -x; - - entry - { - PVPUT(statemachine_pv, 7); - epicsThreadSleep(1.0); - PVPUT(activity_sp, ACTIVITY_TO_ZERO); - } - - when( - within_tolerance_scpi(psu_field, 0, field_tolerance) - && (sweep_active == 0) - ) - { - print_transition_scpi("ramp_down_psu", "at_field"); - } state at_field - - when(delay(300)){ - print_transition_scpi("ramp_down_psu", "ramp_down_psu"); - } state ramp_down_psu - } -} From 41dbae78d55eae6114a48563e0619296cd16dad1 Mon Sep 17 00:00:00 2001 From: Ian Gillingham Date: Wed, 17 Sep 2025 13:05:25 +0100 Subject: [PATCH 29/29] Split out duplicated records from SCPI and legacy databases into ips_common.db. Utilised alarms template file to also create system status records. Removed SCPI statemachine and using a single one, now that the SCPI db creates a dummy SWEEPMODE:PARAMS:SP record. --- IPS/IPS-IOC-01App/Db/Makefile | 3 +- IPS/IPS-IOC-01App/Db/ips_common.db | 627 +++++++++++++ IPS/IPS-IOC-01App/Db/ips_legacy.db | 668 +------------- IPS/IPS-IOC-01App/Db/ips_scpi.db | 861 +----------------- .../scpi_system_alarms_discrete.substitutions | 104 ++- .../Db/scpi_system_alarms_discrete.template | 6 +- IPS/IPS-IOC-01App/src/build.mak | 1 - IPS/IPS-IOC-01App/src/cryomagnet.dbd | 1 - IPS/iocBoot/iocIPS-IOC-01/st.cmd | 6 +- 9 files changed, 745 insertions(+), 1532 deletions(-) diff --git a/IPS/IPS-IOC-01App/Db/Makefile b/IPS/IPS-IOC-01App/Db/Makefile index a761d1bcd..f601d4fea 100644 --- a/IPS/IPS-IOC-01App/Db/Makefile +++ b/IPS/IPS-IOC-01App/Db/Makefile @@ -10,7 +10,8 @@ include $(TOP)/configure/CONFIG #---------------------------------------------------- # Create and install (or just install) into /db # databases, templates, substitutions like this -DB += ips.db +DB += ips_common.db +DB += ips_legacy.db DB += ips_scpi.db DB += ips_scpi_levels.db DB += scpi_system_alarms.db diff --git a/IPS/IPS-IOC-01App/Db/ips_common.db b/IPS/IPS-IOC-01App/Db/ips_common.db index e69de29bb..99a411c45 100644 --- a/IPS/IPS-IOC-01App/Db/ips_common.db +++ b/IPS/IPS-IOC-01App/Db/ips_common.db @@ -0,0 +1,627 @@ +record(bo, "$(P)SIM") +{ + field(SCAN, "Passive") + field(DTYP, "Soft Channel") + field(ZNAM, "NO") + field(ONAM, "YES") + field(VAL, "$(RECSIM=0)") + field(PINI, "YES") +} + +record(bo, "$(P)DISABLE") +{ + field(DESC, "Disable comms") + field(PINI, "YES") + field(VAL, "$(DISABLE=0)") + field(OMSL, "supervisory") + field(ZNAM, "COMMS ENABLED") + field(ONAM, "COMMS DISABLED") +} + +######################################################### +# START OF RECORDS FOR READBACK FROM VERSION COMMAND. +# # Readback of the instrument model and version info. +# # Run the Version command, V. +# # The string was too long to put model and version into same record. +# # Scan this once, probably not needed again. +# The reply comes back and is split amongst other records in the StreamDevice protocol file. +record(stringin, "$(P)GET:VERSION") { + field(DESC, "Examine status") + field(DTYP, "stream") + field(INP, "@$(PROTO) getVersion($(P)) $(PORT)") + field(PINI, "YES") + field(FLNK, "$(P)MODEL") + field(SCAN, "Passive") + field(SIML, "$(P)SIM") + field(SIOL, "$(P)SIM:DONOTHING") + field(SDIS, "$(P)DISABLE") +} + +# Updated in GET:VERSION call to getVersion() +record(stringin, "$(P)MODEL") { + field(DESC, "Model") + field(DTYP, "Soft Channel") + field(SCAN, "Passive") + field(FLNK, "$(P)VERSION") +} + +# Updated in GET:VERSION call to getVersion() +record(stringin, "$(P)VERSION") { + field(DESC, "Firmware version.") + field(DTYP, "Soft Channel") + field(SCAN, "Passive") +} + +# Hold means maintaining present current. +# Clamped means you cannot adjust it - powers up in this +# state. Only the set activity hold command can get out +# of the clamped state. Hold will interrupt a sweep. +record(mbbo, "$(P)ACTIVITY:SP") { + field(DESC, "Activity control") + field(DTYP, "stream") + field(SCAN, "Passive") + field(OUT, "@$(PROTO) setActivity $(PORT)") + field(ZRST, "Hold") + field(ZRVL, "0") + field(ONST, "To Setpoint") + field(ONVL, "1") + field(TWST, "To Zero") + field(TWVL, "2") + field(FRST, "Clamp") + field(FRVL, "4") + + field(SIML, "$(P)SIM") + field(SIOL, "$(P)SIM:ACTIVITY:SP") + field(SDIS, "$(P)DISABLE") +} + +# Think this is the present current the unit is trying to supply. +record(ai, "$(P)CURR") { + field(DESC, "Demand current readback") + field(DTYP, "stream") + field(SCAN, "1 second") + field(INP, "@$(PROTO) getDemandCurrent $(PORT)") + field(EGU, "A") + field(PREC, "4") + + field(SIML, "$(P)SIM") + field(SIOL, "$(P)SIM:CURRENT") + field(SDIS, "$(P)DISABLE") + + info(archive, "VAL") +} + +# The present current setpoint. +record(ai, "$(P)CURR:SP:RBV") { + field(DESC, "Setpoint current readback") + field(DTYP, "stream") + field(SCAN, "1 second") + field(INP, "@$(PROTO) getSetpointCurrent $(PORT)") + field(EGU, "A") + field(PREC, "4") + + field(SIML, "$(P)SIM") + field(SIOL, "$(P)SIM:CURRENT") + field(SDIS, "$(P)DISABLE") + + info(archive, "VAL") +} + +# The present voltage. +record(ai, "$(P)SUPPLY:VOLT") { + field(DESC, "Supply voltage readback") + field(DTYP, "stream") + field(SCAN, "1 second") + field(INP, "@$(PROTO) getSupplyVoltage $(PORT)") + field(EGU, "V") + field(PREC, "8") + + field(SIML, "$(P)SIM") + field(SIOL, "$(P)SIM:SUPPLY:VOLT") + field(SDIS, "$(P)DISABLE") + + field(FLNK, "$(P)SUPPLY:VOLT:_STABILITY:BUF") + + info(archive, "VAL") +} + +record(compress, "$(P)SUPPLY:VOLT:_STABILITY:BUF") { + field(INP, "$(P)SUPPLY:VOLT") + field(ALG, "Circular Buffer") + field(NSAM, "5") + field(FLNK, "$(P)SUPPLY:VOLT:_STABILITY:LOW") +} + +record(compress, "$(P)SUPPLY:VOLT:_STABILITY:LOW") { + field(INP, "$(P)SUPPLY:VOLT:_STABILITY:BUF") + field(ALG, "N to 1 Low Value") + field(NSAM, "1") + field(N, "5") + field(FLNK, "$(P)SUPPLY:VOLT:_STABILITY:HIGH") +} + +record(compress, "$(P)SUPPLY:VOLT:_STABILITY:HIGH") { + field(INP, "$(P)SUPPLY:VOLT:_STABILITY:BUF") + field(ALG, "N to 1 High Value") + field(NSAM, "1") + field(N, "5") + field(FLNK, "$(P)SUPPLY:VOLT:_STABILITY:CALC") +} + +record(calcout, "$(P)SUPPLY:VOLT:_STABILITY:CALC") { + field(INPA, "$(P)SUPPLY:VOLT:_STABILITY:HIGH") + field(INPB, "$(P)SUPPLY:VOLT:_STABILITY:LOW") + field(CALC, "ABS(A-B)<$(STABILITY_VOLTAGE)") + field(OUT, "$(P)SUPPLY:VOLT:STABLE PP") + field(OOPT, "Every Time") +} + +record(bo, "$(P)SUPPLY:VOLT:STABLE") { + field(ZNAM, "NO") + field(ONAM, "YES") + info(archive, "VAL") +} + +# The present current measured. +record(ai, "$(P)MAGNET:CURR:MEAS") { + field(DESC, "Measured magnet current readback") + field(DTYP, "stream") + field(SCAN, "1 second") + field(INP, "@$(PROTO) getMeasuredMagnetCurrent $(PORT)") + field(EGU, "A") + field(PREC, "4") + + field(SIML, "$(P)SIM") + field(SIOL, "$(P)SIM:MAGNET:CURR:MEAS") + field(SDIS, "$(P)DISABLE") + + info(archive, "VAL") +} + +# The present sweeprate for current. +record(ai, "$(P)CURR:RATE") { + field(DESC, "Current sweep rate readback") + field(DTYP, "stream") + field(SCAN, "1 second") + field(INP, "@$(PROTO) getCurrentSweepRate $(PORT)") + field(EGU, "A/min") + field(PREC, "3") + + field(SIML, "$(P)SIM") + field(SIOL, "$(P)SIM:CURR:RATE") + field(SDIS, "$(P)DISABLE") + + info(archive, "VAL") +} + +# The field the unit is attempting to create. +record(ai, "$(P)FIELD") { + field(DESC, "Demand field readback") + field(DTYP, "stream") + field(SCAN, "1 second") + field(INP, "@$(PROTO) getDemandField $(PORT)") + field(EGU, "T") + field(PREC, "5") + + field(SIML, "$(P)SIM") + field(SIOL, "$(P)SIM:FIELD") + field(SDIS, "$(P)DISABLE") + + info(INTEREST, "LOW") + info(archive, "VAL") +} + +record(ao, "$(P)FIELD:SP") { + field(DESC, "Set setpoint field") + field(SCAN, "Passive") + field(EGU, "T") + field(PREC, "5") + field(DRVH, "$(MAX_FIELD)") + field(DRVL, "-$(MAX_FIELD)") + + field(SIML, "$(P)SIM") + field(SIOL, "$(P)SIM:FIELD") + field(SDIS, "$(P)DISABLE") + info(archive, "VAL") +} + +# Set the Field Setpoint (i.e. the field the unit will go to and hold for the magnet.) +record(ao, "$(P)FIELD:SP:_RAW") { + field(DESC, "Send raw field to box") + field(DTYP, "stream") + field(SCAN, "Passive") + field(OUT, "@$(PROTO) setSetpointField $(PORT)") + field(EGU, "T") + field(PREC, "5") + field(DRVH, "$(MAX_FIELD)") + field(DRVL, "-$(MAX_FIELD)") + + field(SIML, "$(P)SIM") + field(SIOL, "$(P)SIM:FIELD") + field(SDIS, "$(P)DISABLE") + info(archive, "VAL") +} + +# The present field setpoint. The target field the unit will aim for when +# told to go to the setpoint. +record(ai, "$(P)FIELD:SP:RBV") { + field(DESC, "Setpoint field readback") + field(DTYP, "stream") + field(SCAN, "1 second") + field(INP, "@$(PROTO) getSetpointField $(PORT)") + field(EGU, "T") + field(PREC, "5") + + field(SIML, "$(P)SIM") + field(SIOL, "$(P)SIM:FIELD") + field(SDIS, "$(P)DISABLE") + info(archive, "VAL") +} + +# The present sweeprate (a.k.a. ramprate) for adjusting the field. +record(ai, "$(P)FIELD:RATE") { + field(DESC, "Field sweep rate readback") + field(DTYP, "stream") + field(SCAN, "1 second") + field(INP, "@$(PROTO) getFieldSweepRate $(PORT)") + field(EGU, "T/min") + field(PREC, "4") + + field(LOLO, "0") + field(LLSV, "MAJOR") + + field(SIML, "$(P)SIM") + field(SIOL, "$(P)SIM:FIELD:RATE") + field(SDIS, "$(P)DISABLE") + info(INTEREST, "HIGH") + info(archive, "VAL") +} + +record(ao, "$(P)FIELD:RATE:SP") { + field(DESC, "Set field sweep rate") + field(DTYP, "stream") + field(SCAN, "Passive") + field(OUT, "@$(PROTO) setFieldSweepRate $(PORT)") + field(EGU, "T/min") + field(PREC, "4") + field(DRVH, "$(MAX_SWEEP_RATE)") + field(DRVL, "0") + field(ASG, "$(MANAGER_ASG)") + + field(SIML, "$(P)SIM") + field(SIOL, "$(P)SIM:FIELD:RATE:SP") + field(SDIS, "$(P)DISABLE") +} + +# The voltage at which the unit will stop ramping/sweeping at the sweeprate +# requested, but reduce it to protect the voltage. +record(ai, "$(P)VOLT:LIMIT:SOFTWARE") { + field(DESC, "Software voltage limit readback") + field(DTYP, "stream") + field(SCAN, "1 second") + field(INP, "@$(PROTO) getSoftwareVoltageLimit $(PORT)") + field(EGU, "V") + field(PREC, "8") + + field(SIML, "$(P)SIM") + field(SIOL, "$(P)SIM:SOFTWAREVOLTAGELIMIT") + field(SDIS, "$(P)DISABLE") +} + +# This is the current that is in the magnet, which in the case of a magnet with a switch +# and a heater is preserved even when the power unit is not connected (cos of how +# superconducting magnets behave). +record(ai, "$(P)MAGNET:CURR:PERSISTENT") { + field(DESC, "Persistent magnet current readback") + field(DTYP, "stream") + field(SCAN, "1 second") + field(INP, "@$(PROTO) getPersistentMagnetCurrent $(PORT)") + field(EGU, "A") + field(PREC, "4") + + field(SIML, "$(P)SIM") + field(SIOL, "$(P)SIM:PERSISTENTMAGNETCURRENT") + field(SDIS, "$(P)DISABLE") + + info(archive, "VAL") +} + +# The field in the magnet due to the persistent current. See current for explanation. +record(ai, "$(P)MAGNET:FIELD:PERSISTENT") { + field(DESC, "Persistent magnet field readback") + field(DTYP, "stream") + field(SCAN, "1 second") + field(INP, "@$(PROTO) getPersistentMagnetField $(PORT)") + field(EGU, "T") + field(PREC, "5") + + field(SIML, "$(P)SIM") + field(SIOL, "$(P)SIM:PERSISTENTMAGNETFIELD") + field(SDIS, "$(P)DISABLE") + + info(INTEREST, "LOW") + + info(archive, "VAL") +} + +# The resistance of the lead from the unit to the magnet that carries +# the current. This is set by the supplier in the controller, all this +# record does is read and report the value. +record(ai, "$(P)RESISTANCE:LEAD") { + field(DESC, "Leadresistance readback") + field(DTYP, "stream") + field(SCAN, "1 second") + field(INP, "@$(PROTO) getLeadResistance $(PORT)") + field(EGU, "mohm") + field(PREC, "5") + + field(SIML, "$(P)SIM") + field(SIOL, "$(P)SIM:LEADRESISTANCE") + field(SDIS, "$(P)DISABLE") + + info(archive, "VAL") +} + +# The inductance of the magnet. Believe this is also set by the supplier +# as a calibration. +record(ai, "$(P)MAGNET:INDUCTANCE") { + field(DESC, "Magnet inductance readback") + field(DTYP, "stream") + field(SCAN, "1 second") + field(INP, "@$(PROTO) getMagnetInductance $(PORT)") + field(EGU, "H") + field(PREC, "5") + + field(SIML, "$(P)SIM") + field(SIOL, "$(P)SIM:MAGNETINDUCTANCE") + field(SDIS, "$(P)DISABLE") + + info(archive, "VAL") +} + +# Amount of time to wait for heater to warm up/cool down. **CAN CAUSE MAGNET TO QUENCH IF SET TOO LOW** +# Oxford Instruments labview driver uses 30s. ISIS cryogenics have asked us to increase this to 60s, +# which is more conservative. +# The HEATER_WAITTIME IOC macro, which is _not_ user-facing, has a default of 60s. +# Configurable to lower values to shorten time for IOC tests. + +record(ao, "$(P)HEATER:WAITTIME") { + field(DESC, "Time to wait for heater") + field(VAL, "$(HEATER_WAITTIME)") + field(PINI, "YES") + info(archive, "VAL") +} + +# CALC record to coerce heater status values. Heater can be off in states 0 or 2, and in error in states 5 or 8, +# and circular buffer (N to 1 Low Value) only looks for lowest (0). +# Output 1 only if heater is on, 0 if off and all other states, including errors. + +record(calc, "$(P)HEATER:_STATUS_CALC") { + field(DESC, "Binary Heater Status") + field(INPA, "$(P)HEATER:STATUS CP MS") + field(CALC, "(A=1)?1:0") # If heater is on, output 1, otherwise 0 + info(archive, "VAL") +} + +record(bo, "$(P)HEATER:STATUS:SP") { + field(DESC, "Set Remote/Local Control") + field(DTYP, "stream") + field(SCAN, "Passive") + field(OUT, "@$(PROTO) setHeaterStatus $(PORT)") + field(ZNAM, "Off") + field(ONAM, "On") + + field(SIML, "$(P)SIM") + field(SIOL, "$(P)SIM:HEATER:STATUS:SP") + field(SDIS, "$(P)DISABLE") +} + +# COMPRESS Record with circular buffer to store $(HEATER_WAITTIME) worth of HEATER:STATUS values +# Used with second COMPRESS record below to check heater has been on for at least $(HEATER_WAITTIME) after starting IOC + +record(compress, "$(P)HEATER:_STATUS_BUFFER") { + field(DESC, "Buffer of heater status values") + field(INP, "$(P)HEATER:_STATUS_CALC.VAL") + field(ALG, "Circular Buffer") + field(NSAM, "$(HEATER_WAITTIME)") + field(SCAN, "1 second") + field(FLNK, "$(P)HEATER:_STATUS_BUFFER_LOWEST") +} + +# COMPRESS record to monitor above and output lowest value in buffer. +# If '1' then whole buffer contains '1' and therefore heater has been ON for at least $(HEATER_WAITTIME) +# If '0' then heater has been OFF at some point in $(HEATER_WAITTIME) + +record(compress, "$(P)HEATER:_STATUS_BUFFER_LOWEST") { + field(DESC, "Lowest value of heater status buffer") + field(INP, "$(P)HEATER:_STATUS_BUFFER") + field(ALG, "N to 1 Low Value") + field(NSAM, "1") + field(N, "$(HEATER_WAITTIME)") + field(FLNK, "$(P)HEATER:ONTIME_OK") + info(archive, "VAL") +} + +# BO record to indicate whether or not heater been on for at least $(HEATER_WAITTIME). +# Monitored by statemachine to determine whether or not OK to set field. + +record(bo, "$(P)HEATER:ONTIME_OK") { + field(DESC, "Heater on for at least $(HEATER_WAITTIME)s") + field(DTYP, "Soft Channel") + field(SCAN, "Passive") + field(OMSL, "closed_loop") + field(DOL, "$(P)HEATER:_STATUS_BUFFER_LOWEST.VAL") + field(ZNAM, "Heater OFF in last $(HEATER_WAITTIME)s") + field(ONAM, "Heater ON for > $(HEATER_WAITTIME)s") + info(archive, "VAL") +} + +# Readback from m of Mmn part of Examine command return. +# The Display is in Amps or Tesla. The Magnet Sweep is fast or slow. +record(mbbi, "$(P)SWEEPMODE:PARAMS") { + field(DESC, "Mode status") + field(DTYP, "Soft Channel") + field(SCAN, "Passive") + field(ZRST, "Amps Fast") + field(ZRVL, "0") + field(ONST, "Tesla Fast") + field(ONVL, "1") + field(TWST, "Amps Fast") + field(TWVL, "2") + field(THST, "Tesla Fast") + field(THVL, "3") + field(FRST, "Amps Slow") + field(FRVL, "4") + field(FVST, "Tesla Slow") + field(FVVL, "5") + field(SXST, "Amps Slow") + field(SXVL, "6") + field(SVST, "Tesla Slow") + field(SVVL, "7") + field(EIST, "Amps Unaffected") + field(EIVL, "8") + field(NIST, "Tesla Unaffected") + field(NIVL, "9") + + field(VAL, "3") + field(PINI, "YES") + + field(SIML, "$(P)SIM") + field(SIOL, "$(P)SIM:SWEEPMODE:PARAMS") + field(SDIS, "$(P)DISABLE") + + info(archive, "VAL") +} + + +# Readback from n of Mmn part of Examine command return. +# (Ignore the Pmn part of the Examine command return - no records for this.) +# 0 output constant, 1, 2, 3 output changing +record(mbbi, "$(P)STS:SWEEPMODE:SWEEP") { + field(DESC, "Mode status") + field(DTYP, "Soft Channel") + field(SCAN, "Passive") + field(ZRST, "At rest") + field(ZRVL, "0") + field(ONST, "Sweeping") + field(ONVL, "1") + field(TWST, "Sweep Limiting") + field(TWVL, "2") + field(THST, "Swping & Lmting") + field(THVL, "3") + + field(SIML, "$(P)SIM") + field(SIOL, "$(P)SIM:STS:SWEEPMODE:SWEEP") + field(SDIS, "$(P)DISABLE") + + info(archive, "VAL") +} + +# PERSISTENT pv is the magnet persistent mode in the cryomagnet statemachine. +record(bo, "$(P)PERSISTENT") { + field(DESC, "Set magnet to persistent") + field(ZNAM, "NO") + field(ONAM, "YES") + field(PINI, "YES") + info(autosaveFields, "VAL") + info(INTEREST, "HIGH") + info(archive, "VAL") +} + +# Play nicely with blocks/genie_python +alias("$(P)PERSISTENT", "$(P)PERSISTENT:SP") + +record(mbbo, "$(P)STATEMACHINE") { + field(DESC, "What the IOC is doing") + + field(ZRVL, "0") + field(ZRST, "Initial state") + + field(ONVL, "1") + field(ONST, "At field") + + field(TWVL, "2") + field(TWST, "Set PSU to match magnet") + + field(THVL, "3") + field(THST, "Wait for volts stable") + + field(FRVL, "4") + field(FRST, "Ensure heater on & warm") + + field(FVVL, "5") + field(FVST, "Set PSU to setpoint") + + field(SXVL, "6") + field(SXST, "Turn heater off & wait") + + field(SVVL, "7") + field(SVST, "Set PSU to zero") + + info(archive, "VAL") +} + + +### +### Records to be more "friendly" to the user. +### + +record(calc, "$(P)FIELD:USER") { + field(DESC, "Field readback") + field(INPA, "$(P)MAGNET:FIELD:PERSISTENT CP MS") + field(INPB, "$(P)FIELD CP MS") + field(INPC, "$(P)HEATER:STATUS CP MS") + field(CALC, "(C=0||C=2)?A:B") # If heater is present and switched off, display persistent field, else display PSU field + field(ASG, "READONLY") + field(EGU, "T") + field(PREC, "5") + info(interest, "HIGH") + info(archive, "VAL") +} + +alias("$(P)FIELD:SP", "$(P)FIELD:USER:SP") # "User" setpoint is same as "normal" setpoint + + +### Simulation record - Just to stop errors, doesn't do anything + +record(ao, "$(P)SIM:DONOTHING") {} + +record(bo, "$(P)SIM:HEATER:STATUS") { + field(ZNAM, "Off") + field(ONAM, "On") +} + +alias("$(P)SIM:HEATER:STATUS", "$(P)SIM:HEATER:STATUS:SP") + +record(ao, "$(P)SIM:MAGNETINDUCTANCE"){} +record(ao, "$(P)SIM:LEADRESISTANCE"){} +record(ao, "$(P)SIM:POSCURRENTLIMIT"){} +record(ao, "$(P)SIM:NEGCURRENTLIMIT"){} +record(ao, "$(P)SIM:HEATERCURRENT"){} +record(ao, "$(P)SIM:TRIPFIELD"){} +record(ao, "$(P)SIM:TRIPCURRENT"){} +record(ao, "$(P)SIM:CURR:RATE"){} +record(ao, "$(P)SIM:SUPPLY:VOLT"){} +record(ao, "$(P)SIM:CURRENT"){} +record(ao, "$(P)SIM:SOFTWAREVOLTAGELIMIT"){} +record(ao, "$(P)SIM:FIELD:RATE"){} +record(ao, "$(P)SIM:FIELD"){} +alias("$(P)SIM:FIELD:RATE", "$(P)SIM:FIELD:RATE:SP") + +record(mbbo, "$(P)SIM:ACTIVITY") { + field(ZRST, "Hold") + field(ZRVL, "0") + field(ONST, "To Setpoint") + field(ONVL, "1") + field(TWST, "To Zero") + field(TWVL, "2") + field(FRST, "Clamp") + field(FRVL, "4") +} + +alias("$(P)SIM:ACTIVITY", "$(P)SIM:ACTIVITY:SP") +record(bo, "$(P)SIM:HEATER:STATUS") { + field(ZNAM, "Off") + field(ONAM, "On") +} + diff --git a/IPS/IPS-IOC-01App/Db/ips_legacy.db b/IPS/IPS-IOC-01App/Db/ips_legacy.db index cc66ef757..b3b39b2ac 100644 --- a/IPS/IPS-IOC-01App/Db/ips_legacy.db +++ b/IPS/IPS-IOC-01App/Db/ips_legacy.db @@ -9,57 +9,6 @@ record (stringin, "$(P)PROTOCOL") field(PINI, "YES") } -record(bo, "$(P)SIM") -{ - field(SCAN, "Passive") - field(DTYP, "Soft Channel") - field(ZNAM, "NO") - field(ONAM, "YES") - field(VAL, "$(RECSIM=0)") - field(PINI, "YES") -} - -record(bo, "$(P)DISABLE") -{ - field(DESC, "Disable comms") - field(PINI, "YES") - field(VAL, "$(DISABLE=0)") - field(OMSL, "supervisory") - field(ZNAM, "COMMS ENABLED") - field(ONAM, "COMMS DISABLED") -} - -######################################################### -# START OF RECORDS FOR READBACK FROM VERSION COMMAND. -# # Readback of the instrument model and version info. -# # Run the Version command, V. -# # The string was too long to put model and version into same record. -# # Scan this once, probably not needed again. -# The reply comes back and is split amongst other records. -record(stringin, "$(P)GET:VERSION") { - field(DESC, "Examine status") - field(DTYP, "stream") - field(INP, "@OxInstIPS.protocol getVersion($(P)) $(PORT)") - field(PINI, "YES") - field(FLNK, "$(P)MODEL") - field(SCAN, "Passive") - field(SIML, "$(P)SIM") - field(SIOL, "$(P)SIM:DONOTHING") - field(SDIS, "$(P)DISABLE") -} - -record(stringin, "$(P)MODEL") { - field(DESC, "Model") - field(DTYP, "Soft Channel") - field(SCAN, "Passive") - field(FLNK, "$(P)VERSION") -} - -record(stringin, "$(P)VERSION") { - field(DESC, "Firmware version.") - field(DTYP, "Soft Channel") - field(SCAN, "Passive") -} # # Readback from Cn part of Examine command return. record(mbbi, "$(P)CONTROL") { @@ -152,279 +101,6 @@ record(mbbi, "$(P)ACTIVITY") { info(archive, "VAL") } -# Hold means maintaining present current. -# Clamped means you cannot adjust it - powers up in this -# state. Only the set activity hold command can get out -# of the clamped state. Hold will interrupt a sweep. -record(mbbo, "$(P)ACTIVITY:SP") { - field(DESC, "Activity control") - field(DTYP, "stream") - field(SCAN, "Passive") - field(OUT, "@OxInstIPS.protocol setActivity $(PORT)") - field(ZRST, "Hold") - field(ZRVL, "0") - field(ONST, "To Setpoint") - field(ONVL, "1") - field(TWST, "To Zero") - field(TWVL, "2") - field(FRST, "Clamp") - field(FRVL, "4") - - field(SIML, "$(P)SIM") - field(SIOL, "$(P)SIM:ACTIVITY:SP") - field(SDIS, "$(P)DISABLE") -} - -# Think this is the present current the unit is trying to supply. -record(ai, "$(P)CURR") { - field(DESC, "Demand current readback") - field(DTYP, "stream") - field(SCAN, "1 second") - field(INP, "@OxInstIPS.protocol getDemandCurrent $(PORT)") - field(EGU, "A") - field(PREC, "4") - - field(SIML, "$(P)SIM") - field(SIOL, "$(P)SIM:CURRENT") - field(SDIS, "$(P)DISABLE") - - info(archive, "VAL") -} - -# The present current setpoint. -record(ai, "$(P)CURR:SP:RBV") { - field(DESC, "Setpoint current readback") - field(DTYP, "stream") - field(SCAN, "1 second") - field(INP, "@OxInstIPS.protocol getSetpointCurrent $(PORT)") - field(EGU, "A") - field(PREC, "4") - - field(SIML, "$(P)SIM") - field(SIOL, "$(P)SIM:CURRENT") - field(SDIS, "$(P)DISABLE") - - info(archive, "VAL") -} - -# The present voltage. -record(ai, "$(P)SUPPLY:VOLT") { - field(DESC, "Supply voltage readback") - field(DTYP, "stream") - field(SCAN, "1 second") - field(INP, "@OxInstIPS.protocol getSupplyVoltage $(PORT)") - field(EGU, "V") - field(PREC, "8") - - field(SIML, "$(P)SIM") - field(SIOL, "$(P)SIM:SUPPLY:VOLT") - field(SDIS, "$(P)DISABLE") - - field(FLNK, "$(P)SUPPLY:VOLT:_STABILITY:BUF") - - info(archive, "VAL") -} - -record(compress, "$(P)SUPPLY:VOLT:_STABILITY:BUF") { - field(INP, "$(P)SUPPLY:VOLT") - field(ALG, "Circular Buffer") - field(NSAM, "5") - field(FLNK, "$(P)SUPPLY:VOLT:_STABILITY:LOW") -} - -record(compress, "$(P)SUPPLY:VOLT:_STABILITY:LOW") { - field(INP, "$(P)SUPPLY:VOLT:_STABILITY:BUF") - field(ALG, "N to 1 Low Value") - field(NSAM, "1") - field(N, "5") - field(FLNK, "$(P)SUPPLY:VOLT:_STABILITY:HIGH") -} - -record(compress, "$(P)SUPPLY:VOLT:_STABILITY:HIGH") { - field(INP, "$(P)SUPPLY:VOLT:_STABILITY:BUF") - field(ALG, "N to 1 High Value") - field(NSAM, "1") - field(N, "5") - field(FLNK, "$(P)SUPPLY:VOLT:_STABILITY:CALC") -} - -record(calcout, "$(P)SUPPLY:VOLT:_STABILITY:CALC") { - field(INPA, "$(P)SUPPLY:VOLT:_STABILITY:HIGH") - field(INPB, "$(P)SUPPLY:VOLT:_STABILITY:LOW") - field(CALC, "ABS(A-B)<$(STABILITY_VOLTAGE)") - field(OUT, "$(P)SUPPLY:VOLT:STABLE PP") - field(OOPT, "Every Time") -} - -record(bo, "$(P)SUPPLY:VOLT:STABLE") { - field(ZNAM, "NO") - field(ONAM, "YES") - info(archive, "VAL") -} - -# The present current measured. -record(ai, "$(P)MAGNET:CURR:MEAS") { - field(DESC, "Measured magnet current readback") - field(DTYP, "stream") - field(SCAN, "1 second") - field(INP, "@OxInstIPS.protocol getMeasuredMagnetCurrent $(PORT)") - field(EGU, "A") - field(PREC, "4") - - field(SIML, "$(P)SIM") - field(SIOL, "$(P)SIM:MAGNET:CURR:MEAS") - field(SDIS, "$(P)DISABLE") - - info(archive, "VAL") -} - -# The present sweeprate for current. -record(ai, "$(P)CURR:RATE") { - field(DESC, "Current sweep rate readback") - field(DTYP, "stream") - field(SCAN, "1 second") - field(INP, "@OxInstIPS.protocol getCurrentSweepRate $(PORT)") - field(EGU, "A/min") - field(PREC, "3") - - field(SIML, "$(P)SIM") - field(SIOL, "$(P)SIM:CURR:RATE") - field(SDIS, "$(P)DISABLE") - - info(archive, "VAL") -} - -# The field the unit is attempting to create. -record(ai, "$(P)FIELD") { - field(DESC, "Demand field readback") - field(DTYP, "stream") - field(SCAN, "1 second") - field(INP, "@OxInstIPS.protocol getDemandField $(PORT)") - field(EGU, "T") - field(PREC, "5") - - field(SIML, "$(P)SIM") - field(SIOL, "$(P)SIM:FIELD") - field(SDIS, "$(P)DISABLE") - - info(INTEREST, "LOW") - info(archive, "VAL") -} - -record(ao, "$(P)FIELD:SP") { - field(DESC, "Set setpoint field") - field(SCAN, "Passive") - field(EGU, "T") - field(PREC, "5") - field(DRVH, "$(MAX_FIELD)") - field(DRVL, "-$(MAX_FIELD)") - - field(SIML, "$(P)SIM") - field(SIOL, "$(P)SIM:FIELD") - field(SDIS, "$(P)DISABLE") - info(archive, "VAL") -} - -# Set the Field Setpoint (i.e. the field the unit will go to and hold for the magnet.) -record(ao, "$(P)FIELD:SP:_RAW") { - field(DESC, "Send raw field to box") - field(DTYP, "stream") - field(SCAN, "Passive") - field(OUT, "@OxInstIPS.protocol setSetpointField $(PORT)") - field(EGU, "T") - field(PREC, "5") - field(DRVH, "$(MAX_FIELD)") - field(DRVL, "-$(MAX_FIELD)") - - field(SIML, "$(P)SIM") - field(SIOL, "$(P)SIM:FIELD") - field(SDIS, "$(P)DISABLE") - info(archive, "VAL") -} - -# The present field setpoint. The target field the unit will aim for when -# told to go to the setpoint. -record(ai, "$(P)FIELD:SP:RBV") { - field(DESC, "Setpoint field readback") - field(DTYP, "stream") - field(SCAN, "1 second") - field(INP, "@OxInstIPS.protocol getSetpointField $(PORT)") - field(EGU, "T") - field(PREC, "5") - - field(SIML, "$(P)SIM") - field(SIOL, "$(P)SIM:FIELD") - field(SDIS, "$(P)DISABLE") - info(archive, "VAL") -} - -# The present sweeprate (a.k.a. ramprate) for adjusting the field. -record(ai, "$(P)FIELD:RATE") { - field(DESC, "Field sweep rate readback") - field(DTYP, "stream") - field(SCAN, "1 second") - field(INP, "@OxInstIPS.protocol getFieldSweepRate $(PORT)") - field(EGU, "T/min") - field(PREC, "4") - - field(LOLO, "0") - field(LLSV, "MAJOR") - - field(SIML, "$(P)SIM") - field(SIOL, "$(P)SIM:FIELD:RATE") - field(SDIS, "$(P)DISABLE") - info(INTEREST, "HIGH") - info(archive, "VAL") -} - -record(ao, "$(P)FIELD:RATE:SP") { - field(DESC, "Set field sweep rate") - field(DTYP, "stream") - field(SCAN, "Passive") - field(OUT, "@OxInstIPS.protocol setFieldSweepRate $(PORT)") - field(EGU, "T/min") - field(PREC, "4") - field(DRVH, "$(MAX_SWEEP_RATE)") - field(DRVL, "0") - field(ASG, "$(MANAGER_ASG)") - - field(SIML, "$(P)SIM") - field(SIOL, "$(P)SIM:FIELD:RATE:SP") - field(SDIS, "$(P)DISABLE") -} - -# The voltage at which the unit will stop ramping/sweeping at the sweeprate -# requested, but reduce it to protect the voltage. -record(ai, "$(P)VOLT:LIMIT:SOFTWARE") { - field(DESC, "Software voltage limit readback") - field(DTYP, "stream") - field(SCAN, "1 second") - field(INP, "@OxInstIPS.protocol getSoftwareVoltageLimit $(PORT)") - field(EGU, "V") - field(PREC, "8") - - field(SIML, "$(P)SIM") - field(SIOL, "$(P)SIM:SOFTWAREVOLTAGELIMIT") - field(SDIS, "$(P)DISABLE") -} - -# This is the current that is in the magnet, which in the case of a magnet with a switch -# and a heater is preserved even when the power unit is not connected (cos of how -# superconducting magnets behave). -record(ai, "$(P)MAGNET:CURR:PERSISTENT") { - field(DESC, "Persistent magnet current readback") - field(DTYP, "stream") - field(SCAN, "1 second") - field(INP, "@OxInstIPS.protocol getPersistentMagnetCurrent $(PORT)") - field(EGU, "A") - field(PREC, "4") - - field(SIML, "$(P)SIM") - field(SIOL, "$(P)SIM:PERSISTENTMAGNETCURRENT") - field(SDIS, "$(P)DISABLE") - - info(archive, "VAL") -} # The current at which a trip last occurred. Am not sure if by trip, they mean # a quench or a problem with the level meter. Believe the unit will take the current @@ -445,23 +121,6 @@ record(ai, "$(P)CURR:TRIP") { info(archive, "VAL") } -# The field in the magnet due to the persistent current. See current for explanation. -record(ai, "$(P)MAGNET:FIELD:PERSISTENT") { - field(DESC, "Persistent magnet field readback") - field(DTYP, "stream") - field(SCAN, "1 second") - field(INP, "@OxInstIPS.protocol getPersistentMagnetField $(PORT)") - field(EGU, "T") - field(PREC, "5") - - field(SIML, "$(P)SIM") - field(SIOL, "$(P)SIM:PERSISTENTMAGNETFIELD") - field(SDIS, "$(P)DISABLE") - - info(INTEREST, "LOW") - - info(archive, "VAL") -} # The field at which a trip last occurred. See current for explanation. record(ai, "$(P)FIELD:TRIP") { @@ -529,40 +188,6 @@ record(ai, "$(P)CURR:LIMIT:POS") { info(archive, "VAL") } -# The resistance of the lead from the unit to the magnet that carries -# the current. This is set by the supplier in the controller, all this -# record does is read and report the value. -record(ai, "$(P)RESISTANCE:LEAD") { - field(DESC, "Leadresistance readback") - field(DTYP, "stream") - field(SCAN, "1 second") - field(INP, "@OxInstIPS.protocol getLeadResistance $(PORT)") - field(EGU, "mohm") - field(PREC, "5") - - field(SIML, "$(P)SIM") - field(SIOL, "$(P)SIM:LEADRESISTANCE") - field(SDIS, "$(P)DISABLE") - - info(archive, "VAL") -} - -# The inductance of the magnet. Believe this is also set by the supplier -# as a calibration. -record(ai, "$(P)MAGNET:INDUCTANCE") { - field(DESC, "Magnet inductance readback") - field(DTYP, "stream") - field(SCAN, "1 second") - field(INP, "@OxInstIPS.protocol getMagnetInductance $(PORT)") - field(EGU, "H") - field(PREC, "5") - - field(SIML, "$(P)SIM") - field(SIOL, "$(P)SIM:MAGNETINDUCTANCE") - field(SDIS, "$(P)DISABLE") - - info(archive, "VAL") -} # # Run the Examine Status command, X. # The reply comes back and is split amongst other records. @@ -651,179 +276,6 @@ record(mbbi, "$(P)HEATER:STATUS") { info(archive, "VAL") } -record(bo, "$(P)HEATER:STATUS:SP") { - field(DESC, "Set Remote/Local Control") - field(DTYP, "stream") - field(SCAN, "Passive") - field(OUT, "@OxInstIPS.protocol setHeaterStatus $(PORT)") - field(ZNAM, "Off") - field(ONAM, "On") - - field(SIML, "$(P)SIM") - field(SIOL, "$(P)SIM:HEATER:STATUS:SP") - field(SDIS, "$(P)DISABLE") -} - -# Amount of time to wait for heater to warm up/cool down. **CAN CAUSE MAGNET TO QUENCH IF SET TOO LOW** -# Oxford Instruments labview driver uses 30s. ISIS cryogenics have asked us to increase this to 60s, -# which is more conservative. -# The HEATER_WAITTIME IOC macro, which is _not_ user-facing, has a default of 60s. -# Configurable to lower values to shorten time for IOC tests. - -record(ao, "$(P)HEATER:WAITTIME") { - field(DESC, "Time to wait for heater") - field(VAL, "$(HEATER_WAITTIME)") - field(PINI, "YES") - info(archive, "VAL") -} - -# CALC record to coerce heater status values. Heater can be off in states 0 or 2, and in error in states 5 or 8, -# and circular buffer (N to 1 Low Value) only looks for lowest (0). -# Output 1 only if heater is on, 0 if off and all other states, including errors. - -record(calc, "$(P)HEATER:_STATUS_CALC") { - field(DESC, "Binary Heater Status") - field(INPA, "$(P)HEATER:STATUS CP MS") - field(CALC, "(A=1)?1:0") # If heater is on, output 1, otherwise 0 - info(archive, "VAL") -} - -# COMPRESS Record with circular buffer to store $(HEATER_WAITTIME) worth of HEATER:STATUS values -# Used with second COMPRESS record below to check heater has been on for at least $(HEATER_WAITTIME) after starting IOC - -record(compress, "$(P)HEATER:_STATUS_BUFFER") { - field(DESC, "Buffer of heater status values") - field(INP, "$(P)HEATER:_STATUS_CALC.VAL") - field(ALG, "Circular Buffer") - field(NSAM, "$(HEATER_WAITTIME)") - field(SCAN, "1 second") - field(FLNK, "$(P)HEATER:_STATUS_BUFFER_LOWEST") -} - -# COMPRESS record to monitor above and output lowest value in buffer. -# If '1' then whole buffer contains '1' and therefore heater has been ON for at least $(HEATER_WAITTIME) -# If '0' then heater has been OFF at some point in $(HEATER_WAITTIME) - -record(compress, "$(P)HEATER:_STATUS_BUFFER_LOWEST") { - field(DESC, "Lowest value of heater status buffer") - field(INP, "$(P)HEATER:_STATUS_BUFFER") - field(ALG, "N to 1 Low Value") - field(NSAM, "1") - field(N, "$(HEATER_WAITTIME)") - field(FLNK, "$(P)HEATER:ONTIME_OK") - info(archive, "VAL") -} - -# BO record to indicate whether or not heater been on for at least $(HEATER_WAITTIME). Monitored by statemachine to determine whether or not OK to set field. - -record(bo, "$(P)HEATER:ONTIME_OK") { - field(DESC, "Heater on for at least $(HEATER_WAITTIME)s") - field(DTYP, "Soft Channel") - field(SCAN, "Passive") - field(OMSL, "closed_loop") - field(DOL, "$(P)HEATER:_STATUS_BUFFER_LOWEST.VAL") - field(ZNAM, "Heater OFF in last $(HEATER_WAITTIME)s") - field(ONAM, "Heater ON for > $(HEATER_WAITTIME)s") - info(archive, "VAL") -} - - -# Readback from m of Mmn part of Examine command return. -# The Display is in Amps or Tesla. The Magnet Sweep is fast or slow. -record(mbbi, "$(P)SWEEPMODE:PARAMS") { - field(DESC, "Mode status") - field(DTYP, "Soft Channel") - field(SCAN, "Passive") - field(ZRST, "Amps Fast") - field(ZRVL, "0") - field(ONST, "Tesla Fast") - field(ONVL, "1") - field(TWST, "Amps Fast") - field(TWVL, "2") - field(THST, "Tesla Fast") - field(THVL, "3") - field(FRST, "Amps Slow") - field(FRVL, "4") - field(FVST, "Tesla Slow") - field(FVVL, "5") - field(SXST, "Amps Slow") - field(SXVL, "6") - field(SVST, "Tesla Slow") - field(SVVL, "7") - field(EIST, "Amps Unaffected") - field(EIVL, "8") - field(NIST, "Tesla Unaffected") - field(NIVL, "9") - - field(VAL, "3") - field(PINI, "YES") - - field(SIML, "$(P)SIM") - field(SIOL, "$(P)SIM:SWEEPMODE:PARAMS") - field(SDIS, "$(P)DISABLE") - - info(archive, "VAL") -} - -# To set the sweep and display mode - its a bit confusing as there -# are duplicates, but we do not present this choice to the user. -# -record(mbbo, "$(P)SWEEPMODE:PARAMS:SP") { - field(DESC, "Set sweep and display mode.") - field(DTYP, "stream") - field(SCAN, "Passive") - field(ZRST, "Amps Fast") - field(ZRVL, "0") - field(ONST, "Tesla Fast") - field(ONVL, "1") - field(TWST, "Amps Fast") - field(TWVL, "2") - field(THST, "Tesla Fast") - field(THVL, "3") - field(FRST, "Amps Slow") - field(FRVL, "4") - field(FVST, "Tesla Slow") - field(FVVL, "5") - field(SXST, "Amps Slow") - field(SXVL, "6") - field(SVST, "Tesla Slow") - field(SVVL, "7") - field(EIST, "Amps Unaffected") - field(EIVL, "8") - field(NIST, "Tesla Unaffected") - field(NIVL, "9") - field(OUT, "@OxInstIPS.protocol setMode $(PORT)") - - field(VAL, "3") - field(PINI, "YES") - - field(SIML, "$(P)SIM") - field(SIOL, "$(P)SIM:SWEEPMODE:PARAMS:SP") - field(SDIS, "$(P)DISABLE") -} - -# Readback from n of Mmn part of Examine command return. -# (Ignore the Pmn part of the Examine command return - no records for this.) -# 0 output constant, 1, 2, 3 output changing -record(mbbi, "$(P)STS:SWEEPMODE:SWEEP") { - field(DESC, "Mode status") - field(DTYP, "Soft Channel") - field(SCAN, "Passive") - field(ZRST, "At rest") - field(ZRVL, "0") - field(ONST, "Sweeping") - field(ONVL, "1") - field(TWST, "Sweep Limiting") - field(TWVL, "2") - field(THST, "Swping & Lmting") - field(THVL, "3") - - field(SIML, "$(P)SIM") - field(SIOL, "$(P)SIM:STS:SWEEPMODE:SWEEP") - field(SDIS, "$(P)DISABLE") - - info(archive, "VAL") -} # To capture bits of mismatching status protocol. # We do not do much with it at the moment. @@ -869,76 +321,36 @@ record(ao, "$(P)SET:WAITINTERVAL") { field(SDIS, "$(P)DISABLE") } -record(bo, "$(P)PERSISTENT") { - field(DESC, "Set magnet to persistent") - field(ZNAM, "NO") - field(ONAM, "YES") - field(PINI, "YES") - info(autosaveFields, "VAL") - info(INTEREST, "HIGH") - info(archive, "VAL") -} - -# Play nicely with blocks/genie_python -alias("$(P)PERSISTENT", "$(P)PERSISTENT:SP") - - -record(mbbo, "$(P)STATEMACHINE") { - field(DESC, "What the IOC is doing") - +record(mbbo, "$(P)SIM:SWEEPMODE:PARAMS") { + field(ZRST, "Amps Fast") field(ZRVL, "0") - field(ZRST, "Initial state") - + field(ONST, "Tesla Fast") field(ONVL, "1") - field(ONST, "At field") - + field(TWST, "Amps Fast") field(TWVL, "2") - field(TWST, "Set PSU to match magnet") - + field(THST, "Tesla Fast") field(THVL, "3") - field(THST, "Wait for volts stable") - + field(FRST, "Amps Slow") field(FRVL, "4") - field(FRST, "Ensure heater on & warm") - + field(FVST, "Tesla Slow") field(FVVL, "5") - field(FVST, "Set PSU to setpoint") - + field(SXST, "Amps Slow") field(SXVL, "6") - field(SXST, "Turn heater off & wait") - + field(SVST, "Tesla Slow") field(SVVL, "7") - field(SVST, "Set PSU to zero") - - info(archive, "VAL") -} - - -### -### Records to be more "friendly" to the user. -### - -record(calc, "$(P)FIELD:USER") { - field(DESC, "Field readback") - field(INPA, "$(P)MAGNET:FIELD:PERSISTENT CP MS") - field(INPB, "$(P)FIELD CP MS") - field(INPC, "$(P)HEATER:STATUS CP MS") - field(CALC, "(C=0||C=2)?A:B") # If heater is present and switched off, display persistent field, else display PSU field - field(ASG, "READONLY") - field(EGU, "T") - field(PREC, "5") - info(interest, "HIGH") - info(archive, "VAL") + field(EIST, "Amps Unaffected") + field(EIVL, "8") + field(NIST, "Tesla Unaffected") + field(NIVL, "9") } -alias("$(P)FIELD:SP", "$(P)FIELD:USER:SP") # "User" setpoint is same as "normal" setpoint - - -### Simulation record - Just to stop errors, doesn't do anything - -record(ao, "$(P)SIM:DONOTHING") {} - -record(mbbo, "$(P)SIM:SWEEPMODE:PARAMS") { +# To set the sweep and display mode - its a bit confusing as there +# are duplicates, but we do not present this choice to the user. +# +record(mbbo, "$(P)SWEEPMODE:PARAMS:SP") { + field(DESC, "Set sweep and display mode.") + field(DTYP, "stream") + field(SCAN, "Passive") field(ZRST, "Amps Fast") field(ZRVL, "0") field(ONST, "Tesla Fast") @@ -959,44 +371,18 @@ record(mbbo, "$(P)SIM:SWEEPMODE:PARAMS") { field(EIVL, "8") field(NIST, "Tesla Unaffected") field(NIVL, "9") -} + field(OUT, "@$(PROTO) setMode $(PORT)") -alias("$(P)SIM:SWEEPMODE:PARAMS", "$(P)SIM:SPEEPMODE:PARAMS:SP") + field(VAL, "3") + field(PINI, "YES") -record(bo, "$(P)SIM:HEATER:STATUS") { - field(ZNAM, "Off") - field(ONAM, "On") + field(SIML, "$(P)SIM") + field(SIOL, "$(P)SIM:SWEEPMODE:PARAMS:SP") + field(SDIS, "$(P)DISABLE") } -alias("$(P)SIM:HEATER:STATUS", "$(P)SIM:HEATER:STATUS:SP") - -record(ao, "$(P)SIM:MAGNETINDUCTANCE"){} -record(ao, "$(P)SIM:LEADRESISTANCE"){} -record(ao, "$(P)SIM:POSCURRENTLIMIT"){} -record(ao, "$(P)SIM:NEGCURRENTLIMIT"){} -record(ao, "$(P)SIM:HEATERCURRENT"){} -record(ao, "$(P)SIM:TRIPFIELD"){} -record(ao, "$(P)SIM:TRIPCURRENT"){} -record(ao, "$(P)SIM:CURR:RATE"){} -record(ao, "$(P)SIM:SUPPLY:VOLT"){} -record(ao, "$(P)SIM:CURRENT"){} -record(ao, "$(P)SIM:SOFTWAREVOLTAGELIMIT"){} -record(ao, "$(P)SIM:FIELD:RATE"){} -record(ao, "$(P)SIM:FIELD"){} -alias("$(P)SIM:FIELD:RATE", "$(P)SIM:FIELD:RATE:SP") - -record(mbbo, "$(P)SIM:ACTIVITY") { - field(ZRST, "Hold") - field(ZRVL, "0") - field(ONST, "To Setpoint") - field(ONVL, "1") - field(TWST, "To Zero") - field(TWVL, "2") - field(FRST, "Clamp") - field(FRVL, "4") -} +alias("$(P)SIM:SWEEPMODE:PARAMS", "$(P)SIM:SPEEPMODE:PARAMS:SP") -alias("$(P)SIM:ACTIVITY", "$(P)SIM:ACTIVITY:SP") record(mbbo, "$(P)SIM:CONTROL") { field(ZRST, "Local & Locked") diff --git a/IPS/IPS-IOC-01App/Db/ips_scpi.db b/IPS/IPS-IOC-01App/Db/ips_scpi.db index 641db342b..510b28ba9 100644 --- a/IPS/IPS-IOC-01App/Db/ips_scpi.db +++ b/IPS/IPS-IOC-01App/Db/ips_scpi.db @@ -9,59 +9,6 @@ record (stringin, "$(P)PROTOCOL") field(PINI, "YES") } -record(bo, "$(P)SIM") -{ - field(SCAN, "Passive") - field(DTYP, "Soft Channel") - field(ZNAM, "NO") - field(ONAM, "YES") - field(VAL, "$(RECSIM=0)") - field(PINI, "YES") -} - -record(bo, "$(P)DISABLE") -{ - field(DESC, "Disable comms") - field(PINI, "YES") - field(VAL, "$(DISABLE=0)") - field(OMSL, "supervisory") - field(ZNAM, "COMMS ENABLED") - field(ONAM, "COMMS DISABLED") -} - -######################################################### -# START OF RECORDS FOR READBACK FROM VERSION COMMAND. -# # Readback of the instrument model and version info. -# # Run the Version command, V. -# # The string was too long to put model and version into same record. -# # Scan this once, probably not needed again. -# The reply comes back and is split amongst other records in the StreamDevice protocol file. -record(stringin, "$(P)GET:VERSION") { - field(DESC, "Examine status") - field(DTYP, "stream") - field(INP, "@OxInstIPS_SCPI.protocol getVersion($(P)) $(PORT)") - field(PINI, "YES") - field(FLNK, "$(P)MODEL") - field(SCAN, "Passive") - field(SIML, "$(P)SIM") - field(SIOL, "$(P)SIM:DONOTHING") - field(SDIS, "$(P)DISABLE") -} - -# Updated in GET:VERSION call to getVersion() -record(stringin, "$(P)MODEL") { - field(DESC, "Model") - field(DTYP, "Soft Channel") - field(SCAN, "Passive") - field(FLNK, "$(P)VERSION") -} - -# Updated in GET:VERSION call to getVersion() -record(stringin, "$(P)VERSION") { - field(DESC, "Firmware version.") - field(DTYP, "Soft Channel") - field(SCAN, "Passive") -} # Readback from STAT:DEV:GRPZ:PSU:ACTN command return (in getActivity()). # Hold means maintaining present current. @@ -93,384 +40,13 @@ record(mbbi, "$(P)ACTIVITY") { info(archive, "VAL") } -# Hold means maintaining present current. -# Clamped means you cannot adjust it - powers up in this -# state. Only the set activity hold command can get out -# of the clamped state. Hold will interrupt a sweep. -record(mbbo, "$(P)ACTIVITY:SP") { - field(DESC, "Activity control") - field(DTYP, "stream") - field(SCAN, "Passive") - field(OUT, "@OxInstIPS_SCPI.protocol setActivity $(PORT)") - field(ZRST, "Hold") - field(ZRVL, "0") - field(ONST, "To Setpoint") - field(ONVL, "1") - field(TWST, "To Zero") - field(TWVL, "2") - field(FRST, "Clamp") - field(FRVL, "4") - - field(SIML, "$(P)SIM") - field(SIOL, "$(P)SIM:ACTIVITY:SP") - field(SDIS, "$(P)DISABLE") -} - -# Think this is the present current the unit is trying to supply. -record(ai, "$(P)CURR") { - field(DESC, "Demand current readback") - field(DTYP, "stream") - field(SCAN, "1 second") - field(INP, "@OxInstIPS_SCPI.protocol getDemandCurrent $(PORT)") - field(EGU, "A") - field(PREC, "4") - - field(SIML, "$(P)SIM") - field(SIOL, "$(P)SIM:CURRENT") - field(SDIS, "$(P)DISABLE") - - info(archive, "VAL") -} - -# The present current setpoint. -record(ai, "$(P)CURR:SP:RBV") { - field(DESC, "Setpoint current readback") - field(DTYP, "stream") - field(SCAN, "1 second") - field(INP, "@OxInstIPS_SCPI.protocol getSetpointCurrent $(PORT)") - field(EGU, "A") - field(PREC, "4") - - field(SIML, "$(P)SIM") - field(SIOL, "$(P)SIM:CURRENT") - field(SDIS, "$(P)DISABLE") - - info(archive, "VAL") -} - -# The present voltage. -record(ai, "$(P)SUPPLY:VOLT") { - field(DESC, "Supply voltage readback") - field(DTYP, "stream") - field(SCAN, "1 second") - field(INP, "@OxInstIPS_SCPI.protocol getSupplyVoltage $(PORT)") - field(EGU, "V") - field(PREC, "8") - - field(SIML, "$(P)SIM") - field(SIOL, "$(P)SIM:SUPPLY:VOLT") - field(SDIS, "$(P)DISABLE") - - field(FLNK, "$(P)SUPPLY:VOLT:_STABILITY:BUF") - - info(archive, "VAL") -} - -record(compress, "$(P)SUPPLY:VOLT:_STABILITY:BUF") { - field(INP, "$(P)SUPPLY:VOLT") - field(ALG, "Circular Buffer") - field(NSAM, "5") - field(FLNK, "$(P)SUPPLY:VOLT:_STABILITY:LOW") -} - -record(compress, "$(P)SUPPLY:VOLT:_STABILITY:LOW") { - field(INP, "$(P)SUPPLY:VOLT:_STABILITY:BUF") - field(ALG, "N to 1 Low Value") - field(NSAM, "1") - field(N, "5") - field(FLNK, "$(P)SUPPLY:VOLT:_STABILITY:HIGH") -} - -record(compress, "$(P)SUPPLY:VOLT:_STABILITY:HIGH") { - field(INP, "$(P)SUPPLY:VOLT:_STABILITY:BUF") - field(ALG, "N to 1 High Value") - field(NSAM, "1") - field(N, "5") - field(FLNK, "$(P)SUPPLY:VOLT:_STABILITY:CALC") -} - -record(calcout, "$(P)SUPPLY:VOLT:_STABILITY:CALC") { - field(INPA, "$(P)SUPPLY:VOLT:_STABILITY:HIGH") - field(INPB, "$(P)SUPPLY:VOLT:_STABILITY:LOW") - field(CALC, "ABS(A-B)<$(STABILITY_VOLTAGE)") - field(OUT, "$(P)SUPPLY:VOLT:STABLE PP") - field(OOPT, "Every Time") -} - -record(bo, "$(P)SUPPLY:VOLT:STABLE") { - field(ZNAM, "NO") - field(ONAM, "YES") - info(archive, "VAL") -} - -# The present current measured. -record(ai, "$(P)MAGNET:CURR:MEAS") { - field(DESC, "Measured magnet current readback") - field(DTYP, "stream") - field(SCAN, "1 second") - field(INP, "@OxInstIPS_SCPI.protocol getMeasuredMagnetCurrent $(PORT)") - field(EGU, "A") - field(PREC, "4") - - field(SIML, "$(P)SIM") - field(SIOL, "$(P)SIM:MAGNET:CURR:MEAS") - field(SDIS, "$(P)DISABLE") - - info(archive, "VAL") -} - -# The present sweeprate for current. -record(ai, "$(P)CURR:RATE") { - field(DESC, "Current sweep rate readback") - field(DTYP, "stream") - field(SCAN, "1 second") - field(INP, "@OxInstIPS_SCPI.protocol getCurrentSweepRate $(PORT)") - field(EGU, "A/min") - field(PREC, "3") - - field(SIML, "$(P)SIM") - field(SIOL, "$(P)SIM:CURR:RATE") - field(SDIS, "$(P)DISABLE") - - info(archive, "VAL") -} - -# The field the unit is attempting to create. -record(ai, "$(P)FIELD") { - field(DESC, "Demand field readback") - field(DTYP, "stream") - field(SCAN, "1 second") - field(INP, "@OxInstIPS_SCPI.protocol getDemandField $(PORT)") - field(EGU, "T") - field(PREC, "5") - - field(SIML, "$(P)SIM") - field(SIOL, "$(P)SIM:FIELD") - field(SDIS, "$(P)DISABLE") - - info(INTEREST, "LOW") - info(archive, "VAL") -} - -record(ao, "$(P)FIELD:SP") { - field(DESC, "Set setpoint field") - field(SCAN, "Passive") - field(EGU, "T") - field(PREC, "5") - field(DRVH, "$(MAX_FIELD)") - field(DRVL, "-$(MAX_FIELD)") - - field(SIML, "$(P)SIM") - field(SIOL, "$(P)SIM:FIELD") - field(SDIS, "$(P)DISABLE") - info(archive, "VAL") -} - -# Set the Field Setpoint (i.e. the field the unit will go to and hold for the magnet.) -record(ao, "$(P)FIELD:SP:_RAW") { - field(DESC, "Send raw field to box") - field(DTYP, "stream") - field(SCAN, "Passive") - field(OUT, "@OxInstIPS_SCPI.protocol setSetpointField $(PORT)") - field(EGU, "T") - field(PREC, "5") - field(DRVH, "$(MAX_FIELD)") - field(DRVL, "-$(MAX_FIELD)") - - field(SIML, "$(P)SIM") - field(SIOL, "$(P)SIM:FIELD") - field(SDIS, "$(P)DISABLE") - info(archive, "VAL") -} - -# The present field setpoint. The target field the unit will aim for when -# told to go to the setpoint. -record(ai, "$(P)FIELD:SP:RBV") { - field(DESC, "Setpoint field readback") - field(DTYP, "stream") - field(SCAN, "1 second") - field(INP, "@OxInstIPS_SCPI.protocol getSetpointField $(PORT)") - field(EGU, "T") - field(PREC, "5") - - field(SIML, "$(P)SIM") - field(SIOL, "$(P)SIM:FIELD") - field(SDIS, "$(P)DISABLE") - info(archive, "VAL") -} - -# The present sweeprate (a.k.a. ramprate) for adjusting the field. -record(ai, "$(P)FIELD:RATE") { - field(DESC, "Field sweep rate readback") - field(DTYP, "stream") - field(SCAN, "1 second") - field(INP, "@OxInstIPS_SCPI.protocol getFieldSweepRate $(PORT)") - field(EGU, "T/min") - field(PREC, "4") - - field(LOLO, "0") - field(LLSV, "MAJOR") - - field(SIML, "$(P)SIM") - field(SIOL, "$(P)SIM:FIELD:RATE") - field(SDIS, "$(P)DISABLE") - info(INTEREST, "HIGH") - info(archive, "VAL") -} - -record(ao, "$(P)FIELD:RATE:SP") { - field(DESC, "Set field sweep rate") - field(DTYP, "stream") - field(SCAN, "Passive") - field(OUT, "@OxInstIPS_SCPI.protocol setFieldSweepRate $(PORT)") - field(EGU, "T/min") - field(PREC, "4") - field(DRVH, "$(MAX_SWEEP_RATE)") - field(DRVL, "0") - field(ASG, "$(MANAGER_ASG)") - - field(SIML, "$(P)SIM") - field(SIOL, "$(P)SIM:FIELD:RATE:SP") - field(SDIS, "$(P)DISABLE") -} - -# The voltage at which the unit will stop ramping/sweeping at the sweeprate -# requested, but reduce it to protect the voltage. -record(ai, "$(P)VOLT:LIMIT:SOFTWARE") { - field(DESC, "Software voltage limit readback") - field(DTYP, "stream") - field(SCAN, "1 second") - field(INP, "@OxInstIPS_SCPI.protocol getSoftwareVoltageLimit $(PORT)") - field(EGU, "V") - field(PREC, "8") - - field(SIML, "$(P)SIM") - field(SIOL, "$(P)SIM:SOFTWAREVOLTAGELIMIT") - field(SDIS, "$(P)DISABLE") -} - -# This is the current that is in the magnet, which in the case of a magnet with a switch -# and a heater is preserved even when the power unit is not connected (cos of how -# superconducting magnets behave). -record(ai, "$(P)MAGNET:CURR:PERSISTENT") { - field(DESC, "Persistent magnet current readback") - field(DTYP, "stream") - field(SCAN, "1 second") - field(INP, "@OxInstIPS_SCPI.protocol getPersistentMagnetCurrent $(PORT)") - field(EGU, "A") - field(PREC, "4") - - field(SIML, "$(P)SIM") - field(SIOL, "$(P)SIM:PERSISTENTMAGNETCURRENT") - field(SDIS, "$(P)DISABLE") - - info(archive, "VAL") -} - -# The field in the magnet due to the persistent current. See current for explanation. -record(ai, "$(P)MAGNET:FIELD:PERSISTENT") { - field(DESC, "Persistent magnet field readback") - field(DTYP, "stream") - field(SCAN, "1 second") - field(INP, "@OxInstIPS_SCPI.protocol getPersistentMagnetField $(PORT)") - field(EGU, "T") - field(PREC, "5") - - field(SIML, "$(P)SIM") - field(SIOL, "$(P)SIM:PERSISTENTMAGNETFIELD") - field(SDIS, "$(P)DISABLE") - - info(INTEREST, "LOW") - - info(archive, "VAL") -} - -# The current being provided to the heater. -record(ai, "$(P)HEATER:CURR") { - field(DESC, "Heater current readback") - field(DTYP, "stream") - field(SCAN, "1 second") - field(INP, "@OxInstIPS_SCPI.protocol getHeaterCurrent $(PORT)") - field(EGU, "mA") - field(PREC, "4") - - field(SIML, "$(P)SIM") - field(SIOL, "$(P)SIM:HEATERCURRENT") - field(SDIS, "$(P)DISABLE") - - info(archive, "VAL") -} -# The lower limit for the current. This refers to a limit on the controller and -# is nothing to do with EPICS record limit or alarm fields. -record(ai, "$(P)CURR:LIMIT:NEG") { - field(DESC, "Neg current limit readback") - field(DTYP, "stream") - field(SCAN, "1 second") - field(INP, "@OxInstIPS_SCPI.protocol getNegCurrentLimit $(PORT)") - field(EGU, "A") - field(PREC, "4") - - field(SIML, "$(P)SIM") - field(SIOL, "$(P)SIM:NEGCURRENTLIMIT") - field(SDIS, "$(P)DISABLE") - - info(archive, "VAL") -} -# The higher limit for the current. This refers to a limit on the controller and -# is nothing to do with EPICS record limit or alarm fields. -record(ai, "$(P)CURR:LIMIT:POS") { - field(DESC, "Pos current limit readback") - field(DTYP, "stream") - field(SCAN, "1 second") - field(INP, "@OxInstIPS_SCPI.protocol getPosCurrentLimit $(PORT)") - field(EGU, "A") - field(PREC, "4") - - field(SIML, "$(P)SIM") - field(SIOL, "$(P)SIM:POSCURRENTLIMIT") - field(SDIS, "$(P)DISABLE") - - info(archive, "VAL") -} -# The resistance of the lead from the unit to the magnet that carries -# the current. This is set by the supplier in the controller, all this -# record does is read and report the value. -record(ai, "$(P)RESISTANCE:LEAD") { - field(DESC, "Leadresistance readback") - field(DTYP, "stream") - field(SCAN, "1 second") - field(INP, "@OxInstIPS_SCPI.protocol getLeadResistance $(PORT)") - field(EGU, "mohm") - field(PREC, "5") - - field(SIML, "$(P)SIM") - field(SIOL, "$(P)SIM:LEADRESISTANCE") - field(SDIS, "$(P)DISABLE") - - info(archive, "VAL") -} - -# The inductance of the magnet. Believe this is also set by the supplier -# as a calibration. -record(ai, "$(P)MAGNET:INDUCTANCE") { - field(DESC, "Magnet inductance readback") - field(DTYP, "stream") - field(SCAN, "1 second") - field(INP, "@OxInstIPS_SCPI.protocol getMagnetInductance $(PORT)") - field(EGU, "H") - field(PREC, "5") - - field(SIML, "$(P)SIM") - field(SIOL, "$(P)SIM:MAGNETINDUCTANCE") - field(SDIS, "$(P)DISABLE") - - info(archive, "VAL") -} # --------------- The following work around limitation of getting legacy status from SCPI protocol ------------- +# Note that the mbbiDirect is split into individual bi records for each status bit, via the +# scpi_system_alarms_discrete.template and substitution files. # Get the status DWORD from each group UID record(mbbiDirect, "$(P)GET:MAGNET:SUPPLY:STATUS") { @@ -485,198 +61,6 @@ record(mbbiDirect, "$(P)GET:MAGNET:SUPPLY:STATUS") { field(SDIS, "$(P)DISABLE") } -# Determine the switch heater mismatch status from the supply status bit -record(bi, "$(P)MAGNET:SUPPLY:STATUS:SWHTRMISMATCH") { - field(DESC, "Switch heater mismatch status") - field(DTYP, "Soft Channel") - field(SCAN, "Passive") - field(INP, "$(P)GET:MAGNET:SUPPLY:STATUS.B0 CP MS") - field(ZNAM, "No") - field(ONAM, "Yes") - field(ZSV, "NO_ALARM") - field(OSV, "MAJOR") -} - -# Determine the Over Temperature (rundown resistors) status from the supply status bit -record(bi, "$(P)MAGNET:SUPPLY:STATUS:OTRUNDOWNRES") { - field(DESC, "Over temp rundown resistors status") - field(DTYP, "Soft Channel") - field(SCAN, "Passive") - field(INP, "$(P)GET:MAGNET:SUPPLY:STATUS.B1 CP MS") - field(ZNAM, "No") - field(ONAM, "Yes") - field(ZSV, "NO_ALARM") - field(OSV, "MAJOR") -} - -# Determine the Over Temperature (sense resistor) status from the supply status bit -record(bi, "$(P)MAGNET:SUPPLY:STATUS:OTSENSERES") { - field(DESC, "Over temp sense resistor status") - field(DTYP, "Soft Channel") - field(SCAN, "Passive") - field(INP, "$(P)GET:MAGNET:SUPPLY:STATUS.B2 CP MS") - field(ZNAM, "No") - field(ONAM, "Yes") - field(ZSV, "NO_ALARM") - field(OSV, "MAJOR") -} - -# Determine the Over Temperature (PCB) status from the supply status bit -record(bi, "$(P)MAGNET:SUPPLY:STATUS:OTPCB") { - field(DESC, "Over temp PCB status") - field(DTYP, "Soft Channel") - field(SCAN, "Passive") - field(INP, "$(P)GET:MAGNET:SUPPLY:STATUS.B3 CP MS") - field(ZNAM, "No") - field(ONAM, "Yes") - field(ZSV, "NO_ALARM") - field(OSV, "MAJOR") -} - -# Determine the calibration failure status from the supply status bit -record(bi, "$(P)MAGNET:SUPPLY:STATUS:CALIBFAIL") { - field(DESC, "Calibration failure status") - field(DTYP, "Soft Channel") - field(SCAN, "Passive") - field(INP, "$(P)GET:MAGNET:SUPPLY:STATUS.B4 CP MS") - field(ZNAM, "No") - field(ONAM, "Yes") - field(ZSV, "NO_ALARM") - field(OSV, "MAJOR") -} - -# Determine the MSP430 firmware error failure status from the supply status bit -record(bi, "$(P)MAGNET:SUPPLY:STATUS:FWFAIL") { - field(DESC, "Firmware failure status") - field(DTYP, "Soft Channel") - field(SCAN, "Passive") - field(INP, "$(P)GET:MAGNET:SUPPLY:STATUS.B5 CP MS") - field(ZNAM, "No") - field(ONAM, "Yes") - field(ZSV, "NO_ALARM") - field(OSV, "MAJOR") -} - -# Determine the rundown resistors failure status from the supply status bit -record(bi, "$(P)MAGNET:SUPPLY:STATUS:RRFAIL") { - field(DESC, "Rundown resistors failure status") - field(DTYP, "Soft Channel") - field(SCAN, "Passive") - field(INP, "$(P)GET:MAGNET:SUPPLY:STATUS.B6 CP MS") - field(ZNAM, "No") - field(ONAM, "Yes") - field(ZSV, "NO_ALARM") - field(OSV, "MAJOR") -} - -# Determine the MSP430 RS-485 failure status from the supply status bit -record(bi, "$(P)MAGNET:SUPPLY:STATUS:RS485FAIL") { - field(DESC, "MSP430 RS485 failure status") - field(DTYP, "Soft Channel") - field(SCAN, "Passive") - field(INP, "$(P)GET:MAGNET:SUPPLY:STATUS.B7 CP MS") - field(ZNAM, "No") - field(ONAM, "Yes") - field(ZSV, "NO_ALARM") - field(OSV, "MAJOR") -} - -# Determine the quench status from the supply status bit -record(bi, "$(P)MAGNET:SUPPLY:STATUS:QUENCHED") { - field(DESC, "Quench status") - field(DTYP, "Soft Channel") - field(SCAN, "Passive") - field(INP, "$(P)GET:MAGNET:SUPPLY:STATUS.B8 CP MS") - field(ZNAM, "No") - field(ONAM, "Yes") - field(ZSV, "NO_ALARM") - field(OSV, "MAJOR") -} - -# Determine the catch detection status from the supply status bit -record(bi, "$(P)MAGNET:SUPPLY:STATUS:CATCH") { - field(DESC, "PSU Catch status") - field(DTYP, "Soft Channel") - field(SCAN, "Passive") - field(INP, "$(P)GET:MAGNET:SUPPLY:STATUS.B9 CP MS") - field(ZNAM, "No") - field(ONAM, "Yes") - field(ZSV, "NO_ALARM") - field(OSV, "MAJOR") -} - -# Determine the Sense amplifier over temperature status from the supply status bit -record(bi, "$(P)MAGNET:SUPPLY:STATUS:OTSENSEAMP") { - field(DESC, "Over temp sense amp") - field(DTYP, "Soft Channel") - field(SCAN, "Passive") - field(INP, "$(P)GET:MAGNET:SUPPLY:STATUS.BC CP MS") - field(ZNAM, "No") - field(ONAM, "Yes") - field(ZSV, "NO_ALARM") - field(OSV, "MAJOR") -} - -# Determine amplifier 1 over temperature status from the supply status bit -record(bi, "$(P)MAGNET:SUPPLY:STATUS:OTAMP1") { - field(DESC, "Over temp amp 1") - field(DTYP, "Soft Channel") - field(SCAN, "Passive") - field(INP, "$(P)GET:MAGNET:SUPPLY:STATUS.BD CP MS") - field(ZNAM, "No") - field(ONAM, "Yes") - field(ZSV, "NO_ALARM") - field(OSV, "MAJOR") -} - -# Determine amplifier 2 over temperature status from the supply status bit -record(bi, "$(P)MAGNET:SUPPLY:STATUS:OTAMP2") { - field(DESC, "Over temp amp 2") - field(DTYP, "Soft Channel") - field(SCAN, "Passive") - field(INP, "$(P)GET:MAGNET:SUPPLY:STATUS.BE CP MS") - field(ZNAM, "No") - field(ONAM, "Yes") - field(ZSV, "NO_ALARM") - field(OSV, "MAJOR") -} - -# Determine PWM Cutoff status from the supply status bit -record(bi, "$(P)MAGNET:SUPPLY:STATUS:PWMCUTOFF") { - field(DESC, "PWM Cutoff status") - field(DTYP, "Soft Channel") - field(SCAN, "Passive") - field(INP, "$(P)GET:MAGNET:SUPPLY:STATUS.BF CP MS") - field(ZNAM, "No") - field(ONAM, "Yes") - field(ZSV, "NO_ALARM") - field(OSV, "MAJOR") -} - -# Determine Voltage ADC error status from the supply status bit -record(bi, "$(P)MAGNET:SUPPLY:STATUS:VADCERROR") { - field(DESC, "Voltage ADC error status") - field(DTYP, "Soft Channel") - field(SCAN, "Passive") - field(INP, "$(P)GET:MAGNET:SUPPLY:STATUS.B10 CP MS") - field(ZNAM, "No") - field(ONAM, "Yes") - field(ZSV, "NO_ALARM") - field(OSV, "MAJOR") -} - -# Determine Current ADC error status from the supply status bit -record(bi, "$(P)MAGNET:SUPPLY:STATUS:IADCERROR") { - field(DESC, "Current ADC error status") - field(DTYP, "Soft Channel") - field(SCAN, "Passive") - field(INP, "$(P)GET:MAGNET:SUPPLY:STATUS.B11 CP MS") - field(ZNAM, "No") - field(ONAM, "Yes") - field(ZSV, "NO_ALARM") - field(OSV, "MAJOR") -} - # The over temperature status should be an or'd output from the numerous temperature alarms record(calc, "$(P)MAGNET:SUPPLY:STATUS:OVERTEMP:CALC") { field(DESC, "Temperature status calc (combined)") @@ -777,82 +161,6 @@ record(mbbi, "$(P)HEATER:STATUS") { info(archive, "VAL") } -record(bo, "$(P)HEATER:STATUS:SP") { - field(DESC, "Set Remote/Local Control") - field(DTYP, "stream") - field(SCAN, "Passive") - field(OUT, "@OxInstIPS_SCPI.protocol setHeaterStatus $(PORT)") - field(ZNAM, "Off") - field(ONAM, "On") - - field(SIML, "$(P)SIM") - field(SIOL, "$(P)SIM:HEATER:STATUS:SP") - field(SDIS, "$(P)DISABLE") -} - -# Amount of time to wait for heater to warm up/cool down. **CAN CAUSE MAGNET TO QUENCH IF SET TOO LOW** -# Oxford Instruments labview driver uses 30s. ISIS cryogenics have asked us to increase this to 60s, -# which is more conservative. -# The HEATER_WAITTIME IOC macro, which is _not_ user-facing, has a default of 60s. -# Configurable to lower values to shorten time for IOC tests. - -record(ao, "$(P)HEATER:WAITTIME") { - field(DESC, "Time to wait for heater") - field(VAL, "$(HEATER_WAITTIME)") - field(PINI, "YES") - info(archive, "VAL") -} - -# CALC record to coerce heater status values. Heater can be off in states 0 or 2, and in error in states 5 or 8, -# and circular buffer (N to 1 Low Value) only looks for lowest (0). -# Output 1 only if heater is on, 0 if off and all other states, including errors. - -record(calc, "$(P)HEATER:_STATUS_CALC") { - field(DESC, "Binary Heater Status") - field(INPA, "$(P)HEATER:STATUS CP MS") - field(CALC, "(A=1)?1:0") # If heater is on, output 1, otherwise 0 - info(archive, "VAL") -} - -# COMPRESS Record with circular buffer to store $(HEATER_WAITTIME) worth of HEATER:STATUS values -# Used with second COMPRESS record below to check heater has been on for at least $(HEATER_WAITTIME) after starting IOC - -record(compress, "$(P)HEATER:_STATUS_BUFFER") { - field(DESC, "Buffer of heater status values") - field(INP, "$(P)HEATER:_STATUS_CALC.VAL") - field(ALG, "Circular Buffer") - field(NSAM, "$(HEATER_WAITTIME)") - field(SCAN, "1 second") - field(FLNK, "$(P)HEATER:_STATUS_BUFFER_LOWEST") -} - -# COMPRESS record to monitor above and output lowest value in buffer. -# If '1' then whole buffer contains '1' and therefore heater has been ON for at least $(HEATER_WAITTIME) -# If '0' then heater has been OFF at some point in $(HEATER_WAITTIME) - -record(compress, "$(P)HEATER:_STATUS_BUFFER_LOWEST") { - field(DESC, "Lowest value of heater status buffer") - field(INP, "$(P)HEATER:_STATUS_BUFFER") - field(ALG, "N to 1 Low Value") - field(NSAM, "1") - field(N, "$(HEATER_WAITTIME)") - field(FLNK, "$(P)HEATER:ONTIME_OK") - info(archive, "VAL") -} - -# BO record to indicate whether or not heater been on for at least $(HEATER_WAITTIME). -# Monitored by statemachine to determine whether or not OK to set field. - -record(bo, "$(P)HEATER:ONTIME_OK") { - field(DESC, "Heater on for at least $(HEATER_WAITTIME)s") - field(DTYP, "Soft Channel") - field(SCAN, "Passive") - field(OMSL, "closed_loop") - field(DOL, "$(P)HEATER:_STATUS_BUFFER_LOWEST.VAL") - field(ZNAM, "Heater OFF in last $(HEATER_WAITTIME)s") - field(ONAM, "Heater ON for > $(HEATER_WAITTIME)s") - info(archive, "VAL") -} # To capture bits of mismatching status protocol. # We do not do much with it at the moment. @@ -862,116 +170,28 @@ record(stringin, "$(P)DBG:STS:MISMATCH") { field(SCAN, "Passive") } -# PERSISTENT pv is the magnet persistent mode in the cryomagnet statemachine. -record(bo, "$(P)PERSISTENT") { - field(DESC, "Set magnet to persistent") - field(ZNAM, "NO") - field(ONAM, "YES") - field(PINI, "YES") - info(autosaveFields, "VAL") - info(INTEREST, "HIGH") - info(archive, "VAL") -} - -# Play nicely with blocks/genie_python -alias("$(P)PERSISTENT", "$(P)PERSISTENT:SP") - - -record(mbbo, "$(P)STATEMACHINE") { - field(DESC, "What the IOC is doing") - - field(ZRVL, "0") - field(ZRST, "Initial state") - - field(ONVL, "1") - field(ONST, "At field") - - field(TWVL, "2") - field(TWST, "Set PSU to match magnet") - - field(THVL, "3") - field(THST, "Wait for volts stable") - - field(FRVL, "4") - field(FRST, "Ensure heater on & warm") - - field(FVVL, "5") - field(FVST, "Set PSU to setpoint") - - field(SXVL, "6") - field(SXST, "Turn heater off & wait") - - field(SVVL, "7") - field(SVST, "Set PSU to zero") - - info(archive, "VAL") -} - - -### -### Records to be more "friendly" to the user. -### - -record(calc, "$(P)FIELD:USER") { - field(DESC, "Field readback") - field(INPA, "$(P)MAGNET:FIELD:PERSISTENT CP MS") - field(INPB, "$(P)FIELD CP MS") - field(INPC, "$(P)HEATER:STATUS CP MS") - field(CALC, "(C=0||C=2)?A:B") # If heater is present and switched off, display persistent field, else display PSU field - field(ASG, "READONLY") - field(EGU, "T") - field(PREC, "5") - info(interest, "HIGH") - info(archive, "VAL") -} - -alias("$(P)FIELD:SP", "$(P)FIELD:USER:SP") # "User" setpoint is same as "normal" setpoint - - -### Simulation record - Just to stop errors, doesn't do anything - -record(ao, "$(P)SIM:DONOTHING") {} - - -record(bo, "$(P)SIM:HEATER:STATUS") { - field(ZNAM, "Off") - field(ONAM, "On") -} - -alias("$(P)SIM:HEATER:STATUS", "$(P)SIM:HEATER:STATUS:SP") - -record(ao, "$(P)SIM:MAGNETINDUCTANCE"){} -record(ao, "$(P)SIM:LEADRESISTANCE"){} -record(ao, "$(P)SIM:POSCURRENTLIMIT"){} -record(ao, "$(P)SIM:NEGCURRENTLIMIT"){} -record(ao, "$(P)SIM:HEATERCURRENT"){} -record(ao, "$(P)SIM:TRIPFIELD"){} -record(ao, "$(P)SIM:TRIPCURRENT"){} -record(ao, "$(P)SIM:CURR:RATE"){} -record(ao, "$(P)SIM:SUPPLY:VOLT"){} -record(ao, "$(P)SIM:CURRENT"){} -record(ao, "$(P)SIM:SOFTWAREVOLTAGELIMIT"){} -record(ao, "$(P)SIM:FIELD:RATE"){} -record(ao, "$(P)SIM:FIELD"){} -alias("$(P)SIM:FIELD:RATE", "$(P)SIM:FIELD:RATE:SP") +# In the legacy version, this used to be the readback from n of Mmn part of Examine command return. +# 0 output constant, 1, 2, 3 output changing +# The SCPI protocol doesn't directly offer this, so it has to be derived via the ACTIVITY record (DEV:GRPZ:PSU:ACTN) +# Direction from Alex Jones: "A response of HOLD or CLMP would be equivalent to n=0 in the response of the X command +# in the old protocol. Responses of RTOS or RTOZ would be equivalent to n=1. +# There is no equivalent for the m=0,1 fast/slow ramps, but we do not use this feature anyway." -record(mbbo, "$(P)SIM:ACTIVITY") { - field(ZRST, "Hold") - field(ZRVL, "0") - field(ONST, "To Setpoint") - field(ONVL, "1") - field(TWST, "To Zero") - field(TWVL, "2") - field(FRST, "Clamp") - field(FRVL, "4") +record(calcout, "$(P)_SWEEPMODE:SWEEP:CALC") { + field(INPA, "$(P)ACTIVITY.RVAL CP") + # 0 = HOLD, 1 = RTOS, 2 = RTOZ, 4 = CLMP + field(CALC, "((A==0)||(A==4))?0:1") + field(OUT, "$(P)STS:SWEEPMODE:SWEEP PP") + field(OOPT, "Every Time") } -alias("$(P)SIM:ACTIVITY", "$(P)SIM:ACTIVITY:SP") - -# The Display is in Amps or Tesla. The Magnet Sweep is fast or slow. -record(mbbi, "$(P)SWEEPMODE:PARAMS") { - field(DESC, "Mode status") - field(DTYP, "Soft Channel") +# This record has been added to the SCPI implementation simply to satisfy the state machine logic +# in cryomagnet.st. The legacy record is mbbo, but this is mbbi as it does not actually set +# anything in the device. +# +record(mbbi, "$(P)SWEEPMODE:PARAMS:SP") { + field(DESC, "Set sweep and display mode.") + field(DTYP, "stream") field(SCAN, "Passive") field(ZRST, "Amps Fast") field(ZRVL, "0") @@ -998,45 +218,8 @@ record(mbbi, "$(P)SWEEPMODE:PARAMS") { field(PINI, "YES") field(SIML, "$(P)SIM") - field(SIOL, "$(P)SIM:SWEEPMODE:PARAMS") + field(SIOL, "$(P)SIM:SWEEPMODE:PARAMS:SP") field(SDIS, "$(P)DISABLE") - - info(archive, "VAL") -} - -# In the legacy version, this used to be the readback from n of Mmn part of Examine command return. -# 0 output constant, 1, 2, 3 output changing -# The SCPI protocol doesn't directly offer this, so it has to be derived via the ACTIVITY record (DEV:GRPZ:PSU:ACTN) -# Direction from Alex Jones: "A response of HOLD or CLMP would be equivalent to n=0 in the response of the X command -# in the old protocol. Responses of RTOS or RTOZ would be equivalent to n=1. -# There is no equivalent for the m=0,1 fast/slow ramps, but we do not use this feature anyway." - -record(calcout, "$(P)_SWEEPMODE:SWEEP:CALC") { - field(INPA, "$(P)ACTIVITY.RVAL CP") - # 0 = HOLD, 1 = RTOS, 2 = RTOZ, 4 = CLMP - field(CALC, "((A==0)||(A==4))?0:1") - field(OUT, "$(P)STS:SWEEPMODE:SWEEP PP") - field(OOPT, "Every Time") -} - -record(mbbi, "$(P)STS:SWEEPMODE:SWEEP") { - field(DESC, "Mode status") - field(DTYP, "Soft Channel") - field(SCAN, "Passive") - field(ZRST, "At rest") - field(ZRVL, "0") - field(ONST, "Sweeping") - field(ONVL, "1") - field(TWST, "Sweep Limiting") - field(TWVL, "2") - field(THST, "Swping & Lmting") - field(THVL, "3") - - field(SIML, "$(P)SIM") - field(SIOL, "$(P)SIM:STS:SWEEPMODE:SWEEP") - field(SDIS, "$(P)DISABLE") - - info(archive, "VAL") } # The temperature of the magnet MB1.T1 diff --git a/IPS/IPS-IOC-01App/Db/scpi_system_alarms_discrete.substitutions b/IPS/IPS-IOC-01App/Db/scpi_system_alarms_discrete.substitutions index e8ff54a3c..f09c07eb1 100644 --- a/IPS/IPS-IOC-01App/Db/scpi_system_alarms_discrete.substitutions +++ b/IPS/IPS-IOC-01App/Db/scpi_system_alarms_discrete.substitutions @@ -1,50 +1,68 @@ file scpi_system_alarms_discrete.template { pattern {P, ALARM_NAME, ALARM_DESC, ALARM_INP} -{"\$(P)", "TBOARD:OPENCIRCUIT", "Temperature board Open Circuit", "TBOARD.B0"} -{"\$(P)", "TBOARD:SHORTCIRCUIT", "Temperature board Short Circuit", "TBOARD.B1"} -{"\$(P)", "TBOARD:CALIBERR", "Temperature board Calibn error", "TBOARD.B2"} -{"\$(P)", "TBOARD:FWERR", "Temperature board fw error", "TBOARD.B3"} -{"\$(P)", "TBOARD:NOTCONFIGD", "Temperature board not configd", "TBOARD.B4"} +{"\$(P)", "STS:SYSTEM:ALARM:TBOARD:OPENCIRCUIT", "Temperature board Open Circuit", "STS:SYSTEM:ALARM:TBOARD.B0"} +{"\$(P)", "STS:SYSTEM:ALARM:TBOARD:SHORTCIRCUIT", "Temperature board Short Circuit", "STS:SYSTEM:ALARM:TBOARD.B1"} +{"\$(P)", "STS:SYSTEM:ALARM:TBOARD:CALIBERR", "Temperature board Calibn error", "STS:SYSTEM:ALARM:TBOARD.B2"} +{"\$(P)", "STS:SYSTEM:ALARM:TBOARD:FWERR", "Temperature board fw error", "STS:SYSTEM:ALARM:TBOARD.B3"} +{"\$(P)", "STS:SYSTEM:ALARM:TBOARD:NOTCONFIGD", "Temperature board not configd", "STS:SYSTEM:ALARM:TBOARD.B4"} -{"\$(P)", "10TBOARD:OPENCIRCUIT", "Temperature board Open Circuit", "10TBOARD.B0"} -{"\$(P)", "10TBOARD:SHORTCIRCUIT", "Temperature board Short Circuit", "10TBOARD.B1"} -{"\$(P)", "10TBOARD:CALIBERR", "Temperature board Calibn error", "10TBOARD.B2"} -{"\$(P)", "10TBOARD:FWERR", "Temperature board fw error", "10TBOARD.B3"} -{"\$(P)", "10TBOARD:NOTCONFIGD", "Temperature board not configd", "10TBOARD.B4"} +{"\$(P)", "STS:SYSTEM:ALARM:10TBOARD:OPENCIRCUIT", "Temperature board Open Circuit", "STS:SYSTEM:ALARM:10TBOARD.B0"} +{"\$(P)", "STS:SYSTEM:ALARM:10TBOARD:SHORTCIRCUIT", "Temperature board Short Circuit", "STS:SYSTEM:ALARM:10TBOARD.B1"} +{"\$(P)", "STS:SYSTEM:ALARM:10TBOARD:CALIBERR", "Temperature board Calibn error", "STS:SYSTEM:ALARM:10TBOARD.B2"} +{"\$(P)", "STS:SYSTEM:ALARM:10TBOARD:FWERR", "Temperature board fw error", "STS:SYSTEM:ALARM:10TBOARD.B3"} +{"\$(P)", "STS:SYSTEM:ALARM:10TBOARD:NOTCONFIGD", "Temperature board not configd", "STS:SYSTEM:ALARM:10TBOARD.B4"} -{"\$(P)", "LBOARD:OPENCIRCUIT", "Levels board Open Circuit", "LBOARD.B0"} -{"\$(P)", "LBOARD:SHORTCIRCUIT", "Levels board Short Circuit", "LBOARD.B1"} -{"\$(P)", "LBOARD:ADCERR", "Levels board ADC error", "LBOARD.B2"} -{"\$(P)", "LBOARD:OVERDEMAND", "Levels board over demand", "LBOARD.B3"} -{"\$(P)", "LBOARD:OVERTEMP", "Levels board over temp", "LBOARD.B4"} -{"\$(P)", "LBOARD:FWERROR", "Levels board fw error", "LBOARD.B5"} -{"\$(P)", "LBOARD:NOTCONFIGD", "Levels board not confgd", "LBOARD.B6"} -{"\$(P)", "LBOARD:NORESERVE", "Levels board no reserve", "LBOARD.B7"} -{"\$(P)", "LBOARD:NORESERVE", "Levels board no reserve", "LBOARD.B7"} -{"\$(P)", "LBOARD:MAGNETSAFETY", "Levels board magnet safety", "LBOARD.B8"} +{"\$(P)", "STS:SYSTEM:ALARM:LBOARD:OPENCIRCUIT", "Levels board Open Circuit", "STS:SYSTEM:ALARM:LBOARD.B0"} +{"\$(P)", "STS:SYSTEM:ALARM:LBOARD:SHORTCIRCUIT", "Levels board Short Circuit", "STS:SYSTEM:ALARM:LBOARD.B1"} +{"\$(P)", "STS:SYSTEM:ALARM:LBOARD:ADCERR", "Levels board ADC error", "STS:SYSTEM:ALARM:LBOARD.B2"} +{"\$(P)", "STS:SYSTEM:ALARM:LBOARD:OVERDEMAND", "Levels board over demand", "STS:SYSTEM:ALARM:LBOARD.B3"} +{"\$(P)", "STS:SYSTEM:ALARM:LBOARD:OVERTEMP", "Levels board over temp", "STS:SYSTEM:ALARM:LBOARD.B4"} +{"\$(P)", "STS:SYSTEM:ALARM:LBOARD:FWERROR", "Levels board fw error", "STS:SYSTEM:ALARM:LBOARD.B5"} +{"\$(P)", "STS:SYSTEM:ALARM:LBOARD:NOTCONFIGD", "Levels board not confgd", "STS:SYSTEM:ALARM:LBOARD.B6"} +{"\$(P)", "STS:SYSTEM:ALARM:LBOARD:NORESERVE", "Levels board no reserve", "STS:SYSTEM:ALARM:LBOARD.B7"} +{"\$(P)", "STS:SYSTEM:ALARM:LBOARD:NORESERVE", "Levels board no reserve", "STS:SYSTEM:ALARM:LBOARD.B7"} +{"\$(P)", "STS:SYSTEM:ALARM:LBOARD:MAGNETSAFETY", "Levels board magnet safety", "STS:SYSTEM:ALARM:LBOARD.B8"} -{"\$(P)", "PBOARD:OPENCIRCUIT", "Pressure board Open Circuit", "PBOARD.B0"} -{"\$(P)", "PBOARD:SHORTCIRCUIT", "Pressure board Short Circuit", "PBOARD.B1"} -{"\$(P)", "PBOARD:CALIBERR", "Pressure board calib error", "PBOARD.B2"} -{"\$(P)", "PBOARD:FWERR", "Pressure board fw error", "PBOARD.B3"} -{"\$(P)", "PBOARD:NOTCONFIGD", "Pressure board not confgd", "PBOARD.B4"} -{"\$(P)", "PBOARD:OVERCURRENT", "Pressure board over current", "PBOARD.B5"} -{"\$(P)", "PBOARD:CURRENTLEAK", "Pressure board current leak", "PBOARD.B6"} -{"\$(P)", "PBOARD:PWONFAIL", "Pressure board power on fail", "PBOARD.B7"} -{"\$(P)", "PBOARD:CHKSUMERR", "Pressure board chksum error", "PBOARD.B8"} -{"\$(P)", "PBOARD:CLKFAIL", "Pressure board clk fail", "PBOARD.B9"} -{"\$(P)", "PBOARD:ADCFAIL", "Pressure board ADC fail", "PBOARD.BA"} -{"\$(P)", "PBOARD:MAINSFAIL", "Pressure board mains fail", "PBOARD.BB"} -{"\$(P)", "PBOARD:REFSFAIL", "Pressure board ref fail", "PBOARD.BC"} -{"\$(P)", "PBOARD:PLUS12VFAIL", "Pressure board +12V fail", "PBOARD.BD"} -{"\$(P)", "PBOARD:MINUS12VFAIL", "Pressure board -12V fail", "PBOARD.BE"} -{"\$(P)", "PBOARD:PLUS8VFAIL", "Pressure board +8V fail", "PBOARD.BF"} -{"\$(P)", "PBOARD:MINUS8VFAIL", "Pressure board -9V fail", "PBOARD.B10"} -{"\$(P)", "PBOARD:AMPGAINERR", "Pressure board amp gain err", "PBOARD.B11"} -{"\$(P)", "PBOARD:AMPOFFSETERR", "Pressure board amp offset err", "PBOARD.B12"} -{"\$(P)", "PBOARD:ADCPGAERR", "Pressure board ADC PGA offset err", "PBOARD.B14"} -{"\$(P)", "PBOARD:ADCXTALERR", "Pressure board ADC XTAL offset err", "PBOARD.B15"} -{"\$(P)", "PBOARD:PLUSEXCITEERR", "Pressure board excitation + error", "PBOARD.B16"} -{"\$(P)", "PBOARD:MINUSEXCITEERR", "Pressure board excitation - error", "PBOARD.B17"} +{"\$(P)", "STS:SYSTEM:ALARM:PBOARD:OPENCIRCUIT", "Pressure board Open Circuit", "STS:SYSTEM:ALARM:PBOARD.B0"} +{"\$(P)", "STS:SYSTEM:ALARM:PBOARD:SHORTCIRCUIT", "Pressure board Short Circuit", "STS:SYSTEM:ALARM:PBOARD.B1"} +{"\$(P)", "STS:SYSTEM:ALARM:PBOARD:CALIBERR", "Pressure board calib error", "STS:SYSTEM:ALARM:PBOARD.B2"} +{"\$(P)", "STS:SYSTEM:ALARM:PBOARD:FWERR", "Pressure board fw error", "STS:SYSTEM:ALARM:PBOARD.B3"} +{"\$(P)", "STS:SYSTEM:ALARM:PBOARD:NOTCONFIGD", "Pressure board not confgd", "STS:SYSTEM:ALARM:PBOARD.B4"} +{"\$(P)", "STS:SYSTEM:ALARM:PBOARD:OVERCURRENT", "Pressure board over current", "STS:SYSTEM:ALARM:PBOARD.B5"} +{"\$(P)", "STS:SYSTEM:ALARM:PBOARD:CURRENTLEAK", "Pressure board current leak", "STS:SYSTEM:ALARM:PBOARD.B6"} +{"\$(P)", "STS:SYSTEM:ALARM:PBOARD:PWONFAIL", "Pressure board power on fail", "STS:SYSTEM:ALARM:PBOARD.B7"} +{"\$(P)", "STS:SYSTEM:ALARM:PBOARD:CHKSUMERR", "Pressure board chksum error", "STS:SYSTEM:ALARM:PBOARD.B8"} +{"\$(P)", "STS:SYSTEM:ALARM:PBOARD:CLKFAIL", "Pressure board clk fail", "STS:SYSTEM:ALARM:PBOARD.B9"} +{"\$(P)", "STS:SYSTEM:ALARM:PBOARD:ADCFAIL", "Pressure board ADC fail", "STS:SYSTEM:ALARM:PBOARD.BA"} +{"\$(P)", "STS:SYSTEM:ALARM:PBOARD:MAINSFAIL", "Pressure board mains fail", "STS:SYSTEM:ALARM:PBOARD.BB"} +{"\$(P)", "STS:SYSTEM:ALARM:PBOARD:REFSFAIL", "Pressure board ref fail", "STS:SYSTEM:ALARM:PBOARD.BC"} +{"\$(P)", "STS:SYSTEM:ALARM:PBOARD:PLUS12VFAIL", "Pressure board +12V fail", "STS:SYSTEM:ALARM:PBOARD.BD"} +{"\$(P)", "STS:SYSTEM:ALARM:PBOARD:MINUS12VFAIL", "Pressure board -12V fail", "STS:SYSTEM:ALARM:PBOARD.BE"} +{"\$(P)", "STS:SYSTEM:ALARM:PBOARD:PLUS8VFAIL", "Pressure board +8V fail", "STS:SYSTEM:ALARM:PBOARD.BF"} +{"\$(P)", "STS:SYSTEM:ALARM:PBOARD:MINUS8VFAIL", "Pressure board -9V fail", "STS:SYSTEM:ALARM:PBOARD.B10"} +{"\$(P)", "STS:SYSTEM:ALARM:PBOARD:AMPGAINERR", "Pressure board amp gain err", "STS:SYSTEM:ALARM:PBOARD.B11"} +{"\$(P)", "STS:SYSTEM:ALARM:PBOARD:AMPOFFSETERR", "Pressure board amp offset err", "STS:SYSTEM:ALARM:PBOARD.B12"} +{"\$(P)", "STS:SYSTEM:ALARM:PBOARD:ADCPGAERR", "Pressure board ADC PGA offset err", "STS:SYSTEM:ALARM:PBOARD.B14"} +{"\$(P)", "STS:SYSTEM:ALARM:PBOARD:ADCXTALERR", "Pressure board ADC XTAL offset err", "STS:SYSTEM:ALARM:PBOARD.B15"} +{"\$(P)", "STS:SYSTEM:ALARM:PBOARD:PLUSEXCITEERR", "Pressure board excitation + error", "STS:SYSTEM:ALARM:PBOARD.B16"} +{"\$(P)", "STS:SYSTEM:ALARM:PBOARD:MINUSEXCITEERR", "Pressure board excitation - error", "STS:SYSTEM:ALARM:PBOARD.B17"} + +{"\$(P)", "MAGNET:SUPPLY:STATUS:SWHTRMISMATCH", "Switch heater mismatch status", "GET:MAGNET:SUPPLY:STATUS.B0"} +{"\$(P)", "MAGNET:SUPPLY:STATUS:OTRUNDOWNRES", "Over temp rundown resistors status", "GET:MAGNET:SUPPLY:STATUS.B1"} +{"\$(P)", "MAGNET:SUPPLY:STATUS:OTSENSERES", "Over temp sense resistor status", "GET:MAGNET:SUPPLY:STATUS.B2"} +{"\$(P)", "MAGNET:SUPPLY:STATUS:OTPCB", "Over temp PCB status", "GET:MAGNET:SUPPLY:STATUS.B3"} +{"\$(P)", "MAGNET:SUPPLY:STATUS:CALIBFAIL", "Calibration failure status", "GET:MAGNET:SUPPLY:STATUS.B4"} +{"\$(P)", "MAGNET:SUPPLY:STATUS:FWFAIL", "Firmware failure status", "GET:MAGNET:SUPPLY:STATUS.B5"} +{"\$(P)", "MAGNET:SUPPLY:STATUS:RRFAIL", "Rundown resistors failure status", "GET:MAGNET:SUPPLY:STATUS.B6"} +{"\$(P)", "MAGNET:SUPPLY:STATUS:RS485FAIL", "MSP430 RS485 failure status", "GET:MAGNET:SUPPLY:STATUS.B7"} +{"\$(P)", "MAGNET:SUPPLY:STATUS:QUENCHED", "Quench status", "GET:MAGNET:SUPPLY:STATUS.B8"} +{"\$(P)", "MAGNET:SUPPLY:STATUS:CATCH", "PSU Catch status", "GET:MAGNET:SUPPLY:STATUS.B9"} +# Intentional gap in bits BA and BB in accordance with OI information +{"\$(P)", "MAGNET:SUPPLY:STATUS:OTSENSEAMP", "Over temp sense amp", "GET:MAGNET:SUPPLY:STATUS.BC"} +{"\$(P)", "MAGNET:SUPPLY:STATUS:OTAMP1", "Over temp amp 1", "GET:MAGNET:SUPPLY:STATUS.BD"} +{"\$(P)", "MAGNET:SUPPLY:STATUS:OTAMP2", "Over temp amp 2", "GET:MAGNET:SUPPLY:STATUS.BE"} +{"\$(P)", "MAGNET:SUPPLY:STATUS:PWMCUTOFF", "PWM Cutoff status", "GET:MAGNET:SUPPLY:STATUS.BF"} +{"\$(P)", "MAGNET:SUPPLY:STATUS:VADCERROR", "Voltage ADC error status", "GET:MAGNET:SUPPLY:STATUS.B10"} +{"\$(P)", "MAGNET:SUPPLY:STATUS:IADCERROR", "Current ADC error status", "GET:MAGNET:SUPPLY:STATUS.B11"} } diff --git a/IPS/IPS-IOC-01App/Db/scpi_system_alarms_discrete.template b/IPS/IPS-IOC-01App/Db/scpi_system_alarms_discrete.template index d5abe13bf..c14267394 100644 --- a/IPS/IPS-IOC-01App/Db/scpi_system_alarms_discrete.template +++ b/IPS/IPS-IOC-01App/Db/scpi_system_alarms_discrete.template @@ -2,18 +2,18 @@ # This file defines the discrete alarms for the SCPI system, which are derived from the # relevant mbbidirect records # -record(bi, "$(P)STS:SYSTEM:ALARM:$(ALARM_NAME)") { +record(bi, "$(P)$(ALARM_NAME)") { field(DESC, "$(ALARM_DESC)") field(DTYP, "Soft Channel") field(SCAN, "Passive") - field(INP, "$(P)STS:SYSTEM:ALARM:$(ALARM_INP) CP MS") + field(INP, "$(P)$(ALARM_INP) CP MS") field(ZNAM, "No") field(ONAM, "Yes") field(ZSV, "NO_ALARM") field(OSV, "MAJOR") field(SIML, "$(P)SIM") - field(SIOL, "$(P)SIM:STS:SYSTEM:ALARM:$(ALARM_NAME)") + field(SIOL, "$(P)SIM:$(ALARM_NAME)") field(SDIS, "$(P)DISABLE") info(archive, "VAL") } diff --git a/IPS/IPS-IOC-01App/src/build.mak b/IPS/IPS-IOC-01App/src/build.mak index a35e5fd38..962a843ee 100644 --- a/IPS/IPS-IOC-01App/src/build.mak +++ b/IPS/IPS-IOC-01App/src/build.mak @@ -54,7 +54,6 @@ $(APPNAME)_LIBS += OxInstIPS # FERMCHOP-IOC-01_registerRecordDeviceDriver.cpp derives from IPS-IOC-01.dbd $(APPNAME)_SRCS += $(APPNAME)_registerRecordDeviceDriver.cpp $(APPNAME)_SRCS += cryomagnet.st -$(APPNAME)_SRCS += cryomagnet_SCPI.st # Build the main IOC entry point on workstation OSs. $(APPNAME)_SRCS_DEFAULT += $(APPNAME)Main.cpp diff --git a/IPS/IPS-IOC-01App/src/cryomagnet.dbd b/IPS/IPS-IOC-01App/src/cryomagnet.dbd index c45e15b16..9d633eec7 100644 --- a/IPS/IPS-IOC-01App/src/cryomagnet.dbd +++ b/IPS/IPS-IOC-01App/src/cryomagnet.dbd @@ -1,2 +1 @@ registrar(cryomagnetRegistrar) -registrar(cryomagnet_SCPIRegistrar) diff --git a/IPS/iocBoot/iocIPS-IOC-01/st.cmd b/IPS/iocBoot/iocIPS-IOC-01/st.cmd index 75b80153e..fa4f7b8cf 100644 --- a/IPS/iocBoot/iocIPS-IOC-01/st.cmd +++ b/IPS/iocBoot/iocIPS-IOC-01/st.cmd @@ -59,7 +59,7 @@ epicsEnvSet("P", "$(MYPVPREFIX)$(IOCNAME):") # The STREAMPROTOCOL env var should be set to either "LEGACY" (default) or "SCPI" # Set the database and protocol file names accordingly stringiftest("STREAMPROTOCOL_SCPI", "$(STREAMPROTOCOL=)", 4, "SCPI") -$(IFNOTSTREAMPROTOCOL_SCPI) epicsEnvSet "DBFILE" "ips.db" +$(IFNOTSTREAMPROTOCOL_SCPI) epicsEnvSet "DBFILE" "ips_legacy.db" $(IFSTREAMPROTOCOL_SCPI) epicsEnvSet "DBFILE" "ips_scpi.db" $(IFNOTSTREAMPROTOCOL_SCPI) epicsEnvSet "PROTOCOLFILE" "OxInstIPS.protocol" $(IFSTREAMPROTOCOL_SCPI) epicsEnvSet "PROTOCOLFILE" "OxInstIPS_SCPI.protocol" @@ -74,6 +74,7 @@ $(IFSTREAMPROTOCOL_SCPI) epicsEnvSet "PROTOCOLFILE" "OxInstIPS_SCPI.protocol" ################## ## Load our record instances +dbLoadRecords("db/ips_common.db","PVPREFIX=$(MYPVPREFIX),P=$(P),PROTO=$(PROTOCOLFILE),RECSIM=$(RECSIM=0),DISABLE=$(DISABLE=0),PORT=$(DEVICE),MAX_FIELD=$(MAX_FIELD=7.0),MAX_SWEEP_RATE=$(MAX_SWEEP_RATE=1.0),STABILITY_VOLTAGE=$(STABILITY_VOLTAGE=0.1),HEATER_WAITTIME=$(HEATER_WAITTIME=60),MANAGER_ASG=$(MANAGER_ASG=MANAGER)") dbLoadRecords("db/$(DBFILE)","PVPREFIX=$(MYPVPREFIX),P=$(P),RECSIM=$(RECSIM=0),DISABLE=$(DISABLE=0),PORT=$(DEVICE),MAX_FIELD=$(MAX_FIELD=7.0),MAX_SWEEP_RATE=$(MAX_SWEEP_RATE=1.0),STABILITY_VOLTAGE=$(STABILITY_VOLTAGE=0.1),HEATER_WAITTIME=$(HEATER_WAITTIME=60),MANAGER_ASG=$(MANAGER_ASG=MANAGER)") $(IFSTREAMPROTOCOL_SCPI) dbLoadRecords("db/ips_scpi_levels.db","PVPREFIX=$(MYPVPREFIX),P=$(P),RECSIM=$(RECSIM=0),DISABLE=$(DISABLE=0),PORT=$(DEVICE),MIN_N2_FREQ=$(MIN_N2_FREQ=5000),MAX_N2_FREQ=$(MAX_N2_FREQ=65000),MANAGER_ASG=$(MANAGER_ASG=MANAGER)") $(IFSTREAMPROTOCOL_SCPI) dbLoadRecords("db/scpi_system_alarms.db","PVPREFIX=$(MYPVPREFIX),P=$(P),RECSIM=$(RECSIM=0),DISABLE=$(DISABLE=0),PORT=$(DEVICE),BOARDID_MAG=$(BOARDID_MAG=MB1.T1),BOARDID_10TMAG=$(BOARDID_10TMAG=DB8.T1),BOARDID_PRESS=$(BOARDID_PRESS=DB5.P1),BOARDID_LEVEL=$(BOARDID_LEVEL=DB1.L1),MANAGER_ASG=$(MANAGER_ASG=MANAGER)") @@ -86,8 +87,7 @@ cd "${TOP}/iocBoot/${IOC}" iocInit ## Start any sequence programs -$(IFNOTSTREAMPROTOCOL_SCPI) seq cryomagnet, "FIELD=$(P)FIELD,FIELD_SETPOINT=$(P)FIELD:SP,FIELD_SETPOINT_ALARM=$(P)FIELD:SP.SEVR,FIELD_SETPOINT_READBACK=$(P)FIELD:SP:RBV,FIELD_SETPOINT_RAW=$(P)FIELD:SP:_RAW,PERSISTENT=$(P)PERSISTENT,MAGNET_FIELD=$(P)MAGNET:FIELD:PERSISTENT,HEATER_STATUS=$(P)HEATER:STATUS,HEATER_STATUS_SP=$(P)HEATER:STATUS:SP,HEATER_WAIT_TIME=$(P)HEATER:WAITTIME,ACTIVITY=$(P)ACTIVITY,ACTIVITY_SP=$(P)ACTIVITY:SP,SWEEPMODE=$(P)SWEEPMODE:PARAMS,SWEEPMODE_SP=$(P)SWEEPMODE:PARAMS:SP,SUPPLYVOLTAGE_STABLE=$(P)SUPPLY:VOLT:STABLE,SWEEP_ACTIVE=$(P)STS:SWEEPMODE:SWEEP,STATEMACHINE=$(P)STATEMACHINE,HEATER_ONTIME_OK=$(P)HEATER:ONTIME_OK") -$(IFSTREAMPROTOCOL_SCPI) seq cryomagnet_SCPI, "FIELD=$(P)FIELD,FIELD_SETPOINT=$(P)FIELD:SP,FIELD_SETPOINT_ALARM=$(P)FIELD:SP.SEVR,FIELD_SETPOINT_READBACK=$(P)FIELD:SP:RBV,FIELD_SETPOINT_RAW=$(P)FIELD:SP:_RAW,PERSISTENT=$(P)PERSISTENT,MAGNET_FIELD=$(P)MAGNET:FIELD:PERSISTENT,HEATER_STATUS=$(P)HEATER:STATUS,HEATER_STATUS_SP=$(P)HEATER:STATUS:SP,HEATER_WAIT_TIME=$(P)HEATER:WAITTIME,ACTIVITY=$(P)ACTIVITY,ACTIVITY_SP=$(P)ACTIVITY:SP,SWEEPMODE=$(P)SWEEPMODE:PARAMS,SUPPLYVOLTAGE_STABLE=$(P)SUPPLY:VOLT:STABLE,SWEEP_ACTIVE=$(P)STS:SWEEPMODE:SWEEP,STATEMACHINE=$(P)STATEMACHINE,HEATER_ONTIME_OK=$(P)HEATER:ONTIME_OK") +seq cryomagnet, "FIELD=$(P)FIELD,FIELD_SETPOINT=$(P)FIELD:SP,FIELD_SETPOINT_ALARM=$(P)FIELD:SP.SEVR,FIELD_SETPOINT_READBACK=$(P)FIELD:SP:RBV,FIELD_SETPOINT_RAW=$(P)FIELD:SP:_RAW,PERSISTENT=$(P)PERSISTENT,MAGNET_FIELD=$(P)MAGNET:FIELD:PERSISTENT,HEATER_STATUS=$(P)HEATER:STATUS,HEATER_STATUS_SP=$(P)HEATER:STATUS:SP,HEATER_WAIT_TIME=$(P)HEATER:WAITTIME,ACTIVITY=$(P)ACTIVITY,ACTIVITY_SP=$(P)ACTIVITY:SP,SWEEPMODE=$(P)SWEEPMODE:PARAMS,SWEEPMODE_SP=$(P)SWEEPMODE:PARAMS:SP,SUPPLYVOLTAGE_STABLE=$(P)SUPPLY:VOLT:STABLE,SWEEP_ACTIVE=$(P)STS:SWEEPMODE:SWEEP,STATEMACHINE=$(P)STATEMACHINE,HEATER_ONTIME_OK=$(P)HEATER:ONTIME_OK") ##ISIS## Stuff that needs to be done after iocInit is called e.g. sequence programs < $(IOCSTARTUP)/postiocinit.cmd